Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH wireless-next v2 16/28] wifi: iwlwifi: mld: Check for null in iwl_mld_wait_sta_txqs_empty
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

I saw some crashes here in eMLSR torture test, looks like mld_txq
was NULL, so add check.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/sta.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
index 6338ca46f68e..288fc4b7604e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
@@ -789,7 +789,7 @@ void iwl_mld_wait_sta_txqs_empty(struct iwl_mld *mld, struct ieee80211_sta *sta)
 		struct iwl_mld_txq *mld_txq =
 			iwl_mld_txq_from_mac80211(sta->txq[i]);
 
-		if (!mld_txq->status.allocated)
+		if (!mld_txq || !mld_txq->status.allocated)
 			continue;
 
 		iwl_trans_wait_txq_empty(mld->trans, mld_txq->fw_id);
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 17/28] wifi: iwlwifi: mld: use warn-on-once in error path.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Just splat a WARNING once, and add debug output to indicate
a bit about why it is hitting the warn path.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/agg.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
index 23d55374ef8a..413a8688e4eb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/agg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
@@ -496,7 +496,9 @@ static void iwl_mld_free_reorder_buffer(struct iwl_mld *mld,
 		 * sync internal DELBA notification should trigger a release
 		 * of all frames in the reorder buffer.
 		 */
-		WARN_ON(1);
+		WARN_ON_ONCE(1);
+		IWL_ERR(mld, "free-reorder-buffer problem, rxq: %d  num-stored: %d, will purge frames\n",
+			i, reorder_buf->num_stored);
 
 		for (int j = 0; j < data->buf_size; j++)
 			__skb_queue_purge(&entries[j].frames);
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 14/28] wifi: mac80211: Add dmesg log regarding warn-on in drv-stop.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

And make it WARN_ON_ONCE.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/driver-ops.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index 59998d0af3ff..397a0281412a 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -38,8 +38,10 @@ void drv_stop(struct ieee80211_local *local, bool suspend)
 	might_sleep();
 	lockdep_assert_wiphy(local->hw.wiphy);
 
-	if (WARN_ON(!local->started))
+	if (WARN_ON_ONCE(!local->started)) {
+		pr_err("mac80211: drv-stop called but local is not started.\n");
 		return;
+	}
 
 	trace_drv_stop(local, suspend);
 	local->ops->stop(&local->hw, suspend);
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 10/28] wifi: mac80211: Ensure sta debugfs is not double-freed.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

I saw an instance where use-after-free was found when attempting to
delete sta's debugfs.  Add check to netdev debugfs free logic to ensure
any sta's that still exist have nulled out debugfs entries since
netdev is going to do a recursive debugfs delete.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/debugfs_netdev.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 000859b8c005..2e4bc34e6c5c 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -1063,6 +1063,8 @@ ieee80211_debugfs_clear_link_ptr(struct ieee80211_sub_if_data *sdata,
 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_link_data *link;
+	struct rhashtable_iter hti;
+	struct sta_info *sta;
 	struct dentry *dir;
 	int i;
 
@@ -1083,6 +1085,28 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 
 		link->debugfs_dir = NULL;
 	}
+
+	/* And, same for all stations.  See ieee80211_sta_debugfs_add where
+	 * they are added to the sdata->debugfs.subdir_stations directory
+	 */
+	rhashtable_walk_enter(&sdata->local->sta_hash.ht, &hti);
+	rhashtable_walk_start(&hti);
+
+	while ((sta = rhashtable_walk_next(&hti))) {
+		if (IS_ERR(sta)) {
+			if (PTR_ERR(sta) != -EAGAIN)
+				break;
+			continue;
+		}
+		if (sta->sdata != sdata)
+			continue;
+
+		sta->debugfs_dir = NULL;
+	}
+
+	rhashtable_walk_stop(&hti);
+	rhashtable_walk_exit(&hti);
+
 	rcu_read_unlock();
 
 	dir = sdata->vif.debugfs_dir;
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 12/28] wifi: iwlwifi: mld:  Improve logging in error cases.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

To give better understanding of how and when failures
happen.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/sta.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
index c478cee570a2..6338ca46f68e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
@@ -574,7 +574,8 @@ static int iwl_mld_rm_sta_from_fw(struct iwl_mld *mld, u8 fw_sta_id)
 				   WIDE_ID(MAC_CONF_GROUP, STA_REMOVE_CMD),
 				   &cmd);
 	if (ret)
-		IWL_ERR(mld, "Failed to remove station. Id=%d\n", fw_sta_id);
+		IWL_ERR(mld, "Failed to remove station. Id=%d ret: %d\n",
+			fw_sta_id, ret);
 
 	return ret;
 }
@@ -735,8 +736,10 @@ int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
 	int ret;
 
 	ret = iwl_mld_init_sta(mld, sta, vif, type);
-	if (ret)
+	if (ret) {
+		IWL_ERR(mld, "iwl-mld-add-sta, mld-init-sta failed. ret=%d\n", ret);
 		return ret;
+	}
 
 	/* We could have add only the deflink link_sta, but it will not work
 	 * in the restart case if the single link that is active during
@@ -744,8 +747,10 @@ int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
 	 */
 	for_each_sta_active_link(mld_sta->vif, sta, link_sta, link_id) {
 		ret = iwl_mld_add_link_sta(mld, link_sta);
-		if (ret)
+		if (ret) {
+			IWL_ERR(mld, "iwl-mld-add-sta, mld-add-link-sta failed. ret=%d\n", ret);
 			goto destroy_sta;
+		}
 	}
 
 	return 0;
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 08/28] wifi: mac80211: Debugfs safety checks.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Safety checks in case links are not be properly cleaned up at
the time we are removing netdev debugfs.  Since link debugfs
is child of netdev debugfs, and we are about to recursively clean
up the netdev tree, be sure to null out any debugfs inode pointers
in the child links.

