diff options
Diffstat (limited to 'net/atm/clip.c')
-rw-r--r-- | net/atm/clip.c | 27 |
1 files changed, 8 insertions, 19 deletions
diff --git a/net/atm/clip.c b/net/atm/clip.c index 3dc0a3a42a57..5597b87b9e64 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
@@ -445,9 +445,9 @@ static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
445 | 445 | ||
446 | static int clip_mkip(struct atm_vcc *vcc, int timeout) | 446 | static int clip_mkip(struct atm_vcc *vcc, int timeout) |
447 | { | 447 | { |
448 | struct sk_buff_head *rq, queue; | ||
448 | struct clip_vcc *clip_vcc; | 449 | struct clip_vcc *clip_vcc; |
449 | struct sk_buff *skb; | 450 | struct sk_buff *skb, *tmp; |
450 | struct sk_buff_head *rq; | ||
451 | unsigned long flags; | 451 | unsigned long flags; |
452 | 452 | ||
453 | if (!vcc->push) | 453 | if (!vcc->push) |
@@ -469,39 +469,28 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout) | |||
469 | vcc->push = clip_push; | 469 | vcc->push = clip_push; |
470 | vcc->pop = clip_pop; | 470 | vcc->pop = clip_pop; |
471 | 471 | ||
472 | __skb_queue_head_init(&queue); | ||
472 | rq = &sk_atm(vcc)->sk_receive_queue; | 473 | rq = &sk_atm(vcc)->sk_receive_queue; |
473 | 474 | ||
474 | spin_lock_irqsave(&rq->lock, flags); | 475 | spin_lock_irqsave(&rq->lock, flags); |
475 | if (skb_queue_empty(rq)) { | 476 | skb_queue_splice_init(rq, &queue); |
476 | skb = NULL; | ||
477 | } else { | ||
478 | /* NULL terminate the list. */ | ||
479 | rq->prev->next = NULL; | ||
480 | skb = rq->next; | ||
481 | } | ||
482 | rq->prev = rq->next = (struct sk_buff *)rq; | ||
483 | rq->qlen = 0; | ||
484 | spin_unlock_irqrestore(&rq->lock, flags); | 477 | spin_unlock_irqrestore(&rq->lock, flags); |
485 | 478 | ||
486 | /* re-process everything received between connection setup and MKIP */ | 479 | /* re-process everything received between connection setup and MKIP */ |
487 | while (skb) { | 480 | skb_queue_walk_safe(&queue, skb, tmp) { |
488 | struct sk_buff *next = skb->next; | ||
489 | |||
490 | skb->next = skb->prev = NULL; | ||
491 | if (!clip_devs) { | 481 | if (!clip_devs) { |
492 | atm_return(vcc, skb->truesize); | 482 | atm_return(vcc, skb->truesize); |
493 | kfree_skb(skb); | 483 | kfree_skb(skb); |
494 | } else { | 484 | } else { |
485 | struct net_device *dev = skb->dev; | ||
495 | unsigned int len = skb->len; | 486 | unsigned int len = skb->len; |
496 | 487 | ||
497 | skb_get(skb); | 488 | skb_get(skb); |
498 | clip_push(vcc, skb); | 489 | clip_push(vcc, skb); |
499 | skb->dev->stats.rx_packets--; | 490 | dev->stats.rx_packets--; |
500 | skb->dev->stats.rx_bytes -= len; | 491 | dev->stats.rx_bytes -= len; |
501 | kfree_skb(skb); | 492 | kfree_skb(skb); |
502 | } | 493 | } |
503 | |||
504 | skb = next; | ||
505 | } | 494 | } |
506 | return 0; | 495 | return 0; |
507 | } | 496 | } |