brcmsmac: fix deadlock on missing firmware
Subsystems (3)
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
@@ -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
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
@@ -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