Root cause of the inode use-after-free is something
different, but this patch may also make system more resiliant.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/debugfs_netdev.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index bc2da35db4ae..000859b8c005 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -1037,9 +1037,33 @@ static void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata,
 		add_link_files(&sdata->deflink, sdata->vif.debugfs_dir);
 }
 
+static void
+ieee80211_debugfs_clear_link_ptr(struct ieee80211_sub_if_data *sdata,
+				 struct dentry *dir)
+{
+	struct ieee80211_link_data *link;
+	int i;
+
+	rcu_read_lock();
+
+	if (sdata->vif.debugfs_dir == dir)
+		sdata->vif.debugfs_dir = NULL;
+
+	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+		link = rcu_access_pointer(sdata->link[i]);
+		if (!link)
+			continue;
+
+		if (dir == link->debugfs_dir)
+			link->debugfs_dir = NULL;
+	}
+	rcu_read_unlock();
+}
+
 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_link_data *link;
+	struct dentry *dir;
 	int i;
 
 	if (!sdata->vif.debugfs_dir)
@@ -1061,8 +1085,10 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 	}
 	rcu_read_unlock();
 
-	debugfs_remove_recursive(sdata->vif.debugfs_dir);
+	dir = sdata->vif.debugfs_dir;
+	debugfs_remove_recursive(dir);
 	sdata->vif.debugfs_dir = NULL;
+	ieee80211_debugfs_clear_link_ptr(sdata, dir);
 	sdata->debugfs.subdir_stations = NULL;
 }
 
@@ -1151,7 +1177,7 @@ void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link)
 
 	/* Recreate the directory excluding the driver data */
 	debugfs_remove_recursive(link->debugfs_dir);
-	link->debugfs_dir = NULL;
+	ieee80211_debugfs_clear_link_ptr(link->sdata, link->debugfs_dir);
 
 	ieee80211_link_debugfs_add(link);
 }
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 15/28] wifi: iwlwifi: mld: Fix use-after-free of bss_conf
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

In certain failure paths, the driver is not fully configured, and
it fails to find the link object.  We still need to remove pointers
to the bss_conf to keep from crashing shortly afterwards.

Search all indices for stale pointer if we cannot do the fast
lookup by ID.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/link.c | 42 +++++++++++++++----
 1 file changed, 34 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c
index b5430e8a73d6..1e4959ceb3db 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c
@@ -504,23 +504,49 @@ void iwl_mld_remove_link(struct iwl_mld *mld,
 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(bss_conf->vif);
 	struct iwl_mld_link *link = iwl_mld_link_from_mac80211(bss_conf);
 	bool is_deflink = link == &mld_vif->deflink;
-	u8 fw_id = link->fw_id;
+	u16 fw_id;
 
-	if (WARN_ON(!link || link->active))
-		return;
+	if (WARN_ON_ONCE(!link)) {
+		IWL_ERR(mld, "Remove nonexistent link, bss_conf: 0x%px link-id: %d\n",
+			bss_conf, bss_conf->link_id);
+		fw_id = 0xffff;
+	} else {
+		fw_id  = link->fw_id;
+	}
+
+	/* Not cleaning it up seems worse than cleaning up an active link,
+	 * so continue on even in warning case.
+	 */
+	if (link && WARN_ON_ONCE(link->active))
+		IWL_ERR(mld, "Removing active link, id: %d\n",
+			bss_conf->link_id);
 
 	iwl_mld_rm_link_from_fw(mld, bss_conf);
 	/* Continue cleanup on failure */
 
-	if (!is_deflink)
+	if (link && !is_deflink)
 		kfree_rcu(link, rcu_head);
 
+	rcu_read_lock();
 	RCU_INIT_POINTER(mld_vif->link[bss_conf->link_id], NULL);
 
-	if (WARN_ON(fw_id >= mld->fw->ucode_capa.num_links))
-		return;
-
-	RCU_INIT_POINTER(mld->fw_id_to_bss_conf[fw_id], NULL);
+	if (fw_id >= mld->fw->ucode_capa.num_links) {
+		struct ieee80211_bss_conf *tmp_bss_conf;
+		int i;
+
+		/* Search for any existing back-pointer */
+		for (i = 0; i < ARRAY_SIZE(mld->fw_id_to_bss_conf); i++) {
+			tmp_bss_conf = rcu_dereference(mld->fw_id_to_bss_conf[i]);
+			if (tmp_bss_conf == bss_conf) {
+				IWL_ERR(mld, "WARNING: Found bss_conf in fw_id_to_bss_conf[%i], Nulling pointer.\n",
+					i);
+				RCU_INIT_POINTER(mld->fw_id_to_bss_conf[i], NULL);
+			}
+		}
+	} else {
+		RCU_INIT_POINTER(mld->fw_id_to_bss_conf[fw_id], NULL);
+	}
+	rcu_read_unlock();
 }
 
 void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 18/28] wifi: iwlwifi: mld: Use warn-on-once in emlsr exit logic.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Only splat warning once, and improve logging to indicate more
about why it is in the problem state.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
index f842f5183223..7a37ca64a612 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
@@ -164,7 +164,10 @@ static void iwl_mld_check_emlsr_prevention(struct iwl_mld *mld,
 		 * The timeouts are chosen so that this will not happen, i.e.
 		 * IWL_MLD_EMLSR_PREVENT_LONG > IWL_MLD_PREVENT_EMLSR_TIMEOUT
 		 */
-		WARN_ON(mld_vif->emlsr.exit_repeat_count > 3);
+		if (WARN_ON_ONCE(mld_vif->emlsr.exit_repeat_count > 3)) {
+			IWL_ERR(mld, "check-emlsr-prevention exit repeats: %d > 3, blocked-reasons: 0x%x\n",
+				mld_vif->emlsr.exit_repeat_count, mld_vif->emlsr.blocked_reasons);
+		}
 	}
 
 	IWL_DEBUG_EHT(mld,
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 09/28] wifi: mac80211: Use warn-on-once in drv_remove_chanctxt
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

