Skip to content

Commit e3f02f3

Browse files
TaeheeYoodavem330
authored andcommitted
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 [#1] PREEMPT SMP NOPTI CPU: 3 PID: 0 Comm: swapper/3 Not tainted 6.10.0-rc3+ #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]> Reviewed-by: Shannon Nelson <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7eadf50 commit e3f02f3

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

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

+18-9
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,20 @@ int ionic_xdp_xmit(struct net_device *netdev, int n,
480480
return nxmit;
481481
}
482482

483+
static void ionic_xdp_rx_put_bufs(struct ionic_queue *q,
484+
struct ionic_buf_info *buf_info,
485+
int nbufs)
486+
{
487+
int i;
488+
489+
for (i = 0; i < nbufs; i++) {
490+
dma_unmap_page(q->dev, buf_info->dma_addr,
491+
IONIC_PAGE_SIZE, DMA_FROM_DEVICE);
492+
buf_info->page = NULL;
493+
buf_info++;
494+
}
495+
}
496+
483497
static bool ionic_run_xdp(struct ionic_rx_stats *stats,
484498
struct net_device *netdev,
485499
struct bpf_prog *xdp_prog,
@@ -493,6 +507,7 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
493507
struct netdev_queue *nq;
494508
struct xdp_frame *xdpf;
495509
int remain_len;
510+
int nbufs = 1;
496511
int frag_len;
497512
int err = 0;
498513

@@ -542,6 +557,7 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
542557
if (page_is_pfmemalloc(bi->page))
543558
xdp_buff_set_frag_pfmemalloc(&xdp_buf);
544559
} while (remain_len > 0);
560+
nbufs += sinfo->nr_frags;
545561
}
546562

547563
xdp_action = bpf_prog_run_xdp(xdp_prog, &xdp_buf);
@@ -574,9 +590,6 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
574590
goto out_xdp_abort;
575591
}
576592

577-
dma_unmap_page(rxq->dev, buf_info->dma_addr,
578-
IONIC_PAGE_SIZE, DMA_FROM_DEVICE);
579-
580593
err = ionic_xdp_post_frame(txq, xdpf, XDP_TX,
581594
buf_info->page,
582595
buf_info->page_offset,
@@ -586,23 +599,19 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
586599
netdev_dbg(netdev, "tx ionic_xdp_post_frame err %d\n", err);
587600
goto out_xdp_abort;
588601
}
589-
buf_info->page = NULL;
602+
ionic_xdp_rx_put_bufs(rxq, buf_info, nbufs);
590603
stats->xdp_tx++;
591604

592605
/* the Tx completion will free the buffers */
593606
break;
594607

595608
case XDP_REDIRECT:
596-
/* unmap the pages before handing them to a different device */
597-
dma_unmap_page(rxq->dev, buf_info->dma_addr,
598-
IONIC_PAGE_SIZE, DMA_FROM_DEVICE);
599-
600609
err = xdp_do_redirect(netdev, &xdp_buf, xdp_prog);
601610
if (err) {
602611
netdev_dbg(netdev, "xdp_do_redirect err %d\n", err);
603612
goto out_xdp_abort;
604613
}
605-
buf_info->page = NULL;
614+
ionic_xdp_rx_put_bufs(rxq, buf_info, nbufs);
606615
rxq->xdp_flush = true;
607616
stats->xdp_redirect++;
608617
break;

0 commit comments

Comments
 (0)