]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/core/dev.c
net: make WARN_ON in dev_disable_lro() useful
[karo-tx-linux.git] / net / core / dev.c
index 3da9fb06d47a658a59ce619f8aaa3d34caaedf26..541f22a035a223daaec4564949bc984a19c411c6 100644 (file)
@@ -1315,7 +1315,8 @@ void dev_disable_lro(struct net_device *dev)
                return;
 
        __ethtool_set_flags(dev, flags & ~ETH_FLAG_LRO);
-       WARN_ON(dev->features & NETIF_F_LRO);
+       if (unlikely(dev->features & NETIF_F_LRO))
+               netdev_WARN(dev, "failed to disable LRO!\n");
 }
 EXPORT_SYMBOL(dev_disable_lro);
 
@@ -2091,7 +2092,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                u32 features;
 
                /*
-                * If device doesnt need skb->dst, release it right now while
+                * If device doesn't need skb->dst, release it right now while
                 * its hot in this cpu cache
                 */
                if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
@@ -2151,7 +2152,7 @@ gso:
                nskb->next = NULL;
 
                /*
-                * If device doesnt need nskb->dst, release it right now while
+                * If device doesn't need nskb->dst, release it right now while
                 * its hot in this cpu cache
                 */
                if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
@@ -2502,8 +2503,8 @@ static inline void ____napi_schedule(struct softnet_data *sd,
 __u32 __skb_get_rxhash(struct sk_buff *skb)
 {
        int nhoff, hash = 0, poff;
-       struct ipv6hdr *ip6;
-       struct iphdr *ip;
+       const struct ipv6hdr *ip6;
+       const struct iphdr *ip;
        u8 ip_proto;
        u32 addr1, addr2, ihl;
        union {
@@ -2518,7 +2519,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb)
                if (!pskb_may_pull(skb, sizeof(*ip) + nhoff))
                        goto done;
 
-               ip = (struct iphdr *) (skb->data + nhoff);
+               ip = (const struct iphdr *) (skb->data + nhoff);
                if (ip->frag_off & htons(IP_MF | IP_OFFSET))
                        ip_proto = 0;
                else
@@ -2531,7 +2532,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb)
                if (!pskb_may_pull(skb, sizeof(*ip6) + nhoff))
                        goto done;
 
-               ip6 = (struct ipv6hdr *) (skb->data + nhoff);
+               ip6 = (const struct ipv6hdr *) (skb->data + nhoff);
                ip_proto = ip6->nexthdr;
                addr1 = (__force u32) ip6->saddr.s6_addr32[3];
                addr2 = (__force u32) ip6->daddr.s6_addr32[3];
@@ -2970,8 +2971,8 @@ EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook);
  * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
  * a compare and 2 stores extra right now if we dont have it on
  * but have CONFIG_NET_CLS_ACT
- * NOTE: This doesnt stop any functionality; if you dont have
- * the ingress scheduler, you just cant add policies on ingress.
+ * NOTE: This doesn't stop any functionality; if you dont have
+ * the ingress scheduler, you just can't add policies on ingress.
  *
  */
 static int ing_filter(struct sk_buff *skb, struct netdev_queue *rxq)
@@ -3130,6 +3131,12 @@ another_round:
 
        __this_cpu_inc(softnet_data.processed);
 
+       if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) {
+               skb = vlan_untag(skb);
+               if (unlikely(!skb))
+                       goto out;
+       }
+
 #ifdef CONFIG_NET_CLS_ACT
        if (skb->tc_verd & TC_NCLS) {
                skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
@@ -3177,7 +3184,7 @@ ncls:
                        ret = deliver_skb(skb, pt_prev, orig_dev);
                        pt_prev = NULL;
                }