But still log it to dmesg.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/driver-ops.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 51bf3c7822a7..e2283d7dcd1e 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1035,8 +1035,10 @@ static inline void drv_remove_chanctx(struct ieee80211_local *local,
 	might_sleep();
 	lockdep_assert_wiphy(local->hw.wiphy);
 
-	if (WARN_ON(!ctx->driver_present))
+	if (WARN_ON_ONCE(!ctx->driver_present)) {
+		pr_err("drv-remove-chanctx, NOT driver_present, not sending request to driver.");
 		return;
+	}
 
 	trace_drv_remove_chanctx(local, ctx);
 	if (local->ops->remove_chanctx)
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 13/28] wifi: iwlwifi: mld: Remove warning about BAID.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

It seems to be expected behaviour, and is seen fairly often
in testing in adverse conditions, so make it a one-line log
message instead of WARN splat.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/agg.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
index a757077b0a7a..23d55374ef8a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/agg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
@@ -216,10 +216,16 @@ iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,
 	if (baid == IWL_RX_REORDER_DATA_INVALID_BAID)
 		return IWL_MLD_PASS_SKB;
 
-	/* no sta yet */
-	if (WARN_ONCE(!sta,
-		      "Got valid BAID without a valid station assigned\n"))
+	/* no sta yet.  This happens fairly often, don't WARN_ON about it. */
+	if (!sta) {
+		static bool done_once;
+
+		if (!done_once) {
+			IWL_ERR(mld, "Got valid BAID without a valid station assigned, will not log again.\n");
+			done_once = true;
+		}
 		return IWL_MLD_PASS_SKB;
+	}
 
 	mld_sta = iwl_mld_sta_from_mac80211(sta);
 
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 20/28] wifi: iwlwifi: mld: Improve logging message.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Indicate that the problem is being fixed.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index 0c53d6bd9651..1557aa2a4866 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -647,7 +647,7 @@ void iwl_mld_mac80211_stop(struct ieee80211_hw *hw, bool suspend)
 	 */
 	for (int i = 0; i < ARRAY_SIZE(mld->scan.uid_status); i++)
 		if (WARN_ONCE(mld->scan.uid_status[i],
-			      "UMAC scan UID %d status was not cleaned (0x%x 0x%x)\n",
+			      "mac80211-stop: UMAC scan UID %d status was not cleaned (0x%x 0x%x), forcing to 0\n",
 			      i, mld->scan.uid_status[i], mld->scan.status))
 			mld->scan.uid_status[i] = 0;
 }
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 21/28] wifi: iwlwifi: mld: Protect from null mld_sta
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Torture tests were crashing here, protect against a null
mld_sta.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index 1557aa2a4866..43bc73764dcd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -1911,6 +1911,7 @@ static void iwl_mld_mac80211_flush(struct ieee80211_hw *hw,
 	iwl_mld_add_txq_list(mld);
 
 	for (int i = 0; i < mld->fw->ucode_capa.num_stations; i++) {
+		struct iwl_mld_sta *mld_sta;
 		struct ieee80211_link_sta *link_sta =
 			wiphy_dereference(mld->wiphy,
 					  mld->fw_id_to_link_sta[i]);
@@ -1919,7 +1920,8 @@ static void iwl_mld_mac80211_flush(struct ieee80211_hw *hw,
 			continue;
 
 		/* Check that the sta belongs to the given vif */
-		if (vif && vif != iwl_mld_sta_from_mac80211(link_sta->sta)->vif)
+		mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta);
+		if (vif && (!mld_sta || vif != mld_sta->vif))
 			continue;
 
 		if (drop)
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 23/28] wifi: iwlwifi: mld: Support force-cleanup op
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

This lets mac80211 force the driver to clean up any lingering
configuration, fixing use-after-free in case of unrecoverable
hardware failure.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index 43bc73764dcd..31a3818f32bc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -560,6 +560,18 @@ iwl_mld_restart_cleanup(struct iwl_mld *mld)
 	iwl_mld_ftm_restart_cleanup(mld);
 }
 
+/* mac80211 thinks our driver/firmware/hardware has crashed
+ * and cannot be recovered.  Force clean any existing configuration
+ * (stas, etc), as mac80211 will not attempt further cleanup.
+ */
+static void iwl_mld_mac80211_force_cleanup(struct ieee80211_hw *hw)
+{
+	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
+
+	IWL_ERR(mld, "mac80211-force-cleanup called, calling mld_restart_cleanup.\n");
+	iwl_mld_restart_cleanup(mld);
+}
+
 static
 int iwl_mld_mac80211_start(struct ieee80211_hw *hw)
 {
@@ -2717,6 +2729,7 @@ const struct ieee80211_ops iwl_mld_hw_ops = {
 	.config = iwl_mld_mac80211_config,
 	.get_antenna = iwl_mld_get_antenna,
 	.set_antenna = iwl_mld_set_antenna,
+	.force_cleanup = iwl_mld_mac80211_force_cleanup,
 	.add_interface = iwl_mld_mac80211_add_interface,
 	.remove_interface = iwl_mld_mac80211_remove_interface,
 	.conf_tx = iwl_mld_mac80211_conf_tx,
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 19/28] wifi: iwlwifi: mld: Improve error message in rx path.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Print return code that is causing the failure path.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/rx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c
index 214dcfde2fb4..f5c20a3aa869 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c
@@ -2204,8 +2204,8 @@ void iwl_mld_sync_rx_queues(struct iwl_mld *mld,
 	ret = wait_event_timeout(mld->rxq_sync.waitq,
 				 READ_ONCE(mld->rxq_sync.state) == 0,
 				 SYNC_RX_QUEUE_TIMEOUT);
-	WARN_ONCE(!ret, "RXQ sync failed: state=0x%lx, cookie=%d\n",
-		  mld->rxq_sync.state, mld->rxq_sync.cookie);
+	WARN_ONCE(!ret, "RXQ sync failed: state=0x%lx, cookie=%d, ret: %d\n",
+		  mld->rxq_sync.state, mld->rxq_sync.cookie, ret);
 
 out:
 	mld->rxq_sync.state = 0;
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 24/28] wifi: iwlwifi: mld: Fix NPE in flush logic.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

It appears that sometimes the sta can be NULL, so check for
that and return early.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/sta.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
index 288fc4b7604e..06e064466e3b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
@@ -779,6 +779,9 @@ void iwl_mld_flush_sta_txqs(struct iwl_mld *mld, struct ieee80211_sta *sta)
 
 void iwl_mld_wait_sta_txqs_empty(struct iwl_mld *mld, struct ieee80211_sta *sta)
 {
+	if (!sta)
+		return;
+
 	/* Avoid a warning in iwl_trans_wait_txq_empty if are anyway on the way
 	 * to a restart.
 	 */
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 27/28] wifi: iwlwifi: mld: Convert to WARN_ONCE in link removal path.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

While the comment indicates this should not happen, it does at least
when firmware is being problematic.  Change to WARN_ON_ONCE to
decrease log spam.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/sta.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.h b/drivers/net/wireless/intel/iwlwifi/mld/sta.h
index 1897b121aae2..44c54e6d68e6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.h
@@ -170,7 +170,7 @@ iwl_mld_cleanup_sta(void *data, struct ieee80211_sta *sta)
 			continue;
 
 		/* Should not happen as link removal should always succeed */
-		WARN_ON(1);
+		WARN_ON_ONCE(1);
 		RCU_INIT_POINTER(mld_sta->link[link_id], NULL);
 		RCU_INIT_POINTER(mld_sta->mld->fw_id_to_link_sta[mld_link_sta->fw_id],
 				 NULL);
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 22/28] wifi: mac80211: Add force-cleanup call to driver.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

When hardware is determined by mac80211 to be in non-recoverable
state, then SDATA_IN_DRIVER flag is removed, and mac80211 will no
longer do any 'graceful' teardown of the objects in the driver.

This was causing use-after-free crashes in the iwlwifi driver
since it's logic to do internal cleanup is not quite right for
some reason.

Add an explicit callback to the driver to tell it to clean up
whatever it needs to clean up in case mac80211 considers it
dead.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 include/net/mac80211.h    | 7 +++++++
 net/mac80211/driver-ops.h | 8 ++++++++
 net/mac80211/util.c       | 5 +++++
 3 files changed, 20 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 9cc482191ab9..d963f213863b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3934,6 +3934,12 @@ struct ieee80211_prep_tx_info {
  *	you should ensure to cancel it on this callback.
  *	Must be implemented and can sleep.
  *
+ * @force_cleanup: Called after mac80211 determines the
+ *      driver/firmware/hardware has failed and cannot
+ *      be restarted.  SDATA_IN_DRIVER is false at this point,
+ *      so normal cleanup will not happen.  This force_cleanup
+ *      operation lets the driver do any needed houskeeping.
+ *
  * @suspend: Suspend the device; mac80211 itself will quiesce before and
  *	stop transmitting and doing any other configuration, and then
  *	ask the device to suspend. This is only invoked when WoWLAN is
@@ -4569,6 +4575,7 @@ struct ieee80211_ops {
 		   struct sk_buff *skb);
 	int (*start)(struct ieee80211_hw *hw);
 	void (*stop)(struct ieee80211_hw *hw, bool suspend);
+	void (*force_cleanup)(struct ieee80211_hw *hw);
 #ifdef CONFIG_PM
 	int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
 	int (*resume)(struct ieee80211_hw *hw);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index e2283d7dcd1e..3bd3d078ce9b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -300,6 +300,14 @@ static inline void drv_cancel_hw_scan(struct ieee80211_local *local,
 	trace_drv_return_void(local);
 }
 
+static inline void
+drv_force_cleanup(struct ieee80211_local *local)
+{
+	lockdep_assert_wiphy(local->hw.wiphy);
+	if (local->ops->force_cleanup)
+		local->ops->force_cleanup(&local->hw);
+}
+
 static inline int
 drv_sched_scan_start(struct ieee80211_local *local,
 		     struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 55054de62508..ec11ee6b8752 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1692,6 +1692,11 @@ static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
 	 */
 	list_for_each_entry(ctx, &local->chanctx_list, list)
 		ctx->driver_present = false;
+
+	/* Tell driver to purge any remaining configuration it may have
+	 * lingering around.
+	 */
+	drv_force_cleanup(local);
 }
 
 static void ieee80211_assign_chanctx(struct ieee80211_local *local,
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 25/28] wifi: iwlwifi: mld: Fix bad return address in tx code.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

iwl_mld_txq_from_mac80211 was returning the offset into
txq without checking if txq was NULL.  In case txq is
NULL, this would return a small, but non NULL pointer.

The safety check in calling code would then treat it
as non-null and attempt to dereference.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/tx.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.h b/drivers/net/wireless/intel/iwlwifi/mld/tx.h
index 520f15f9d33c..8b0da098c25f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.h
@@ -45,6 +45,8 @@ static inline void iwl_mld_init_txq(struct iwl_mld_txq *mld_txq)
 static inline struct iwl_mld_txq *
 iwl_mld_txq_from_mac80211(struct ieee80211_txq *txq)
 {
+	if (!txq)
+		return NULL;
 	return (void *)txq->drv_priv;
 }
 
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 28/28] wifi: mac80211: Decrease WARN spam.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Comment one of them out, and make another WARN_ONCE.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/link.c | 1 -
 net/mac80211/util.c | 3 ++-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index 6125e79f67c9..e3a825ea3a04 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -544,7 +544,6 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
 		ret = drv_change_sta_links(local, sdata, &sta->sta,
 					   old_active | active_links,
 					   active_links);
