* [PATCH 0/2] wifi: rsi: stop packet threads before bus teardown
@ 2026-10-28 14:20 Zhao Li
2026-10-28 14:20 ` [PATCH 1/2] wifi: rsi: stop WLAN threads before teardown Zhao Li
2026-10-28 14:20 ` [PATCH 2/2] wifi: rsi: stop coexistence TX before bus teardown Zhao Li
0 siblings, 2 replies; 3+ messages in thread
From: Zhao Li @ 2026-10-28 14:20 UTC (permalink / raw)
To: Johannes Berg
Cc: Jiangshan Yi, Arend van Spriel, Stefan Hansson,
Uwe Kleine-König, Ville Nummela, Jeongjun Park,
Fariya Fatima, John W. Linville, Amitkumar Karwar,
Prameela Rani Garnepudi, Siva Rebbagondla, Kalle Valo,
linux-wireless, linux-kernel
Stop the WLAN RX and TX threads before mac80211 or bus teardown. Then
stop coexistence TX after HCI unregister and before USB reset or SDIO
chip reset and function disable. Probe failures are covered before
buffer freeing or function disable.
Patch 1 makes repeated thread stops safe and prevents the WLAN TX loop
from draining queued packets after a stop request. Patch 2 does the same
for coexistence TX without adding an exported core-to-bus wrapper.
The driver is orphaned and the series was not run on RS9113 or RS9116
hardware. Testing from device users would be helpful.
LLM assistance was used to review this series.
Zhao Li (2):
wifi: rsi: stop WLAN threads before teardown
wifi: rsi: stop coexistence TX before bus teardown
drivers/net/wireless/rsi/rsi_91x_coex.c | 3 +++
drivers/net/wireless/rsi/rsi_91x_core.c | 2 +-
drivers/net/wireless/rsi/rsi_91x_sdio.c | 5 +++++
drivers/net/wireless/rsi/rsi_91x_usb.c | 15 +++++++++++----
drivers/net/wireless/rsi/rsi_coex.h | 12 ++++++++++++
drivers/net/wireless/rsi/rsi_common.h | 4 ++++
6 files changed, 36 insertions(+), 5 deletions(-)
base-commit: 25e73f1d6868c759c8eb56cad4e411692c5341b4
--
2.56.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] wifi: rsi: stop WLAN threads before teardown
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
2026-10-28 14:20 ` [PATCH 2/2] wifi: rsi: stop coexistence TX before bus teardown Zhao Li
1 sibling, 0 replies; 3+ messages in thread
From: Zhao Li @ 2026-10-28 14:20 UTC (permalink / raw)
To: Johannes Berg
Cc: Jiangshan Yi, Arend van Spriel, Stefan Hansson,
Uwe Kleine-König, Ville Nummela, Jeongjun Park,
Fariya Fatima, John W. Linville, Amitkumar Karwar,
Prameela Rani Garnepudi, Siva Rebbagondla, Kalle Valo,
linux-wireless, linux-kernel, stable
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
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 2/2] wifi: rsi: stop coexistence TX before bus teardown
2026-10-28 14:20 [PATCH 0/2] wifi: rsi: stop packet threads before bus teardown Zhao Li
2026-10-28 14:20 ` [PATCH 1/2] wifi: rsi: stop WLAN threads before teardown Zhao Li
@ 2026-10-28 14:20 ` Zhao Li
1 sibling, 0 replies; 3+ messages in thread
From: Zhao Li @ 2026-10-28 14:20 UTC (permalink / raw)
To: Johannes Berg
Cc: Jiangshan Yi, Arend van Spriel, Stefan Hansson,
Uwe Kleine-König, Ville Nummela, Jeongjun Park,
Fariya Fatima, John W. Linville, Amitkumar Karwar,
Prameela Rani Garnepudi, Siva Rebbagondla, Kalle Valo,
linux-wireless, linux-kernel, stable
The coexistence TX thread can continue using an RSI bus after disconnect
resets or disables it. On USB, interface cleanup can also free the shared
TX buffer before the final core cleanup stops the thread.
rsi_coex_detach() only stops the thread from rsi_91x_deinit(), after the
bus has been reset or disabled. Its stop wakeup first drains any queued
Bluetooth packets through that unavailable bus.
Check the stop request before each queued packet. Stop coexistence TX
once HCI unregister has completed and before USB reset. Also stop it in
interface cleanup before freeing the TX buffer so probe unwind is
covered. On SDIO, stop it before chip reset and function disable on
disconnect, and before function disable during probe unwind.
rsi_coex_detach() still purges and frees the queues. The repeated stops
are harmless after the previous patch.
LLM assistance was used to find the bug and review.
Fixes: 716b840c7641 ("rsi: handle BT traffic in 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_coex.c | 3 +++
drivers/net/wireless/rsi/rsi_91x_sdio.c | 3 +++
drivers/net/wireless/rsi/rsi_91x_usb.c | 2 ++
drivers/net/wireless/rsi/rsi_coex.h | 12 ++++++++++++
4 files changed, 20 insertions(+)
diff --git a/drivers/net/wireless/rsi/rsi_91x_coex.c b/drivers/net/wireless/rsi/rsi_91x_coex.c
index 023c539fc384..de2a973873ef 100644
--- a/drivers/net/wireless/rsi/rsi_91x_coex.c
+++ b/drivers/net/wireless/rsi/rsi_91x_coex.c
@@ -40,6 +40,9 @@ static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb)
struct sk_buff *skb;
do {
+ if (atomic_read(&coex_cb->coex_tx_thread.thread_done))
+ break;
+
coex_q = rsi_coex_determine_coex_q(coex_cb);
rsi_dbg(INFO_ZONE, "queue = %d\n", coex_q);
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index c5619a34940d..87108f4a4326 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -1080,6 +1080,7 @@ static int rsi_probe(struct sdio_func *pfunction,
rsi_kill_thread(&sdev->rx_thread);
fail_kill_thread:
rsi_kill_thread(&adapter->priv->tx_thread);
+ rsi_coex_stop_thread(adapter->priv);
sdio_claim_host(pfunction);
sdio_disable_func(pfunction);
sdio_release_host(pfunction);
@@ -1231,6 +1232,8 @@ static void rsi_disconnect(struct sdio_func *pfunction)
adapter->priv->bt_adapter = NULL;
}
+ rsi_coex_stop_thread(adapter->priv);
+
/* Reset Chip */
rsi_reset_chip(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 99e029e66407..f8b5c264a8a9 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -563,6 +563,7 @@ static void rsi_deinit_usb_interface(struct rsi_hw *adapter)
rsi_kill_thread(&dev->rx_thread);
rsi_kill_thread(&adapter->priv->tx_thread);
+ rsi_coex_stop_thread(adapter->priv);
usb_free_urb(dev->rx_cb[0].rx_urb);
if (adapter->priv->coex_mode > 1)
@@ -896,6 +897,7 @@ static void rsi_disconnect(struct usb_interface *pfunction)
adapter->priv->bt_adapter = NULL;
}
+ rsi_coex_stop_thread(adapter->priv);
rsi_reset_card(adapter);
rsi_deinit_usb_interface(adapter);
rsi_91x_deinit(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_coex.h b/drivers/net/wireless/rsi/rsi_coex.h
index 2c14e4c651b9..cdd83650c5f1 100644
--- a/drivers/net/wireless/rsi/rsi_coex.h
+++ b/drivers/net/wireless/rsi/rsi_coex.h
@@ -29,9 +29,21 @@ struct rsi_coex_ctrl_block {
struct rsi_thread coex_tx_thread;
};
+static inline void rsi_coex_stop_thread(struct rsi_common *common)
+{
+ struct rsi_coex_ctrl_block *coex_cb = common->coex_cb;
+
+ if (common->coex_mode > 1)
+ rsi_kill_thread(&coex_cb->coex_tx_thread);
+}
+
int rsi_coex_attach(struct rsi_common *common);
void rsi_coex_detach(struct rsi_common *common);
int rsi_coex_send_pkt(void *priv, struct sk_buff *skb, u8 proto_type);
int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg);
+#else
+static inline void rsi_coex_stop_thread(struct rsi_common *common)
+{
+}
#endif
#endif
--
2.56.0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-28 14:21 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-28 14:20 [PATCH 0/2] wifi: rsi: stop packet threads before bus teardown Zhao Li
2026-10-28 14:20 ` [PATCH 1/2] wifi: rsi: stop WLAN threads before teardown Zhao Li
2026-10-28 14:20 ` [PATCH 2/2] wifi: rsi: stop coexistence TX before bus teardown Zhao Li
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®