-               if (vlan_hwaccel_do_receive(&skb)) {
+               if (vlan_do_receive(&skb)) {
                        ret = __netif_receive_skb(skb);
                        goto out;
                } else if (unlikely(!skb))
@@ -3800,7 +3807,7 @@ static void net_rx_action(struct softirq_action *h)
                 * with netpoll's poll_napi().  Only the entity which
                 * obtains the lock and sees NAPI_STATE_SCHED set will
                 * actually make the ->poll() call.  Therefore we avoid
-                * accidently calling ->poll() when NAPI is not scheduled.
+                * accidentally calling ->poll() when NAPI is not scheduled.
                 */
                work = 0;
                if (test_bit(NAPI_STATE_SCHED, &n->state)) {
@@ -5203,11 +5210,15 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
        }
 
        /* TSO requires that SG is present as well. */
-       if ((features & NETIF_F_TSO) && !(features & NETIF_F_SG)) {
-               netdev_info(dev, "Dropping NETIF_F_TSO since no SG feature.\n");
-               features &= ~NETIF_F_TSO;
+       if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) {
+               netdev_info(dev, "Dropping TSO features since no SG feature.\n");
+               features &= ~NETIF_F_ALL_TSO;
        }
 
+       /* TSO ECN requires that TSO is present as well. */
+       if ((features & NETIF_F_ALL_TSO) == NETIF_F_TSO_ECN)
+               features &= ~NETIF_F_TSO_ECN;
+
        /* Software GSO depends on SG. */
        if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) {
                netdev_info(dev, "Dropping NETIF_F_GSO since no SG feature.\n");
@@ -5236,11 +5247,13 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
 }
 EXPORT_SYMBOL(netdev_fix_features);
 
-void netdev_update_features(struct net_device *dev)
+int __netdev_update_features(struct net_device *dev)
 {
        u32 features;
        int err = 0;
 
+       ASSERT_RTNL();
+
        features = netdev_get_wanted_features(dev);
 
        if (dev->netdev_ops->ndo_fix_features)
@@ -5250,7 +5263,7 @@ void netdev_update_features(struct net_device *dev)
        features = netdev_fix_features(dev, features);
 
        if (dev->features == features)
-               return;
+               return 0;
 
        netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n",
                dev->features, features);
@@ -5258,12 +5271,23 @@ void netdev_update_features(struct net_device *dev)
        if (dev->netdev_ops->ndo_set_features)
                err = dev->netdev_ops->ndo_set_features(dev, features);
 
-       if (!err)
-               dev->features = features;
-       else if (err < 0)
+       if (unlikely(err < 0)) {
                netdev_err(dev,
                        "set_features() failed (%d); wanted 0x%08x, left 0x%08x\n",
                        err, features, dev->features);
+               return -1;
+       }
+
+       if (!err)
+               dev->features = features;
+
+       return 1;
+}
+
+void netdev_update_features(struct net_device *dev)
+{
+       if (__netdev_update_features(dev))
+               netdev_features_change(dev);
 }
 EXPORT_SYMBOL(netdev_update_features);
 
@@ -5414,6 +5438,14 @@ int register_netdevice(struct net_device *dev)
                dev->features &= ~NETIF_F_GSO;
        }
 
+       /* Turn on no cache copy if HW is doing checksum */
+       dev->hw_features |= NETIF_F_NOCACHE_COPY;
+       if ((dev->features & NETIF_F_ALL_CSUM) &&
+           !(dev->features & NETIF_F_NO_CSUM)) {
+               dev->wanted_features |= NETIF_F_NOCACHE_COPY;
+               dev->features |= NETIF_F_NOCACHE_COPY;
+       }
+
        /* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
         * vlan_dev_init() will do the dev->features check, so these features
         * are enabled only if supported by underlying device.
@@ -5430,7 +5462,7 @@ int register_netdevice(struct net_device *dev)
                goto err_uninit;
        dev->reg_state = NETREG_REGISTERED;
 
-       netdev_update_features(dev);
+       __netdev_update_features(dev);
 
        /*
         *      Default initial state at registry is that the
@@ -6171,6 +6203,10 @@ u32 netdev_increment_features(u32 all, u32 one, u32 mask)
                }
        }
 
+       /* If device can't no cache copy, don't do for all */
+       if (!(one & NETIF_F_NOCACHE_COPY))
+               all &= ~NETIF_F_NOCACHE_COPY;
+
        one |= NETIF_F_ALL_CSUM;
 
        one |= all & NETIF_F_ONE_FOR_ALL;
@@ -6336,7 +6372,7 @@ static void __net_exit default_device_exit(struct net *net)
                if (dev->rtnl_link_ops)
                        continue;
 
-               /* Push remaing network devices to init_net */
+               /* Push remaining network devices to init_net */
                snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex);
                err = dev_change_net_namespace(dev, &init_net, fb_name);
                if (err) {