Skip to contentSkip to conversation

brcmsmac: fix deadlock on missing firmware

PATCH New Emil Goode 1 participant 2 messages Mar 9, 2014

Subsystems (3)
lore
Share & tools
lore

Emil Goode

author
#0 lore raw

PATCH 1/2 brcmsmac: fix deadlock on missing firmware

When brcm80211 firmware is not installed networking hangs. A deadlock happens because we call ieee80211_unregister_hw() from the .start callback of struct ieee80211_ops. When .start is called we are under rtnl lock and ieee80211_unregister_hw() tries to take it again.

Function call stack:

dev_change_flags()

	__dev_change_flags()
		__dev_open()
			ASSERT_RTNL() <-- Assert rtnl lock
			ops->ndo_open()

.ndo_open = ieee80211_open,

ieee80211_open()

	ieee80211_do_open()
		drv_start()
			local->ops->start()

.start = brcms_ops_start,

brcms_ops_start()

	brcms_remove()
		ieee80211_unregister_hw()
			rtnl_lock() <-- Here we deadlock

Introduced by:
commit 25b5632fb35ca61b8ae3eee235edcdc2883f7a5e ("brcmsmac: request firmware in .start() callback")

This patch fixes the bug by removing the call to brcms_remove() and moves the brcms_request_fw() call to the top of the .start callback to not initiate anything unless firmware is installed.

---
 drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c |   14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +6 -8
index 925034b..93598cd 100644
@@ -426,6 +426,12 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
 	bool blocked;
 	int err;
 
+	if (!wl->ucode.bcm43xx_bomminor) {
+		err = brcms_request_fw(wl, wl->wlc->hw->d11core);
+		if (err)
+			return -ENOENT;
+	}
+
 	ieee80211_wake_queues(hw);
 	spin_lock_bh(&wl->lock);
 	blocked = brcms_rfkill_set_hw_state(wl);
@@ -433,14 +439,6 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
 	if (!blocked)
 		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
 
-	if (!wl->ucode.bcm43xx_bomminor) {
-		err = brcms_request_fw(wl, wl->wlc->hw->d11core);
-		if (err) {
-			brcms_remove(wl->wlc->hw->d11core);
-			return -ENOENT;
-		}
-	}
-
 	spin_lock_bh(&wl->lock);
 	/* avoid acknowledging frames before a non-monitor device is added */
 	wl->mute_tx = true;
Signature · 1 line
1.7.10.4
author
#1 lore raw

PATCH 2/2 brcmsmac: update comment to reflect the code

The brcms_attach function is defined as static but the comment is saying that it should not be static or gcc will issue a warning. I believe we can remove the comment as I don't se a problem with this function being defined as static.

---
 drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c |    6 ------
 1 file changed, 6 deletions(-)
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +0 -6
index 93598cd..8c5fa4e 100644
@@ -1092,12 +1092,6 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
  * Attach to the WL device identified by vendor and device parameters.
  * regs is a host accessible memory address pointing to WL device registers.
  *
- * brcms_attach is not defined as static because in the case where no bus
- * is defined, wl_attach will never be called, and thus, gcc will issue
- * a warning that this function is defined but not used if we declare
- * it as static.
- *
- *
  * is called in brcms_bcma_probe() context, therefore no locking required.
  */
 static struct brcms_info *brcms_attach(struct bcma_device *pdev)
Signature · 1 line
1.7.10.4