[Acked] [PATCH][trusty] UBUNTU: SAUCE: brcmsmac: fix deadlock on missing firmware
Andy Whitcroft
apw at canonical.com
Thu Apr 3 07:54:09 UTC 2014
On Wed, Apr 02, 2014 at 03:32:27PM -0500, Seth Forshee wrote:
> From: Emil Goode <emilgoode at gmail.com>
>
> 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.
>
> Signed-off-by: Emil Goode <emilgoode at gmail.com>
> Signed-off-by: John W. Linville <linville at tuxdriver.com>
> (cherry picked from commit 8fc1e8c240aab968db658b2d8d079b4391207a36
> git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git)
> BugLink: http://bugs.launchpad.net/bugs/1300416
> Signed-off-by: Seth Forshee <seth.forshee at canonical.com>
> ---
> drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 14 ++++++--------
> 1 file changed, 6 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> index edc5d10..03a56df 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> @@ -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;
Looks sane to check for the firmware early and bail without initialising
at all.
Acked-by: Andy Whitcroft <apw at canonical.com>
-apw
More information about the kernel-team
mailing list