kernel: Add ATM fixes pending upstream merge (queue reduction, race fixes)
[openwrt.git] / target / linux / generic / patches-3.6 / 131-atm-fixes.patch
1 commit 86768086727a60335b08c34b2966c784029a24cf
2 Author: David Woodhouse <David.Woodhouse@intel.com>
3 Date:   Wed Nov 28 10:15:05 2012 +0000
4
5     pppoatm: optimise PPP channel wakeups after sock_owned_by_user()
6     
7     We don't need to schedule the wakeup tasklet on *every* unlock; only if we
8     actually blocked the channel in the first place.
9     
10     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
11     Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
12
13 commit a009aa5fde926350f7a7e558a3ac0180e10eb24a
14 Author: Krzysztof Mazur <krzysiek@podlesie.net>
15 Date:   Wed Nov 28 09:08:04 2012 +0100
16
17     br2684: allow assign only on a connected socket
18     
19     The br2684 does not check if used vcc is in connected state,
20     causing potential Oops in pppoatm_send() when vcc->send() is called
21     on not fully connected socket.
22     
23     Now br2684 can be assigned only on connected sockets; otherwise
24     -EINVAL error is returned.
25     
26     Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
27     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
28
29 commit ae2169bcb6375fb214cadd0ea50ac54bcf39b0d6
30 Author: Nathan Williams <nathan@traverse.com.au>
31 Date:   Tue Nov 27 17:34:09 2012 +1100
32
33     solos-pci: Fix leak of skb received for unknown vcc
34     
35     ... and ensure that the next skb is set up for RX in the DMA case.
36     
37     Signed-off-by: Nathan Williams <nathan@traverse.com.au>
38     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
39
40 commit 6227612becaebe2f9f4ad7d0cdf27e298bb56687
41 Author: David Woodhouse <David.Woodhouse@intel.com>
42 Date:   Wed Nov 28 00:46:45 2012 +0000
43
44     br2684: fix module_put() race
45     
46     The br2684 code used module_put() during unassignment from vcc with
47     hope that we have BKL. This assumption is no longer true.
48     
49     Now owner field in atmvcc is used to move this module_put()
50     to vcc_destroy_socket().
51     
52     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
53     Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
54
55 commit 44abbb464896dc2270716d25e12fe47e57eeb1d3
56 Author: David Woodhouse <David.Woodhouse@intel.com>
57 Date:   Wed Nov 28 00:05:52 2012 +0000
58
59     pppoatm: fix missing wakeup in pppoatm_send()
60     
61     Now that we can return zero from pppoatm_send() for reasons *other* than
62     the queue being full, that means we can't depend on a subsequent call to
63     pppoatm_pop() waking the queue, and we might leave it stalled
64     indefinitely.
65     
66     Use the ->release_cb() callback to wake the queue after the sock is
67     unlocked.
68     
69     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
70     Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
71
72 commit c93eeac2ebee497dbc9b6ad39c235ff3061be141
73 Author: David Woodhouse <David.Woodhouse@intel.com>
74 Date:   Wed Nov 28 00:03:11 2012 +0000
75
76     atm: Add release_cb() callback to vcc
77     
78     The immediate use case for this is that it will allow us to ensure that a
79     pppoatm queue is woken after it has to drop a packet due to the sock being
80     locked.
81     
82     Note that 'release_cb' is called when the socket is *unlocked*. This is
83     not to be confused with vcc_release() — which probably ought to be called
84     vcc_close().
85     
86     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
87     Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
88
89 commit 9b3e2e224cc4326d8897243b24d778abf9098a8d
90 Author: David Woodhouse <dwmw2@infradead.org>
91 Date:   Tue Nov 27 23:28:36 2012 +0000
92
93     br2684: don't send frames on not-ready vcc
94     
95     Avoid submitting packets to a vcc which is being closed. Things go badly
96     wrong when the ->pop method gets later called after everything's been
97     torn down.
98     
99     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
100     Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
101
102 commit 26c7c53318cf56a690ae553104f4a60181734fb5
103 Author: David Woodhouse <David.Woodhouse@intel.com>
104 Date:   Tue Nov 27 23:49:24 2012 +0000
105
106     solos-pci: Wait for pending TX to complete when releasing vcc
107     
108     We should no longer be calling the old pop routine for the vcc, after
109     vcc_release() has completed. Make sure we wait for any pending TX skbs
110     to complete, by waiting for our own PKT_PCLOSE control skb to be sent.
111     
112     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
113
114 commit 1a3304e89b9ba168340a37926014be11c3ad110e
115 Author: Krzysztof Mazur <krzysiek@podlesie.net>
116 Date:   Tue Nov 6 23:17:02 2012 +0100
117
118     pppoatm: do not inline pppoatm_may_send()
119     
120     The pppoatm_may_send() is quite heavy and it's called three times
121     in pppoatm_send() and inlining costs more than 200 bytes of code
122     (more than 10% of total pppoatm driver code size).
123     
124     add/remove: 1/0 grow/shrink: 0/1 up/down: 132/-367 (-235)
125     function                                     old     new   delta
126     pppoatm_may_send                               -     132    +132
127     pppoatm_send                                 900     533    -367
128     
129     Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
130     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
131
132 commit 294398bcd0fe26335059a185b59cfb5de1fc4c71
133 Author: Krzysztof Mazur <krzysiek@podlesie.net>
134 Date:   Sat Nov 10 23:33:19 2012 +0100
135
136     pppoatm: drop frames to not-ready vcc
137     
138     Patches "atm: detach protocol before closing vcc"
139     and "pppoatm: allow assign only on a connected socket" fixed
140     common cases where the pppoatm_send() crashes while sending
141     frame to not-ready vcc. However there are still some other cases
142     where we can send frames to vcc, which is flagged as ATM_VF_CLOSE
143     (for instance after vcc_release_async()) or it's opened but not
144     ready yet.
145     
146     Now pppoatm_send(), like vcc_sendmsg(), checks for vcc flags that
147     indicate that vcc is not ready. If the vcc is not ready we just
148     drop frame. Queueing frames is much more complicated because we
149     don't have callbacks that inform us about vcc flags changes.
150     
151     Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
152     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
153
154 commit 3ac108006fd7f20cb8fc8ea2287f1497bcda00a1
155 Author: Krzysztof Mazur <krzysiek@podlesie.net>
156 Date:   Tue Nov 6 23:17:00 2012 +0100
157
158     pppoatm: take ATM socket lock in pppoatm_send()
159     
160     The pppoatm_send() does not take any lock that will prevent concurrent
161     vcc_sendmsg(). This causes two problems:
162     
163         - there is no locking between checking the send queue size
164           with atm_may_send() and incrementing sk_wmem_alloc,
165           and the real queue size can be a little higher than sk_sndbuf
166     
167         - the vcc->sendmsg() can be called concurrently. I'm not sure
168           if it's allowed. Some drivers (eni, nicstar, ...) seem
169           to assume it will never happen.
170     
171     Now pppoatm_send() takes ATM socket lock, the same that is used
172     in vcc_sendmsg() and other ATM socket functions. The pppoatm_send()
173     is called with BH disabled, so bh_lock_sock() is used instead
174     of lock_sock().
175     
176     Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
177     Cc: Chas Williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
178     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
179
180 commit e41faed9cde1acce657f75a0b19a1787e9850d3f
181 Author: Krzysztof Mazur <krzysiek@podlesie.net>
182 Date:   Tue Nov 6 23:16:59 2012 +0100
183
184     pppoatm: fix module_put() race
185     
186     The pppoatm used module_put() during unassignment from vcc with
187     hope that we have BKL. This assumption is no longer true.
188     
189     Now owner field in atmvcc is used to move this module_put()
190     to vcc_destroy_socket().
191     
192     Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
193     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
194
195 commit 3b1a914595f3f9beb9e38ff3ddc7bdafa092ba22
196 Author: Krzysztof Mazur <krzysiek@podlesie.net>
197 Date:   Tue Nov 6 23:16:58 2012 +0100
198
199     pppoatm: allow assign only on a connected socket
200     
201     The pppoatm does not check if used vcc is in connected state,
202     causing an Oops in pppoatm_send() when vcc->send() is called
203     on not fully connected socket.
204     
205     Now pppoatm can be assigned only on connected sockets; otherwise
206     -EINVAL error is returned.
207     
208     Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
209     Cc: Chas Williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
210     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
211
212 commit ec809bd817dfa1905283468e4c813684ed4efe78
213 Author: Krzysztof Mazur <krzysiek@podlesie.net>
214 Date:   Tue Nov 6 23:16:57 2012 +0100
215
216     atm: add owner of push() callback to atmvcc
217     
218     The atm is using atmvcc->push(vcc, NULL) callback to notify protocol
219     that vcc will be closed and protocol must detach from it. This callback
220     is usually used by protocol to decrement module usage count by module_put(),
221     but it leaves small window then module is still used after module_put().
222     
223     Now the owner of push() callback is kept in atmvcc and
224     module_put(atmvcc->owner) is called after the protocol is detached from vcc.
225     
226     Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
227     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
228     Acked-by: Chas Williams <chas@cmf.nrl.navy.mil>
229
230 commit ae088d663beebb3cad0e7abaac67ee61a7c578d5
231 Author: David Woodhouse <dwmw2@infradead.org>
232 Date:   Sun Nov 25 12:06:52 2012 +0000
233
234     atm: br2684: Fix excessive queue bloat
235     
236     There's really no excuse for an additional wmem_default of buffering
237     between the netdev queue and the ATM device. Two packets (one in-flight,
238     and one ready to send) ought to be fine. It's not as if it should take
239     long to get another from the netdev queue when we need it.
240     
241     If necessary we can make the queue space configurable later, but I don't
242     think it's likely to be necessary.
243     
244     cf. commit 9d02daf754238adac48fa075ee79e7edd3d79ed3 (pppoatm: Fix
245     excessive queue bloat) which did something very similar for PPPoATM.
246     
247     Note that there is a tremendously unlikely race condition which may
248     result in qspace temporarily going negative. If a CPU running the
249     br2684_pop() function goes off into the weeds for a long period of time
250     after incrementing qspace to 1, but before calling netdev_wake_queue()...
251     and another CPU ends up calling br2684_start_xmit() and *stopping* the
252     queue again before the first CPU comes back, the netdev queue could
253     end up being woken when qspace has already reached zero.
254     
255     An alternative approach to coping with this race would be to check in
256     br2684_start_xmit() for qspace==0 and return NETDEV_TX_BUSY, but just
257     using '> 0' and '< 1' for comparison instead of '== 0' and '!= 0' is
258     simpler. It just warranted a mention of *why* we do it that way...
259     
260     Move the call to atmvcc->send() to happen *after* the accounting and
261     potentially stopping the netdev queue, in br2684_xmit_vcc(). This matters
262     if the ->send() call suffers an immediate failure, because it'll call
263     br2684_pop() with the offending skb before returning. We want that to
264     happen *after* we've done the initial accounting for the packet in
265     question. Also make it return an appropriate success/failure indication
266     while we're at it.
267     
268     Tested by running 'ping -l 1000 bottomless.aaisp.net.uk' from within my
269     network, with only a single PPPoE-over-BR2684 link running. And after
270     setting txqueuelen on the nas0 interface to something low (5, in fact).
271     Before the patch, we'd see about 15 packets being queued and a resulting
272     latency of ~56ms being reached. After the patch, we see only about 8,
273     which is fairly much what we expect. And a max latency of ~36ms. On this
274     OpenWRT box, wmem_default is 163840.
275     
276     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
277     Reviewed-by: Krzysztof Mazur <krzysiek@podlesie.net>
278     Signed-off-by: David S. Miller <davem@davemloft.net>
279
280 diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
281 index 9851093..6258961 100644
282 --- a/drivers/atm/solos-pci.c
283 +++ b/drivers/atm/solos-pci.c
284 @@ -92,6 +92,7 @@ struct pkt_hdr {
285  };
286  
287  struct solos_skb_cb {
288 +       struct completion c;
289         struct atm_vcc *vcc;
290         uint32_t dma_addr;
291  };
292 @@ -710,7 +711,8 @@ void solos_bh(unsigned long card_arg)
293                                                 dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n",
294                                                          le16_to_cpu(header->vpi), le16_to_cpu(header->vci),
295                                                          port);
296 -                                       continue;
297 +                                       dev_kfree_skb_any(skb);
298 +                                       break;
299                                 }
300                                 atm_charge(vcc, skb->truesize);
301                                 vcc->push(vcc, skb);
302 @@ -881,11 +883,18 @@ static void pclose(struct atm_vcc *vcc)
303         header->vci = cpu_to_le16(vcc->vci);
304         header->type = cpu_to_le16(PKT_PCLOSE);
305  
306 +       init_completion(&SKB_CB(skb)->c);
307 +
308         fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, NULL);
309  
310         clear_bit(ATM_VF_ADDR, &vcc->flags);
311         clear_bit(ATM_VF_READY, &vcc->flags);
312  
313 +       if (!wait_for_completion_timeout(&SKB_CB(skb)->c,
314 +                                        msecs_to_jiffies(5000)))
315 +               dev_warn(&card->dev->dev, "Timeout waiting for VCC close on port %d\n",
316 +                        SOLOS_CHAN(vcc->dev));
317 +
318         /* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the
319            tasklet has finished processing any incoming packets (and, more to
320            the point, using the vcc pointer). */
321 @@ -1011,9 +1020,12 @@ static uint32_t fpga_tx(struct solos_card *card)
322                         if (vcc) {
323                                 atomic_inc(&vcc->stats->tx);
324                                 solos_pop(vcc, oldskb);
325 -                       } else
326 +                       } else {
327 +                               struct pkt_hdr *header = (void *)oldskb->data;
328 +                               if (le16_to_cpu(header->type) == PKT_PCLOSE)
329 +                                       complete(&SKB_CB(oldskb)->c);
330                                 dev_kfree_skb_irq(oldskb);
331 -
332 +                       }
333                 }
334         }
335         /* For non-DMA TX, write the 'TX start' bit for all four ports simultaneously */
336 @@ -1345,6 +1357,8 @@ static struct pci_driver fpga_driver = {
337  
338  static int __init solos_pci_init(void)
339  {
340 +       BUILD_BUG_ON(sizeof(struct solos_skb_cb) > sizeof(((struct sk_buff *)0)->cb));
341 +
342         printk(KERN_INFO "Solos PCI Driver Version %s\n", VERSION);
343         return pci_register_driver(&fpga_driver);
344  }
345 diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
346 index 22ef21c..c1da539 100644
347 --- a/include/linux/atmdev.h
348 +++ b/include/linux/atmdev.h
349 @@ -99,6 +99,7 @@ struct atm_vcc {
350         struct atm_dev  *dev;           /* device back pointer */
351         struct atm_qos  qos;            /* QOS */
352         struct atm_sap  sap;            /* SAP */
353 +       void (*release_cb)(struct atm_vcc *vcc); /* release_sock callback */
354         void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
355         void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
356         int (*push_oam)(struct atm_vcc *vcc,void *cell);
357 @@ -106,6 +107,7 @@ struct atm_vcc {
358         void            *dev_data;      /* per-device data */
359         void            *proto_data;    /* per-protocol data */
360         struct k_atm_aal_stats *stats;  /* pointer to AAL stats group */
361 +       struct module *owner;           /* owner of ->push function */
362         /* SVC part --- may move later ------------------------------------- */
363         short           itf;            /* interface number */
364         struct sockaddr_atmsvc local;
365 diff --git a/net/atm/br2684.c b/net/atm/br2684.c
366 index 4819d315..a4ee4ad 100644
367 --- a/net/atm/br2684.c
368 +++ b/net/atm/br2684.c
369 @@ -68,12 +68,14 @@ struct br2684_vcc {
370         /* keep old push, pop functions for chaining */
371         void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb);
372         void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
373 +       struct module *old_owner;
374         enum br2684_encaps encaps;
375         struct list_head brvccs;
376  #ifdef CONFIG_ATM_BR2684_IPFILTER
377         struct br2684_filter filter;
378  #endif /* CONFIG_ATM_BR2684_IPFILTER */
379         unsigned int copies_needed, copies_failed;
380 +       atomic_t qspace;
381  };
382  
383  struct br2684_dev {
384 @@ -181,18 +183,15 @@ static struct notifier_block atm_dev_notifier = {
385  static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
386  {
387         struct br2684_vcc *brvcc = BR2684_VCC(vcc);
388 -       struct net_device *net_dev = skb->dev;
389  
390 -       pr_debug("(vcc %p ; net_dev %p )\n", vcc, net_dev);
391 +       pr_debug("(vcc %p ; net_dev %p )\n", vcc, brvcc->device);
392         brvcc->old_pop(vcc, skb);
393  
394 -       if (!net_dev)
395 -               return;
396 -
397 -       if (atm_may_send(vcc, 0))
398 -               netif_wake_queue(net_dev);
399 -
400 +       /* If the queue space just went up from zero, wake */
401 +       if (atomic_inc_return(&brvcc->qspace) == 1)
402 +               netif_wake_queue(brvcc->device);
403  }
404 +
405  /*
406   * Send a packet out a particular vcc.  Not to useful right now, but paves
407   * the way for multiple vcc's per itf.  Returns true if we can send,
408 @@ -251,21 +250,30 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
409         skb_debug(skb);
410  
411         ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
412 +       if (test_bit(ATM_VF_RELEASED, &atmvcc->flags) ||
413 +           test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
414 +           !test_bit(ATM_VF_READY, &atmvcc->flags)) {
415 +               dev_kfree_skb(skb);
416 +               return 0;
417 +       }
418         pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
419         atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
420         ATM_SKB(skb)->atm_options = atmvcc->atm_options;
421         dev->stats.tx_packets++;
422         dev->stats.tx_bytes += skb->len;
423 -       atmvcc->send(atmvcc, skb);
424  
425 -       if (!atm_may_send(atmvcc, 0)) {
426 +       if (atomic_dec_return(&brvcc->qspace) < 1) {
427 +               /* No more please! */
428                 netif_stop_queue(brvcc->device);
429 -               /*check for race with br2684_pop*/
430 -               if (atm_may_send(atmvcc, 0))
431 -                       netif_start_queue(brvcc->device);
432 +               /* We might have raced with br2684_pop() */
433 +               if (unlikely(atomic_read(&brvcc->qspace) > 0))
434 +                       netif_wake_queue(brvcc->device);
435         }
436  
437 -       return 1;
438 +       /* If this fails immediately, the skb will be freed and br2684_pop()
439 +          will wake the queue if appropriate. Just return an error so that
440 +          the stats are updated correctly */
441 +       return !atmvcc->send(atmvcc, skb);
442  }
443  
444  static inline struct br2684_vcc *pick_outgoing_vcc(const struct sk_buff *skb,
445 @@ -378,8 +386,8 @@ static void br2684_close_vcc(struct br2684_vcc *brvcc)
446         write_unlock_irq(&devs_lock);
447         brvcc->atmvcc->user_back = NULL;        /* what about vcc->recvq ??? */
448         brvcc->old_push(brvcc->atmvcc, NULL);   /* pass on the bad news */
449 +       module_put(brvcc->old_owner);
450         kfree(brvcc);
451 -       module_put(THIS_MODULE);
452  }
453  
454  /* when AAL5 PDU comes in: */
455 @@ -504,6 +512,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
456         brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
457         if (!brvcc)
458                 return -ENOMEM;
459 +       /*
460 +        * Allow two packets in the ATM queue. One actually being sent, and one
461 +        * for the ATM 'TX done' handler to send. It shouldn't take long to get
462 +        * the next one from the netdev queue, when we need it. More than that
463 +        * would be bufferbloat.
464 +        */
465 +       atomic_set(&brvcc->qspace, 2);
466         write_lock_irq(&devs_lock);
467         net_dev = br2684_find_dev(&be.ifspec);
468         if (net_dev == NULL) {
469 @@ -546,9 +561,11 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
470         brvcc->encaps = (enum br2684_encaps)be.encaps;
471         brvcc->old_push = atmvcc->push;
472         brvcc->old_pop = atmvcc->pop;
473 +       brvcc->old_owner = atmvcc->owner;
474         barrier();
475         atmvcc->push = br2684_push;
476         atmvcc->pop = br2684_pop;
477 +       atmvcc->owner = THIS_MODULE;
478  
479         /* initialize netdev carrier state */
480         if (atmvcc->dev->signal == ATM_PHY_SIG_LOST)
481 @@ -687,10 +704,13 @@ static int br2684_ioctl(struct socket *sock, unsigned int cmd,
482                         return -ENOIOCTLCMD;
483                 if (!capable(CAP_NET_ADMIN))
484                         return -EPERM;
485 -               if (cmd == ATM_SETBACKEND)
486 +               if (cmd == ATM_SETBACKEND) {
487 +                       if (sock->state != SS_CONNECTED)
488 +                               return -EINVAL;
489                         return br2684_regvcc(atmvcc, argp);
490 -               else
491 +               } else {
492                         return br2684_create(argp);
493 +               }
494  #ifdef CONFIG_ATM_BR2684_IPFILTER
495         case BR2684_SETFILT:
496                 if (atmvcc->push != br2684_push)
497 diff --git a/net/atm/common.c b/net/atm/common.c
498 index 0c0ad93..806fc0a 100644
499 --- a/net/atm/common.c
500 +++ b/net/atm/common.c
501 @@ -126,10 +126,19 @@ static void vcc_write_space(struct sock *sk)
502         rcu_read_unlock();
503  }
504  
505 +static void vcc_release_cb(struct sock *sk)
506 +{
507 +       struct atm_vcc *vcc = atm_sk(sk);
508 +
509 +       if (vcc->release_cb)
510 +               vcc->release_cb(vcc);
511 +}
512 +
513  static struct proto vcc_proto = {
514         .name     = "VCC",
515         .owner    = THIS_MODULE,
516         .obj_size = sizeof(struct atm_vcc),
517 +       .release_cb = vcc_release_cb,
518  };
519  
520  int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
521 @@ -156,7 +165,9 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
522         atomic_set(&sk->sk_rmem_alloc, 0);
523         vcc->push = NULL;
524         vcc->pop = NULL;
525 +       vcc->owner = NULL;
526         vcc->push_oam = NULL;
527 +       vcc->release_cb = NULL;
528         vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
529         vcc->atm_options = vcc->aal_options = 0;
530         sk->sk_destruct = vcc_sock_destruct;
531 @@ -175,6 +186,7 @@ static void vcc_destroy_socket(struct sock *sk)
532                         vcc->dev->ops->close(vcc);
533                 if (vcc->push)
534                         vcc->push(vcc, NULL); /* atmarpd has no push */
535 +               module_put(vcc->owner);
536  
537                 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
538                         atm_return(vcc, skb->truesize);
539 diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
540 index 226dca9..8c93267 100644
541 --- a/net/atm/pppoatm.c
542 +++ b/net/atm/pppoatm.c
543 @@ -60,6 +60,8 @@ struct pppoatm_vcc {
544         struct atm_vcc  *atmvcc;        /* VCC descriptor */
545         void (*old_push)(struct atm_vcc *, struct sk_buff *);
546         void (*old_pop)(struct atm_vcc *, struct sk_buff *);
547 +       void (*old_release_cb)(struct atm_vcc *);
548 +       struct module *old_owner;
549                                         /* keep old push/pop for detaching */
550         enum pppoatm_encaps encaps;
551         atomic_t inflight;
552 @@ -107,6 +109,24 @@ static void pppoatm_wakeup_sender(unsigned long arg)
553         ppp_output_wakeup((struct ppp_channel *) arg);
554  }
555  
556 +static void pppoatm_release_cb(struct atm_vcc *atmvcc)
557 +{
558 +       struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
559 +
560 +       /*
561 +        * As in pppoatm_pop(), it's safe to clear the BLOCKED bit here because
562 +        * the wakeup *can't* race with pppoatm_send(). They both hold the PPP
563 +        * channel's ->downl lock. And the potential race with *setting* it,
564 +        * which leads to the double-check dance in pppoatm_may_send(), doesn't
565 +        * exist here. In the sock_owned_by_user() case in pppoatm_send(), we
566 +        * set the BLOCKED bit while the socket is still locked. We know that
567 +        * ->release_cb() can't be called until that's done.
568 +        */
569 +       if (test_and_clear_bit(BLOCKED, &pvcc->blocked))
570 +               tasklet_schedule(&pvcc->wakeup_tasklet);
571 +       if (pvcc->old_release_cb)
572 +               pvcc->old_release_cb(atmvcc);
573 +}
574  /*
575   * This gets called every time the ATM card has finished sending our
576   * skb.  The ->old_pop will take care up normal atm flow control,
577 @@ -151,12 +171,11 @@ static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc)
578         pvcc = atmvcc_to_pvcc(atmvcc);
579         atmvcc->push = pvcc->old_push;
580         atmvcc->pop = pvcc->old_pop;
581 +       atmvcc->release_cb = pvcc->old_release_cb;
582         tasklet_kill(&pvcc->wakeup_tasklet);
583         ppp_unregister_channel(&pvcc->chan);
584         atmvcc->user_back = NULL;
585         kfree(pvcc);
586 -       /* Gee, I hope we have the big kernel lock here... */
587 -       module_put(THIS_MODULE);
588  }
589  
590  /* Called when an AAL5 PDU comes in */
591 @@ -165,9 +184,13 @@ static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
592         struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
593         pr_debug("\n");
594         if (skb == NULL) {                      /* VCC was closed */
595 +               struct module *module;
596 +
597                 pr_debug("removing ATMPPP VCC %p\n", pvcc);
598 +               module = pvcc->old_owner;
599                 pppoatm_unassign_vcc(atmvcc);
600                 atmvcc->push(atmvcc, NULL);     /* Pass along bad news */
601 +               module_put(module);
602                 return;
603         }
604         atm_return(atmvcc, skb->truesize);
605 @@ -211,7 +234,7 @@ error:
606         ppp_input_error(&pvcc->chan, 0);
607  }
608  
609 -static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
610 +static int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
611  {
612         /*
613          * It's not clear that we need to bother with using atm_may_send()
614 @@ -269,10 +292,33 @@ static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
615  static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
616  {
617         struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
618 +       struct atm_vcc *vcc;
619 +       int ret;
620 +
621         ATM_SKB(skb)->vcc = pvcc->atmvcc;
622         pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc);
623         if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
624                 (void) skb_pull(skb, 1);
625 +
626 +       vcc = ATM_SKB(skb)->vcc;
627 +       bh_lock_sock(sk_atm(vcc));
628 +       if (sock_owned_by_user(sk_atm(vcc))) {
629 +               /*
630 +                * Needs to happen (and be flushed, hence test_and_) before we unlock
631 +                * the socket. It needs to be seen by the time our ->release_cb gets
632 +                * called.
633 +                */
634 +               test_and_set_bit(BLOCKED, &pvcc->blocked);
635 +               goto nospace;
636 +       }
637 +       if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
638 +           test_bit(ATM_VF_CLOSE, &vcc->flags) ||
639 +           !test_bit(ATM_VF_READY, &vcc->flags)) {
640 +               bh_unlock_sock(sk_atm(vcc));
641 +               kfree_skb(skb);
642 +               return DROP_PACKET;
643 +       }
644 +
645         switch (pvcc->encaps) {         /* LLC encapsulation needed */
646         case e_llc:
647                 if (skb_headroom(skb) < LLC_LEN) {
648 @@ -285,8 +331,10 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
649                         }
650                         consume_skb(skb);
651                         skb = n;
652 -                       if (skb == NULL)
653 +                       if (skb == NULL) {
654 +                               bh_unlock_sock(sk_atm(vcc));
655                                 return DROP_PACKET;
656 +                       }
657                 } else if (!pppoatm_may_send(pvcc, skb->truesize))
658                         goto nospace;
659                 memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
660 @@ -296,6 +344,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
661                         goto nospace;
662                 break;
663         case e_autodetect:
664 +               bh_unlock_sock(sk_atm(vcc));
665                 pr_debug("Trying to send without setting encaps!\n");
666                 kfree_skb(skb);
667                 return 1;
668 @@ -305,9 +354,12 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
669         ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
670         pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
671                  skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
672 -       return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
673 +       ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
674             ? DROP_PACKET : 1;
675 +       bh_unlock_sock(sk_atm(vcc));
676 +       return ret;
677  nospace:
678 +       bh_unlock_sock(sk_atm(vcc));
679         /*
680          * We don't have space to send this SKB now, but we might have
681          * already applied SC_COMP_PROT compression, so may need to undo
682 @@ -362,6 +414,8 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
683         atomic_set(&pvcc->inflight, NONE_INFLIGHT);
684         pvcc->old_push = atmvcc->push;
685         pvcc->old_pop = atmvcc->pop;
686 +       pvcc->old_owner = atmvcc->owner;
687 +       pvcc->old_release_cb = atmvcc->release_cb;
688         pvcc->encaps = (enum pppoatm_encaps) be.encaps;
689         pvcc->chan.private = pvcc;
690         pvcc->chan.ops = &pppoatm_ops;
691 @@ -377,7 +431,9 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
692         atmvcc->user_back = pvcc;
693         atmvcc->push = pppoatm_push;
694         atmvcc->pop = pppoatm_pop;
695 +       atmvcc->release_cb = pppoatm_release_cb;
696         __module_get(THIS_MODULE);
697 +       atmvcc->owner = THIS_MODULE;
698  
699         /* re-process everything received between connection setup and
700            backend setup */
701 @@ -406,6 +462,8 @@ static int pppoatm_ioctl(struct socket *sock, unsigned int cmd,
702                         return -ENOIOCTLCMD;
703                 if (!capable(CAP_NET_ADMIN))
704                         return -EPERM;
705 +               if (sock->state != SS_CONNECTED)
706 +                       return -EINVAL;
707                 return pppoatm_assign_vcc(atmvcc, argp);
708                 }
709         case PPPIOCGCHAN: