diff options
Diffstat (limited to 'net/atm/br2684.c')
-rw-r--r-- | net/atm/br2684.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index b04162f10d85..83a1c1b1d6cd 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -23,7 +23,6 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary | |||
23 | #include <linux/atmbr2684.h> | 23 | #include <linux/atmbr2684.h> |
24 | 24 | ||
25 | #include "common.h" | 25 | #include "common.h" |
26 | #include "ipcommon.h" | ||
27 | 26 | ||
28 | /* | 27 | /* |
29 | * Define this to use a version of the code which interacts with the higher | 28 | * Define this to use a version of the code which interacts with the higher |
@@ -500,11 +499,12 @@ Note: we do not have explicit unassign, but look at _push() | |||
500 | */ | 499 | */ |
501 | int err; | 500 | int err; |
502 | struct br2684_vcc *brvcc; | 501 | struct br2684_vcc *brvcc; |
503 | struct sk_buff_head copy; | ||
504 | struct sk_buff *skb; | 502 | struct sk_buff *skb; |
503 | struct sk_buff_head *rq; | ||
505 | struct br2684_dev *brdev; | 504 | struct br2684_dev *brdev; |
506 | struct net_device *net_dev; | 505 | struct net_device *net_dev; |
507 | struct atm_backend_br2684 be; | 506 | struct atm_backend_br2684 be; |
507 | unsigned long flags; | ||
508 | 508 | ||
509 | if (copy_from_user(&be, arg, sizeof be)) | 509 | if (copy_from_user(&be, arg, sizeof be)) |
510 | return -EFAULT; | 510 | return -EFAULT; |
@@ -554,12 +554,30 @@ Note: we do not have explicit unassign, but look at _push() | |||
554 | brvcc->old_push = atmvcc->push; | 554 | brvcc->old_push = atmvcc->push; |
555 | barrier(); | 555 | barrier(); |
556 | atmvcc->push = br2684_push; | 556 | atmvcc->push = br2684_push; |
557 | skb_queue_head_init(©); | 557 | |
558 | skb_migrate(&sk_atm(atmvcc)->sk_receive_queue, ©); | 558 | rq = &sk_atm(atmvcc)->sk_receive_queue; |
559 | while ((skb = skb_dequeue(©)) != NULL) { | 559 | |
560 | spin_lock_irqsave(&rq->lock, flags); | ||
561 | if (skb_queue_empty(rq)) { | ||
562 | skb = NULL; | ||
563 | } else { | ||
564 | /* NULL terminate the list. */ | ||
565 | rq->prev->next = NULL; | ||
566 | skb = rq->next; | ||
567 | } | ||
568 | rq->prev = rq->next = (struct sk_buff *)rq; | ||
569 | rq->qlen = 0; | ||
570 | spin_unlock_irqrestore(&rq->lock, flags); | ||
571 | |||
572 | while (skb) { | ||
573 | struct sk_buff *next = skb->next; | ||
574 | |||
575 | skb->next = skb->prev = NULL; | ||
560 | BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; | 576 | BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; |
561 | BRPRIV(skb->dev)->stats.rx_packets--; | 577 | BRPRIV(skb->dev)->stats.rx_packets--; |
562 | br2684_push(atmvcc, skb); | 578 | br2684_push(atmvcc, skb); |
579 | |||
580 | skb = next; | ||
563 | } | 581 | } |
564 | __module_get(THIS_MODULE); | 582 | __module_get(THIS_MODULE); |
565 | return 0; | 583 | return 0; |