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 25b5632fb3
("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.
Signed-off-by: Emil Goode <emilgoode@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
abee4c8414
commit
8fc1e8c240
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue