Skip to content

Commit fb5833d

Browse files
TaeheeYoodavem330
authored andcommitted
net: sfc: fix using uninitialized xdp tx_queue
In some cases, xdp tx_queue can get used before initialization. 1. interface up/down 2. ring buffer size change When CPU cores are lower than maximum number of channels of sfc driver, it creates new channels only for XDP. When an interface is up or ring buffer size is changed, all channels are initialized. But xdp channels are always initialized later. So, the below scenario is possible. Packets are received to rx queue of normal channels and it is acted XDP_TX and tx_queue of xdp channels get used. But these tx_queues are not initialized yet. If so, TX DMA or queue error occurs. In order to avoid this problem. 1. initializes xdp tx_queues earlier than other rx_queue in efx_start_channels(). 2. checks whether tx_queue is initialized or not in efx_xdp_tx_buffers(). Splat looks like: sfc 0000:08:00.1 enp8s0f1np1: TX queue 10 spurious TX completion id 250 sfc 0000:08:00.1 enp8s0f1np1: resetting (RECOVER_OR_ALL) sfc 0000:08:00.1 enp8s0f1np1: MC command 0x80 inlen 100 failed rc=-22 (raw=22) arg=789 sfc 0000:08:00.1 enp8s0f1np1: has been disabled Fixes: f28100c ("sfc: fix lack of XDP TX queues - error XDP TX failed (-22)") Acked-by: Martin Habets <habetsm.xilinx@gmail.com> Signed-off-by: Taehee Yoo <ap420073@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 1946014 commit fb5833d

3 files changed

Lines changed: 6 additions & 1 deletion

File tree

drivers/net/ethernet/sfc/efx_channels.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1140,7 +1140,7 @@ void efx_start_channels(struct efx_nic *efx)
11401140
struct efx_rx_queue *rx_queue;
11411141
struct efx_channel *channel;
11421142

1143-
efx_for_each_channel(channel, efx) {
1143+
efx_for_each_channel_rev(channel, efx) {
11441144
efx_for_each_channel_tx_queue(tx_queue, channel) {
11451145
efx_init_tx_queue(tx_queue);
11461146
atomic_inc(&efx->active_queues);

drivers/net/ethernet/sfc/tx.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@ int efx_xdp_tx_buffers(struct efx_nic *efx, int n, struct xdp_frame **xdpfs,
443443
if (unlikely(!tx_queue))
444444
return -EINVAL;
445445

446+
if (!tx_queue->initialised)
447+
return -EINVAL;
448+
446449
if (efx->xdp_txq_queues_mode != EFX_XDP_TX_QUEUES_DEDICATED)
447450
HARD_TX_LOCK(efx->net_dev, tx_queue->core_txq, cpu);
448451

drivers/net/ethernet/sfc/tx_common.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
101101
netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
102102
"shutting down TX queue %d\n", tx_queue->queue);
103103

104+
tx_queue->initialised = false;
105+
104106
if (!tx_queue->buffer)
105107
return;
106108

0 commit comments

Comments
 (0)