]> Git Repo - linux.git/commitdiff
wifi: ath10k: Fix memory leak in management tx
authorManikanta Pubbisetty <[email protected]>
Tue, 15 Oct 2024 06:41:03 +0000 (12:11 +0530)
committerJeff Johnson <[email protected]>
Wed, 16 Oct 2024 14:30:31 +0000 (07:30 -0700)
In the current logic, memory is allocated for storing the MSDU context
during management packet TX but this memory is not being freed during
management TX completion. Similar leaks are seen in the management TX
cleanup logic.

Kmemleak reports this problem as below,

unreferenced object 0xffffff80b64ed250 (size 16):
  comm "kworker/u16:7", pid 148, jiffies 4294687130 (age 714.199s)
  hex dump (first 16 bytes):
    00 2b d8 d8 80 ff ff ff c4 74 e9 fd 07 00 00 00  .+.......t......
  backtrace:
    [<ffffffe6e7b245dc>] __kmem_cache_alloc_node+0x1e4/0x2d8
    [<ffffffe6e7adde88>] kmalloc_trace+0x48/0x110
    [<ffffffe6bbd765fc>] ath10k_wmi_tlv_op_gen_mgmt_tx_send+0xd4/0x1d8 [ath10k_core]
    [<ffffffe6bbd3eed4>] ath10k_mgmt_over_wmi_tx_work+0x134/0x298 [ath10k_core]
    [<ffffffe6e78d5974>] process_scheduled_works+0x1ac/0x400
    [<ffffffe6e78d60b8>] worker_thread+0x208/0x328
    [<ffffffe6e78dc890>] kthread+0x100/0x1c0
    [<ffffffe6e78166c0>] ret_from_fork+0x10/0x20

Free the memory during completion and cleanup to fix the leak.

Protect the mgmt_pending_tx idr_remove() operation in
ath10k_wmi_tlv_op_cleanup_mgmt_tx_send() using ar->data_lock similar to
other instances.

Tested-on: WCN3990 hw1.0 SNOC WLAN.HL.2.0-01387-QCAHLSWMTPLZ-1

Fixes: dc405152bb64 ("ath10k: handle mgmt tx completion event")
Fixes: c730c477176a ("ath10k: Remove msdu from idr when management pkt send fails")
Cc: [email protected]
Signed-off-by: Manikanta Pubbisetty <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jeff Johnson <[email protected]>
drivers/net/wireless/ath/ath10k/wmi-tlv.c
drivers/net/wireless/ath/ath10k/wmi.c

index dbaf26d6a7a61806ac0f7d19ee9d69ead306aecf..16d07d619b4df9245606a227c2aa9d1a156d06b9 100644 (file)
@@ -3043,9 +3043,14 @@ ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar,
                                       struct sk_buff *msdu)
 {
        struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
+       struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
        struct ath10k_wmi *wmi = &ar->wmi;
 
-       idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
+       spin_lock_bh(&ar->data_lock);
+       pkt_addr = idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
+       spin_unlock_bh(&ar->data_lock);
+
+       kfree(pkt_addr);
 
        return 0;
 }
index fe2344598364973eae9916a5368744b70ec6325c..1d58452ed8ca6d782810a46f65330f5078acef3f 100644 (file)
@@ -2441,6 +2441,7 @@ wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param)
        dma_unmap_single(ar->dev, pkt_addr->paddr,
                         msdu->len, DMA_TO_DEVICE);
        info = IEEE80211_SKB_CB(msdu);
+       kfree(pkt_addr);
 
        if (param->status) {
                info->flags &= ~IEEE80211_TX_STAT_ACK;
@@ -9612,6 +9613,7 @@ static int ath10k_wmi_mgmt_tx_clean_up_pending(int msdu_id, void *ptr,
        dma_unmap_single(ar->dev, pkt_addr->paddr,
                         msdu->len, DMA_TO_DEVICE);
        ieee80211_free_txskb(ar->hw, msdu);
+       kfree(pkt_addr);
 
        return 0;
 }
This page took 0.102108 seconds and 4 git commands to generate.