diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-01-18 10:34:51 +1100 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-01-18 10:34:51 +1100 |
commit | 9cdf083f981b8d37b3212400a359368661385099 (patch) | |
tree | aa15a6a08ad87e650dea40fb59b3180bef0d345b /net/atm/br2684.c | |
parent | e499e01d234a31d59679b7b1e1cf628d917ba49a (diff) | |
parent | a8b3485287731978899ced11f24628c927890e78 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'net/atm/br2684.c')
-rw-r--r-- | net/atm/br2684.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index d00cca97eb3..83a1c1b1d6c 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -23,7 +23,6 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary #include <linux/atmbr2684.h> #include "common.h" -#include "ipcommon.h" /* * Define this to use a version of the code which interacts with the higher @@ -372,7 +371,7 @@ static int br2684_setfilt(struct atm_vcc *atmvcc, void __user *arg) /* Returns 1 if packet should be dropped */ static inline int -packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb) +packet_fails_filter(__be16 type, struct br2684_vcc *brvcc, struct sk_buff *skb) { if (brvcc->filter.netmask == 0) return 0; /* no filter in place */ @@ -500,11 +499,12 @@ Note: we do not have explicit unassign, but look at _push() */ int err; struct br2684_vcc *brvcc; - struct sk_buff_head copy; struct sk_buff *skb; + struct sk_buff_head *rq; struct br2684_dev *brdev; struct net_device *net_dev; struct atm_backend_br2684 be; + unsigned long flags; if (copy_from_user(&be, arg, sizeof be)) return -EFAULT; @@ -554,12 +554,30 @@ Note: we do not have explicit unassign, but look at _push() brvcc->old_push = atmvcc->push; barrier(); atmvcc->push = br2684_push; - skb_queue_head_init(©); - skb_migrate(&sk_atm(atmvcc)->sk_receive_queue, ©); - while ((skb = skb_dequeue(©)) != NULL) { + + rq = &sk_atm(atmvcc)->sk_receive_queue; + + spin_lock_irqsave(&rq->lock, flags); + if (skb_queue_empty(rq)) { + skb = NULL; + } else { + /* NULL terminate the list. */ + rq->prev->next = NULL; + skb = rq->next; + } + rq->prev = rq->next = (struct sk_buff *)rq; + rq->qlen = 0; + spin_unlock_irqrestore(&rq->lock, flags); + + while (skb) { + struct sk_buff *next = skb->next; + + skb->next = skb->prev = NULL; BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; BRPRIV(skb->dev)->stats.rx_packets--; br2684_push(atmvcc, skb); + + skb = next; } __module_get(THIS_MODULE); return 0; |