Skip to content

Commit 059a47f

Browse files
TaeheeYoodavem330
authored andcommitted
net: sfc: add missing xdp queue reinitialization
After rx/tx ring buffer size is changed, kernel panic occurs when it acts XDP_TX or XDP_REDIRECT. When tx/rx ring buffer size is changed(ethtool -G), sfc driver reallocates and reinitializes rx and tx queues and their buffer (tx_queue->buffer). But it misses reinitializing xdp queues(efx->xdp_tx_queues). So, while it is acting XDP_TX or XDP_REDIRECT, it uses the uninitialized tx_queue->buffer. A new function efx_set_xdp_channels() is separated from efx_set_channels() to handle only xdp queues. Splat looks like: BUG: kernel NULL pointer dereference, address: 000000000000002a #PF: supervisor write access in kernel mode #PF: error_code(0x0002) - not-present page PGD 0 P4D 0 Oops: 0002 [#4] PREEMPT SMP NOPTI RIP: 0010:efx_tx_map_chunk+0x54/0x90 [sfc] CPU: 2 PID: 0 Comm: swapper/2 Tainted: G D 5.17.0+ torvalds#55 e8beeee8289528f11357029357cf Code: 48 8b 8d a8 01 00 00 48 8d 14 52 4c 8d 2c d0 44 89 e0 48 85 c9 74 0e 44 89 e2 4c 89 f6 48 80 RSP: 0018:ffff92f121e45c60 EFLAGS: 00010297 RIP: 0010:efx_tx_map_chunk+0x54/0x90 [sfc] RAX: 0000000000000040 RBX: ffff92ea506895c0 RCX: ffffffffc0330870 RDX: 0000000000000001 RSI: 00000001139b10ce RDI: ffff92ea506895c0 RBP: ffffffffc0358a80 R08: 00000001139b110d R09: 0000000000000000 R10: 0000000000000001 R11: ffff92ea414c0088 R12: 0000000000000040 R13: 0000000000000018 R14: 00000001139b10ce R15: ffff92ea506895c0 FS: 0000000000000000(0000) GS:ffff92f121ec0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 Code: 48 8b 8d a8 01 00 00 48 8d 14 52 4c 8d 2c d0 44 89 e0 48 85 c9 74 0e 44 89 e2 4c 89 f6 48 80 CR2: 000000000000002a CR3: 00000003e6810004 CR4: 00000000007706e0 RSP: 0018:ffff92f121e85c60 EFLAGS: 00010297 PKRU: 55555554 RAX: 0000000000000040 RBX: ffff92ea50689700 RCX: ffffffffc0330870 RDX: 0000000000000001 RSI: 00000001145a90ce RDI: ffff92ea50689700 RBP: ffffffffc0358a80 R08: 00000001145a910d R09: 0000000000000000 R10: 0000000000000001 R11: ffff92ea414c0088 R12: 0000000000000040 R13: 0000000000000018 R14: 00000001145a90ce R15: ffff92ea50689700 FS: 0000000000000000(0000) GS:ffff92f121e80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000000000002a CR3: 00000003e6810005 CR4: 00000000007706e0 PKRU: 55555554 Call Trace: <IRQ> efx_xdp_tx_buffers+0x12b/0x3d0 [sfc 84c94b8e32d44d296c17e10a634d3ad454de4ba5] __efx_rx_packet+0x5c3/0x930 [sfc 84c94b8e32d44d296c17e10a634d3ad454de4ba5] efx_rx_packet+0x28c/0x2e0 [sfc 84c94b8e32d44d296c17e10a634d3ad454de4ba5] efx_ef10_ev_process+0x5f8/0xf40 [sfc 84c94b8e32d44d296c17e10a634d3ad454de4ba5] ? enqueue_task_fair+0x95/0x550 efx_poll+0xc4/0x360 [sfc 84c94b8e32d44d296c17e10a634d3ad454de4ba5] Fixes: 3990a8f ("sfc: allocate channels for XDP tx queues") Signed-off-by: Taehee Yoo <ap420073@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 2975dbd commit 059a47f

