From 927c414f8361ffc1161826c8de8c7fb622ea4fef Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 3 Aug 2008 21:29:57 -0700 Subject: [PATCH] --- yaml --- r: 107730 b: refs/heads/master c: 6e583ce5242f32e925dcb198f7123256d0798370 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/net/core/dev.c | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/[refs] b/[refs] index 39f689ece63f..77503cbb0ea6 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 283d07ac201ee9f8aa6dc6f7519436b48760baff +refs/heads/master: 6e583ce5242f32e925dcb198f7123256d0798370 diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index cbf80098980c..fc6c9881eca8 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -1909,7 +1909,6 @@ int netif_rx(struct sk_buff *skb) if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { if (queue->input_pkt_queue.qlen) { enqueue: - dev_hold(skb->dev); __skb_queue_tail(&queue->input_pkt_queue, skb); local_irq_restore(flags); return NET_RX_SUCCESS; @@ -2270,6 +2269,20 @@ int netif_receive_skb(struct sk_buff *skb) return ret; } +/* Network device is going away, flush any packets still pending */ +static void flush_backlog(void *arg) +{ + struct net_device *dev = arg; + struct softnet_data *queue = &__get_cpu_var(softnet_data); + struct sk_buff *skb, *tmp; + + skb_queue_walk_safe(&queue->input_pkt_queue, skb, tmp) + if (skb->dev == dev) { + __skb_unlink(skb, &queue->input_pkt_queue); + kfree_skb(skb); + } +} + static int process_backlog(struct napi_struct *napi, int quota) { int work = 0; @@ -2279,7 +2292,6 @@ static int process_backlog(struct napi_struct *napi, int quota) napi->weight = weight_p; do { struct sk_buff *skb; - struct net_device *dev; local_irq_disable(); skb = __skb_dequeue(&queue->input_pkt_queue); @@ -2288,14 +2300,9 @@ static int process_backlog(struct napi_struct *napi, int quota) local_irq_enable(); break; } - local_irq_enable(); - dev = skb->dev; - netif_receive_skb(skb); - - dev_put(dev); } while (++work < quota && jiffies == start_time); return work; @@ -4169,6 +4176,8 @@ void netdev_run_todo(void) dev->reg_state = NETREG_UNREGISTERED; + on_each_cpu(flush_backlog, dev, 1); + netdev_wait_allrefs(dev); /* paranoia */