Commit b2598318 authored by Yunsheng Lin's avatar Yunsheng Lin Committed by David S. Miller
Browse files

net: hns3: check FE bit before calling hns3_add_frag()



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: default avatarYunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e1b5e598
Loading
Loading
Loading
Loading
+13 −33
Original line number Diff line number Diff line
@@ -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
	 */
	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)) {