[PATCH net v2] octeontx2-pf: fix XDP frames freed as skbs on interface down

From: Nicolai Buchwitz

Date: Tue Nov 03 2026 - 04:10:26 EST


On interface down, the TX completion cleanup also runs on the XDP
queues, but treats the pending xdp_frames as skbs. Freeing them with
dev_kfree_skb_any() corrupts page pool memory. AF_XDP TX completions
in these queues were never reported to the socket either.

This happens when XDP_TX or redirected packets are still in flight on
ifdown, or when the XDP program is replaced.

Fixes: 94c80f748873 ("octeontx2-pf: use xdp_return_frame() to free xdp buffers")
Signed-off-by: Nicolai Buchwitz <nb@xxxxxxxxxxx>
---
Pre-existing bug, flagged by the clashiko review of my ipsec transmit
fixes for this driver [1], which seems reasonable (and fixable) to me.

The other pre-existing findings there (e.g. the SA lifetime in
cn10k_ipsec_del_state()) may be worth fixing too, but I'll leave those
to the maintainers.

Compile-tested only, I have no octeontx2 hardware.

[1] https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261027-nb-otx2-ipsec-tx-fixes-net-v1-0-2114c4f10c36%40tipi-net.de
---
Changes in v2:
- Report AF_XDP TX completions with xsk_tx_completed() (Daniel, sashiko)
- Link to v1: https://patch.msgid.link/20261030-nb-otx2-xdp-cqe-cleanup-net-v1-1-710635c0f504@xxxxxxxxxxx
---
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index 90af9b9044aa0..b038bb1451949 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -1332,6 +1332,7 @@ void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
struct nix_cqe_tx_s *cqe;
struct netdev_queue *txq;
int processed_cqe = 0;
+ int xsk_frames = 0;
struct sg_list *sg;
int qidx;

@@ -1348,6 +1349,10 @@ void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)

if (!cqe)
continue;
+ if (cq->cq_type == CQ_XDP) {
+ otx2_xdp_snd_pkt_handler(pfvf, sq, cqe, &xsk_frames);
+ continue;
+ }
sg = &sq->sg[cqe->comp.sqe_id];
skb = (struct sk_buff *)sg->skb;
if (skb) {
@@ -1359,6 +1364,9 @@ void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
}
}

+ if (xsk_frames && sq->xsk_pool)
+ xsk_tx_completed(sq->xsk_pool, xsk_frames);
+
if (likely(tx_pkts)) {
if (qidx >= pfvf->hw.tx_queues)
qidx -= pfvf->hw.xdp_queues;

---
base-commit: c3e67bd82b9b9b1a5118f09a429ccefe2aab0741
change-id: 20261028-nb-otx2-xdp-cqe-cleanup-net-5810d40e1d30

Best regards,
--
Nicolai Buchwitz <nb@xxxxxxxxxxx>