mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating
@ 2026-10-03  9:20 Jiale Yao
  2026-10-03  9:20 ` [PATCH v2 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup Jiale Yao
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Jiale Yao @ 2026-10-03  9:20 UTC (permalink / raw)
  To: Jeff Johnson, Kalle Valo, Michal Kazior, Shashidhar Lakkavalli,
	Bhagavathi Perumal S, Karthikeyan Periyasamy,
	Govindaraj Saminathan, Sriram R, Carl Huang,
	Vasanthakumar Thiagarajan, Wen Gong, Ramya Gnanasekar,
	linux-wireless, ath10k, linux-kernel, ath11k, ath12k
  Cc: Jiale Yao

The ath10k, ath11k, and ath12k cleanup paths walk an IDR while removing
the current entry. idr_for_each() retains radix-tree iterator state across
the callback, so that removal can invalidate the walk.

Use idr_for_each_entry() in each cleanup path. It performs a fresh
idr_get_next() lookup for every iteration, allowing the current entry to
be removed safely before its skb is released. Keeping the existing locked
removal helpers also ensures that a concurrent TX completion cannot find
an IDR entry which points to an already freed skb.

Changes in v2:
- Rework the ath11k and ath12k pending management TX cleanup patches to
  remove each IDR entry before freeing its skb, as pointed out by
  Rameshkumar and Jeff.
- Use idr_for_each_entry() for the pending cleanup callers instead of
  leaving freed skb pointers in the IDR until idr_destroy().

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/core.c   |  3 +--
 drivers/net/wireless/ath/ath11k/mac.c    | 33 ++++++++++++------------
 drivers/net/wireless/ath/ath11k/mac.h    |  2 +-
 drivers/net/wireless/ath/ath12k/core.c   |  3 +--
 drivers/net/wireless/ath/ath12k/mac.c    | 33 ++++++++++++------------
 drivers/net/wireless/ath/ath12k/mac.h    |  2 +-
 7 files changed, 44 insertions(+), 39 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup
  2026-10-03  9:20 [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
@ 2026-10-03  9:20 ` Jiale Yao
  2026-10-10  1:31   ` Jeff Johnson
  2026-10-03  9:20 ` [PATCH v2 2/5] wifi: ath11k: avoid IDR mutation during pending mgmt " Jiale Yao
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Jiale Yao @ 2026-10-03  9:20 UTC (permalink / raw)
  To: Jeff Johnson, Michal Kazior, Kalle Valo, 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] 9+ messages in thread

