From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A6FA53D3D06; Mon, 20 Apr 2026 13:23:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776691417; cv=none; b=bBhKT0sD8WZ+i9Z/xM1JIHoUJjoMqxwdOJ57Lh2PF9MUTAfmrw47AGoYkymOMxbXQE4KiAJPJ5cM1GWEjMDviL8Bwf4pubw8dbmesHpFWn91Y21j5H+mnwYIHA2YhFbmLRYEGrARezmENQFJaL19qdorjdeKhLJq0ZYC/SxILYM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776691417; c=relaxed/simple; bh=t6WXuGdXT/jnJrIbR0CAcjUvYkXbpgvxo6/TwxkRo4g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AVeNANTPl4t4AUknvNT4e1fxwKjjgc+CUaL/oesOmEyzZMKUWe0fBbZoiUiRhVU8ZJYJIa46gnj04MuHU93+PykOJjV3xo2SMJTufhwODT8EgYg0z2Vjy6Jnq/ni5bZvHRuEsQpA2L/VYq3Ab9Ndj9x6EfzDbg+6P04Ajk0DxBQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mel+HvyN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mel+HvyN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 96FC9C19425; Mon, 20 Apr 2026 13:23:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1776691417; bh=t6WXuGdXT/jnJrIbR0CAcjUvYkXbpgvxo6/TwxkRo4g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mel+HvyNYfqYjrOH7Dn0A9N72XxeVlrHXhQtWC4uppGHC2RcUdOf28BNHCOfU0l2V lsPrun1Pu2lqTKxXqa9Vwj230PkoXHgw2mp/ptmG2VusjkUr0LOEcBg4R6XPENqGAi d+pEIVEgXikIC6MwsdwIWRifniaO9F2O0jQwkqXenYHiUj96eKlsl+vBArL6pkpWHx 0FNxKVuAmSYMShRSnjoR5li9iUbIq6IzRtOZUUygUf5bPd87i+P7gIpQM3TiiE8e+y ZWmdW64JHHsK0JM8rT8fbXghCKuGpPzc1tQn9XyLmBwbvDDtXIcuryGb0G69YsAArK efaR25gBSg5fA== From: Sasha Levin To: patches@lists.linux.dev, stable@vger.kernel.org Cc: Ville Nummela , Johannes Berg , Sasha Levin , linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH AUTOSEL 7.0-5.10] wifi: rsi_91x_usb: do not pause rfkill polling when stopping mac80211 Date: Mon, 20 Apr 2026 09:16:48 -0400 Message-ID: <20260420132314.1023554-14-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org> References: <20260420132314.1023554-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 7.0 Content-Transfer-Encoding: 8bit From: Ville Nummela [ Upstream commit 777d8ba5aada960c666f810d5d820ab55ebb64c3 ] Removing rsi_91x USB adapter could cause rtnetlink to lock up. When rsi_mac80211_stop is called, wiphy_lock is locked. Call to wiphy_rfkill_stop_polling would wait until the work queue has finished, but because the work queue waits for wiphy_lock, that would never happen. Moving the call to rsi_disconnect avoids the lock up. Signed-off-by: Ville Nummela Link: https://patch.msgid.link/20260318081912.87744-1-ville.nummela@kempower.com Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- LLM Generated explanations, may be completely bogus: Now I have all the information needed. Let me compile the full analysis. --- ## PHASE 1: COMMIT MESSAGE FORENSICS ### Step 1.1: Subject Line - **Subsystem**: `wifi: rsi_91x_usb` (USB WiFi driver for RSI 91x chipset) - **Action verb**: "do not pause" - indicates preventing incorrect behavior that causes a hang - **Summary**: Stop rfkill polling from being paused during mac80211 stop, which causes a deadlock Record: [wifi: rsi_91x_usb] [do not pause] [Avoid deadlock by moving rfkill stop polling out of mac80211 stop callback] ### Step 1.2: Tags - **Signed-off-by**: Ville Nummela (author, external contributor from Kempower) - **Link**: `https://patch.msgid.link/20260318081912.87744-1- ville.nummela@kempower.com` - **Signed-off-by**: Johannes Berg (Intel, the wireless subsystem maintainer - applied the patch) - No Fixes: tag (expected for manual review) - No Reported-by, Tested-by, Reviewed-by Record: Patch authored by external contributor (Ville Nummela), applied by the wifi subsystem maintainer (Johannes Berg). No explicit stable nomination. ### Step 1.3: Commit Body Analysis The message describes a **deadlock**: 1. Removing the RSI USB adapter causes rtnetlink to lock up 2. `rsi_mac80211_stop` is called with `wiphy_lock` held 3. `wiphy_rfkill_stop_polling` calls `cancel_delayed_work_sync`, which waits for the rfkill poll work to finish 4. The rfkill poll work needs `wiphy_lock` to complete (via `guard(wiphy)` in `cfg80211_rfkill_poll`) 5. Classic ABBA deadlock: Thread A holds wiphy_lock, waits for work; work needs wiphy_lock Record: Real deadlock. Trigger: USB adapter removal. Failure: system hang (rtnetlink lockup). ### Step 1.4: Hidden Bug Fix Detection This is explicitly a deadlock fix, not disguised. The description clearly explains the locking inversion. Record: Explicit deadlock fix, not hidden. ## PHASE 2: DIFF ANALYSIS ### Step 2.1: Inventory - **Files changed**: 3 - `drivers/net/wireless/rsi/rsi_91x_mac80211.c`: +16/-1 (new function + remove call) - `drivers/net/wireless/rsi/rsi_91x_usb.c`: +2/-0 (call new function) - `drivers/net/wireless/rsi/rsi_common.h`: +1/-0 (declare new function) - **Total**: ~19 lines added, 1 removed - **Functions modified**: `rsi_mac80211_stop()` (removed `wiphy_rfkill_stop_polling` call), `rsi_disconnect()` (added call to new function) - **Functions added**: `rsi_mac80211_rfkill_exit()` (new helper) - **Scope**: Small, single-subsystem, well-contained ### Step 2.2: Code Flow Change 1. **rsi_mac80211_stop()**: BEFORE: called `wiphy_rfkill_stop_polling()` while holding `common->mutex` (and with `wiphy_lock` held by caller). AFTER: no longer calls it. 2. **rsi_disconnect()** (USB): BEFORE: went straight to `rsi_mac80211_detach()`. AFTER: calls `rsi_mac80211_rfkill_exit()` first (without wiphy_lock held), then `rsi_mac80211_detach()`. 3. **New `rsi_mac80211_rfkill_exit()`**: Calls `wiphy_rfkill_stop_polling()` without wiphy_lock held, breaking the deadlock. ### Step 2.3: Bug Mechanism - **Category**: Deadlock/lock ordering - **Mechanism**: `rsi_mac80211_stop()` (called with `wiphy_lock` held) invokes `wiphy_rfkill_stop_polling()` which calls `cancel_delayed_work_sync()`. The work item (`cfg80211_rfkill_poll`) needs `wiphy_lock`. Classic ABBA deadlock. - **Fix**: Move the polling stop to `rsi_disconnect()`, before `rsi_mac80211_detach()`, where `wiphy_lock` is NOT held. ### Step 2.4: Fix Quality - Obviously correct: removes the deadlocking call from the locked context, moves it to unlocked context - Minimal/surgical: small change, well-contained within the rsi driver - Other drivers (ath9k, rtlwifi, mt76, etc.) all call `wiphy_rfkill_stop_polling()` from their deinit paths, NOT from `.stop` - confirming this is the right pattern - Regression risk: very low. The rfkill polling is stopped slightly earlier in the teardown sequence ## PHASE 3: GIT HISTORY INVESTIGATION ### Step 3.1: Blame - `wiphy_rfkill_stop_polling(hw->wiphy)` in `rsi_mac80211_stop()` was added by commit `edba3532c65223` ("rsi: add support for rf-kill functionality") by Pavani Muthyala, 2017-08-03. - The deadlock was introduced when `cfg80211_rfkill_poll()` acquired wiphy_lock: commit `8e2f6f2366219` ("wifi: cfg80211: lock wiphy mutex for rfkill poll") by Johannes Berg, 2023-11-24, first in v6.7-rc4. - `drv_stop()` has had `lockdep_assert_wiphy()` since commit `0e8185ce1ddebf` (v6.7-rc1). Record: Bug is a latent deadlock since v6.7 (when wiphy_lock was added to the rfkill poll path). Buggy rfkill call in rsi since 2017, but it only became a deadlock with v6.7. ### Step 3.2: No Fixes: tag present (expected). ### Step 3.3: File History Recent changes to rsi files are mostly cleanups and unrelated bug fixes. No prerequisites identified. ### Step 3.4: Author Ville Nummela appears to be an external contributor (Kempower). This is their first rsi commit. However, the patch was applied by Johannes Berg, the wifi subsystem maintainer. ### Step 3.5: Dependencies The fix is standalone. It uses only existing APIs (`wiphy_rfkill_stop_polling`) and creates a simple wrapper function. No dependencies on other patches. ## PHASE 4: MAILING LIST RESEARCH Lore is protected by anti-bot measures, preventing direct access. B4 dig could not find the commit in the local tree. The Link tag confirms the patch was submitted and reviewed through the standard wireless-next workflow and applied by Johannes Berg. Record: Could not access lore discussion. Patch applied by subsystem maintainer. ## PHASE 5: CODE SEMANTIC ANALYSIS ### Step 5.1: Functions Modified - `rsi_mac80211_stop()` - the `.stop` mac80211 callback - `rsi_disconnect()` - USB disconnect handler - New: `rsi_mac80211_rfkill_exit()` ### Step 5.2: Callers - `rsi_mac80211_stop()` is called by mac80211 via `drv_stop()` (confirmed: `lockdep_assert_wiphy()` at driver-ops.c:39). Called when interface goes down. - `rsi_disconnect()` is the USB `.disconnect` callback, called by USB subsystem on device removal. ### Step 5.3-5.4: Call Chain for Deadlock Verified complete deadlock chain: 1. USB removal -> `rsi_disconnect()` -> `rsi_mac80211_detach()` -> `ieee80211_unregister_hw()` -> interface shutdown -> `drv_stop()` [acquires wiphy_lock] -> `rsi_mac80211_stop()` 2. `rsi_mac80211_stop()` -> `wiphy_rfkill_stop_polling()` -> `rfkill_pause_polling()` -> `cancel_delayed_work_sync(&rfkill->poll_work)` 3. Work item: `rfkill_poll()` -> `cfg80211_rfkill_poll()` -> `guard(wiphy)(&rdev->wiphy)` [tries to acquire wiphy_lock] -> BLOCKED ### Step 5.5: Similar Patterns All other wifi drivers (ath9k, rtlwifi, mt76, rtl818x, brcmsmac) call `wiphy_rfkill_stop_polling()` from their deinit/disconnect path, NOT from `.stop`. RSI was unique in calling it from `.stop`. ## PHASE 6: STABLE TREE ANALYSIS ### Step 6.1: Buggy Code in Stable - The deadlock requires both: - `wiphy_rfkill_stop_polling()` in `rsi_mac80211_stop()` (since 2017, commit edba3532) - `wiphy_lock` acquisition in `cfg80211_rfkill_poll()` (since v6.7, commit 8e2f6f23) - The deadlock exists in v6.7+ stable trees (6.12.y, 6.6.y if 8e2f6f23 was backported) ### Step 6.2: Backport Complications The fix is simple and self-contained. The rsi driver code in this area has been stable. Clean apply expected for recent stable trees. ### Step 6.3: No related fixes already in stable. ## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT - **Subsystem**: wifi (drivers/net/wireless/rsi/) - USB WiFi driver - **Criticality**: IMPORTANT - WiFi is commonly used, RSI chipsets are used in embedded/IoT - **Maintainer**: Applied by Johannes Berg (the wireless subsystem maintainer), strong trust signal ## PHASE 8: IMPACT AND RISK ASSESSMENT ### Step 8.1: Affected Users Users of RSI 91x USB WiFi adapters. When removing the adapter (physically or via software), the system hangs. ### Step 8.2: Trigger Conditions - **Trigger**: Removing RSI USB WiFi adapter (unplug or modprobe -r) - **Frequency**: Every time the adapter is removed - **Unprivileged**: Physical access needed, but could also be triggered by system suspend/resume or hotplug events ### Step 8.3: Failure Mode Severity - **Failure mode**: System hang / deadlock (rtnetlink locks up) - **Severity**: CRITICAL - system becomes partially or fully unusable; rtnetlink lockup affects all networking operations ### Step 8.4: Risk-Benefit - **Benefit**: HIGH - prevents guaranteed system hang on USB adapter removal - **Risk**: VERY LOW - 19 lines changed, moves existing call to correct context, pattern matches all other wifi drivers - **Ratio**: Strongly favorable ## PHASE 9: FINAL SYNTHESIS ### Step 9.1: Evidence Summary **FOR backporting:** - Fixes a real, reproducible deadlock (system hang) on USB adapter removal - Small, surgical fix (~20 lines across 3 files in one driver) - Obviously correct: moves `wiphy_rfkill_stop_polling()` from locked context to unlocked context - Pattern matches all other wifi drivers (ath9k, rtlwifi, mt76, etc.) - Applied by wireless subsystem maintainer (Johannes Berg) - Standalone fix with no dependencies - Bug exists since v6.7 (when wiphy_lock was added to rfkill poll) **AGAINST backporting:** - No explicit stable nomination or Fixes: tag (expected for manual review) - Only fixes USB path (SDIO has same latent issue but wasn't addressed - minor concern) - Author is external contributor with no previous rsi commits (mitigated by maintainer sign-off) ### Step 9.2: Stable Rules Checklist 1. Obviously correct and tested? **YES** - clear deadlock fix, correct locking pattern 2. Fixes a real bug? **YES** - deadlock causing system hang 3. Important issue? **YES** - deadlock = CRITICAL severity 4. Small and contained? **YES** - ~20 lines in one driver 5. No new features or APIs? **YES** - only moves existing functionality 6. Can apply to stable trees? **YES** - standalone, no dependencies ### Step 9.3: Exception Categories Not an exception case - this is a straightforward deadlock fix. ### Step 9.4: Decision This is a clear, small, surgical fix for a real deadlock that causes system hang when removing an RSI USB WiFi adapter. It follows the same pattern used by all other wifi drivers. Applied by the wifi subsystem maintainer. ## Verification - [Phase 1] Parsed tags: Link to patch.msgid.link, SOB by author and Johannes Berg (maintainer) - [Phase 2] Diff analysis: 1 line removed from `rsi_mac80211_stop()`, 16-line new function `rsi_mac80211_rfkill_exit()` added, 2 lines calling it in `rsi_disconnect()` - [Phase 3] git blame: `wiphy_rfkill_stop_polling` in `.stop` added by edba3532c65223 (2017) - [Phase 3] git show 8e2f6f2366219: confirmed `wiphy_lock` added to `cfg80211_rfkill_poll()` in v6.7-rc4 - [Phase 3] git show 0e8185ce1ddebf: confirmed `lockdep_assert_wiphy()` in `drv_stop()` since v6.7-rc1 - [Phase 3] git describe --contains 8e2f6f2366219: deadlock exists since v6.7-rc4 - [Phase 4] Could not access lore (anti-bot protection); patch Link tag confirms standard review - [Phase 5] Verified deadlock chain: `drv_stop()` holds wiphy_lock (driver-ops.c:39) -> `rsi_mac80211_stop()` -> `rfkill_pause_polling()` -> `cancel_delayed_work_sync()` blocks on work item needing wiphy_lock via `guard(wiphy)` in `cfg80211_rfkill_poll()` (core.c:224) - [Phase 5] Confirmed all other wifi drivers (ath9k, rtlwifi, mt76, rtl818x, brcmsmac) call `wiphy_rfkill_stop_polling()` from deinit path, not `.stop` - [Phase 6] Bug exists in v6.7+ trees; code in rsi driver unchanged in affected area - [Phase 8] Failure mode: deadlock/system hang, severity CRITICAL - UNVERIFIED: Could not access lore discussion for reviewer feedback **YES** drivers/net/wireless/rsi/rsi_91x_mac80211.c | 17 ++++++++++++++++- drivers/net/wireless/rsi/rsi_91x_usb.c | 2 ++ drivers/net/wireless/rsi/rsi_common.h | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index c7ae8031436ae..3faf2235728be 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -325,6 +325,22 @@ void rsi_mac80211_detach(struct rsi_hw *adapter) } EXPORT_SYMBOL_GPL(rsi_mac80211_detach); +/** + * rsi_mac80211_rfkill_exit() - This function is used to stop rfkill polling + * when the device is removed. + * @adapter: Pointer to the adapter structure. + * + * Return: None. + */ +void rsi_mac80211_rfkill_exit(struct rsi_hw *adapter) +{ + struct ieee80211_hw *hw = adapter->hw; + + if (hw) + wiphy_rfkill_stop_polling(hw->wiphy); +} +EXPORT_SYMBOL_GPL(rsi_mac80211_rfkill_exit); + /** * rsi_indicate_tx_status() - This function indicates the transmit status. * @adapter: Pointer to the adapter structure. @@ -422,7 +438,6 @@ static void rsi_mac80211_stop(struct ieee80211_hw *hw, bool suspend) rsi_dbg(ERR_ZONE, "===> Interface DOWN <===\n"); mutex_lock(&common->mutex); common->iface_down = true; - wiphy_rfkill_stop_polling(hw->wiphy); /* Block all rx frames */ rsi_send_rx_filter_frame(common, 0xffff); diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c index d83204701e27e..8765cac6f875b 100644 --- a/drivers/net/wireless/rsi/rsi_91x_usb.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c @@ -877,6 +877,8 @@ static void rsi_disconnect(struct usb_interface *pfunction) if (!adapter) return; + rsi_mac80211_rfkill_exit(adapter); + rsi_mac80211_detach(adapter); if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 && diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h index 7aa5124575cfe..591602beeec68 100644 --- a/drivers/net/wireless/rsi/rsi_common.h +++ b/drivers/net/wireless/rsi/rsi_common.h @@ -79,6 +79,7 @@ static inline int rsi_kill_thread(struct rsi_thread *handle) } void rsi_mac80211_detach(struct rsi_hw *hw); +void rsi_mac80211_rfkill_exit(struct rsi_hw *hw); u16 rsi_get_connected_channel(struct ieee80211_vif *vif); struct rsi_hw *rsi_91x_init(u16 oper_mode); void rsi_91x_deinit(struct rsi_hw *adapter); -- 2.53.0