]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
i40evf: Be much more verbose about what we can and cannot offload
authorAlexander Duyck <alexander.h.duyck@intel.com>
Wed, 21 Dec 2016 22:07:35 +0000 (17:07 -0500)
committerDhaval Giani <dhaval.giani@oracle.com>
Wed, 8 Mar 2017 00:41:06 +0000 (19:41 -0500)
Orabug: 24568124

This change makes it so that we are much more robust about defining what we
can and cannot offload.  Previously we were performing no checks.  This
should bring us up to parity with the i40e PF driver.

In addition the device only supports GSO as long as the MSS is 64 or
greater.  We were not checking this so an MSS less than that was resulting
in Tx hangs.

Change-ID: If533553ec92fc6ba694eab6ac81fdaf3004f3592
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
(cherry picked from commit 06fc016c43eac5d88a53677ed0db7e28a7a1b4bd)
Signed-off-by: Brian Maly <brian.maly@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
Signed-off-by: Dhaval Giani <dhaval.giani@oracle.com>
drivers/net/ethernet/intel/i40evf/i40evf_main.c
drivers/net/ethernet/intel/i40evf/kcompat.h

index 45568b0bcd3fa92683bf474f82467d6d2f4abd28..24c1cc5cc448e8117c8f7ebe399795996c922930 100644 (file)
@@ -26,6 +26,8 @@
 
 #include "i40evf.h"
 #include "i40e_prototype.h"
+#include "kcompat.h"
+
 static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter);
 static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter);
 static int i40evf_close(struct net_device *netdev);
@@ -2176,6 +2178,64 @@ static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
        return 0;
 }
 
+/**
+ * i40evf_features_check - Validate encapsulated packet conforms to limits
+ * @skb: skb buff
+ * @netdev: This physical port's netdev
+ * @features: Offload features that the stack believes apply
+ **/
+static netdev_features_t i40evf_features_check(struct sk_buff *skb,
+                                              struct net_device *dev,
+                                              netdev_features_t features)
+{
+       size_t len;
+
+       /* No point in doing any of this if neither checksum nor GSO are
+        * being requested for this frame.  We can rule out both by just
+        * checking for CHECKSUM_PARTIAL
+        */
+       if (skb->ip_summed != CHECKSUM_PARTIAL)
+               return features;
+
+       /* We cannot support GSO if the MSS is going to be less than
+        * 64 bytes.  If it is then we need to drop support for GSO.
+        */
+       if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
+               features &= ~NETIF_F_GSO_MASK;
+
+       /* MACLEN can support at most 63 words */
+       len = skb_network_header(skb) - skb->data;
+       if (len & ~(63 * 2))
+               goto out_err;
+
+       /* IPLEN and EIPLEN can support at most 127 dwords */
+       len = skb_transport_header(skb) - skb_network_header(skb);
+       if (len & ~(127 * 4))
+               goto out_err;
+
+       if (skb->encapsulation) {
+               /* L4TUNLEN can support 127 words */
+               len = skb_inner_network_header(skb) - skb_transport_header(skb);
+               if (len & ~(127 * 2))
+                       goto out_err;
+
+               /* IPLEN can support at most 127 dwords */
+               len = skb_inner_transport_header(skb) -
+                     skb_inner_network_header(skb);
+               if (len & ~(127 * 4))
+                       goto out_err;
+       }
+
+       /* No need to validate L4LEN as TCP is the only protocol with a
+        * a flexible value and we support all possible values supported
+        * by TCP, which is at most 15 dwords
+        */
+
+       return features;
+out_err:
+       return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+}
+
 #define I40EVF_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_TX |\
                              NETIF_F_HW_VLAN_CTAG_RX |\
                              NETIF_F_HW_VLAN_CTAG_FILTER)
@@ -2210,6 +2270,7 @@ static const struct net_device_ops i40evf_netdev_ops = {
        .ndo_tx_timeout         = i40evf_tx_timeout,
        .ndo_vlan_rx_add_vid    = i40evf_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = i40evf_vlan_rx_kill_vid,
+       .ndo_features_check     = i40evf_features_check,
        .ndo_fix_features       = i40evf_fix_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = i40evf_netpoll,
index efec554cdab34ad36b4146eb3170da22ec102f52..6fd9e05f3931017f792d61d3b35d6de90553d1d3 100644 (file)
 
 #endif
 
+#define NETIF_F_CSUM_MASK      (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
+                                NETIF_F_HW_CSUM)
+
+
 static inline void csum_replace_by_diff(__sum16 *sum, __wsum diff)
 {
        *sum = csum_fold(csum_add(diff, ~csum_unfold(*sum)));