-		WARN_ON_ONCE(ret);
 
 		/*
 		 * Do it again, just in case - the driver might very
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index ec11ee6b8752..df156f8b5211 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1879,7 +1879,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 		if (suspended)
 			WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n");
 		else
-			WARN(1, "Hardware became unavailable during restart.\n");
+			WARN_ONCE(1, "Hardware became unavailable during restart: %d\n", res);
+
 		ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
 						IEEE80211_QUEUE_STOP_REASON_SUSPEND,
 						false);
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next v2 26/28] wifi: mac80211: Ensure link work-items are only initialized once.
From: greearb @ 2026-03-12 17:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260312170026.285494-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Re-initialization could cause corruption in work queues in case
links were not properly stopped for some reason.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/ieee80211_i.h |  1 +
 net/mac80211/link.c        | 28 ++++++++++++++++++++--------
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d71e0c6d2165..ac4e10f16cd9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1079,6 +1079,7 @@ struct ieee80211_link_data {
 
 
 	bool operating_11g_mode;
+	bool already_initialized; /* has ieee80211_link_init been called? */
 
 	struct {
 		struct wiphy_work finalize_work;
diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index 03bfca27d205..6125e79f67c9 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -110,14 +110,25 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
 	link->user_power_level = sdata->local->user_power_level;
 	link_conf->txpower = INT_MIN;
 
-	wiphy_work_init(&link->csa.finalize_work,
-			ieee80211_csa_finalize_work);
-	wiphy_work_init(&link->color_change_finalize_work,
-			ieee80211_color_change_finalize_work);
-	wiphy_delayed_work_init(&link->color_collision_detect_work,
-				ieee80211_color_collision_detection_work);
-	wiphy_hrtimer_work_init(&link->dfs_cac_timer_work,
-				ieee80211_dfs_cac_timer_work);
+	if (link->already_initialized) {
+		wiphy_delayed_work_cancel(link->sdata->local->hw.wiphy,
+					  &link->color_collision_detect_work);
+		wiphy_work_cancel(link->sdata->local->hw.wiphy,
+				  &link->color_change_finalize_work);
+		wiphy_work_cancel(link->sdata->local->hw.wiphy,
+				  &link->csa.finalize_work);
+		wiphy_hrtimer_work_cancel(link->sdata->local->hw.wiphy,
+					  &link->dfs_cac_timer_work);
+	} else {
+		wiphy_work_init(&link->csa.finalize_work,
+				ieee80211_csa_finalize_work);
+		wiphy_work_init(&link->color_change_finalize_work,
+				ieee80211_color_change_finalize_work);
+		wiphy_delayed_work_init(&link->color_collision_detect_work,
+					ieee80211_color_collision_detection_work);
+		wiphy_hrtimer_work_init(&link->dfs_cac_timer_work,
+					ieee80211_dfs_cac_timer_work);
+	}
 
 	if (!deflink) {
 		switch (sdata->vif.type) {
@@ -138,6 +149,7 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
 		ieee80211_link_debugfs_add(link);
 	}
 
+	link->already_initialized = true;
 	rcu_assign_pointer(sdata->vif.link_conf[link_id], link_conf);
 	rcu_assign_pointer(sdata->link[link_id], link);
 }
-- 
2.42.0


^ permalink raw reply related

* Re: [PATCH] wifi: rtl8xxxu: Enable AP mode for RTL8188EU
From: Bitterblue Smith @ 2026-03-12 17:06 UTC (permalink / raw)
  To: Georg Müller, Jes.Sorensen; +Cc: linux-wireless, linux-kernel
In-Reply-To: <98711825-cbf3-46ad-a26c-9f1d284480ac@gmx.net>

On 12/03/2026 18:08, Georg Müller wrote:
> 
> Am 12.03.26 um 16:58 schrieb Bitterblue Smith:
>> On 12/03/2026 16:21, Georg Müller wrote:
>>> Allow devices with this driver to be used as a wireless access point.
>>>
>>> I successfully tested this with a TP-Link TP-Link TL-WN725N adapter.
>>>
>>> Experiments two years ago failed, but some other improvements to the
>>> driver seemed to have resolved theses issues.
>>>
>>
>> The rate control code still doesn't handle more than one station.
>> It's not going to work right.
>>
>> It shouldn't be too complicated. The ra_info member of rtl8xxxu_priv
>> needs to become an array.
> 
> Ok, I have only tested it with one client in my setup.
> 
> So the ra_info array needs to of size max_macid_num?
> Dynamically allocated or hard-coded in struct rtl8xxxu_priv (8188e seems
> to be the only user of struct rtl8xxxu_ra_info)?
> 

Yes. :)

Also, if I remember correctly, there was a member of rtl8xxxu_ra_info
that needs to be moved to rtl8xxxu_priv, because it's a global thing,
not per macid.

> Best regards,
> Georg
> 


^ permalink raw reply

* Re: [PATCH v2 1/2] mt76: mt7921: add mt7921-specific get_txpower callback
From: Lucid Duck @ 2026-03-12 17:38 UTC (permalink / raw)
  To: bryam vargas
  Cc: Sean Wang, Felix Fietkau, Lorenzo Bianconi, linux-wireless,
	linux-mediatek
In-Reply-To: <CANAPQzgD312EPSbvaQTE6U+wn85L65+xZHms7DP509ApxWvSZA@mail.gmail.com>

Hi Bryam, Sean,

