From: Zhao Li <enderaoelyther@gmail.com>
To: Johannes Berg <johannes@sipsolutions.net>
Cc: "Sebastian Krzyszkowiak" <sebastian.krzyszkowiak@puri.sm>,
"Arend van Spriel" <arend.vanspriel@broadcom.com>,
"Ville Nummela" <ville.nummela@kempower.com>,
"Jiangshan Yi" <yijiangshan@kylinos.cn>,
"Marek Vasut" <marex@nabladev.com>,
"Toke Høiland-Jørgensen" <toke@toke.dk>,
"Stefan Hansson" <newbyte@postmarketos.org>,
"Ping-Ke Shih" <pkshih@realtek.com>,
"Jakub Kicinski" <kuba@kernel.org>,
"Ethan Nelson-Moore" <enelsonmoore@gmail.com>,
"Pengpeng Hou" <pengpeng@iscas.ac.cn>,
"Prameela Rani Garnepudi" <prameela.j04cs@gmail.com>,
"Siva Rebbagondla" <siva.rebbagondla@redpinesignals.com>,
"Kalle Valo" <kvalo@kernel.org>,
linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: [PATCH 3/3] wifi: rsi: serialize background scan state
Date: Wed, 28 Oct 2026 22:19:27 +0800 [thread overview]
Message-ID: <20261028141927.9306-4-enderaoelyther@gmail.com> (raw)
In-Reply-To: <20261028141927.9306-1-enderaoelyther@gmail.com>
The firmware completion event runs in the RX thread without
common->mutex, while scan cancellation can clear hwscan under that mutex.
Both paths test bgscan_en before sending STOP and reporting completion.
An interleaving can therefore dereference a NULL or freed request in
rsi_send_bgscan_params(), or report the scan twice.
The RX path cannot take common->mutex: rsi_mac80211_start() holds it while
waiting for that path to finish firmware initialization after
hibernation.
Add a scan-specific mutex and use it to serialize start, cancellation,
and firmware completion. Clear bgscan_en and hwscan together even when
STOP cannot be queued so a later event cannot report the same scan again.
LLM assistance was used to find the bug and review.
Fixes: 7fdcb8e12660 ("rsi: add support for hardware scan offload")
Cc: stable@vger.kernel.org
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
---
Validation: W=1 module builds with MODPOST passed with CONFIG_RSI_COEX
enabled and disabled. Not reproduced; RS9113/RS9116 hardware was
unavailable.
Sparse C=2 passed. Targeted Smatch introduced no new diagnostics.
Host state is serialized, but no hardware or protocol evidence established
how a late event from a scan whose STOP command was not queued is attributed
after a later scan starts.
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 31 +++++++++++++++------
drivers/net/wireless/rsi/rsi_91x_main.c | 1 +
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 16 +++++++----
drivers/net/wireless/rsi/rsi_main.h | 2 ++
4 files changed, 36 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index a2e981e261d6..5617c7ef6196 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -249,15 +249,21 @@ static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw,
scan_req->n_channels == 0)
return -EINVAL;
+ mutex_lock(&common->scan_mutex);
+
/* Scan already in progress. So return */
- if (common->bgscan_en)
- return -EBUSY;
+ if (common->bgscan_en) {
+ ret = -EBUSY;
+ goto out;
+ }
/* If STA is not connected, return with special value 1, in order
* to start sw_scan in mac80211
*/
- if (!vif->cfg.assoc)
- return 1;
+ if (!vif->cfg.assoc) {
+ ret = 1;
+ goto out;
+ }
mutex_lock(&common->mutex);
common->hwscan = scan_req;
@@ -270,6 +276,9 @@ static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw,
}
mutex_unlock(&common->mutex);
+out:
+ mutex_unlock(&common->scan_mutex);
+
return ret;
}
@@ -283,16 +292,20 @@ static void rsi_mac80211_cancel_hw_scan(struct ieee80211_hw *hw,
};
rsi_dbg(INFO_ZONE, "***** Hardware scan stop *****\n");
- mutex_lock(&common->mutex);
+ mutex_lock(&common->scan_mutex);
if (common->bgscan_en) {
- if (!rsi_send_bgscan_params(common, RSI_STOP_BGSCAN))
- common->bgscan_en = false;
+ mutex_lock(&common->mutex);
+ if (rsi_send_bgscan_params(common, RSI_STOP_BGSCAN))
+ rsi_dbg(ERR_ZONE, "Failed to stop background scan\n");
+ mutex_unlock(&common->mutex);
+ common->bgscan_en = false;
+ common->hwscan = NULL;
ieee80211_scan_completed(adapter->hw, &info);
rsi_dbg(INFO_ZONE, "Back ground scan cancelled\n");
}
- common->hwscan = NULL;
- mutex_unlock(&common->mutex);
+
+ mutex_unlock(&common->scan_mutex);
}
/**
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 2ce514766620..16f57c964ca3 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -325,6 +325,7 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode)
rsi_init_event(&common->tx_thread.event);
mutex_init(&common->mutex);
+ mutex_init(&common->scan_mutex);
mutex_init(&common->tx_lock);
mutex_init(&common->rx_lock);
mutex_init(&common->tx_bus_mutex);
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 165423313c5f..5f11de44f880 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -2107,17 +2107,23 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
rsi_dbg(INFO_ZONE, "Wakeup/Sleep confirmation.\n");
return rsi_handle_ps_confirm(adapter, msg);
- case BG_SCAN_PROBE_REQ:
+ case BG_SCAN_PROBE_REQ: {
+ struct cfg80211_scan_info info = {};
+
rsi_dbg(INFO_ZONE, "BG scan complete event\n");
+ mutex_lock(&common->scan_mutex);
if (common->bgscan_en) {
- struct cfg80211_scan_info info = {};
-
- if (!rsi_send_bgscan_params(common, RSI_STOP_BGSCAN))
- common->bgscan_en = 0;
+ if (rsi_send_bgscan_params(common, RSI_STOP_BGSCAN))
+ rsi_dbg(ERR_ZONE,
+ "Failed to stop background scan\n");
+ common->bgscan_en = false;
+ common->hwscan = NULL;
ieee80211_scan_completed(adapter->hw, &info);
}
+ mutex_unlock(&common->scan_mutex);
rsi_dbg(INFO_ZONE, "Background scan completed\n");
break;
+ }
default:
rsi_dbg(INFO_ZONE, "%s: Invalid TA confirm pkt received\n",
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index dcf8fb40698b..5fa8fd93a17e 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -250,6 +250,8 @@ struct rsi_common {
struct completion wlan_init_completion;
/* Mutex declaration */
struct mutex mutex;
+ /* Protect background scan state. */
+ struct mutex scan_mutex;
/* Mutex used for tx thread */
struct mutex tx_lock;
/* Mutex used for rx thread */
--
2.56.0
prev parent reply other threads:[~2026-10-28 14:20 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-28 14:19 [PATCH 0/3] wifi: rsi: fix background scan result and state lifetime Zhao Li
2026-10-28 14:19 ` [PATCH 1/3] wifi: rsi: initialize background scan completion data Zhao Li
2026-10-28 14:19 ` [PATCH 2/3] wifi: rsi: report background scan start failures Zhao Li
2026-10-28 14:19 ` Zhao Li [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261028141927.9306-4-enderaoelyther@gmail.com \
--to=enderaoelyther@gmail.com \
--cc=arend.vanspriel@broadcom.com \
--cc=enelsonmoore@gmail.com \
--cc=johannes@sipsolutions.net \
--cc=kuba@kernel.org \
--cc=kvalo@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=marex@nabladev.com \
--cc=newbyte@postmarketos.org \
--cc=pengpeng@iscas.ac.cn \
--cc=pkshih@realtek.com \
--cc=prameela.j04cs@gmail.com \
--cc=sebastian.krzyszkowiak@puri.sm \
--cc=siva.rebbagondla@redpinesignals.com \
--cc=stable@vger.kernel.org \
--cc=toke@toke.dk \
--cc=ville.nummela@kempower.com \
--cc=yijiangshan@kylinos.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox