patch-2.4.15 linux/net/irda/irlmp.c
Next file: linux/net/irda/irlmp_event.c
Previous file: linux/net/irda/irlap_frame.c
Back to the patch index
Back to the overall index
- Lines: 204
- Date:
Fri Nov 9 14:22:17 2001
- Orig file:
v2.4.14/linux/net/irda/irlmp.c
- Orig date:
Tue Oct 9 17:06:53 2001
diff -u --recursive --new-file v2.4.14/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
@@ -11,6 +11,7 @@
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
+ * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -75,7 +76,7 @@
*/
int __init irlmp_init(void)
{
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
/* Initialize the irlmp structure. */
irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
if (irlmp == NULL)
@@ -170,14 +171,14 @@
#endif /* CONFIG_IRDA_ULTRA */
} else
self->dlsap_sel = LSAP_ANY;
- self->connected = FALSE;
+ /* self->connected = FALSE; -> already NULL via memset() */
init_timer(&self->watchdog_timer);
ASSERT(notify->instance != NULL, return NULL;);
self->notify = *notify;
- irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
+ self->lsap_state = LSAP_DISCONNECTED;
/* Insert into queue of unconnected LSAPs */
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, (int) self,
@@ -237,6 +238,7 @@
ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
lsap = hashbin_remove(lap->lsaps, (int) self, NULL);
}
+ self->lap = NULL;
/* Check if we found the LSAP! If not then try the unconnected lsaps */
if (!lsap) {
lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self,
@@ -281,7 +283,7 @@
lap->daddr = DEV_ADDR_ANY;
lap->lsaps = hashbin_new(HB_GLOBAL);
- irlmp_next_lap_state(lap, LAP_STANDBY);
+ lap->lap_state = LAP_STANDBY;
init_timer(&lap->idle_timer);
@@ -346,7 +348,7 @@
"(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n",
self->slsap_sel, dlsap_sel, saddr, daddr);
- if (self->connected)
+ if (test_bit(0, &self->connected))
return -EISCONN;
/* Client must supply destination device address */
@@ -435,7 +437,7 @@
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self, NULL);
- self->connected = TRUE;
+ set_bit(0, &self->connected); /* TRUE */
/*
* User supplied qos specifications?
@@ -481,6 +483,8 @@
self->notify.connect_indication(self->notify.instance, self,
&self->qos, max_seg_size,
max_header_size, skb);
+ else
+ dev_kfree_skb(skb);
}
/*
@@ -495,7 +499,7 @@
ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
ASSERT(userdata != NULL, return -1;);
- self->connected = TRUE;
+ set_bit(0, &self->connected); /* TRUE */
IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
self->slsap_sel, self->dlsap_sel);
@@ -543,7 +547,8 @@
self->notify.connect_confirm(self->notify.instance, self,
&self->qos, max_seg_size,
max_header_size, skb);
- }
+ } else
+ dev_kfree_skb(skb);
}
/*
@@ -598,16 +603,18 @@
ASSERT(self != NULL, return -1;);
ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ ASSERT(userdata != NULL, return -1;);
- /* Already disconnected? */
- if (!self->connected) {
- WARNING(__FUNCTION__ "(), already disconnected!\n");
+ /* Already disconnected ?
+ * There is a race condition between irlmp_disconnect_indication()
+ * and us that might mess up the hashbins below. This fixes it.
+ * Jean II */
+ if (! test_and_clear_bit(0, &self->connected)) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), already disconnected!\n");
+ dev_kfree_skb(userdata);
return -1;
}
- ASSERT(userdata != NULL, return -1;);
- ASSERT(self->connected == TRUE, return -1;);
-
skb_push(userdata, LMP_CONTROL_HEADER);
/*
@@ -634,7 +641,6 @@
NULL);
/* Reset some values */
- self->connected = FALSE;
self->dlsap_sel = LSAP_ANY;
self->lap = NULL;
@@ -651,16 +657,23 @@
{
struct lsap_cb *lsap;
- IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
+ IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
ASSERT(self != NULL, return;);
ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
- ASSERT(self->connected == TRUE, return;);
IRDA_DEBUG(3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
self->slsap_sel, self->dlsap_sel);
- self->connected = FALSE;
- self->dlsap_sel = LSAP_ANY;
+ /* Already disconnected ?
+ * There is a race condition between irlmp_disconnect_request()
+ * and us that might mess up the hashbins below. This fixes it.
+ * Jean II */
+ if (! test_and_clear_bit(0, &self->connected)) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), already disconnected!\n");
+ if (userdata)
+ dev_kfree_skb(userdata);
+ return;
+ }
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp->cache.valid = FALSE;
@@ -679,6 +692,7 @@
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap, (int) lsap,
NULL);
+ self->dlsap_sel = LSAP_ANY;
self->lap = NULL;
/*
@@ -689,7 +703,8 @@
self, reason, userdata);
else {
IRDA_DEBUG(0, __FUNCTION__ "(), no handler\n");
- dev_kfree_skb(userdata);
+ if (userdata)
+ dev_kfree_skb(userdata);
}
}
@@ -1401,7 +1416,7 @@
irlmp_client_t *client;
__u32 handle;
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(1, __FUNCTION__ "()\n");
ASSERT(irlmp != NULL, return 0;);
/* Get a unique handle for this client */
@@ -1673,14 +1688,15 @@
len += sprintf(buf+len, "saddr: %#08x, daddr: %#08x, ",
lap->saddr, lap->daddr);
- len += sprintf(buf+len, "refcount: %d", lap->refcount);
+ len += sprintf(buf+len, "num lsaps: %d",
+ HASHBIN_GET_SIZE(lap->lsaps));
len += sprintf(buf+len, "\n");
- len += sprintf(buf+len, "\nConnected LSAPs:\n");
+ len += sprintf(buf+len, "\n Connected LSAPs:\n");
self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
while (self != NULL) {
ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
- len += sprintf(buf+len, "lsap state: %s, ",
+ len += sprintf(buf+len, " lsap state: %s, ",
irlsap_state[ self->lsap_state]);
len += sprintf(buf+len,
"slsap_sel: %#02x, dlsap_sel: %#02x, ",
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)