I tested this on my MT7921AU USB adapter (Alfa AWUS036AXML, Fedora,
kernel 6.18.16, ISED/Canada). The callback itself is clean and with
one fix it gives correct values on all three bands, stable across a
full gauntlet. Nice work.


chanctx channel source (affects all mt7921 phy->chandef readers)
-----------------------------------------------------------------

This one bit me during testing and is worth flagging because it
affects more than just the callback. mt7921 uses the chanctx model,
and mt7921_add_chanctx() stores the context in dev->new_ctx without
updating phy->chandef. So phy->chandef.chan stays stuck on whatever
channel the firmware scanned at probe time -- channel 229 (6 GHz) on
my system. I confirmed via debugfs: "Tx power table (channel 229)"
while actually connected to 2.4 GHz ch6.

Because the callback reads phy->chandef.chan->max_power, it returns
12 dBm on every band. mt76_get_power_bound() has the same issue
internally since it also reads phy->chandef.chan.

The fix that worked for me: read the channel from the VIF chanctx
(falling back to phy->chandef.chan when unassociated) and inline the
SAR + delta math to avoid get_power_bound:

    rcu_read_lock();
    ctx = rcu_dereference(vif->bss_conf.chanctx_conf);
    chan = ctx ? ctx->def.chan : phy->chandef.chan;
    rcu_read_unlock();

    if (!chan)
        return mt76_get_txpower(hw, vif, link_id, dbm);

    n_chains = hweight16(phy->chainmask);
    delta = mt76_tx_power_path_delta(n_chains);
    tx_power = mt76_get_sar_power(phy, chan, chan->max_power * 2);
    tx_power -= delta;
    tx_power = mt76_get_rate_power_limits(phy, chan, &limits, tx_power);
    *dbm = DIV_ROUND_UP(tx_power + delta, 2);


A note on Sean's rate power loop direction
-------------------------------------------

Sean's feedback on both our patches points toward deriving the
reported value from mt76_connac_mcu_rate_txpower_band() -- the loop
that computes per-rate power limits before sending SKU tables to
firmware. That would sidestep the chanctx issue entirely since
txpower_cur gets written at configuration time rather than computed
at query time.

Looking at the code, mt7915 already does this (mt7915/mcu.c:3396):

    tx_power = mt76_get_rate_power_limits(...);
    mphy->txpower_cur = tx_power;

The connac equivalent calls mt76_get_rate_power_limits() in the same
loop but discards the return value. If that were fixed to match
mt7915, the existing mt76_get_txpower() would report correctly
without a per-driver callback.

That approach would also cover user txpower limits for free --
`iw dev set txpower fixed 1500` currently succeeds but the callback
reports the regulatory ceiling because it starts from chan->max_power.
The rate power loop already reads 2 * phy->hw->conf.power_level
(mt76_connac_mcu.c:2162), so user limits would be reflected
automatically.

Either way, happy to help test whatever direction v3 takes.


Test results (chanctx fix applied)
------------------------------------

Alfa AWUS036AXML (MT7921AU, USB, 2x2 MIMO)
Kernel 6.18.16-200.fc43.x86_64, ISED/Canada

    Per-band (10 runs each):
      2.4 GHz ch6:   30.00 dBm  (ISED: 30)   10/10 PASS
      5 GHz ch100:   26.00 dBm  (ISED: 26)   10/10 PASS
      6 GHz ch5:     12.00 dBm  (ISED: 12)   10/10 PASS

    Band switching:           18/18 correct
    Rapid cycling (20/band):  60/60 PASS
    Regdomain (CA/US/CA):     9/9 PASS (5 GHz: 26->24->26)
    60-min soak (5 GHz):      61/61 PASS, zero drift
    USB torture (module reload, monitor cycling, assoc interrupt):
                              20/20 PASS
    Kernel errors:            zero across all phases

Tested-by: Lucid Duck <lucid_duck@justthetip.ca>

^ permalink raw reply

* Re: [syzbot ci] Re: iwlwifi + mac80211 stability
From: Johannes Berg @ 2026-03-12 17:44 UTC (permalink / raw)
  To: Ben Greear, syzbot ci, linux-wireless; +Cc: syzbot, syzkaller-bugs
In-Reply-To: <1e6b8cbb-0f89-6b9b-b2cf-d21ca80dd7a2@candelatech.com>

On Thu, 2026-03-12 at 08:25 -0700, Ben Greear wrote:
> Which would be triggered by this from patch 0004, I guess.   The phyd
> pointer appears to be an error code -13 instead of clean NULL, so I guess I
> need to add checks for where that is created as well.

No ...

> --- a/net/mac80211/debugfs.c
> +++ b/net/mac80211/debugfs.c
> @@ -680,6 +680,12 @@ void debugfs_hw_add(struct ieee80211_local *local)
>   		return;
> 
>   	local->debugfs.keys = debugfs_create_dir("keys", phyd);
> +	if (IS_ERR(local->debugfs.keys)) {
> +		pr_err("Failed to create local keys debugfs dir, rv: %ld phyd: 0x%px\n",
> +		       (long)(local->debugfs.keys), phyd);
> +		local->debugfs.keys = NULL;
> +		return;
> +	}

That's just never going to get applied anyway, so what you _really_ need
to do is stop sending this crap.

johannes

^ permalink raw reply

* Re: [PATCH 1/2] mt76: connac: fix txpower_cur not updated in mt76_connac_mcu_set_rate_txpower()
From: bryam vargas @ 2026-03-12 18:22 UTC (permalink / raw)
  To: Sean Wang
  Cc: linux-wireless, nbd, lorenzo,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <CANAPQzj24sTgnuXMo3wqVDhA==UQ6JQLESk0AernQUUmZvTi2w@mail.gmail.com>

Subject: Bug: mt7921u unrecoverable chip hang requiring system reboot
(USB device disappears from bus)

Hi,

