Merge tag 'dmaengine-fix-4.6-rc4' of git://git.infradead.org/users/vkoul/slave-dma
[deliverable/linux.git] / net / core / dev.c
index 8cba3d852f251c503b193823b71b27aaef3fb3ae..77a71cd68535fc02ae939168934fa4fb4f419644 100644 (file)
@@ -3829,8 +3829,14 @@ static void net_tx_action(struct softirq_action *h)
                                trace_consume_skb(skb);
                        else
                                trace_kfree_skb(skb, net_tx_action);
-                       __kfree_skb(skb);
+
+                       if (skb->fclone != SKB_FCLONE_UNAVAILABLE)
+                               __kfree_skb(skb);
+                       else
+                               __kfree_skb_defer(skb);
                }
+
+               __kfree_skb_flush();
        }
 
        if (sd->output_queue) {
@@ -4154,7 +4160,10 @@ ncls:
                        ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
        } else {
 drop:
-               atomic_long_inc(&skb->dev->rx_dropped);
+               if (!deliver_exact)
+                       atomic_long_inc(&skb->dev->rx_dropped);
+               else
+                       atomic_long_inc(&skb->dev->rx_nohandler);
                kfree_skb(skb);
                /* Jamal, now you will not able to escape explaining
                 * me how you were going to use this. :-)
@@ -4429,7 +4438,8 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
                NAPI_GRO_CB(skb)->same_flow = 0;
                NAPI_GRO_CB(skb)->flush = 0;
                NAPI_GRO_CB(skb)->free = 0;
-               NAPI_GRO_CB(skb)->udp_mark = 0;
+               NAPI_GRO_CB(skb)->encap_mark = 0;
+               NAPI_GRO_CB(skb)->is_fou = 0;
                NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
 
                /* Setup for GRO checksum validation */
@@ -5152,6 +5162,7 @@ static void net_rx_action(struct softirq_action *h)
                }
        }
 
+       __kfree_skb_flush();
        local_irq_disable();
 
        list_splice_tail_init(&sd->poll_list, &list);
@@ -5379,12 +5390,12 @@ void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)
 {
        struct netdev_adjacent *lower;
 
-       lower = list_entry((*iter)->next, struct netdev_adjacent, list);
+       lower = list_entry(*iter, struct netdev_adjacent, list);
 
        if (&lower->list == &dev->adj_list.lower)
                return NULL;
 
-       *iter = &lower->list;
+       *iter = lower->list.next;
 
        return lower->dev;
 }
@@ -6435,6 +6446,7 @@ EXPORT_SYMBOL(dev_get_phys_port_id);
  *     dev_get_phys_port_name - Get device physical port name
  *     @dev: device
  *     @name: port name
+ *     @len: limit of bytes to copy to name
  *
  *     Get device physical port name
  */
@@ -7253,24 +7265,31 @@ void netdev_run_todo(void)
        }
 }
 
-/* Convert net_device_stats to rtnl_link_stats64.  They have the same
- * fields in the same order, with only the type differing.
+/* Convert net_device_stats to rtnl_link_stats64. rtnl_link_stats64 has
+ * all the same fields in the same order as net_device_stats, with only
+ * the type differing, but rtnl_link_stats64 may have additional fields
+ * at the end for newer counters.
  */
 void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64,
                             const struct net_device_stats *netdev_stats)
 {
 #if BITS_PER_LONG == 64
-       BUILD_BUG_ON(sizeof(*stats64) != sizeof(*netdev_stats));
+       BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats));
        memcpy(stats64, netdev_stats, sizeof(*stats64));
+       /* zero out counters that only exist in rtnl_link_stats64 */
+       memset((char *)stats64 + sizeof(*netdev_stats), 0,
+              sizeof(*stats64) - sizeof(*netdev_stats));
 #else
-       size_t i, n = sizeof(*stats64) / sizeof(u64);
+       size_t i, n = sizeof(*netdev_stats) / sizeof(unsigned long);
        const unsigned long *src = (const unsigned long *)netdev_stats;
        u64 *dst = (u64 *)stats64;
 
-       BUILD_BUG_ON(sizeof(*netdev_stats) / sizeof(unsigned long) !=
-                    sizeof(*stats64) / sizeof(u64));
+       BUILD_BUG_ON(n > sizeof(*stats64) / sizeof(u64));
        for (i = 0; i < n; i++)
                dst[i] = src[i];
+       /* zero out counters that only exist in rtnl_link_stats64 */
+       memset((char *)stats64 + n * sizeof(u64), 0,
+              sizeof(*stats64) - n * sizeof(u64));
 #endif
 }
 EXPORT_SYMBOL(netdev_stats_to_stats64);
@@ -7300,6 +7319,7 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
        }
        storage->rx_dropped += atomic_long_read(&dev->rx_dropped);
        storage->tx_dropped += atomic_long_read(&dev->tx_dropped);
+       storage->rx_nohandler += atomic_long_read(&dev->rx_nohandler);
        return storage;
 }
 EXPORT_SYMBOL(dev_get_stats);
@@ -7422,8 +7442,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
        dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM;
        setup(dev);
 
-       if (!dev->tx_queue_len)
+       if (!dev->tx_queue_len) {
                dev->priv_flags |= IFF_NO_QUEUE;
+               dev->tx_queue_len = 1;
+       }
 
        dev->num_tx_queues = txqs;
        dev->real_num_tx_queues = txqs;
This page took 0.044329 seconds and 5 git commands to generate.