[PATCH ath-next] wifi: ath12k: free skb during idr cleanup callback
Baochen Qiang
baochen.qiang at oss.qualcomm.com
Mon Sep 29 19:31:52 PDT 2025
On 9/24/2025 6:03 AM, Muna Sinada wrote:
> From: Karthik M <quic_karm at quicinc.com>
>
> ath12k just like ath11k [1] did not handle skb cleanup during idr
> cleanup callback. Both ath12k_mac_vif_txmgmt_idr_remove() and
> ath12k_mac_tx_mgmt_pending_free() performed idr cleanup and DMA
> unmapping for skb but only ath12k_mac_tx_mgmt_pending_free() freed
> skb. As a result, during vdev deletion a memory leak occurs.
>
> Refactor all clean up steps into a new function. New function
> ath12k_mac_tx_mgmt_free() creates a centralized area where idr
> cleanup, DMA unmapping for skb and freeing skb is performed. Utilize
> skb pointer given by idr_remove(), instead of passed as a function
> argument because IDR will be protected by locking. This will prevent
> concurrent modification of the same IDR.
>
> Now ath12k_mac_tx_mgmt_pending_free() and
> ath12k_mac_vif_txmgmt_idr_remove() call ath12k_mac_tx_mgmt_free().
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
>
> Link: https://lore.kernel.org/r/1637832614-13831-1-git-send-email-quic_srirrama@quicinc.com > # [1]
> Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
> Signed-off-by: Karthik M <quic_karm at quicinc.com>
> Signed-off-by: Muna Sinada <muna.sinada at oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang at oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath12k/mac.c | 34 ++++++++++++++-------------
> 1 file changed, 18 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 1d7b60aa5cb0..eacab798630a 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -8290,23 +8290,32 @@ static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
> wake_up(&ar->txmgmt_empty_waitq);
> }
>
> -int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
> +static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
> {
> - struct sk_buff *msdu = skb;
> + struct sk_buff *msdu;
> struct ieee80211_tx_info *info;
> - struct ath12k *ar = ctx;
> - struct ath12k_base *ab = ar->ab;
>
> spin_lock_bh(&ar->txmgmt_idr_lock);
> - idr_remove(&ar->txmgmt_idr, buf_id);
> + msdu = idr_remove(&ar->txmgmt_idr, buf_id);
> spin_unlock_bh(&ar->txmgmt_idr_lock);
> - dma_unmap_single(ab->dev, ATH12K_SKB_CB(msdu)->paddr, msdu->len,
> +
> + if (!msdu)
> + return;
> +
> + dma_unmap_single(ar->ab->dev, ATH12K_SKB_CB(msdu)->paddr, msdu->len,
> DMA_TO_DEVICE);
>
> info = IEEE80211_SKB_CB(msdu);
> memset(&info->status, 0, sizeof(info->status));
>
> - ath12k_mgmt_over_wmi_tx_drop(ar, skb);
> + ath12k_mgmt_over_wmi_tx_drop(ar, msdu);
> +}
> +
> +int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
> +{
> + struct ath12k *ar = ctx;
> +
> + ath12k_mac_tx_mgmt_free(ar, buf_id);
>
> return 0;
> }
> @@ -8315,17 +8324,10 @@ static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
> {
> struct ieee80211_vif *vif = ctx;
> struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
> - struct sk_buff *msdu = skb;
> struct ath12k *ar = skb_cb->ar;
> - struct ath12k_base *ab = ar->ab;
>
> - if (skb_cb->vif == vif) {
> - spin_lock_bh(&ar->txmgmt_idr_lock);
> - idr_remove(&ar->txmgmt_idr, buf_id);
> - spin_unlock_bh(&ar->txmgmt_idr_lock);
> - dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len,
> - DMA_TO_DEVICE);
> - }
> + if (skb_cb->vif == vif)
> + ath12k_mac_tx_mgmt_free(ar, buf_id);
>
> return 0;
> }
>
> base-commit: 32be3ca4cf78b309dfe7ba52fe2d7cc3c23c5634
More information about the ath12k
mailing list