* [PATCH 0/5] wifi: ath: avoid IDR mutation while iterating
@ 2026-09-26 15:48 Jiale Yao
2026-09-26 15:48 ` [PATCH 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup Jiale Yao
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Jiale Yao @ 2026-09-26 15:48 UTC (permalink / raw)
To: Jeff Johnson, Michal Kazior, Kalle Valo, Manikanta Pubbisetty,
Sathishkumar Muruganandam, Maharaja Kennadyrajan,
Karthikeyan Periyasamy, Anilkumar Kolli, Baochen Qiang,
Bhagavathi Perumal S, Sriram R, Balamurugan Selvarajan,
linux-wireless, ath10k, linux-kernel, ath11k, ath12k
Cc: Jiale Yao
The ath10k, ath11k, and ath12k cleanup paths walk an IDR while their
callbacks remove the current entry. idr_for_each() retains radix-tree
iterator state across the callback, so that removal can invalidate the
walk.
For ath11k and ath12k full teardown, keep the callback limited to
releasing the supplied skb and leave IDR teardown to the following
idr_destroy(), matching the established SCMI fix. For selective per-vif
cleanup, use idr_for_each_entry() so each iteration starts with a fresh
lookup before removing a matching entry. ath10k also uses
idr_for_each_entry() because its shared TX completion helper must retain
the per-entry removal.
Jiale Yao (5):
wifi: ath10k: avoid IDR mutation during TX cleanup
wifi: ath11k: avoid IDR mutation during pending mgmt TX cleanup
wifi: ath11k: avoid IDR mutation during vif mgmt TX cleanup
wifi: ath12k: avoid IDR mutation during pending mgmt TX cleanup
wifi: ath12k: avoid IDR mutation during vif mgmt TX cleanup
drivers/net/wireless/ath/ath10k/htt_tx.c | 7 +++-
drivers/net/wireless/ath/ath11k/mac.c | 46 +++++++++++++-----------
drivers/net/wireless/ath/ath12k/mac.c | 46 +++++++++++++-----------
3 files changed, 58 insertions(+), 41 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup
2026-09-26 15:48 [PATCH 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
@ 2026-09-26 15:48 ` Jiale Yao
2026-09-26 15:48 ` [PATCH 2/5] wifi: ath11k: avoid IDR mutation during pending mgmt " Jiale Yao
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Jiale Yao @ 2026-09-26 15:48 UTC (permalink / raw)
To: Jeff Johnson, Kalle Valo, Michal Kazior, linux-wireless, ath10k,
linux-kernel
Cc: Jiale Yao
ath10k_htt_flush_tx_queue() walks pending_tx with idr_for_each().
Its callback calls ath10k_txrx_tx_unref(), which removes the current
entry from pending_tx through ath10k_htt_tx_free_msdu_id().
idr_for_each() keeps radix-tree iterator state across the callback.
Removing the current entry can therefore invalidate that state and
make the remaining walk unsafe.
Use idr_for_each_entry(), which starts a fresh lookup after each
callback. The current entry can then be removed safely, while the
following idr_destroy() continues to release the IDR itself.
Fixes: 89d6d83565e9 ("ath10k: use idr api for msdu_ids")
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
drivers/net/wireless/ath/ath10k/htt_tx.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index e46f579d745d..9993c5a2f96c 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -535,8 +535,13 @@ void ath10k_htt_tx_destroy(struct ath10k_htt *htt)
static void ath10k_htt_flush_tx_queue(struct ath10k_htt *htt)
{
+ struct sk_buff *msdu;
+ int msdu_id;
+
ath10k_htc_stop_hl(htt->ar);
- idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
+
+ idr_for_each_entry(&htt->pending_tx, msdu, msdu_id)
+ ath10k_htt_tx_clean_up_pending(msdu_id, msdu, htt->ar);
}
void ath10k_htt_tx_stop(struct ath10k_htt *htt)
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/5] wifi: ath11k: avoid IDR mutation during pending mgmt TX cleanup
2026-09-26 15:48 [PATCH 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
2026-09-26 15:48 ` [PATCH 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup Jiale Yao
@ 2026-09-26 15:48 ` Jiale Yao
2026-09-26 15:48 ` [PATCH 3/5] wifi: ath11k: avoid IDR mutation during vif " Jiale Yao
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Jiale Yao @ 2026-09-26 15:48 UTC (permalink / raw)
To: Jeff Johnson, Shashidhar Lakkavalli, Venkateswara Naralasetty,
Maharaja Kennadyrajan, Ganesh Sesetti, Miles Hu, linux-wireless,
ath11k, linux-kernel
Cc: Jiale Yao
ath11k_mac_tx_mgmt_pending_free() is passed as an idr_for_each()
callback and removes the current entry from txmgmt_idr. This can
invalidate the radix-tree iterator retained by idr_for_each().
Both callers destroy the IDR immediately after the walk, so removing
each entry in the callback is unnecessary. Split skb release from IDR
removal and let the callback release the supplied skb without updating
the IDR. The following idr_destroy() tears down the IDR itself.
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
drivers/net/wireless/ath/ath11k/mac.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index ae91b57c8422..696f9dd65ad4 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -6146,18 +6146,11 @@ static void ath11k_mgmt_over_wmi_tx_drop(struct ath11k *ar, struct sk_buff *skb)
wake_up(&ar->txmgmt_empty_waitq);
}
-static void ath11k_mac_tx_mgmt_free(struct ath11k *ar, int buf_id)
+static void ath11k_mac_tx_mgmt_free_skb(struct ath11k *ar,
+ struct sk_buff *msdu)
{
- struct sk_buff *msdu;
struct ieee80211_tx_info *info;
- spin_lock_bh(&ar->txmgmt_idr_lock);
- msdu = idr_remove(&ar->txmgmt_idr, buf_id);
- spin_unlock_bh(&ar->txmgmt_idr_lock);
-
- if (!msdu)
- return;
-
dma_unmap_single(ar->ab->dev, ATH11K_SKB_CB(msdu)->paddr, msdu->len,
DMA_TO_DEVICE);
@@ -6167,11 +6160,23 @@ static void ath11k_mac_tx_mgmt_free(struct ath11k *ar, int buf_id)
ath11k_mgmt_over_wmi_tx_drop(ar, msdu);
}
+static void ath11k_mac_tx_mgmt_free(struct ath11k *ar, int buf_id)
+{
+ struct sk_buff *msdu;
+
+ spin_lock_bh(&ar->txmgmt_idr_lock);
+ msdu = idr_remove(&ar->txmgmt_idr, buf_id);
+ spin_unlock_bh(&ar->txmgmt_idr_lock);
+
+ if (msdu)
+ ath11k_mac_tx_mgmt_free_skb(ar, msdu);
+}
+
int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
{
struct ath11k *ar = ctx;
- ath11k_mac_tx_mgmt_free(ar, buf_id);
+ ath11k_mac_tx_mgmt_free_skb(ar, skb);
return 0;
}
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/5] wifi: ath11k: avoid IDR mutation during vif mgmt TX cleanup
2026-09-26 15:48 [PATCH 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
2026-09-26 15:48 ` [PATCH 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup Jiale Yao
2026-09-26 15:48 ` [PATCH 2/5] wifi: ath11k: avoid IDR mutation during pending mgmt " Jiale Yao
@ 2026-09-26 15:48 ` Jiale Yao
2026-09-26 15:48 ` [PATCH 4/5] wifi: ath12k: avoid IDR mutation during pending " Jiale Yao
2026-09-26 15:48 ` [PATCH 5/5] wifi: ath12k: avoid IDR mutation during vif " Jiale Yao
4 siblings, 0 replies; 8+ messages in thread
From: Jiale Yao @ 2026-09-26 15:48 UTC (permalink / raw)
To: Jeff Johnson, Pradeep Kumar Chitrapu, Kalle Valo, Sven Eckelmann,
Govindaraj Saminathan, Ganesh Sesetti, linux-wireless, ath11k,
linux-kernel
Cc: Jiale Yao
ath11k_mac_op_remove_interface() walks txmgmt_idr with idr_for_each(),
and its callback removes each entry belonging to the interface. Removing
the current entry can invalidate the radix-tree iterator retained by
idr_for_each().
Move the walk into a helper that uses idr_for_each_entry(). It performs a
fresh lookup for every iteration, so each matching entry can be removed
through the locked removal helper without retaining iterator state across
the removal.
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
drivers/net/wireless/ath/ath11k/mac.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 696f9dd65ad4..07de423086c9 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -6181,16 +6181,18 @@ int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
return 0;
}
-static int ath11k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
+static void ath11k_mac_vif_txmgmt_cleanup(struct ath11k *ar,
+ struct ieee80211_vif *vif)
{
- struct ieee80211_vif *vif = ctx;
- struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB((struct sk_buff *)skb);
- struct ath11k *ar = skb_cb->ar;
-
- if (skb_cb->vif == vif)
- ath11k_mac_tx_mgmt_free(ar, buf_id);
+ struct ath11k_skb_cb *skb_cb;
+ struct sk_buff *skb;
+ int buf_id;
- return 0;
+ idr_for_each_entry(&ar->txmgmt_idr, skb, buf_id) {
+ skb_cb = ATH11K_SKB_CB(skb);
+ if (skb_cb->vif == vif)
+ ath11k_mac_tx_mgmt_free(ar, buf_id);
+ }
}
static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
@@ -7421,8 +7423,7 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
ath11k_peer_cleanup(ar, arvif->vdev_id);
- idr_for_each(&ar->txmgmt_idr,
- ath11k_mac_vif_txmgmt_idr_remove, vif);
+ ath11k_mac_vif_txmgmt_cleanup(ar, vif);
for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
spin_lock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 4/5] wifi: ath12k: avoid IDR mutation during pending mgmt TX cleanup
2026-09-26 15:48 [PATCH 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
` (2 preceding siblings ...)
2026-09-26 15:48 ` [PATCH 3/5] wifi: ath11k: avoid IDR mutation during vif " Jiale Yao
@ 2026-09-26 15:48 ` Jiale Yao
2026-09-28 5:49 ` Rameshkumar Sundaram
2026-09-26 15:48 ` [PATCH 5/5] wifi: ath12k: avoid IDR mutation during vif " Jiale Yao
4 siblings, 1 reply; 8+ messages in thread
From: Jiale Yao @ 2026-09-26 15:48 UTC (permalink / raw)
To: Jeff Johnson, Bhagavathi Perumal S, Balamurugan Selvarajan,
Baochen Qiang, Wen Gong, Carl Huang, linux-wireless, ath12k,
linux-kernel
Cc: Jiale Yao
ath12k_mac_tx_mgmt_pending_free() is passed as an idr_for_each()
callback and removes the current entry from txmgmt_idr. This can
invalidate the radix-tree iterator retained by idr_for_each().
Both callers destroy the IDR immediately after the walk, so removing
each entry in the callback is unnecessary. Split skb release from IDR
removal and let the callback release the supplied skb without updating
the IDR. The following idr_destroy() tears down the IDR itself.
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 99bf5cf79d10..7695b21149d1 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -9166,18 +9166,11 @@ static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
wake_up(&ar->txmgmt_empty_waitq);
}
-static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
+static void ath12k_mac_tx_mgmt_free_skb(struct ath12k *ar,
+ struct sk_buff *msdu)
{
- struct sk_buff *msdu;
struct ieee80211_tx_info *info;
- spin_lock_bh(&ar->txmgmt_idr_lock);
- msdu = idr_remove(&ar->txmgmt_idr, buf_id);
- spin_unlock_bh(&ar->txmgmt_idr_lock);
-
- if (!msdu)
- return;
-
dma_unmap_single(ar->ab->dev, ATH12K_SKB_CB(msdu)->paddr, msdu->len,
DMA_TO_DEVICE);
@@ -9187,11 +9180,23 @@ static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
ath12k_mgmt_over_wmi_tx_drop(ar, msdu);
}
+static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
+{
+ struct sk_buff *msdu;
+
+ spin_lock_bh(&ar->txmgmt_idr_lock);
+ msdu = idr_remove(&ar->txmgmt_idr, buf_id);
+ spin_unlock_bh(&ar->txmgmt_idr_lock);
+
+ if (msdu)
+ ath12k_mac_tx_mgmt_free_skb(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);
+ ath12k_mac_tx_mgmt_free_skb(ar, skb);
return 0;
}
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 5/5] wifi: ath12k: avoid IDR mutation during vif mgmt TX cleanup
2026-09-26 15:48 [PATCH 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
` (3 preceding siblings ...)
2026-09-26 15:48 ` [PATCH 4/5] wifi: ath12k: avoid IDR mutation during pending " Jiale Yao
@ 2026-09-26 15:48 ` Jiale Yao
4 siblings, 0 replies; 8+ messages in thread
From: Jiale Yao @ 2026-09-26 15:48 UTC (permalink / raw)
To: Jeff Johnson, Vasanthakumar Thiagarajan, Carl Huang,
Ramya Gnanasekar, P Praneesh, linux-wireless, ath12k,
linux-kernel
Cc: Jiale Yao
ath12k_mac_vdev_delete() walks txmgmt_idr with idr_for_each(), and its
callback removes each entry belonging to the interface. Removing the
current entry can invalidate the radix-tree iterator retained by
idr_for_each().
Move the walk into a helper that uses idr_for_each_entry(). It performs a
fresh lookup for every iteration, so each matching entry can be removed
through the locked removal helper without retaining iterator state across
the removal.
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 7695b21149d1..ba41b0fa728e 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -9201,16 +9201,18 @@ int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
return 0;
}
-static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
+static void ath12k_mac_vif_txmgmt_cleanup(struct ath12k *ar,
+ struct ieee80211_vif *vif)
{
- struct ieee80211_vif *vif = ctx;
- struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
- struct ath12k *ar = skb_cb->ar;
-
- if (skb_cb->vif == vif)
- ath12k_mac_tx_mgmt_free(ar, buf_id);
+ struct ath12k_skb_cb *skb_cb;
+ struct sk_buff *skb;
+ int buf_id;
- return 0;
+ idr_for_each_entry(&ar->txmgmt_idr, skb, buf_id) {
+ skb_cb = ATH12K_SKB_CB(skb);
+ if (skb_cb->vif == vif)
+ ath12k_mac_tx_mgmt_free(ar, buf_id);
+ }
}
static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arvif,
@@ -10972,8 +10974,7 @@ static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arv
ath12k_peer_cleanup(ar, arvif->vdev_id);
ath12k_ahvif_put_link_cache(ahvif, arvif->link_id);
- idr_for_each(&ar->txmgmt_idr,
- ath12k_mac_vif_txmgmt_idr_remove, vif);
+ ath12k_mac_vif_txmgmt_cleanup(ar, vif);
ath12k_mac_vif_unref(ath12k_ab_to_dp(ab), vif);
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 4/5] wifi: ath12k: avoid IDR mutation during pending mgmt TX cleanup
2026-09-26 15:48 ` [PATCH 4/5] wifi: ath12k: avoid IDR mutation during pending " Jiale Yao
@ 2026-09-28 5:49 ` Rameshkumar Sundaram
2026-09-28 8:26 ` jiale yao
0 siblings, 1 reply; 8+ messages in thread
From: Rameshkumar Sundaram @ 2026-09-28 5:49 UTC (permalink / raw)
To: Jiale Yao, Jeff Johnson, Bhagavathi Perumal S,
Balamurugan Selvarajan, Baochen Qiang, Wen Gong, Carl Huang,
linux-wireless, ath12k, linux-kernel
On 9/26/2026 9:18 PM, Jiale Yao wrote:
> ath12k_mac_tx_mgmt_pending_free() is passed as an idr_for_each()
> callback and removes the current entry from txmgmt_idr. This can
> invalidate the radix-tree iterator retained by idr_for_each().
>
> Both callers destroy the IDR immediately after the walk, so removing
> each entry in the callback is unnecessary. Split skb release from IDR
> removal and let the callback release the supplied skb without updating
> the IDR. The following idr_destroy() tears down the IDR itself.
>
> Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
> Signed-off-by: Jiale Yao <yaojiale02@163.com>
> ---
> drivers/net/wireless/ath/ath12k/mac.c | 25 +++++++++++++++----------
> 1 file changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 99bf5cf79d10..7695b21149d1 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -9166,18 +9166,11 @@ static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
> wake_up(&ar->txmgmt_empty_waitq);
> }
>
> -static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
> +static void ath12k_mac_tx_mgmt_free_skb(struct ath12k *ar,
> + struct sk_buff *msdu)
> {
> - struct sk_buff *msdu;
> struct ieee80211_tx_info *info;
>
> - spin_lock_bh(&ar->txmgmt_idr_lock);
> - msdu = idr_remove(&ar->txmgmt_idr, buf_id);
> - spin_unlock_bh(&ar->txmgmt_idr_lock);
> -
> - if (!msdu)
> - return;
> -
> dma_unmap_single(ar->ab->dev, ATH12K_SKB_CB(msdu)->paddr, msdu->len,
> DMA_TO_DEVICE);
>
> @@ -9187,11 +9180,23 @@ static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
> ath12k_mgmt_over_wmi_tx_drop(ar, msdu);
> }
>
> +static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
> +{
> + struct sk_buff *msdu;
> +
> + spin_lock_bh(&ar->txmgmt_idr_lock);
> + msdu = idr_remove(&ar->txmgmt_idr, buf_id);
> + spin_unlock_bh(&ar->txmgmt_idr_lock);
> +
> + if (msdu)
> + ath12k_mac_tx_mgmt_free_skb(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);
> + ath12k_mac_tx_mgmt_free_skb(ar, skb);
this now keeps the freed skbs in the idr for the whole time
idr_for_each() runs as opposed to previous implementation which removed
the idr entry as well which looked safe.
>
> return 0;
> }
--
Ramesh
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re:Re: [PATCH 4/5] wifi: ath12k: avoid IDR mutation during pending mgmt TX cleanup
2026-09-28 5:49 ` Rameshkumar Sundaram
@ 2026-09-28 8:26 ` jiale yao
0 siblings, 0 replies; 8+ messages in thread
From: jiale yao @ 2026-09-28 8:26 UTC (permalink / raw)
To: Rameshkumar Sundaram
Cc: Jeff Johnson, Bhagavathi Perumal S, Balamurugan Selvarajan,
Baochen Qiang, Wen Gong, Carl Huang, linux-wireless, ath12k,
linux-kernel
At 2026-09-28 13:49:54, "Rameshkumar Sundaram" <rameshkumar.sundaram@oss.qualcomm.com> wrote:
>On 9/26/2026 9:18 PM, Jiale Yao wrote:
>> ath12k_mac_tx_mgmt_pending_free() is passed as an idr_for_each()
>> callback and removes the current entry from txmgmt_idr. This can
>> invalidate the radix-tree iterator retained by idr_for_each().
>>
>> Both callers destroy the IDR immediately after the walk, so removing
>> each entry in the callback is unnecessary. Split skb release from IDR
>> removal and let the callback release the supplied skb without updating
>> the IDR. The following idr_destroy() tears down the IDR itself.
>>
>> Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
>> Signed-off-by: Jiale Yao <yaojiale02@163.com>
>> ---
>> drivers/net/wireless/ath/ath12k/mac.c | 25 +++++++++++++++----------
>> 1 file changed, 15 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
>> index 99bf5cf79d10..7695b21149d1 100644
>> --- a/drivers/net/wireless/ath/ath12k/mac.c
>> +++ b/drivers/net/wireless/ath/ath12k/mac.c
>> @@ -9166,18 +9166,11 @@ static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
>> wake_up(&ar->txmgmt_empty_waitq);
>> }
>>
>> -static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
>> +static void ath12k_mac_tx_mgmt_free_skb(struct ath12k *ar,
>> + struct sk_buff *msdu)
>> {
>> - struct sk_buff *msdu;
>> struct ieee80211_tx_info *info;
>>
>> - spin_lock_bh(&ar->txmgmt_idr_lock);
>> - msdu = idr_remove(&ar->txmgmt_idr, buf_id);
>> - spin_unlock_bh(&ar->txmgmt_idr_lock);
>> -
>> - if (!msdu)
>> - return;
>> -
>> dma_unmap_single(ar->ab->dev, ATH12K_SKB_CB(msdu)->paddr, msdu->len,
>> DMA_TO_DEVICE);
>>
>> @@ -9187,11 +9180,23 @@ static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
>> ath12k_mgmt_over_wmi_tx_drop(ar, msdu);
>> }
>>
>> +static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
>> +{
>> + struct sk_buff *msdu;
>> +
>> + spin_lock_bh(&ar->txmgmt_idr_lock);
>> + msdu = idr_remove(&ar->txmgmt_idr, buf_id);
>> + spin_unlock_bh(&ar->txmgmt_idr_lock);
>> +
>> + if (msdu)
>> + ath12k_mac_tx_mgmt_free_skb(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);
>> + ath12k_mac_tx_mgmt_free_skb(ar, skb);
>
>this now keeps the freed skbs in the idr for the whole time
>idr_for_each() runs as opposed to previous implementation which removed
>the idr entry as well which looked safe.
Thanks for the review.
The original issue is the same as the one fixed by commit c38b1e19485a
("firmware: arm_scmi: Avoid IDR updates while cleaning channels").
ath12k_mac_tx_mgmt_pending_free() is called from idr_for_each(), and
ath12k_mac_tx_mgmt_free() removes the current entry from that same IDR
before the iterator advances. This can invalidate the iterator state.
You are right that my patch leaves freed skb pointers in the IDR until
idr_destroy(), which is undesirable.
I will send a v2 using idr_for_each_entry(), which performs a fresh
idr_get_next() lookup for each iteration. The entry will then be removed
from the IDR before its skb is freed, avoiding both the invalid iterator
state and stale skb pointers.
Thanks,
Jiale
>
>
>>
>> return 0;
>> }
>
>
>--
>Ramesh
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-28 8:26 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-26 15:48 [PATCH 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
2026-09-26 15:48 ` [PATCH 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup Jiale Yao
2026-09-26 15:48 ` [PATCH 2/5] wifi: ath11k: avoid IDR mutation during pending mgmt " Jiale Yao
2026-09-26 15:48 ` [PATCH 3/5] wifi: ath11k: avoid IDR mutation during vif " Jiale Yao
2026-09-26 15:48 ` [PATCH 4/5] wifi: ath12k: avoid IDR mutation during pending " Jiale Yao
2026-09-28 5:49 ` Rameshkumar Sundaram
2026-09-28 8:26 ` jiale yao
2026-09-26 15:48 ` [PATCH 5/5] wifi: ath12k: avoid IDR mutation during vif " Jiale Yao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®