* [PATCH v2 2/5] wifi: ath11k: avoid IDR mutation during pending mgmt TX cleanup
  2026-10-03  9:20 [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
  2026-10-03  9:20 ` [PATCH v2 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup Jiale Yao
@ 2026-10-03  9:20 ` Jiale Yao
  2026-10-03  9:21 ` [PATCH v2 3/5] wifi: ath11k: avoid IDR mutation during vif " Jiale Yao
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Jiale Yao @ 2026-10-03  9:20 UTC (permalink / raw)
  To: Jeff Johnson, Manikanta Pubbisetty, kbuild test robot,
	Vasanthakumar Thiagarajan, Maharaja Kennadyrajan,
	Rajkumar Manoharan, linux-wireless, ath11k, linux-kernel
  Cc: Jiale Yao

The pending management TX cleanup walks txmgmt_idr with idr_for_each(),
and its callback removes the current entry. This can invalidate the
radix-tree iterator retained by idr_for_each().

Use idr_for_each_entry() so every iteration starts with a fresh lookup.
Continue to remove each entry under txmgmt_idr_lock before freeing its skb,
preventing concurrent TX completion from finding a stale skb pointer.

Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
 drivers/net/wireless/ath/ath11k/core.c |  3 +--
 drivers/net/wireless/ath/ath11k/mac.c  | 12 ++++++------
 drivers/net/wireless/ath/ath11k/mac.h  |  2 +-
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 8039124e7832..31ac17c51036 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -2449,8 +2449,7 @@ void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
 		complete(&ar->thermal.wmi_sync);
 
 		wake_up(&ar->dp.tx_empty_waitq);
-		idr_for_each(&ar->txmgmt_idr,
-			     ath11k_mac_tx_mgmt_pending_free, ar);
+		ath11k_mac_tx_mgmt_pending_free(ar);
 		idr_destroy(&ar->txmgmt_idr);
 		wake_up(&ar->txmgmt_empty_waitq);
 
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index ae91b57c8422..f9af403a2f0d 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -6167,13 +6167,13 @@ static void ath11k_mac_tx_mgmt_free(struct ath11k *ar, int buf_id)
 	ath11k_mgmt_over_wmi_tx_drop(ar, msdu);
 }
 
-int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
+void ath11k_mac_tx_mgmt_pending_free(struct ath11k *ar)
 {
-	struct ath11k *ar = ctx;
-
-	ath11k_mac_tx_mgmt_free(ar, buf_id);
+	struct sk_buff *msdu;
+	int buf_id;
 
-	return 0;
+	idr_for_each_entry(&ar->txmgmt_idr, msdu, buf_id)
+		ath11k_mac_tx_mgmt_free(ar, buf_id);
 }
 
 static int ath11k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
@@ -10417,7 +10417,7 @@ static void __ath11k_mac_unregister(struct ath11k *ar)
 
 	ieee80211_unregister_hw(ar->hw);
 
-	idr_for_each(&ar->txmgmt_idr, ath11k_mac_tx_mgmt_pending_free, ar);
+	ath11k_mac_tx_mgmt_pending_free(ar);
 	idr_destroy(&ar->txmgmt_idr);
 
 	kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h
index 59f83c7175fd..127cb476b44b 100644
--- a/drivers/net/wireless/ath/ath11k/mac.h
+++ b/drivers/net/wireless/ath/ath11k/mac.h
@@ -162,7 +162,7 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id)
 
 void ath11k_mac_drain_tx(struct ath11k *ar);
 void ath11k_mac_peer_cleanup_all(struct ath11k *ar);
-int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
+void ath11k_mac_tx_mgmt_pending_free(struct ath11k *ar);
 u8 ath11k_mac_bw_to_mac80211_bw(u8 bw);
 enum nl80211_he_gi ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi);
 enum nl80211_he_ru_alloc ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy);
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 3/5] wifi: ath11k: avoid IDR mutation during vif mgmt TX cleanup
  2026-10-03  9:20 [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
  2026-10-03  9:20 ` [PATCH v2 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup Jiale Yao
  2026-10-03  9:20 ` [PATCH v2 2/5] wifi: ath11k: avoid IDR mutation during pending mgmt " Jiale Yao
@ 2026-10-03  9:21 ` Jiale Yao
  2026-10-03  9:21 ` [PATCH v2 4/5] wifi: ath12k: avoid IDR mutation during pending " Jiale Yao
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Jiale Yao @ 2026-10-03  9:21 UTC (permalink / raw)
  To: Jeff Johnson, Maharaja Kennadyrajan, Govindaraj Saminathan,
	Karthikeyan Periyasamy, Rajkumar Manoharan, Sriram R,
	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 f9af403a2f0d..e7ece258f142 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -6176,16 +6176,18 @@ void ath11k_mac_tx_mgmt_pending_free(struct ath11k *ar)
 		ath11k_mac_tx_mgmt_free(ar, buf_id);
 }
 
-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,
@@ -7416,8 +7418,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] 9+ messages in thread

* [PATCH v2 4/5] wifi: ath12k: avoid IDR mutation during pending mgmt TX cleanup
  2026-10-03  9:20 [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
                   ` (2 preceding siblings ...)
  2026-10-03  9:21 ` [PATCH v2 3/5] wifi: ath11k: avoid IDR mutation during vif " Jiale Yao
@ 2026-10-03  9:21 ` Jiale Yao
  2026-10-03  9:21 ` [PATCH v2 5/5] wifi: ath12k: avoid IDR mutation during vif " Jiale Yao
  2026-10-10 17:07 ` [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating Jeff Johnson
  5 siblings, 0 replies; 9+ messages in thread
From: Jiale Yao @ 2026-10-03  9:21 UTC (permalink / raw)
  To: Jeff Johnson, Carl Huang, Baochen Qiang, Pradeep Kumar Chitrapu,
	Wen Gong, Kalle Valo, linux-wireless, ath12k, linux-kernel
  Cc: Jiale Yao

The pending management TX cleanup walks txmgmt_idr with idr_for_each(),
and its callback removes the current entry. This can invalidate the
radix-tree iterator retained by idr_for_each().

Use idr_for_each_entry() so every iteration starts with a fresh lookup.
Continue to remove each entry under txmgmt_idr_lock before freeing its skb,
preventing concurrent TX completion from finding a stale skb pointer.

Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
 drivers/net/wireless/ath/ath12k/core.c |  3 +--
 drivers/net/wireless/ath/ath12k/mac.c  | 12 ++++++------
 drivers/net/wireless/ath/ath12k/mac.h  |  2 +-
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index 262a2045309b..e9aa5e4e999d 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -1514,8 +1514,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
 			complete_all(&ar->thermal.wmi_sync);
 
 			wake_up(&ar->dp.tx_empty_waitq);
-			idr_for_each(&ar->txmgmt_idr,
-				     ath12k_mac_tx_mgmt_pending_free, ar);
+			ath12k_mac_tx_mgmt_pending_free(ar);
 			idr_destroy(&ar->txmgmt_idr);
 			wake_up(&ar->txmgmt_empty_waitq);
 
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 99bf5cf79d10..c0acb92b7320 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -9187,13 +9187,13 @@ static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id)
 	ath12k_mgmt_over_wmi_tx_drop(ar, msdu);
 }
 
-int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
+void ath12k_mac_tx_mgmt_pending_free(struct ath12k *ar)
 {
-	struct ath12k *ar = ctx;
-
-	ath12k_mac_tx_mgmt_free(ar, buf_id);
+	struct sk_buff *msdu;
+	int buf_id;
 
-	return 0;
+	idr_for_each_entry(&ar->txmgmt_idr, msdu, buf_id)
+		ath12k_mac_tx_mgmt_free(ar, buf_id);
 }
 
 static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
@@ -14725,7 +14725,7 @@ static struct wiphy_iftype_ext_capab ath12k_iftypes_ext_capa[] = {
 
 static void ath12k_mac_cleanup_unregister(struct ath12k *ar)
 {
-	idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, ar);
+	ath12k_mac_tx_mgmt_pending_free(ar);
 	idr_destroy(&ar->txmgmt_idr);
 
 	kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h
index aba98afd4365..ae44ebfd9bd9 100644
--- a/drivers/net/wireless/ath/ath12k/mac.h
+++ b/drivers/net/wireless/ath/ath12k/mac.h
@@ -173,7 +173,7 @@ struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id)
 void ath12k_mac_drain_tx(struct ath12k *ar);
 void ath12k_mac_peer_cleanup_all(struct ath12k *ar);
 void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah);
