net: add a noref bit on skb dst
[firefly-linux-kernel-4.4.55.git] / net / core / dev.c
index 9bf1cccb067e3c2fa40ea4a8ac1e6a22fc6630fd..6c820650b80fbe63105303eed14d92fc0115a5a8 100644 (file)
@@ -1454,7 +1454,7 @@ void net_disable_timestamp(void)
 }
 EXPORT_SYMBOL(net_disable_timestamp);
 
-static inline void net_timestamp(struct sk_buff *skb)
+static inline void net_timestamp_set(struct sk_buff *skb)
 {
        if (atomic_read(&netstamp_needed))
                __net_timestamp(skb);
@@ -1462,6 +1462,12 @@ static inline void net_timestamp(struct sk_buff *skb)
                skb->tstamp.tv64 = 0;
 }
 
+static inline void net_timestamp_check(struct sk_buff *skb)
+{
+       if (!skb->tstamp.tv64 && atomic_read(&netstamp_needed))
+               __net_timestamp(skb);
+}
+
 /**
  * dev_forward_skb - loopback an skb to another netif
  *
@@ -1470,7 +1476,7 @@ static inline void net_timestamp(struct sk_buff *skb)
  *
  * return values:
  *     NET_RX_SUCCESS  (no congestion)
- *     NET_RX_DROP     (packet was dropped)
+ *     NET_RX_DROP     (packet was dropped, but freed)
  *
  * dev_forward_skb can be used for injecting an skb from the
  * start_xmit function of one device into the receive queue
@@ -1484,12 +1490,11 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
 {
        skb_orphan(skb);
 
-       if (!(dev->flags & IFF_UP))
-               return NET_RX_DROP;
-
-       if (skb->len > (dev->mtu + dev->hard_header_len))
+       if (!(dev->flags & IFF_UP) ||
+           (skb->len > (dev->mtu + dev->hard_header_len))) {
+               kfree_skb(skb);
                return NET_RX_DROP;
-
+       }
        skb_set_dev(skb, dev);
        skb->tstamp.tv64 = 0;
        skb->pkt_type = PACKET_HOST;
@@ -1509,9 +1514,9 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 
 #ifdef CONFIG_NET_CLS_ACT
        if (!(skb->tstamp.tv64 && (G_TC_FROM(skb->tc_verd) & AT_INGRESS)))
-               net_timestamp(skb);
+               net_timestamp_set(skb);
 #else
-       net_timestamp(skb);
+       net_timestamp_set(skb);
 #endif
 
        rcu_read_lock();
@@ -1557,8 +1562,9 @@ static inline void __netif_reschedule(struct Qdisc *q)
 
        local_irq_save(flags);
        sd = &__get_cpu_var(softnet_data);
-       q->next_sched = sd->output_queue;
-       sd->output_queue = q;
+       q->next_sched = NULL;
+       *sd->output_queue_tailp = q;
+       sd->output_queue_tailp = &q->next_sched;
        raise_softirq_irqoff(NET_TX_SOFTIRQ);
        local_irq_restore(flags);
 }
@@ -1902,13 +1908,6 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                if (!list_empty(&ptype_all))
                        dev_queue_xmit_nit(skb, dev);
 
-               if (netif_needs_gso(dev, skb)) {
-                       if (unlikely(dev_gso_segment(skb)))
-                               goto out_kfree_skb;
-                       if (skb->next)
-                               goto gso;
-               }
-
                /*
                 * If device doesnt need skb->dst, release it right now while
                 * its hot in this cpu cache
@@ -1917,6 +1916,14 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        skb_dst_drop(skb);
 
                skb_orphan_try(skb);
+
+               if (netif_needs_gso(dev, skb)) {
+                       if (unlikely(dev_gso_segment(skb)))
+                               goto out_kfree_skb;
+                       if (skb->next)
+                               goto gso;
+               }
+
                rc = ops->ndo_start_xmit(skb, dev);
                if (rc == NETDEV_TX_OK)
                        txq_trans_update(txq);
@@ -2045,6 +2052,8 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
                 * waiting to be sent out; and the qdisc is not running -
                 * xmit the skb directly.
                 */