File tree

1 file changed

+81
-65
lines changed

1 file changed

+81
-65
lines changed

drivers/net/ethernet/sfc/efx_channels.c

Lines changed: 81 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,85 @@ void efx_remove_channels(struct efx_nic *efx)
786786
kfree(efx->xdp_tx_queues);
787787
}
788788

789+
static int efx_set_xdp_tx_queue(struct efx_nic *efx, int xdp_queue_number,
790+
struct efx_tx_queue *tx_queue)
791+
{
792+
if (xdp_queue_number >= efx->xdp_tx_queue_count)
793+
return -EINVAL;
794+
795+
netif_dbg(efx, drv, efx->net_dev,
796+
"Channel %u TXQ %u is XDP %u, HW %u\n",
797+
tx_queue->channel->channel, tx_queue->label,
798+
xdp_queue_number, tx_queue->queue);
799+
efx->xdp_tx_queues[xdp_queue_number] = tx_queue;
800+
return 0;
801+
}
802+
803+
static void efx_set_xdp_channels(struct efx_nic *efx)
804+
{
805+
struct efx_tx_queue *tx_queue;
806+
struct efx_channel *channel;
807+
unsigned int next_queue = 0;
808+
int xdp_queue_number = 0;
809+
int rc;
810+
811+
/* We need to mark which channels really have RX and TX
812+
* queues, and adjust the TX queue numbers if we have separate
813+
* RX-only and TX-only channels.
814+
*/
815+
efx_for_each_channel(channel, efx) {
816+
if (channel->channel < efx->tx_channel_offset)
817+
continue;
818+
819+
if (efx_channel_is_xdp_tx(channel)) {
820+
efx_for_each_channel_tx_queue(tx_queue, channel) {
821+
tx_queue->queue = next_queue++;
822+
rc = efx_set_xdp_tx_queue(efx, xdp_queue_number,
823+
tx_queue);
824+
if (rc == 0)
825+
xdp_queue_number++;
826+
}
827+
} else {
828+
efx_for_each_channel_tx_queue(tx_queue, channel) {
829+
tx_queue->queue = next_queue++;
830+
netif_dbg(efx, drv, efx->net_dev,
831+
"Channel %u TXQ %u is HW %u\n",
832+
channel->channel, tx_queue->label,
833+
tx_queue->queue);
834+
}
835+
836+
/* If XDP is borrowing queues from net stack, it must
837+
* use the queue with no csum offload, which is the
838+
* first one of the channel
839+
* (note: tx_queue_by_type is not initialized yet)
840+
*/
841+
if (efx->xdp_txq_queues_mode ==
842+
EFX_XDP_TX_QUEUES_BORROWED) {
843+
tx_queue = &channel->tx_queue[0];
844+
rc = efx_set_xdp_tx_queue(efx, xdp_queue_number,
845+
tx_queue);
846+
if (rc == 0)
847+
xdp_queue_number++;
848+
}
849+
}
850+
}
851+
WARN_ON(efx->xdp_txq_queues_mode == EFX_XDP_TX_QUEUES_DEDICATED &&
852+
xdp_queue_number != efx->xdp_tx_queue_count);
853+
WARN_ON(efx->xdp_txq_queues_mode != EFX_XDP_TX_QUEUES_DEDICATED &&
854+
xdp_queue_number > efx->xdp_tx_queue_count);
855+
856+
/* If we have more CPUs than assigned XDP TX queues, assign the already
857+
* existing queues to the exceeding CPUs
858+
*/
859+
next_queue = 0;
860+
while (xdp_queue_number < efx->xdp_tx_queue_count) {
861+
tx_queue = efx->xdp_tx_queues[next_queue++];
862+
rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
863+
if (rc == 0)
864+
xdp_queue_number++;
865+
}
866+
}
867+
789868
int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
790869
{
791870
struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel;
@@ -857,6 +936,7 @@ int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
857936
efx_init_napi_channel(efx->channel[i]);
858937
}
859938