-int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
+void ath12k_mac_tx_mgmt_pending_free(struct ath12k *ar);
 enum rate_info_bw ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw);
 enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw);
 enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher);
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 5/5] wifi: ath12k: avoid IDR mutation during vif mgmt TX cleanup
  2026-10-03  9:20 [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
                   ` (3 preceding siblings ...)
  2026-10-03  9:21 ` [PATCH v2 4/5] wifi: ath12k: avoid IDR mutation during pending " Jiale Yao
@ 2026-10-03  9:21 ` Jiale Yao
  2026-10-10 17:07 ` [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating Jeff Johnson
  5 siblings, 0 replies; 9+ messages in thread
From: Jiale Yao @ 2026-10-03  9:21 UTC (permalink / raw)
  To: Jeff Johnson, Vasanthakumar Thiagarajan, Balamurugan Selvarajan,
	Sriram R, Carl Huang, 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 c0acb92b7320..108ace48cc97 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -9196,16 +9196,18 @@ void ath12k_mac_tx_mgmt_pending_free(struct ath12k *ar)
 		ath12k_mac_tx_mgmt_free(ar, buf_id);
 }
 
-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,
@@ -10967,8 +10969,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] 9+ messages in thread

* Re: [PATCH v2 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup
  2026-10-03  9:20 ` [PATCH v2 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup Jiale Yao
@ 2026-10-10  1:31   ` Jeff Johnson
  2026-10-10 14:20     ` Jeff Johnson
  0 siblings, 1 reply; 9+ messages in thread
From: Jeff Johnson @ 2026-10-10  1:31 UTC (permalink / raw)
  To: Jiale Yao, Jeff Johnson, Michal Kazior, Kalle Valo,
	linux-wireless, ath10k, linux-kernel

On 10/3/2026 2:20 AM, Jiale Yao wrote:
> 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);

my review agent notes:
**Actionable issue:** `ath10k_htt_tx_clean_up_pending` retains its old
`idr_for_each`-callback signature even though it's now called directly:

```c
static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
```

The `skb` parameter is completely unused inside the function — it's not
read anywhere. Since this is a `static` function no longer used as a
callback, the signature should be cleaned up in the same patch:

- Remove the unused `void *skb` parameter
- Change `void *ctx` to `struct ath10k *ar`
- Make the return type `void` (the `return 0` is vestigial)

As-is, the call site `ath10k_htt_tx_clean_up_pending(msdu_id, msdu, htt->ar)`
passes `msdu` as a `void *` that the callee silently discards — confusing
for future readers.

>  }
>  
>  void ath10k_htt_tx_stop(struct ath10k_htt *htt)


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup
  2026-10-10  1:31   ` Jeff Johnson
@ 2026-10-10 14:20     ` Jeff Johnson
  0 siblings, 0 replies; 9+ messages in thread
From: Jeff Johnson @ 2026-10-10 14:20 UTC (permalink / raw)
  To: Jiale Yao, Jeff Johnson, Michal Kazior, Kalle Valo,
	linux-wireless, ath10k, linux-kernel

On 10/9/2026 6:31 PM, Jeff Johnson wrote:
> On 10/3/2026 2:20 AM, Jiale Yao wrote:
>> 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);
> 
> my review agent notes:
> **Actionable issue:** `ath10k_htt_tx_clean_up_pending` retains its old
> `idr_for_each`-callback signature even though it's now called directly:
> 
> ```c
> static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
> ```
> 
> The `skb` parameter is completely unused inside the function — it's not
> read anywhere. Since this is a `static` function no longer used as a
> callback, the signature should be cleaned up in the same patch:
> 
> - Remove the unused `void *skb` parameter
> - Change `void *ctx` to `struct ath10k *ar`
> - Make the return type `void` (the `return 0` is vestigial)
> 
> As-is, the call site `ath10k_htt_tx_clean_up_pending(msdu_id, msdu, htt->ar)`
> passes `msdu` as a `void *` that the callee silently discards — confusing
> for future readers.

BTW no need to send a new version to address this unless reviewers have other
issues -- I'll make this change when applying the patches to my 'pending' branch


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating
  2026-10-03  9:20 [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
                   ` (4 preceding siblings ...)
  2026-10-03  9:21 ` [PATCH v2 5/5] wifi: ath12k: avoid IDR mutation during vif " Jiale Yao
@ 2026-10-10 17:07 ` Jeff Johnson
  5 siblings, 0 replies; 9+ messages in thread
From: Jeff Johnson @ 2026-10-10 17:07 UTC (permalink / raw)
  To: Jiale Yao, Jeff Johnson, Shashidhar Lakkavalli, linux-wireless,
	ath10k, linux-kernel, ath11k, ath12k

On 10/3/2026 2:20 AM, Jiale Yao wrote:
> The ath10k, ath11k, and ath12k cleanup paths walk an IDR while removing
> the current entry. idr_for_each() retains radix-tree iterator state across
> the callback, so that removal can invalidate the walk.
> 
> Use idr_for_each_entry() in each cleanup path. It performs a fresh
> idr_get_next() lookup for every iteration, allowing the current entry to
> be removed safely before its skb is released. Keeping the existing locked
> removal helpers also ensures that a concurrent TX completion cannot find
> an IDR entry which points to an already freed skb.
> 
> Changes in v2:
> - Rework the ath11k and ath12k pending management TX cleanup patches to
>   remove each IDR entry before freeing its skb, as pointed out by
>   Rameshkumar and Jeff.
> - Use idr_for_each_entry() for the pending cleanup callers instead of
>   leaving freed skb pointers in the IDR until idr_destroy().
> 
> 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/core.c   |  3 +--
>  drivers/net/wireless/ath/ath11k/mac.c    | 33 ++++++++++++------------
>  drivers/net/wireless/ath/ath11k/mac.h    |  2 +-
>  drivers/net/wireless/ath/ath12k/core.c   |  3 +--
>  drivers/net/wireless/ath/ath12k/mac.c    | 33 ++++++++++++------------
>  drivers/net/wireless/ath/ath12k/mac.h    |  2 +-
>  7 files changed, 44 insertions(+), 39 deletions(-)
> 

(dropped obsolete codeaurora and quicinc addresses)
Version with the ath10k change updated is in my 'pending' branch:
https://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git/commit/?h=pending&id=3d806fd957b02ca1fa7991ffaf6c02ddd3dcbfe4

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-10-10 17:07 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-03  9:20 [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating Jiale Yao
2026-10-03  9:20 ` [PATCH v2 1/5] wifi: ath10k: avoid IDR mutation during TX cleanup Jiale Yao
2026-10-10  1:31   ` Jeff Johnson
2026-10-10 14:20     ` Jeff Johnson
2026-10-03  9:20 ` [PATCH v2 2/5] wifi: ath11k: avoid IDR mutation during pending mgmt " Jiale Yao
2026-10-03  9:21 ` [PATCH v2 3/5] wifi: ath11k: avoid IDR mutation during vif " Jiale Yao
2026-10-03  9:21 ` [PATCH v2 4/5] wifi: ath12k: avoid IDR mutation during pending " Jiale Yao
2026-10-03  9:21 ` [PATCH v2 5/5] wifi: ath12k: avoid IDR mutation during vif " Jiale Yao
2026-10-10 17:07 ` [PATCH v2 0/5] wifi: ath: avoid IDR mutation while iterating Jeff Johnson

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®