]> git.itanic.dy.fi Git - linux-stable/commitdiff
net: hns3: implement ndo_features_check ops for hns3 driver
authorYunsheng Lin <linyunsheng@huawei.com>
Thu, 19 Dec 2019 06:57:44 +0000 (14:57 +0800)
committerDavid S. Miller <davem@davemloft.net>
Sat, 21 Dec 2019 05:20:39 +0000 (21:20 -0800)
The function netif_skb_features() will disable the TSO feature
by using dflt_features_check() if the driver does not implement
ndo_features_check ops, which may cause performance degradation
problem when hns3 hardware can do multiple tagged TSO.

Also, the HNS3 hardware only supports checksum on the SKB with
a max header len of 480 bytes, so remove the checksum and TSO
related features when the header len is over 480 bytes.

Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c

index 5679a0cef975ce966e308ec2b710c5f3bfa65235..840a1fbc4d2e6d34b2a0087be20258248c527343 100644 (file)
@@ -1556,6 +1556,37 @@ static int hns3_nic_set_features(struct net_device *netdev,
        return 0;
 }
 
+static netdev_features_t hns3_features_check(struct sk_buff *skb,
+                                            struct net_device *dev,
+                                            netdev_features_t features)
+{
+#define HNS3_MAX_HDR_LEN       480U
+#define HNS3_MAX_L4_HDR_LEN    60U
+
+       size_t len;
+
+       if (skb->ip_summed != CHECKSUM_PARTIAL)
+               return features;
+
+       if (skb->encapsulation)
+               len = skb_inner_transport_header(skb) - skb->data;
+       else
+               len = skb_transport_header(skb) - skb->data;
+
+       /* Assume L4 is 60 byte as TCP is the only protocol with a
+        * a flexible value, and it's max len is 60 bytes.
+        */
+       len += HNS3_MAX_L4_HDR_LEN;
+
+       /* Hardware only supports checksum on the skb with a max header
+        * len of 480 bytes.
+        */
+       if (len > HNS3_MAX_HDR_LEN)
+               features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+
+       return features;
+}
+
 static void hns3_nic_get_stats64(struct net_device *netdev,
                                 struct rtnl_link_stats64 *stats)
 {
@@ -1970,6 +2001,7 @@ static const struct net_device_ops hns3_nic_netdev_ops = {
        .ndo_do_ioctl           = hns3_nic_do_ioctl,
        .ndo_change_mtu         = hns3_nic_change_mtu,
        .ndo_set_features       = hns3_nic_set_features,
+       .ndo_features_check     = hns3_features_check,
        .ndo_get_stats64        = hns3_nic_get_stats64,
        .ndo_setup_tc           = hns3_nic_setup_tc,
        .ndo_set_rx_mode        = hns3_nic_set_rx_mode,