]>
Commit | Line | Data |
---|---|---|
f9435081 | 1 | diff -u -p linux/include/net/irda/irmod.d2.h linux/include/net/irda/irmod.h |
2 | --- linux/include/net/irda/irmod.d2.h Wed Nov 7 13:21:31 2001 | |
3 | +++ linux/include/net/irda/irmod.h Wed Nov 7 13:57:41 2001 | |
4 | @@ -10,6 +10,7 @@ | |
5 | * Modified by: Dag Brattli <dagb@cs.uit.no> | |
6 | * | |
7 | * Copyright (c) 1998-2000 Dag Brattli, 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 | @@ -25,108 +26,19 @@ | |
13 | #ifndef IRMOD_H | |
14 | #define IRMOD_H | |
15 | ||
16 | -#include <linux/skbuff.h> | |
17 | -#include <linux/miscdevice.h> | |
18 | +#include <net/irda/irda.h> /* Notify stuff */ | |
19 | ||
20 | -#include <net/irda/irqueue.h> | |
21 | +/* Nothing much here anymore - Maybe this header should be merged in | |
22 | + * another header like net/irda/irda.h... - Jean II */ | |
23 | ||
24 | -#define IRMGR_IOC_MAGIC 'm' | |
25 | -#define IRMGR_IOCTNPC _IO(IRMGR_IOC_MAGIC, 1) | |
26 | -#define IRMGR_IOC_MAXNR 1 | |
27 | - | |
28 | -/* | |
29 | - * Events that we pass to the user space manager | |
30 | - */ | |
31 | -typedef enum { | |
32 | - EVENT_DEVICE_DISCOVERED = 0, | |
33 | - EVENT_REQUEST_MODULE, | |
34 | - EVENT_IRLAN_START, | |
35 | - EVENT_IRLAN_STOP, | |
36 | - EVENT_IRLPT_START, /* Obsolete */ | |
37 | - EVENT_IRLPT_STOP, /* Obsolete */ | |
38 | - EVENT_IROBEX_START, /* Obsolete */ | |
39 | - EVENT_IROBEX_STOP, /* Obsolete */ | |
40 | - EVENT_IRDA_STOP, | |
41 | - EVENT_NEED_PROCESS_CONTEXT, | |
42 | -} IRMGR_EVENT; | |
43 | - | |
44 | -/* | |
45 | - * Event information passed to the IrManager daemon process | |
46 | - */ | |
47 | -struct irmanager_event { | |
48 | - IRMGR_EVENT event; | |
49 | - char devname[10]; | |
50 | - char info[32]; | |
51 | - int service; | |
52 | - __u32 saddr; | |
53 | - __u32 daddr; | |
54 | -}; | |
55 | - | |
56 | -typedef void (*TODO_CALLBACK)( void *self, __u32 param); | |
57 | - | |
58 | -/* | |
59 | - * Same as irmanager_event but this one can be queued and inclueds some | |
60 | - * addtional information | |
61 | - */ | |
62 | -struct irda_event { | |
63 | - irda_queue_t q; /* Must be first */ | |
64 | - | |
65 | - struct irmanager_event event; | |
66 | -}; | |
67 | - | |
68 | -/* | |
69 | - * Funtions with needs to be called with a process context | |
70 | - */ | |
71 | -struct irda_todo { | |
72 | - irda_queue_t q; /* Must be first */ | |
73 | - | |
74 | - void *self; | |
75 | - TODO_CALLBACK callback; | |
76 | - __u32 param; | |
77 | -}; | |
78 | - | |
79 | -/* | |
80 | - * Main structure for the IrDA device (not much here :-) | |
81 | - */ | |
82 | -struct irda_cb { | |
83 | - struct miscdevice dev; | |
84 | - wait_queue_head_t wait_queue; | |
85 | - | |
86 | - int in_use; | |
87 | - | |
88 | - irda_queue_t *event_queue; /* Events queued for the irmanager */ | |
89 | - irda_queue_t *todo_queue; /* Todo list */ | |
90 | -}; | |
91 | - | |
92 | -int irmod_init_module(void); | |
93 | -void irmod_cleanup_module(void); | |
94 | - | |
95 | -/* | |
96 | - * Function irda_lock (lock) | |
97 | - * | |
98 | - * Lock variable. Returns false if the lock is already set. | |
99 | - * | |
100 | - */ | |
101 | -static inline int irda_lock(int *lock) | |
102 | -{ | |
103 | - if (test_and_set_bit( 0, (void *) lock)) { | |
104 | - IRDA_DEBUG(3, __FUNCTION__ | |
105 | - "(), Trying to lock, already locked variable!\n"); | |
106 | - return FALSE; | |
107 | - } | |
108 | - return TRUE; | |
109 | -} | |
110 | - | |
111 | -inline int irda_unlock(int *lock); | |
112 | +/* Locking wrapper - Note the inverted logic on irda_lock(). | |
113 | + * Those function basically return false if the lock is already in the | |
114 | + * position you want to set it. - Jean II */ | |
115 | +#define irda_lock(lock) (! test_and_set_bit(0, (void *) (lock))) | |
116 | +#define irda_unlock(lock) (test_and_clear_bit(0, (void *) (lock))) | |
117 | ||
118 | +/* Zero the notify structure */ | |
119 | void irda_notify_init(notify_t *notify); | |
120 | - | |
121 | -void irda_execute_as_process(void *self, TODO_CALLBACK callback, __u32 param); | |
122 | -void irmanager_notify(struct irmanager_event *event); | |
123 | - | |
124 | -extern void irda_proc_modcount(struct inode *, int); | |
125 | -void irda_mod_inc_use_count(void); | |
126 | -void irda_mod_dec_use_count(void); | |
127 | ||
128 | #endif /* IRMOD_H */ | |
129 | ||
130 | diff -u -p linux/net/irda/irsyms.d2.c linux/net/irda/irsyms.c | |
131 | --- linux/net/irda/irsyms.d2.c Wed Nov 7 13:16:00 2001 | |
132 | +++ linux/net/irda/irsyms.c Wed Nov 7 13:42:19 2001 | |
133 | @@ -10,6 +10,7 @@ | |
134 | * Modified by: Dag Brattli <dagb@cs.uit.no> | |
135 | * | |
136 | * Copyright (c) 1997, 1999-2000 Dag Brattli, All Rights Reserved. | |
137 | + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com> | |
138 | * | |
139 | * This program is free software; you can redistribute it and/or | |
140 | * modify it under the terms of the GNU General Public License as | |
141 | @@ -79,7 +80,6 @@ EXPORT_SYMBOL(irttp_dup); | |
142 | EXPORT_SYMBOL(irda_debug); | |
143 | #endif | |
144 | EXPORT_SYMBOL(irda_notify_init); | |
145 | -EXPORT_SYMBOL(irda_lock); | |
146 | #ifdef CONFIG_PROC_FS | |
147 | EXPORT_SYMBOL(proc_irda); | |
148 | #endif | |
149 | @@ -217,21 +217,6 @@ static void __exit irda_cleanup(void) | |
150 | ||
151 | /* Remove middle layer */ | |
152 | irlmp_cleanup(); | |
153 | -} | |
154 | - | |
155 | -/* | |
156 | - * Function irda_unlock (lock) | |
157 | - * | |
158 | - * Unlock variable. Returns false if lock is already unlocked | |
159 | - * | |
160 | - */ | |
161 | -inline int irda_unlock(int *lock) | |
162 | -{ | |
163 | - if (!test_and_clear_bit(0, (void *) lock)) { | |
164 | - printk("Trying to unlock already unlocked variable!\n"); | |
165 | - return FALSE; | |
166 | - } | |
167 | - return TRUE; | |
168 | } | |
169 | ||
170 | /* | |
171 | diff -u -p linux/net/irda/irttp.d2.c linux/net/irda/irttp.c | |
172 | --- linux/net/irda/irttp.d2.c Tue Oct 30 18:14:58 2001 | |
173 | +++ linux/net/irda/irttp.c Wed Nov 7 13:33:09 2001 | |
174 | @@ -11,6 +11,7 @@ | |
175 | * | |
176 | * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, | |
177 | * All Rights Reserved. | |
178 | + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com> | |
179 | * | |
180 | * This program is free software; you can redistribute it and/or | |
181 | * modify it under the terms of the GNU General Public License as | |
182 | @@ -223,6 +224,11 @@ static void __irttp_close_tsap(struct ts | |
183 | ||
184 | del_timer(&self->todo_timer); | |
185 | ||
186 | + /* This one won't be cleaned up if we are diconnect_pend + close_pend | |
187 | + * and we receive a disconnect_indication */ | |
188 | + if (self->disconnect_skb) | |
189 | + dev_kfree_skb(self->disconnect_skb); | |
190 | + | |
191 | self->connected = FALSE; | |
192 | self->magic = ~TTP_TSAP_MAGIC; | |
193 | ||
194 | @@ -235,6 +241,9 @@ static void __irttp_close_tsap(struct ts | |
195 | * Remove TSAP from list of all TSAPs and then deallocate all resources | |
196 | * associated with this TSAP | |
197 | * | |
198 | + * Note : because we *free* the tsap structure, it is the responsability | |
199 | + * of the caller to make sure we are called only once and to deal with | |
200 | + * possible race conditions. - Jean II | |
201 | */ | |
202 | int irttp_close_tsap(struct tsap_cb *self) | |
203 | { | |
204 | @@ -248,8 +257,8 @@ int irttp_close_tsap(struct tsap_cb *sel | |
205 | /* Make sure tsap has been disconnected */ | |
206 | if (self->connected) { | |
207 | /* Check if disconnect is not pending */ | |
208 | - if (!self->disconnect_pend) { | |
209 | - IRDA_DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n"); | |
210 | + if (!test_bit(0, &self->disconnect_pend)) { | |
211 | + WARNING(__FUNCTION__ "(), TSAP still connected!\n"); | |
212 | irttp_disconnect_request(self, NULL, P_NORMAL); | |
213 | } | |
214 | self->close_pend = TRUE; | |
215 | @@ -407,6 +416,7 @@ static void irttp_run_tx_queue(struct ts | |
216 | unsigned long flags; | |
217 | int n; | |
218 | ||
219 | + /* Get exclusive access to the tx queue, otherwise don't touch it */ | |
220 | if (irda_lock(&self->tx_queue_lock) == FALSE) | |
221 | return; | |
222 | ||
223 | @@ -473,27 +483,17 @@ static void irttp_run_tx_queue(struct ts | |
224 | * close the socket, we are dead ! | |
225 | * Jean II */ | |
226 | if (skb->sk != NULL) { | |
227 | - struct sk_buff *tx_skb; | |
228 | - | |
229 | /* IrSOCK application, IrOBEX, ... */ | |
230 | IRDA_DEBUG(4, __FUNCTION__ "() : Detaching SKB from socket.\n"); | |
231 | - /* Note : still looking for a more efficient way | |
232 | - * to do that - Jean II */ | |
233 | ||
234 | - /* Get another skb on the same buffer, but without | |
235 | - * a reference to the socket (skb->sk = NULL) */ | |
236 | - tx_skb = skb_clone(skb, GFP_ATOMIC); | |
237 | - if (tx_skb != NULL) { | |
238 | - /* Release the skb associated with the | |
239 | - * socket, and use the new skb insted */ | |
240 | - kfree_skb(skb); | |
241 | - skb = tx_skb; | |
242 | - } | |
243 | + /* That's the right way to do it - Jean II */ | |
244 | + skb_orphan(skb); | |
245 | } else { | |
246 | /* IrCOMM over IrTTP, IrLAN, ... */ | |
247 | IRDA_DEBUG(4, __FUNCTION__ "() : Got SKB not attached to a socket.\n"); | |
248 | } | |
249 | ||
250 | + /* Pass the skb to IrLMP - done */ | |
251 | irlmp_data_request(self->lsap, skb); | |
252 | self->stats.tx_packets++; | |
253 | ||
254 | @@ -1105,18 +1105,23 @@ int irttp_disconnect_request(struct tsap | |
255 | /* Already disconnected? */ | |
256 | if (!self->connected) { | |
257 | IRDA_DEBUG(4, __FUNCTION__ "(), already disconnected!\n"); | |
258 | + if (userdata) | |
259 | + dev_kfree_skb(userdata); | |
260 | return -1; | |
261 | } | |
262 | ||
263 | - /* Disconnect already pending? */ | |
264 | - if (self->disconnect_pend) { | |
265 | - IRDA_DEBUG(1, __FUNCTION__ "(), disconnect already pending\n"); | |
266 | - if (userdata) { | |
267 | + /* Disconnect already pending ? | |
268 | + * We need to use an atomic operation to prevent reentry. This | |
269 | + * function may be called from various context, like user, timer | |
270 | + * for following a disconnect_indication() (i.e. net_bh). | |
271 | + * Jean II */ | |
272 | + if(test_and_set_bit(0, &self->disconnect_pend)) { | |
273 | + IRDA_DEBUG(0, __FUNCTION__ "(), disconnect already pending\n"); | |
274 | + if (userdata) | |
275 | dev_kfree_skb(userdata); | |
276 | - } | |
277 | ||
278 | /* Try to make some progress */ | |
279 | - irttp_run_rx_queue(self); | |
280 | + irttp_run_tx_queue(self); | |
281 | return -1; | |
282 | } | |
283 | ||
284 | @@ -1125,25 +1130,20 @@ int irttp_disconnect_request(struct tsap | |
285 | */ | |
286 | if (skb_queue_len(&self->tx_queue) > 0) { | |
287 | if (priority == P_HIGH) { | |
288 | - IRDA_DEBUG(1, __FUNCTION__ "High priority!!()\n" ); | |
289 | - | |
290 | /* | |
291 | * No need to send the queued data, if we are | |
292 | * disconnecting right now since the data will | |
293 | * not have any usable connection to be sent on | |
294 | */ | |
295 | + IRDA_DEBUG(1, __FUNCTION__ "High priority!!()\n" ); | |
296 | irttp_flush_queues(self); | |
297 | } else if (priority == P_NORMAL) { | |
298 | /* | |
299 | - * Must delay disconnect til after all data segments | |
300 | - * have been sent an the tx_queue is empty | |
301 | + * Must delay disconnect until after all data segments | |
302 | + * have been sent and the tx_queue is empty | |
303 | */ | |
304 | - if (userdata) | |
305 | - self->disconnect_skb = userdata; | |
306 | - else | |
307 | - self->disconnect_skb = NULL; | |
308 | - | |
309 | - self->disconnect_pend = TRUE; | |
310 | + /* We'll reuse this one later for the disconnect */ | |
311 | + self->disconnect_skb = userdata; /* May be NULL */ | |
312 | ||
313 | irttp_run_tx_queue(self); | |
314 | ||
315 | @@ -1152,9 +1152,8 @@ int irttp_disconnect_request(struct tsap | |
316 | } | |
317 | } | |
318 | IRDA_DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n"); | |
319 | - | |
320 | self->connected = FALSE; | |
321 | - | |
322 | + | |
323 | if (!userdata) { | |
324 | skb = dev_alloc_skb(64); | |
325 | if (!skb) | |
326 | @@ -1169,6 +1168,9 @@ int irttp_disconnect_request(struct tsap | |
327 | } | |
328 | ret = irlmp_disconnect_request(self->lsap, userdata); | |
329 | ||
330 | + /* The disconnect is no longer pending */ | |
331 | + clear_bit(0, &self->disconnect_pend); /* FALSE */ | |
332 | + | |
333 | return ret; | |
334 | } | |
335 | ||
336 | @@ -1190,19 +1192,27 @@ void irttp_disconnect_indication(void *i | |
337 | ASSERT(self != NULL, return;); | |
338 | ASSERT(self->magic == TTP_TSAP_MAGIC, return;); | |
339 | ||
340 | + /* Prevent higher layer to send more data */ | |
341 | self->connected = FALSE; | |
342 | ||
343 | /* Check if client has already tried to close the TSAP */ | |
344 | if (self->close_pend) { | |
345 | + /* In this case, the higher layer is probably gone. Don't | |
346 | + * bother it and clean up the remains - Jean II */ | |
347 | + if (skb) | |
348 | + dev_kfree_skb(skb); | |
349 | irttp_close_tsap(self); | |
350 | return; | |
351 | } | |
352 | ||
353 | + /* If we are here, we assume that is the higher layer is still | |
354 | + * waiting for the disconnect notification and able to process it, | |
355 | + * even if he tried to disconnect. Otherwise, it would have already | |
356 | + * attempted to close the tsap and self->close_pend would be TRUE. | |
357 | + * Jean II */ | |
358 | + | |
359 | /* No need to notify the client if has already tried to disconnect */ | |
360 | - if (self->disconnect_pend) | |
361 | - return; | |
362 | - | |
363 | - if (self->notify.disconnect_indication) | |
364 | + if(self->notify.disconnect_indication) | |
365 | self->notify.disconnect_indication(self->notify.instance, self, | |
366 | reason, skb); | |
367 | else | |
368 | @@ -1222,7 +1232,7 @@ void irttp_do_data_indication(struct tsa | |
369 | int err; | |
370 | ||
371 | /* Check if client has already tried to close the TSAP */ | |
372 | - if (self->close_pend || self->disconnect_pend) { | |
373 | + if (self->close_pend) { | |
374 | dev_kfree_skb(skb); | |
375 | return; | |
376 | } | |
377 | @@ -1263,6 +1273,7 @@ void irttp_run_rx_queue(struct tsap_cb * | |
378 | IRDA_DEBUG(2, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", | |
379 | self->send_credit, self->avail_credit, self->remote_credit); | |
380 | ||
381 | + /* Get exclusive access to the rx queue, otherwise don't touch it */ | |
382 | if (irda_lock(&self->rx_queue_lock) == FALSE) | |
383 | return; | |
384 | ||
385 | @@ -1500,7 +1511,7 @@ static int irttp_param_max_sdu_size(void | |
386 | else | |
387 | self->tx_max_sdu_size = param->pv.i; | |
388 | ||
389 | - IRDA_DEBUG(0, __FUNCTION__ "(), MaxSduSize=%d\n", param->pv.i); | |
390 | + IRDA_DEBUG(1, __FUNCTION__ "(), MaxSduSize=%d\n", param->pv.i); | |
391 | ||
392 | return 0; | |
393 | } | |
394 | @@ -1530,18 +1541,16 @@ static void irttp_todo_expired(unsigned | |
395 | } | |
396 | ||
397 | /* Check if time for disconnect */ | |
398 | - if (self->disconnect_pend) { | |
399 | + if (test_bit(0, &self->disconnect_pend)) { | |
400 | /* Check if it's possible to disconnect yet */ | |
401 | if (skb_queue_empty(&self->tx_queue)) { | |
402 | - | |
403 | /* Make sure disconnect is not pending anymore */ | |
404 | - self->disconnect_pend = FALSE; | |
405 | - if (self->disconnect_skb) { | |
406 | - irttp_disconnect_request( | |
407 | - self, self->disconnect_skb, P_NORMAL); | |
408 | - self->disconnect_skb = NULL; | |
409 | - } else | |
410 | - irttp_disconnect_request(self, NULL, P_NORMAL); | |
411 | + clear_bit(0, &self->disconnect_pend); /* FALSE */ | |
412 | + | |
413 | + /* Note : self->disconnect_skb may be NULL */ | |
414 | + irttp_disconnect_request(self, self->disconnect_skb, | |
415 | + P_NORMAL); | |
416 | + self->disconnect_skb = NULL; | |
417 | } else { | |
418 | /* Try again later */ | |
419 | irttp_start_todo_timer(self, 1*HZ); | |
420 | diff -u -p linux/net/irda/af_irda.d2.c linux/net/irda/af_irda.c | |
421 | --- linux/net/irda/af_irda.d2.c Fri Nov 2 11:09:12 2001 | |
422 | +++ linux/net/irda/af_irda.c Mon Nov 5 18:40:11 2001 | |
423 | @@ -11,7 +11,7 @@ | |
424 | * Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc. | |
425 | * | |
426 | * Copyright (c) 1999 Dag Brattli <dagb@cs.uit.no> | |
427 | - * Copyright (c) 1999 Jean Tourrilhes <jt@hpl.hp.com> | |
428 | + * Copyright (c) 1999-2001 Jean Tourrilhes <jt@hpl.hp.com> | |
429 | * All Rights Reserved. | |
430 | * | |
431 | * This program is free software; you can redistribute it and/or | |
432 | @@ -134,33 +134,41 @@ static void irda_disconnect_indication(v | |
433 | ||
434 | IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self); | |
435 | ||
436 | + /* Don't care about it, but let's not leak it */ | |
437 | + if(skb) | |
438 | + dev_kfree_skb(skb); | |
439 | + | |
440 | sk = self->sk; | |
441 | if (sk == NULL) | |
442 | return; | |
443 | ||
444 | - sk->state = TCP_CLOSE; | |
445 | - sk->err = ECONNRESET; | |
446 | - sk->shutdown |= SEND_SHUTDOWN; | |
447 | - if (!sk->dead) { | |
448 | + /* Prevent race conditions with irda_release() and irda_shutdown() */ | |
449 | + if ((!sk->dead) && (sk->state != TCP_CLOSE)) { | |
450 | + sk->state = TCP_CLOSE; | |
451 | + sk->err = ECONNRESET; | |
452 | + sk->shutdown |= SEND_SHUTDOWN; | |
453 | + | |
454 | sk->state_change(sk); | |
455 | - sk->dead = 1; | |
456 | - } | |
457 | + sk->dead = 1; /* Uh-oh... Should use sock_orphan ? */ | |
458 | ||
459 | - /* Close our TSAP. | |
460 | - * If we leave it open, IrLMP put it back into the list of | |
461 | - * unconnected LSAPs. The problem is that any incoming request | |
462 | - * can then be matched to this socket (and it will be, because | |
463 | - * it is at the head of the list). This would prevent any | |
464 | - * listening socket waiting on the same TSAP to get those requests. | |
465 | - * Some apps forget to close sockets, or hang to it a bit too long, | |
466 | - * so we may stay in this dead state long enough to be noticed... | |
467 | - * Note : all socket function do check sk->state, so we are safe... | |
468 | - * Jean II | |
469 | - */ | |
470 | - if (self->tsap) { | |
471 | - irttp_close_tsap(self->tsap); | |
472 | - self->tsap = NULL; | |
473 | - } | |
474 | + /* Close our TSAP. | |
475 | + * If we leave it open, IrLMP put it back into the list of | |
476 | + * unconnected LSAPs. The problem is that any incoming request | |
477 | + * can then be matched to this socket (and it will be, because | |
478 | + * it is at the head of the list). This would prevent any | |
479 | + * listening socket waiting on the same TSAP to get those | |
480 | + * requests. Some apps forget to close sockets, or hang to it | |
481 | + * a bit too long, so we may stay in this dead state long | |
482 | + * enough to be noticed... | |
483 | + * Note : all socket function do check sk->state, so we are | |
484 | + * safe... | |
485 | + * Jean II | |
486 | + */ | |
487 | + if (self->tsap) { | |
488 | + irttp_close_tsap(self->tsap); | |
489 | + self->tsap = NULL; | |
490 | + } | |
491 | + } | |
492 | ||
493 | /* Note : once we are there, there is not much you want to do | |
494 | * with the socket anymore, apart from closing it. | |
495 | @@ -222,7 +230,8 @@ static void irda_connect_confirm(void *i | |
496 | self->max_data_size); | |
497 | ||
498 | memcpy(&self->qos_tx, qos, sizeof(struct qos_info)); | |
499 | - kfree_skb(skb); | |
500 | + dev_kfree_skb(skb); | |
501 | + // Should be ??? skb_queue_tail(&sk->receive_queue, skb); | |
502 | ||
503 | /* We are now connected! */ | |
504 | sk->state = TCP_ESTABLISHED; | |
505 | @@ -1205,7 +1214,7 @@ static int irda_release(struct socket *s | |
506 | sk->protinfo.irda = NULL; | |
507 | ||
508 | sock_orphan(sk); | |
509 | - sock->sk = NULL; | |
510 | + sock->sk = NULL; | |
511 | ||
512 | /* Purge queues (see sock_init_data()) */ | |
513 | skb_queue_purge(&sk->receive_queue); | |
514 | diff -u -p linux/net/irda/iriap.d2.c linux/net/irda/iriap.c | |
515 | --- linux/net/irda/iriap.d2.c Fri Nov 2 11:14:13 2001 | |
516 | +++ linux/net/irda/iriap.c Mon Nov 5 18:41:12 2001 | |
517 | @@ -11,6 +11,7 @@ | |
518 | * | |
519 | * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, | |
520 | * All Rights Reserved. | |
521 | + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com> | |
522 | * | |
523 | * This program is free software; you can redistribute it and/or | |
524 | * modify it under the terms of the GNU General Public License as | |
525 | @@ -773,7 +774,7 @@ static void iriap_connect_indication(voi | |
526 | { | |
527 | struct iriap_cb *self, *new; | |
528 | ||
529 | - IRDA_DEBUG(0, __FUNCTION__ "()\n"); | |
530 | + IRDA_DEBUG(1, __FUNCTION__ "()\n"); | |
531 | ||
532 | self = (struct iriap_cb *) instance; | |
533 | ||
534 | diff -u -p linux/net/irda/irnet/irnet.d2.h linux/net/irda/irnet/irnet.h | |
535 | --- linux/net/irda/irnet/irnet.d2.h Wed Oct 31 16:09:19 2001 | |
536 | +++ linux/net/irda/irnet/irnet.h Wed Nov 7 14:02:34 2001 | |
537 | @@ -126,17 +126,17 @@ | |
538 | * History : | |
539 | * ------- | |
540 | * | |
541 | - * v1 - 15/5/00 - Jean II | |
542 | + * v1 - 15.5.00 - Jean II | |
543 | * o Basic IrNET (hook to ppp_generic & IrTTP - incl. multipoint) | |
544 | * o control channel on /dev/irnet (set name/address) | |
545 | * o event channel on /dev/irnet (for user space daemon) | |
546 | * | |
547 | - * v2 - 5/6/00 - Jean II | |
548 | + * v2 - 5.6.00 - Jean II | |
549 | * o Enable DROP_NOT_READY to avoid PPP timeouts & other weirdness... | |
550 | * o Add DISCONNECT_TO event and rename DISCONNECT_FROM. | |
551 | * o Set official device number alloaction on /dev/irnet | |
552 | * | |
553 | - * v3 - 30/8/00 - Jean II | |
554 | + * v3 - 30.8.00 - Jean II | |
555 | * o Update to latest Linux-IrDA changes : | |
556 | * - queue_t => irda_queue_t | |
557 | * o Update to ppp-2.4.0 : | |
558 | @@ -148,17 +148,17 @@ | |
559 | * another multilink bug (darn !) | |
560 | * o Remove LINKNAME_IOCTL cruft | |
561 | * | |
562 | - * v3b - 31/8/00 - Jean II | |
563 | + * v3b - 31.8.00 - Jean II | |
564 | * o Dump discovery log at event channel startup | |
565 | * | |
566 | - * v4 - 28/9/00 - Jean II | |
567 | + * v4 - 28.9.00 - Jean II | |
568 | * o Fix interaction between poll/select and dump discovery log | |
569 | * o Add IRNET_BLOCKED_LINK event (depend on new IrDA-Linux patch) | |
570 | * o Add IRNET_NOANSWER_FROM event (mostly to help support) | |
571 | * o Release flow control in disconnect_indication | |
572 | * o Block packets while connecting (speed up connections) | |
573 | * | |
574 | - * v5 - 11/01/01 - Jean II | |
575 | + * v5 - 11.01.01 - Jean II | |
576 | * o Init self->max_header_size, just in case... | |
577 | * o Set up ap->chan.hdrlen, to get zero copy on tx side working. | |
578 | * o avoid tx->ttp->flow->ppp->tx->... loop, by checking flow state | |
579 | @@ -169,7 +169,7 @@ | |
580 | * o Declare hashbin HB_NOLOCK instead of HB_LOCAL to avoid | |
581 | * disabling and enabling irq twice | |
582 | * | |
583 | - * v6 - 31/05/01 - Jean II | |
584 | + * v6 - 31.05.01 - Jean II | |
585 | * o Print source address in Found, Discovery, Expiry & Request events | |
586 | * o Print requested source address in /proc/net/irnet | |
587 | * o Change control channel input. Allow multiple commands in one line. | |
588 | @@ -186,12 +186,19 @@ | |
589 | * o Add ttp_connect flag to prevent rentry on the connect procedure | |
590 | * o Test and fixups to eliminate side effects of retries | |
591 | * | |
592 | - * v7 - 22/08/01 - Jean II | |
593 | + * v7 - 22.08.01 - Jean II | |
594 | * o Cleanup : Change "saddr = 0x0" to "saddr = DEV_ADDR_ANY" | |
595 | * o Fix bug in BLOCK_WHEN_CONNECT introduced in v6 : due to the | |
596 | * asynchronous IAS query, self->tsap is NULL when PPP send the | |
597 | * first packet. This was preventing "connect-delay 0" to work. | |
598 | * Change the test in ppp_irnet_send() to self->ttp_connect. | |
599 | + * | |
600 | + * v8 - 1.11.01 - Jean II | |
601 | + * o Tighten the use of self->ttp_connect and self->ttp_open to | |
602 | + * prevent various race conditions. | |
603 | + * o Avoid leaking discovery log and skb | |
604 | + * o Replace "self" with "server" in irnet_connect_indication() to | |
605 | + * better detect cut'n'paste error ;-) | |
606 | */ | |
607 | ||
608 | /***************************** INCLUDES *****************************/ | |
609 | @@ -204,6 +211,7 @@ | |
610 | #include <linux/proc_fs.h> | |
611 | #include <linux/devfs_fs_kernel.h> | |
612 | #include <linux/netdevice.h> | |
613 | +#include <linux/miscdevice.h> | |
614 | #include <linux/poll.h> | |
615 | #include <linux/config.h> | |
616 | #include <linux/ctype.h> /* isspace() */ | |
617 | diff -u -p linux/net/irda/irnet/irnet_irda.d2.c linux/net/irda/irnet/irnet_irda.c | |
618 | --- linux/net/irda/irnet/irnet_irda.d2.c Wed Oct 31 16:00:53 2001 | |
619 | +++ linux/net/irda/irnet/irnet_irda.c Wed Nov 7 10:48:58 2001 | |
620 | @@ -272,7 +272,7 @@ irnet_connect_tsap(irnet_socket * self) | |
621 | err = irnet_open_tsap(self); | |
622 | if(err != 0) | |
623 | { | |
624 | - self->ttp_connect = 0; | |
625 | + clear_bit(0, &self->ttp_connect); | |
626 | DERROR(IRDA_SR_ERROR, "connect aborted!\n"); | |
627 | return(err); | |
628 | } | |
629 | @@ -283,7 +283,7 @@ irnet_connect_tsap(irnet_socket * self) | |
630 | self->max_sdu_size_rx, NULL); | |
631 | if(err != 0) | |
632 | { | |
633 | - self->ttp_connect = 0; | |
634 | + clear_bit(0, &self->ttp_connect); | |
635 | DERROR(IRDA_SR_ERROR, "connect aborted!\n"); | |
636 | return(err); | |
637 | } | |
638 | @@ -377,7 +377,7 @@ irnet_discover_daddr_and_lsap_sel(irnet_ | |
639 | if(self->discoveries == NULL) | |
640 | { | |
641 | self->disco_number = -1; | |
642 | - self->ttp_connect = 0; | |
643 | + clear_bit(0, &self->ttp_connect); | |
644 | DRETURN(-ENETUNREACH, IRDA_SR_INFO, "No Cachelog...\n"); | |
645 | } | |
646 | DEBUG(IRDA_SR_INFO, "Got the log (0x%X), size is %d\n", | |
647 | @@ -399,7 +399,7 @@ irnet_discover_daddr_and_lsap_sel(irnet_ | |
648 | kfree(self->discoveries); | |
649 | self->discoveries = NULL; | |
650 | ||
651 | - self->ttp_connect = 0; | |
652 | + clear_bit(0, &self->ttp_connect); | |
653 | DRETURN(-ENETUNREACH, IRDA_SR_INFO, "Cachelog empty...\n"); | |
654 | } | |
655 | ||
656 | @@ -518,12 +518,12 @@ irda_irnet_connect(irnet_socket * self) | |
657 | ||
658 | DENTER(IRDA_SOCK_TRACE, "(self=0x%X)\n", (unsigned int) self); | |
659 | ||
660 | - /* Check if we have opened a local TSAP : | |
661 | - * If we have already opened a TSAP, it means that either we are already | |
662 | - * connected or in the process of doing so... */ | |
663 | - if(self->ttp_connect) | |
664 | + /* Check if we are already trying to connect. | |
665 | + * Because irda_irnet_connect() can be called directly by pppd plus | |
666 | + * packet retries in ppp_generic and connect may take time, plus we may | |
667 | + * race with irnet_connect_indication(), we need to be careful there... */ | |
668 | + if(test_and_set_bit(0, &self->ttp_connect)) | |
669 | DRETURN(-EBUSY, IRDA_SOCK_INFO, "Already connecting...\n"); | |
670 | - self->ttp_connect = 1; | |
671 | if((self->iriap != NULL) || (self->tsap != NULL)) | |
672 | DERROR(IRDA_SOCK_ERROR, "Socket not cleaned up...\n"); | |
673 | ||
674 | @@ -579,6 +579,7 @@ irda_irnet_connect(irnet_socket * self) | |
675 | * | |
676 | * Destroy irnet instance | |
677 | * | |
678 | + * Note : this need to be called from a process context. | |
679 | */ | |
680 | void | |
681 | irda_irnet_destroy(irnet_socket * self) | |
682 | @@ -601,6 +602,23 @@ irda_irnet_destroy(irnet_socket * self) | |
683 | DASSERT(entry == self, , IRDA_SOCK_ERROR, "Can't remove from hash.\n"); | |
684 | } | |
685 | ||
686 | + /* If we were connected, post a message */ | |
687 | + if(test_bit(0, &self->ttp_open)) | |
688 | + { | |
689 | + /* Note : as the disconnect comes from ppp_generic, the unit number | |
690 | + * doesn't exist anymore when we post the event, so we need to pass | |
691 | + * NULL as the first arg... */ | |
692 | + irnet_post_event(NULL, IRNET_DISCONNECT_TO, | |
693 | + self->saddr, self->daddr, self->rname); | |
694 | + } | |
695 | + | |
696 | + /* Prevent various IrDA callbacks from messing up things | |
697 | + * Need to be first */ | |
698 | + clear_bit(0, &self->ttp_connect); | |
699 | + | |
700 | + /* Prevent higher layer from accessing IrTTP */ | |
701 | + clear_bit(0, &self->ttp_open); | |
702 | + | |
703 | /* Unregister with IrLMP */ | |
704 | irlmp_unregister_client(self->ckey); | |
705 | ||
706 | @@ -611,19 +629,14 @@ irda_irnet_destroy(irnet_socket * self) | |
707 | self->iriap = NULL; | |
708 | } | |
709 | ||
710 | - /* If we were connected, post a message */ | |
711 | - if(self->ttp_open) | |
712 | + /* Cleanup eventual discoveries from connection attempt */ | |
713 | + if(self->discoveries != NULL) | |
714 | { | |
715 | - /* Note : as the disconnect comes from ppp_generic, the unit number | |
716 | - * doesn't exist anymore when we post the event, so we need to pass | |
717 | - * NULL as the first arg... */ | |
718 | - irnet_post_event(NULL, IRNET_DISCONNECT_TO, | |
719 | - self->saddr, self->daddr, self->rname); | |
720 | + /* Cleanup our copy of the discovery log */ | |
721 | + kfree(self->discoveries); | |
722 | + self->discoveries = NULL; | |
723 | } | |
724 | ||
725 | - /* Prevent higher layer from accessing IrTTP */ | |
726 | - self->ttp_open = 0; | |
727 | - | |
728 | /* Close our IrTTP connection */ | |
729 | if(self->tsap) | |
730 | { | |
731 | @@ -761,7 +774,7 @@ irnet_find_socket(irnet_socket * self) | |
732 | while(new !=(irnet_socket *) NULL) | |
733 | { | |
734 | /* Is it available ? */ | |
735 | - if(!(new->ttp_open) && (new->rdaddr == DEV_ADDR_ANY) && | |
736 | + if(!(test_bit(0, &new->ttp_open)) && (new->rdaddr == DEV_ADDR_ANY) && | |
737 | (new->rname[0] == '\0') && (new->ppp_open)) | |
738 | { | |
739 | /* Yes !!! Get it.. */ | |
740 | @@ -788,17 +801,17 @@ irnet_find_socket(irnet_socket * self) | |
741 | * | |
742 | */ | |
743 | static inline int | |
744 | -irnet_connect_socket(irnet_socket * self, | |
745 | +irnet_connect_socket(irnet_socket * server, | |
746 | irnet_socket * new, | |
747 | struct qos_info * qos, | |
748 | __u32 max_sdu_size, | |
749 | __u8 max_header_size) | |
750 | { | |
751 | - DENTER(IRDA_SERV_TRACE, "(self=0x%X, new=0x%X)\n", | |
752 | - (unsigned int) self, (unsigned int) new); | |
753 | + DENTER(IRDA_SERV_TRACE, "(server=0x%X, new=0x%X)\n", | |
754 | + (unsigned int) server, (unsigned int) new); | |
755 | ||
756 | /* Now attach up the new socket */ | |
757 | - new->tsap = irttp_dup(self->tsap, new); | |
758 | + new->tsap = irttp_dup(server->tsap, new); | |
759 | DABORT(new->tsap == NULL, -1, IRDA_SERV_ERROR, "dup failed!\n"); | |
760 | ||
761 | /* Set up all the relevant parameters on the new socket */ | |
762 | @@ -817,17 +830,32 @@ irnet_connect_socket(irnet_socket * self | |
763 | #endif /* STREAM_COMPAT */ | |
764 | ||
765 | /* Clean up the original one to keep it in listen state */ | |
766 | - self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY; | |
767 | - self->tsap->lsap->lsap_state = LSAP_DISCONNECTED; | |
768 | + server->tsap->dtsap_sel = server->tsap->lsap->dlsap_sel = LSAP_ANY; | |
769 | + server->tsap->lsap->lsap_state = LSAP_DISCONNECTED; | |
770 | ||
771 | /* Send a connection response on the new socket */ | |
772 | irttp_connect_response(new->tsap, new->max_sdu_size_rx, NULL); | |
773 | ||
774 | /* Allow PPP to send its junk over the new socket... */ | |
775 | - new->ttp_open = 1; | |
776 | - new->ttp_connect = 0; | |
777 | + set_bit(0, &new->ttp_open); | |
778 | + | |
779 | + /* Not connecting anymore, and clean up last possible remains | |
780 | + * of connection attempts on the socket */ | |
781 | + clear_bit(0, &new->ttp_connect); | |
782 | + if(new->iriap) | |
783 | + { | |
784 | + iriap_close(new->iriap); | |
785 | + new->iriap = NULL; | |
786 | + } | |
787 | + if(new->discoveries != NULL) | |
788 | + { | |
789 | + kfree(new->discoveries); | |
790 | + new->discoveries = NULL; | |
791 | + } | |
792 | + | |
793 | #ifdef CONNECT_INDIC_KICK | |
794 | - /* As currently we don't packets in ppp_irnet_send(), this is not needed... | |
795 | + /* As currently we don't block packets in ppp_irnet_send() while passive, | |
796 | + * this is not really needed... | |
797 | * Also, not doing it give IrDA a chance to finish the setup properly | |
798 | * before beeing swamped with packets... */ | |
799 | ppp_output_wakeup(&new->chan); | |
800 | @@ -835,7 +863,7 @@ irnet_connect_socket(irnet_socket * self | |
801 | ||
802 | /* Notify the control channel */ | |
803 | irnet_post_event(new, IRNET_CONNECT_FROM, | |
804 | - new->saddr, new->daddr, self->rname); | |
805 | + new->saddr, new->daddr, server->rname); | |
806 | ||
807 | DEXIT(IRDA_SERV_TRACE, "\n"); | |
808 | return 0; | |
809 | @@ -1053,12 +1081,33 @@ irnet_disconnect_indication(void * insta | |
810 | struct sk_buff *skb) | |
811 | { | |
812 | irnet_socket * self = (irnet_socket *) instance; | |
813 | + int test = 0; | |
814 | ||
815 | DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self); | |
816 | DASSERT(self != NULL, , IRDA_CB_ERROR, "Self is NULL !!!\n"); | |
817 | ||
818 | + /* Don't care about it, but let's not leak it */ | |
819 | + if(skb) | |
820 | + dev_kfree_skb(skb); | |
821 | + | |
822 | + /* Prevent higher layer from accessing IrTTP */ | |
823 | + test = test_and_clear_bit(0, &self->ttp_open); | |
824 | + /* Not connecting anymore... | |
825 | + * (note : TSAP is open, so IAP callbacks are no longer pending...) */ | |
826 | + test |= test_and_clear_bit(0, &self->ttp_connect); | |
827 | + | |
828 | + /* If both self->ttp_open and self->ttp_connect are NULL, it mean that we | |
829 | + * have a race condition with irda_irnet_destroy() or | |
830 | + * irnet_connect_indication(), so don't mess up tsap... | |
831 | + */ | |
832 | + if(!test) | |
833 | + { | |
834 | + DERROR(IRDA_CB_ERROR, "Race condition detected...\n"); | |
835 | + return; | |
836 | + } | |
837 | + | |
838 | /* If we were active, notify the control channel */ | |
839 | - if(self->ttp_open) | |
840 | + if(test_bit(0, &self->ttp_open)) | |
841 | irnet_post_event(self, IRNET_DISCONNECT_FROM, | |
842 | self->saddr, self->daddr, self->rname); | |
843 | else | |
844 | @@ -1067,15 +1116,10 @@ irnet_disconnect_indication(void * insta | |
845 | irnet_post_event(self, IRNET_NOANSWER_FROM, | |
846 | self->saddr, self->daddr, self->rname); | |
847 | ||
848 | - /* Prevent higher layer from accessing IrTTP */ | |
849 | - self->ttp_open = 0; | |
850 | - self->ttp_connect = 0; | |
851 | - | |
852 | - /* Close our IrTTP connection */ | |
853 | + /* Close our IrTTP connection, cleanup tsap */ | |
854 | if((self->tsap) && (self != &irnet_server.s)) | |
855 | { | |
856 | DEBUG(IRDA_CB_INFO, "Closing our TTP connection.\n"); | |
857 | - irttp_disconnect_request(self->tsap, NULL, P_NORMAL); | |
858 | irttp_close_tsap(self->tsap); | |
859 | self->tsap = NULL; | |
860 | ||
861 | @@ -1114,6 +1158,13 @@ irnet_connect_confirm(void * instance, | |
862 | ||
863 | DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self); | |
864 | ||
865 | + /* Check if socket is closing down (via irda_irnet_destroy()) */ | |
866 | + if(! test_bit(0, &self->ttp_connect)) | |
867 | + { | |
868 | + DERROR(IRDA_CB_ERROR, "Socket no longer connecting. Ouch !\n"); | |
869 | + return; | |
870 | + } | |
871 | + | |
872 | /* How much header space do we need to reserve */ | |
873 | self->max_header_size = max_header_size; | |
874 | ||
875 | @@ -1129,8 +1180,8 @@ irnet_connect_confirm(void * instance, | |
876 | self->saddr = irttp_get_saddr(self->tsap); | |
877 | ||
878 | /* Allow higher layer to access IrTTP */ | |
879 | - self->ttp_connect = 0; | |
880 | - self->ttp_open = 1; | |
881 | + set_bit(0, &self->ttp_open); | |
882 | + clear_bit(0, &self->ttp_connect); /* Not racy, IrDA traffic is serial */ | |
883 | /* Give a kick in the ass of ppp_generic so that he sends us some data */ | |
884 | ppp_output_wakeup(&self->chan); | |
885 | ||
886 | @@ -1251,56 +1302,76 @@ irnet_connect_indication(void * instanc | |
887 | __u8 max_header_size, | |
888 | struct sk_buff *skb) | |
889 | { | |
890 | - irnet_socket * self = &irnet_server.s; | |
891 | + irnet_socket * server = &irnet_server.s; | |
892 | irnet_socket * new = (irnet_socket *) NULL; | |
893 | ||
894 | - DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self); | |
895 | + DENTER(IRDA_TCB_TRACE, "(server=0x%X)\n", (unsigned int) server); | |
896 | DASSERT(instance == &irnet_server, , IRDA_CB_ERROR, | |
897 | "Invalid instance (0x%X) !!!\n", (unsigned int) instance); | |
898 | DASSERT(sap == irnet_server.s.tsap, , IRDA_CB_ERROR, "Invalid sap !!!\n"); | |
899 | ||
900 | /* Try to find the most appropriate IrNET socket */ | |
901 | - new = irnet_find_socket(self); | |
902 | + new = irnet_find_socket(server); | |
903 | ||
904 | /* After all this hard work, do we have an socket ? */ | |
905 | if(new == (irnet_socket *) NULL) | |
906 | { | |
907 | DEXIT(IRDA_CB_INFO, ": No socket waiting for this connection.\n"); | |
908 | - irnet_disconnect_server(self, skb); | |
909 | + irnet_disconnect_server(server, skb); | |
910 | return; | |
911 | } | |
912 | ||
913 | /* Is the socket already busy ? */ | |
914 | - if(new->ttp_open) | |
915 | + if(test_bit(0, &new->ttp_open)) | |
916 | { | |
917 | DEXIT(IRDA_CB_INFO, ": Socket already connected.\n"); | |
918 | - irnet_disconnect_server(self, skb); | |
919 | + irnet_disconnect_server(server, skb); | |
920 | return; | |
921 | } | |
922 | ||
923 | - /* Socket connecting */ | |
924 | - if(new->tsap != NULL) | |
925 | - { | |
926 | - /* The socket has sent a IrTTP connection request and is waiting for | |
927 | - * a connection response (that may never come). | |
928 | - * Now, the pain is that the socket has open a tsap and is waiting on it, | |
929 | - * while the other end is trying to connect to it on another tsap. | |
930 | - * Argh ! We will deal with that later... | |
931 | + /* Socket connecting ? | |
932 | + * Clear up flag : prevent irnet_disconnect_indication() to mess up tsap */ | |
933 | + if(test_and_clear_bit(0, &new->ttp_connect)) | |
934 | + { | |
935 | + /* The socket is trying to connect to the other end and may have sent | |
936 | + * a IrTTP connection request and is waiting for a connection response | |
937 | + * (that may never come). | |
938 | + * Now, the pain is that the socket may have opened a tsap and is | |
939 | + * waiting on it, while the other end is trying to connect to it on | |
940 | + * another tsap. | |
941 | */ | |
942 | DERROR(IRDA_CB_ERROR, "Socket already connecting. Ouch !\n"); | |
943 | #ifdef ALLOW_SIMULT_CONNECT | |
944 | - /* Close the connection the new socket was attempting. | |
945 | - * WARNING : This need more testing ! */ | |
946 | - irttp_close_tsap(new->tsap); | |
947 | + /* Cleanup the TSAP if necessary - IrIAP will be cleaned up later */ | |
948 | + if(new->tsap != NULL) | |
949 | + { | |
950 | + /* Close the connection the new socket was attempting. | |
951 | + * This seems to be safe... */ | |
952 | + irttp_close_tsap(new->tsap); | |
953 | + new->tsap = NULL; | |
954 | + } | |
955 | /* Note : no return, fall through... */ | |
956 | #else /* ALLOW_SIMULT_CONNECT */ | |
957 | - irnet_disconnect_server(self, skb); | |
958 | + irnet_disconnect_server(server, skb); | |
959 | return; | |
960 | #endif /* ALLOW_SIMULT_CONNECT */ | |
961 | } | |
962 | + else | |
963 | + /* If socket is not connecting or connected, tsap should be NULL */ | |
964 | + if(new->tsap != NULL) | |
965 | + { | |
966 | + /* If we are here, we are also in irnet_disconnect_indication(), | |
967 | + * and it's a nice race condition... On the other hand, we can't be | |
968 | + * in irda_irnet_destroy() otherwise we would not have found the | |
969 | + * socket in the hashbin. */ | |
970 | + /* Better get out of here, otherwise we will mess up tsaps ! */ | |
971 | + DERROR(IRDA_CB_ERROR, "Race condition detected, abort connect...\n"); | |
972 | + irnet_disconnect_server(server, skb); | |
973 | + return; | |
974 | + } | |
975 | ||
976 | /* So : at this point, we have a socket, and it is idle. Good ! */ | |
977 | - irnet_connect_socket(self, new, qos, max_sdu_size, max_header_size); | |
978 | + irnet_connect_socket(server, new, qos, max_sdu_size, max_header_size); | |
979 | ||
980 | /* Check size of received packet */ | |
981 | if(skb->len > 0) | |
982 | @@ -1349,24 +1420,25 @@ irnet_getvalue_confirm(int result, | |
983 | DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self); | |
984 | DASSERT(self != NULL, , IRDA_OCB_ERROR, "Self is NULL !!!\n"); | |
985 | ||
986 | - /* We probably don't need to make any more queries */ | |
987 | - iriap_close(self->iriap); | |
988 | - self->iriap = NULL; | |
989 | - | |
990 | - /* Check if already connected (via irnet_connect_socket()) */ | |
991 | - if(self->ttp_open) | |
992 | + /* Check if already connected (via irnet_connect_socket()) | |
993 | + * or socket is closing down (via irda_irnet_destroy()) */ | |
994 | + if(! test_bit(0, &self->ttp_connect)) | |
995 | { | |
996 | - DERROR(IRDA_OCB_ERROR, "Socket already connected. Ouch !\n"); | |
997 | + DERROR(IRDA_OCB_ERROR, "Socket no longer connecting. Ouch !\n"); | |
998 | return; | |
999 | } | |
1000 | ||
1001 | + /* We probably don't need to make any more queries */ | |
1002 | + iriap_close(self->iriap); | |
1003 | + self->iriap = NULL; | |
1004 | + | |
1005 | /* Post process the IAS reply */ | |
1006 | self->dtsap_sel = irnet_ias_to_tsap(self, result, value); | |
1007 | ||
1008 | /* If error, just go out */ | |
1009 | if(self->errno) | |
1010 | { | |
1011 | - self->ttp_connect = 0; | |
1012 | + clear_bit(0, &self->ttp_connect); | |
1013 | DERROR(IRDA_OCB_ERROR, "IAS connect failed ! (0x%X)\n", self->errno); | |
1014 | return; | |
1015 | } | |
1016 | @@ -1412,6 +1484,14 @@ irnet_discovervalue_confirm(int result, | |
1017 | DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self); | |
1018 | DASSERT(self != NULL, , IRDA_OCB_ERROR, "Self is NULL !!!\n"); | |
1019 | ||
1020 | + /* Check if already connected (via irnet_connect_socket()) | |
1021 | + * or socket is closing down (via irda_irnet_destroy()) */ | |
1022 | + if(! test_bit(0, &self->ttp_connect)) | |
1023 | + { | |
1024 | + DERROR(IRDA_OCB_ERROR, "Socket no longer connecting. Ouch !\n"); | |
1025 | + return; | |
1026 | + } | |
1027 | + | |
1028 | /* Post process the IAS reply */ | |
1029 | dtsap_sel = irnet_ias_to_tsap(self, result, value); | |
1030 | ||
1031 | @@ -1468,15 +1548,8 @@ irnet_discovervalue_confirm(int result, | |
1032 | if(self->daddr == DEV_ADDR_ANY) | |
1033 | { | |
1034 | self->daddr = DEV_ADDR_ANY; | |
1035 | - self->ttp_connect = 0; | |
1036 | + clear_bit(0, &self->ttp_connect); | |
1037 | DEXIT(IRDA_OCB_TRACE, ": cannot discover IrNET in any device !!!\n"); | |
1038 | - return; | |
1039 | - } | |
1040 | - | |
1041 | - /* Check if already connected (via irnet_connect_socket()) */ | |
1042 | - if(self->ttp_open) | |
1043 | - { | |
1044 | - DERROR(IRDA_OCB_ERROR, "Socket already connected. Ouch !\n"); | |
1045 | return; | |
1046 | } | |
1047 | ||
1048 | diff -u -p linux/net/irda/irnet/irnet_ppp.d2.c linux/net/irda/irnet/irnet_ppp.c | |
1049 | --- linux/net/irda/irnet/irnet_ppp.d2.c Thu Nov 1 12:14:43 2001 | |
1050 | +++ linux/net/irda/irnet/irnet_ppp.c Thu Nov 1 14:11:53 2001 | |
1051 | @@ -850,7 +850,7 @@ ppp_irnet_send(struct ppp_channel * chan | |
1052 | DASSERT(self != NULL, 0, PPP_ERROR, "Self is NULL !!!\n"); | |
1053 | ||
1054 | /* Check if we are connected */ | |
1055 | - if(self->ttp_open == 0) | |
1056 | + if(!(test_bit(0, &self->ttp_open))) | |
1057 | { | |
1058 | #ifdef CONNECT_IN_SEND | |
1059 | /* Let's try to connect one more time... */ | |
1060 | @@ -884,7 +884,7 @@ ppp_irnet_send(struct ppp_channel * chan | |
1061 | */ | |
1062 | #ifdef BLOCK_WHEN_CONNECT | |
1063 | /* If we are attempting to connect */ | |
1064 | - if(self->ttp_connect) | |
1065 | + if(test_bit(0, &self->ttp_connect)) | |
1066 | { | |
1067 | /* Blocking packet, ppp_generic will retry later */ | |
1068 | return 0; | |
1069 |