From: Zhao Li <enderaoelyther@gmail.com>
To: Johannes Berg <johannes@sipsolutions.net>
Cc: "Jiangshan Yi" <yijiangshan@kylinos.cn>,
"Arend van Spriel" <arend.vanspriel@broadcom.com>,
"Stefan Hansson" <newbyte@postmarketos.org>,
"Uwe Kleine-König" <u.kleine-koenig@baylibre.com>,
"Ville Nummela" <ville.nummela@kempower.com>,
"Jeongjun Park" <aha310510@gmail.com>,
"Fariya Fatima" <fariyaf@gmail.com>,
"John W. Linville" <linville@tuxdriver.com>,
"Amitkumar Karwar" <amit.karwar@redpinesignals.com>,
"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 1/2] wifi: rsi: stop WLAN threads before teardown
Date: Wed, 28 Oct 2026 22:20:14 +0800 [thread overview]
Message-ID: <20261028142015.10717-2-enderaoelyther@gmail.com> (raw)
In-Reply-To: <20261028142015.10717-1-enderaoelyther@gmail.com>
Disconnect and probe unwind can leave RSI packet threads using mac80211
state or a bus that teardown has already released.
The USB path unregisters mac80211 before stopping RX and can free its
shared TX buffer while the WLAN TX thread is running. The SDIO paths can
leave WLAN TX active across mac80211 detach or function disable. Waking
the TX thread to stop it can also drain queued packets because its
processing loop does not check the stop request.
Make repeated thread stops harmless, and stop the TX drain loop when
teardown requests it. On USB, stop the RX URBs and the WLAN RX and TX
threads before detaching mac80211. Leave coexistence TX and its shared
buffer available until HCI unregister completes. On SDIO, stop WLAN TX
before mac80211 detach and function disable, including probe unwind.
LLM assistance was used to find the bug and review.
Fixes: dad0d04fa7ba ("rsi: Add RS9113 wireless driver")
Cc: stable@vger.kernel.org
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
---
Validation: W=1 module builds with MODPOST passed for every prefix with
CONFIG_RSI_COEX enabled and disabled. The series applies to v7.3.
Not reproduced; RS9113/RS9116 hardware was unavailable.
Sparse C=2 passed. Smatch across all configured translation units under
drivers/net/wireless/rsi introduced no new diagnostics.
drivers/net/wireless/rsi/rsi_91x_core.c | 2 +-
drivers/net/wireless/rsi/rsi_91x_sdio.c | 2 ++
drivers/net/wireless/rsi/rsi_91x_usb.c | 13 +++++++++----
drivers/net/wireless/rsi/rsi_common.h | 4 ++++
4 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index 3281fc94e107..2555bb53766d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -267,7 +267,7 @@ void rsi_core_qos_processor(struct rsi_common *common)
int status;
tstamp_1 = jiffies;
- while (1) {
+ while (!atomic_read(&common->tx_thread.thread_done)) {
q_num = rsi_core_determine_hal_queue(common);
rsi_dbg(DATA_TX_ZONE,
"%s: Queue number = %d\n", __func__, q_num);
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index bfa386b820d8..c5619a34940d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -1079,6 +1079,7 @@ static int rsi_probe(struct sdio_func *pfunction,
fail_claim_irq:
rsi_kill_thread(&sdev->rx_thread);
fail_kill_thread:
+ rsi_kill_thread(&adapter->priv->tx_thread);
sdio_claim_host(pfunction);
sdio_disable_func(pfunction);
sdio_release_host(pfunction);
@@ -1220,6 +1221,7 @@ static void rsi_disconnect(struct sdio_func *pfunction)
sdio_release_host(pfunction);
mdelay(10);
+ rsi_kill_thread(&adapter->priv->tx_thread);
rsi_mac80211_detach(adapter);
mdelay(10);
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 8765cac6f875..99e029e66407 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -562,6 +562,7 @@ static void rsi_deinit_usb_interface(struct rsi_hw *adapter)
struct rsi_91x_usbdev *dev = adapter->rsi_dev;
rsi_kill_thread(&dev->rx_thread);
+ rsi_kill_thread(&adapter->priv->tx_thread);
usb_free_urb(dev->rx_cb[0].rx_urb);
if (adapter->priv->coex_mode > 1)
@@ -873,12 +874,20 @@ static int rsi_probe(struct usb_interface *pfunction,
static void rsi_disconnect(struct usb_interface *pfunction)
{
struct rsi_hw *adapter = usb_get_intfdata(pfunction);
+ struct rsi_91x_usbdev *dev;
if (!adapter)
return;
+ dev = adapter->rsi_dev;
rsi_mac80211_rfkill_exit(adapter);
+ if (adapter->priv->coex_mode > 1)
+ rsi_rx_urb_kill(adapter, BT_EP);
+ rsi_rx_urb_kill(adapter, WLAN_EP);
+ rsi_kill_thread(&dev->rx_thread);
+ rsi_kill_thread(&adapter->priv->tx_thread);
+
rsi_mac80211_detach(adapter);
if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 &&
@@ -887,10 +896,6 @@ static void rsi_disconnect(struct usb_interface *pfunction)
adapter->priv->bt_adapter = NULL;
}
- if (adapter->priv->coex_mode > 1)
- rsi_rx_urb_kill(adapter, BT_EP);
- rsi_rx_urb_kill(adapter, WLAN_EP);
-
rsi_reset_card(adapter);
rsi_deinit_usb_interface(adapter);
rsi_91x_deinit(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index 2a33a81f71a3..2407ec61d412 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -72,9 +72,13 @@ static inline int rsi_create_kthread(struct rsi_common *common,
static inline void rsi_kill_thread(struct rsi_thread *handle)
{
+ if (IS_ERR_OR_NULL(handle->task))
+ return;
+
atomic_inc(&handle->thread_done);
rsi_set_event(&handle->event);
wait_for_completion(&handle->completion);
+ handle->task = NULL;
}
void rsi_mac80211_detach(struct rsi_hw *hw);
--
2.56.0
next prev parent reply other threads:[~2026-10-28 14:20 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-28 14:20 [PATCH 0/2] wifi: rsi: stop packet threads before bus teardown Zhao Li
2026-10-28 14:20 ` Zhao Li [this message]
2026-10-28 14:20 ` [PATCH 2/2] wifi: rsi: stop coexistence TX " Zhao Li
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=20261028142015.10717-2-enderaoelyther@gmail.com \
--to=enderaoelyther@gmail.com \
--cc=aha310510@gmail.com \
--cc=amit.karwar@redpinesignals.com \
--cc=arend.vanspriel@broadcom.com \
--cc=fariyaf@gmail.com \
--cc=johannes@sipsolutions.net \
--cc=kvalo@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
--cc=newbyte@postmarketos.org \
--cc=prameela.j04cs@gmail.com \
--cc=siva.rebbagondla@redpinesignals.com \
--cc=stable@vger.kernel.org \
--cc=u.kleine-koenig@baylibre.com \
--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
all inboxes | Powered by JetHome®