+               if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE))
+                       skb_dst_force(skb);
                __qdisc_update_bstats(q, skb->len);
                if (sch_direct_xmit(skb, q, dev, txq, root_lock))
                        __qdisc_run(q);
@@ -2053,6 +2062,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
 
                rc = NET_XMIT_SUCCESS;
        } else {
+               skb_dst_force(skb);
                rc = qdisc_enqueue_root(skb, q);
                qdisc_run(q);
        }
@@ -2200,10 +2210,17 @@ EXPORT_SYMBOL(dev_queue_xmit);
   =======================================================================*/
 
 int netdev_max_backlog __read_mostly = 1000;
+int netdev_tstamp_prequeue __read_mostly = 1;
 int netdev_budget __read_mostly = 300;
 int weight_p __read_mostly = 64;            /* old backlog weight */
 
-DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
+/* Called with irq disabled */
+static inline void ____napi_schedule(struct softnet_data *sd,
+                                    struct napi_struct *napi)
+{
+       list_add_tail(&napi->poll_list, &sd->poll_list);
+       __raise_softirq_irqoff(NET_RX_SOFTIRQ);
+}
 
 #ifdef CONFIG_RPS
 
@@ -2228,7 +2245,11 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
        int cpu = -1;
        u8 ip_proto;
        u16 tcpu;
-       u32 addr1, addr2, ports, ihl;
+       u32 addr1, addr2, ihl;
+       union {
+               u32 v32;
+               u16 v16[2];
+       } ports;
 
        if (skb_rx_queue_recorded(skb)) {
                u16 index = skb_get_rx_queue(skb);
@@ -2274,7 +2295,6 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
        default:
                goto done;
        }
-       ports = 0;
        switch (ip_proto) {
        case IPPROTO_TCP:
        case IPPROTO_UDP:
@@ -2284,25 +2304,20 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
        case IPPROTO_SCTP:
        case IPPROTO_UDPLITE:
                if (pskb_may_pull(skb, (ihl * 4) + 4)) {
-                       __be16 *hports = (__be16 *) (skb->data + (ihl * 4));
-                       u32 sport, dport;
-
-                       sport = (__force u16) hports[0];
-                       dport = (__force u16) hports[1];
-                       if (dport < sport)
-                               swap(sport, dport);
-                       ports = (sport << 16) + dport;
+                       ports.v32 = * (__force u32 *) (skb->data + (ihl * 4));
+                       if (ports.v16[1] < ports.v16[0])
+                               swap(ports.v16[0], ports.v16[1]);
+                       break;
                }
-               break;
-
        default:
+               ports.v32 = 0;
                break;
        }
 
        /* get a consistent hash (same value on both flow directions) */
        if (addr2 < addr1)
                swap(addr1, addr2);
-       skb->rxhash = jhash_3words(addr1, addr2, ports, hashrnd);
+       skb->rxhash = jhash_3words(addr1, addr2, ports.v32, hashrnd);
        if (!skb->rxhash)
                skb->rxhash = 1;
 
@@ -2365,8 +2380,8 @@ static void rps_trigger_softirq(void *data)
 {
        struct softnet_data *sd = data;
 
-       __napi_schedule(&sd->backlog);
-       __get_cpu_var(netdev_rx_stat).received_rps++;
+       ____napi_schedule(sd, &sd->backlog);
+       sd->received_rps++;
 }
 
 #endif /* CONFIG_RPS */
@@ -2405,32 +2420,34 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
        sd = &per_cpu(softnet_data, cpu);
 
        local_irq_save(flags);
-       __get_cpu_var(netdev_rx_stat).total++;
 
        rps_lock(sd);
