Commit 2646c46d authored by Roland Vossen's avatar Roland Vossen Committed by John W. Linville

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: default avatarJohannes Berg <johannes@sipsolutions.net>
Reviewed-by: default avatarAlwin Beukers <alwin@broadcom.com>
Reviewed-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarRoland Vossen <rvossen@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c6c44893
...@@ -284,6 +284,7 @@ static int brcms_ops_start(struct ieee80211_hw *hw) ...@@ -284,6 +284,7 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
{ {
struct brcms_info *wl = hw->priv; struct brcms_info *wl = hw->priv;
bool blocked; bool blocked;
int err;
ieee80211_wake_queues(hw); ieee80211_wake_queues(hw);
spin_lock_bh(&wl->lock); spin_lock_bh(&wl->lock);
...@@ -292,20 +293,48 @@ static int brcms_ops_start(struct ieee80211_hw *hw) ...@@ -292,20 +293,48 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
if (!blocked) if (!blocked)
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); 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) static void brcms_ops_stop(struct ieee80211_hw *hw)
{ {
struct brcms_info *wl = hw->priv;
int status;
ieee80211_stop_queues(hw); 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 static int
brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{ {
struct brcms_info *wl;
int err;
/* Just STA for now */ /* Just STA for now */
if (vif->type != NL80211_IFTYPE_AP && if (vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_MESH_POINT && vif->type != NL80211_IFTYPE_MESH_POINT &&
...@@ -317,32 +346,12 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ...@@ -317,32 +346,12 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
wl = hw->priv; 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 static void
brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 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) static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
...@@ -874,37 +883,18 @@ static void brcms_free(struct brcms_info *wl) ...@@ -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. * precondition: perimeter lock is not acquired.
*/ */
static void brcms_remove(struct pci_dev *pdev) static void brcms_remove(struct pci_dev *pdev)
{ {
struct brcms_info *wl; struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ieee80211_hw *hw; struct brcms_info *wl = hw->priv;
int status;
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) { if (wl->wlc) {
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
ieee80211_unregister_hw(hw); ieee80211_unregister_hw(hw);
spin_lock_bh(&wl->lock);
brcms_down(wl);
spin_unlock_bh(&wl->lock);
} }
pci_disable_device(pdev); pci_disable_device(pdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment