}
 EXPORT_SYMBOL(netif_receive_skb);
 
-/* Network device is going away, flush any packets still pending
- * Called with irqs disabled.
- */
-static void flush_backlog(void *arg)
+struct flush_work {
+       struct net_device *dev;
+       struct work_struct work;
+};
+
+DEFINE_PER_CPU(struct flush_work, flush_works);
+
+/* Network device is going away, flush any packets still pending */
+static void flush_backlog(struct work_struct *work)
 {
-       struct net_device *dev = arg;
-       struct softnet_data *sd = this_cpu_ptr(&softnet_data);
+       struct flush_work *flush = container_of(work, typeof(*flush), work);
+       struct net_device *dev = flush->dev;
        struct sk_buff *skb, *tmp;
+       struct softnet_data *sd;
+
+       local_bh_disable();
+       sd = this_cpu_ptr(&softnet_data);
 
+       local_irq_disable();
        rps_lock(sd);
        skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) {
                if (skb->dev == dev) {
                }
        }
        rps_unlock(sd);
+       local_irq_enable();
 
        skb_queue_walk_safe(&sd->process_queue, skb, tmp) {
                if (skb->dev == dev) {
                        input_queue_head_incr(sd);
                }
        }
+       local_bh_enable();
+}
+
+static void flush_all_backlogs(struct net_device *dev)
+{
+       unsigned int cpu;
+
+       get_online_cpus();
+
+       for_each_online_cpu(cpu) {
+               struct flush_work *flush = per_cpu_ptr(&flush_works, cpu);
+
+               INIT_WORK(&flush->work, flush_backlog);
+               flush->dev = dev;
+               queue_work_on(cpu, system_highpri_wq, &flush->work);
+       }
+
+       for_each_online_cpu(cpu)
+               flush_work(&per_cpu_ptr(&flush_works, cpu)->work);
+
+       put_online_cpus();
 }
 
 static int napi_gro_complete(struct sk_buff *skb)
 
 static int process_backlog(struct napi_struct *napi, int quota)
 {
-       int work = 0;
        struct softnet_data *sd = container_of(napi, struct softnet_data, backlog);
+       bool again = true;
+       int work = 0;
 
        /* Check if we have pending ipi, its better to send them now,
         * not waiting net_rx_action() end.
        }
 
        napi->weight = weight_p;
-       local_irq_disable();
-       while (1) {
+       while (again) {
                struct sk_buff *skb;
 
                while ((skb = __skb_dequeue(&sd->process_queue))) {
                        rcu_read_lock();
-                       local_irq_enable();
                        __netif_receive_skb(skb);
                        rcu_read_unlock();
-                       local_irq_disable();
                        input_queue_head_incr(sd);
-                       if (++work >= quota) {
-                               local_irq_enable();
+                       if (++work >= quota)
                                return work;
-                       }
+
                }
 
+               local_irq_disable();
                rps_lock(sd);
                if (skb_queue_empty(&sd->input_pkt_queue)) {
                        /*
                         * and we dont need an smp_mb() memory barrier.
                         */
                        napi->state = 0;
-                       rps_unlock(sd);
-
-                       break;
+                       again = false;
+               } else {
+                       skb_queue_splice_tail_init(&sd->input_pkt_queue,
+                                                  &sd->process_queue);
                }
-
-               skb_queue_splice_tail_init(&sd->input_pkt_queue,
-                                          &sd->process_queue);
                rps_unlock(sd);
+               local_irq_enable();
        }
-       local_irq_enable();
 
        return work;
 }
                unlist_netdevice(dev);
 
                dev->reg_state = NETREG_UNREGISTERING;
-               on_each_cpu(flush_backlog, dev, 1);
+               flush_all_backlogs(dev);
        }
 
        synchronize_net();