Commit 9dbb1370 authored by Björn Töpel's avatar Björn Töpel Committed by Jeff Kirsher
Browse files

i40e: clean zero-copy XDP Tx ring on shutdown/reset



When the zero-copy enabled XDP Tx ring is torn down, due to
configuration changes, outstanding frames on the hardware descriptor
ring are queued on the completion ring.

The completion ring has a back-pressure mechanism that will guarantee
that there is sufficient space on the ring.

Signed-off-by: default avatarBjörn Töpel <bjorn.topel@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 679b05c0
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -636,13 +636,18 @@ void i40e_clean_tx_ring(struct i40e_ring *tx_ring)
	unsigned long bi_size;
	u16 i;

	if (ring_is_xdp(tx_ring) && tx_ring->xsk_umem) {
		i40e_xsk_clean_tx_ring(tx_ring);
	} else {
		/* ring already cleared, nothing to do */
		if (!tx_ring->tx_bi)
			return;

		/* Free all the Tx ring sk_buffs */
		for (i = 0; i < tx_ring->count; i++)
		i40e_unmap_and_free_tx_resource(tx_ring, &tx_ring->tx_bi[i]);
			i40e_unmap_and_free_tx_resource(tx_ring,
							&tx_ring->tx_bi[i]);
	}

	bi_size = sizeof(struct i40e_tx_buffer) * tx_ring->count;
	memset(tx_ring->tx_bi, 0, bi_size);
+2 −0
Original line number Diff line number Diff line
@@ -87,4 +87,6 @@ static inline void i40e_arm_wb(struct i40e_ring *tx_ring,
	}
}

void i40e_xsk_clean_tx_ring(struct i40e_ring *tx_ring);

#endif /* I40E_TXRX_COMMON_ */
+30 −0
Original line number Diff line number Diff line
@@ -830,3 +830,33 @@ int i40e_xsk_async_xmit(struct net_device *dev, u32 queue_id)

	return 0;
}

/**
 * i40e_xsk_clean_xdp_ring - Clean the XDP Tx ring on shutdown
 * @xdp_ring: XDP Tx ring
 **/
void i40e_xsk_clean_tx_ring(struct i40e_ring *tx_ring)
{
	u16 ntc = tx_ring->next_to_clean, ntu = tx_ring->next_to_use;
	struct xdp_umem *umem = tx_ring->xsk_umem;
	struct i40e_tx_buffer *tx_bi;
	u32 xsk_frames = 0;

	while (ntc != ntu) {
		tx_bi = &tx_ring->tx_bi[ntc];

		if (tx_bi->xdpf)
			i40e_clean_xdp_tx_buffer(tx_ring, tx_bi);
		else
			xsk_frames++;

		tx_bi->xdpf = NULL;

		ntc++;
		if (ntc >= tx_ring->count)
			ntc = 0;
	}

	if (xsk_frames)
		xsk_umem_complete_tx(umem, xsk_frames);
}