]> git.pld-linux.org Git - packages/kernel.git/blob - ir243_lap_lmp_races-2.diff
- added description of djurban's branch
[packages/kernel.git] / ir243_lap_lmp_races-2.diff
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
4 @@ -11,6 +11,7 @@
5   * 
6   *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
7   *     All Rights Reserved.
8 + *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
9   *     
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 {
13  
14         struct irlap_cb *irlap;   /* Instance of IrLAP layer */
15         hashbin_t *lsaps;         /* LSAP associated with this link */
16 -       int refcount;
17  
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
23 @@ -11,6 +11,7 @@
24   * 
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>
28   *     
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);
35 -
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);
39  
40  void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event, 
41                         struct sk_buff *skb);
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
45 @@ -12,6 +12,7 @@
46   * 
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>
50   *     
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,
55         WD_TIMER_EXPIRED,
56         BACKOFF_TIMER_EXPIRED,
57 +       MEDIA_BUSY_TIMER_EXPIRED,
58  } IRLAP_EVENT;
59  
60  /*
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
64 @@ -11,6 +11,7 @@
65   * 
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>
69   *     
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 
72 @@ -47,7 +48,9 @@
73   *  duration of the P-timer.
74   */
75  #define WD_TIMEOUT          (POLL_TIMEOUT*2)
76 +
77  #define MEDIABUSY_TIMEOUT   (500*HZ/1000)    /* 500 msec */
78 +#define SMALLBUSY_TIMEOUT   (100*HZ/1000)    /* 100 msec - IrLAP 6.13.4 */
79  
80  /*
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);
85  
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 *);
89  
90  struct lsap_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
94 @@ -10,6 +10,7 @@
95   * Modified by:   Dag Brattli <dagb@cs.uit.no>
96   * 
97   *     Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
98 + *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
99   *      
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;
103  
104  #ifndef FALSE 
105  #define FALSE 0
106 +#endif
107 +
108 +/* Hack to do small backoff when setting media busy in IrLAP */
109 +#ifndef SMALL
110 +#define SMALL 5
111  #endif
112  
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
117 @@ -11,6 +11,7 @@
118   * 
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>
122   *     
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
126   */
127  int __init irlmp_init(void)
128  {
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);
133         if (irlmp == NULL)
134 @@ -170,14 +171,14 @@ struct lsap_cb *irlmp_open_lsap(__u8 sls
135  #endif /* CONFIG_IRDA_ULTRA */
136         } else
137                 self->dlsap_sel = LSAP_ANY;
138 -       self->connected = FALSE;
139 +       /* self->connected = FALSE; -> already NULL via memset() */
140  
141         init_timer(&self->watchdog_timer);
142  
143         ASSERT(notify->instance != NULL, return NULL;);
144         self->notify = *notify;
145  
146 -       irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
147 +       self->lsap_state = LSAP_DISCONNECTED;
148         
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);
154         }
155 +       self->lap = NULL;
156         /* Check if we found the LSAP! If not then try the unconnected lsaps */
157         if (!lsap) {
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);
162  
163 -       irlmp_next_lap_state(lap, LAP_STANDBY);
164 +       lap->lap_state = LAP_STANDBY;
165         
166         init_timer(&lap->idle_timer);
167  
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);
171         
172 -       if (self->connected) 
173 +       if (test_bit(0, &self->connected))
174                 return -EISCONN;
175         
176         /* Client must supply destination device address */
177 @@ -435,7 +437,7 @@ int irlmp_connect_request(struct lsap_cb
178  
179         hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self, NULL);
180  
181 -       self->connected = TRUE;
182 +       set_bit(0, &self->connected);   /* TRUE */
183         
184         /*
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);
190 +       else
191 +               dev_kfree_skb(skb);
192  }
193  
194  /*
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;);
198  
199 -       self->connected = TRUE;
200 +       set_bit(0, &self->connected);   /* TRUE */
201  
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);
208 -       }
209 +       } else
210 +               dev_kfree_skb(skb);
211  }
212  
213  /*
214 @@ -598,16 +603,18 @@ int irlmp_disconnect_request(struct lsap
215  
216         ASSERT(self != NULL, return -1;);
217         ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
218 +       ASSERT(userdata != NULL, return -1;);
219  
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.
226 +        * Jean II */
227 +       if (! test_and_clear_bit(0, &self->connected)) {
228 +               IRDA_DEBUG(0, __FUNCTION__ "(), already disconnected!\n");
229 +               dev_kfree_skb(userdata);
230                 return -1;
231         }
232  
233 -       ASSERT(userdata != NULL, return -1;);
234 -       ASSERT(self->connected == TRUE, return -1;);
235 -       
236         skb_push(userdata, LMP_CONTROL_HEADER);
237  
238         /* 
239 @@ -634,7 +641,6 @@ int irlmp_disconnect_request(struct lsap
240                        NULL);
241         
242         /* Reset some values */
243 -       self->connected = FALSE;
244         self->dlsap_sel = LSAP_ANY;
245         self->lap = NULL;
246         
247 @@ -651,16 +657,23 @@ void irlmp_disconnect_indication(struct 
248  {
249         struct lsap_cb *lsap;
250  
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;); 
256  
257         IRDA_DEBUG(3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
258                    self->slsap_sel, self->dlsap_sel);
259  
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.
265 +        * Jean II */
266 +       if (! test_and_clear_bit(0, &self->connected)) {
267 +               IRDA_DEBUG(0, __FUNCTION__ "(), already disconnected!\n");
268 +               if (userdata)
269 +                       dev_kfree_skb(userdata);
270 +               return;
271 +       }
272  
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, 
277                        NULL);
278  
279 +       self->dlsap_sel = LSAP_ANY;
280         self->lap = NULL;
281         
282         /*
283 @@ -689,7 +703,8 @@ void irlmp_disconnect_indication(struct 
284                                                    self, reason, userdata);
285         else {
286                 IRDA_DEBUG(0, __FUNCTION__ "(), no handler\n");
287 -               dev_kfree_skb(userdata);
288 +               if (userdata)
289 +                       dev_kfree_skb(userdata);
290         }
291  }
292  
293 @@ -1401,7 +1416,7 @@ __u32 irlmp_register_client(__u16 hint_m
294         irlmp_client_t *client;
295         __u32 handle;
296  
297 -       IRDA_DEBUG(0, __FUNCTION__ "()\n");
298 +       IRDA_DEBUG(1, __FUNCTION__ "()\n");
299         ASSERT(irlmp != NULL, return 0;);
300         
301         /* Get a unique handle for this client */
302 @@ -1673,14 +1688,15 @@ int irlmp_proc_read(char *buf, char **st
303  
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");
310  
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
324 @@ -11,6 +11,7 @@
325   * 
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>
329   *     
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
334  };
335  
336 +static inline void irlmp_next_lap_state(struct lap_cb *self,
337 +                                       IRLMP_STATE state) 
338 +{
339 +       /*
340 +       IRDA_DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
341 +       */
342 +       self->lap_state = state;
343 +}
344 +
345 +static inline void irlmp_next_lsap_state(struct lsap_cb *self,
346 +                                        LSAP_STATE state) 
347 +{
348 +       /*
349 +       ASSERT(self != NULL, return;);
350 +       IRDA_DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
351 +       */
352 +       self->lsap_state = state;
353 +}
354 +
355  /* Do connection control events */
356  int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event, 
357                         struct sk_buff *skb)
358 @@ -223,7 +243,6 @@ static void irlmp_state_standby(struct l
359                 IRDA_DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
360  
361                 irlmp_next_lap_state(self, LAP_U_CONNECT);
362 -               self->refcount++;
363  
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);
372                 }
373                 break;
374         case LM_LAP_CONNECT_REQUEST:
375                 /* Already trying to connect */
376 -               self->refcount++;
377                 break;
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);
386                 }
387                 break;
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;
392  
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");
398  
399 -               self->refcount--;
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);
406 +               }
407                 break;
408         default:
409                 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
410 @@ -352,7 +374,6 @@ static void irlmp_state_active(struct la
411         switch (event) {
412         case LM_LAP_CONNECT_REQUEST:
413                 IRDA_DEBUG(4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
414 -               self->refcount++;
415  
416                 /*
417                  *  LAP connection allready active, just bounce back! Since we 
418 @@ -379,8 +400,6 @@ static void irlmp_state_active(struct la
419                 /* Keep state */
420                 break;
421         case LM_LAP_DISCONNECT_REQUEST:
422 -               self->refcount--;
423 -
424                 /*
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
428                 break;
429         case LM_LAP_DISCONNECT_INDICATION:
430                 irlmp_next_lap_state(self, LAP_STANDBY);                
431 -               self->refcount = 0;
432                 
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).
443                  * Jean II */
444 @@ -577,9 +597,8 @@ static int irlmp_state_connect(struct ls
445                  * Jean II */
446                 IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
447  
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);
453                 break;
454         default:
455 @@ -612,15 +631,6 @@ static int irlmp_state_connect_pend(stru
456         case LM_CONNECT_REQUEST:
457                 /* Keep state */
458                 break;
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");
465 -               /* Keep state */
466 -               irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
467 -               break;
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
472  
473                 /* Go back to disconnected mode, keep the socket waiting */
474                 self->dlsap_sel = LSAP_ANY;
475 +               if(self->conn_skb)
476 +                       dev_kfree_skb(self->conn_skb);
477                 self->conn_skb = NULL;
478                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
479                 break;
480 @@ -856,7 +868,7 @@ static int irlmp_state_setup_pend(struct
481                 irlmp_next_lsap_state(self, LSAP_SETUP);
482                 break;
483         case LM_WATCHDOG_TIMEOUT:
484 -               IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
485 +               IRDA_DEBUG(0, __FUNCTION__ "() : WATCHDOG_TIMEOUT !\n");
486  
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
490                 break;  
491         }
492         return ret;
493 -}
494 -
495 -void irlmp_next_lap_state(struct lap_cb *self, IRLMP_STATE state) 
496 -{
497 -       IRDA_DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
498 -       self->lap_state = state;
499 -}
500 -
501 -void irlmp_next_lsap_state(struct lsap_cb *self, LSAP_STATE state) 
502 -{
503 -       ASSERT(self != NULL, return;);
504 -
505 -       IRDA_DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
506 -       self->lsap_state = state;
507  }
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
511 @@ -11,6 +11,7 @@
512   * 
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>
516   *     
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 
519 @@ -34,9 +35,6 @@
520  #include <net/irda/irlmp_frame.h>
521  #include <net/irda/discovery.h>
522  
523 -#define        DISCO_SMALL_DELAY       250     /* Delay for some discoveries in ms */
524 -struct timer_list disco_delay;         /* The timer associated */
525 -
526  static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap, 
527                                        __u8 slsap, int status, hashbin_t *);
528  
529 @@ -343,28 +341,6 @@ void irlmp_link_connect_confirm(struct l
530  }
531  
532  /*
533 - * Function irlmp_discovery_timeout (priv)
534 - *
535 - *    Create a discovery event to the state machine (called after a delay)
536 - *
537 - * Note : irlmp_do_lap_event will handle the very rare case where the LAP
538 - * is destroyed while we were sleeping.
539 - */
540 -static void irlmp_discovery_timeout(u_long     priv)
541 -{
542 -       struct lap_cb *self;
543 -
544 -       IRDA_DEBUG(2, __FUNCTION__ "()\n");
545 -
546 -       self = (struct lap_cb *) priv;
547 -       ASSERT(self != NULL, return;);
548 -
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);
552 -}
553 -
554 -/*
555   * Function irlmp_link_discovery_indication (self, log)
556   *
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.
565   *
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...
571 - *
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...
577 -
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...
587   *
588   * Jean II
589   */
590 @@ -409,14 +376,9 @@ void irlmp_link_discovery_indication(str
591  
592         irlmp_add_discovery(irlmp->cachelog, discovery);
593         
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);
605  }
606  
607  /*
608 @@ -435,10 +397,6 @@ void irlmp_link_discovery_confirm(struct
609         ASSERT(self->magic == LMP_LAP_MAGIC, return;);
610         
611         irlmp_add_discovery_log(irlmp->cachelog, log);
612 -
613 -       /* If discovery delay was activated, kill it! */
614 -       if(timer_pending(&disco_delay))
615 -               del_timer(&disco_delay);
616  
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
622 @@ -10,6 +10,7 @@
623   * Modified by:   Dag Brattli <dagb@cs.uit.no>
624   * 
625   *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
626 + *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
627   *     
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.
639 +                * Jean II */
640                 return;
641         }
642  
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
650         
651         /* 
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
657 +        * collisions).
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
663          */
664 -       if (discovery_log && HASHBIN_GET_SIZE(discovery_log) > 0)
665 +       if (discovery_log)
666                 irda_device_set_media_busy(self->netdev, FALSE);
667         
668         /* Inform IrLMP */
669 @@ -580,7 +594,18 @@ void irlap_discovery_indication(struct i
670         ASSERT(discovery != NULL, return;);
671  
672         ASSERT(self->notify.instance != NULL, return;);
673 -       
674 +
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 !
683 +        * Jean II */
684 +       irda_device_set_media_busy(self->netdev, SMALL);
685 +
686         irlmp_link_discovery_indication(self->notify.instance, discovery);
687  }
688  
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
692 @@ -12,6 +12,7 @@
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>
697   *     
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",
702         "WD_TIMER_EXPIRED",
703         "BACKOFF_TIMER_EXPIRED",
704 +       "MEDIA_BUSY_TIMER_EXPIRED",
705  };
706  
707  const char *irlap_state[] = {
708 @@ -263,15 +265,7 @@ void irlap_do_event(struct irlap_cb *sel
709                                                     NULL, NULL);
710                 }
711                 break;
712 -       case LAP_NDM:
713 -               /* Check if we should try to connect */
714 -               if ((self->connect_pending) && !self->media_busy) {
715 -                       self->connect_pending = FALSE;
716 -                       
717 -                       ret = (*state[self->state])(self, CONNECT_REQUEST, 
718 -                                                   NULL, NULL);
719 -               }
720 -               break;
721 +/*     case LAP_NDM: */
722  /*     case LAP_CONN: */
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
734 -        * send them...
735 -        * Jean II */
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 */
740  }
741  
742  /*
743 @@ -339,6 +322,9 @@ static int irlap_state_ndm(struct irlap_
744                 ASSERT(self->netdev != NULL, return -1;);
745  
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");
752                         
753 @@ -379,6 +365,9 @@ static int irlap_state_ndm(struct irlap_
754                                                 
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()
759 +                        * Jean II */
760                         return 0;
761                 } 
762                 
763 @@ -417,8 +406,7 @@ static int irlap_state_ndm(struct irlap_
764                          */
765                         irlap_start_query_timer(self, QUERY_TIMEOUT*info->S);
766                         irlap_next_state(self, LAP_REPLY);
767 -               }
768 -               else {
769 +               } else {
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); 
775                 }
776                 break;
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.
786 +                * Jean II */
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...
792 +                        * Jean II */
793 +                       ret = (*state[self->state])(self, SEND_UI_FRAME, 
794 +                                                   NULL, NULL);
795 +               }
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;
801 +
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);
807 +                       else
808 +                               ret = (*state[self->state])(self,
809 +                                                           CONNECT_REQUEST, 
810 +                                                           NULL, NULL);
811 +                       self->disconnect_pending = FALSE;
812 +               }
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...
823 +                * Jean II */
824 +               break;
825  #ifdef CONFIG_IRDA_ULTRA
826         case SEND_UI_FRAME:
827                 /* Only allowed to repeat an operation twice */
828 @@ -735,8 +771,10 @@ static int irlap_state_conn(struct irlap
829  
830                 break;          
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);
837                 break;
838         default:
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);
842                 break;
843         case RECV_RD_RSP:
844 -               IRDA_DEBUG(0, __FUNCTION__ "(), RECV_RD_RSP\n");
845 +               IRDA_DEBUG(1, __FUNCTION__ "(), RECV_RD_RSP\n");
846  
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);
855                 break;
856         default:
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
861 @@ -11,6 +11,7 @@
862   * 
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>
866   *     
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)
872  {
873 -       IRDA_DEBUG(0, __FUNCTION__ "()\n");
874 +       IRDA_DEBUG(2, __FUNCTION__ "()\n");
875  
876         /* Check if this is a command or a response frame */
877         if (command)
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
881 @@ -11,6 +11,7 @@
882   * 
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>
886   *     
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);
891  }
892  
893 -void irlap_start_mbusy_timer(struct irlap_cb *self)
894 +void irlap_start_mbusy_timer(struct irlap_cb *self, int timeout)
895  {
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);
899  }
900  
901  void irlap_stop_mbusy_timer(struct irlap_cb *self)
902  {
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);
907  
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
913 -                * irlap_event.c).
914 -                * Also, moved this code from irlap_media_busy_expired()
915 -                * to here to catch properly all cases...
916 -                * Jean II */
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...
923 +        * Jean II */
924 +       if (self->state == LAP_NDM)
925 +               irlap_do_event(self, MEDIA_BUSY_TIMER_EXPIRED, NULL, NULL);
926  }
927  
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;);
931  
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 */
937  }
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
941 @@ -10,6 +10,7 @@
942   * Modified by:   Dag Brattli <dagb@cs.uit.no>
943   * 
944   *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
945 + *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
946   *     
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
950  
951         if (status) {
952                 self->media_busy = TRUE;
953 -               irlap_start_mbusy_timer(self);
954 +               if (status == SMALL)
955 +                       irlap_start_mbusy_timer(self, SMALLBUSY_TIMEOUT);
956 +               else
957 +                       irlap_start_mbusy_timer(self, MEDIABUSY_TIMEOUT);
958                 IRDA_DEBUG( 4, "Media busy!\n");
959         } else {
960                 self->media_busy = FALSE;
961
This page took 0.46226 seconds and 3 git commands to generate.