diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2012-11-27 19:05:52 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-12-01 19:05:15 -0500 |
commit | 0e56d99a5b557c760394d6941d7d1fc8d279eff3 (patch) | |
tree | 530833693bc6df77fcee11f7632971c31429bcaf | |
parent | b89588531f1db93a218c108eee713ff6002a67bf (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>
-rw-r--r-- | net/atm/pppoatm.c | 12 |
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 | ||
112 | static 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 | ||