1 diff -u -p linux/include/net/irda/irlmp.d2.h linux/include/net/irda/irlmp.h
2 --- linux/include/net/irda/irlmp.d2.h Fri Nov 2 14:11:19 2001
3 +++ linux/include/net/irda/irlmp.h Mon Nov 5 18:46:49 2001
6 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
8 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 @@ -131,7 +132,6 @@ struct lap_cb {
14 struct irlap_cb *irlap; /* Instance of IrLAP layer */
15 hashbin_t *lsaps; /* LSAP associated with this link */
18 __u8 caddr; /* Connection address */
19 __u32 saddr; /* Source device address */
20 diff -u -p linux/include/net/irda/irlmp_event.d2.h linux/include/net/irda/irlmp_event.h
21 --- linux/include/net/irda/irlmp_event.d2.h Fri Nov 2 18:47:47 2001
22 +++ linux/include/net/irda/irlmp_event.h Mon Nov 5 18:47:05 2001
25 * Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
26 * All Rights Reserved.
27 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
29 * This program is free software; you can redistribute it and/or
30 * modify it under the terms of the GNU General Public License as
31 @@ -102,10 +103,6 @@ extern const char *irlsap_state[];
32 void irlmp_watchdog_timer_expired(void *data);
33 void irlmp_discovery_timer_expired(void *data);
34 void irlmp_idle_timer_expired(void *data);
36 -void irlmp_next_station_state(IRLMP_STATE state);
37 -void irlmp_next_lsap_state(struct lsap_cb *self, LSAP_STATE state);
38 -void irlmp_next_lap_state(struct lap_cb *self, IRLMP_STATE state);
40 void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
42 diff -u -p linux/include/net/irda/irlap_event.d2.h linux/include/net/irda/irlap_event.h
43 --- linux/include/net/irda/irlap_event.d2.h Fri Nov 2 18:47:12 2001
44 +++ linux/include/net/irda/irlap_event.h Mon Nov 5 18:46:30 2001
47 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
48 * All Rights Reserved.
49 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
51 * This program is free software; you can redistribute it and/or
52 * modify it under the terms of the GNU General Public License as
53 @@ -103,6 +104,7 @@ typedef enum {
54 DISCOVERY_TIMER_EXPIRED,
56 BACKOFF_TIMER_EXPIRED,
57 + MEDIA_BUSY_TIMER_EXPIRED,
61 diff -u -p linux/include/net/irda/timer.d2.h linux/include/net/irda/timer.h
62 --- linux/include/net/irda/timer.d2.h Mon Nov 5 14:12:40 2001
63 +++ linux/include/net/irda/timer.h Mon Nov 5 18:48:00 2001
66 * Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>,
67 * All Rights Reserved.
68 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
70 * This program is free software; you can redistribute it and/or
71 * modify it under the terms of the GNU General Public License as
73 * duration of the P-timer.
75 #define WD_TIMEOUT (POLL_TIMEOUT*2)
77 #define MEDIABUSY_TIMEOUT (500*HZ/1000) /* 500 msec */
78 +#define SMALLBUSY_TIMEOUT (100*HZ/1000) /* 100 msec - IrLAP 6.13.4 */
81 * Slot timer must never exceed 85 ms, and must always be at least 25 ms,
82 @@ -75,7 +78,7 @@ inline void irlap_start_final_timer(stru
83 inline void irlap_start_wd_timer(struct irlap_cb *self, int timeout);
84 inline void irlap_start_backoff_timer(struct irlap_cb *self, int timeout);
86 -void irlap_start_mbusy_timer(struct irlap_cb *);
87 +void irlap_start_mbusy_timer(struct irlap_cb *self, int timeout);
88 void irlap_stop_mbusy_timer(struct irlap_cb *);
91 diff -u -p linux/include/net/irda/irda.d2.h linux/include/net/irda/irda.h
92 --- linux/include/net/irda/irda.d2.h Mon Nov 5 14:07:34 2001
93 +++ linux/include/net/irda/irda.h Mon Nov 5 18:46:05 2001
95 * Modified by: Dag Brattli <dagb@cs.uit.no>
97 * Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
98 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
100 * This program is free software; you can redistribute it and/or
101 * modify it under the terms of the GNU General Public License as
102 @@ -42,6 +43,11 @@ typedef __u32 magic_t;
108 +/* Hack to do small backoff when setting media busy in IrLAP */
113 #ifndef IRDA_MIN /* Lets not mix this MIN with other header files */
114 diff -u -p linux/net/irda/irlmp.d2.c linux/net/irda/irlmp.c
115 --- linux/net/irda/irlmp.d2.c Wed Oct 31 15:44:59 2001
116 +++ linux/net/irda/irlmp.c Mon Nov 5 18:43:34 2001
119 * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
120 * All Rights Reserved.
121 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
123 * This program is free software; you can redistribute it and/or
124 * modify it under the terms of the GNU General Public License as
125 @@ -75,7 +76,7 @@ int irlmp_proc_read(char *buf, char **st
127 int __init irlmp_init(void)
129 - IRDA_DEBUG(0, __FUNCTION__ "()\n");
130 + IRDA_DEBUG(1, __FUNCTION__ "()\n");
131 /* Initialize the irlmp structure. */
132 irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
134 @@ -170,14 +171,14 @@ struct lsap_cb *irlmp_open_lsap(__u8 sls
135 #endif /* CONFIG_IRDA_ULTRA */
137 self->dlsap_sel = LSAP_ANY;
138 - self->connected = FALSE;
139 + /* self->connected = FALSE; -> already NULL via memset() */
141 init_timer(&self->watchdog_timer);
143 ASSERT(notify->instance != NULL, return NULL;);
144 self->notify = *notify;
146 - irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
147 + self->lsap_state = LSAP_DISCONNECTED;
149 /* Insert into queue of unconnected LSAPs */
150 hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, (int) self,
151 @@ -237,6 +238,7 @@ void irlmp_close_lsap(struct lsap_cb *se
152 ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
153 lsap = hashbin_remove(lap->lsaps, (int) self, NULL);
156 /* Check if we found the LSAP! If not then try the unconnected lsaps */
158 lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self,
159 @@ -281,7 +283,7 @@ void irlmp_register_link(struct irlap_cb
160 lap->daddr = DEV_ADDR_ANY;
161 lap->lsaps = hashbin_new(HB_GLOBAL);
163 - irlmp_next_lap_state(lap, LAP_STANDBY);
164 + lap->lap_state = LAP_STANDBY;
166 init_timer(&lap->idle_timer);
168 @@ -346,7 +348,7 @@ int irlmp_connect_request(struct lsap_cb
169 "(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n",
170 self->slsap_sel, dlsap_sel, saddr, daddr);
172 - if (self->connected)
173 + if (test_bit(0, &self->connected))
176 /* Client must supply destination device address */
177 @@ -435,7 +437,7 @@ int irlmp_connect_request(struct lsap_cb
179 hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self, NULL);
181 - self->connected = TRUE;
182 + set_bit(0, &self->connected); /* TRUE */
185 * User supplied qos specifications?
186 @@ -481,6 +483,8 @@ void irlmp_connect_indication(struct lsa
187 self->notify.connect_indication(self->notify.instance, self,
188 &self->qos, max_seg_size,
189 max_header_size, skb);
191 + dev_kfree_skb(skb);
195 @@ -495,7 +499,7 @@ int irlmp_connect_response(struct lsap_c
196 ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
197 ASSERT(userdata != NULL, return -1;);
199 - self->connected = TRUE;
200 + set_bit(0, &self->connected); /* TRUE */
202 IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
203 self->slsap_sel, self->dlsap_sel);
204 @@ -543,7 +547,8 @@ void irlmp_connect_confirm(struct lsap_c
205 self->notify.connect_confirm(self->notify.instance, self,
206 &self->qos, max_seg_size,
207 max_header_size, skb);
210 + dev_kfree_skb(skb);
214 @@ -598,16 +603,18 @@ int irlmp_disconnect_request(struct lsap
216 ASSERT(self != NULL, return -1;);
217 ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
218 + ASSERT(userdata != NULL, return -1;);
220 - /* Already disconnected? */
221 - if (!self->connected) {
222 - WARNING(__FUNCTION__ "(), already disconnected!\n");
223 + /* Already disconnected ?
224 + * There is a race condition between irlmp_disconnect_indication()
225 + * and us that might mess up the hashbins below. This fixes it.
227 + if (! test_and_clear_bit(0, &self->connected)) {
228 + IRDA_DEBUG(0, __FUNCTION__ "(), already disconnected!\n");
229 + dev_kfree_skb(userdata);
233 - ASSERT(userdata != NULL, return -1;);
234 - ASSERT(self->connected == TRUE, return -1;);
236 skb_push(userdata, LMP_CONTROL_HEADER);
239 @@ -634,7 +641,6 @@ int irlmp_disconnect_request(struct lsap
242 /* Reset some values */
243 - self->connected = FALSE;
244 self->dlsap_sel = LSAP_ANY;
247 @@ -651,16 +657,23 @@ void irlmp_disconnect_indication(struct
249 struct lsap_cb *lsap;
251 - IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
252 + IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
253 ASSERT(self != NULL, return;);
254 ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
255 - ASSERT(self->connected == TRUE, return;);
257 IRDA_DEBUG(3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
258 self->slsap_sel, self->dlsap_sel);
260 - self->connected = FALSE;
261 - self->dlsap_sel = LSAP_ANY;
262 + /* Already disconnected ?
263 + * There is a race condition between irlmp_disconnect_request()
264 + * and us that might mess up the hashbins below. This fixes it.
266 + if (! test_and_clear_bit(0, &self->connected)) {
267 + IRDA_DEBUG(0, __FUNCTION__ "(), already disconnected!\n");
269 + dev_kfree_skb(userdata);
273 #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
274 irlmp->cache.valid = FALSE;
275 @@ -679,6 +692,7 @@ void irlmp_disconnect_indication(struct
276 hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap, (int) lsap,
279 + self->dlsap_sel = LSAP_ANY;
283 @@ -689,7 +703,8 @@ void irlmp_disconnect_indication(struct
284 self, reason, userdata);
286 IRDA_DEBUG(0, __FUNCTION__ "(), no handler\n");
287 - dev_kfree_skb(userdata);
289 + dev_kfree_skb(userdata);
293 @@ -1401,7 +1416,7 @@ __u32 irlmp_register_client(__u16 hint_m
294 irlmp_client_t *client;
297 - IRDA_DEBUG(0, __FUNCTION__ "()\n");
298 + IRDA_DEBUG(1, __FUNCTION__ "()\n");
299 ASSERT(irlmp != NULL, return 0;);
301 /* Get a unique handle for this client */
302 @@ -1673,14 +1688,15 @@ int irlmp_proc_read(char *buf, char **st
304 len += sprintf(buf+len, "saddr: %#08x, daddr: %#08x, ",
305 lap->saddr, lap->daddr);
306 - len += sprintf(buf+len, "refcount: %d", lap->refcount);
307 + len += sprintf(buf+len, "num lsaps: %d",
308 + HASHBIN_GET_SIZE(lap->lsaps));
309 len += sprintf(buf+len, "\n");
311 - len += sprintf(buf+len, "\nConnected LSAPs:\n");
312 + len += sprintf(buf+len, "\n Connected LSAPs:\n");
313 self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
314 while (self != NULL) {
315 ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
316 - len += sprintf(buf+len, "lsap state: %s, ",
317 + len += sprintf(buf+len, " lsap state: %s, ",
318 irlsap_state[ self->lsap_state]);
319 len += sprintf(buf+len,
320 "slsap_sel: %#02x, dlsap_sel: %#02x, ",
321 diff -u -p linux/net/irda/irlmp_event.d2.c linux/net/irda/irlmp_event.c
322 --- linux/net/irda/irlmp_event.d2.c Fri Nov 2 13:55:19 2001
323 +++ linux/net/irda/irlmp_event.c Mon Nov 5 18:43:56 2001
326 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
327 * All Rights Reserved.
328 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
330 * This program is free software; you can redistribute it and/or
331 * modify it under the terms of the GNU General Public License as
332 @@ -114,6 +115,25 @@ static int (*lsap_state[])( struct lsap_
333 irlmp_state_setup_pend
336 +static inline void irlmp_next_lap_state(struct lap_cb *self,
340 + IRDA_DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
342 + self->lap_state = state;
345 +static inline void irlmp_next_lsap_state(struct lsap_cb *self,
349 + ASSERT(self != NULL, return;);
350 + IRDA_DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
352 + self->lsap_state = state;
355 /* Do connection control events */
356 int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
358 @@ -223,7 +243,6 @@ static void irlmp_state_standby(struct l
359 IRDA_DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
361 irlmp_next_lap_state(self, LAP_U_CONNECT);
364 /* FIXME: need to set users requested QoS */
365 irlap_connect_request(self->irlap, self->daddr, NULL, 0);
366 @@ -278,12 +297,12 @@ static void irlmp_state_u_connect(struct
367 * the lsaps may already have gone. This avoid getting stuck
368 * forever in LAP_ACTIVE state - Jean II */
369 if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
370 + IRDA_DEBUG(0, __FUNCTION__ "() NO LSAPs !\n");
371 irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
374 case LM_LAP_CONNECT_REQUEST:
375 /* Already trying to connect */
378 case LM_LAP_CONNECT_CONFIRM:
379 /* For all lsap_ce E Associated do LS_Connect_confirm */
380 @@ -298,12 +317,13 @@ static void irlmp_state_u_connect(struct
381 * the lsaps may already have gone. This avoid getting stuck
382 * forever in LAP_ACTIVE state - Jean II */
383 if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
384 + IRDA_DEBUG(0, __FUNCTION__ "() NO LSAPs !\n");
385 irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
388 case LM_LAP_DISCONNECT_INDICATION:
389 + IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_INDICATION\n");
390 irlmp_next_lap_state(self, LAP_STANDBY);
391 - self->refcount = 0;
393 /* Send disconnect event to all LSAPs using this link */
394 lsap = (struct lsap_cb *) hashbin_get_first( self->lsaps);
395 @@ -322,9 +342,11 @@ static void irlmp_state_u_connect(struct
396 case LM_LAP_DISCONNECT_REQUEST:
397 IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
400 - if (self->refcount == 0)
401 - irlmp_next_lap_state(self, LAP_STANDBY);
402 + /* One of the LSAP did timeout or was closed, if it was
403 + * the last one, try to get out of here - Jean II */
404 + if (HASHBIN_GET_SIZE(self->lsaps) <= 1) {
405 + irlap_disconnect_request(self->irlap);
409 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
410 @@ -352,7 +374,6 @@ static void irlmp_state_active(struct la
412 case LM_LAP_CONNECT_REQUEST:
413 IRDA_DEBUG(4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
417 * LAP connection allready active, just bounce back! Since we
418 @@ -379,8 +400,6 @@ static void irlmp_state_active(struct la
421 case LM_LAP_DISCONNECT_REQUEST:
425 * Need to find out if we should close IrLAP or not. If there
426 * is only one LSAP connection left on this link, that LSAP
427 @@ -419,7 +438,6 @@ static void irlmp_state_active(struct la
429 case LM_LAP_DISCONNECT_INDICATION:
430 irlmp_next_lap_state(self, LAP_STANDBY);
431 - self->refcount = 0;
433 /* In some case, at this point our side has already closed
434 * all lsaps, and we are waiting for the idle_timer to
435 @@ -517,6 +535,8 @@ static int irlmp_state_disconnected(stru
436 * If we receive this event while our LAP is closing down,
437 * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
438 * CONNECT_PEND state forever.
439 + * The other cause of getting stuck down there is if the
440 + * higher layer never reply to the CONNECT_INDICATION.
441 * Anyway, it make sense to make sure that we always have
442 * a backup plan. 1 second is plenty (should be immediate).
444 @@ -577,9 +597,8 @@ static int irlmp_state_connect(struct ls
446 IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
448 - /* Here, we should probably disconnect proper */
449 + /* Disconnect, get out... - Jean II */
450 self->dlsap_sel = LSAP_ANY;
451 - self->conn_skb = NULL;
452 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
455 @@ -612,15 +631,6 @@ static int irlmp_state_connect_pend(stru
456 case LM_CONNECT_REQUEST:
459 - case LM_CONNECT_INDICATION:
460 - /* Will happen in some rare cases when the socket get stuck,
461 - * the other side retries the connect request.
462 - * We just unstuck the socket - Jean II */
463 - IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_INDICATION, "
464 - "LSAP stuck in CONNECT_PEND state...\n");
466 - irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
468 case LM_CONNECT_RESPONSE:
469 IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, "
470 "no indication issued yet\n");
471 @@ -648,6 +658,8 @@ static int irlmp_state_connect_pend(stru
473 /* Go back to disconnected mode, keep the socket waiting */
474 self->dlsap_sel = LSAP_ANY;
476 + dev_kfree_skb(self->conn_skb);
477 self->conn_skb = NULL;
478 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
480 @@ -856,7 +868,7 @@ static int irlmp_state_setup_pend(struct
481 irlmp_next_lsap_state(self, LSAP_SETUP);
483 case LM_WATCHDOG_TIMEOUT:
484 - IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
485 + IRDA_DEBUG(0, __FUNCTION__ "() : WATCHDOG_TIMEOUT !\n");
487 ASSERT(self->lap != NULL, return -1;);
488 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
489 @@ -881,18 +893,4 @@ static int irlmp_state_setup_pend(struct
495 -void irlmp_next_lap_state(struct lap_cb *self, IRLMP_STATE state)
497 - IRDA_DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
498 - self->lap_state = state;
501 -void irlmp_next_lsap_state(struct lsap_cb *self, LSAP_STATE state)
503 - ASSERT(self != NULL, return;);
505 - IRDA_DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
506 - self->lsap_state = state;
508 diff -u -p linux/net/irda/irlmp_frame.d2.c linux/net/irda/irlmp_frame.c
509 --- linux/net/irda/irlmp_frame.d2.c Thu Nov 1 15:07:57 2001
510 +++ linux/net/irda/irlmp_frame.c Mon Nov 5 18:44:14 2001
513 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
514 * All Rights Reserved.
515 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
517 * This program is free software; you can redistribute it and/or
518 * modify it under the terms of the GNU General Public License as
520 #include <net/irda/irlmp_frame.h>
521 #include <net/irda/discovery.h>
523 -#define DISCO_SMALL_DELAY 250 /* Delay for some discoveries in ms */
524 -struct timer_list disco_delay; /* The timer associated */
526 static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap,
527 __u8 slsap, int status, hashbin_t *);
529 @@ -343,28 +341,6 @@ void irlmp_link_connect_confirm(struct l
533 - * Function irlmp_discovery_timeout (priv)
535 - * Create a discovery event to the state machine (called after a delay)
537 - * Note : irlmp_do_lap_event will handle the very rare case where the LAP
538 - * is destroyed while we were sleeping.
540 -static void irlmp_discovery_timeout(u_long priv)
542 - struct lap_cb *self;
544 - IRDA_DEBUG(2, __FUNCTION__ "()\n");
546 - self = (struct lap_cb *) priv;
547 - ASSERT(self != NULL, return;);
549 - /* Just handle it the same way as a discovery confirm,
550 - * bypass the LM_LAP state machine (see below) */
551 - irlmp_discovery_confirm(irlmp->cachelog);
555 * Function irlmp_link_discovery_indication (self, log)
557 * Device is discovering us
558 @@ -379,25 +355,16 @@ static void irlmp_discovery_timeout(u_lo
559 * o Make faster discovery, statistically divide time of discovery
560 * events by 2 (important for the latency aspect and user feel)
561 * o Even is we do active discovery, the other node might not
562 - * answer our discoveries (ex: Palm).
563 + * answer our discoveries (ex: Palm). The Palm will just perform
564 + * one active discovery and connect directly to us.
566 * However, when both devices discover each other, they might attempt to
567 * connect to each other following the discovery event, and it would create
568 * collisions on the medium (SNRM battle).
569 - * The trick here is to defer the event by a little delay to avoid both
570 - * devices to jump in exactly at the same time...
572 - * The delay is currently set to 0.25s, which leave enough time to perform
573 - * a connection and don't interfer with next discovery (the lowest discovery
574 - * period/timeout that may be set is 1s). The message triggering this
575 - * event was the last of the discovery, so the medium is now free...
576 - * Maybe more testing is needed to get the value right...
578 - * One more problem : the other node might do only a single discovery
579 - * and connect immediately to us, and we would receive only a single
580 - * discovery indication event, and because of the delay, it will arrive
581 - * while the LAP is connected. That's another good reason to
582 - * bypass the LM_LAP state machine ;-)
583 + * The "fix" for that is to disable all connection requests in IrLAP
584 + * for 100ms after a discovery indication by setting the media_busy flag.
585 + * Previously, we used to postpone the event which was quite ugly. Now
586 + * that IrLAP takes care of this problem, just pass the event up...
590 @@ -409,14 +376,9 @@ void irlmp_link_discovery_indication(str
592 irlmp_add_discovery(irlmp->cachelog, discovery);
594 - /* If delay was activated, kill it! */
595 - if(timer_pending(&disco_delay))
596 - del_timer(&disco_delay);
597 - /* Set delay timer to expire in 0.25s. */
598 - disco_delay.expires = jiffies + (DISCO_SMALL_DELAY * HZ/1000);
599 - disco_delay.function = irlmp_discovery_timeout;
600 - disco_delay.data = (unsigned long) self;
601 - add_timer(&disco_delay);
602 + /* Just handle it the same way as a discovery confirm,
603 + * bypass the LM_LAP state machine (see below) */
604 + irlmp_discovery_confirm(irlmp->cachelog);
608 @@ -435,10 +397,6 @@ void irlmp_link_discovery_confirm(struct
609 ASSERT(self->magic == LMP_LAP_MAGIC, return;);
611 irlmp_add_discovery_log(irlmp->cachelog, log);
613 - /* If discovery delay was activated, kill it! */
614 - if(timer_pending(&disco_delay))
615 - del_timer(&disco_delay);
617 /* Propagate event to various LSAPs registered for it.
618 * We bypass the LM_LAP state machine because
619 diff -u -p linux/net/irda/irlap.d2.c linux/net/irda/irlap.c
620 --- linux/net/irda/irlap.d2.c Fri Nov 2 17:23:04 2001
621 +++ linux/net/irda/irlap.c Mon Nov 5 18:41:34 2001
623 * Modified by: Dag Brattli <dagb@cs.uit.no>
625 * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
626 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
628 * This program is free software; you can redistribute it and/or
629 * modify it under the terms of the GNU General Public License as
630 @@ -502,10 +503,17 @@ void irlap_discovery_request(struct irla
631 IRDA_DEBUG(4, __FUNCTION__
632 "(), discovery only possible in NDM mode\n");
633 irlap_discovery_confirm(self, NULL);
634 + /* Note : in theory, if we are not in NDM, we could postpone
635 + * the discovery like we do for connection request.
636 + * In practice, it's not worth it. If the media was busy,
637 + * it's likely next time around it won't be busy. If we are
638 + * in REPLY state, we will get passive discovery info & event.
643 - /* Check if last discovery request finished in time */
644 + /* Check if last discovery request finished in time, or if
645 + * it was aborted due to the media busy flag. */
646 if (self->discovery_log != NULL) {
647 hashbin_delete(self->discovery_log, (FREE_FUNC) kfree);
648 self->discovery_log = NULL;
649 @@ -555,10 +563,16 @@ void irlap_discovery_confirm(struct irla
652 * Check for successful discovery, since we are then allowed to clear
653 - * the media busy condition (irlap p.94). This should allow us to make
654 - * connection attempts much easier.
655 + * the media busy condition (IrLAP 6.13.4 - p.94). This should allow
656 + * us to make connection attempts much faster and easier (i.e. no
658 + * Setting media busy to false will also generate an event allowing
659 + * to process pending events in NDM state machine.
660 + * Note : the spec doesn't define what's a successful discovery is.
661 + * If we want Ultra to work, it's successful even if there is
662 + * nobody discovered - Jean II
664 - if (discovery_log && HASHBIN_GET_SIZE(discovery_log) > 0)
666 irda_device_set_media_busy(self->netdev, FALSE);
669 @@ -580,7 +594,18 @@ void irlap_discovery_indication(struct i
670 ASSERT(discovery != NULL, return;);
672 ASSERT(self->notify.instance != NULL, return;);
675 + /* A device is very likely to connect immediately after it performs
676 + * a successful discovery. This means that in our case, we are much
677 + * more likely to receive a connection request over the medium.
678 + * So, we backoff to avoid collisions.
679 + * IrLAP spec 6.13.4 suggest 100ms...
680 + * Note : this little trick actually make a *BIG* difference. If I set
681 + * my Linux box with discovery enabled and one Ultra frame sent every
682 + * second, my Palm has no trouble connecting to it every time !
684 + irda_device_set_media_busy(self->netdev, SMALL);
686 irlmp_link_discovery_indication(self->notify.instance, discovery);
689 diff -u -p linux/net/irda/irlap_event.d2.c linux/net/irda/irlap_event.c
690 --- linux/net/irda/irlap_event.d2.c Fri Nov 2 16:28:13 2001
691 +++ linux/net/irda/irlap_event.c Mon Nov 5 18:42:55 2001
693 * Copyright (c) 1998-2000 Dag Brattli <dag@brattli.net>,
694 * Copyright (c) 1998 Thomas Davis <ratbert@radiks.net>
695 * All Rights Reserved.
696 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
698 * This program is free software; you can redistribute it and/or
699 * modify it under the terms of the GNU General Public License as
700 @@ -114,6 +115,7 @@ static const char *irlap_event[] = {
701 "DISCOVERY_TIMER_EXPIRED",
703 "BACKOFF_TIMER_EXPIRED",
704 + "MEDIA_BUSY_TIMER_EXPIRED",
707 const char *irlap_state[] = {
708 @@ -263,15 +265,7 @@ void irlap_do_event(struct irlap_cb *sel
713 - /* Check if we should try to connect */
714 - if ((self->connect_pending) && !self->media_busy) {
715 - self->connect_pending = FALSE;
717 - ret = (*state[self->state])(self, CONNECT_REQUEST,
723 /* case LAP_RESET_WAIT: */
724 /* case LAP_RESET_CHECK: */
725 @@ -305,17 +299,6 @@ void irlap_next_state(struct irlap_cb *s
726 if ((state != LAP_XMIT_P) && (state != LAP_XMIT_S))
727 self->bytes_left = self->line_capacity;
728 #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
729 -#ifdef CONFIG_IRDA_ULTRA
730 - /* Send any pending Ultra frames if any */
731 - /* The higher layers may have sent a few Ultra frames while we
732 - * were doing discovery (either query or reply). Those frames
733 - * have been queued, but were never sent. It is now time to
736 - if ((state == LAP_NDM) && (!skb_queue_empty(&self->txq_ultra)))
737 - /* Force us to listen 500 ms before sending Ultra */
738 - irda_device_set_media_busy(self->netdev, TRUE);
739 -#endif /* CONFIG_IRDA_ULTRA */
743 @@ -339,6 +322,9 @@ static int irlap_state_ndm(struct irlap_
744 ASSERT(self->netdev != NULL, return -1;);
746 if (self->media_busy) {
747 + /* Note : this will never happen, because we test
748 + * media busy in irlap_connect_request() and
749 + * postpone the event... - Jean II */
750 IRDA_DEBUG(0, __FUNCTION__
751 "(), CONNECT_REQUEST: media busy!\n");
753 @@ -379,6 +365,9 @@ static int irlap_state_ndm(struct irlap_
755 /* This will make IrLMP try again */
756 irlap_discovery_confirm(self, NULL);
757 + /* Note : the discovery log is not cleaned up here,
758 + * it will be done in irlap_discovery_request()
763 @@ -417,8 +406,7 @@ static int irlap_state_ndm(struct irlap_
765 irlap_start_query_timer(self, QUERY_TIMEOUT*info->S);
766 irlap_next_state(self, LAP_REPLY);
770 /* This is the final slot. How is it possible ?
771 * This would happen is both discoveries are just slightly
772 * offset (if they are in sync, all packets are lost).
773 @@ -440,6 +428,54 @@ static int irlap_state_ndm(struct irlap_
774 irlap_discovery_indication(self, info->discovery);
777 + case MEDIA_BUSY_TIMER_EXPIRED:
778 + /* A bunch of events may be postponed because the media is
779 + * busy (usually immediately after we close a connection),
780 + * or while we are doing discovery (state query/reply).
781 + * In all those cases, the media busy flag will be cleared
782 + * when it's OK for us to process those postponed events.
783 + * This event is not mentioned in the state machines in the
784 + * IrLAP spec. It's because they didn't consider Ultra and
785 + * postponing connection request is optional.
787 +#ifdef CONFIG_IRDA_ULTRA
788 + /* Send any pending Ultra frames if any */
789 + if (!skb_queue_empty(&self->txq_ultra)) {
790 + /* We don't send the frame, just post an event.
791 + * Also, previously this code was in timer.c...
793 + ret = (*state[self->state])(self, SEND_UI_FRAME,
796 +#endif /* CONFIG_IRDA_ULTRA */
797 + /* Check if we should try to connect.
798 + * This code was previously in irlap_do_event() */
799 + if (self->connect_pending) {
800 + self->connect_pending = FALSE;
802 + /* This one *should* not pend in this state, except
803 + * if a socket try to connect and immediately
804 + * disconnect. - clear - Jean II */
805 + if (self->disconnect_pending)
806 + irlap_disconnect_indication(self, LAP_DISC_INDICATION);
808 + ret = (*state[self->state])(self,
811 + self->disconnect_pending = FALSE;
813 + /* Note : one way to test if this code works well (including
814 + * media busy and small busy) is to create a user space
815 + * application generating an Ultra packet every 3.05 sec (or
816 + * 2.95 sec) and to see how it interact with discovery.
817 + * It's fairly easy to check that no packet is lost, that the
818 + * packets are postponed during discovery and that after
819 + * discovery indication you have a 100ms "gap".
820 + * As connection request and Ultra are now processed the same
821 + * way, this avoid the tedious job of trying IrLAP connection
822 + * in all those cases...
825 #ifdef CONFIG_IRDA_ULTRA
827 /* Only allowed to repeat an operation twice */
828 @@ -735,8 +771,10 @@ static int irlap_state_conn(struct irlap
831 case DISCONNECT_REQUEST:
832 + IRDA_DEBUG(0, __FUNCTION__ "(), Disconnect request!\n");
833 irlap_send_dm_frame(self);
834 - irlap_next_state( self, LAP_CONN);
835 + irlap_next_state( self, LAP_NDM);
836 + irlap_disconnect_indication(self, LAP_DISC_INDICATION);
839 IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
840 @@ -1417,13 +1455,12 @@ static int irlap_state_nrm_p(struct irla
841 irlap_start_final_timer(self, self->final_timeout);
844 - IRDA_DEBUG(0, __FUNCTION__ "(), RECV_RD_RSP\n");
845 + IRDA_DEBUG(1, __FUNCTION__ "(), RECV_RD_RSP\n");
847 - irlap_next_state(self, LAP_PCLOSE);
848 - irlap_send_disc_frame(self);
849 irlap_flush_all_queues(self);
850 - irlap_start_final_timer(self, self->final_timeout);
851 - self->retry_count = 0;
852 + irlap_next_state(self, LAP_XMIT_P);
853 + /* Call back the LAP state machine to do a proper disconnect */
854 + irlap_disconnect_request(self);
857 IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n",
858 diff -u -p linux/net/irda/irlap_frame.d2.c linux/net/irda/irlap_frame.c
859 --- linux/net/irda/irlap_frame.d2.c Fri Nov 2 18:15:13 2001
860 +++ linux/net/irda/irlap_frame.c Mon Nov 5 18:43:15 2001
863 * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
864 * All Rights Reserved.
865 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
867 * This program is free software; you can redistribute it and/or
868 * modify it under the terms of the GNU General Public License as
869 @@ -696,7 +697,7 @@ static void irlap_recv_srej_frame(struct
870 static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
871 struct irlap_info *info, int command)
873 - IRDA_DEBUG(0, __FUNCTION__ "()\n");
874 + IRDA_DEBUG(2, __FUNCTION__ "()\n");
876 /* Check if this is a command or a response frame */
878 diff -u -p linux/net/irda/timer.d2.c linux/net/irda/timer.c
879 --- linux/net/irda/timer.d2.c Fri Nov 2 18:04:22 2001
880 +++ linux/net/irda/timer.c Mon Nov 5 18:45:23 2001
883 * Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
884 * All Rights Reserved.
885 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
887 * This program is free software; you can redistribute it and/or
888 * modify it under the terms of the GNU General Public License as
889 @@ -94,29 +95,24 @@ void irlap_start_backoff_timer(struct ir
890 irlap_backoff_timer_expired);
893 -void irlap_start_mbusy_timer(struct irlap_cb *self)
894 +void irlap_start_mbusy_timer(struct irlap_cb *self, int timeout)
896 - irda_start_timer(&self->media_busy_timer, MEDIABUSY_TIMEOUT,
897 + irda_start_timer(&self->media_busy_timer, timeout,
898 (void *) self, irlap_media_busy_expired);
901 void irlap_stop_mbusy_timer(struct irlap_cb *self)
903 /* If timer is activated, kill it! */
904 - if(timer_pending(&self->media_busy_timer))
905 - del_timer(&self->media_busy_timer);
906 + del_timer(&self->media_busy_timer);
908 -#ifdef CONFIG_IRDA_ULTRA
909 - /* Send any pending Ultra frames if any */
910 - if (!skb_queue_empty(&self->txq_ultra))
911 - /* Note : we don't send the frame, just post an event.
912 - * Frames will be sent only if we are in NDM mode (see
914 - * Also, moved this code from irlap_media_busy_expired()
915 - * to here to catch properly all cases...
917 - irlap_do_event(self, SEND_UI_FRAME, NULL, NULL);
918 -#endif /* CONFIG_IRDA_ULTRA */
919 + /* If we are in NDM, there is a bunch of events in LAP that
920 + * that be pending due to the media_busy condition, such as
921 + * CONNECT_REQUEST and SEND_UI_FRAME. If we don't generate
922 + * an event, they will wait forever...
924 + if (self->state == LAP_NDM)
925 + irlap_do_event(self, MEDIA_BUSY_TIMER_EXPIRED, NULL, NULL);
928 void irlmp_start_watchdog_timer(struct lsap_cb *self, int timeout)
929 @@ -237,5 +233,7 @@ void irlap_media_busy_expired(void* data
930 ASSERT(self != NULL, return;);
932 irda_device_set_media_busy(self->netdev, FALSE);
933 - /* Note : will deal with Ultra frames */
934 + /* Note : the LAP event will be send in irlap_stop_mbusy_timer(),
935 + * to catch other cases where the flag is cleared (for example
936 + * after a discovery) - Jean II */
938 diff -u -p linux/net/irda/irda_device.d2.c linux/net/irda/irda_device.c
939 --- linux/net/irda/irda_device.d2.c Fri Nov 2 18:04:40 2001
940 +++ linux/net/irda/irda_device.c Mon Nov 5 18:40:43 2001
942 * Modified by: Dag Brattli <dagb@cs.uit.no>
944 * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
945 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
947 * This program is free software; you can redistribute it and/or
948 * modify it under the terms of the GNU General Public License as
949 @@ -181,7 +182,10 @@ void irda_device_set_media_busy(struct n
952 self->media_busy = TRUE;
953 - irlap_start_mbusy_timer(self);
954 + if (status == SMALL)
955 + irlap_start_mbusy_timer(self, SMALLBUSY_TIMEOUT);
957 + irlap_start_mbusy_timer(self, MEDIABUSY_TIMEOUT);
958 IRDA_DEBUG( 4, "Media busy!\n");
960 self->media_busy = FALSE;