net: hns3: fix for miscalculation of rx unused desc
authorYunsheng Lin <linyunsheng@huawei.com>
Tue, 19 Oct 2021 14:16:32 +0000 (22:16 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 20 Oct 2021 10:38:11 +0000 (11:38 +0100)
rx unused desc is the desc that need attatching new buffer
before refilling to hw to receive new packet, the number of
desc need attatching new buffer is calculated using next_to_use
and next_to_clean. when next_to_use == next_to_clean, currently
hns3 driver assumes that all the desc has the buffer attatched,
but 'next_to_use == next_to_clean' also means all the desc need
attatching new buffer if hw has comsumed all the desc and the
driver has not attatched any buffer to the desc yet.

This patch adds 'refill' in desc_cb to indicate whether a new
buffer has been refilled to a desc.

Fixes: 76ad4f0ee747 ("net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC")
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h

index ea89772..2ecc9ab 100644 (file)
@@ -3255,6 +3255,7 @@ static void hns3_buffer_detach(struct hns3_enet_ring *ring, int i)
 {
        hns3_unmap_buffer(ring, &ring->desc_cb[i]);
        ring->desc[i].addr = 0;
+       ring->desc_cb[i].refill = 0;
 }
 
 static void hns3_free_buffer_detach(struct hns3_enet_ring *ring, int i,
@@ -3333,6 +3334,7 @@ static int hns3_alloc_and_attach_buffer(struct hns3_enet_ring *ring, int i)
 
        ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma +
                                         ring->desc_cb[i].page_offset);
+       ring->desc_cb[i].refill = 1;
 
        return 0;
 }
@@ -3362,6 +3364,7 @@ static void hns3_replace_buffer(struct hns3_enet_ring *ring, int i,
 {
        hns3_unmap_buffer(ring, &ring->desc_cb[i]);
        ring->desc_cb[i] = *res_cb;
+       ring->desc_cb[i].refill = 1;
        ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma +
                                         ring->desc_cb[i].page_offset);
        ring->desc[i].rx.bd_base_info = 0;
@@ -3370,6 +3373,7 @@ static void hns3_replace_buffer(struct hns3_enet_ring *ring, int i,
 static void hns3_reuse_buffer(struct hns3_enet_ring *ring, int i)
 {
        ring->desc_cb[i].reuse_flag = 0;
+       ring->desc_cb[i].refill = 1;
        ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma +
                                         ring->desc_cb[i].page_offset);
        ring->desc[i].rx.bd_base_info = 0;
@@ -3476,6 +3480,9 @@ static int hns3_desc_unused(struct hns3_enet_ring *ring)
        int ntc = ring->next_to_clean;
        int ntu = ring->next_to_use;
 
+       if (unlikely(ntc == ntu && !ring->desc_cb[ntc].refill))
+               return ring->desc_num;
+
        return ((ntc >= ntu) ? 0 : ring->desc_num) + ntc - ntu;
 }
 
@@ -3821,6 +3828,7 @@ static void hns3_rx_ring_move_fw(struct hns3_enet_ring *ring)
 {
        ring->desc[ring->next_to_clean].rx.bd_base_info &=
                cpu_to_le32(~BIT(HNS3_RXD_VLD_B));
+       ring->desc_cb[ring->next_to_clean].refill = 0;
        ring->next_to_clean += 1;
 
        if (unlikely(ring->next_to_clean == ring->desc_num))
index 9d9be36..f09a61d 100644 (file)
@@ -330,6 +330,7 @@ struct hns3_desc_cb {
        u32 length;     /* length of the buffer */
 
        u16 reuse_flag;
+       u16 refill;
 
        /* desc type, used by the ring user to mark the type of the priv data */
        u16 type;