#include <net/irda/irlmp.h>
#include <net/irda/irlmp_frame.h>
+static __u8 irlmp_find_free_slsap(void);
+static int irlmp_slsap_inuse(__u8 slsap_sel);
+
/* Master structure */
struct irlmp_cb *irlmp = NULL;
/* These can be altered by the sysctl interface */
int sysctl_discovery = 0;
int sysctl_discovery_timeout = 3; /* 3 seconds by default */
-EXPORT_SYMBOL(sysctl_discovery_timeout);
int sysctl_discovery_slots = 6; /* 6 slots by default */
int sysctl_lap_keepalive_time = LM_IDLE_TIMEOUT * 1000 / HZ;
char sysctl_devname[65];
"LM_INIT_DISCONNECT",
"ERROR, NOT USED",
};
-EXPORT_SYMBOL(irlmp_reasons);
/*
* Function irlmp_init (void)
spin_lock_init(&irlmp->cachelog->hb_spinlock);
- irlmp->free_lsap_sel = 0x10; /* Reserved 0x00-0x0f */
+ irlmp->last_lsap_sel = 0x0f; /* Reserved 0x00-0x0f */
strcpy(sysctl_devname, "Linux");
/* Do discovery every 3 seconds */
void __exit irlmp_cleanup(void)
{
/* Check for main structure */
- ASSERT(irlmp != NULL, return;);
- ASSERT(irlmp->magic == LMP_MAGIC, return;);
+ IRDA_ASSERT(irlmp != NULL, return;);
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return;);
del_timer(&irlmp->discovery_timer);
{
struct lsap_cb *self;
- ASSERT(notify != NULL, return NULL;);
- ASSERT(irlmp != NULL, return NULL;);
- ASSERT(irlmp->magic == LMP_MAGIC, return NULL;);
- ASSERT(notify->instance != NULL, return NULL;);
+ IRDA_ASSERT(notify != NULL, return NULL;);
+ IRDA_ASSERT(irlmp != NULL, return NULL;);
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return NULL;);
+ IRDA_ASSERT(notify->instance != NULL, return NULL;);
/* Does the client care which Source LSAP selector it gets? */
if (slsap_sel == LSAP_ANY) {
/* Allocate new instance of a LSAP connection */
self = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
if (self == NULL) {
- ERROR("%s: can't allocate memory", __FUNCTION__);
+ IRDA_ERROR("%s: can't allocate memory\n", __FUNCTION__);
return NULL;
}
memset(self, 0, sizeof(struct lsap_cb));
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
/*
* Set some of the variables to preset values
struct lap_cb *lap;
struct lsap_cb *lsap = NULL;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
/*
* Find out if we should remove this LSAP from a link or from the
*/
lap = self->lap;
if (lap) {
- ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
/* We might close a LSAP before it has completed the
* connection setup. In those case, higher layers won't
* send a proper disconnect request. Harmless, except
{
struct lap_cb *lap;
- ASSERT(irlmp != NULL, return;);
- ASSERT(irlmp->magic == LMP_MAGIC, return;);
- ASSERT(notify != NULL, return;);
+ IRDA_ASSERT(irlmp != NULL, return;);
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return;);
+ IRDA_ASSERT(notify != NULL, return;);
/*
* Allocate new instance of a LSAP connection
*/
lap = kmalloc(sizeof(struct lap_cb), GFP_KERNEL);
if (lap == NULL) {
- ERROR("%s: unable to kmalloc\n", __FUNCTION__);
+ IRDA_ERROR("%s: unable to kmalloc\n", __FUNCTION__);
return;
}
memset(lap, 0, sizeof(struct lap_cb));
#endif
lap->lsaps = hashbin_new(HB_LOCK);
if (lap->lsaps == NULL) {
- WARNING("%s(), unable to kmalloc lsaps\n", __FUNCTION__);
+ IRDA_WARNING("%s(), unable to kmalloc lsaps\n", __FUNCTION__);
kfree(lap);
return;
}
* will be triggered anymore. Jean II */
link = hashbin_remove(irlmp->links, saddr, NULL);
if (link) {
- ASSERT(link->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(link->magic == LMP_LAP_MAGIC, return;);
/* Kill all the LSAPs on this link. Jean II */
link->reason = LAP_DISC_INDICATION;
struct lsap_cb *lsap;
int ret;
- ASSERT(self != NULL, return -EBADR;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;);
+ IRDA_ASSERT(self != NULL, return -EBADR;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;);
IRDA_DEBUG(2,
"%s(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n",
}
/* Make room for MUX control header (3 bytes) */
- ASSERT(skb_headroom(tx_skb) >= LMP_CONTROL_HEADER, return -1;);
+ IRDA_ASSERT(skb_headroom(tx_skb) >= LMP_CONTROL_HEADER, return -1;);
skb_push(tx_skb, LMP_CONTROL_HEADER);
self->dlsap_sel = dlsap_sel;
*/
lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self, NULL);
- ASSERT(lsap != NULL, return -1;);
- ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
- ASSERT(lsap->lap != NULL, return -1;);
- ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
+ IRDA_ASSERT(lsap != NULL, return -1;);
+ IRDA_ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(lsap->lap != NULL, return -1;);
+ IRDA_ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (long) self,
NULL);
int lap_header_size;
int max_header_size;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
- ASSERT(self->lap != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self->lap != NULL, return;);
IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
__FUNCTION__, self->slsap_sel, self->dlsap_sel);
*/
int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata)
{
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
- ASSERT(userdata != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(userdata != NULL, return -1;);
/* We set the connected bit and move the lsap to the connected list
* in the state machine itself. Jean II */
__FUNCTION__, self->slsap_sel, self->dlsap_sel);
/* Make room for MUX control header (3 bytes) */
- ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return -1;);
+ IRDA_ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return -1;);
skb_push(userdata, LMP_CONTROL_HEADER);
irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, userdata);
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(skb != NULL, return;);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
- ASSERT(self->lap != NULL, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(self->lap != NULL, return;);
self->qos = *self->lap->qos;
return new;
}
-EXPORT_SYMBOL(irlmp_dup);
/*
* Function irlmp_disconnect_request (handle, userdata)
{
struct lsap_cb *lsap;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
- ASSERT(userdata != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(userdata != NULL, return -1;);
/* Already disconnected ?
* There is a race condition between irlmp_disconnect_indication()
* Remove LSAP from list of connected LSAPs for the particular link
* and insert it into the list of unconnected LSAPs
*/
- ASSERT(self->lap != NULL, return -1;);
- ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
- ASSERT(self->lap->lsaps != NULL, return -1;);
+ IRDA_ASSERT(self->lap != NULL, return -1;);
+ IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self->lap->lsaps != NULL, return -1;);
lsap = hashbin_remove(self->lap->lsaps, (long) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
self->lap->cache.valid = FALSE;
#endif
- ASSERT(lsap != NULL, return -1;);
- ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
- ASSERT(lsap == self, return -1;);
+ IRDA_ASSERT(lsap != NULL, return -1;);
+ IRDA_ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(lsap == self, return -1;);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self,
(long) self, NULL);
struct lsap_cb *lsap;
IRDA_DEBUG(1, "%s(), reason=%s\n", __FUNCTION__, irlmp_reasons[reason]);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
IRDA_DEBUG(3, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
__FUNCTION__, self->slsap_sel, self->dlsap_sel);
/*
* Remove association between this LSAP and the link it used
*/
- ASSERT(self->lap != NULL, return;);
- ASSERT(self->lap->lsaps != NULL, return;);
+ IRDA_ASSERT(self->lap != NULL, return;);
+ IRDA_ASSERT(self->lap->lsaps != NULL, return;);
lsap = hashbin_remove(self->lap->lsaps, (long) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
self->lap->cache.valid = FALSE;
#endif
- ASSERT(lsap != NULL, return;);
- ASSERT(lsap == self, return;);
+ IRDA_ASSERT(lsap != NULL, return;);
+ IRDA_ASSERT(lsap == self, return;);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap,
(long) lsap, NULL);
* Note : separate from irlmp_do_discovery() so that we can handle
* passive discovery properly.
*/
-void irlmp_do_expiry()
+void irlmp_do_expiry(void)
{
struct lap_cb *lap;
*/
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
- ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
if (lap->lap_state == LAP_STANDBY) {
/* Expire discoveries discovered on this link */
/* Make sure the value is sane */
if ((nslots != 1) && (nslots != 6) && (nslots != 8) && (nslots != 16)){
- WARNING("%s: invalid value for number of slots!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: invalid value for number of slots!\n",
+ __FUNCTION__);
nslots = sysctl_discovery_slots = 8;
}
*/
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
- ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
if (lap->lap_state == LAP_STANDBY) {
/* Try to discover */
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(log != NULL, return;);
+ IRDA_ASSERT(log != NULL, return;);
if (!(HASHBIN_GET_SIZE(log)))
return;
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(expiries != NULL, return;);
+ IRDA_ASSERT(expiries != NULL, return;);
/* For each client - notify callback may touch client list */
client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);
* Used by IrLAP to get the discovery info it needs when answering
* discovery requests by other devices.
*/
-discovery_t *irlmp_get_discovery_response()
+discovery_t *irlmp_get_discovery_response(void)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(irlmp != NULL, return NULL;);
+ IRDA_ASSERT(irlmp != NULL, return NULL;);
u16ho(irlmp->discovery_rsp.data.hints) = irlmp->hints.word;
{
int ret;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
/* Make room for MUX header */
- ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);
+ IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);
skb_push(userdata, LMP_HEADER);
ret = irlmp_do_lsap_event(self, LM_DATA_REQUEST, userdata);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(userdata != NULL, return -1;);
+ IRDA_ASSERT(userdata != NULL, return -1;);
/* Make room for MUX header */
- ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);
+ IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);
skb_push(userdata, LMP_HEADER);
ret = irlmp_do_lsap_event(self, LM_UDATA_REQUEST, userdata);
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
/* Hide LMP header from layer above */
skb_pull(skb, LMP_HEADER);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(userdata != NULL, return -1;);
+ IRDA_ASSERT(userdata != NULL, return -1;);
/* Make room for MUX and PID header */
- ASSERT(skb_headroom(userdata) >= LMP_HEADER+LMP_PID_HEADER,
- return -1;);
+ IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER+LMP_PID_HEADER,
+ return -1;);
/* Insert protocol identifier */
skb_push(userdata, LMP_PID_HEADER);
/* Try to send Connectionless packets out on all links */
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
- ASSERT(lap->magic == LMP_LAP_MAGIC, return -1;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return -1;);
clone_skb = skb_clone(userdata, GFP_ATOMIC);
if (!clone_skb) {
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
/* Hide LMP and PID header from layer above */
skb_pull(skb, LMP_HEADER+LMP_PID_HEADER);
}
#endif /* CONFIG_IRDA_ULTRA */
-void irlmp_status_request(void)
-{
- IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
-}
-
/*
* Propagate status indication from LAP to LSAPs (via LMP)
* This don't trigger any change of state in lap_cb, lmp_cb or lsap_cb,
curr = (struct lsap_cb *) hashbin_get_first( self->lsaps);
while (NULL != hashbin_find_next(self->lsaps, (long) curr, NULL,
(void *) &next) ) {
- ASSERT(curr->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(curr->magic == LMP_LSAP_MAGIC, return;);
/*
* Inform service user if he has requested it
*/
struct lsap_cb *curr;
int lsap_todo;
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
- ASSERT(flow == FLOW_START, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(flow == FLOW_START, return;);
/* Get the number of lsap. That's the only safe way to know
* that we have looped around... - Jean II */
service = kmalloc(sizeof(irlmp_service_t), GFP_ATOMIC);
if (!service) {
IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __FUNCTION__);
- return 0;
+ return NULL;
}
service->hints.word = hints;
hashbin_insert(irlmp->services, (irda_queue_t *) service,
irlmp_client_t *client;
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- ASSERT(irlmp != NULL, return 0;);
+ IRDA_ASSERT(irlmp != NULL, return NULL;);
/* Make a new registration */
client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC);
if (!client) {
IRDA_DEBUG( 1, "%s(), Unable to kmalloc!\n", __FUNCTION__);
- return 0;
+ return NULL;
}
/* Register the details */
* Function irlmp_slsap_inuse (slsap)
*
* Check if the given source LSAP selector is in use
+ *
+ * This function is clearly not very efficient. On the mitigating side, the
+ * stack make sure that in 99% of the cases, we are called only once
+ * for each socket allocation. We could probably keep a bitmap
+ * of the allocated LSAP, but I'm not sure the complexity is worth it.
+ * Jean II
*/
-int irlmp_slsap_inuse(__u8 slsap_sel)
+static int irlmp_slsap_inuse(__u8 slsap_sel)
{
struct lsap_cb *self;
struct lap_cb *lap;
unsigned long flags;
- ASSERT(irlmp != NULL, return TRUE;);
- ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
- ASSERT(slsap_sel != LSAP_ANY, return TRUE;);
+ IRDA_ASSERT(irlmp != NULL, return TRUE;);
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
+ IRDA_ASSERT(slsap_sel != LSAP_ANY, return TRUE;);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
return FALSE;
#endif /* CONFIG_IRDA_ULTRA */
- /* Valid values are between 0 and 127 */
+ /* Valid values are between 0 and 127 (0x0-0x6F) */
if (slsap_sel > LSAP_MAX)
return TRUE;
spin_lock_irqsave(&irlmp->links->hb_spinlock, flags);
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
- ASSERT(lap->magic == LMP_LAP_MAGIC, return TRUE;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, goto errlap;);
/* Careful for priority inversions here !
- * All other uses of attrib spinlock are independent of
- * the object spinlock, so we are safe. Jean II */
+ * irlmp->links is never taken while another IrDA
+ * spinlock is held, so we are safe. Jean II */
spin_lock(&lap->lsaps->hb_spinlock);
+ /* For this IrLAP, check all the LSAPs */
self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
while (self != NULL) {
- ASSERT(self->magic == LMP_LSAP_MAGIC, return TRUE;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC,
+ goto errlsap;);
if ((self->slsap_sel == slsap_sel)) {
IRDA_DEBUG(4, "Source LSAP selector=%02x in use\n",
- self->slsap_sel);
- return TRUE;
+ self->slsap_sel);
+ goto errlsap;
}
self = (struct lsap_cb*) hashbin_get_next(lap->lsaps);
}
spin_unlock(&lap->lsaps->hb_spinlock);
+
/* Next LAP */
lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
}
spin_unlock_irqrestore(&irlmp->links->hb_spinlock, flags);
+
+ /*
+ * Server sockets are typically waiting for connections and
+ * therefore reside in the unconnected list. We don't want
+ * to give out their LSAPs for obvious reasons...
+ * Jean II
+ */
+ spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
+
+ self = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
+ while (self != NULL) {
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, goto erruncon;);
+ if ((self->slsap_sel == slsap_sel)) {
+ IRDA_DEBUG(4, "Source LSAP selector=%02x in use (unconnected)\n",
+ self->slsap_sel);
+ goto erruncon;
+ }
+ self = (struct lsap_cb*) hashbin_get_next(irlmp->unconnected_lsaps);
+ }
+ spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags);
+
return FALSE;
+
+ /* Error exit from within one of the two nested loops.
+ * Make sure we release the right spinlock in the righ order.
+ * Jean II */
+errlsap:
+ spin_unlock(&lap->lsaps->hb_spinlock);
+IRDA_ASSERT_LABEL(errlap:)
+ spin_unlock_irqrestore(&irlmp->links->hb_spinlock, flags);
+ return TRUE;
+
+ /* Error exit from within the unconnected loop.
+ * Just one spinlock to release... Jean II */
+erruncon:
+ spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags);
+ return TRUE;
}
/*
* Find a free source LSAP to use. This function is called if the service
* user has requested a source LSAP equal to LM_ANY
*/
-__u8 irlmp_find_free_slsap(void)
+static __u8 irlmp_find_free_slsap(void)
{
__u8 lsap_sel;
int wrapped = 0;
- ASSERT(irlmp != NULL, return -1;);
- ASSERT(irlmp->magic == LMP_MAGIC, return -1;);
-
- lsap_sel = irlmp->free_lsap_sel++;
-
- /* Check if the new free lsap is really free */
- while (irlmp_slsap_inuse(irlmp->free_lsap_sel)) {
- irlmp->free_lsap_sel++;
+ IRDA_ASSERT(irlmp != NULL, return -1;);
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return -1;);
+
+ /* Most users don't really care which LSAPs they are given,
+ * and therefore we automatically give them a free LSAP.
+ * This function try to find a suitable LSAP, i.e. which is
+ * not in use and is within the acceptable range. Jean II */
+
+ do {
+ /* Always increment to LSAP number before using it.
+ * In theory, we could reuse the last LSAP number, as long
+ * as it is no longer in use. Some IrDA stack do that.
+ * However, the previous socket may be half closed, i.e.
+ * we closed it, we think it's no longer in use, but the
+ * other side did not receive our close and think it's
+ * active and still send data on it.
+ * This is similar to what is done with PIDs and TCP ports.
+ * Also, this reduce the number of calls to irlmp_slsap_inuse()
+ * which is an expensive function to call.
+ * Jean II */
+ irlmp->last_lsap_sel++;
/* Check if we need to wraparound (0x70-0x7f are reserved) */
- if (irlmp->free_lsap_sel > LSAP_MAX) {
- irlmp->free_lsap_sel = 10;
+ if (irlmp->last_lsap_sel > LSAP_MAX) {
+ /* 0x00-0x10 are also reserved for well know ports */
+ irlmp->last_lsap_sel = 0x10;
/* Make sure we terminate the loop */
- if (wrapped++)
+ if (wrapped++) {
+ IRDA_ERROR("%s: no more free LSAPs !\n",
+ __FUNCTION__);
return 0;
+ }
}
- }
- IRDA_DEBUG(4, "%s(), next free lsap_sel=%02x\n",
+
+ /* If the LSAP is in use, try the next one.
+ * Despite the autoincrement, we need to check if the lsap
+ * is really in use or not, first because LSAP may be
+ * directly allocated in irlmp_open_lsap(), and also because
+ * we may wraparound on old sockets. Jean II */
+ } while (irlmp_slsap_inuse(irlmp->last_lsap_sel));
+
+ /* Got it ! */
+ lsap_sel = irlmp->last_lsap_sel;
+ IRDA_DEBUG(4, "%s(), found free lsap_sel=%02x\n",
__FUNCTION__, lsap_sel);
return lsap_sel;
seq_puts(seq, "\nRegistered Link Layers:\n");
else if (iter->hashbin == irlmp->unconnected_lsaps) {
self = v;
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -EINVAL; );
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -EINVAL; );
seq_printf(seq, "lsap state: %s, ",
irlsap_state[ self->lsap_state]);
seq_printf(seq,
for (self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
self != NULL;
self = (struct lsap_cb *)hashbin_get_next(lap->lsaps)) {
- ASSERT(self->magic == LMP_LSAP_MAGIC, break;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC,
+ goto outloop;);
seq_printf(seq, " lsap state: %s, ",
irlsap_state[ self->lsap_state]);
seq_printf(seq,
seq_putc(seq, '\n');
}
+ IRDA_ASSERT_LABEL(outloop:)
spin_unlock(&lap->lsaps->hb_spinlock);
seq_putc(seq, '\n');
} else
int rc = -ENOMEM;
struct irlmp_iter_state *s;
- ASSERT(irlmp != NULL, return -EINVAL;);
+ IRDA_ASSERT(irlmp != NULL, return -EINVAL;);
s = kmalloc(sizeof(*s), GFP_KERNEL);
if (!s)