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
5 * Modified by: Dag Brattli <dagb@cs.uit.no>
7 * Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
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
16 -#include <linux/skbuff.h>
17 -#include <linux/miscdevice.h>
18 +#include <net/irda/irda.h> /* Notify stuff */
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 */
24 -#define IRMGR_IOC_MAGIC 'm'
25 -#define IRMGR_IOCTNPC _IO(IRMGR_IOC_MAGIC, 1)
26 -#define IRMGR_IOC_MAXNR 1
29 - * Events that we pass to the user space manager
32 - EVENT_DEVICE_DISCOVERED = 0,
33 - EVENT_REQUEST_MODULE,
36 - EVENT_IRLPT_START, /* Obsolete */
37 - EVENT_IRLPT_STOP, /* Obsolete */
38 - EVENT_IROBEX_START, /* Obsolete */
39 - EVENT_IROBEX_STOP, /* Obsolete */
41 - EVENT_NEED_PROCESS_CONTEXT,
45 - * Event information passed to the IrManager daemon process
47 -struct irmanager_event {
56 -typedef void (*TODO_CALLBACK)( void *self, __u32 param);
59 - * Same as irmanager_event but this one can be queued and inclueds some
60 - * addtional information
63 - irda_queue_t q; /* Must be first */
65 - struct irmanager_event event;
69 - * Funtions with needs to be called with a process context
72 - irda_queue_t q; /* Must be first */
75 - TODO_CALLBACK callback;
80 - * Main structure for the IrDA device (not much here :-)
83 - struct miscdevice dev;
84 - wait_queue_head_t wait_queue;
88 - irda_queue_t *event_queue; /* Events queued for the irmanager */
89 - irda_queue_t *todo_queue; /* Todo list */
92 -int irmod_init_module(void);
93 -void irmod_cleanup_module(void);
96 - * Function irda_lock (lock)
98 - * Lock variable. Returns false if the lock is already set.
101 -static inline int irda_lock(int *lock)
103 - if (test_and_set_bit( 0, (void *) lock)) {
104 - IRDA_DEBUG(3, __FUNCTION__
105 - "(), Trying to lock, already locked variable!\n");
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)))
118 +/* Zero the notify structure */
119 void irda_notify_init(notify_t *notify);
121 -void irda_execute_as_process(void *self, TODO_CALLBACK callback, __u32 param);
122 -void irmanager_notify(struct irmanager_event *event);
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);
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
134 * Modified by: Dag Brattli <dagb@cs.uit.no>
136 * Copyright (c) 1997, 1999-2000 Dag Brattli, All Rights Reserved.
137 + * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
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);
144 EXPORT_SYMBOL(irda_notify_init);
145 -EXPORT_SYMBOL(irda_lock);
146 #ifdef CONFIG_PROC_FS
147 EXPORT_SYMBOL(proc_irda);
149 @@ -217,21 +217,6 @@ static void __exit irda_cleanup(void)
151 /* Remove middle layer */
156 - * Function irda_unlock (lock)
158 - * Unlock variable. Returns false if lock is already unlocked
161 -inline int irda_unlock(int *lock)
163 - if (!test_and_clear_bit(0, (void *) lock)) {
164 - printk("Trying to unlock already unlocked variable!\n");
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
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>
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
184 del_timer(&self->todo_timer);
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);
191 self->connected = FALSE;
192 self->magic = ~TTP_TSAP_MAGIC;
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
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
202 int irttp_close_tsap(struct tsap_cb *self)
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);
214 self->close_pend = TRUE;
215 @@ -407,6 +416,7 @@ static void irttp_run_tx_queue(struct ts
219 + /* Get exclusive access to the tx queue, otherwise don't touch it */
220 if (irda_lock(&self->tx_queue_lock) == FALSE)
223 @@ -473,27 +483,17 @@ static void irttp_run_tx_queue(struct ts
224 * close the socket, we are dead !
226 if (skb->sk != NULL) {
227 - struct sk_buff *tx_skb;
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 */
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 */
243 + /* That's the right way to do it - Jean II */
246 /* IrCOMM over IrTTP, IrLAN, ... */
247 IRDA_DEBUG(4, __FUNCTION__ "() : Got SKB not attached to a socket.\n");
250 + /* Pass the skb to IrLMP - done */
251 irlmp_data_request(self->lsap, skb);
252 self->stats.tx_packets++;
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");
259 + dev_kfree_skb(userdata);
263 - /* Disconnect already pending? */
264 - if (self->disconnect_pend) {
265 - IRDA_DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
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).
272 + if(test_and_set_bit(0, &self->disconnect_pend)) {
273 + IRDA_DEBUG(0, __FUNCTION__ "(), disconnect already pending\n");
275 dev_kfree_skb(userdata);
278 /* Try to make some progress */
279 - irttp_run_rx_queue(self);
280 + irttp_run_tx_queue(self);
284 @@ -1125,25 +1130,20 @@ int irttp_disconnect_request(struct tsap
286 if (skb_queue_len(&self->tx_queue) > 0) {
287 if (priority == P_HIGH) {
288 - IRDA_DEBUG(1, __FUNCTION__ "High priority!!()\n" );
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
295 + IRDA_DEBUG(1, __FUNCTION__ "High priority!!()\n" );
296 irttp_flush_queues(self);
297 } else if (priority == P_NORMAL) {
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
305 - self->disconnect_skb = userdata;
307 - self->disconnect_skb = NULL;
309 - self->disconnect_pend = TRUE;
310 + /* We'll reuse this one later for the disconnect */
311 + self->disconnect_skb = userdata; /* May be NULL */
313 irttp_run_tx_queue(self);
315 @@ -1152,9 +1152,8 @@ int irttp_disconnect_request(struct tsap
318 IRDA_DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
320 self->connected = FALSE;
324 skb = dev_alloc_skb(64);
326 @@ -1169,6 +1168,9 @@ int irttp_disconnect_request(struct tsap
328 ret = irlmp_disconnect_request(self->lsap, userdata);
330 + /* The disconnect is no longer pending */
331 + clear_bit(0, &self->disconnect_pend); /* FALSE */
336 @@ -1190,19 +1192,27 @@ void irttp_disconnect_indication(void *i
337 ASSERT(self != NULL, return;);
338 ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
340 + /* Prevent higher layer to send more data */
341 self->connected = FALSE;
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 */
348 + dev_kfree_skb(skb);
349 irttp_close_tsap(self);
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.
359 /* No need to notify the client if has already tried to disconnect */
360 - if (self->disconnect_pend)
363 - if (self->notify.disconnect_indication)
364 + if(self->notify.disconnect_indication)
365 self->notify.disconnect_indication(self->notify.instance, self,
368 @@ -1222,7 +1232,7 @@ void irttp_do_data_indication(struct tsa
371 /* Check if client has already tried to close the TSAP */
372 - if (self->close_pend || self->disconnect_pend) {
373 + if (self->close_pend) {
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);
381 + /* Get exclusive access to the rx queue, otherwise don't touch it */
382 if (irda_lock(&self->rx_queue_lock) == FALSE)
385 @@ -1500,7 +1511,7 @@ static int irttp_param_max_sdu_size(void
387 self->tx_max_sdu_size = param->pv.i;
389 - IRDA_DEBUG(0, __FUNCTION__ "(), MaxSduSize=%d\n", param->pv.i);
390 + IRDA_DEBUG(1, __FUNCTION__ "(), MaxSduSize=%d\n", param->pv.i);
394 @@ -1530,18 +1541,16 @@ static void irttp_todo_expired(unsigned
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)) {
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;
410 - irttp_disconnect_request(self, NULL, P_NORMAL);
411 + clear_bit(0, &self->disconnect_pend); /* FALSE */
413 + /* Note : self->disconnect_skb may be NULL */
414 + irttp_disconnect_request(self, self->disconnect_skb,
416 + self->disconnect_skb = NULL;
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
424 * Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
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.
431 * This program is free software; you can redistribute it and/or
432 @@ -134,33 +134,41 @@ static void irda_disconnect_indication(v
434 IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self);
436 + /* Don't care about it, but let's not leak it */
438 + dev_kfree_skb(skb);
444 - sk->state = TCP_CLOSE;
445 - sk->err = ECONNRESET;
446 - sk->shutdown |= SEND_SHUTDOWN;
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;
454 sk->state_change(sk);
457 + sk->dead = 1; /* Uh-oh... Should use sock_orphan ? */
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...
471 - irttp_close_tsap(self->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
488 + irttp_close_tsap(self->tsap);
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);
498 memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
500 + dev_kfree_skb(skb);
501 + // Should be ??? skb_queue_tail(&sk->receive_queue, skb);
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;
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
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>
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
527 struct iriap_cb *self, *new;
529 - IRDA_DEBUG(0, __FUNCTION__ "()\n");
530 + IRDA_DEBUG(1, __FUNCTION__ "()\n");
532 self = (struct iriap_cb *) instance;
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 @@
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)
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
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
562 - * v3b - 31/8/00 - Jean II
563 + * v3b - 31.8.00 - Jean II
564 * o Dump discovery log at event channel startup
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)
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
580 * o Declare hashbin HB_NOLOCK instead of HB_LOCAL to avoid
581 * disabling and enabling irq twice
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
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.
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 ;-)
608 /***************************** INCLUDES *****************************/
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);
624 - self->ttp_connect = 0;
625 + clear_bit(0, &self->ttp_connect);
626 DERROR(IRDA_SR_ERROR, "connect aborted!\n");
629 @@ -283,7 +283,7 @@ irnet_connect_tsap(irnet_socket * self)
630 self->max_sdu_size_rx, NULL);
633 - self->ttp_connect = 0;
634 + clear_bit(0, &self->ttp_connect);
635 DERROR(IRDA_SR_ERROR, "connect aborted!\n");
638 @@ -377,7 +377,7 @@ irnet_discover_daddr_and_lsap_sel(irnet_
639 if(self->discoveries == NULL)
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");
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;
651 - self->ttp_connect = 0;
652 + clear_bit(0, &self->ttp_connect);
653 DRETURN(-ENETUNREACH, IRDA_SR_INFO, "Cachelog empty...\n");
656 @@ -518,12 +518,12 @@ irda_irnet_connect(irnet_socket * self)
658 DENTER(IRDA_SOCK_TRACE, "(self=0x%X)\n", (unsigned int) self);
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");
674 @@ -579,6 +579,7 @@ irda_irnet_connect(irnet_socket * self)
676 * Destroy irnet instance
678 + * Note : this need to be called from a process context.
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");
686 + /* If we were connected, post a message */
687 + if(test_bit(0, &self->ttp_open))
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);
696 + /* Prevent various IrDA callbacks from messing up things
697 + * Need to be first */
698 + clear_bit(0, &self->ttp_connect);
700 + /* Prevent higher layer from accessing IrTTP */
701 + clear_bit(0, &self->ttp_open);
703 /* Unregister with IrLMP */
704 irlmp_unregister_client(self->ckey);
706 @@ -611,19 +629,14 @@ irda_irnet_destroy(irnet_socket * self)
710 - /* If we were connected, post a message */
712 + /* Cleanup eventual discoveries from connection attempt */
713 + if(self->discoveries != NULL)
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;
725 - /* Prevent higher layer from accessing IrTTP */
726 - self->ttp_open = 0;
728 /* Close our IrTTP connection */
731 @@ -761,7 +774,7 @@ irnet_find_socket(irnet_socket * self)
732 while(new !=(irnet_socket *) NULL)
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))
739 /* Yes !!! Get it.. */
740 @@ -788,17 +801,17 @@ irnet_find_socket(irnet_socket * self)
744 -irnet_connect_socket(irnet_socket * self,
745 +irnet_connect_socket(irnet_socket * server,
747 struct qos_info * qos,
749 __u8 max_header_size)
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);
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");
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 */
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;
771 /* Send a connection response on the new socket */
772 irttp_connect_response(new->tsap, new->max_sdu_size_rx, NULL);
774 /* Allow PPP to send its junk over the new socket... */
776 - new->ttp_connect = 0;
777 + set_bit(0, &new->ttp_open);
779 + /* Not connecting anymore, and clean up last possible remains
780 + * of connection attempts on the socket */
781 + clear_bit(0, &new->ttp_connect);
784 + iriap_close(new->iriap);
787 + if(new->discoveries != NULL)
789 + kfree(new->discoveries);
790 + new->discoveries = NULL;
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
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);
807 DEXIT(IRDA_SERV_TRACE, "\n");
809 @@ -1053,12 +1081,33 @@ irnet_disconnect_indication(void * insta
812 irnet_socket * self = (irnet_socket *) instance;
815 DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
816 DASSERT(self != NULL, , IRDA_CB_ERROR, "Self is NULL !!!\n");
818 + /* Don't care about it, but let's not leak it */
820 + dev_kfree_skb(skb);
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);
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...
834 + DERROR(IRDA_CB_ERROR, "Race condition detected...\n");
838 /* If we were active, notify the control channel */
840 + if(test_bit(0, &self->ttp_open))
841 irnet_post_event(self, IRNET_DISCONNECT_FROM,
842 self->saddr, self->daddr, self->rname);
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);
848 - /* Prevent higher layer from accessing IrTTP */
849 - self->ttp_open = 0;
850 - self->ttp_connect = 0;
852 - /* Close our IrTTP connection */
853 + /* Close our IrTTP connection, cleanup tsap */
854 if((self->tsap) && (self != &irnet_server.s))
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);
861 @@ -1114,6 +1158,13 @@ irnet_connect_confirm(void * instance,
863 DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
865 + /* Check if socket is closing down (via irda_irnet_destroy()) */
866 + if(! test_bit(0, &self->ttp_connect))
868 + DERROR(IRDA_CB_ERROR, "Socket no longer connecting. Ouch !\n");
872 /* How much header space do we need to reserve */
873 self->max_header_size = max_header_size;
875 @@ -1129,8 +1180,8 @@ irnet_connect_confirm(void * instance,
876 self->saddr = irttp_get_saddr(self->tsap);
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);
886 @@ -1251,56 +1302,76 @@ irnet_connect_indication(void * instanc
887 __u8 max_header_size,
890 - irnet_socket * self = &irnet_server.s;
891 + irnet_socket * server = &irnet_server.s;
892 irnet_socket * new = (irnet_socket *) NULL;
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");
900 /* Try to find the most appropriate IrNET socket */
901 - new = irnet_find_socket(self);
902 + new = irnet_find_socket(server);
904 /* After all this hard work, do we have an socket ? */
905 if(new == (irnet_socket *) NULL)
907 DEXIT(IRDA_CB_INFO, ": No socket waiting for this connection.\n");
908 - irnet_disconnect_server(self, skb);
909 + irnet_disconnect_server(server, skb);
913 /* Is the socket already busy ? */
915 + if(test_bit(0, &new->ttp_open))
917 DEXIT(IRDA_CB_INFO, ": Socket already connected.\n");
918 - irnet_disconnect_server(self, skb);
919 + irnet_disconnect_server(server, skb);
923 - /* Socket connecting */
924 - if(new->tsap != NULL)
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))
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
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)
950 + /* Close the connection the new socket was attempting.
951 + * This seems to be safe... */
952 + irttp_close_tsap(new->tsap);
955 /* Note : no return, fall through... */
956 #else /* ALLOW_SIMULT_CONNECT */
957 - irnet_disconnect_server(self, skb);
958 + irnet_disconnect_server(server, skb);
960 #endif /* ALLOW_SIMULT_CONNECT */
963 + /* If socket is not connecting or connected, tsap should be NULL */
964 + if(new->tsap != NULL)
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);
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);
980 /* Check size of received packet */
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");
986 - /* We probably don't need to make any more queries */
987 - iriap_close(self->iriap);
988 - self->iriap = NULL;
990 - /* Check if already connected (via irnet_connect_socket()) */
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))
996 - DERROR(IRDA_OCB_ERROR, "Socket already connected. Ouch !\n");
997 + DERROR(IRDA_OCB_ERROR, "Socket no longer connecting. Ouch !\n");
1001 + /* We probably don't need to make any more queries */
1002 + iriap_close(self->iriap);
1003 + self->iriap = NULL;
1005 /* Post process the IAS reply */
1006 self->dtsap_sel = irnet_ias_to_tsap(self, result, value);
1008 /* If error, just go out */
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);
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");
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))
1024 + DERROR(IRDA_OCB_ERROR, "Socket no longer connecting. Ouch !\n");
1028 /* Post process the IAS reply */
1029 dtsap_sel = irnet_ias_to_tsap(self, result, value);
1031 @@ -1468,15 +1548,8 @@ irnet_discovervalue_confirm(int result,
1032 if(self->daddr == DEV_ADDR_ANY)
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");
1041 - /* Check if already connected (via irnet_connect_socket()) */
1042 - if(self->ttp_open)
1044 - DERROR(IRDA_OCB_ERROR, "Socket already connected. Ouch !\n");
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");
1054 /* Check if we are connected */
1055 - if(self->ttp_open == 0)
1056 + if(!(test_bit(0, &self->ttp_open)))
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
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))
1067 /* Blocking packet, ppp_generic will retry later */