From 2646c46d56792bdb370784d1cd6e696a7b3bbf67 Mon Sep 17 00:00:00 2001 From: Roland Vossen Date: Fri, 21 Oct 2011 16:16:27 +0200 Subject: [PATCH] brcm80211: smac: modified Mac80211 callback interface Upon ops_start(), a Mac80211 driver should enable receive functionality to support monitor mode. Also, upon ops_stop(), it should disable rx. Driver did not follow this rule so code has been changed. Reported-by: Johannes Berg Reviewed-by: Alwin Beukers Reviewed-by: Arend van Spriel Signed-off-by: Roland Vossen Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmsmac/mac80211_if.c | 84 ++++++++----------- 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 915b74199911..f38ba17c2ebd 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -284,6 +284,7 @@ static int brcms_ops_start(struct ieee80211_hw *hw) { struct brcms_info *wl = hw->priv; bool blocked; + int err; ieee80211_wake_queues(hw); spin_lock_bh(&wl->lock); @@ -292,20 +293,48 @@ static int brcms_ops_start(struct ieee80211_hw *hw) if (!blocked) wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); - return 0; + spin_lock_bh(&wl->lock); + if (!wl->pub->up) + err = brcms_up(wl); + else + err = -ENODEV; + spin_unlock_bh(&wl->lock); + + if (err != 0) + wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__, + err); + return err; } static void brcms_ops_stop(struct ieee80211_hw *hw) { + struct brcms_info *wl = hw->priv; + int status; + ieee80211_stop_queues(hw); + + if (wl->wlc == NULL) + return; + + spin_lock_bh(&wl->lock); + status = brcms_c_chipmatch(wl->wlc->hw->vendorid, + wl->wlc->hw->deviceid); + spin_unlock_bh(&wl->lock); + if (!status) { + wiphy_err(wl->wiphy, + "wl: brcms_ops_stop: chipmatch failed\n"); + return; + } + + /* put driver in down state */ + spin_lock_bh(&wl->lock); + brcms_down(wl); + spin_unlock_bh(&wl->lock); } static int brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct brcms_info *wl; - int err; - /* Just STA for now */ if (vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_MESH_POINT && @@ -317,32 +346,12 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return -EOPNOTSUPP; } - wl = hw->priv; - spin_lock_bh(&wl->lock); - if (!wl->pub->up) - err = brcms_up(wl); - else - err = -ENODEV; - spin_unlock_bh(&wl->lock); - - if (err != 0) - wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__, - err); - - return err; + return 0; } static void brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct brcms_info *wl; - - wl = hw->priv; - - /* put driver in down state */ - spin_lock_bh(&wl->lock); - brcms_down(wl); - spin_unlock_bh(&wl->lock); } static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) @@ -874,37 +883,18 @@ static void brcms_free(struct brcms_info *wl) } /* -* called from both kernel as from this kernel module. +* called from both kernel as from this kernel module (error flow on attach) * precondition: perimeter lock is not acquired. */ static void brcms_remove(struct pci_dev *pdev) { - struct brcms_info *wl; - struct ieee80211_hw *hw; - int status; + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct brcms_info *wl = hw->priv; - hw = pci_get_drvdata(pdev); - wl = hw->priv; - if (!wl) { - pr_err("wl: brcms_remove: pci_get_drvdata failed\n"); - return; - } - - spin_lock_bh(&wl->lock); - status = brcms_c_chipmatch(pdev->vendor, pdev->device); - spin_unlock_bh(&wl->lock); - if (!status) { - wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch " - "failed\n"); - return; - } if (wl->wlc) { wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); ieee80211_unregister_hw(hw); - spin_lock_bh(&wl->lock); - brcms_down(wl); - spin_unlock_bh(&wl->lock); } pci_disable_device(pdev);