diff options
author | Samuel Ortiz <samuel@sortiz.org> | 2007-03-16 23:31:03 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-03-20 03:09:42 -0400 |
commit | c577c2b99387b5ff8607d42d6eaff9ec024d4773 (patch) | |
tree | 1f4e56d1209b1140060978183e7c03655477d149 /net/irda/irnet | |
parent | 7bb1bbe615de25d955b974cb47d40fa198154bb9 (diff) |
[IrDA]: Calling ppp_unregister_channel() from process context
We need to call ppp_unregister_channel() when IrNET disconnects, and this
must be done from a process context.
Bug reported and patch tested by Guennadi Liakhovetski.
Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/irda/irnet')
-rw-r--r-- | net/irda/irnet/irnet.h | 2 | ||||
-rw-r--r-- | net/irda/irnet/irnet_irda.c | 34 |
2 files changed, 26 insertions, 10 deletions
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h index 873ae189e37a..bc2e15ce7004 100644 --- a/net/irda/irnet/irnet.h +++ b/net/irda/irnet/irnet.h | |||
@@ -419,7 +419,7 @@ typedef struct irnet_socket | |||
419 | u32 raccm; /* to please pppd - dummy) */ | 419 | u32 raccm; /* to please pppd - dummy) */ |
420 | unsigned int flags; /* PPP flags (compression, ...) */ | 420 | unsigned int flags; /* PPP flags (compression, ...) */ |
421 | unsigned int rbits; /* Unused receive flags ??? */ | 421 | unsigned int rbits; /* Unused receive flags ??? */ |
422 | 422 | struct work_struct disconnect_work; /* Process context disconnection */ | |
423 | /* ------------------------ IrTTP part ------------------------ */ | 423 | /* ------------------------ IrTTP part ------------------------ */ |
424 | /* We create a pseudo "socket" over the IrDA tranport */ | 424 | /* We create a pseudo "socket" over the IrDA tranport */ |
425 | unsigned long ttp_open; /* Set when IrTTP is ready */ | 425 | unsigned long ttp_open; /* Set when IrTTP is ready */ |
diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c index c378e668af0c..a4f1439ffdd8 100644 --- a/net/irda/irnet/irnet_irda.c +++ b/net/irda/irnet/irnet_irda.c | |||
@@ -10,6 +10,27 @@ | |||
10 | 10 | ||
11 | #include "irnet_irda.h" /* Private header */ | 11 | #include "irnet_irda.h" /* Private header */ |
12 | 12 | ||
13 | /* | ||
14 | * PPP disconnect work: we need to make sure we're in | ||
15 | * process context when calling ppp_unregister_channel(). | ||
16 | */ | ||
17 | static void irnet_ppp_disconnect(struct work_struct *work) | ||
18 | { | ||
19 | irnet_socket * self = | ||
20 | container_of(work, irnet_socket, disconnect_work); | ||
21 | |||
22 | if (self == NULL) | ||
23 | return; | ||
24 | /* | ||
25 | * If we were connected, cleanup & close the PPP | ||
26 | * channel, which will kill pppd (hangup) and the rest. | ||
27 | */ | ||
28 | if (self->ppp_open && !self->ttp_open && !self->ttp_connect) { | ||
29 | ppp_unregister_channel(&self->chan); | ||
30 | self->ppp_open = 0; | ||
31 | } | ||
32 | } | ||
33 | |||
13 | /************************* CONTROL CHANNEL *************************/ | 34 | /************************* CONTROL CHANNEL *************************/ |
14 | /* | 35 | /* |
15 | * When ppp is not active, /dev/irnet act as a control channel. | 36 | * When ppp is not active, /dev/irnet act as a control channel. |
@@ -499,6 +520,8 @@ irda_irnet_create(irnet_socket * self) | |||
499 | #endif /* DISCOVERY_NOMASK */ | 520 | #endif /* DISCOVERY_NOMASK */ |
500 | self->tx_flow = FLOW_START; /* Flow control from IrTTP */ | 521 | self->tx_flow = FLOW_START; /* Flow control from IrTTP */ |
501 | 522 | ||
523 | INIT_WORK(&self->disconnect_work, irnet_ppp_disconnect); | ||
524 | |||
502 | DEXIT(IRDA_SOCK_TRACE, "\n"); | 525 | DEXIT(IRDA_SOCK_TRACE, "\n"); |
503 | return(0); | 526 | return(0); |
504 | } | 527 | } |
@@ -1134,15 +1157,8 @@ irnet_disconnect_indication(void * instance, | |||
1134 | { | 1157 | { |
1135 | if(test_open) | 1158 | if(test_open) |
1136 | { | 1159 | { |
1137 | #ifdef MISSING_PPP_API | 1160 | /* ppp_unregister_channel() wants a user context. */ |
1138 | /* ppp_unregister_channel() wants a user context, which we | 1161 | schedule_work(&self->disconnect_work); |
1139 | * are guaranteed to NOT have here. What are we supposed | ||
1140 | * to do here ? Jean II */ | ||
1141 | /* If we were connected, cleanup & close the PPP channel, | ||
1142 | * which will kill pppd (hangup) and the rest */ | ||
1143 | ppp_unregister_channel(&self->chan); | ||
1144 | self->ppp_open = 0; | ||
1145 | #endif | ||
1146 | } | 1162 | } |
1147 | else | 1163 | else |
1148 | { | 1164 | { |