From 4de5a8a0edddc453f1a4c93b6d9f09013a23b72e Mon Sep 17 00:00:00 2001 From: Rameshkumar Sundaram Date: Thu, 13 Aug 2026 23:09:20 +0530 Subject: [PATCH] wifi: ath12k: fix DMA unwind for ext MSDU descriptor retry ath12k_wifi7_dp_tx() maps the original MSDU into ti.paddr and stores the address in skb_cb->paddr. When an extended MSDU descriptor is used, the function later maps the ext descriptor and overwrites ti.paddr and ti.data_len with the ext-desc DMA address and length. If TCL ring allocation then fails, the error path first unmaps the ext-desc DMA address from skb_cb->paddr_ext_desc. It then falls through to fail_unmap_dma, which uses ti.paddr/ti.data_len for the original MSDU unmap. At that point ti.paddr still refers to the ext-desc mapping, so the ext descriptor is unmapped twice and the original MSDU mapping is left mapped. Fix the original MSDU unwind to use skb_cb->paddr and skb->len instead of ti.paddr/ti.data_len. The ti fields cannot be used after the ext descriptor is mapped because they are intentionally reused for the buffer submitted to TCL. Also clear skb_cb->paddr_ext_desc after the ext-desc unmap so a TCL ring retry cannot observe stale ext-desc DMA state from the previous attempt. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1 Fixes: 37a068fc9dc4 ("wifi: ath12k: Handle error cases during extended skb allocation") Signed-off-by: Rameshkumar Sundaram Reviewed-by: Baochen Qiang Link: https://patch.msgid.link/20260813-ext-msdu-fix-v1-1-c5e80ccd061a@oss.qualcomm.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c index 587d58eeccfa..0dcb566fd182 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_tx.c @@ -449,15 +449,17 @@ skip_htt_meta: return 0; fail_unmap_dma_ext: - if (skb_cb->paddr_ext_desc) + if (skb_cb->paddr_ext_desc) { dma_unmap_single(dp->dev, skb_cb->paddr_ext_desc, skb_ext_desc->len, DMA_TO_DEVICE); + skb_cb->paddr_ext_desc = 0; + } fail_free_ext_skb: kfree_skb(skb_ext_desc); fail_unmap_dma: - dma_unmap_single(dp->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE); + dma_unmap_single(dp->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); fail_remove_tx_buf: ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id);