-       if (sd->input_pkt_queue.qlen <= netdev_max_backlog) {
-               if (sd->input_pkt_queue.qlen) {
+       if (skb_queue_len(&sd->input_pkt_queue) <= netdev_max_backlog) {
+               if (skb_queue_len(&sd->input_pkt_queue)) {
 enqueue:
                        __skb_queue_tail(&sd->input_pkt_queue, skb);
 #ifdef CONFIG_RPS
-                       *qtail = sd->input_queue_head + sd->input_pkt_queue.qlen;
+                       *qtail = sd->input_queue_head +
+                                       skb_queue_len(&sd->input_pkt_queue);
 #endif
                        rps_unlock(sd);
                        local_irq_restore(flags);
                        return NET_RX_SUCCESS;
                }
 
-               /* Schedule NAPI for backlog device */
-               if (napi_schedule_prep(&sd->backlog)) {
+               /* Schedule NAPI for backlog device
+                * We can use non atomic operation since we own the queue lock
+                */
+               if (!__test_and_set_bit(NAPI_STATE_SCHED, &sd->backlog.state)) {
                        if (!rps_ipi_queued(sd))
-                               __napi_schedule(&sd->backlog);
+                               ____napi_schedule(sd, &sd->backlog);
                }
                goto enqueue;
        }
 
+       sd->dropped++;
        rps_unlock(sd);
 
-       __get_cpu_var(netdev_rx_stat).dropped++;
        local_irq_restore(flags);
 
        kfree_skb(skb);
@@ -2460,8 +2477,8 @@ int netif_rx(struct sk_buff *skb)
        if (netpoll_rx(skb))
                return NET_RX_DROP;
 
-       if (!skb->tstamp.tv64)
-               net_timestamp(skb);
+       if (netdev_tstamp_prequeue)
+               net_timestamp_check(skb);
 
 #ifdef CONFIG_RPS
        {
@@ -2530,6 +2547,7 @@ static void net_tx_action(struct softirq_action *h)
                local_irq_disable();
                head = sd->output_queue;
                sd->output_queue = NULL;
+               sd->output_queue_tailp = &sd->output_queue;
                local_irq_enable();
 
                while (head) {
@@ -2606,7 +2624,8 @@ static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
 #endif
 
 #if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
-struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly;
+struct sk_buff *(*macvlan_handle_frame_hook)(struct macvlan_port *p,
+                                            struct sk_buff *skb) __read_mostly;
 EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook);
 
 static inline struct sk_buff *handle_macvlan(struct sk_buff *skb,
@@ -2614,14 +2633,17 @@ static inline struct sk_buff *handle_macvlan(struct sk_buff *skb,
                                             int *ret,
                                             struct net_device *orig_dev)
 {
-       if (skb->dev->macvlan_port == NULL)
+       struct macvlan_port *port;
+
+       port = rcu_dereference(skb->dev->macvlan_port);
+       if (!port)
                return skb;
 
        if (*pt_prev) {
                *ret = deliver_skb(skb, *pt_prev, orig_dev);
                *pt_prev = NULL;
        }
-       return macvlan_handle_frame_hook(skb);
+       return macvlan_handle_frame_hook(port, skb);
 }
 #else
 #define handle_macvlan(skb, pt_prev, ret, orig_dev)    (skb)
@@ -2781,8 +2803,8 @@ static int __netif_receive_skb(struct sk_buff *skb)
        int ret = NET_RX_DROP;
        __be16 type;
 
-       if (!skb->tstamp.tv64)
-               net_timestamp(skb);
+       if (!netdev_tstamp_prequeue)
+               net_timestamp_check(skb);
 
        if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb))
                return NET_RX_SUCCESS;
@@ -2804,7 +2826,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
                        skb->dev = master;
        }
 
-       __get_cpu_var(netdev_rx_stat).total++;
+       __get_cpu_var(softnet_data).processed++;
 
        skb_reset_network_header(skb);
        skb_reset_transport_header(skb);
@@ -2900,23 +2922,28 @@ out:
  */
 int netif_receive_skb(struct sk_buff *skb)
 {
+       if (netdev_tstamp_prequeue)
+               net_timestamp_check(skb);
+
 #ifdef CONFIG_RPS
-       struct rps_dev_flow voidflow, *rflow = &voidflow;
-       int cpu, ret;
+       {
+               struct rps_dev_flow voidflow, *rflow = &voidflow;
+               int cpu, ret;
 
-       rcu_read_lock();
+               rcu_read_lock();
 
-       cpu = get_rps_cpu(skb->dev, skb, &rflow);
+               cpu = get_rps_cpu(skb->dev, skb, &rflow);
 
-       if (cpu >= 0) {
-               ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail);
-               rcu_read_unlock();
-       } else {
-               rcu_read_unlock();
-               ret = __netif_receive_skb(skb);
-       }
+               if (cpu >= 0) {
+                       ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail);
+                       rcu_read_unlock();
+               } else {
+                       rcu_read_unlock();
+                       ret = __netif_receive_skb(skb);
+               }
 
-       return ret;
+               return ret;
+       }
 #else
        return __netif_receive_skb(skb);
 #endif
@@ -2933,13 +2960,21 @@ static void flush_backlog(void *arg)
        struct sk_buff *skb, *tmp;
 
        rps_lock(sd);
-       skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp)
+       skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) {
                if (skb->dev == dev) {
                        __skb_unlink(skb, &sd->input_pkt_queue);
                        kfree_skb(skb);
-                       input_queue_head_incr(sd);
+                       input_queue_head_add(sd, 1);
                }
+       }
        rps_unlock(sd);
