Skip to content

Commit e21eb2d

Browse files
TaeheeYooNipaLocal
authored and
NipaLocal
committed
ionic: fix kernel panic due to multi-buffer handling
Currently, the ionic_run_xdp() doesn't handle multi-buffer packets properly for XDP_TX and XDP_REDIRECT. When a jumbo frame is received, the ionic_run_xdp() first makes xdp frame with all necessary pages in the rx descriptor. And if the action is either XDP_TX or XDP_REDIRECT, it should unmap dma-mapping and reset page pointer to NULL for all pages, not only the first page. But it doesn't for SG pages. So, SG pages unexpectedly will be reused. It eventually causes kernel panic. Oops: general protection fault, probably for non-canonical address 0x504f4e4dbebc64ff: 0000 [kernel-patches#1] PREEMPT SMP NOPTI CPU: 3 PID: 0 Comm: swapper/3 Not tainted 6.10.0-rc3+ kernel-patches#25 RIP: 0010:xdp_return_frame+0x42/0x90 Code: 01 75 12 5b 4c 89 e6 5d 31 c9 41 5c 31 d2 41 5d e9 73 fd ff ff 44 8b 6b 20 0f b7 43 0a 49 81 ed 68 01 00 00 49 29 c5 49 01 fd <41> 80 7d0 RSP: 0018:ffff99d00122ce08 EFLAGS: 00010202 RAX: 0000000000005453 RBX: ffff8d325f904000 RCX: 0000000000000001 RDX: 00000000670e1000 RSI: 000000011f90d000 RDI: 504f4e4d4c4b4a49 RBP: ffff99d003907740 R08: 0000000000000000 R09: 0000000000000000 R10: 000000011f90d000 R11: 0000000000000000 R12: ffff8d325f904010 R13: 504f4e4dbebc64fd R14: ffff8d3242b070c8 R15: ffff99d0039077c0 FS: 0000000000000000(0000) GS:ffff8d399f780000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f41f6c85e38 CR3: 000000037ac30000 CR4: 00000000007506f0 PKRU: 55555554 Call Trace: <IRQ> ? die_addr+0x33/0x90 ? exc_general_protection+0x251/0x2f0 ? asm_exc_general_protection+0x22/0x30 ? xdp_return_frame+0x42/0x90 ionic_tx_clean+0x211/0x280 [ionic 15881354510e6a9c655c59c54812b319ed2cd015] ionic_tx_cq_service+0xd3/0x210 [ionic 15881354510e6a9c655c59c54812b319ed2cd015] ionic_txrx_napi+0x41/0x1b0 [ionic 15881354510e6a9c655c59c54812b319ed2cd015] __napi_poll.constprop.0+0x29/0x1b0 net_rx_action+0x2c4/0x350 handle_softirqs+0xf4/0x320 irq_exit_rcu+0x78/0xa0 common_interrupt+0x77/0x90 Fixes: 5377805 ("ionic: implement xdp frags support") Signed-off-by: Taehee Yoo <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent 650fc02 commit e21eb2d

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

drivers/net/ethernet/pensando/ionic/ionic_txrx.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -487,14 +487,13 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
487487
struct ionic_buf_info *buf_info,
488488
int len)
489489
{
490+
int remain_len, frag_len, i, err = 0;
491+
struct skb_shared_info *sinfo;
490492
u32 xdp_action = XDP_ABORTED;
491493
struct xdp_buff xdp_buf;
492494
struct ionic_queue *txq;
493495
struct netdev_queue *nq;
494496
struct xdp_frame *xdpf;
495-
int remain_len;
496-
int frag_len;
497-
int err = 0;
498497

499498
xdp_init_buff(&xdp_buf, IONIC_PAGE_SIZE, rxq->xdp_rxq_info);
500499
frag_len = min_t(u16, len, IONIC_XDP_MAX_LINEAR_MTU + VLAN_ETH_HLEN);
@@ -513,7 +512,6 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
513512
*/
514513
remain_len = len - frag_len;
515514
if (remain_len) {
516-
struct skb_shared_info *sinfo;
517515
struct ionic_buf_info *bi;
518516
skb_frag_t *frag;
519517

@@ -576,7 +574,6 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
576574

577575
dma_unmap_page(rxq->dev, buf_info->dma_addr,
578576
IONIC_PAGE_SIZE, DMA_FROM_DEVICE);
579-
580577
err = ionic_xdp_post_frame(txq, xdpf, XDP_TX,
581578
buf_info->page,
582579
buf_info->page_offset,
@@ -587,12 +584,22 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
587584
goto out_xdp_abort;
588585
}
589586
buf_info->page = NULL;
587+
if (xdp_frame_has_frags(xdpf)) {
588+
for (i = 0; i < sinfo->nr_frags; i++) {
589+
buf_info++;
590+
dma_unmap_page(rxq->dev, buf_info->dma_addr,
591+
IONIC_PAGE_SIZE, DMA_FROM_DEVICE);
592+
buf_info->page = NULL;
593+
}
594+
}
595+
590596
stats->xdp_tx++;
591597

592598
/* the Tx completion will free the buffers */
593599
break;
594600

595601
case XDP_REDIRECT:
602+
xdpf = xdp_convert_buff_to_frame(&xdp_buf);
596603
/* unmap the pages before handing them to a different device */
597604
dma_unmap_page(rxq->dev, buf_info->dma_addr,
598605
IONIC_PAGE_SIZE, DMA_FROM_DEVICE);
@@ -603,6 +610,15 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
603610
goto out_xdp_abort;
604611
}
605612
buf_info->page = NULL;
613+
if (xdp_frame_has_frags(xdpf)) {
614+
for (i = 0; i < sinfo->nr_frags; i++) {
615+
buf_info++;
616+
dma_unmap_page(rxq->dev, buf_info->dma_addr,
617+
IONIC_PAGE_SIZE, DMA_FROM_DEVICE);
618+
buf_info->page = NULL;
619+
}
620+
}
621+
606622
rxq->xdp_flush = true;
607623
stats->xdp_redirect++;
608624
break;

0 commit comments

Comments
 (0)