I'm filing a bug report for a recurring failure mode on the MT7921U USB
WiFi adapter where the chip becomes completely unresponsive and
eventually disappears from the USB bus, requiring a full system reboot
to recover.

This follows up on Sean Wang's suggestion to document the failure before
proposing driver-level recovery mechanisms.


== Hardware ==

  System:    Minisforum NAB9 (Intel i9-12900H)
  Adapter:   MediaTek MT7921AU USB (VID 35bc, PID 0107)
  Kernel:    6.18.x (Ubuntu 24.04)
  Location:  Bogotá, Colombia (2400m altitude)
  Uptime:    Continuous operation as home server (6-12 daily users)


== Symptoms ==

The MT7921U periodically enters a state where:

1. nmcli device show / iw dev wlan0 info time out
2. WiFi scan requests hang indefinitely
3. The interface exists in ip link but is non-functional
4. All software recovery attempts fail (driver reload, USB
   unbind/rebind, USB controller reset, uhubctl power cycle)
5. The device eventually disappears from lsusb entirely
6. Only a full system reboot restores the adapter


== Structured Event Log ==

I run an automated monitoring script (net-rescue.sh) that checks chip
responsiveness every 10 minutes and logs events with timestamps and
system uptime. Here is the complete chip-events.log from January
through March 2026:

Recoverable events (soft USB reset succeeds):
  2026-01-11 20:29 HANG -> RECOVERED (soft_usb_reset) [8s]
  2026-01-11 20:34 HANG -> RECOVERED (soft_usb_reset) [7s]
  2026-01-11 20:45 HANG -> RECOVERED (soft_usb_reset) [8s]
  2026-01-11 20:55 HANG -> RECOVERED (soft_usb_reset) [7s]
  2026-01-14 09:34 HANG -> RECOVERED (soft_usb_reset) [373s]
  2026-01-16 13:37 HANG -> RECOVERED (soft_usb_reset) [313s]
  2026-01-17 15:21 HANG -> RECOVERED (soft_usb_reset) [129s]
  2026-02-28 13:49 HANG -> RECOVERED (soft_usb_reset) [99s]

Unrecoverable events (all escalation levels fail):
  2026-01-13 17:16 HANG -> FAILED (all_recovery_attempts_failed)
  2026-01-26 14:10 HANG -> FAILED (all_recovery_attempts_failed)
  2026-02-09 14:33 HANG -> FAILED (all_recovery_attempts_failed)
  2026-02-11 11:07 HANG -> FAILED -> 14x DISAPPEARED over 3+ hours
  2026-02-22 09:45 HANG -> FAILED -> 35x DISAPPEARED over 6+ hours

The DISAPPEARED entries mean the device is no longer visible on the
USB bus at all. The monitoring script runs every ~10 minutes, so each
DISAPPEARED entry is a separate detection cycle confirming the device
remains absent.

The Feb 11 and Feb 22 incidents are the most telling: after the initial
hang and failed recovery, the chip vanished from the bus entirely and
stayed gone for hours until the daily 2:00 AM scheduled reboot
restored it.


== Recovery Escalation (all fail in unrecoverable case) ==

  Level 1: USB deauthorize/reauthorize via sysfs
  Level 2: modprobe -r mt7921u / modprobe mt7921u
  Level 3: USB unbind/rebind via /sys/bus/usb/drivers/usb/
  Level 4: uhubctl power cycle (physical power cut to USB port)
  Level 5: xhci_pci / ehci_pci module reload

When the chip enters the unrecoverable state, mt792xu_wfsys_reset()
cannot succeed because the chip does not respond to USB vendor
requests. Even cutting physical power to the USB port via uhubctl
and restoring it does not bring the device back. Only a full system
reboot (which resets the xHCI controller at BIOS level) recovers it.


== Pattern Analysis ==

From the event log:
  - 10 HANG events over ~2 months of continuous operation
  - 8 recovered via soft USB reset (80% success rate)
  - 5 required system reboot (escalation completely failed)
  - 2 incidents with extended DISAPPEARED state (3-6 hours)

The Jan 11 cluster (4 HANGs in 30 minutes) suggests a transient
condition that resolves with soft resets. The Feb 11 and Feb 22
incidents represent a different, more severe failure where the
chip enters a state that no software recovery can address.


== Pending Data ==

I can provide the following on request or when the next event occurs:
  - Full dmesg around HANG/DISAPPEARED transitions
  - lsusb -t (USB topology) and lsusb -v -d 0e8d:7961
  - usbmon traces during the failure
  - journalctl entries from net-rescue.service

The static USB data (topology, device descriptor) I can provide
immediately. The dynamic data (dmesg during failure) requires waiting
for the next natural occurrence, as the system has been stable since
the last incident.


== Related Reports ==

  https://github.com/openwrt/mt76/issues/838
  https://github.com/morrownr/USB-WiFi/issues/410
  https://github.com/raspberrypi/linux/issues/5193

All describe the same symptom: mt7921u interface becomes a zombie
(UP but unable to TX/RX), requiring physical USB unplug or system
reboot.


== Note on Environment ==

This system operates at 2400m altitude where atmospheric neutron
flux is elevated compared to sea level. I initially attributed these
events to cosmic radiation-induced SEFI (Single Event Functional
Interrupt), but as Sean correctly pointed out, the failure mode needs
to be understood before attributing a cause. The structured event log
is provided as evidence of the failure pattern regardless of root
cause.

This is a home server under active development running multiple
services (ERP, Minecraft, Tailscale, DNS/DHCP, containers). When the
chip enters the unrecoverable state and I'm not physically near the
hardware, the system can remain without WiFi connectivity for days
until I can manually reboot it.

Best regards,
Bryam Vargas

^ permalink raw reply