+
+       skb_queue_walk_safe(&sd->process_queue, skb, tmp) {
+               if (skb->dev == dev) {
+                       __skb_unlink(skb, &sd->process_queue);
+                       kfree_skb(skb);
+               }
+       }
 }
 
 static int napi_gro_complete(struct sk_buff *skb)
@@ -3242,30 +3277,85 @@ gro_result_t napi_gro_frags(struct napi_struct *napi)
 }
 EXPORT_SYMBOL(napi_gro_frags);
 
+/*
+ * net_rps_action sends any pending IPI's for rps.
+ * Note: called with local irq disabled, but exits with local irq enabled.
+ */
+static void net_rps_action_and_irq_enable(struct softnet_data *sd)
+{
+#ifdef CONFIG_RPS
+       struct softnet_data *remsd = sd->rps_ipi_list;
+
+       if (remsd) {
+               sd->rps_ipi_list = NULL;
+
+               local_irq_enable();
+
+               /* Send pending IPI's to kick RPS processing on remote cpus. */
+               while (remsd) {
+                       struct softnet_data *next = remsd->rps_ipi_next;
+
+                       if (cpu_online(remsd->cpu))
+                               __smp_call_function_single(remsd->cpu,
+                                                          &remsd->csd, 0);
+                       remsd = next;
+               }
+       } else
+#endif
+               local_irq_enable();
+}
+
 static int process_backlog(struct napi_struct *napi, int quota)
 {
        int work = 0;
-       struct softnet_data *sd = &__get_cpu_var(softnet_data);
+       struct softnet_data *sd = container_of(napi, struct softnet_data, backlog);
 
+#ifdef CONFIG_RPS
+       /* Check if we have pending ipi, its better to send them now,
+        * not waiting net_rx_action() end.
+        */
+       if (sd->rps_ipi_list) {
+               local_irq_disable();
+               net_rps_action_and_irq_enable(sd);
+       }
+#endif
        napi->weight = weight_p;
-       do {
+       local_irq_disable();
+       while (work < quota) {
                struct sk_buff *skb;
+               unsigned int qlen;
 
-               local_irq_disable();
-               rps_lock(sd);
-               skb = __skb_dequeue(&sd->input_pkt_queue);
-               if (!skb) {
-                       __napi_complete(napi);
-                       rps_unlock(sd);
+               while ((skb = __skb_dequeue(&sd->process_queue))) {
                        local_irq_enable();
-                       break;
+                       __netif_receive_skb(skb);
+                       if (++work >= quota)
+                               return work;
+                       local_irq_disable();
                }
-               input_queue_head_incr(sd);
-               rps_unlock(sd);
-               local_irq_enable();
 
-               __netif_receive_skb(skb);
-       } while (++work < quota);
+               rps_lock(sd);
+               qlen = skb_queue_len(&sd->input_pkt_queue);
+               if (qlen) {
+                       input_queue_head_add(sd, qlen);
+                       skb_queue_splice_tail_init(&sd->input_pkt_queue,
+                                                  &sd->process_queue);
+               }
+               if (qlen < quota - work) {
+                       /*
+                        * Inline a custom version of __napi_complete().
+                        * only current cpu owns and manipulates this napi,
+                        * and NAPI_STATE_SCHED is the only possible flag set on backlog.
+                        * we can use a plain write instead of clear_bit(),
+                        * and we dont need an smp_mb() memory barrier.
+                        */
+                       list_del(&napi->poll_list);
+                       napi->state = 0;
+
+                       quota = work + qlen;
+               }
+               rps_unlock(sd);
+       }
+       local_irq_enable();
 
        return work;
 }
@@ -3281,8 +3371,7 @@ void __napi_schedule(struct napi_struct *n)
        unsigned long flags;
 
        local_irq_save(flags);
-       list_add_tail(&n->poll_list, &__get_cpu_var(softnet_data).poll_list);
-       __raise_softirq_irqoff(NET_RX_SOFTIRQ);
+       ____napi_schedule(&__get_cpu_var(softnet_data), n);
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL(__napi_schedule);
@@ -3353,45 +3442,16 @@ void netif_napi_del(struct napi_struct *napi)
 }
 EXPORT_SYMBOL(netif_napi_del);
 
