aboutsummaryrefslogtreecommitdiffstats
path: root/net/atm
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2012-11-27 19:05:52 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-12-01 19:05:15 -0500
commit0e56d99a5b557c760394d6941d7d1fc8d279eff3 (patch)
tree530833693bc6df77fcee11f7632971c31429bcaf /net/atm
parentb89588531f1db93a218c108eee713ff6002a67bf (diff)
pppoatm: fix missing wakeup in pppoatm_send()
Now that we can return zero from pppoatm_send() for reasons *other* than the queue being full, that means we can't depend on a subsequent call to pppoatm_pop() waking the queue, and we might leave it stalled indefinitely. Use the ->release_cb() callback to wake the queue after the sock is unlocked. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
Diffstat (limited to 'net/atm')
-rw-r--r--net/atm/pppoatm.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 3dce84af5dbe..9fcda8c85e9a 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -60,6 +60,7 @@ struct pppoatm_vcc {
60 struct atm_vcc *atmvcc; /* VCC descriptor */ 60 struct atm_vcc *atmvcc; /* VCC descriptor */
61 void (*old_push)(struct atm_vcc *, struct sk_buff *); 61 void (*old_push)(struct atm_vcc *, struct sk_buff *);
62 void (*old_pop)(struct atm_vcc *, struct sk_buff *); 62 void (*old_pop)(struct atm_vcc *, struct sk_buff *);
63 void (*old_release_cb)(struct atm_vcc *);
63 struct module *old_owner; 64 struct module *old_owner;
64 /* keep old push/pop for detaching */ 65 /* keep old push/pop for detaching */
65 enum pppoatm_encaps encaps; 66 enum pppoatm_encaps encaps;
@@ -108,6 +109,14 @@ static void pppoatm_wakeup_sender(unsigned long arg)
108 ppp_output_wakeup((struct ppp_channel *) arg); 109 ppp_output_wakeup((struct ppp_channel *) arg);
109} 110}
110 111
112static void pppoatm_release_cb(struct atm_vcc *atmvcc)
113{
114 struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
115
116 tasklet_schedule(&pvcc->wakeup_tasklet);
117 if (pvcc->old_release_cb)
118 pvcc->old_release_cb(atmvcc);
119}
111/* 120/*
112 * This gets called every time the ATM card has finished sending our 121 * This gets called every time the ATM card has finished sending our
113 * skb. The ->old_pop will take care up normal atm flow control, 122 * skb. The ->old_pop will take care up normal atm flow control,
@@ -152,6 +161,7 @@ static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc)
152 pvcc = atmvcc_to_pvcc(atmvcc); 161 pvcc = atmvcc_to_pvcc(atmvcc);
153 atmvcc->push = pvcc->old_push; 162 atmvcc->push = pvcc->old_push;
154 atmvcc->pop = pvcc->old_pop; 163 atmvcc->pop = pvcc->old_pop;
164 atmvcc->release_cb = pvcc->old_release_cb;
155 tasklet_kill(&pvcc->wakeup_tasklet); 165 tasklet_kill(&pvcc->wakeup_tasklet);
156 ppp_unregister_channel(&pvcc->chan); 166 ppp_unregister_channel(&pvcc->chan);
157 atmvcc->user_back = NULL; 167 atmvcc->user_back = NULL;
@@ -388,6 +398,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
388 pvcc->old_push = atmvcc->push; 398 pvcc->old_push = atmvcc->push;
389 pvcc->old_pop = atmvcc->pop; 399 pvcc->old_pop = atmvcc->pop;
390 pvcc->old_owner = atmvcc->owner; 400 pvcc->old_owner = atmvcc->owner;
401 pvcc->old_release_cb = atmvcc->release_cb;
391 pvcc->encaps = (enum pppoatm_encaps) be.encaps; 402 pvcc->encaps = (enum pppoatm_encaps) be.encaps;
392 pvcc->chan.private = pvcc; 403 pvcc->chan.private = pvcc;
393 pvcc->chan.ops = &pppoatm_ops; 404 pvcc->chan.ops = &pppoatm_ops;
@@ -403,6 +414,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
403 atmvcc->user_back = pvcc; 414 atmvcc->user_back = pvcc;
404 atmvcc->push = pppoatm_push; 415 atmvcc->push = pppoatm_push;
405 atmvcc->pop = pppoatm_pop; 416 atmvcc->pop = pppoatm_pop;
417 atmvcc->release_cb = pppoatm_release_cb;
406 __module_get(THIS_MODULE); 418 __module_get(THIS_MODULE);
407 atmvcc->owner = THIS_MODULE; 419 atmvcc->owner = THIS_MODULE;
408 420