* Re: [PATCH wireless-next v8 2/3] wifi: cfg80211: add initial UHR support
From: Johannes Berg @ 2026-03-12 19:32 UTC (permalink / raw)
  To: Harshitha Prem, linux-wireless
  Cc: Karthikeyan Kathirvel, vasanthakumar.thiagarajan,
	Lorenzo Bianconi, ath12k, Jeff Johnson, Ping-Ke Shih,
	Manish Dharanenthiran, Jouni Malinen, Benjamin Berg
In-Reply-To: <c676b2cd73463fa88f459f0416c60b03f20dd027.camel@sipsolutions.net>


> > Because of this, an event-driven approach was considered.

So - starting this again from scratch. Benjamin and I spent some time
discussing this today too, and hashed out a (mostly?) workable solution
that should address most of the issues. I'll try to summarise that
below.

As will become obvious - and that's why I quoted only the line _you_
wrote before - this means we (including myself :)) need to stop being
afraid of hostapd doing (soft?) real-time [1] tasks...

[1] I'm using that word in the (formal) sense of having a deadline, not
of having to be particularly fast.


Let's assume the following constraints:

- preparing a beacon template as a real-time task can be done by
hostapd, given enough heads-up time
- no periodic events in a steady state when the AP is operating
normally
- TSF drift between links is correctly handled (maintaining <=30us
offset at any time)

We evidently already make these assumptions:

- if beacon intervals are not the same, the TBTT offset in RNR is
filled in by firmware (I see no way around this)
- either firmware fills in TSF offset, or it's just zero, and not
really accounting for slight drifts (but that's probably OK since it
never adds up given the <=30us requirement)

And also let's introduce some new operations to driver/firmware:

- the firmware can drop a frame that it's not able to transmit before
a given (as frame metadata) TSF value on the link, and indicate to
the driver that this is the reason the frame was dropped
- the firmware can create events at/after beacon TBTT (or beacon
transmission), this can be controlled by the driver; these events
contain the next TBTT's timestamp value
- the TSF offsets between links can be known to the driver, if they can
change (I suspect CSA could do that?) this can somehow be noticed by
or given to the driver

With that, it seems we can redesign this whole thing to be event-driven
and (mostly?) race-free.

In steady state, basically nothing would change from what hostapd is
doing today. It simply configures beacon templates, occasionally updates
them if elements need to change, and sends probe responses,
(re)association responses etc. as usual.

During any sort of update (CSA, color change, EHT updates, UHR updates)
things operate a bit differently:

1) hostapd enables TBTT / beacon transmit events, these events would be
generated by firmware and passed up, for each link, containing also the
TBTT timestamp of the _next_ beacon to be transmitted

2) hostapd waits for the TBTT event for the link that it wants to do the
update on, ignoring events for other links

3) starting from that TBTT event, on each TBTT event hostapd generates a
new beacon template for the link the event was for, and configures it to
the driver/firmware. Since that's a future beacon, it has to predict the
content of that beacon using
- the TBTT of the first beacon carrying the update announcement
- the TSF offsets between the links
- the beacon intervals of all the links
(a bit more on this later)

4) After applying the updates (a bit more on this later) and noticing
that the announcements are finished, hostapd waits for one more TBTT
event for each link and configures the beacons back to steady state,
after which it turns off the events.

If, at any time during this, hostapd needs to send a probe response,
(re)association response, EPP Capa/Operation response (or others?) which
holds information about the updates with the current counter values,
hostapd will create the frame per the current counters that it
maintains, and will transmit this frame with a TSF cut-off value
indicating that it must be transmitted before the next TBTT (over all
links), or dropped.
If this frame ends up being dropped by firmware because it didn't get
out before the indicated TSF, hostapd gets a specific notification for
this and then simply re-generates it and sends it again. This could
possibly repeat if TBTTs are close together on multiple links, but I
think it's not worth optimising for this case, though it could be done
by deferring the response slightly based on timers, or at the expense of
a more complex API ("defer until X and don't send after Y" vs. "don't
send after Y"), neither seems really worthwhile.


I said I'd give more information for (3) and (4) above, so:

For (3), also consider that it already has to effectively be able to do
this for the templates thing we discussed, it has to predict what each
link is going to look like in the future. I think this isn't too much of
an issue, but care must be taken especially if beacon intervals differ.

For (4), I think the way how the updates are done may depend on what the
update is. If, for example, it's DBE increasing the bandwidth, then
could just do the update _before_ the 0 beacon is transmitted, and if
it's decreasing bandwidth could do it _after_ the 0 beacon is
transmitted. Some of these may potentially require management by the
kernel or even driver/firmware (how do you switch NPCA parameters at the
exact right point if not in FW?), and perhaps (especially for CSA?)
there will be some considerations regarding multiple interfaces.
I mostly think this question is orthogonal, since armed with a TBTT
hostapd could also request that this update be done at a given TBTT.


We haven't really been able to poke significant holes into this, but
maybe that doesn't mean much. Couple of thoughts on that:

 * For each link, hostapd has roughly the whole beacon interval to build
   the next beacon's template, which seems reasonable.
 * There's a really weird corner case where an assoc response is
   attempted to transmit just before a beacon, doesn't get an ACK, but a
   retransmission isn't possible until after the beacon and it's dropped
   due to the TSF cut-off. Doesn't seem worth worrying about.
 * If the TBTTs for two links are at the same time, and the events to
   userspace for them are not coming "updated link first", then the
   beacon transmitted at the same time on the unchanged link may not yet
   be announcing the update, depending on the event order, given that
   hostapd waited for the affected link's first TBTT event. This doesn't
   really seem like a problem, but I think could be addressed by
   updating all the links on the first event immediately or so, or
   (Benjamin prefers this I think) adding the first beacon's TBTT to the
   response to the event enable command, I just worry that would cause
   other races that would need to be addressed.

That's it for now :) Let me know what you think.

johannes

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox