Commit bf02d9fe authored by David Arinzon's avatar David Arinzon Committed by Paolo Abeni

net: ena: Fix incorrect descriptor free behavior

ENA has two types of TX queues:
- queues which only process TX packets arriving from the network stack
- queues which only process TX packets forwarded to it by XDP_REDIRECT
  or XDP_TX instructions

The ena_free_tx_bufs() cycles through all descriptors in a TX queue
and unmaps + frees every descriptor that hasn't been acknowledged yet
by the device (uncompleted TX transactions).
The function assumes that the processed TX queue is necessarily from
the first category listed above and ends up using napi_consume_skb()
for descriptors belonging to an XDP specific queue.

This patch solves a bug in which, in case of a VF reset, the
descriptors aren't freed correctly, leading to crashes.

Fixes: 548c4940 ("net: ena: Implement XDP_TX action")
Signed-off-by: default avatarShay Agroskin <shayagr@amazon.com>
Signed-off-by: default avatarDavid Arinzon <darinzon@amazon.com>
Reviewed-by: default avatarShannon Nelson <shannon.nelson@amd.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent f7e41718
...@@ -718,8 +718,11 @@ void ena_unmap_tx_buff(struct ena_ring *tx_ring, ...@@ -718,8 +718,11 @@ void ena_unmap_tx_buff(struct ena_ring *tx_ring,
static void ena_free_tx_bufs(struct ena_ring *tx_ring) static void ena_free_tx_bufs(struct ena_ring *tx_ring)
{ {
bool print_once = true; bool print_once = true;
bool is_xdp_ring;
u32 i; u32 i;
is_xdp_ring = ENA_IS_XDP_INDEX(tx_ring->adapter, tx_ring->qid);
for (i = 0; i < tx_ring->ring_size; i++) { for (i = 0; i < tx_ring->ring_size; i++) {
struct ena_tx_buffer *tx_info = &tx_ring->tx_buffer_info[i]; struct ena_tx_buffer *tx_info = &tx_ring->tx_buffer_info[i];
...@@ -739,10 +742,15 @@ static void ena_free_tx_bufs(struct ena_ring *tx_ring) ...@@ -739,10 +742,15 @@ static void ena_free_tx_bufs(struct ena_ring *tx_ring)
ena_unmap_tx_buff(tx_ring, tx_info); ena_unmap_tx_buff(tx_ring, tx_info);
dev_kfree_skb_any(tx_info->skb); if (is_xdp_ring)
xdp_return_frame(tx_info->xdpf);
else
dev_kfree_skb_any(tx_info->skb);
} }
netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
tx_ring->qid)); if (!is_xdp_ring)
netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
tx_ring->qid));
} }
static void ena_free_all_tx_bufs(struct ena_adapter *adapter) static void ena_free_all_tx_bufs(struct ena_adapter *adapter)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment