net: hns3: add support for RX completion checksum
authorHuazhong Tan <tanhuazhong@huawei.com>
Sat, 28 Nov 2020 03:51:44 +0000 (11:51 +0800)
committerJakub Kicinski <kuba@kernel.org>
Tue, 1 Dec 2020 23:16:31 +0000 (15:16 -0800)
In some cases (for example ip fragment), hardware will
calculate the checksum of whole packet in RX, and setup
the HNS3_RXD_L2_CSUM_B flag in the descriptor, so add
support to utilize this checksum.

Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c

index 632ad4257b18cba327ab5215909c13c557049429..1647877be14853be9ba5b22053e2bd8f311edac5 100644 (file)
@@ -2798,6 +2798,22 @@ static int hns3_gro_complete(struct sk_buff *skb, u32 l234info)
        return 0;
 }
 
+static void hns3_checksum_complete(struct hns3_enet_ring *ring,
+                                  struct sk_buff *skb, u32 l234info)
+{
+       u32 lo, hi;
+
+       u64_stats_update_begin(&ring->syncp);
+       ring->stats.csum_complete++;
+       u64_stats_update_end(&ring->syncp);
+       skb->ip_summed = CHECKSUM_COMPLETE;
+       lo = hnae3_get_field(l234info, HNS3_RXD_L2_CSUM_L_M,
+                            HNS3_RXD_L2_CSUM_L_S);
+       hi = hnae3_get_field(l234info, HNS3_RXD_L2_CSUM_H_M,
+                            HNS3_RXD_L2_CSUM_H_S);
+       skb->csum = csum_unfold((__force __sum16)(lo | hi << 8));
+}
+
 static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
                             u32 l234info, u32 bd_base_info, u32 ol_info)
 {
@@ -2812,6 +2828,11 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
        if (!(netdev->features & NETIF_F_RXCSUM))
                return;
 
+       if (l234info & BIT(HNS3_RXD_L2_CSUM_B)) {
+               hns3_checksum_complete(ring, skb, l234info);
+               return;
+       }
+
        /* check if hardware has done checksum */
        if (!(bd_base_info & BIT(HNS3_RXD_L3L4P_B)))
                return;
index 8d3365231bfd1503b9e06d824fa8d898a3e882ff..40681a018dc93aee5ffd27400a0453564c8304f4 100644 (file)
@@ -82,6 +82,12 @@ enum hns3_nic_state {
 #define HNS3_RXD_STRP_TAGP_S                   13
 #define HNS3_RXD_STRP_TAGP_M                   (0x3 << HNS3_RXD_STRP_TAGP_S)
 
+#define HNS3_RXD_L2_CSUM_B                     15
+#define HNS3_RXD_L2_CSUM_L_S                   4
+#define HNS3_RXD_L2_CSUM_L_M                   (0xff << HNS3_RXD_L2_CSUM_L_S)
+#define HNS3_RXD_L2_CSUM_H_S                   24
+#define HNS3_RXD_L2_CSUM_H_M                   (0xff << HNS3_RXD_L2_CSUM_H_S)
+
 #define HNS3_RXD_L2E_B                         16
 #define HNS3_RXD_L3E_B                         17
 #define HNS3_RXD_L4E_B                         18
@@ -371,6 +377,7 @@ struct ring_stats {
                        u64 err_bd_num;
                        u64 l2_err;
                        u64 l3l4_csum_err;
+                       u64 csum_complete;
                        u64 rx_multicast;
                        u64 non_reuse_pg;
                };
index c30d5d3786c4fbfa81b7817000175b61ebbd39f0..3cca3c125c038fbcf387e2d749e773ab6d81b704 100644 (file)
@@ -55,6 +55,7 @@ static const struct hns3_stats hns3_rxq_stats[] = {
        HNS3_TQP_STAT("err_bd_num", err_bd_num),
        HNS3_TQP_STAT("l2_err", l2_err),
        HNS3_TQP_STAT("l3l4_csum_err", l3l4_csum_err),
+       HNS3_TQP_STAT("csum_complete", csum_complete),
        HNS3_TQP_STAT("multicast", rx_multicast),
        HNS3_TQP_STAT("non_reuse_pg", non_reuse_pg),
 };