net: hns3: check FE bit before calling hns3_add_frag()
authorYunsheng Lin <linyunsheng@huawei.com>
Thu, 19 Dec 2019 06:57:40 +0000 (14:57 +0800)
committerDavid S. Miller <davem@davemloft.net>
Sat, 21 Dec 2019 05:20:39 +0000 (21:20 -0800)
A BD with FE bit means that it is the last BD of a packet,
currently the FE bit is checked before calling hns3_add_frag(),
which is unnecessary because the FE bit may have been checked
in some case.

This patch checks the FE bit before calling hns3_add_frag()
after processing the first BD of a SKB and adjust the location
of memcpy() to reduce duplication.

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 b113b895dab716d37e64f9c854cdf257db0681f2..5679a0cef975ce966e308ec2b710c5f3bfa65235 100644 (file)
@@ -2788,7 +2788,6 @@ static bool hns3_parse_vlan_tag(struct hns3_enet_ring *ring,
 static int hns3_alloc_skb(struct hns3_enet_ring *ring, unsigned int length,
                          unsigned char *va)
 {
-#define HNS3_NEED_ADD_FRAG     1
        struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_clean];
        struct net_device *netdev = ring_to_netdev(ring);
        struct sk_buff *skb;
@@ -2832,33 +2831,19 @@ static int hns3_alloc_skb(struct hns3_enet_ring *ring, unsigned int length,
                            desc_cb);
        ring_ptr_move_fw(ring, next_to_clean);
 
-       return HNS3_NEED_ADD_FRAG;
+       return 0;
 }
 
-static int hns3_add_frag(struct hns3_enet_ring *ring, struct hns3_desc *desc,
-                        bool pending)
+static int hns3_add_frag(struct hns3_enet_ring *ring)
 {
        struct sk_buff *skb = ring->skb;
        struct sk_buff *head_skb = skb;
        struct sk_buff *new_skb;
        struct hns3_desc_cb *desc_cb;
-       struct hns3_desc *pre_desc;
+       struct hns3_desc *desc;
        u32 bd_base_info;
-       int pre_bd;
-
-       /* if there is pending bd, the SW param next_to_clean has moved
-        * to next and the next is NULL
-        */
-       if (pending) {
-               pre_bd = (ring->next_to_clean - 1 + ring->desc_num) %
-                        ring->desc_num;
-               pre_desc = &ring->desc[pre_bd];
-               bd_base_info = le32_to_cpu(pre_desc->rx.bd_base_info);
-       } else {
-               bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
-       }
 
-       while (!(bd_base_info & BIT(HNS3_RXD_FE_B))) {
+       do {
                desc = &ring->desc[ring->next_to_clean];
                desc_cb = &ring->desc_cb[ring->next_to_clean];
                bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
@@ -2895,7 +2880,7 @@ static int hns3_add_frag(struct hns3_enet_ring *ring, struct hns3_desc *desc,
                hns3_nic_reuse_page(skb, ring->frag_num++, ring, 0, desc_cb);
                ring_ptr_move_fw(ring, next_to_clean);
                ring->pending_buf++;
-       }
+       } while (!(bd_base_info & BIT(HNS3_RXD_FE_B)));
 
        return 0;
 }
@@ -3063,28 +3048,23 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring)
 
                if (ret < 0) /* alloc buffer fail */
                        return ret;
-               if (ret > 0) { /* need add frag */
-                       ret = hns3_add_frag(ring, desc, false);
+               if (!(bd_base_info & BIT(HNS3_RXD_FE_B))) { /* need add frag */
+                       ret = hns3_add_frag(ring);
                        if (ret)
                                return ret;
-
-                       /* As the head data may be changed when GRO enable, copy
-                        * the head data in after other data rx completed
-                        */
-                       memcpy(skb->data, ring->va,
-                              ALIGN(ring->pull_len, sizeof(long)));
                }
        } else {
-               ret = hns3_add_frag(ring, desc, true);
+               ret = hns3_add_frag(ring);
                if (ret)
                        return ret;
+       }
 
-               /* As the head data may be changed when GRO enable, copy
-                * the head data in after other data rx completed
-                */
+       /* As the head data may be changed when GRO enable, copy
+        * the head data in after other data rx completed
+        */
+       if (skb->len > HNS3_RX_HEAD_SIZE)
                memcpy(skb->data, ring->va,
                       ALIGN(ring->pull_len, sizeof(long)));
-       }
 
        ret = hns3_handle_bdinfo(ring, skb);
        if (unlikely(ret)) {