[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