-/*
- * net_rps_action sends any pending IPI's for rps.
- * Note: called with local irq disabled, but exits with local irq enabled.
- */
-static void net_rps_action_and_irq_disable(void)
-{
-#ifdef CONFIG_RPS
-       struct softnet_data *sd = &__get_cpu_var(softnet_data);
-       struct softnet_data *remsd = sd->rps_ipi_list;
-
-       if (remsd) {
-               sd->rps_ipi_list = NULL;
-
-               local_irq_enable();
-
-               /* Send pending IPI's to kick RPS processing on remote cpus. */
-               while (remsd) {
-                       struct softnet_data *next = remsd->rps_ipi_next;
-
-                       if (cpu_online(remsd->cpu))
-                               __smp_call_function_single(remsd->cpu,
-                                                          &remsd->csd, 0);
-                       remsd = next;
-               }
-       } else
-#endif
-               local_irq_enable();
-}
-
 static void net_rx_action(struct softirq_action *h)
 {
-       struct list_head *list = &__get_cpu_var(softnet_data).poll_list;
+       struct softnet_data *sd = &__get_cpu_var(softnet_data);
        unsigned long time_limit = jiffies + 2;
        int budget = netdev_budget;
        void *have;
 
        local_irq_disable();
 
-       while (!list_empty(list)) {
+       while (!list_empty(&sd->poll_list)) {
                struct napi_struct *n;
                int work, weight;
 
@@ -3409,7 +3469,7 @@ static void net_rx_action(struct softirq_action *h)
                 * entries to the tail of this list, and only ->poll()
                 * calls can remove this head entry from the list.
                 */
-               n = list_first_entry(list, struct napi_struct, poll_list);
+               n = list_first_entry(&sd->poll_list, struct napi_struct, poll_list);
 
                have = netpoll_poll_lock(n);
 
@@ -3444,13 +3504,13 @@ static void net_rx_action(struct softirq_action *h)
                                napi_complete(n);
                                local_irq_disable();
                        } else
-                               list_move_tail(&n->poll_list, list);
+                               list_move_tail(&n->poll_list, &sd->poll_list);
                }
 
                netpoll_poll_unlock(have);
        }
 out:
-       net_rps_action_and_irq_disable();
+       net_rps_action_and_irq_enable(sd);
 
 #ifdef CONFIG_NET_DMA
        /*
@@ -3463,7 +3523,7 @@ out:
        return;
 
 softnet_break:
-       __get_cpu_var(netdev_rx_stat).time_squeeze++;
+       sd->time_squeeze++;
        __raise_softirq_irqoff(NET_RX_SOFTIRQ);
        goto out;
 }
@@ -3664,17 +3724,17 @@ static int dev_seq_show(struct seq_file *seq, void *v)
        return 0;
 }
 
-static struct netif_rx_stats *softnet_get_online(loff_t *pos)
+static struct softnet_data *softnet_get_online(loff_t *pos)
 {
-       struct netif_rx_stats *rc = NULL;
+       struct softnet_data *sd = NULL;
 
        while (*pos < nr_cpu_ids)
                if (cpu_online(*pos)) {
-                       rc = &per_cpu(netdev_rx_stat, *pos);
+                       sd = &per_cpu(softnet_data, *pos);
                        break;
                } else
                        ++*pos;
-       return rc;
+       return sd;
 }
 
 static void *softnet_seq_start(struct seq_file *seq, loff_t *pos)
@@ -3694,12 +3754,12 @@ static void softnet_seq_stop(struct seq_file *seq, void *v)
 
 static int softnet_seq_show(struct seq_file *seq, void *v)
 {
-       struct netif_rx_stats *s = v;
+       struct softnet_data *sd = v;
 
        seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
-                  s->total, s->dropped, s->time_squeeze, 0,
+                  sd->processed, sd->dropped, sd->time_squeeze, 0,
                   0, 0, 0, 0, /* was fastroute */
-                  s->cpu_collision, s->received_rps);
+                  sd->cpu_collision, sd->received_rps);
        return 0;
 }
 
@@ -5587,7 +5647,6 @@ static int dev_cpu_callback(struct notifier_block *nfb,
                            void *ocpu)
 {
        struct sk_buff **list_skb;
-       struct Qdisc **list_net;
        struct sk_buff *skb;
        unsigned int cpu, oldcpu = (unsigned long)ocpu;
        struct softnet_data *sd, *oldsd;
@@ -5608,13 +5667,13 @@ static int dev_cpu_callback(struct notifier_block *nfb,
        *list_skb = oldsd->completion_queue;
        oldsd->completion_queue = NULL;
 
-       /* Find end of our output_queue. */
-       list_net = &sd->output_queue;
-       while (*list_net)
-               list_net = &(*list_net)->next_sched;
        /* Append output queue from offline CPU. */
-       *list_net = oldsd->output_queue;
-       oldsd->output_queue = NULL;
+       if (oldsd->output_queue) {
+               *sd->output_queue_tailp = oldsd->output_queue;
+               sd->output_queue_tailp = oldsd->output_queue_tailp;
+               oldsd->output_queue = NULL;
+               oldsd->output_queue_tailp = &oldsd->output_queue;
+       }
 
        raise_softirq_irqoff(NET_TX_SOFTIRQ);
        local_irq_enable();
@@ -5622,8 +5681,10 @@ static int dev_cpu_callback(struct notifier_block *nfb,
        /* Process offline CPU's input_pkt_queue */
        while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) {
                netif_rx(skb);
-               input_queue_head_incr(oldsd);
+               input_queue_head_add(oldsd, 1);
        }
+       while ((skb = __skb_dequeue(&oldsd->process_queue)))
+               netif_rx(skb);
 
        return NOTIFY_OK;
 }
@@ -5841,10 +5902,13 @@ static int __init net_dev_init(void)
        for_each_possible_cpu(i) {
                struct softnet_data *sd = &per_cpu(softnet_data, i);
 
+               memset(sd, 0, sizeof(*sd));
                skb_queue_head_init(&sd->input_pkt_queue);
+               skb_queue_head_init(&sd->process_queue);
                sd->completion_queue = NULL;
                INIT_LIST_HEAD(&sd->poll_list);
-
+               sd->output_queue = NULL;
+               sd->output_queue_tailp = &sd->output_queue;
 #ifdef CONFIG_RPS
                sd->csd.func = rps_trigger_softirq;
                sd->csd.info = sd;