939+
efx_set_xdp_channels(efx);
860940
out:
861941
/* Destroy unused channel structures */
862942
for (i = 0; i < efx->n_channels; i++) {
@@ -889,26 +969,9 @@ int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
889969
goto out;
890970
}
891971

892-
static inline int
893-
efx_set_xdp_tx_queue(struct efx_nic *efx, int xdp_queue_number,
894-
struct efx_tx_queue *tx_queue)
895-
{
896-
if (xdp_queue_number >= efx->xdp_tx_queue_count)
897-
return -EINVAL;
898-
899-
netif_dbg(efx, drv, efx->net_dev, "Channel %u TXQ %u is XDP %u, HW %u\n",
900-
tx_queue->channel->channel, tx_queue->label,
901-
xdp_queue_number, tx_queue->queue);
902-
efx->xdp_tx_queues[xdp_queue_number] = tx_queue;
903-
return 0;
904-
}
905-
906972
int efx_set_channels(struct efx_nic *efx)
907973
{
908-
struct efx_tx_queue *tx_queue;
909974
struct efx_channel *channel;
910-
unsigned int next_queue = 0;
911-
int xdp_queue_number;
912975
int rc;
913976

914977
efx->tx_channel_offset =
@@ -926,61 +989,14 @@ int efx_set_channels(struct efx_nic *efx)
926989
return -ENOMEM;
927990
}
928991

929-
/* We need to mark which channels really have RX and TX
930-
* queues, and adjust the TX queue numbers if we have separate
931-
* RX-only and TX-only channels.
932-
*/
933-
xdp_queue_number = 0;
934992
efx_for_each_channel(channel, efx) {
935993
if (channel->channel < efx->n_rx_channels)
936994
channel->rx_queue.core_index = channel->channel;
937995
else
938996
channel->rx_queue.core_index = -1;
939-
940-
if (channel->channel >= efx->tx_channel_offset) {
941-
if (efx_channel_is_xdp_tx(channel)) {
942-
efx_for_each_channel_tx_queue(tx_queue, channel) {
943-
tx_queue->queue = next_queue++;
944-
rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
945-
if (rc == 0)
946-
xdp_queue_number++;
947-
}
948-
} else {
949-
efx_for_each_channel_tx_queue(tx_queue, channel) {
950-
tx_queue->queue = next_queue++;
951-
netif_dbg(efx, drv, efx->net_dev, "Channel %u TXQ %u is HW %u\n",
952-
channel->channel, tx_queue->label,
953-
tx_queue->queue);
954-
}
955-
956-
/* If XDP is borrowing queues from net stack, it must use the queue
957-
* with no csum offload, which is the first one of the channel
958-
* (note: channel->tx_queue_by_type is not initialized yet)
959-
*/
960-
if (efx->xdp_txq_queues_mode == EFX_XDP_TX_QUEUES_BORROWED) {
961-
tx_queue = &channel->tx_queue[0];
962-
rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
963-
if (rc == 0)
964-
xdp_queue_number++;
965-
}
966-
}
967-
}
968997
}
969-
WARN_ON(efx->xdp_txq_queues_mode == EFX_XDP_TX_QUEUES_DEDICATED &&
970-
xdp_queue_number != efx->xdp_tx_queue_count);
971-
WARN_ON(efx->xdp_txq_queues_mode != EFX_XDP_TX_QUEUES_DEDICATED &&
972-
xdp_queue_number > efx->xdp_tx_queue_count);
973998

974-
/* If we have more CPUs than assigned XDP TX queues, assign the already
975-
* existing queues to the exceeding CPUs
976-
*/
977-
next_queue = 0;
978-
while (xdp_queue_number < efx->xdp_tx_queue_count) {
979-
tx_queue = efx->xdp_tx_queues[next_queue++];
980-
rc = efx_set_xdp_tx_queue(efx, xdp_queue_number, tx_queue);
981-
if (rc == 0)
982-
xdp_queue_number++;
983-
}
999+
efx_set_xdp_channels(efx);
9841000

9851001
rc = netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
9861002
if (rc)

0 commit comments

Comments
 (0)