Thread (6 messages) 6 messages, 4 authors, 17d ago

Re: [PATCH] wifi: brcmfmac: drain bus_reset work on device removal

From: Arend van Spriel <arend.vanspriel@broadcom.com>
Date: 2026-07-10 19:18:31
Also in: linux-wireless, lkml, stable

On 10/07/2026 02:23, Eddie Phillips wrote:
On Thu,  9 Jul 2026 10:16:35 +0000 Fan Wu [off-list ref] wrote:
quoted
brcmf_fw_crashed() and the debugfs "reset" entry both schedule
drvr->bus_reset, whose callback recovers drvr through container_of()
and dereferences it.  The teardown paths free drvr (brcmf_free ->
wiphy_free) without draining the work, so a bus_reset callback pending
or running during removal can outlive drvr.
[...]
quoted
This issue was found by an in-house static analysis tool.

Fixes: 4684997d9eea ("brcmfmac: reset PCIe bus on a firmware crash")
Cc: stable@vger.kernel.org
Signed-off-by: Fan Wu <redacted>
Assisted-by: Codex:gpt-5.5
---
  .../broadcom/brcm80211/brcmfmac/bcmsdh.c      | 13 ++++++++
  .../broadcom/brcm80211/brcmfmac/bus.h         |  6 ++++
  .../broadcom/brcm80211/brcmfmac/core.c        | 33 +++++++++++++++++--
  .../broadcom/brcm80211/brcmfmac/pcie.c        |  6 ++++
  .../broadcom/brcm80211/brcmfmac/sdio.c        |  6 ++++
  .../broadcom/brcm80211/brcmfmac/sdio.h        |  1 +
  .../broadcom/brcm80211/brcmfmac/usb.c         |  3 ++
  7 files changed, 66 insertions(+), 2 deletions(-)
[...]
quoted
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index fed9cd5f2..b934feb9b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -1164,6 +1164,35 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data)
  	return 0;
  }
  
+/* Serialize bus_reset arming (debugfs reset write, brcmf_fw_crashed) against the
+ * teardown drain: the remove path takes bus_reset_lock, sets ->removing and cancels
+ * the work under it, so a racing armer either schedules before the cancel (and is
+ * drained) or observes ->removing and desists.
+ */
+static void brcmf_bus_schedule_reset(struct brcmf_bus *bus_if)
+{
+	mutex_lock(&bus_if->bus_reset_lock);
+	if (bus_if->drvr && bus_if->drvr->bus_reset.func && !bus_if->removing)
+		schedule_work(&bus_if->drvr->bus_reset);
+	mutex_unlock(&bus_if->bus_reset_lock);
+}
Is this safe in a softIRQ context?
mutex_lock() sleeps until it can get the lock.
What softIRQ context? brcmf_fw_crashed() is called by PCIe (thread) and 
SDIO (worker).
quoted
+
+void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if)
+{
+	mutex_lock(&bus_if->bus_reset_lock);
+	bus_if->removing = true;
+	if (bus_if->drvr)
+		cancel_work_sync(&bus_if->drvr->bus_reset);
+	mutex_unlock(&bus_if->bus_reset_lock);
+}
How about if brcmf_pcie_remove() calls brcmf_bus_cancel_reset_work(),
takes the lock and calls cancel_work_sync(), sleeps. If debugfs
path is already running, it can invoke the worker thread. Is there
potential that both try to reset?
What is "both" here?
Regards,
Arend
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help