wifi: ath12k: Handle error cases during extended skb allocation
[ Upstream commit 37a068fc9dc4feb8d76e8896bb33883d06c11a6b ]
Currently, in the case of extended skb allocation, the buffer is freed
before the DMA unmap operation. This premature deletion can result in
skb->data corruption, as the memory region could be re-allocated for other
purposes. Fix this issue by reordering the failure cases by calling
dma_unmap_single() first, then followed by the corresponding kfree_skb().
This helps avoid data corruption in case of failures in dp_tx().
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
Fixes: d889913205 ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: P Praneesh <praneesh.p@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250411060154.1388159-2-praneesh.p@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
316060297e
commit
3fffbb8d33
@@ -227,7 +227,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
|
||||
struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
|
||||
struct hal_tcl_data_cmd *hal_tcl_desc;
|
||||
struct hal_tx_msdu_ext_desc *msg;
|
||||
struct sk_buff *skb_ext_desc;
|
||||
struct sk_buff *skb_ext_desc = NULL;
|
||||
struct hal_srng *tcl_ring;
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
struct dp_tx_ring *tx_ring;
|
||||
@@ -397,18 +397,15 @@ map:
|
||||
if (ret < 0) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_DP_TX,
|
||||
"Failed to add HTT meta data, dropping packet\n");
|
||||
kfree_skb(skb_ext_desc);
|
||||
goto fail_unmap_dma;
|
||||
goto fail_free_ext_skb;
|
||||
}
|
||||
}
|
||||
|
||||
ti.paddr = dma_map_single(ab->dev, skb_ext_desc->data,
|
||||
skb_ext_desc->len, DMA_TO_DEVICE);
|
||||
ret = dma_mapping_error(ab->dev, ti.paddr);
|
||||
if (ret) {
|
||||
kfree_skb(skb_ext_desc);
|
||||
goto fail_unmap_dma;
|
||||
}
|
||||
if (ret)
|
||||
goto fail_free_ext_skb;
|
||||
|
||||
ti.data_len = skb_ext_desc->len;
|
||||
ti.type = HAL_TCL_DESC_TYPE_EXT_DESC;
|
||||
@@ -444,7 +441,7 @@ map:
|
||||
ring_selector++;
|
||||
}
|
||||
|
||||
goto fail_unmap_dma;
|
||||
goto fail_unmap_dma_ext;
|
||||
}
|
||||
|
||||
ath12k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti);
|
||||
@@ -460,13 +457,16 @@ map:
|
||||
|
||||
return 0;
|
||||
|
||||
fail_unmap_dma:
|
||||
dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
|
||||
|
||||
fail_unmap_dma_ext:
|
||||
if (skb_cb->paddr_ext_desc)
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
|
||||
sizeof(struct hal_tx_msdu_ext_desc),
|
||||
DMA_TO_DEVICE);
|
||||
fail_free_ext_skb:
|
||||
kfree_skb(skb_ext_desc);
|
||||
|
||||
fail_unmap_dma:
|
||||
dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
|
||||
|
||||
fail_remove_tx_buf:
|
||||
ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id);
|
||||
|
||||
Reference in New Issue
Block a user