summaryrefslogtreecommitdiff
path: root/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/brcm80211/brcmsmac/wl_mac80211.c')
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wl_mac80211.c469
1 files changed, 231 insertions, 238 deletions
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
index c1b07ae31674..6c6236c969b7 100644
--- a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
+++ b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
@@ -30,6 +30,7 @@
#include <bcmdefs.h>
#include <bcmwifi.h>
#include <bcmutils.h>
+#include <bcmnvram.h>
#include <pcicfg.h>
#include <wlioctl.h>
#include <sbhnddma.h>
@@ -48,6 +49,8 @@
#include "wl_ucode.h"
#include "wl_mac80211.h"
+#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */
+
static void wl_timer(unsigned long data);
static void _wl_timer(struct wl_timer *t);
@@ -81,6 +84,7 @@ static int __devinit wl_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static void wl_remove(struct pci_dev *pdev);
static void wl_free(struct wl_info *wl);
+static void wl_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br);
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
@@ -129,7 +133,6 @@ static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw);
static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf);
static int wl_ops_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
-static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
static void wl_ops_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
@@ -147,6 +150,7 @@ static int wl_ops_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
u8 buf_size);
static void wl_ops_rfkill_poll(struct ieee80211_hw *hw);
+static void wl_ops_flush(struct ieee80211_hw *hw, bool drop);
static void wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
@@ -154,7 +158,7 @@ static void wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
WL_LOCK(wl);
if (!wl->pub->up) {
- WL_ERROR("ops->tx called while down\n");
+ wiphy_err(wl->wiphy, "ops->tx called while down\n");
kfree_skb(skb);
goto done;
}
@@ -169,7 +173,6 @@ static int wl_ops_start(struct ieee80211_hw *hw)
bool blocked;
/*
struct ieee80211_channel *curchan = hw->conf.channel;
- WL_NONE("%s : Initial channel: %d\n", __func__, curchan->hw_value);
*/
ieee80211_wake_queues(hw);
@@ -184,10 +187,6 @@ static int wl_ops_start(struct ieee80211_hw *hw)
static void wl_ops_stop(struct ieee80211_hw *hw)
{
-#ifdef BRCMDBG
- struct wl_info *wl = hw->priv;
- ASSERT(wl);
-#endif /*BRCMDBG*/
ieee80211_stop_queues(hw);
}
@@ -203,8 +202,8 @@ wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
vif->type != NL80211_IFTYPE_STATION &&
vif->type != NL80211_IFTYPE_WDS &&
vif->type != NL80211_IFTYPE_ADHOC) {
- WL_ERROR("%s: Attempt to add type %d, only STA for now\n",
- __func__, vif->type);
+ wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only"
+ " STA for now\n", __func__, vif->type);
return -EOPNOTSUPP;
}
@@ -214,7 +213,8 @@ wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
WL_UNLOCK(wl);
if (err != 0) {
- WL_ERROR("%s: wl_up() returned %d\n", __func__, err);
+ wiphy_err(hw->wiphy, "%s: wl_up() returned %d\n", __func__,
+ err);
}
return err;
}
@@ -249,7 +249,8 @@ ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
break;
case NL80211_CHAN_HT40MINUS:
case NL80211_CHAN_HT40PLUS:
- WL_ERROR("%s: Need to implement 40 Mhz Channels!\n", __func__);
+ wiphy_err(hw->wiphy,
+ "%s: Need to implement 40 Mhz Channels!\n", __func__);
err = 1;
break;
}
@@ -265,39 +266,41 @@ static int wl_ops_config(struct ieee80211_hw *hw, u32 changed)
struct wl_info *wl = HW_TO_WL(hw);
int err = 0;
int new_int;
+ struct wiphy *wiphy = hw->wiphy;
WL_LOCK(wl);
if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
if (wlc_iovar_setint
(wl->wlc, "bcn_li_bcn", conf->listen_interval)) {
- WL_ERROR("%s: Error setting listen_interval\n",
- __func__);
+ wiphy_err(wiphy, "%s: Error setting listen_interval\n",
+ __func__);
err = -EIO;
goto config_out;
}
wlc_iovar_getint(wl->wlc, "bcn_li_bcn", &new_int);
- ASSERT(new_int == conf->listen_interval);
}
if (changed & IEEE80211_CONF_CHANGE_MONITOR)
- WL_ERROR("%s: change monitor mode: %s (implement)\n", __func__,
- conf->flags & IEEE80211_CONF_MONITOR ?
- "true" : "false");
+ wiphy_err(wiphy, "%s: change monitor mode: %s (implement)\n",
+ __func__, conf->flags & IEEE80211_CONF_MONITOR ?
+ "true" : "false");
if (changed & IEEE80211_CONF_CHANGE_PS)
- WL_ERROR("%s: change power-save mode: %s (implement)\n",
- __func__, conf->flags & IEEE80211_CONF_PS ?
- "true" : "false");
+ wiphy_err(wiphy, "%s: change power-save mode: %s (implement)\n",
+ __func__, conf->flags & IEEE80211_CONF_PS ?
+ "true" : "false");
if (changed & IEEE80211_CONF_CHANGE_POWER) {
if (wlc_iovar_setint
(wl->wlc, "qtxpower", conf->power_level * 4)) {
- WL_ERROR("%s: Error setting power_level\n", __func__);
+ wiphy_err(wiphy, "%s: Error setting power_level\n",
+ __func__);
err = -EIO;
goto config_out;
}
wlc_iovar_getint(wl->wlc, "qtxpower", &new_int);
if (new_int != (conf->power_level * 4))
- WL_ERROR("%s: Power level req != actual, %d %d\n",
- __func__, conf->power_level * 4, new_int);
+ wiphy_err(wiphy, "%s: Power level req != actual, %d %d"
+ "\n", __func__, conf->power_level * 4,
+ new_int);
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
err = ieee_set_channel(hw, conf->channel, conf->channel_type);
@@ -306,13 +309,13 @@ static int wl_ops_config(struct ieee80211_hw *hw, u32 changed)
if (wlc_set
(wl->wlc, WLC_SET_SRL,
conf->short_frame_max_tx_count) < 0) {
- WL_ERROR("%s: Error setting srl\n", __func__);
+ wiphy_err(wiphy, "%s: Error setting srl\n", __func__);
err = -EIO;
goto config_out;
}
if (wlc_set(wl->wlc, WLC_SET_LRL, conf->long_frame_max_tx_count)
< 0) {
- WL_ERROR("%s: Error setting lrl\n", __func__);
+ wiphy_err(wiphy, "%s: Error setting lrl\n", __func__);
err = -EIO;
goto config_out;
}
@@ -329,25 +332,18 @@ wl_ops_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *info, u32 changed)
{
struct wl_info *wl = HW_TO_WL(hw);
+ struct wiphy *wiphy = hw->wiphy;
int val;
if (changed & BSS_CHANGED_ASSOC) {
/* association status changed (associated/disassociated)
* also implies a change in the AID.
*/
- WL_ERROR("%s: %s: %sassociated\n", KBUILD_MODNAME, __func__,
- info->assoc ? "" : "dis");
+ wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME,
+ __func__, info->assoc ? "" : "dis");
+ WL_LOCK(wl);
wlc_associate_upd(wl->wlc, info->assoc);
- }
- if (changed & BSS_CHANGED_ERP_CTS_PROT) {
- /* CTS protection changed */
- WL_ERROR("%s: use_cts_prot: %s (implement)\n", __func__,
- info->use_cts_prot ? "true" : "false");
- }
- if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- /* preamble changed */
- WL_ERROR("%s: short preamble: %s (implement)\n", __func__,
- info->use_short_preamble ? "true" : "false");
+ WL_UNLOCK(wl);
}
if (changed & BSS_CHANGED_ERP_SLOT) {
/* slot timing changed */
@@ -363,29 +359,57 @@ wl_ops_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_HT) {
/* 802.11n parameters changed */
u16 mode = info->ht_operation_mode;
- WL_NONE("%s: HT mode: 0x%04X\n", __func__, mode);
+
+ WL_LOCK(wl);
wlc_protection_upd(wl->wlc, WLC_PROT_N_CFG,
mode & IEEE80211_HT_OP_MODE_PROTECTION);
wlc_protection_upd(wl->wlc, WLC_PROT_N_NONGF,
mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
wlc_protection_upd(wl->wlc, WLC_PROT_N_OBSS,
mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);
+ WL_UNLOCK(wl);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
- /* Basic rateset changed */
- WL_ERROR("%s: Need to change Basic Rates: 0x%x (implement)\n",
- __func__, (u32) info->basic_rates);
+ struct ieee80211_supported_band *bi;
+ u32 br_mask, i;
+ u16 rate;
+ struct wl_rateset rs;
+ int error;
+
+ /* retrieve the current rates */
+ WL_LOCK(wl);
+ error = wlc_ioctl(wl->wlc, WLC_GET_CURR_RATESET,
+ &rs, sizeof(rs), NULL);
+ WL_UNLOCK(wl);
+ if (error) {
+ wiphy_err(wiphy, "%s: retrieve rateset failed: %d\n",
+ __func__, error);
+ return;
+ }
+ br_mask = info->basic_rates;
+ bi = hw->wiphy->bands[wlc_get_curband(wl->wlc)];
+ for (i = 0; i < bi->n_bitrates; i++) {
+ /* convert to internal rate value */
+ rate = (bi->bitrates[i].bitrate << 1) / 10;
+
+ /* set/clear basic rate flag */
+ wl_set_basic_rate(&rs, rate, br_mask & 1);
+ br_mask >>= 1;
+ }
+
+ /* update the rate set */
+ WL_LOCK(wl);
+ wlc_ioctl(wl->wlc, WLC_SET_RATESET, &rs, sizeof(rs), NULL);
+ WL_UNLOCK(wl);
}
if (changed & BSS_CHANGED_BEACON_INT) {
/* Beacon interval changed */
- WL_NONE("%s: Beacon Interval: %d\n",
- __func__, info->beacon_int);
+ WL_LOCK(wl);
wlc_set(wl->wlc, WLC_SET_BCNPRD, info->beacon_int);
+ WL_UNLOCK(wl);
}
if (changed & BSS_CHANGED_BSSID) {
/* BSSID changed, for whatever reason (IBSS and managed mode) */
- WL_NONE("%s: new BSSID: aid %d bss:%pM\n", __func__,
- info->aid, info->bssid);
WL_LOCK(wl);
wlc_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
info->bssid);
@@ -393,41 +417,42 @@ wl_ops_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_BEACON) {
/* Beacon data changed, retrieve new beacon (beaconing modes) */
- WL_ERROR("%s: beacon changed\n", __func__);
+ wiphy_err(wiphy, "%s: beacon changed\n", __func__);
}
if (changed & BSS_CHANGED_BEACON_ENABLED) {
/* Beaconing should be enabled/disabled (beaconing modes) */
- WL_ERROR("%s: Beacon enabled: %s\n", __func__,
- info->enable_beacon ? "true" : "false");
+ wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__,
+ info->enable_beacon ? "true" : "false");
}
if (changed & BSS_CHANGED_CQM) {
/* Connection quality monitor config changed */
- WL_ERROR("%s: cqm change: threshold %d, hys %d (implement)\n",
- __func__, info->cqm_rssi_thold, info->cqm_rssi_hyst);
+ wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d "
+ " (implement)\n", __func__, info->cqm_rssi_thold,
+ info->cqm_rssi_hyst);
}
if (changed & BSS_CHANGED_IBSS) {
/* IBSS join status changed */
- WL_ERROR("%s: IBSS joined: %s (implement)\n", __func__,
- info->ibss_joined ? "true" : "false");
+ wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__,
+ info->ibss_joined ? "true" : "false");
}
if (changed & BSS_CHANGED_ARP_FILTER) {
/* Hardware ARP filter address list or state changed */
- WL_ERROR("%s: arp filtering: enabled %s, count %d (implement)\n",
- __func__, info->arp_filter_enabled ? "true" : "false",
- info->arp_addr_cnt);
+ wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d"
+ " (implement)\n", __func__, info->arp_filter_enabled ?
+ "true" : "false", info->arp_addr_cnt);
}
if (changed & BSS_CHANGED_QOS) {
/*
* QoS for this association was enabled/disabled.
* Note that it is only ever disabled for station mode.
*/
- WL_ERROR("%s: qos enabled: %s (implement)\n", __func__,
- info->qos ? "true" : "false");
+ wiphy_err(wiphy, "%s: qos enabled: %s (implement)\n", __func__,
+ info->qos ? "true" : "false");
}
if (changed & BSS_CHANGED_IDLE) {
/* Idle changed for this BSS/interface */
- WL_ERROR("%s: BSS idle: %s (implement)\n", __func__,
- info->idle ? "true" : "false");
+ wiphy_err(wiphy, "%s: BSS idle: %s (implement)\n", __func__,
+ info->idle ? "true" : "false");
}
return;
}
@@ -438,23 +463,23 @@ wl_ops_configure_filter(struct ieee80211_hw *hw,
unsigned int *total_flags, u64 multicast)
{
struct wl_info *wl = hw->priv;
+ struct wiphy *wiphy = hw->wiphy;
changed_flags &= MAC_FILTERS;
*total_flags &= MAC_FILTERS;
if (changed_flags & FIF_PROMISC_IN_BSS)
- WL_ERROR("FIF_PROMISC_IN_BSS\n");
+ wiphy_err(wiphy, "FIF_PROMISC_IN_BSS\n");
if (changed_flags & FIF_ALLMULTI)
- WL_ERROR("FIF_ALLMULTI\n");
+ wiphy_err(wiphy, "FIF_ALLMULTI\n");
if (changed_flags & FIF_FCSFAIL)
- WL_ERROR("FIF_FCSFAIL\n");
+ wiphy_err(wiphy, "FIF_FCSFAIL\n");
if (changed_flags & FIF_PLCPFAIL)
- WL_ERROR("FIF_PLCPFAIL\n");
+ wiphy_err(wiphy, "FIF_PLCPFAIL\n");
if (changed_flags & FIF_CONTROL)
- WL_ERROR("FIF_CONTROL\n");
+ wiphy_err(wiphy, "FIF_CONTROL\n");
if (changed_flags & FIF_OTHER_BSS)
- WL_ERROR("FIF_OTHER_BSS\n");
+ wiphy_err(wiphy, "FIF_OTHER_BSS\n");
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
- WL_NONE("FIF_BCN_PRBRESP_PROMISC\n");
WL_LOCK(wl);
if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS;
@@ -471,14 +496,12 @@ wl_ops_configure_filter(struct ieee80211_hw *hw,
static int
wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
{
- WL_NONE("%s: Enter\n", __func__);
return 0;
}
static void wl_ops_sw_scan_start(struct ieee80211_hw *hw)
{
struct wl_info *wl = hw->priv;
- WL_NONE("Scan Start\n");
WL_LOCK(wl);
wlc_scan_start(wl->wlc);
WL_UNLOCK(wl);
@@ -488,7 +511,6 @@ static void wl_ops_sw_scan_start(struct ieee80211_hw *hw)
static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw)
{
struct wl_info *wl = hw->priv;
- WL_NONE("Scan Complete\n");
WL_LOCK(wl);
wlc_scan_stop(wl->wlc);
WL_UNLOCK(wl);
@@ -497,7 +519,7 @@ static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw)
static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf)
{
- WL_ERROR("%s: Enter\n", __func__);
+ wiphy_err(hw->wiphy, "%s: Enter\n", __func__);
return;
}
@@ -510,20 +532,10 @@ wl_ops_get_stats(struct ieee80211_hw *hw,
WL_LOCK(wl);
cnt = wl->pub->_cnt;
- stats->dot11ACKFailureCount = cnt->txnoack;
- stats->dot11RTSFailureCount = cnt->txnocts;
- stats->dot11FCSErrorCount = cnt->rxcrc;
- stats->dot11RTSSuccessCount = cnt->txrts;
- WL_UNLOCK(wl);
- return 0;
-}
-
-static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
-{
- struct wl_info *wl = hw->priv;
-
- WL_LOCK(wl);
- wlc_iovar_setint(wl->wlc, "rtsthresh", value & 0xFFFF);
+ stats->dot11ACKFailureCount = 0;
+ stats->dot11RTSFailureCount = 0;
+ stats->dot11FCSErrorCount = 0;
+ stats->dot11RTSSuccessCount = 0;
WL_UNLOCK(wl);
return 0;
}
@@ -532,10 +544,10 @@ static void
wl_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
{
- WL_NONE("%s: Enter\n", __func__);
switch (cmd) {
default:
- WL_ERROR("%s: Unknown cmd = %d\n", __func__, cmd);
+ wiphy_err(hw->wiphy, "%s: Unknown cmd = %d\n", __func__,
+ cmd);
break;
}
return;
@@ -547,12 +559,8 @@ wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
{
struct wl_info *wl = hw->priv;
- WL_NONE("%s: Enter (WME config)\n", __func__);
- WL_NONE("queue %d, txop %d, cwmin %d, cwmax %d, aifs %d\n", queue,
- params->txop, params->cw_min, params->cw_max, params->aifs);
-
WL_LOCK(wl);
- wlc_wme_setparams(wl->wlc, queue, (void *)params, true);
+ wlc_wme_setparams(wl->wlc, queue, params, true);
WL_UNLOCK(wl);
return 0;
@@ -560,7 +568,7 @@ wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
static u64 wl_ops_get_tsf(struct ieee80211_hw *hw)
{
- WL_ERROR("%s: Enter\n", __func__);
+ wiphy_err(hw->wiphy, "%s: Enter\n", __func__);
return 0;
}
@@ -585,7 +593,7 @@ wl_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
wl->pub->global_ampdu = &(scb->scb_ampdu);
wl->pub->global_ampdu->scb = scb;
wl->pub->global_ampdu->max_pdu = 16;
- pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
+ bcm_pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT);
sta->ht_cap.ht_supported = true;
@@ -603,7 +611,6 @@ static int
wl_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- WL_NONE("%s: Enter\n", __func__);
return 0;
}
@@ -614,27 +621,25 @@ wl_ops_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
u8 buf_size)
{
-#if defined(BCMDBG)
struct scb *scb = (struct scb *)sta->drv_priv;
-#endif
struct wl_info *wl = hw->priv;
int status;
- ASSERT(scb->magic == SCB_MAGIC);
+ if (WARN_ON(scb->magic != SCB_MAGIC))
+ return -EIDRM;
switch (action) {
case IEEE80211_AMPDU_RX_START:
- WL_NONE("%s: action = IEEE80211_AMPDU_RX_START\n", __func__);
break;
case IEEE80211_AMPDU_RX_STOP:
- WL_NONE("%s: action = IEEE80211_AMPDU_RX_STOP\n", __func__);
break;
case IEEE80211_AMPDU_TX_START:
WL_LOCK(wl);
status = wlc_aggregatable(wl->wlc, tid);
WL_UNLOCK(wl);
if (!status) {
- /* WL_ERROR("START: tid %d is not agg' able, return FAILURE to stack\n", tid); */
- return -1;
+ wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n",
+ tid);
+ return -EINVAL;
}
/* XXX: Use the starting sequence number provided ... */
*ssn = 0;
@@ -650,11 +655,10 @@ wl_ops_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_TX_OPERATIONAL:
/* Not sure what to do here */
/* Power save wakeup */
- WL_NONE("%s: action = IEEE80211_AMPDU_TX_OPERATIONAL\n",
- __func__);
break;
default:
- WL_ERROR("%s: Invalid command, ignoring\n", __func__);
+ wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n",
+ __func__);
}
return 0;
@@ -669,10 +673,21 @@ static void wl_ops_rfkill_poll(struct ieee80211_hw *hw)
blocked = wlc_check_radio_disabled(wl->wlc);
WL_UNLOCK(wl);
- WL_NONE("wl: rfkill_poll: %d\n", blocked);
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
}
+static void wl_ops_flush(struct ieee80211_hw *hw, bool drop)
+{
+ struct wl_info *wl = HW_TO_WL(hw);
+
+ no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
+
+ /* wait for packet queue and dma fifos to run empty */
+ WL_LOCK(wl);
+ wlc_wait_for_tx_completion(wl->wlc, drop);
+ WL_UNLOCK(wl);
+}
+
static const struct ieee80211_ops wl_ops = {
.tx = wl_ops_tx,
.start = wl_ops_start,
@@ -687,7 +702,6 @@ static const struct ieee80211_ops wl_ops = {
.sw_scan_complete = wl_ops_sw_scan_complete,
.set_tsf = wl_ops_set_tsf,
.get_stats = wl_ops_get_stats,
- .set_rts_threshold = wl_ops_set_rts_threshold,
.sta_notify = wl_ops_sta_notify,
.conf_tx = wl_ops_conf_tx,
.get_tsf = wl_ops_get_tsf,
@@ -695,6 +709,7 @@ static const struct ieee80211_ops wl_ops = {
.sta_remove = wl_ops_sta_remove,
.ampdu_action = wl_ops_ampdu_action,
.rfkill_poll = wl_ops_rfkill_poll,
+ .flush = wl_ops_flush,
};
/*
@@ -702,8 +717,6 @@ static const struct ieee80211_ops wl_ops = {
*/
static int wl_set_hint(struct wl_info *wl, char *abbrev)
{
- WL_NONE("%s: Sending country code %c%c to MAC80211\n",
- __func__, abbrev[0], abbrev[1]);
return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
}
@@ -724,7 +737,7 @@ static int wl_set_hint(struct wl_info *wl, char *abbrev)
static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
uint bustype, void *btparam, uint irq)
{
- struct wl_info *wl;
+ struct wl_info *wl = NULL;
int unit, err;
unsigned long base_addr;
@@ -735,14 +748,16 @@ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
err = 0;
if (unit < 0) {
- WL_ERROR("wl%d: unit number overflow, exiting\n", unit);
return NULL;
}
/* allocate private info */
hw = pci_get_drvdata(btparam); /* btparam == pdev */
- wl = hw->priv;
- ASSERT(wl);
+ if (hw != NULL)
+ wl = hw->priv;
+ if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL))
+ return NULL;
+ wl->wiphy = hw->wiphy;
atomic_set(&wl->callbacks, 0);
@@ -759,13 +774,13 @@ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
/* Do nothing */
} else {
bustype = PCI_BUS;
- WL_TRACE("force to PCI\n");
+ BCMMSG(wl->wiphy, "force to PCI\n");
}
wl->bcm_bustype = bustype;
wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ);
if (wl->regsva == NULL) {
- WL_ERROR("wl%d: ioremap() failed\n", unit);
+ wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit);
goto fail;
}
spin_lock_init(&wl->lock);
@@ -773,11 +788,11 @@ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
/* prepare ucode */
if (wl_request_fw(wl, (struct pci_dev *)btparam) < 0) {
- WL_ERROR("%s: Failed to find firmware usually in %s\n",
- KBUILD_MODNAME, "/lib/firmware/brcm");
+ wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
+ "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
wl_release_fw(wl);
wl_remove((struct pci_dev *)btparam);
- goto fail1;
+ return NULL;
}
/* common load-time initialization */
@@ -785,24 +800,22 @@ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
wl->regsva, wl->bcm_bustype, btparam, &err);
wl_release_fw(wl);
if (!wl->wlc) {
- WL_ERROR("%s: wlc_attach() failed with code %d\n",
- KBUILD_MODNAME, err);
+ wiphy_err(wl->wiphy, "%s: wlc_attach() failed with code %d\n",
+ KBUILD_MODNAME, err);
goto fail;
}
wl->pub = wlc_pub(wl->wlc);
wl->pub->ieee_hw = hw;
- ASSERT(wl->pub->ieee_hw);
- ASSERT(wl->pub->ieee_hw->priv == wl);
-
if (wlc_iovar_setint(wl->wlc, "mpc", 0)) {
- WL_ERROR("wl%d: Error setting MPC variable to 0\n", unit);
+ wiphy_err(wl->wiphy, "wl%d: Error setting MPC variable to 0\n",
+ unit);
}
/* register our interrupt handler */
if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
- WL_ERROR("wl%d: request_irq() failed\n", unit);
+ wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);
goto fail;
}
wl->irq = irq;
@@ -812,18 +825,20 @@ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
NULL);
if (ieee_hw_init(hw)) {
- WL_ERROR("wl%d: %s: ieee_hw_init failed!\n", unit, __func__);
+ wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit,
+ __func__);
goto fail;
}
memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
- ASSERT(is_valid_ether_addr(perm));
+ if (WARN_ON(!is_valid_ether_addr(perm)))
+ goto fail;
SET_IEEE80211_PERM_ADDR(hw, perm);
err = ieee80211_register_hw(hw);
if (err) {
- WL_ERROR("%s: ieee80211_register_hw failed, status %d\n",
- __func__, err);
+ wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status"
+ "%d\n", __func__, err);
}
if (wl->pub->srom_ccode[0])
@@ -831,8 +846,8 @@ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
else
err = wl_set_hint(wl, "US");
if (err) {
- WL_ERROR("%s: regulatory_hint failed, status %d\n",
- __func__, err);
+ wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n",
+ __func__, err);
}
wl_found++;
@@ -840,7 +855,6 @@ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
fail:
wl_free(wl);
-fail1:
return NULL;
}
@@ -1027,9 +1041,8 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
if (wlc_get(wl->wlc, WLC_GET_PHYLIST, (int *)&phy_list) < 0) {
- WL_ERROR("Phy list failed\n");
+ wiphy_err(hw->wiphy, "Phy list failed\n");
}
- WL_NONE("%s: phylist = %c\n", __func__, phy_list[0]);
if (phy_list[0] == 'n' || phy_list[0] == 'c') {
if (phy_list[0] == 'c') {
@@ -1039,8 +1052,7 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw)
}
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl_band_2GHz_nphy;
} else {
- BUG();
- return -1;
+ return -EPERM;
}
/* Assume all bands use the same phy. True for 11n devices. */
@@ -1050,12 +1062,9 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&wl_band_5GHz_nphy;
} else {
- return -1;
+ return -EPERM;
}
}
-
- WL_NONE("%s: 2ghz = %d, 5ghz = %d\n", __func__, 1, has_5g);
-
return 0;
}
@@ -1070,8 +1079,7 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
| IEEE80211_HW_AMPDU_AGGREGATION;
hw->extra_tx_headroom = wlc_get_header_len();
- /* FIXME: should get this from wlc->machwcap */
- hw->queues = 4;
+ hw->queues = N_TX_QUEUES;
/* FIXME: this doesn't seem to be used properly in minstrel_ht.
* mac80211/status.c:ieee80211_tx_status() checks this value,
* but mac80211/rc80211_minstrel_ht.c:minstrel_ht_get_rate()
@@ -1104,11 +1112,9 @@ wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct ieee80211_hw *hw;
u32 val;
- ASSERT(pdev);
-
- WL_TRACE("%s: bus %d slot %d func %d irq %d\n",
- __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn), pdev->irq);
+ dev_info(&pdev->dev, "bus %d slot %d func %d irq %d\n",
+ pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn), pdev->irq);
if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
(((pdev->device & 0xff00) != 0x4300) &&
@@ -1118,9 +1124,9 @@ wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
rc = pci_enable_device(pdev);
if (rc) {
- WL_ERROR("%s: Cannot enable device %d-%d_%d\n",
- __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn));
+ pr_err("%s: Cannot enable device %d-%d_%d\n",
+ __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn));
return -ENODEV;
}
pci_set_master(pdev);
@@ -1131,9 +1137,8 @@ wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw = ieee80211_alloc_hw(sizeof(struct wl_info), &wl_ops);
if (!hw) {
- WL_ERROR("%s: ieee80211_alloc_hw failed\n", __func__);
- rc = -ENOMEM;
- goto err_1;
+ pr_err("%s: ieee80211_alloc_hw failed\n", __func__);
+ return -ENOMEM;
}
SET_IEEE80211_DEV(hw, &pdev->dev);
@@ -1146,14 +1151,11 @@ wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
PCI_BUS, pdev, pdev->irq);
if (!wl) {
- WL_ERROR("%s: %s: wl_attach failed!\n",
- KBUILD_MODNAME, __func__);
+ pr_err("%s: %s: wl_attach failed!\n", KBUILD_MODNAME,
+ __func__);
return -ENODEV;
}
return 0;
- err_1:
- WL_ERROR("%s: err_1: Major hoarkage\n", __func__);
- return 0;
}
static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -1161,12 +1163,11 @@ static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
struct wl_info *wl;
struct ieee80211_hw *hw;
- WL_TRACE("wl: wl_suspend\n");
-
hw = pci_get_drvdata(pdev);
wl = HW_TO_WL(hw);
if (!wl) {
- WL_ERROR("wl: wl_suspend: pci_get_drvdata failed\n");
+ wiphy_err(wl->wiphy,
+ "wl_suspend: pci_get_drvdata failed\n");
return -ENODEV;
}
@@ -1187,11 +1188,11 @@ static int wl_resume(struct pci_dev *pdev)
int err = 0;
u32 val;
- WL_TRACE("wl: wl_resume\n");
hw = pci_get_drvdata(pdev);
wl = HW_TO_WL(hw);
if (!wl) {
- WL_ERROR("wl: wl_resume: pci_get_drvdata failed\n");
+ wiphy_err(wl->wiphy,
+ "wl: wl_resume: pci_get_drvdata failed\n");
return -ENODEV;
}
@@ -1231,7 +1232,7 @@ static void wl_remove(struct pci_dev *pdev)
hw = pci_get_drvdata(pdev);
wl = HW_TO_WL(hw);
if (!wl) {
- WL_ERROR("wl: wl_remove: pci_get_drvdata failed\n");
+ pr_err("wl: wl_remove: pci_get_drvdata failed\n");
return;
}
@@ -1239,7 +1240,7 @@ static void wl_remove(struct pci_dev *pdev)
status = wlc_chipmatch(pdev->vendor, pdev->device);
WL_UNLOCK(wl);
if (!status) {
- WL_ERROR("wl: wl_remove: wlc_chipmatch failed\n");
+ wiphy_err(wl->wiphy, "wl: wl_remove: wlc_chipmatch failed\n");
return;
}
if (wl->wlc) {
@@ -1249,7 +1250,6 @@ static void wl_remove(struct pci_dev *pdev)
WL_LOCK(wl);
wl_down(wl);
WL_UNLOCK(wl);
- WL_NONE("%s: Down\n", __func__);
}
pci_disable_device(pdev);
@@ -1342,7 +1342,6 @@ static void wl_free(struct wl_info *wl)
{
struct wl_timer *t, *next;
- ASSERT(wl);
/* free ucode data */
if (wl->fw.fw_cnt)
wl_ucode_data_free();
@@ -1389,13 +1388,30 @@ static void wl_free(struct wl_info *wl)
wl->regsva = NULL;
}
+/* flags the given rate in rateset as requested */
+static void wl_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br)
+{
+ u32 i;
+
+ for (i = 0; i < rs->count; i++) {
+ if (rate != (rs->rates[i] & 0x7f))
+ continue;
+
+ if (is_br)
+ rs->rates[i] |= WLC_RATE_FLAG;
+ else
+ rs->rates[i] &= WLC_RATE_MASK;
+ return;
+ }
+}
+
/*
* precondition: perimeter lock has been acquired
*/
void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
int prio)
{
- WL_ERROR("Shouldn't be here %s\n", __func__);
+ wiphy_err(wl->wiphy, "Shouldn't be here %s\n", __func__);
}
/*
@@ -1403,8 +1419,7 @@ void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
*/
void wl_init(struct wl_info *wl)
{
- WL_TRACE("wl%d: wl_init\n", wl->pub->unit);
-
+ BCMMSG(WL_TO_HW(wl)->wiphy, "wl%d\n", wl->pub->unit);
wl_reset(wl);
wlc_init(wl->wlc);
@@ -1415,8 +1430,7 @@ void wl_init(struct wl_info *wl)
*/
uint wl_reset(struct wl_info *wl)
{
- WL_TRACE("wl%d: wl_reset\n", wl->pub->unit);
-
+ BCMMSG(WL_TO_HW(wl)->wiphy, "wl%d\n", wl->pub->unit);
wlc_reset(wl->wlc);
/* dpc will not be rescheduled */
@@ -1429,7 +1443,7 @@ uint wl_reset(struct wl_info *wl)
* These are interrupt on/off entry points. Disable interrupts
* during interrupt state transition.
*/
-void BCMFASTPATH wl_intrson(struct wl_info *wl)
+void wl_intrson(struct wl_info *wl)
{
unsigned long flags;
@@ -1446,7 +1460,7 @@ bool wl_alloc_dma_resources(struct wl_info *wl, uint addrwidth)
return true;
}
-u32 BCMFASTPATH wl_intrsoff(struct wl_info *wl)
+u32 wl_intrsoff(struct wl_info *wl)
{
unsigned long flags;
u32 status;
@@ -1503,7 +1517,7 @@ void wl_down(struct wl_info *wl)
WL_LOCK(wl);
}
-static irqreturn_t BCMFASTPATH wl_isr(int irq, void *dev_id)
+static irqreturn_t wl_isr(int irq, void *dev_id)
{
struct wl_info *wl;
bool ours, wantdpc;
@@ -1521,7 +1535,6 @@ static irqreturn_t BCMFASTPATH wl_isr(int irq, void *dev_id)
/* ...and call the second level interrupt handler */
/* schedule dpc */
- ASSERT(wl->resched == false);
tasklet_schedule(&wl->tasklet);
}
}
@@ -1531,7 +1544,7 @@ static irqreturn_t BCMFASTPATH wl_isr(int irq, void *dev_id)
return IRQ_RETVAL(ours);
}
-static void BCMFASTPATH wl_dpc(unsigned long data)
+static void wl_dpc(unsigned long data)
{
struct wl_info *wl;
@@ -1613,7 +1626,8 @@ struct wl_timer *wl_init_timer(struct wl_info *wl, void (*fn) (void *arg),
t = kzalloc(sizeof(struct wl_timer), GFP_ATOMIC);
if (!t) {
- WL_ERROR("wl%d: wl_init_timer: out of memory\n", wl->pub->unit);
+ wiphy_err(wl->wiphy, "wl%d: wl_init_timer: out of memory\n",
+ wl->pub->unit);
return 0;
}
@@ -1644,12 +1658,10 @@ void wl_add_timer(struct wl_info *wl, struct wl_timer *t, uint ms, int periodic)
{
#ifdef BCMDBG
if (t->set) {
- WL_ERROR("%s: Already set. Name: %s, per %d\n",
- __func__, t->name, periodic);
+ wiphy_err(wl->wiphy, "%s: Already set. Name: %s, per %d\n",
+ __func__, t->name, periodic);
}
#endif
- ASSERT(!t->set);
-
t->ms = ms;
t->periodic = (bool) periodic;
t->set = true;
@@ -1719,37 +1731,6 @@ void wl_free_timer(struct wl_info *wl, struct wl_timer *t)
*/
static int wl_linux_watchdog(void *ctx)
{
- struct wl_info *wl = (struct wl_info *) ctx;
- struct wl_cnt *cnt;
- struct net_device_stats *stats = NULL;
- uint id;
- /* refresh stats */
- if (wl->pub->up) {
- ASSERT(wl->stats_id < 2);
-
- cnt = wl->pub->_cnt;
- id = 1 - wl->stats_id;
- stats = &wl->stats_watchdog[id];
- stats->rx_packets = cnt->rxframe;
- stats->tx_packets = cnt->txframe;
- stats->rx_bytes = cnt->rxbyte;
- stats->tx_bytes = cnt->txbyte;
- stats->rx_errors = cnt->rxerror;
- stats->tx_errors = cnt->txerror;
- stats->collisions = 0;
-
- stats->rx_length_errors = 0;
- stats->rx_over_errors = cnt->rxoflo;
- stats->rx_crc_errors = cnt->rxcrc;
- stats->rx_frame_errors = 0;
- stats->rx_fifo_errors = cnt->rxoflo;
- stats->rx_missed_errors = 0;
-
- stats->tx_fifo_errors = cnt->txuflo;
-
- wl->stats_id = id;
- }
-
return 0;
}
@@ -1780,8 +1761,8 @@ int wl_ucode_init_buf(struct wl_info *wl, void **pbuf, u32 idx)
pdata = wl->fw.fw_bin[i]->data + hdr->offset;
*pbuf = kmalloc(hdr->len, GFP_ATOMIC);
if (*pbuf == NULL) {
- WL_ERROR("fail to alloc %d bytes\n",
- hdr->len);
+ wiphy_err(wl->wiphy, "fail to alloc %d"
+ " bytes\n", hdr->len);
goto fail;
}
memcpy(*pbuf, pdata, hdr->len);
@@ -1789,10 +1770,11 @@ int wl_ucode_init_buf(struct wl_info *wl, void **pbuf, u32 idx)
}
}
}
- WL_ERROR("ERROR: ucode buf tag:%d can not be found!\n", idx);
+ wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n",
+ idx);
*pbuf = NULL;
fail:
- return BCME_NOTFOUND;
+ return -ENODATA;
}
/*
@@ -1810,14 +1792,18 @@ int wl_ucode_init_uint(struct wl_info *wl, u32 *data, u32 idx)
entry++, hdr++) {
if (hdr->idx == idx) {
pdata = wl->fw.fw_bin[i]->data + hdr->offset;
- ASSERT(hdr->len == 4);
+ if (hdr->len != 4) {
+ wiphy_err(wl->wiphy,
+ "ERROR: fw hdr len\n");
+ return -ENOMSG;
+ }
*data = *((u32 *) pdata);
return 0;
}
}
}
- WL_ERROR("ERROR: ucode tag:%d can not be found!\n", idx);
- return -1;
+ wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx);
+ return -ENOMSG;
}
/*
@@ -1837,26 +1823,22 @@ static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev)
break;
sprintf(fw_name, "%s-%d.fw", wl_firmwares[i],
UCODE_LOADER_API_VER);
- WL_NONE("request fw %s\n", fw_name);
status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
if (status) {
- WL_ERROR("%s: fail to load firmware %s\n",
- KBUILD_MODNAME, fw_name);
+ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+ KBUILD_MODNAME, fw_name);
return status;
}
- WL_NONE("request fw %s\n", fw_name);
sprintf(fw_name, "%s_hdr-%d.fw", wl_firmwares[i],
UCODE_LOADER_API_VER);
status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
if (status) {
- WL_ERROR("%s: fail to load firmware %s\n",
- KBUILD_MODNAME, fw_name);
+ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+ KBUILD_MODNAME, fw_name);
return status;
}
wl->fw.hdr_num_entries[i] =
wl->fw.fw_hdr[i]->size / (sizeof(struct wl_fw_hdr));
- WL_NONE("request fw %s find: %d entries\n",
- fw_name, wl->fw.hdr_num_entries[i]);
}
wl->fw.fw_cnt = i;
return wl_ucode_data_init(wl);
@@ -1904,16 +1886,17 @@ int wl_check_firmwares(struct wl_info *wl)
if (fw == NULL && fw_hdr == NULL) {
break;
} else if (fw == NULL || fw_hdr == NULL) {
- WL_ERROR("%s: invalid bin/hdr fw\n", __func__);
+ wiphy_err(wl->wiphy, "%s: invalid bin/hdr fw\n",
+ __func__);
rc = -EBADF;
} else if (fw_hdr->size % sizeof(struct wl_fw_hdr)) {
- WL_ERROR("%s: non integral fw hdr file size %zu/%zu\n",
- __func__, fw_hdr->size,
- sizeof(struct wl_fw_hdr));
+ wiphy_err(wl->wiphy, "%s: non integral fw hdr file "
+ "size %zu/%zu\n", __func__, fw_hdr->size,
+ sizeof(struct wl_fw_hdr));
rc = -EBADF;
} else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
- WL_ERROR("%s: out of bounds fw file size %zu\n",
- __func__, fw->size);
+ wiphy_err(wl->wiphy, "%s: out of bounds fw file size "
+ "%zu\n", __func__, fw->size);
rc = -EBADF;
} else {
/* check if ucode section overruns firmware image */
@@ -1922,15 +1905,17 @@ int wl_check_firmwares(struct wl_info *wl)
!rc; entry++, ucode_hdr++) {
if (ucode_hdr->offset + ucode_hdr->len >
fw->size) {
- WL_ERROR("%s: conflicting bin/hdr\n",
- __func__);
+ wiphy_err(wl->wiphy,
+ "%s: conflicting bin/hdr\n",
+ __func__);
rc = -EBADF;
}
}
}
}
if (rc == 0 && wl->fw.fw_cnt != i) {
- WL_ERROR("%s: invalid fw_cnt=%d\n", __func__, wl->fw.fw_cnt);
+ wiphy_err(wl->wiphy, "%s: invalid fw_cnt=%d\n", __func__,
+ wl->fw.fw_cnt);
rc = -EBADF;
}
return rc;
@@ -1943,8 +1928,6 @@ bool wl_rfkill_set_hw_state(struct wl_info *wl)
{
bool blocked = wlc_check_radio_disabled(wl->wlc);
- WL_NONE("%s: update hw state: blocked=%s\n", __func__,
- blocked ? "true" : "false");
WL_UNLOCK(wl);
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
if (blocked)
@@ -1952,3 +1935,13 @@ bool wl_rfkill_set_hw_state(struct wl_info *wl)
WL_LOCK(wl);
return blocked;
}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void wl_msleep(struct wl_info *wl, uint ms)
+{
+ WL_UNLOCK(wl);
+ msleep(ms);
+ WL_LOCK(wl);
+}