Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 13/22] brcm80211: use endian annotation for scan time configuration
From: Arend van Spriel @ 2011-10-12 18:51 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1318445492-24207-1-git-send-email-arend@broadcom.com>

For scanning several timeout parameters are configured on the device.
These parameters have been endian annotated and converted appropriately.

Reported-by: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: Roland Vossen <rvossen@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 8fc8173..1b09be0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -3497,12 +3497,15 @@ dongle_rom_out:
 
 static s32
 brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
-		s32 scan_unassoc_time, s32 scan_passive_time)
+		      s32 scan_unassoc_time, s32 scan_passive_time)
 {
 	s32 err = 0;
+	__le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time);
+	__le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time);
+	__le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time);
 
 	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
-			   &scan_assoc_time, sizeof(scan_assoc_time));
+			   &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO("Scan assoc time is not supported\n");
@@ -3511,7 +3514,7 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 		goto dongle_scantime_out;
 	}
 	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
-			   &scan_unassoc_time, sizeof(scan_unassoc_time));
+			   &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO("Scan unassoc time is not supported\n");
@@ -3521,7 +3524,7 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 	}
 
 	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
-			   &scan_passive_time, sizeof(scan_passive_time));
+			   &scan_passive_tm_le, sizeof(scan_passive_tm_le));
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO("Scan passive time is not supported\n");
-- 
1.7.4.1



^ permalink raw reply related

* [PATCH 22/22] brcm80211: removed file wifi.c
From: Arend van Spriel @ 2011-10-12 18:51 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Alwin Beukers, Arend van Spriel
In-Reply-To: <1318445492-24207-1-git-send-email-arend@broadcom.com>

From: Alwin Beukers <alwin@broadcom.com>

Wifi.c was empty after previous cleanups, so it was removed.

Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmutil/Makefile |    3 +--
 drivers/net/wireless/brcm80211/brcmutil/wifi.c   |   16 ----------------
 2 files changed, 1 insertions(+), 18 deletions(-)
 delete mode 100644 drivers/net/wireless/brcm80211/brcmutil/wifi.c

diff --git a/drivers/net/wireless/brcm80211/brcmutil/Makefile b/drivers/net/wireless/brcm80211/brcmutil/Makefile
index 720e261..6281c41 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmutil/Makefile
@@ -20,8 +20,7 @@ ccflags-y :=				\
 	-Idrivers/net/wireless/brcm80211/include
 
 BRCMUTIL_OFILES := \
-	utils.o \
-	wifi.o
+	utils.o
 
 MODULEPFX := brcmutil
 
diff --git a/drivers/net/wireless/brcm80211/brcmutil/wifi.c b/drivers/net/wireless/brcm80211/brcmutil/wifi.c
deleted file mode 100644
index 8483f24..0000000
--- a/drivers/net/wireless/brcm80211/brcmutil/wifi.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <brcmu_wifi.h>
-- 
1.7.4.1



^ permalink raw reply related

* [PATCH 09/22] brcm80211: use endian annotations in scan related function
From: Arend van Spriel @ 2011-10-12 18:51 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1318445492-24207-1-git-send-email-arend@broadcom.com>

The scan related functions provide scan parameters to the device
which need to be in little-endian. These parameters have been
annotated and conversions were placed as needed.

Reported-by: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: Roland Vossen <rvossen@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index fc643c1..1218ed7 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -475,7 +475,7 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
 	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
 	struct net_device *ndev = cfg_to_ndev(cfg_priv);
 	struct brcmf_ssid ssid;
-	s32 passive_scan;
+	__le32 passive_scan;
 	s32 err = 0;
 
 	/* Broadcast scan by default */
@@ -483,7 +483,7 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
 
 	iscan->state = WL_ISCAN_STATE_SCANING;
 
-	passive_scan = cfg_priv->active_scan ? 0 : 1;
+	passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
 	err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
 			&passive_scan, sizeof(passive_scan));
 	if (err) {
@@ -511,7 +511,7 @@ __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
 	struct cfg80211_ssid *ssids;
 	struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
-	s32 passive_scan;
+	__le32 passive_scan;
 	bool iscan_req;
 	bool spec_scan;
 	s32 err = 0;
@@ -567,7 +567,7 @@ __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 			WL_SCAN("Broadcast scan\n");
 		}
 
-		passive_scan = cfg_priv->active_scan ? 0 : 1;
+		passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
 		err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
 				&passive_scan, sizeof(passive_scan));
 		if (err) {
-- 
1.7.4.1



^ permalink raw reply related

* [PATCH 03/22] brcm80211: cleanup function prototypes
From: Arend van Spriel @ 2011-10-12 18:51 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Alwin Beukers, Arend van Spriel
In-Reply-To: <1318445492-24207-1-git-send-email-arend@broadcom.com>

From: Alwin Beukers <alwin@broadcom.com>

- removed unneeded fn prototypes from include files.
- explicitly marked fn prototypes as extern in include files.
- reordered functions to account for removed forward declarations
  in include files.
- removed unused functions: brcms_c_txflowcontrol_override,
  brcms_c_txflowcontrol_prio_isset, brcms_c_txflowcontrol.

Reviewed-by: Roland Vossen <rvossen@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmsmac/main.c | 3425 ++++++++++++------------
 drivers/net/wireless/brcm80211/brcmsmac/main.h |   84 -
 drivers/net/wireless/brcm80211/brcmsmac/pub.h  |   49 +-
 3 files changed, 1663 insertions(+), 1895 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 665bf80..cce6228 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -343,53 +343,6 @@ struct d11init {
 	__le32 value;
 };
 
-/* currently the best mechanism for determining SIFS is the band in use */
-static u16 get_sifs(struct brcms_band *band)
-{
-	return band->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME :
-				 BPHY_SIFS_TIME;
-}
-
-
-/*
- * Detect Card removed.
- * Even checking an sbconfig register read will not false trigger when the core
- * is in reset it breaks CF address mechanism. Accessing gphy phyversion will
- * cause SB error if aphy is in reset on 4306B0-DB. Need a simple accessible
- * reg with fixed 0/1 pattern (some platforms return all 0).
- * If clocks are present, call the sb routine which will figure out if the
- * device is removed.
- */
-static bool brcms_deviceremoved(struct brcms_c_info *wlc)
-{
-	if (!wlc->hw->clk)
-		return ai_deviceremoved(wlc->hw->sih);
-	return (R_REG(&wlc->hw->regs->maccontrol) &
-		(MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN;
-}
-
-/* sum the individual fifo tx pending packet counts */
-static s16 brcms_txpktpendtot(struct brcms_c_info *wlc)
-{
-	return wlc->core->txpktpend[0] + wlc->core->txpktpend[1] +
-	       wlc->core->txpktpend[2] + wlc->core->txpktpend[3];
-}
-
-static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc)
-{
-	return wlc->pub->_nbands > 1 && !wlc->bandlocked;
-}
-
-static int brcms_chspec_bw(u16 chanspec)
-{
-	if (CHSPEC_IS40(chanspec))
-		return BRCMS_40_MHZ;
-	if (CHSPEC_IS20(chanspec))
-		return BRCMS_20_MHZ;
-
-	return BRCMS_10_MHZ;
-}
-
 struct edcf_acparam {
 	u8 ACI;
 	u8 ECW;
@@ -465,6 +418,66 @@ static const char fifo_names[6][0];
 static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
 #endif
 
+/* currently the best mechanism for determining SIFS is the band in use */
+static u16 get_sifs(struct brcms_band *band)
+{
+	return band->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME :
+				 BPHY_SIFS_TIME;
+}
+
+/*
+ * Detect Card removed.
+ * Even checking an sbconfig register read will not false trigger when the core
+ * is in reset it breaks CF address mechanism. Accessing gphy phyversion will
+ * cause SB error if aphy is in reset on 4306B0-DB. Need a simple accessible
+ * reg with fixed 0/1 pattern (some platforms return all 0).
+ * If clocks are present, call the sb routine which will figure out if the
+ * device is removed.
+ */
+static bool brcms_deviceremoved(struct brcms_c_info *wlc)
+{
+	if (!wlc->hw->clk)
+		return ai_deviceremoved(wlc->hw->sih);
+	return (R_REG(&wlc->hw->regs->maccontrol) &
+		(MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN;
+}
+
+/* sum the individual fifo tx pending packet counts */
+static s16 brcms_txpktpendtot(struct brcms_c_info *wlc)
+{
+	return wlc->core->txpktpend[0] + wlc->core->txpktpend[1] +
+	       wlc->core->txpktpend[2] + wlc->core->txpktpend[3];
+}
+
+static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc)
+{
+	return wlc->pub->_nbands > 1 && !wlc->bandlocked;
+}
+
+static int brcms_chspec_bw(u16 chanspec)
+{
+	if (CHSPEC_IS40(chanspec))
+		return BRCMS_40_MHZ;
+	if (CHSPEC_IS20(chanspec))
+		return BRCMS_20_MHZ;
+
+	return BRCMS_10_MHZ;
+}
+
+/*
+ * return true if Minimum Power Consumption should
+ * be entered, false otherwise
+ */
+static bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc)
+{
+	return false;
+}
+
+static bool brcms_c_ismpc(struct brcms_c_info *wlc)
+{
+	return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc));
+}
+
 static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg)
 {
 	if (cfg == NULL)
@@ -646,6 +659,79 @@ static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
 	}
 }
 
+/*
+ * calculate frame duration of a given rate and length, return
+ * time in usec unit
+ */
+uint
+brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
+			u8 preamble_type, uint mac_len)
+{
+	uint nsyms, dur = 0, Ndps, kNdps;
+	uint rate = rspec2rate(ratespec);
+
+	if (rate == 0) {
+		wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n",
+			  wlc->pub->unit);
+		rate = BRCM_RATE_1M;
+	}
+
+	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n",
+		 wlc->pub->unit, ratespec, preamble_type, mac_len);
+
+	if (is_mcs_rate(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec);
+
+		dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+		if (preamble_type == BRCMS_MM_PREAMBLE)
+			dur += PREN_MM_EXT;
+		/* 1000Ndbps = kbps * 4 */
+		kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+				   rspec_issgi(ratespec)) * 4;
+
+		if (rspec_stc(ratespec) == 0)
+			nsyms =
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, kNdps);
+		else
+			/* STBC needs to have even number of symbols */
+			nsyms =
+			    2 *
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+
+		dur += APHY_SYMBOL_TIME * nsyms;
+		if (wlc->band->bandtype == BRCM_BAND_2G)
+			dur += DOT11_OFDM_SIGNAL_EXTENSION;
+	} else if (is_ofdm_rate(rate)) {
+		dur = APHY_PREAMBLE_TIME;
+		dur += APHY_SIGNAL_TIME;
+		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+		Ndps = rate * 2;
+		/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+		nsyms =
+		    CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
+			 Ndps);
+		dur += APHY_SYMBOL_TIME * nsyms;
+		if (wlc->band->bandtype == BRCM_BAND_2G)
+			dur += DOT11_OFDM_SIGNAL_EXTENSION;
+	} else {
+		/*
+		 * calc # bits * 2 so factor of 2 in rate (1/2 mbps)
+		 * will divide out
+		 */
+		mac_len = mac_len * 8 * 2;
+		/* calc ceiling of bits/rate = microseconds of air time */
+		dur = (mac_len + rate - 1) / rate;
+		if (preamble_type & BRCMS_SHORT_PREAMBLE)
+			dur += BPHY_PLCP_SHORT_TIME;
+		else
+			dur += BPHY_PLCP_TIME;
+	}
+	return dur;
+}
+
 static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
 				const struct d11init *inits)
 {
@@ -740,6 +826,26 @@ static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
 	}
 }
 
+/* low-level band switch utility routine */
+static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit)
+{
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+		bandunit);
+
+	wlc_hw->band = wlc_hw->bandstate[bandunit];
+
+	/*
+	 * BMAC_NOTE:
+	 *   until we eliminate need for wlc->band refs in low level code
+	 */
+	wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
+
+	/* set gmode core flag */
+	if (wlc_hw->sbclk && !wlc_hw->noreset)
+		ai_core_cflags(wlc_hw->sih, SICF_GMODE,
+			       ((bandunit == 0) ? SICF_GMODE : 0));
+}
+
 /* switch to new band but leave it inactive */
 static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
 {
@@ -763,107 +869,45 @@ static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
 	return macintmask;
 }
 
-/* Process received frames */
-/*
- * Return true if more frames need to be processed. false otherwise.
- * Param 'bound' indicates max. # frames to process before break out.
- */
+/* process an individual struct tx_status */
 static bool
-brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
+brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
 {
 	struct sk_buff *p;
-	struct sk_buff *head = NULL;
-	struct sk_buff *tail = NULL;
-	uint n = 0;
-	uint bound_limit = bound ? RXBND : -1;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-	/* gather received frames */
-	while ((p = dma_rx(wlc_hw->di[fifo]))) {
+	uint queue;
+	struct d11txh *txh;
+	struct scb *scb = NULL;
+	bool free_pdu;
+	int tx_rts, tx_frame_count, tx_rts_count;
+	uint totlen, supr_status;
+	bool lastframe;
+	struct ieee80211_hdr *h;
+	u16 mcl;
+	struct ieee80211_tx_info *tx_info;
+	struct ieee80211_tx_rate *txrate;
+	int i;
 
-		if (!tail)
-			head = tail = p;
-		else {
-			tail->prev = p;
-			tail = p;
-		}
+	/* discard intermediate indications for ucode with one legitimate case:
+	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange,
+	 *   but the subsequent tx of DATA failed. so it will start rts/cts
+	 *   from the beginning (resetting the rts transmission count)
+	 */
+	if (!(txs->status & TX_STATUS_AMPDU)
+	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
+		wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
+			  __func__);
+		return false;
+	}
 
-		/* !give others some time to run! */
-		if (++n >= bound_limit)
-			break;
+	queue = txs->frameid & TXFID_QUEUE_MASK;
+	if (queue >= NFIFO) {
+		p = NULL;
+		goto fatal;
 	}
 
-	/* post more rbufs */
-	dma_rxfill(wlc_hw->di[fifo]);
-
-	/* process each frame */
-	while ((p = head) != NULL) {
-		struct d11rxhdr_le *rxh_le;
-		struct d11rxhdr *rxh;
-		head = head->prev;
-		p->prev = NULL;
-
-		rxh_le = (struct d11rxhdr_le *)p->data;
-		rxh = (struct d11rxhdr *)p->data;
-
-		/* fixup rx header endianness */
-		rxh->RxFrameSize = le16_to_cpu(rxh_le->RxFrameSize);
-		rxh->PhyRxStatus_0 = le16_to_cpu(rxh_le->PhyRxStatus_0);
-		rxh->PhyRxStatus_1 = le16_to_cpu(rxh_le->PhyRxStatus_1);
-		rxh->PhyRxStatus_2 = le16_to_cpu(rxh_le->PhyRxStatus_2);
-		rxh->PhyRxStatus_3 = le16_to_cpu(rxh_le->PhyRxStatus_3);
-		rxh->PhyRxStatus_4 = le16_to_cpu(rxh_le->PhyRxStatus_4);
-		rxh->PhyRxStatus_5 = le16_to_cpu(rxh_le->PhyRxStatus_5);
-		rxh->RxStatus1 = le16_to_cpu(rxh_le->RxStatus1);
-		rxh->RxStatus2 = le16_to_cpu(rxh_le->RxStatus2);
-		rxh->RxTSFTime = le16_to_cpu(rxh_le->RxTSFTime);
-		rxh->RxChan = le16_to_cpu(rxh_le->RxChan);
-
-		brcms_c_recv(wlc_hw->wlc, p);
-	}
-
-	return n >= bound_limit;
-}
-
-/* process an individual struct tx_status */
-static bool
-brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
-{
-	struct sk_buff *p;
-	uint queue;
-	struct d11txh *txh;
-	struct scb *scb = NULL;
-	bool free_pdu;
-	int tx_rts, tx_frame_count, tx_rts_count;
-	uint totlen, supr_status;
-	bool lastframe;
-	struct ieee80211_hdr *h;
-	u16 mcl;
-	struct ieee80211_tx_info *tx_info;
-	struct ieee80211_tx_rate *txrate;
-	int i;
-
-	/* discard intermediate indications for ucode with one legitimate case:
-	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange,
-	 *   but the subsequent tx of DATA failed. so it will start rts/cts
-	 *   from the beginning (resetting the rts transmission count)
-	 */
-	if (!(txs->status & TX_STATUS_AMPDU)
-	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
-		wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
-			  __func__);
-		return false;
-	}
-
-	queue = txs->frameid & TXFID_QUEUE_MASK;
-	if (queue >= NFIFO) {
-		p = NULL;
-		goto fatal;
-	}
-
-	p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
-	if (p == NULL)
-		goto fatal;
+	p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
+	if (p == NULL)
+		goto fatal;
 
 	txh = (struct d11txh *) (p->data);
 	mcl = le16_to_cpu(txh->MacTxControlLow);
@@ -1054,97 +1098,14 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
 	return morepending;
 }
 
-/* second-level interrupt processing
- *   Return true if another dpc needs to be re-scheduled. false otherwise.
- *   Param 'bounded' indicates if applicable loops should be bounded.
- */
-bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
+static void brcms_c_tbtt(struct brcms_c_info *wlc)
 {
-	u32 macintstatus;
-	struct brcms_hardware *wlc_hw = wlc->hw;
-	struct d11regs __iomem *regs = wlc_hw->regs;
-	struct wiphy *wiphy = wlc->wiphy;
-
-	if (brcms_deviceremoved(wlc)) {
-		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
-			  __func__);
-		brcms_down(wlc->wl);
-		return false;
-	}
-
-	/* grab and clear the saved software intstatus bits */
-	macintstatus = wlc->macintstatus;
-	wlc->macintstatus = 0;
-
-	BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
-	       wlc_hw->unit, macintstatus);
-
-	WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
-
-	/* tx status */
-	if (macintstatus & MI_TFS) {
-		bool fatal;
-		if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
-			wlc->macintstatus |= MI_TFS;
-		if (fatal) {
-			wiphy_err(wiphy, "MI_TFS: fatal\n");
-			goto fatal;
-		}
-	}
-
-	if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
-		brcms_c_tbtt(wlc);
-
-	/* ATIM window end */
-	if (macintstatus & MI_ATIMWINEND) {
-		BCMMSG(wlc->wiphy, "end of ATIM window\n");
-		OR_REG(&regs->maccommand, wlc->qvalid);
-		wlc->qvalid = 0;
-	}
-
-	/*
-	 * received data or control frame, MI_DMAINT is
-	 * indication of RX_FIFO interrupt
-	 */
-	if (macintstatus & MI_DMAINT)
-		if (brcms_b_recv(wlc_hw, RX_FIFO, bounded))
-			wlc->macintstatus |= MI_DMAINT;
-
-	/* noise sample collected */
-	if (macintstatus & MI_BG_NOISE)
-		wlc_phy_noise_sample_intr(wlc_hw->band->pi);
-
-	if (macintstatus & MI_GP0) {
-		wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
-			"(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
-
-		printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
-					__func__, wlc_hw->sih->chip,
-					wlc_hw->sih->chiprev);
-		/* big hammer */
-		brcms_init(wlc->wl);
-	}
-
-	/* gptimer timeout */
-	if (macintstatus & MI_TO)
-		W_REG(&regs->gptimer, 0);
-
-	if (macintstatus & MI_RFDISABLE) {
-		BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
-		       " RF Disable Input\n", wlc_hw->unit);
-		brcms_rfkill_set_hw_state(wlc->wl);
-	}
-
-	/* send any enq'd tx packets. Just makes sure to jump start tx */
-	if (!pktq_empty(&wlc->pkt_queue->q))
-		brcms_c_send_q(wlc);
-
-	/* it isn't done and needs to be resched if macintstatus is non-zero */
-	return wlc->macintstatus != 0;
-
- fatal:
-	brcms_init(wlc->wl);
-	return wlc->macintstatus != 0;
+	if (!wlc->bsscfg->BSS)
+		/*
+		 * DirFrmQ is now valid...defer setting until end
+		 * of ATIM window
+		 */
+		wlc->qvalid |= MCMD_DIRFRMQVAL;
 }
 
 /* set initial host flags value */
@@ -1922,26 +1883,6 @@ static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
 	WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
 }
 
-/* low-level band switch utility routine */
-void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit)
-{
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
-		bandunit);
-
-	wlc_hw->band = wlc_hw->bandstate[bandunit];
-
-	/*
-	 * BMAC_NOTE:
-	 *   until we eliminate need for wlc->band refs in low level code
-	 */
-	wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
-
-	/* set gmode core flag */
-	if (wlc_hw->sbclk && !wlc_hw->noreset)
-		ai_core_cflags(wlc_hw->sih, SICF_GMODE,
-			       ((bandunit == 0) ? SICF_GMODE : 0));
-}
-
 static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw)
 {
 
@@ -2405,6 +2346,13 @@ void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type)
 	wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
 }
 
+static void brcms_c_fatal_error(struct brcms_c_info *wlc)
+{
+	wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n",
+		  wlc->pub->unit);
+	brcms_init(wlc->wl);
+}
+
 static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
 {
 	bool fatal = false;
@@ -2962,7 +2910,7 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
 	}
 }
 
-void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
+static void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
 {
 	bool dev_gone;
 
@@ -3106,6 +3054,16 @@ brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf,
 	}
 }
 
+/* Copy a buffer to shared memory.
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ */
+static void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset,
+			const void *buf, int len)
+{
+	brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
+}
+
 static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw,
 				   u16 SRL, u16 LRL)
 {
@@ -3159,7 +3117,7 @@ static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
  * conditions under which the PM bit should be set in outgoing frames
  * and STAY_AWAKE is meaningful
  */
-bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
+static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
 {
 	struct brcms_bss_cfg *cfg = wlc->bsscfg;
 
@@ -3185,6 +3143,58 @@ bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
 	return true;
 }
 
+static void brcms_c_statsupd(struct brcms_c_info *wlc)
+{
+	int i;
+	struct macstat macstats;
+#ifdef BCMDBG
+	u16 delta;
+	u16 rxf0ovfl;
+	u16 txfunfl[NFIFO];
+#endif				/* BCMDBG */
+
+	/* if driver down, make no sense to update stats */
+	if (!wlc->pub->up)
+		return;
+
+#ifdef BCMDBG
+	/* save last rx fifo 0 overflow count */
+	rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
+
+	/* save last tx fifo  underflow count */
+	for (i = 0; i < NFIFO; i++)
+		txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
+#endif				/* BCMDBG */
+
+	/* Read mac stats from contiguous shared memory */
+	brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats,
+				sizeof(struct macstat), OBJADDR_SHM_SEL);
+
+#ifdef BCMDBG
+	/* check for rx fifo 0 overflow */
+	delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
+	if (delta)
+		wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n",
+			  wlc->pub->unit, delta);
+
+	/* check for tx fifo underflows */
+	for (i = 0; i < NFIFO; i++) {
+		delta =
+		    (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
+			      txfunfl[i]);
+		if (delta)
+			wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!"
+				  "\n", wlc->pub->unit, delta, i);
+	}
+#endif				/* BCMDBG */
+
+	/* merge counters from dma module */
+	for (i = 0; i < NFIFO; i++) {
+		if (wlc->hw->di[i])
+			dma_counterreset(wlc->hw->di[i]);
+	}
+}
+
 static void brcms_b_reset(struct brcms_hardware *wlc_hw)
 {
 	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
@@ -3211,13 +3221,6 @@ void brcms_c_reset(struct brcms_c_info *wlc)
 	brcms_b_reset(wlc->hw);
 }
 
-void brcms_c_fatal_error(struct brcms_c_info *wlc)
-{
-	wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n",
-		  wlc->pub->unit);
-	brcms_init(wlc->wl);
-}
-
 /* Return the channel the driver should initialize during brcms_c_init.
  * the channel may have to be changed from the currently configured channel
  * if other configurations are in conflict (bandlocked, 11n mode disabled,
@@ -3494,11 +3497,115 @@ static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc,
 					    chanspec);
 
 	brcms_c_stf_ss_update(wlc, wlc->band);
-
 }
 
-static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
-				     u16 chanspec)
+static void
+brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs)
+{
+	brcms_c_rateset_default(rs, NULL, wlc->band->phytype,
+		wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL,
+		(bool) (wlc->pub->_n_enab & SUPPORT_11N),
+		brcms_chspec_bw(wlc->default_bss->chanspec),
+		wlc->stf->txstreams);
+}
+
+/* derive wlc->band->basic_rate[] table from 'rateset' */
+static void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
+			      struct brcms_c_rateset *rateset)
+{
+	u8 rate;
+	u8 mandatory;
+	u8 cck_basic = 0;
+	u8 ofdm_basic = 0;
+	u8 *br = wlc->band->basic_rate;
+	uint i;
+
+	/* incoming rates are in 500kbps units as in 802.11 Supported Rates */
+	memset(br, 0, BRCM_MAXRATE + 1);
+
+	/* For each basic rate in the rates list, make an entry in the
+	 * best basic lookup.
+	 */
+	for (i = 0; i < rateset->count; i++) {
+		/* only make an entry for a basic rate */
+		if (!(rateset->rates[i] & BRCMS_RATE_FLAG))
+			continue;
+
+		/* mask off basic bit */
+		rate = (rateset->rates[i] & BRCMS_RATE_MASK);
+
+		if (rate > BRCM_MAXRATE) {
+			wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: "
+				  "invalid rate 0x%X in rate set\n",
+				  rateset->rates[i]);
+			continue;
+		}
+
+		br[rate] = rate;
+	}
+
+	/* The rate lookup table now has non-zero entries for each
+	 * basic rate, equal to the basic rate: br[basicN] = basicN
+	 *
+	 * To look up the best basic rate corresponding to any
+	 * particular rate, code can use the basic_rate table
+	 * like this
+	 *
+	 * basic_rate = wlc->band->basic_rate[tx_rate]
+	 *
+	 * Make sure there is a best basic rate entry for
+	 * every rate by walking up the table from low rates
+	 * to high, filling in holes in the lookup table
+	 */
+
+	for (i = 0; i < wlc->band->hw_rateset.count; i++) {
+		rate = wlc->band->hw_rateset.rates[i];
+
+		if (br[rate] != 0) {
+			/* This rate is a basic rate.
+			 * Keep track of the best basic rate so far by
+			 * modulation type.
+			 */
+			if (is_ofdm_rate(rate))
+				ofdm_basic = rate;
+			else
+				cck_basic = rate;
+
+			continue;
+		}
+
+		/* This rate is not a basic rate so figure out the
+		 * best basic rate less than this rate and fill in
+		 * the hole in the table
+		 */
+
+		br[rate] = is_ofdm_rate(rate) ? ofdm_basic : cck_basic;
+
+		if (br[rate] != 0)
+			continue;
+
+		if (is_ofdm_rate(rate)) {
+			/*
+			 * In 11g and 11a, the OFDM mandatory rates
+			 * are 6, 12, and 24 Mbps
+			 */
+			if (rate >= BRCM_RATE_24M)
+				mandatory = BRCM_RATE_24M;
+			else if (rate >= BRCM_RATE_12M)
+				mandatory = BRCM_RATE_12M;
+			else
+				mandatory = BRCM_RATE_6M;
+		} else {
+			/* In 11b, all CCK rates are mandatory 1 - 11 Mbps */
+			mandatory = rate;
+		}
+
+		br[rate] = mandatory;
+	}
+}
+
+static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
+				     u16 chanspec)
 {
 	struct brcms_c_rateset default_rateset;
 	uint parkband;
@@ -3543,6 +3650,44 @@ static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
 	brcms_c_set_phy_chanspec(wlc, chanspec);
 }
 
+static void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc)
+{
+	if (wlc->bcnmisc_monitor)
+		brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
+	else
+		brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, 0);
+}
+
+void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc)
+{
+	wlc->bcnmisc_monitor = promisc;
+	brcms_c_mac_bcn_promisc(wlc);
+}
+
+/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */
+static void brcms_c_mac_promisc(struct brcms_c_info *wlc)
+{
+	u32 promisc_bits = 0;
+
+	/*
+	 * promiscuous mode just sets MCTL_PROMISC
+	 * Note: APs get all BSS traffic without the need to set
+	 * the MCTL_PROMISC bit since all BSS data traffic is
+	 * directed at the AP
+	 */
+	if (wlc->pub->promisc)
+		promisc_bits |= MCTL_PROMISC;
+
+	/* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL
+	 * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is
+	 * handled in brcms_c_mac_bcn_promisc()
+	 */
+	if (wlc->monitor)
+		promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL;
+
+	brcms_b_mctrl(wlc->hw, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
+}
+
 /*
  * ucode, hwmac update
  *    Channel dependent updates for ucode and hw
@@ -3576,6 +3721,88 @@ static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc)
 	brcms_c_mac_promisc(wlc);
 }
 
+static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate,
+				   u8 basic_rate)
+{
+	u8 phy_rate, index;
+	u8 basic_phy_rate, basic_index;
+	u16 dir_table, basic_table;
+	u16 basic_ptr;
+
+	/* Shared memory address for the table we are reading */
+	dir_table = is_ofdm_rate(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
+
+	/* Shared memory address for the table we are writing */
+	basic_table = is_ofdm_rate(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
+
+	/*
+	 * for a given rate, the LS-nibble of the PLCP SIGNAL field is
+	 * the index into the rate table.
+	 */
+	phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
+	basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK;
+	index = phy_rate & 0xf;
+	basic_index = basic_phy_rate & 0xf;
+
+	/* Find the SHM pointer to the ACK rate entry by looking in the
+	 * Direct-map Table
+	 */
+	basic_ptr = brcms_b_read_shm(wlc->hw, (dir_table + basic_index * 2));
+
+	/* Update the SHM BSS-basic-rate-set mapping table with the pointer
+	 * to the correct basic rate for the given incoming rate
+	 */
+	brcms_b_write_shm(wlc->hw, (basic_table + index * 2), basic_ptr);
+}
+
+static const struct brcms_c_rateset *
+brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc)
+{
+	const struct brcms_c_rateset *rs_dflt;
+
+	if (BRCMS_PHY_11N_CAP(wlc->band)) {
+		if (wlc->band->bandtype == BRCM_BAND_5G)
+			rs_dflt = &ofdm_mimo_rates;
+		else
+			rs_dflt = &cck_ofdm_mimo_rates;
+	} else if (wlc->band->gmode)
+		rs_dflt = &cck_ofdm_rates;
+	else
+		rs_dflt = &cck_rates;
+
+	return rs_dflt;
+}
+
+static void brcms_c_set_ratetable(struct brcms_c_info *wlc)
+{
+	const struct brcms_c_rateset *rs_dflt;
+	struct brcms_c_rateset rs;
+	u8 rate, basic_rate;
+	uint i;
+
+	rs_dflt = brcms_c_rateset_get_hwrs(wlc);
+
+	brcms_c_rateset_copy(rs_dflt, &rs);
+	brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+
+	/* walk the phy rate table and update SHM basic rate lookup table */
+	for (i = 0; i < rs.count; i++) {
+		rate = rs.rates[i] & BRCMS_RATE_MASK;
+
+		/* for a given rate brcms_basic_rate returns the rate at
+		 * which a response ACK/CTS should be sent.
+		 */
+		basic_rate = brcms_basic_rate(wlc, rate);
+		if (basic_rate == 0)
+			/* This should only happen if we are using a
+			 * restricted rateset.
+			 */
+			basic_rate = rs.rates[0] & BRCMS_RATE_MASK;
+
+		brcms_c_write_rate_shm(wlc, rate, basic_rate);
+	}
+}
+
 /* band-specific init */
 static void brcms_c_bsinit(struct brcms_c_info *wlc)
 {
@@ -3655,183 +3882,35 @@ static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc)
 	}
 }
 
-void brcms_c_init(struct brcms_c_info *wlc)
+/* push sw hps and wake state through hardware */
+static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
 {
-	struct d11regs __iomem *regs;
-	u16 chanspec;
-	bool mute = false;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+	u32 v1, v2;
+	bool hps;
+	bool awake_before;
 
-	regs = wlc->regs;
+	hps = brcms_c_ps_allowed(wlc);
 
-	/*
-	 * This will happen if a big-hammer was executed. In
-	 * that case, we want to go back to the channel that
-	 * we were on and not new channel
-	 */
-	if (wlc->pub->associated)
-		chanspec = wlc->home_chanspec;
-	else
-		chanspec = brcms_c_init_chanspec(wlc);
+	BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
 
-	brcms_b_init(wlc->hw, chanspec, mute);
+	v1 = R_REG(&wlc->regs->maccontrol);
+	v2 = MCTL_WAKE;
+	if (hps)
+		v2 |= MCTL_HPS;
 
-	/* update beacon listen interval */
-	brcms_c_bcn_li_upd(wlc);
+	brcms_b_mctrl(wlc->hw, MCTL_WAKE | MCTL_HPS, v2);
 
-	/* write ethernet address to core */
-	brcms_c_set_mac(wlc->bsscfg);
-	brcms_c_set_bssid(wlc->bsscfg);
-
-	/* Update tsf_cfprep if associated and up */
-	if (wlc->pub->associated && wlc->bsscfg->up) {
-		u32 bi;
-
-		/* get beacon period and convert to uS */
-		bi = wlc->bsscfg->current_bss->beacon_period << 10;
-		/*
-		 * update since init path would reset
-		 * to default value
-		 */
-		W_REG(&regs->tsf_cfprep,
-		      (bi << CFPREP_CBI_SHIFT));
-
-		/* Update maccontrol PM related bits */
-		brcms_c_set_ps_ctrl(wlc);
-	}
-
-	brcms_c_bandinit_ordered(wlc, chanspec);
-
-	/* init probe response timeout */
-	brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout);
-
-	/* init max burst txop (framebursting) */
-	brcms_b_write_shm(wlc->hw, M_MBURST_TXOP,
-		      (wlc->
-		       _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
-
-	/* initialize maximum allowed duty cycle */
-	brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
-	brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
-
-	/*
-	 * Update some shared memory locations related to
-	 * max AMPDU size allowed to received
-	 */
-	brcms_c_ampdu_shm_upd(wlc->ampdu);
-
-	/* band-specific inits */
-	brcms_c_bsinit(wlc);
-
-	/* Enable EDCF mode (while the MAC is suspended) */
-	OR_REG(&regs->ifs_ctl, IFS_USEEDCF);
-	brcms_c_edcf_setparams(wlc, false);
-
-	/* Init precedence maps for empty FIFOs */
-	brcms_c_tx_prec_map_init(wlc);
-
-	/* read the ucode version if we have not yet done so */
-	if (wlc->ucode_rev == 0) {
-		wlc->ucode_rev =
-		    brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16);
-		wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR);
-	}
-
-	/* ..now really unleash hell (allow the MAC out of suspend) */
-	brcms_c_enable_mac(wlc);
-
-	/* clear tx flow control */
-	brcms_c_txflowcontrol_reset(wlc);
-
-	/* enable the RF Disable Delay timer */
-	W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
-
-	/* initialize mpc delay */
-	wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
-
-	/*
-	 * Initialize WME parameters; if they haven't been set by some other
-	 * mechanism (IOVar, etc) then read them from the hardware.
-	 */
-	if (GFIELD(wlc->wme_retries[0], EDCF_SHORT) == 0) {
-		/* Uninitialized; read from HW */
-		int ac;
-
-		for (ac = 0; ac < AC_COUNT; ac++)
-			wlc->wme_retries[ac] =
-			    brcms_b_read_shm(wlc->hw, M_AC_TXLMT_ADDR(ac));
-	}
-}
-
-void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc)
-{
-	wlc->bcnmisc_monitor = promisc;
-	brcms_c_mac_bcn_promisc(wlc);
-}
-
-void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc)
-{
-	if (wlc->bcnmisc_monitor)
-		brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
-	else
-		brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, 0);
-}
-
-/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */
-void brcms_c_mac_promisc(struct brcms_c_info *wlc)
-{
-	u32 promisc_bits = 0;
-
-	/*
-	 * promiscuous mode just sets MCTL_PROMISC
-	 * Note: APs get all BSS traffic without the need to set
-	 * the MCTL_PROMISC bit since all BSS data traffic is
-	 * directed at the AP
-	 */
-	if (wlc->pub->promisc)
-		promisc_bits |= MCTL_PROMISC;
-
-	/* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL
-	 * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is
-	 * handled in brcms_c_mac_bcn_promisc()
-	 */
-	if (wlc->monitor)
-		promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL;
-
-	brcms_b_mctrl(wlc->hw, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
-}
-
-/* push sw hps and wake state through hardware */
-void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
-{
-	u32 v1, v2;
-	bool hps;
-	bool awake_before;
-
-	hps = brcms_c_ps_allowed(wlc);
-
-	BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
-
-	v1 = R_REG(&wlc->regs->maccontrol);
-	v2 = MCTL_WAKE;
-	if (hps)
-		v2 |= MCTL_HPS;
-
-	brcms_b_mctrl(wlc->hw, MCTL_WAKE | MCTL_HPS, v2);
-
-	awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
+	awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
 
 	if (!awake_before)
 		brcms_b_wait_for_wake(wlc->hw);
-
 }
 
 /*
  * Write this BSS config's MAC address to core.
  * Updates RXE match engine.
  */
-int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg)
+static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg)
 {
 	int err = 0;
 	struct brcms_c_info *wlc = bsscfg->wlc;
@@ -3847,7 +3926,7 @@ int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg)
 /* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl).
  * Updates RXE match engine.
  */
-void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg)
+static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg)
 {
 	/* we need to update BSSID in RXE match registers */
 	brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID);
@@ -3868,7 +3947,7 @@ static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
  * Suspend the the MAC and update the slot timing
  * for standard 11b/g (20us slots) or shortslot 11g (9us slots).
  */
-void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
+static void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
 {
 	/* use the override if it is set */
 	if (wlc->shortslot_override != BRCMS_SHORTSLOT_AUTO)
@@ -3882,7 +3961,7 @@ void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
 	brcms_b_set_shortslot(wlc->hw, shortslot);
 }
 
-void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
+static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
 {
 	if (wlc->home_chanspec != chanspec) {
 		wlc->home_chanspec = chanspec;
@@ -3952,7 +4031,7 @@ static void brcms_c_setband(struct brcms_c_info *wlc,
 	brcms_c_bsinit(wlc);
 }
 
-void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
+static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
 {
 	uint bandunit;
 	bool switchband = false;
@@ -4006,31 +4085,6 @@ void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
 	brcms_c_ucode_mac_upd(wlc);
 }
 
-u32 brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc,
-				      struct brcms_c_rateset *rs)
-{
-	u32 lowest_basic_rspec;
-	uint i;
-
-	/* Use the lowest basic rate */
-	lowest_basic_rspec = rs->rates[0] & BRCMS_RATE_MASK;
-	for (i = 0; i < rs->count; i++) {
-		if (rs->rates[i] & BRCMS_RATE_FLAG) {
-			lowest_basic_rspec = rs->rates[i] & BRCMS_RATE_MASK;
-			break;
-		}
-	}
-
-	/*
-	 * pick siso/cdd as default for OFDM (note no basic
-	 * rate MCSs are supported yet)
-	 */
-	if (is_ofdm_rate(lowest_basic_rspec))
-		lowest_basic_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
-
-	return lowest_basic_rspec;
-}
-
 /*
  * This function changes the phytxctl for beacon based on current
  * beacon ratespec AND txant setting as per this table:
@@ -4239,7 +4293,7 @@ static void brcms_c_radio_monitor_start(struct brcms_c_info *wlc)
 	brcms_add_timer(wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true);
 }
 
-void brcms_c_radio_disable(struct brcms_c_info *wlc)
+static void brcms_c_radio_disable(struct brcms_c_info *wlc)
 {
 	if (!wlc->pub->up) {
 		brcms_c_down_led_upd(wlc);
@@ -4261,7 +4315,7 @@ static void brcms_c_radio_enable(struct brcms_c_info *wlc)
 	brcms_up(wlc->wl);
 }
 
-bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc)
+static bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc)
 {
 	if (!wlc->radio_monitor)
 		return true;
@@ -4347,6 +4401,60 @@ static void brcms_b_watchdog(void *arg)
 	wlc_phy_watchdog(wlc_hw->band->pi);
 }
 
+static void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc)
+{
+	bool mpc_radio, radio_state;
+
+	/*
+	 * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
+	 * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
+	 * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
+	 * the radio is going down.
+	 */
+	if (!wlc->mpc) {
+		if (!wlc->pub->radio_disabled)
+			return;
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
+		brcms_c_radio_upd(wlc);
+		if (!wlc->pub->radio_disabled)
+			brcms_c_radio_monitor_stop(wlc);
+		return;
+	}
+
+	/*
+	 * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in
+	 * wlc->pub->radio_disabled to go ON, always call radio_upd
+	 * synchronously to go OFF, postpone radio_upd to later when
+	 * context is safe(e.g. watchdog)
+	 */
+	radio_state =
+	    (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
+	     ON);
+	mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON;
+
+	if (radio_state == ON && mpc_radio == OFF)
+		wlc->mpc_delay_off = wlc->mpc_dlycnt;
+	else if (radio_state == OFF && mpc_radio == ON) {
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
+		brcms_c_radio_upd(wlc);
+		if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD)
+			wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT;
+		else
+			wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
+	}
+	/*
+	 * Below logic is meant to capture the transition from mpc off
+	 * to mpc on for reasons other than wlc->mpc_delay_off keeping
+	 * the mpc off. In that case reset wlc->mpc_delay_off to
+	 * wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
+	 */
+	if ((wlc->prev_non_delay_mpc == false) &&
+	    (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off)
+		wlc->mpc_delay_off = wlc->mpc_dlycnt;
+
+	wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc);
+}
+
 /* common watchdog code */
 static void brcms_c_watchdog(void *arg)
 {
@@ -4408,7 +4516,7 @@ static void brcms_c_watchdog_by_timer(void *arg)
 	brcms_c_watchdog(arg);
 }
 
-bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
+static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
 {
 	wlc->wdtimer = brcms_init_timer(wlc->wl, brcms_c_watchdog_by_timer,
 		wlc, "watchdog");
@@ -4436,7 +4544,7 @@ bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
  * Initialize brcms_c_info default values ...
  * may get overrides later in this function
  */
-void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
+static void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
 {
 	int i;
 
@@ -5025,224 +5133,33 @@ static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap)
 	}
 }
 
-/*
- * The common driver entry routine. Error codes should be unique
- */
-struct brcms_c_info *
-brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
-	       bool piomode, void __iomem *regsva, struct pci_dev *btparam,
-	       uint *perr)
+static void brcms_c_timers_deinit(struct brcms_c_info *wlc)
 {
-	struct brcms_c_info *wlc;
-	uint err = 0;
-	uint i, j;
-	struct brcms_pub *pub;
-
-	/* allocate struct brcms_c_info state and its substructures */
-	wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device);
-	if (wlc == NULL)
-		goto fail;
-	wlc->wiphy = wl->wiphy;
-	pub = wlc->pub;
-
-#if defined(BCMDBG)
-	wlc_info_dbg = wlc;
-#endif
+	/* free timer state */
+	if (wlc->wdtimer) {
+		brcms_free_timer(wlc->wdtimer);
+		wlc->wdtimer = NULL;
+	}
+	if (wlc->radio_timer) {
+		brcms_free_timer(wlc->radio_timer);
+		wlc->radio_timer = NULL;
+	}
+}
 
-	wlc->band = wlc->bandstate[0];
-	wlc->core = wlc->corestate;
-	wlc->wl = wl;
-	pub->unit = unit;
-	pub->_piomode = piomode;
-	wlc->bandinit_pending = false;
+static void brcms_c_detach_module(struct brcms_c_info *wlc)
+{
+	if (wlc->asi) {
+		brcms_c_antsel_detach(wlc->asi);
+		wlc->asi = NULL;
+	}
 
-	/* populate struct brcms_c_info with default values  */
-	brcms_c_info_init(wlc, unit);
+	if (wlc->ampdu) {
+		brcms_c_ampdu_detach(wlc->ampdu);
+		wlc->ampdu = NULL;
+	}
 
-	/* update sta/ap related parameters */
-	brcms_c_ap_upd(wlc);
-
-	/*
-	 * low level attach steps(all hw accesses go
-	 * inside, no more in rest of the attach)
-	 */
-	err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva,
-			     btparam);
-	if (err)
-		goto fail;
-
-	brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, OFF);
-
-	pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band);
-
-	/* disable allowed duty cycle */
-	wlc->tx_duty_cycle_ofdm = 0;
-	wlc->tx_duty_cycle_cck = 0;
-
-	brcms_c_stf_phy_chain_calc(wlc);
-
-	/* txchain 1: txant 0, txchain 2: txant 1 */
-	if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
-		wlc->stf->txant = wlc->stf->hw_txchain - 1;
-
-	/* push to BMAC driver */
-	wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
-			       wlc->stf->hw_rxchain);
-
-	/* pull up some info resulting from the low attach */
-	for (i = 0; i < NFIFO; i++)
-		wlc->core->txavail[i] = wlc->hw->txavail[i];
-
-	memcpy(&wlc->perm_etheraddr, &wlc->hw->etheraddr, ETH_ALEN);
-	memcpy(&pub->cur_etheraddr, &wlc->hw->etheraddr, ETH_ALEN);
-
-	for (j = 0; j < wlc->pub->_nbands; j++) {
-		wlc->band = wlc->bandstate[j];
-
-		if (!brcms_c_attach_stf_ant_init(wlc)) {
-			err = 24;
-			goto fail;
-		}
-
-		/* default contention windows size limits */
-		wlc->band->CWmin = APHY_CWMIN;
-		wlc->band->CWmax = PHY_CWMAX;
-
-		/* init gmode value */
-		if (wlc->band->bandtype == BRCM_BAND_2G) {
-			wlc->band->gmode = GMODE_AUTO;
-			brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER,
-					   wlc->band->gmode);
-		}
-
-		/* init _n_enab supported mode */
-		if (BRCMS_PHY_11N_CAP(wlc->band)) {
-			pub->_n_enab = SUPPORT_11N;
-			brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
-						   ((pub->_n_enab ==
-						     SUPPORT_11N) ? WL_11N_2x2 :
-						    WL_11N_3x3));
-		}
-
-		/* init per-band default rateset, depend on band->gmode */
-		brcms_default_rateset(wlc, &wlc->band->defrateset);
-
-		/* fill in hw_rateset */
-		brcms_c_rateset_filter(&wlc->band->defrateset,
-				   &wlc->band->hw_rateset, false,
-				   BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
-				   (bool) (wlc->pub->_n_enab & SUPPORT_11N));
-	}
-
-	/*
-	 * update antenna config due to
-	 * wlc->stf->txant/txchain/ant_rx_ovr change
-	 */
-	brcms_c_stf_phy_txant_upd(wlc);
-
-	/* attach each modules */
-	err = brcms_c_attach_module(wlc);
-	if (err != 0)
-		goto fail;
-
-	if (!brcms_c_timers_init(wlc, unit)) {
-		wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit,
-			  __func__);
-		err = 32;
-		goto fail;
-	}
-
-	/* depend on rateset, gmode */
-	wlc->cmi = brcms_c_channel_mgr_attach(wlc);
-	if (!wlc->cmi) {
-		wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed"
-			  "\n", unit, __func__);
-		err = 33;
-		goto fail;
-	}
-
-	/* init default when all parameters are ready, i.e. ->rateset */
-	brcms_c_bss_default_init(wlc);
-
-	/*
-	 * Complete the wlc default state initializations..
-	 */
-
-	/* allocate our initial queue */
-	wlc->pkt_queue = brcms_c_txq_alloc(wlc);
-	if (wlc->pkt_queue == NULL) {
-		wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n",
-			  unit, __func__);
-		err = 100;
-		goto fail;
-	}
-
-	wlc->bsscfg->wlc = wlc;
-
-	wlc->mimoft = FT_HT;
-	wlc->mimo_40txbw = AUTO;
-	wlc->ofdm_40txbw = AUTO;
-	wlc->cck_40txbw = AUTO;
-	brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G);
-
-	/* Set default values of SGI */
-	if (BRCMS_SGI_CAP_PHY(wlc)) {
-		brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
-					       BRCMS_N_SGI_40));
-	} else if (BRCMS_ISSSLPNPHY(wlc->band)) {
-		brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
-					       BRCMS_N_SGI_40));
-	} else {
-		brcms_c_ht_update_sgi_rx(wlc, 0);
-	}
-
-	/* initialize radio_mpc_disable according to wlc->mpc */
-	brcms_c_radio_mpc_upd(wlc);
-	brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail);
-
-	if (perr)
-		*perr = 0;
-
-	return wlc;
-
- fail:
-	wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n",
-		  unit, __func__, err);
-	if (wlc)
-		brcms_c_detach(wlc);
-
-	if (perr)
-		*perr = err;
-	return NULL;
-}
-
-static void brcms_c_timers_deinit(struct brcms_c_info *wlc)
-{
-	/* free timer state */
-	if (wlc->wdtimer) {
-		brcms_free_timer(wlc->wdtimer);
-		wlc->wdtimer = NULL;
-	}
-	if (wlc->radio_timer) {
-		brcms_free_timer(wlc->radio_timer);
-		wlc->radio_timer = NULL;
-	}
-}
-
-static void brcms_c_detach_module(struct brcms_c_info *wlc)
-{
-	if (wlc->asi) {
-		brcms_c_antsel_detach(wlc->asi);
-		wlc->asi = NULL;
-	}
-
-	if (wlc->ampdu) {
-		brcms_c_ampdu_detach(wlc->ampdu);
-		wlc->ampdu = NULL;
-	}
-
-	brcms_c_stf_detach(wlc);
-}
+	brcms_c_stf_detach(wlc);
+}
 
 /*
  * low level detach
@@ -5332,7 +5249,7 @@ uint brcms_c_detach(struct brcms_c_info *wlc)
 }
 
 /* update state that depends on the current value of "ap" */
-void brcms_c_ap_upd(struct brcms_c_info *wlc)
+static void brcms_c_ap_upd(struct brcms_c_info *wlc)
 {
 	/* STA-BSS; short capable */
 	wlc->PLCPHdr_override = BRCMS_PLCP_SHORT;
@@ -5341,73 +5258,6 @@ void brcms_c_ap_upd(struct brcms_c_info *wlc)
 	wlc->mpc = true;
 }
 
-/*
- * return true if Minimum Power Consumption should
- * be entered, false otherwise
- */
-bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc)
-{
-	return false;
-}
-
-bool brcms_c_ismpc(struct brcms_c_info *wlc)
-{
-	return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc));
-}
-
-void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc)
-{
-	bool mpc_radio, radio_state;
-
-	/*
-	 * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
-	 * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
-	 * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
-	 * the radio is going down.
-	 */
-	if (!wlc->mpc) {
-		if (!wlc->pub->radio_disabled)
-			return;
-		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
-		brcms_c_radio_upd(wlc);
-		if (!wlc->pub->radio_disabled)
-			brcms_c_radio_monitor_stop(wlc);
-		return;
-	}
-
-	/*
-	 * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in
-	 * wlc->pub->radio_disabled to go ON, always call radio_upd
-	 * synchronously to go OFF, postpone radio_upd to later when
-	 * context is safe(e.g. watchdog)
-	 */
-	radio_state =
-	    (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
-	     ON);
-	mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON;
-
-	if (radio_state == ON && mpc_radio == OFF)
-		wlc->mpc_delay_off = wlc->mpc_dlycnt;
-	else if (radio_state == OFF && mpc_radio == ON) {
-		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
-		brcms_c_radio_upd(wlc);
-		if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD)
-			wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT;
-		else
-			wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
-	}
-	/*
-	 * Below logic is meant to capture the transition from mpc off
-	 * to mpc on for reasons other than wlc->mpc_delay_off keeping
-	 * the mpc off. In that case reset wlc->mpc_delay_off to
-	 * wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
-	 */
-	if ((wlc->prev_non_delay_mpc == false) &&
-	    (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off)
-		wlc->mpc_delay_off = wlc->mpc_dlycnt;
-
-	wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc);
-}
 /* Initialize just the hardware when coming out of POR or S3/S5 system states */
 static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
 {
@@ -6195,59 +6045,7 @@ void brcms_c_print_txstatus(struct tx_status *txs)
 #endif				/* defined(BCMDBG) */
 }
 
-void brcms_c_statsupd(struct brcms_c_info *wlc)
-{
-	int i;
-	struct macstat macstats;
-#ifdef BCMDBG
-	u16 delta;
-	u16 rxf0ovfl;
-	u16 txfunfl[NFIFO];
-#endif				/* BCMDBG */
-
-	/* if driver down, make no sense to update stats */
-	if (!wlc->pub->up)
-		return;
-
-#ifdef BCMDBG
-	/* save last rx fifo 0 overflow count */
-	rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
-
-	/* save last tx fifo  underflow count */
-	for (i = 0; i < NFIFO; i++)
-		txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
-#endif				/* BCMDBG */
-
-	/* Read mac stats from contiguous shared memory */
-	brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats,
-				sizeof(struct macstat), OBJADDR_SHM_SEL);
-
-#ifdef BCMDBG
-	/* check for rx fifo 0 overflow */
-	delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
-	if (delta)
-		wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n",
-			  wlc->pub->unit, delta);
-
-	/* check for tx fifo underflows */
-	for (i = 0; i < NFIFO; i++) {
-		delta =
-		    (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
-			      txfunfl[i]);
-		if (delta)
-			wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!"
-				  "\n", wlc->pub->unit, delta, i);
-	}
-#endif				/* BCMDBG */
-
-	/* merge counters from dma module */
-	for (i = 0; i < NFIFO; i++) {
-		if (wlc->hw->di[i])
-			dma_counterreset(wlc->hw->di[i]);
-	}
-}
-
-bool brcms_c_chipmatch(u16 vendor, u16 device)
+bool brcms_c_chipmatch(u16 vendor, u16 device)
 {
 	if (vendor != PCI_VENDOR_ID_BROADCOM) {
 		pr_err("chipmatch: unknown vendor id %04x\n", vendor);
@@ -6417,24 +6215,7 @@ u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
 	return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2));
 }
 
-/* Callback for device removed */
-
-/*
- * Attempts to queue a packet onto a multiple-precedence queue,
- * if necessary evicting a lower precedence packet from the queue.
- *
- * 'prec' is the precedence number that has already been mapped
- * from the packet priority.
- *
- * Returns true if packet consumed (queued), false if not.
- */
-static bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q,
-		      struct sk_buff *pkt, int prec)
-{
-	return brcms_c_prec_enq_head(wlc, q, pkt, prec, false);
-}
-
-bool
+static bool
 brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
 		      struct sk_buff *pkt, int prec, bool head)
 {
@@ -6481,6 +6262,21 @@ brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
 	return true;
 }
 
+/*
+ * Attempts to queue a packet onto a multiple-precedence queue,
+ * if necessary evicting a lower precedence packet from the queue.
+ *
+ * 'prec' is the precedence number that has already been mapped
+ * from the packet priority.
+ *
+ * Returns true if packet consumed (queued), false if not.
+ */
+static bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q,
+		      struct sk_buff *pkt, int prec)
+{
+	return brcms_c_prec_enq_head(wlc, q, pkt, prec, false);
+}
+
 void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb,
 		     struct sk_buff *sdu, uint prec)
 {
@@ -6647,6 +6443,43 @@ brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec,
 	return mac_len;
 }
 
+/*
+ * Return true if the specified rate is supported by the specified band.
+ * BRCM_BAND_AUTO indicates the current band.
+ */
+static bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band,
+		    bool verbose)
+{
+	struct brcms_c_rateset *hw_rateset;
+	uint i;
+
+	if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype))
+		hw_rateset = &wlc->band->hw_rateset;
+	else if (wlc->pub->_nbands > 1)
+		hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
+	else
+		/* other band specified and we are a single band device */
+		return false;
+
+	/* check if this is a mimo rate */
+	if (is_mcs_rate(rspec)) {
+		if ((rspec & RSPEC_RATE_MASK) >= MCS_TABLE_SIZE)
+			goto error;
+
+		return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
+	}
+
+	for (i = 0; i < hw_rateset->count; i++)
+		if (hw_rateset->rates[i] == rspec2rate(rspec))
+			return true;
+ error:
+	if (verbose)
+		wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x "
+			  "not in hw_rateset\n", wlc->pub->unit, rspec);
+
+	return false;
+}
+
 static u32
 mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
 		       u32 int_val)
@@ -6764,84 +6597,291 @@ done:
 }
 
 /*
- * Add struct d11txh, struct cck_phy_hdr.
- *
- * 'p' data must start with 802.11 MAC header
- * 'p' must allow enough bytes of local headers to be "pushed" onto the packet
- *
- * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes)
- *
+ * Compute PLCP, but only requires actual rate and length of pkt.
+ * Rate is given in the driver standard multiple of 500 kbps.
+ * le is set for 11 Mbps rate if necessary.
+ * Broken out for PRQ.
  */
-static u16
-brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
-		     struct sk_buff *p, struct scb *scb, uint frag,
-		     uint nfrags, uint queue, uint next_frag_len)
-{
-	struct ieee80211_hdr *h;
-	struct d11txh *txh;
-	u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN];
-	int len, phylen, rts_phylen;
-	u16 mch, phyctl, xfts, mainrates;
-	u16 seq = 0, mcl = 0, status = 0, frameid = 0;
-	u32 rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M };
-	u32 rts_rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M };
-	bool use_rts = false;
-	bool use_cts = false;
-	bool use_rifs = false;
-	bool short_preamble[2] = { false, false };
-	u8 preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
-	u8 rts_preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
-	u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN];
-	struct ieee80211_rts *rts = NULL;
-	bool qos;
-	uint ac;
-	bool hwtkmic = false;
-	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
-#define ANTCFG_NONE 0xFF
-	u8 antcfg = ANTCFG_NONE;
-	u8 fbantcfg = ANTCFG_NONE;
-	uint phyctl1_stf = 0;
-	u16 durid = 0;
-	struct ieee80211_tx_rate *txrate[2];
-	int k;
-	struct ieee80211_tx_info *tx_info;
-	bool is_mcs;
-	u16 mimo_txbw;
-	u8 mimo_preamble_type;
 
-	/* locate 802.11 MAC header */
-	h = (struct ieee80211_hdr *)(p->data);
-	qos = ieee80211_is_data_qos(h->frame_control);
+static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
+			     uint length, u8 *plcp)
+{
+	u16 usec = 0;
+	u8 le = 0;
 
-	/* compute length of frame in bytes for use in PLCP computations */
-	len = brcmu_pkttotlen(p);
-	phylen = len + FCS_LEN;
+	switch (rate_500) {
+	case BRCM_RATE_1M:
+		usec = length << 3;
+		break;
+	case BRCM_RATE_2M:
+		usec = length << 2;
+		break;
+	case BRCM_RATE_5M5:
+		usec = (length << 4) / 11;
+		if ((length << 4) - (usec * 11) > 0)
+			usec++;
+		break;
+	case BRCM_RATE_11M:
+		usec = (length << 3) / 11;
+		if ((length << 3) - (usec * 11) > 0) {
+			usec++;
+			if ((usec * 11) - (length << 3) >= 8)
+				le = D11B_PLCP_SIGNAL_LE;
+		}
+		break;
 
-	/* Get tx_info */
-	tx_info = IEEE80211_SKB_CB(p);
+	default:
+		wiphy_err(wlc->wiphy,
+			  "brcms_c_cck_plcp_set: unsupported rate %d\n",
+			  rate_500);
+		rate_500 = BRCM_RATE_1M;
+		usec = length << 3;
+		break;
+	}
+	/* PLCP signal byte */
+	plcp[0] = rate_500 * 5;	/* r (500kbps) * 5 == r (100kbps) */
+	/* PLCP service byte */
+	plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED);
+	/* PLCP length u16, little endian */
+	plcp[2] = usec & 0xff;
+	plcp[3] = (usec >> 8) & 0xff;
+	/* PLCP CRC16 */
+	plcp[4] = 0;
+	plcp[5] = 0;
+}
 
-	/* add PLCP */
-	plcp = skb_push(p, D11_PHY_HDR_LEN);
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void brcms_c_compute_mimo_plcp(u32 rspec, uint length, u8 *plcp)
+{
+	u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
+	plcp[0] = mcs;
+	if (rspec_is40mhz(rspec) || (mcs == 32))
+		plcp[0] |= MIMO_PLCP_40MHZ;
+	BRCMS_SET_MIMO_PLCP_LEN(plcp, length);
+	plcp[3] = rspec_mimoplcp3(rspec); /* rspec already holds this byte */
+	plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */
+	plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */
+	plcp[5] = 0;
+}
 
-	/* add Broadcom tx descriptor header */
-	txh = (struct d11txh *) skb_push(p, D11_TXH_LEN);
-	memset(txh, 0, D11_TXH_LEN);
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void
+brcms_c_compute_ofdm_plcp(u32 rspec, u32 length, u8 *plcp)
+{
+	u8 rate_signal;
+	u32 tmp = 0;
+	int rate = rspec2rate(rspec);
 
-	/* setup frameid */
-	if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-		/* non-AP STA should never use BCMC queue */
-		if (queue == TX_BCMC_FIFO) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == "
-				  "TX_BCMC!\n", wlc->pub->unit, __func__);
-			frameid = bcmc_fid_generate(wlc, NULL, txh);
-		} else {
-			/* Increment the counter for first fragment */
-			if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
-				scb->seqnum[p->priority]++;
+	/*
+	 * encode rate per 802.11a-1999 sec 17.3.4.1, with lsb
+	 * transmitted first
+	 */
+	rate_signal = rate_info[rate] & BRCMS_RATE_MASK;
+	memset(plcp, 0, D11_PHY_HDR_LEN);
+	D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal);
 
-			/* extract fragment number from frame first */
-			seq = le16_to_cpu(h->seq_ctrl) & FRAGNUM_MASK;
-			seq |= (scb->seqnum[p->priority] << SEQNUM_SHIFT);
+	tmp = (length & 0xfff) << 5;
+	plcp[2] |= (tmp >> 16) & 0xff;
+	plcp[1] |= (tmp >> 8) & 0xff;
+	plcp[0] |= tmp & 0xff;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec,
+				 uint length, u8 *plcp)
+{
+	int rate = rspec2rate(rspec);
+
+	brcms_c_cck_plcp_set(wlc, rate, length, plcp);
+}
+
+static void
+brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rspec,
+		     uint length, u8 *plcp)
+{
+	if (is_mcs_rate(rspec))
+		brcms_c_compute_mimo_plcp(rspec, length, plcp);
+	else if (is_ofdm_rate(rspec))
+		brcms_c_compute_ofdm_plcp(rspec, length, plcp);
+	else
+		brcms_c_compute_cck_plcp(wlc, rspec, length, plcp);
+}
+
+/* brcms_c_compute_rtscts_dur()
+ *
+ * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame
+ * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK
+ * DUR for CTS-TO-SELF w/ frame    = 2 SIFS         + next frame time + 1 ACK
+ *
+ * cts			cts-to-self or rts/cts
+ * rts_rate		rts or cts rate in unit of 500kbps
+ * rate			next MPDU rate in unit of 500kbps
+ * frame_len		next MPDU frame length in bytes
+ */
+u16
+brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
+			   u32 rts_rate,
+			   u32 frame_rate, u8 rts_preamble_type,
+			   u8 frame_preamble_type, uint frame_len, bool ba)
+{
+	u16 dur, sifs;
+
+	sifs = get_sifs(wlc->band);
+
+	if (!cts_only) {
+		/* RTS/CTS */
+		dur = 3 * sifs;
+		dur +=
+		    (u16) brcms_c_calc_cts_time(wlc, rts_rate,
+					       rts_preamble_type);
+	} else {
+		/* CTS-TO-SELF */
+		dur = 2 * sifs;
+	}
+
+	dur +=
+	    (u16) brcms_c_calc_frame_time(wlc, frame_rate, frame_preamble_type,
+					 frame_len);
+	if (ba)
+		dur +=
+		    (u16) brcms_c_calc_ba_time(wlc, frame_rate,
+					      BRCMS_SHORT_PREAMBLE);
+	else
+		dur +=
+		    (u16) brcms_c_calc_ack_time(wlc, frame_rate,
+					       frame_preamble_type);
+	return dur;
+}
+
+static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec)
+{
+	u16 phyctl1 = 0;
+	u16 bw;
+
+	if (BRCMS_ISLCNPHY(wlc->band)) {
+		bw = PHY_TXC1_BW_20MHZ;
+	} else {
+		bw = rspec_get_bw(rspec);
+		/* 10Mhz is not supported yet */
+		if (bw < PHY_TXC1_BW_20MHZ) {
+			wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is "
+				  "not supported yet, set to 20L\n", bw);
+			bw = PHY_TXC1_BW_20MHZ;
+		}
+	}
+
+	if (is_mcs_rate(rspec)) {
+		uint mcs = rspec & RSPEC_RATE_MASK;
+
+		/* bw, stf, coding-type is part of rspec_phytxbyte2 returns */
+		phyctl1 = rspec_phytxbyte2(rspec);
+		/* set the upper byte of phyctl1 */
+		phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
+	} else if (is_cck_rate(rspec) && !BRCMS_ISLCNPHY(wlc->band)
+		   && !BRCMS_ISSSLPNPHY(wlc->band)) {
+		/*
+		 * In CCK mode LPPHY overloads OFDM Modulation bits with CCK
+		 * Data Rate. Eventually MIMOPHY would also be converted to
+		 * this format
+		 */
+		/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
+		phyctl1 = (bw | (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT));
+	} else {		/* legacy OFDM/CCK */
+		s16 phycfg;
+		/* get the phyctl byte from rate phycfg table */
+		phycfg = brcms_c_rate_legacy_phyctl(rspec2rate(rspec));
+		if (phycfg == -1) {
+			wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong "
+				  "legacy OFDM/CCK rate\n");
+			phycfg = 0;
+		}
+		/* set the upper byte of phyctl1 */
+		phyctl1 =
+		    (bw | (phycfg << 8) |
+		     (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT));
+	}
+	return phyctl1;
+}
+
+/*
+ * Add struct d11txh, struct cck_phy_hdr.
+ *
+ * 'p' data must start with 802.11 MAC header
+ * 'p' must allow enough bytes of local headers to be "pushed" onto the packet
+ *
+ * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes)
+ *
+ */
+static u16
+brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
+		     struct sk_buff *p, struct scb *scb, uint frag,
+		     uint nfrags, uint queue, uint next_frag_len)
+{
+	struct ieee80211_hdr *h;
+	struct d11txh *txh;
+	u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN];
+	int len, phylen, rts_phylen;
+	u16 mch, phyctl, xfts, mainrates;
+	u16 seq = 0, mcl = 0, status = 0, frameid = 0;
+	u32 rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M };
+	u32 rts_rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M };
+	bool use_rts = false;
+	bool use_cts = false;
+	bool use_rifs = false;
+	bool short_preamble[2] = { false, false };
+	u8 preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
+	u8 rts_preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
+	u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN];
+	struct ieee80211_rts *rts = NULL;
+	bool qos;
+	uint ac;
+	bool hwtkmic = false;
+	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+#define ANTCFG_NONE 0xFF
+	u8 antcfg = ANTCFG_NONE;
+	u8 fbantcfg = ANTCFG_NONE;
+	uint phyctl1_stf = 0;
+	u16 durid = 0;
+	struct ieee80211_tx_rate *txrate[2];
+	int k;
+	struct ieee80211_tx_info *tx_info;
+	bool is_mcs;
+	u16 mimo_txbw;
+	u8 mimo_preamble_type;
+
+	/* locate 802.11 MAC header */
+	h = (struct ieee80211_hdr *)(p->data);
+	qos = ieee80211_is_data_qos(h->frame_control);
+
+	/* compute length of frame in bytes for use in PLCP computations */
+	len = brcmu_pkttotlen(p);
+	phylen = len + FCS_LEN;
+
+	/* Get tx_info */
+	tx_info = IEEE80211_SKB_CB(p);
+
+	/* add PLCP */
+	plcp = skb_push(p, D11_PHY_HDR_LEN);
+
+	/* add Broadcom tx descriptor header */
+	txh = (struct d11txh *) skb_push(p, D11_TXH_LEN);
+	memset(txh, 0, D11_TXH_LEN);
+
+	/* setup frameid */
+	if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+		/* non-AP STA should never use BCMC queue */
+		if (queue == TX_BCMC_FIFO) {
+			wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == "
+				  "TX_BCMC!\n", wlc->pub->unit, __func__);
+			frameid = bcmc_fid_generate(wlc, NULL, txh);
+		} else {
+			/* Increment the counter for first fragment */
+			if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+				scb->seqnum[p->priority]++;
+
+			/* extract fragment number from frame first */
+			seq = le16_to_cpu(h->seq_ctrl) & FRAGNUM_MASK;
+			seq |= (scb->seqnum[p->priority] << SEQNUM_SHIFT);
 			h->seq_ctrl = cpu_to_le16(seq);
 
 			frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
@@ -7518,237 +7558,30 @@ brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
 		wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n");
 }
 
-/*
- * Compute PLCP, but only requires actual rate and length of pkt.
- * Rate is given in the driver standard multiple of 500 kbps.
- * le is set for 11 Mbps rate if necessary.
- * Broken out for PRQ.
- */
-
-static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
-			     uint length, u8 *plcp)
+u32
+brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
+			   bool use_rspec, u16 mimo_ctlchbw)
 {
-	u16 usec = 0;
-	u8 le = 0;
+	u32 rts_rspec = 0;
 
-	switch (rate_500) {
-	case BRCM_RATE_1M:
-		usec = length << 3;
-		break;
-	case BRCM_RATE_2M:
-		usec = length << 2;
-		break;
-	case BRCM_RATE_5M5:
-		usec = (length << 4) / 11;
-		if ((length << 4) - (usec * 11) > 0)
-			usec++;
-		break;
-	case BRCM_RATE_11M:
-		usec = (length << 3) / 11;
-		if ((length << 3) - (usec * 11) > 0) {
-			usec++;
-			if ((usec * 11) - (length << 3) >= 8)
-				le = D11B_PLCP_SIGNAL_LE;
-		}
-		break;
-
-	default:
-		wiphy_err(wlc->wiphy,
-			  "brcms_c_cck_plcp_set: unsupported rate %d\n",
-			  rate_500);
-		rate_500 = BRCM_RATE_1M;
-		usec = length << 3;
-		break;
-	}
-	/* PLCP signal byte */
-	plcp[0] = rate_500 * 5;	/* r (500kbps) * 5 == r (100kbps) */
-	/* PLCP service byte */
-	plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED);
-	/* PLCP length u16, little endian */
-	plcp[2] = usec & 0xff;
-	plcp[3] = (usec >> 8) & 0xff;
-	/* PLCP CRC16 */
-	plcp[4] = 0;
-	plcp[5] = 0;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void brcms_c_compute_mimo_plcp(u32 rspec, uint length, u8 *plcp)
-{
-	u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
-	plcp[0] = mcs;
-	if (rspec_is40mhz(rspec) || (mcs == 32))
-		plcp[0] |= MIMO_PLCP_40MHZ;
-	BRCMS_SET_MIMO_PLCP_LEN(plcp, length);
-	plcp[3] = rspec_mimoplcp3(rspec); /* rspec already holds this byte */
-	plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */
-	plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */
-	plcp[5] = 0;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void
-brcms_c_compute_ofdm_plcp(u32 rspec, u32 length, u8 *plcp)
-{
-	u8 rate_signal;
-	u32 tmp = 0;
-	int rate = rspec2rate(rspec);
-
-	/*
-	 * encode rate per 802.11a-1999 sec 17.3.4.1, with lsb
-	 * transmitted first
-	 */
-	rate_signal = rate_info[rate] & BRCMS_RATE_MASK;
-	memset(plcp, 0, D11_PHY_HDR_LEN);
-	D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal);
-
-	tmp = (length & 0xfff) << 5;
-	plcp[2] |= (tmp >> 16) & 0xff;
-	plcp[1] |= (tmp >> 8) & 0xff;
-	plcp[0] |= tmp & 0xff;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec,
-				 uint length, u8 *plcp)
-{
-	int rate = rspec2rate(rspec);
-
-	brcms_c_cck_plcp_set(wlc, rate, length, plcp);
-}
-
-void
-brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rspec,
-		     uint length, u8 *plcp)
-{
-	if (is_mcs_rate(rspec))
-		brcms_c_compute_mimo_plcp(rspec, length, plcp);
-	else if (is_ofdm_rate(rspec))
-		brcms_c_compute_ofdm_plcp(rspec, length, plcp);
-	else
-		brcms_c_compute_cck_plcp(wlc, rspec, length, plcp);
-}
-
-/* brcms_c_compute_rtscts_dur()
- *
- * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame
- * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK
- * DUR for CTS-TO-SELF w/ frame    = 2 SIFS         + next frame time + 1 ACK
- *
- * cts			cts-to-self or rts/cts
- * rts_rate		rts or cts rate in unit of 500kbps
- * rate			next MPDU rate in unit of 500kbps
- * frame_len		next MPDU frame length in bytes
- */
-u16
-brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
-			   u32 rts_rate,
-			   u32 frame_rate, u8 rts_preamble_type,
-			   u8 frame_preamble_type, uint frame_len, bool ba)
-{
-	u16 dur, sifs;
-
-	sifs = get_sifs(wlc->band);
-
-	if (!cts_only) {
-		/* RTS/CTS */
-		dur = 3 * sifs;
-		dur +=
-		    (u16) brcms_c_calc_cts_time(wlc, rts_rate,
-					       rts_preamble_type);
-	} else {
-		/* CTS-TO-SELF */
-		dur = 2 * sifs;
-	}
-
-	dur +=
-	    (u16) brcms_c_calc_frame_time(wlc, frame_rate, frame_preamble_type,
-					 frame_len);
-	if (ba)
-		dur +=
-		    (u16) brcms_c_calc_ba_time(wlc, frame_rate,
-					      BRCMS_SHORT_PREAMBLE);
-	else
-		dur +=
-		    (u16) brcms_c_calc_ack_time(wlc, frame_rate,
-					       frame_preamble_type);
-	return dur;
-}
-
-u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec)
-{
-	u16 phyctl1 = 0;
-	u16 bw;
-
-	if (BRCMS_ISLCNPHY(wlc->band)) {
-		bw = PHY_TXC1_BW_20MHZ;
-	} else {
-		bw = rspec_get_bw(rspec);
-		/* 10Mhz is not supported yet */
-		if (bw < PHY_TXC1_BW_20MHZ) {
-			wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is "
-				  "not supported yet, set to 20L\n", bw);
-			bw = PHY_TXC1_BW_20MHZ;
-		}
-	}
-
-	if (is_mcs_rate(rspec)) {
-		uint mcs = rspec & RSPEC_RATE_MASK;
-
-		/* bw, stf, coding-type is part of rspec_phytxbyte2 returns */
-		phyctl1 = rspec_phytxbyte2(rspec);
-		/* set the upper byte of phyctl1 */
-		phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
-	} else if (is_cck_rate(rspec) && !BRCMS_ISLCNPHY(wlc->band)
-		   && !BRCMS_ISSSLPNPHY(wlc->band)) {
-		/*
-		 * In CCK mode LPPHY overloads OFDM Modulation bits with CCK
-		 * Data Rate. Eventually MIMOPHY would also be converted to
-		 * this format
-		 */
-		/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
-		phyctl1 = (bw | (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT));
-	} else {		/* legacy OFDM/CCK */
-		s16 phycfg;
-		/* get the phyctl byte from rate phycfg table */
-		phycfg = brcms_c_rate_legacy_phyctl(rspec2rate(rspec));
-		if (phycfg == -1) {
-			wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong "
-				  "legacy OFDM/CCK rate\n");
-			phycfg = 0;
-		}
-		/* set the upper byte of phyctl1 */
-		phyctl1 =
-		    (bw | (phycfg << 8) |
-		     (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT));
-	}
-	return phyctl1;
-}
-
-u32
-brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
-			   bool use_rspec, u16 mimo_ctlchbw)
-{
-	u32 rts_rspec = 0;
-
-	if (use_rspec)
-		/* use frame rate as rts rate */
-		rts_rspec = rspec;
-	else if (wlc->band->gmode && wlc->protection->_g && !is_cck_rate(rspec))
-		/* Use 11Mbps as the g protection RTS target rate and fallback.
-		 * Use the brcms_basic_rate() lookup to find the best basic rate
-		 * under the target in case 11 Mbps is not Basic.
-		 * 6 and 9 Mbps are not usually selected by rate selection, but
-		 * even if the OFDM rate we are protecting is 6 or 9 Mbps, 11
-		 * is more robust.
-		 */
-		rts_rspec = brcms_basic_rate(wlc, BRCM_RATE_11M);
-	else
-		/* calculate RTS rate and fallback rate based on the frame rate
-		 * RTS must be sent at a basic rate since it is a
-		 * control frame, sec 9.6 of 802.11 spec
-		 */
-		rts_rspec = brcms_basic_rate(wlc, rspec);
+	if (use_rspec)
+		/* use frame rate as rts rate */
+		rts_rspec = rspec;
+	else if (wlc->band->gmode && wlc->protection->_g && !is_cck_rate(rspec))
+		/* Use 11Mbps as the g protection RTS target rate and fallback.
+		 * Use the brcms_basic_rate() lookup to find the best basic rate
+		 * under the target in case 11 Mbps is not Basic.
+		 * 6 and 9 Mbps are not usually selected by rate selection, but
+		 * even if the OFDM rate we are protecting is 6 or 9 Mbps, 11
+		 * is more robust.
+		 */
+		rts_rspec = brcms_basic_rate(wlc, BRCM_RATE_11M);
+	else
+		/* calculate RTS rate and fallback rate based on the frame rate
+		 * RTS must be sent at a basic rate since it is a
+		 * control frame, sec 9.6 of 802.11 spec
+		 */
+		rts_rspec = brcms_basic_rate(wlc, rspec);
 
 	if (BRCMS_PHY_11N_CAP(wlc->band)) {
 		/* set rts txbw to correct side band */
@@ -7772,16 +7605,6 @@ brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
 	return rts_rspec;
 }
 
-void brcms_c_tbtt(struct brcms_c_info *wlc)
-{
-	if (!wlc->bsscfg->BSS)
-		/*
-		 * DirFrmQ is now valid...defer setting until end
-		 * of ATIM window
-		 */
-		wlc->qvalid |= MCMD_DIRFRMQVAL;
-}
-
 void
 brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend)
 {
@@ -7796,7 +7619,7 @@ brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend)
 }
 
 /* Update beacon listen interval in shared memory */
-void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
+static void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
 {
 	/* wake up every DTIM is the default */
 	if (wlc->bcn_li_dtim == 1)
@@ -7993,93 +7816,33 @@ brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
 	ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
 }
 
-/* Process received frames */
-/*
- * Return true if more frames need to be processed. false otherwise.
- * Param 'bound' indicates max. # frames to process before break out.
+/* calculate frame duration for Mixed-mode L-SIG spoofing, return
+ * number of bytes goes in the length field
+ *
+ * Formula given by HT PHY Spec v 1.13
+ *   len = 3(nsyms + nstream + 3) - 3
  */
-void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
+u16
+brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
+		      uint mac_len)
 {
-	struct d11rxhdr *rxh;
-	struct ieee80211_hdr *h;
-	uint len;
-	bool is_amsdu;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
-	/* frame starts with rxhdr */
-	rxh = (struct d11rxhdr *) (p->data);
+	uint nsyms, len = 0, kNdps;
 
-	/* strip off rxhdr */
-	skb_pull(p, BRCMS_HWRXOFF);
+	BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n",
+		 wlc->pub->unit, rspec2rate(ratespec), mac_len);
 
-	/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
-	if (rxh->RxStatus1 & RXS_PBPRES) {
-		if (p->len < 2) {
-			wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of "
-				  "len %d\n", wlc->pub->unit, p->len);
-			goto toss;
-		}
-		skb_pull(p, 2);
-	}
+	if (is_mcs_rate(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		int tot_streams = (mcs_2_txstreams(mcs) + 1) +
+				  rspec_stc(ratespec);
 
-	h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
-	len = p->len;
-
-	if (rxh->RxStatus1 & RXS_FCSERR) {
-		if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
-			wiphy_err(wlc->wiphy, "FCSERR while scanning******* -"
-				  " tossing\n");
-			goto toss;
-		} else {
-			wiphy_err(wlc->wiphy, "RCSERR!!!\n");
-			goto toss;
-		}
-	}
-
-	/* check received pkt has at least frame control field */
-	if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control))
-		goto toss;
-
-	/* not supporting A-MSDU */
-	is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
-	if (is_amsdu)
-		goto toss;
-
-	brcms_c_recvctl(wlc, rxh, p);
-	return;
-
- toss:
-	brcmu_pkt_buf_free_skb(p);
-}
-
-/* calculate frame duration for Mixed-mode L-SIG spoofing, return
- * number of bytes goes in the length field
- *
- * Formula given by HT PHY Spec v 1.13
- *   len = 3(nsyms + nstream + 3) - 3
- */
-u16
-brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
-		      uint mac_len)
-{
-	uint nsyms, len = 0, kNdps;
-
-	BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n",
-		 wlc->pub->unit, rspec2rate(ratespec), mac_len);
-
-	if (is_mcs_rate(ratespec)) {
-		uint mcs = ratespec & RSPEC_RATE_MASK;
-		int tot_streams = (mcs_2_txstreams(mcs) + 1) +
-				  rspec_stc(ratespec);
-
-		/*
-		 * the payload duration calculation matches that
-		 * of regular ofdm
-		 */
-		/* 1000Ndbps = kbps * 4 */
-		kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
-				   rspec_issgi(ratespec)) * 4;
+		/*
+		 * the payload duration calculation matches that
+		 * of regular ofdm
+		 */
+		/* 1000Ndbps = kbps * 4 */
+		kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+				   rspec_issgi(ratespec)) * 4;
 
 		if (rspec_stc(ratespec) == 0)
 			nsyms =
@@ -8104,737 +7867,847 @@ brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
 	return (u16) len;
 }
 
-/*
- * calculate frame duration of a given rate and length, return
- * time in usec unit
- */
-uint
-brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
-			u8 preamble_type, uint mac_len)
+static void
+brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
 {
-	uint nsyms, dur = 0, Ndps, kNdps;
-	uint rate = rspec2rate(ratespec);
+	const struct brcms_c_rateset *rs_dflt;
+	struct brcms_c_rateset rs;
+	u8 rate;
+	u16 entry_ptr;
+	u8 plcp[D11_PHY_HDR_LEN];
+	u16 dur, sifs;
+	uint i;
 
-	if (rate == 0) {
-		wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n",
-			  wlc->pub->unit);
-		rate = BRCM_RATE_1M;
-	}
+	sifs = get_sifs(wlc->band);
 
-	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n",
-		 wlc->pub->unit, ratespec, preamble_type, mac_len);
+	rs_dflt = brcms_c_rateset_get_hwrs(wlc);
 
-	if (is_mcs_rate(ratespec)) {
-		uint mcs = ratespec & RSPEC_RATE_MASK;
-		int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec);
+	brcms_c_rateset_copy(rs_dflt, &rs);
+	brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
 
-		dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
-		if (preamble_type == BRCMS_MM_PREAMBLE)
-			dur += PREN_MM_EXT;
-		/* 1000Ndbps = kbps * 4 */
-		kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
-				   rspec_issgi(ratespec)) * 4;
+	/*
+	 * walk the phy rate table and update MAC core SHM
+	 * basic rate table entries
+	 */
+	for (i = 0; i < rs.count; i++) {
+		rate = rs.rates[i] & BRCMS_RATE_MASK;
 
-		if (rspec_stc(ratespec) == 0)
-			nsyms =
-			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
-				  APHY_TAIL_NBITS) * 1000, kNdps);
-		else
-			/* STBC needs to have even number of symbols */
-			nsyms =
-			    2 *
-			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
-				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+		entry_ptr = brcms_b_rate_shm_offset(wlc->hw, rate);
+
+		/* Calculate the Probe Response PLCP for the given rate */
+		brcms_c_compute_plcp(wlc, rate, frame_len, plcp);
 
-		dur += APHY_SYMBOL_TIME * nsyms;
-		if (wlc->band->bandtype == BRCM_BAND_2G)
-			dur += DOT11_OFDM_SIGNAL_EXTENSION;
-	} else if (is_ofdm_rate(rate)) {
-		dur = APHY_PREAMBLE_TIME;
-		dur += APHY_SIGNAL_TIME;
-		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
-		Ndps = rate * 2;
-		/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
-		nsyms =
-		    CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
-			 Ndps);
-		dur += APHY_SYMBOL_TIME * nsyms;
-		if (wlc->band->bandtype == BRCM_BAND_2G)
-			dur += DOT11_OFDM_SIGNAL_EXTENSION;
-	} else {
 		/*
-		 * calc # bits * 2 so factor of 2 in rate (1/2 mbps)
-		 * will divide out
+		 * Calculate the duration of the Probe Response
+		 * frame plus SIFS for the MAC
 		 */
-		mac_len = mac_len * 8 * 2;
-		/* calc ceiling of bits/rate = microseconds of air time */
-		dur = (mac_len + rate - 1) / rate;
-		if (preamble_type & BRCMS_SHORT_PREAMBLE)
-			dur += BPHY_PLCP_SHORT_TIME;
-		else
-			dur += BPHY_PLCP_TIME;
+		dur = (u16) brcms_c_calc_frame_time(wlc, rate,
+						BRCMS_LONG_PREAMBLE, frame_len);
+		dur += sifs;
+
+		/* Update the SHM Rate Table entry Probe Response values */
+		brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS,
+			      (u16) (plcp[0] + (plcp[1] << 8)));
+		brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS + 2,
+			      (u16) (plcp[2] + (plcp[3] << 8)));
+		brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_DUR_POS, dur);
 	}
-	return dur;
 }
 
-/* derive wlc->band->basic_rate[] table from 'rateset' */
-void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
-			      struct brcms_c_rateset *rateset)
+/*	Max buffering needed for beacon template/prb resp template is 142 bytes.
+ *
+ *	PLCP header is 6 bytes.
+ *	802.11 A3 header is 24 bytes.
+ *	Max beacon frame body template length is 112 bytes.
+ *	Max probe resp frame body template length is 110 bytes.
+ *
+ *      *len on input contains the max length of the packet available.
+ *
+ *	The *len value is set to the number of bytes in buf used, and starts
+ *	with the PLCP and included up to, but not including, the 4 byte FCS.
+ */
+static void
+brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
+			 u32 bcn_rspec,
+			 struct brcms_bss_cfg *cfg, u16 *buf, int *len)
 {
-	u8 rate;
-	u8 mandatory;
-	u8 cck_basic = 0;
-	u8 ofdm_basic = 0;
-	u8 *br = wlc->band->basic_rate;
-	uint i;
-
-	/* incoming rates are in 500kbps units as in 802.11 Supported Rates */
-	memset(br, 0, BRCM_MAXRATE + 1);
+	static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
+	struct cck_phy_hdr *plcp;
+	struct ieee80211_mgmt *h;
+	int hdr_len, body_len;
 
-	/* For each basic rate in the rates list, make an entry in the
-	 * best basic lookup.
-	 */
-	for (i = 0; i < rateset->count; i++) {
-		/* only make an entry for a basic rate */
-		if (!(rateset->rates[i] & BRCMS_RATE_FLAG))
-			continue;
+	hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
 
-		/* mask off basic bit */
-		rate = (rateset->rates[i] & BRCMS_RATE_MASK);
+	/* calc buffer size provided for frame body */
+	body_len = *len - hdr_len;
+	/* return actual size */
+	*len = hdr_len + body_len;
 
-		if (rate > BRCM_MAXRATE) {
-			wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: "
-				  "invalid rate 0x%X in rate set\n",
-				  rateset->rates[i]);
-			continue;
-		}
+	/* format PHY and MAC headers */
+	memset((char *)buf, 0, hdr_len);
 
-		br[rate] = rate;
-	}
+	plcp = (struct cck_phy_hdr *) buf;
 
-	/* The rate lookup table now has non-zero entries for each
-	 * basic rate, equal to the basic rate: br[basicN] = basicN
-	 *
-	 * To look up the best basic rate corresponding to any
-	 * particular rate, code can use the basic_rate table
-	 * like this
-	 *
-	 * basic_rate = wlc->band->basic_rate[tx_rate]
-	 *
-	 * Make sure there is a best basic rate entry for
-	 * every rate by walking up the table from low rates
-	 * to high, filling in holes in the lookup table
+	/*
+	 * PLCP for Probe Response frames are filled in from
+	 * core's rate table
 	 */
+	if (type == IEEE80211_STYPE_BEACON)
+		/* fill in PLCP */
+		brcms_c_compute_plcp(wlc, bcn_rspec,
+				 (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
+				 (u8 *) plcp);
 
-	for (i = 0; i < wlc->band->hw_rateset.count; i++) {
-		rate = wlc->band->hw_rateset.rates[i];
+	/* "Regular" and 16 MBSS but not for 4 MBSS */
+	/* Update the phytxctl for the beacon based on the rspec */
+	brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
 
-		if (br[rate] != 0) {
-			/* This rate is a basic rate.
-			 * Keep track of the best basic rate so far by
-			 * modulation type.
-			 */
-			if (is_ofdm_rate(rate))
-				ofdm_basic = rate;
-			else
-				cck_basic = rate;
+	h = (struct ieee80211_mgmt *)&plcp[1];
 
-			continue;
-		}
+	/* fill in 802.11 header */
+	h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
 
-		/* This rate is not a basic rate so figure out the
-		 * best basic rate less than this rate and fill in
-		 * the hole in the table
-		 */
+	/* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
+	/* A1 filled in by MAC for prb resp, broadcast for bcn */
+	if (type == IEEE80211_STYPE_BEACON)
+		memcpy(&h->da, &ether_bcast, ETH_ALEN);
+	memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN);
+	memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
 
-		br[rate] = is_ofdm_rate(rate) ? ofdm_basic : cck_basic;
+	/* SEQ filled in by MAC */
+}
 
-		if (br[rate] != 0)
-			continue;
+int brcms_c_get_header_len(void)
+{
+	return TXOFF;
+}
 
-		if (is_ofdm_rate(rate)) {
-			/*
-			 * In 11g and 11a, the OFDM mandatory rates
-			 * are 6, 12, and 24 Mbps
-			 */
-			if (rate >= BRCM_RATE_24M)
-				mandatory = BRCM_RATE_24M;
-			else if (rate >= BRCM_RATE_12M)
-				mandatory = BRCM_RATE_12M;
-			else
-				mandatory = BRCM_RATE_6M;
-		} else {
-			/* In 11b, all CCK rates are mandatory 1 - 11 Mbps */
-			mandatory = rate;
-		}
+/*
+ * Update all beacons for the system.
+ */
+void brcms_c_update_beacon(struct brcms_c_info *wlc)
+{
+	struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
 
-		br[rate] = mandatory;
-	}
+	if (bsscfg->up && !bsscfg->BSS)
+		/* Clear the soft intmask */
+		wlc->defmacintmask &= ~MI_BCNTPL;
 }
 
-static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate,
-				   u8 basic_rate)
+/* Write ssid into shared memory */
+static void
+brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
 {
-	u8 phy_rate, index;
-	u8 basic_phy_rate, basic_index;
-	u16 dir_table, basic_table;
-	u16 basic_ptr;
+	u8 *ssidptr = cfg->SSID;
+	u16 base = M_SSID;
+	u8 ssidbuf[IEEE80211_MAX_SSID_LEN];
 
-	/* Shared memory address for the table we are reading */
-	dir_table = is_ofdm_rate(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
+	/* padding the ssid with zero and copy it into shm */
+	memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN);
+	memcpy(ssidbuf, ssidptr, cfg->SSID_len);
 
-	/* Shared memory address for the table we are writing */
-	basic_table = is_ofdm_rate(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
+	brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN);
+	brcms_b_write_shm(wlc->hw, M_SSIDLEN, (u16) cfg->SSID_len);
+}
+
+static void
+brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
+			      struct brcms_bss_cfg *cfg,
+			      bool suspend)
+{
+	u16 prb_resp[BCN_TMPL_LEN / 2];
+	int len = BCN_TMPL_LEN;
 
 	/*
-	 * for a given rate, the LS-nibble of the PLCP SIGNAL field is
-	 * the index into the rate table.
+	 * write the probe response to hardware, or save in
+	 * the config structure
 	 */
-	phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
-	basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK;
-	index = phy_rate & 0xf;
-	basic_index = basic_phy_rate & 0xf;
 
-	/* Find the SHM pointer to the ACK rate entry by looking in the
-	 * Direct-map Table
-	 */
-	basic_ptr = brcms_b_read_shm(wlc->hw, (dir_table + basic_index * 2));
+	/* create the probe response template */
+	brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
+				 cfg, prb_resp, &len);
 
-	/* Update the SHM BSS-basic-rate-set mapping table with the pointer
-	 * to the correct basic rate for the given incoming rate
+	if (suspend)
+		brcms_c_suspend_mac_and_wait(wlc);
+
+	/* write the probe response into the template region */
+	brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
+				    (len + 3) & ~3, prb_resp);
+
+	/* write the length of the probe response frame (+PLCP/-FCS) */
+	brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len);
+
+	/* write the SSID and SSID length */
+	brcms_c_shm_ssid_upd(wlc, cfg);
+
+	/*
+	 * Write PLCP headers and durations for probe response frames
+	 * at all rates. Use the actual frame length covered by the
+	 * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table()
+	 * by subtracting the PLCP len and adding the FCS.
 	 */
-	brcms_b_write_shm(wlc->hw, (basic_table + index * 2), basic_ptr);
+	len += (-D11_PHY_HDR_LEN + FCS_LEN);
+	brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
+
+	if (suspend)
+		brcms_c_enable_mac(wlc);
 }
 
-static const struct brcms_c_rateset *
-brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc)
+void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
 {
-	const struct brcms_c_rateset *rs_dflt;
-
-	if (BRCMS_PHY_11N_CAP(wlc->band)) {
-		if (wlc->band->bandtype == BRCM_BAND_5G)
-			rs_dflt = &ofdm_mimo_rates;
-		else
-			rs_dflt = &cck_ofdm_mimo_rates;
-	} else if (wlc->band->gmode)
-		rs_dflt = &cck_ofdm_rates;
-	else
-		rs_dflt = &cck_rates;
+	struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
 
-	return rs_dflt;
+	/* update AP or IBSS probe responses */
+	if (bsscfg->up && !bsscfg->BSS)
+		brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
 }
 
-void brcms_c_set_ratetable(struct brcms_c_info *wlc)
+/* prepares pdu for transmission. returns BCM error codes */
+int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop)
 {
-	const struct brcms_c_rateset *rs_dflt;
-	struct brcms_c_rateset rs;
-	u8 rate, basic_rate;
-	uint i;
+	uint fifo;
+	struct d11txh *txh;
+	struct ieee80211_hdr *h;
+	struct scb *scb;
 
-	rs_dflt = brcms_c_rateset_get_hwrs(wlc);
+	txh = (struct d11txh *) (pdu->data);
+	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
 
-	brcms_c_rateset_copy(rs_dflt, &rs);
-	brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+	/* get the pkt queue info. This was put at brcms_c_sendctl or
+	 * brcms_c_send for PDU */
+	fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
 
-	/* walk the phy rate table and update SHM basic rate lookup table */
-	for (i = 0; i < rs.count; i++) {
-		rate = rs.rates[i] & BRCMS_RATE_MASK;
+	scb = NULL;
 
-		/* for a given rate brcms_basic_rate returns the rate at
-		 * which a response ACK/CTS should be sent.
-		 */
-		basic_rate = brcms_basic_rate(wlc, rate);
-		if (basic_rate == 0)
-			/* This should only happen if we are using a
-			 * restricted rateset.
-			 */
-			basic_rate = rs.rates[0] & BRCMS_RATE_MASK;
+	*fifop = fifo;
 
-		brcms_c_write_rate_shm(wlc, rate, basic_rate);
+	/* return if insufficient dma resources */
+	if (*wlc->core->txavail[fifo] < MAX_DMA_SEGS) {
+		/* Mark precedences related to this FIFO, unsendable */
+		/* A fifo is full. Clear precedences related to that FIFO */
+		wlc->tx_prec_map &= ~(wlc->fifo2prec_map[fifo]);
+		return -EBUSY;
 	}
+	return 0;
 }
 
-/*
- * Return true if the specified rate is supported by the specified band.
- * BRCM_BAND_AUTO indicates the current band.
- */
-bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band,
-		    bool verbose)
+int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
+			   uint *blocks)
 {
-	struct brcms_c_rateset *hw_rateset;
-	uint i;
+	if (fifo >= NFIFO)
+		return -EINVAL;
 
-	if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype))
-		hw_rateset = &wlc->band->hw_rateset;
-	else if (wlc->pub->_nbands > 1)
-		hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
-	else
-		/* other band specified and we are a single band device */
-		return false;
+	*blocks = wlc_hw->xmtfifo_sz[fifo];
 
-	/* check if this is a mimo rate */
-	if (is_mcs_rate(rspec)) {
-		if ((rspec & RSPEC_RATE_MASK) >= MCS_TABLE_SIZE)
-			goto error;
+	return 0;
+}
 
-		return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
-	}
+void
+brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
+		  const u8 *addr)
+{
+	brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr);
+	if (match_reg_offset == RCM_BSSID_OFFSET)
+		memcpy(wlc->bsscfg->BSSID, addr, ETH_ALEN);
+}
 
-	for (i = 0; i < hw_rateset->count; i++)
-		if (hw_rateset->rates[i] == rspec2rate(rspec))
-			return true;
- error:
-	if (verbose)
-		wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x "
-			  "not in hw_rateset\n", wlc->pub->unit, rspec);
+/*
+ * Flag 'scan in progress' to withhold dynamic phy calibration
+ */
+void brcms_c_scan_start(struct brcms_c_info *wlc)
+{
+	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
+}
 
-	return false;
+void brcms_c_scan_stop(struct brcms_c_info *wlc)
+{
+	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
 }
 
-void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
+void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
 {
-	const struct brcms_c_rateset *rs_dflt;
-	struct brcms_c_rateset rs;
-	u8 rate;
-	u16 entry_ptr;
-	u8 plcp[D11_PHY_HDR_LEN];
-	u16 dur, sifs;
-	uint i;
+	wlc->pub->associated = state;
+	wlc->bsscfg->associated = state;
+}
 
-	sifs = get_sifs(wlc->band);
+/*
+ * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
+ * AMPDU traffic, packets pending in hardware have to be invalidated so that
+ * when later on hardware releases them, they can be handled appropriately.
+ */
+void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
+			       struct ieee80211_sta *sta,
+			       void (*dma_callback_fn))
+{
+	struct dma_pub *dmah;
+	int i;
+	for (i = 0; i < NFIFO; i++) {
+		dmah = hw->di[i];
+		if (dmah != NULL)
+			dma_walk_packets(dmah, dma_callback_fn, sta);
+	}
+}
 
-	rs_dflt = brcms_c_rateset_get_hwrs(wlc);
+int brcms_c_get_curband(struct brcms_c_info *wlc)
+{
+	return wlc->band->bandunit;
+}
 
-	brcms_c_rateset_copy(rs_dflt, &rs);
-	brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
+{
+	/* flush packet queue when requested */
+	if (drop)
+		brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
 
-	/*
-	 * walk the phy rate table and update MAC core SHM
-	 * basic rate table entries
-	 */
-	for (i = 0; i < rs.count; i++) {
-		rate = rs.rates[i] & BRCMS_RATE_MASK;
+	/* wait for queue and DMA fifos to run dry */
+	while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0)
+		brcms_msleep(wlc->wl, 1);
+}
 
-		entry_ptr = brcms_b_rate_shm_offset(wlc->hw, rate);
+void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
+{
+	wlc->bcn_li_bcn = interval;
+	if (wlc->pub->up)
+		brcms_c_bcn_li_upd(wlc);
+}
 
-		/* Calculate the Probe Response PLCP for the given rate */
-		brcms_c_compute_plcp(wlc, rate, frame_len, plcp);
+int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr)
+{
+	uint qdbm;
 
-		/*
-		 * Calculate the duration of the Probe Response
-		 * frame plus SIFS for the MAC
-		 */
-		dur = (u16) brcms_c_calc_frame_time(wlc, rate,
-						BRCMS_LONG_PREAMBLE, frame_len);
-		dur += sifs;
+	/* Remove override bit and clip to max qdbm value */
+	qdbm = min_t(uint, txpwr * BRCMS_TXPWR_DB_FACTOR, 0xff);
+	return wlc_phy_txpower_set(wlc->band->pi, qdbm, false);
+}
 
-		/* Update the SHM Rate Table entry Probe Response values */
-		brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS,
-			      (u16) (plcp[0] + (plcp[1] << 8)));
-		brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS + 2,
-			      (u16) (plcp[2] + (plcp[3] << 8)));
-		brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_DUR_POS, dur);
-	}
+int brcms_c_get_tx_power(struct brcms_c_info *wlc)
+{
+	uint qdbm;
+	bool override;
+
+	wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override);
+
+	/* Return qdbm units */
+	return (int)(qdbm / BRCMS_TXPWR_DB_FACTOR);
 }
 
-/*	Max buffering needed for beacon template/prb resp template is 142 bytes.
- *
- *	PLCP header is 6 bytes.
- *	802.11 A3 header is 24 bytes.
- *	Max beacon frame body template length is 112 bytes.
- *	Max probe resp frame body template length is 110 bytes.
- *
- *      *len on input contains the max length of the packet available.
- *
- *	The *len value is set to the number of bytes in buf used, and starts
- *	with the PLCP and included up to, but not including, the 4 byte FCS.
- */
-static void
-brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
-			 u32 bcn_rspec,
-			 struct brcms_bss_cfg *cfg, u16 *buf, int *len)
+void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc)
 {
-	static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
-	struct cck_phy_hdr *plcp;
-	struct ieee80211_mgmt *h;
-	int hdr_len, body_len;
+	wlc->mpc = mpc;
+	brcms_c_radio_mpc_upd(wlc);
+}
 
-	hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
+{
+	struct d11rxhdr *rxh;
+	struct ieee80211_hdr *h;
+	uint len;
+	bool is_amsdu;
 
-	/* calc buffer size provided for frame body */
-	body_len = *len - hdr_len;
-	/* return actual size */
-	*len = hdr_len + body_len;
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
 
-	/* format PHY and MAC headers */
-	memset((char *)buf, 0, hdr_len);
+	/* frame starts with rxhdr */
+	rxh = (struct d11rxhdr *) (p->data);
 
-	plcp = (struct cck_phy_hdr *) buf;
+	/* strip off rxhdr */
+	skb_pull(p, BRCMS_HWRXOFF);
 
-	/*
-	 * PLCP for Probe Response frames are filled in from
-	 * core's rate table
-	 */
-	if (type == IEEE80211_STYPE_BEACON)
-		/* fill in PLCP */
-		brcms_c_compute_plcp(wlc, bcn_rspec,
-				 (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
-				 (u8 *) plcp);
+	/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
+	if (rxh->RxStatus1 & RXS_PBPRES) {
+		if (p->len < 2) {
+			wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of "
+				  "len %d\n", wlc->pub->unit, p->len);
+			goto toss;
+		}
+		skb_pull(p, 2);
+	}
 
-	/* "Regular" and 16 MBSS but not for 4 MBSS */
-	/* Update the phytxctl for the beacon based on the rspec */
-	brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
+	h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
+	len = p->len;
 
-	h = (struct ieee80211_mgmt *)&plcp[1];
+	if (rxh->RxStatus1 & RXS_FCSERR) {
+		if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
+			wiphy_err(wlc->wiphy, "FCSERR while scanning******* -"
+				  " tossing\n");
+			goto toss;
+		} else {
+			wiphy_err(wlc->wiphy, "RCSERR!!!\n");
+			goto toss;
+		}
+	}
 
-	/* fill in 802.11 header */
-	h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
+	/* check received pkt has at least frame control field */
+	if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control))
+		goto toss;
 
-	/* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
-	/* A1 filled in by MAC for prb resp, broadcast for bcn */
-	if (type == IEEE80211_STYPE_BEACON)
-		memcpy(&h->da, &ether_bcast, ETH_ALEN);
-	memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN);
-	memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
+	/* not supporting A-MSDU */
+	is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
+	if (is_amsdu)
+		goto toss;
 
-	/* SEQ filled in by MAC */
-}
+	brcms_c_recvctl(wlc, rxh, p);
+	return;
 
-int brcms_c_get_header_len(void)
-{
-	return TXOFF;
+ toss:
+	brcmu_pkt_buf_free_skb(p);
 }
 
+/* Process received frames */
 /*
- * Update all beacons for the system.
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
  */
-void brcms_c_update_beacon(struct brcms_c_info *wlc)
+static bool
+brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
 {
-	struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
+	struct sk_buff *p;
+	struct sk_buff *head = NULL;
+	struct sk_buff *tail = NULL;
+	uint n = 0;
+	uint bound_limit = bound ? RXBND : -1;
 
-	if (bsscfg->up && !bsscfg->BSS)
-		/* Clear the soft intmask */
-		wlc->defmacintmask &= ~MI_BCNTPL;
-}
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	/* gather received frames */
+	while ((p = dma_rx(wlc_hw->di[fifo]))) {
 
-/* Write ssid into shared memory */
-void brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
-{
-	u8 *ssidptr = cfg->SSID;
-	u16 base = M_SSID;
-	u8 ssidbuf[IEEE80211_MAX_SSID_LEN];
+		if (!tail)
+			head = tail = p;
+		else {
+			tail->prev = p;
+			tail = p;
+		}
 
-	/* padding the ssid with zero and copy it into shm */
-	memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN);
-	memcpy(ssidbuf, ssidptr, cfg->SSID_len);
+		/* !give others some time to run! */
+		if (++n >= bound_limit)
+			break;
+	}
 
-	brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN);
-	brcms_b_write_shm(wlc->hw, M_SSIDLEN, (u16) cfg->SSID_len);
+	/* post more rbufs */
+	dma_rxfill(wlc_hw->di[fifo]);
+
+	/* process each frame */
+	while ((p = head) != NULL) {
+		struct d11rxhdr_le *rxh_le;
+		struct d11rxhdr *rxh;
+		head = head->prev;
+		p->prev = NULL;
+
+		rxh_le = (struct d11rxhdr_le *)p->data;
+		rxh = (struct d11rxhdr *)p->data;
+
+		/* fixup rx header endianness */
+		rxh->RxFrameSize = le16_to_cpu(rxh_le->RxFrameSize);
+		rxh->PhyRxStatus_0 = le16_to_cpu(rxh_le->PhyRxStatus_0);
+		rxh->PhyRxStatus_1 = le16_to_cpu(rxh_le->PhyRxStatus_1);
+		rxh->PhyRxStatus_2 = le16_to_cpu(rxh_le->PhyRxStatus_2);
+		rxh->PhyRxStatus_3 = le16_to_cpu(rxh_le->PhyRxStatus_3);
+		rxh->PhyRxStatus_4 = le16_to_cpu(rxh_le->PhyRxStatus_4);
+		rxh->PhyRxStatus_5 = le16_to_cpu(rxh_le->PhyRxStatus_5);
+		rxh->RxStatus1 = le16_to_cpu(rxh_le->RxStatus1);
+		rxh->RxStatus2 = le16_to_cpu(rxh_le->RxStatus2);
+		rxh->RxTSFTime = le16_to_cpu(rxh_le->RxTSFTime);
+		rxh->RxChan = le16_to_cpu(rxh_le->RxChan);
+
+		brcms_c_recv(wlc_hw->wlc, p);
+	}
+
+	return n >= bound_limit;
 }
 
-void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
+/* second-level interrupt processing
+ *   Return true if another dpc needs to be re-scheduled. false otherwise.
+ *   Param 'bounded' indicates if applicable loops should be bounded.
+ */
+bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 {
-	struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
+	u32 macintstatus;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	struct d11regs __iomem *regs = wlc_hw->regs;
+	struct wiphy *wiphy = wlc->wiphy;
 
-	/* update AP or IBSS probe responses */
-	if (bsscfg->up && !bsscfg->BSS)
-		brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
+	if (brcms_deviceremoved(wlc)) {
+		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return false;
+	}
+
+	/* grab and clear the saved software intstatus bits */
+	macintstatus = wlc->macintstatus;
+	wlc->macintstatus = 0;
+
+	BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
+	       wlc_hw->unit, macintstatus);
+
+	WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
+
+	/* tx status */
+	if (macintstatus & MI_TFS) {
+		bool fatal;
+		if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
+			wlc->macintstatus |= MI_TFS;
+		if (fatal) {
+			wiphy_err(wiphy, "MI_TFS: fatal\n");
+			goto fatal;
+		}
+	}
+
+	if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
+		brcms_c_tbtt(wlc);
+
+	/* ATIM window end */
+	if (macintstatus & MI_ATIMWINEND) {
+		BCMMSG(wlc->wiphy, "end of ATIM window\n");
+		OR_REG(&regs->maccommand, wlc->qvalid);
+		wlc->qvalid = 0;
+	}
+
+	/*
+	 * received data or control frame, MI_DMAINT is
+	 * indication of RX_FIFO interrupt
+	 */
+	if (macintstatus & MI_DMAINT)
+		if (brcms_b_recv(wlc_hw, RX_FIFO, bounded))
+			wlc->macintstatus |= MI_DMAINT;
+
+	/* noise sample collected */
+	if (macintstatus & MI_BG_NOISE)
+		wlc_phy_noise_sample_intr(wlc_hw->band->pi);
+
+	if (macintstatus & MI_GP0) {
+		wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
+			"(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
+
+		printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
+					__func__, wlc_hw->sih->chip,
+					wlc_hw->sih->chiprev);
+		/* big hammer */
+		brcms_init(wlc->wl);
+	}
+
+	/* gptimer timeout */
+	if (macintstatus & MI_TO)
+		W_REG(&regs->gptimer, 0);
+
+	if (macintstatus & MI_RFDISABLE) {
+		BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
+		       " RF Disable Input\n", wlc_hw->unit);
+		brcms_rfkill_set_hw_state(wlc->wl);
+	}
+
+	/* send any enq'd tx packets. Just makes sure to jump start tx */
+	if (!pktq_empty(&wlc->pkt_queue->q))
+		brcms_c_send_q(wlc);
+
+	/* it isn't done and needs to be resched if macintstatus is non-zero */
+	return wlc->macintstatus != 0;
+
+ fatal:
+	brcms_init(wlc->wl);
+	return wlc->macintstatus != 0;
 }
 
-void
-brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
-			      struct brcms_bss_cfg *cfg,
-			      bool suspend)
+void brcms_c_init(struct brcms_c_info *wlc)
 {
-	u16 prb_resp[BCN_TMPL_LEN / 2];
-	int len = BCN_TMPL_LEN;
+	struct d11regs __iomem *regs;
+	u16 chanspec;
+	bool mute = false;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+	regs = wlc->regs;
 
 	/*
-	 * write the probe response to hardware, or save in
-	 * the config structure
+	 * This will happen if a big-hammer was executed. In
+	 * that case, we want to go back to the channel that
+	 * we were on and not new channel
 	 */
+	if (wlc->pub->associated)
+		chanspec = wlc->home_chanspec;
+	else
+		chanspec = brcms_c_init_chanspec(wlc);
 
-	/* create the probe response template */
-	brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
-				 cfg, prb_resp, &len);
+	brcms_b_init(wlc->hw, chanspec, mute);
 
-	if (suspend)
-		brcms_c_suspend_mac_and_wait(wlc);
+	/* update beacon listen interval */
+	brcms_c_bcn_li_upd(wlc);
 
-	/* write the probe response into the template region */
-	brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
-				    (len + 3) & ~3, prb_resp);
+	/* write ethernet address to core */
+	brcms_c_set_mac(wlc->bsscfg);
+	brcms_c_set_bssid(wlc->bsscfg);
 
-	/* write the length of the probe response frame (+PLCP/-FCS) */
-	brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len);
+	/* Update tsf_cfprep if associated and up */
+	if (wlc->pub->associated && wlc->bsscfg->up) {
+		u32 bi;
 
-	/* write the SSID and SSID length */
-	brcms_c_shm_ssid_upd(wlc, cfg);
+		/* get beacon period and convert to uS */
+		bi = wlc->bsscfg->current_bss->beacon_period << 10;
+		/*
+		 * update since init path would reset
+		 * to default value
+		 */
+		W_REG(&regs->tsf_cfprep,
+		      (bi << CFPREP_CBI_SHIFT));
+
+		/* Update maccontrol PM related bits */
+		brcms_c_set_ps_ctrl(wlc);
+	}
+
+	brcms_c_bandinit_ordered(wlc, chanspec);
+
+	/* init probe response timeout */
+	brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout);
+
+	/* init max burst txop (framebursting) */
+	brcms_b_write_shm(wlc->hw, M_MBURST_TXOP,
+		      (wlc->
+		       _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
+
+	/* initialize maximum allowed duty cycle */
+	brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
+	brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
 
 	/*
-	 * Write PLCP headers and durations for probe response frames
-	 * at all rates. Use the actual frame length covered by the
-	 * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table()
-	 * by subtracting the PLCP len and adding the FCS.
+	 * Update some shared memory locations related to
+	 * max AMPDU size allowed to received
 	 */
-	len += (-D11_PHY_HDR_LEN + FCS_LEN);
-	brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
+	brcms_c_ampdu_shm_upd(wlc->ampdu);
 
-	if (suspend)
-		brcms_c_enable_mac(wlc);
-}
+	/* band-specific inits */
+	brcms_c_bsinit(wlc);
 
-/* prepares pdu for transmission. returns BCM error codes */
-int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop)
-{
-	uint fifo;
-	struct d11txh *txh;
-	struct ieee80211_hdr *h;
-	struct scb *scb;
+	/* Enable EDCF mode (while the MAC is suspended) */
+	OR_REG(&regs->ifs_ctl, IFS_USEEDCF);
+	brcms_c_edcf_setparams(wlc, false);
 
-	txh = (struct d11txh *) (pdu->data);
-	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
+	/* Init precedence maps for empty FIFOs */
+	brcms_c_tx_prec_map_init(wlc);
 
-	/* get the pkt queue info. This was put at brcms_c_sendctl or
-	 * brcms_c_send for PDU */
-	fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
+	/* read the ucode version if we have not yet done so */
+	if (wlc->ucode_rev == 0) {
+		wlc->ucode_rev =
+		    brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16);
+		wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR);
+	}
 
-	scb = NULL;
+	/* ..now really unleash hell (allow the MAC out of suspend) */
+	brcms_c_enable_mac(wlc);
 
-	*fifop = fifo;
+	/* clear tx flow control */
+	brcms_c_txflowcontrol_reset(wlc);
 
-	/* return if insufficient dma resources */
-	if (*wlc->core->txavail[fifo] < MAX_DMA_SEGS) {
-		/* Mark precedences related to this FIFO, unsendable */
-		/* A fifo is full. Clear precedences related to that FIFO */
-		wlc->tx_prec_map &= ~(wlc->fifo2prec_map[fifo]);
-		return -EBUSY;
-	}
-	return 0;
-}
+	/* enable the RF Disable Delay timer */
+	W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
 
-void brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs)
-{
-	brcms_c_rateset_default(rs, NULL, wlc->band->phytype,
-		wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL,
-		(bool) (wlc->pub->_n_enab & SUPPORT_11N),
-		brcms_chspec_bw(wlc->default_bss->chanspec),
-		wlc->stf->txstreams);
-}
+	/* initialize mpc delay */
+	wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
 
-/* Copy a buffer to shared memory.
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- */
-void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset, const void *buf,
-			int len)
-{
-	brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
+	/*
+	 * Initialize WME parameters; if they haven't been set by some other
+	 * mechanism (IOVar, etc) then read them from the hardware.
+	 */
+	if (GFIELD(wlc->wme_retries[0], EDCF_SHORT) == 0) {
+		/* Uninitialized; read from HW */
+		int ac;
+
+		for (ac = 0; ac < AC_COUNT; ac++)
+			wlc->wme_retries[ac] =
+			    brcms_b_read_shm(wlc->hw, M_AC_TXLMT_ADDR(ac));
+	}
 }
 
-int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
-			   uint *blocks)
+/*
+ * The common driver entry routine. Error codes should be unique
+ */
+struct brcms_c_info *
+brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
+	       bool piomode, void __iomem *regsva, struct pci_dev *btparam,
+	       uint *perr)
 {
-	if (fifo >= NFIFO)
-		return -EINVAL;
+	struct brcms_c_info *wlc;
+	uint err = 0;
+	uint i, j;
+	struct brcms_pub *pub;
 
-	*blocks = wlc_hw->xmtfifo_sz[fifo];
+	/* allocate struct brcms_c_info state and its substructures */
+	wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device);
+	if (wlc == NULL)
+		goto fail;
+	wlc->wiphy = wl->wiphy;
+	pub = wlc->pub;
 
-	return 0;
-}
+#if defined(BCMDBG)
+	wlc_info_dbg = wlc;
+#endif
 
-void
-brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
-		  const u8 *addr)
-{
-	brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr);
-	if (match_reg_offset == RCM_BSSID_OFFSET)
-		memcpy(wlc->bsscfg->BSSID, addr, ETH_ALEN);
-}
+	wlc->band = wlc->bandstate[0];
+	wlc->core = wlc->corestate;
+	wlc->wl = wl;
+	pub->unit = unit;
+	pub->_piomode = piomode;
+	wlc->bandinit_pending = false;
 
-/* check for the particular priority flow control bit being set */
-bool
-brcms_c_txflowcontrol_prio_isset(struct brcms_c_info *wlc,
-				 struct brcms_txq_info *q,
-				 int prio)
-{
-	uint prio_mask;
+	/* populate struct brcms_c_info with default values  */
+	brcms_c_info_init(wlc, unit);
 
-	if (prio == ALLPRIO)
-		prio_mask = TXQ_STOP_FOR_PRIOFC_MASK;
-	else
-		prio_mask = NBITVAL(prio);
+	/* update sta/ap related parameters */
+	brcms_c_ap_upd(wlc);
 
-	return (q->stopped & prio_mask) == prio_mask;
-}
+	/*
+	 * low level attach steps(all hw accesses go
+	 * inside, no more in rest of the attach)
+	 */
+	err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva,
+			     btparam);
+	if (err)
+		goto fail;
 
-/* propagate the flow control to all interfaces using the given tx queue */
-void brcms_c_txflowcontrol(struct brcms_c_info *wlc,
-			   struct brcms_txq_info *qi,
-			   bool on, int prio)
-{
-	uint prio_bits;
-	uint cur_bits;
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, OFF);
 
-	BCMMSG(wlc->wiphy, "flow control kicks in\n");
+	pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band);
 
-	if (prio == ALLPRIO)
-		prio_bits = TXQ_STOP_FOR_PRIOFC_MASK;
-	else
-		prio_bits = NBITVAL(prio);
+	/* disable allowed duty cycle */
+	wlc->tx_duty_cycle_ofdm = 0;
+	wlc->tx_duty_cycle_cck = 0;
 
-	cur_bits = qi->stopped & prio_bits;
+	brcms_c_stf_phy_chain_calc(wlc);
 
-	/* Check for the case of no change and return early
-	 * Otherwise update the bit and continue
-	 */
-	if (on) {
-		if (cur_bits == prio_bits)
-			return;
+	/* txchain 1: txant 0, txchain 2: txant 1 */
+	if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
+		wlc->stf->txant = wlc->stf->hw_txchain - 1;
 
-		mboolset(qi->stopped, prio_bits);
-	} else {
-		if (cur_bits == 0)
-			return;
+	/* push to BMAC driver */
+	wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
+			       wlc->stf->hw_rxchain);
 
-		mboolclr(qi->stopped, prio_bits);
-	}
+	/* pull up some info resulting from the low attach */
+	for (i = 0; i < NFIFO; i++)
+		wlc->core->txavail[i] = wlc->hw->txavail[i];
 
-	/* If there is a flow control override we will not change the external
-	 * flow control state.
-	 */
-	if (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK)
-		return;
+	memcpy(&wlc->perm_etheraddr, &wlc->hw->etheraddr, ETH_ALEN);
+	memcpy(&pub->cur_etheraddr, &wlc->hw->etheraddr, ETH_ALEN);
 
-	brcms_c_txflowcontrol_signal(wlc, qi, on, prio);
-}
+	for (j = 0; j < wlc->pub->_nbands; j++) {
+		wlc->band = wlc->bandstate[j];
 
-void
-brcms_c_txflowcontrol_override(struct brcms_c_info *wlc,
-			       struct brcms_txq_info *qi,
-			       bool on, uint override)
-{
-	uint prev_override;
+		if (!brcms_c_attach_stf_ant_init(wlc)) {
+			err = 24;
+			goto fail;
+		}
 
-	prev_override = (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK);
+		/* default contention windows size limits */
+		wlc->band->CWmin = APHY_CWMIN;
+		wlc->band->CWmax = PHY_CWMAX;
 
-	/* Update the flow control bits and do an early return if there is
-	 * no change in the external flow control state.
-	 */
-	if (on) {
-		mboolset(qi->stopped, override);
-		/* if there was a previous override bit on, then setting this
-		 * makes no difference.
-		 */
-		if (prev_override)
-			return;
+		/* init gmode value */
+		if (wlc->band->bandtype == BRCM_BAND_2G) {
+			wlc->band->gmode = GMODE_AUTO;
+			brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER,
+					   wlc->band->gmode);
+		}
 
-		brcms_c_txflowcontrol_signal(wlc, qi, ON, ALLPRIO);
-	} else {
-		mboolclr(qi->stopped, override);
-		/* clearing an override bit will only make a difference for
-		 * flow control if it was the only bit set. For any other
-		 * override setting, just return
-		 */
-		if (prev_override != override)
-			return;
+		/* init _n_enab supported mode */
+		if (BRCMS_PHY_11N_CAP(wlc->band)) {
+			pub->_n_enab = SUPPORT_11N;
+			brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
+						   ((pub->_n_enab ==
+						     SUPPORT_11N) ? WL_11N_2x2 :
+						    WL_11N_3x3));
+		}
 
-		if (qi->stopped == 0) {
-			brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
-		} else {
-			int prio;
+		/* init per-band default rateset, depend on band->gmode */
+		brcms_default_rateset(wlc, &wlc->band->defrateset);
 
-			for (prio = MAXPRIO; prio >= 0; prio--) {
-				if (!mboolisset(qi->stopped, NBITVAL(prio)))
-					brcms_c_txflowcontrol_signal(
-						wlc, qi, OFF, prio);
-			}
-		}
+		/* fill in hw_rateset */
+		brcms_c_rateset_filter(&wlc->band->defrateset,
+				   &wlc->band->hw_rateset, false,
+				   BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
+				   (bool) (wlc->pub->_n_enab & SUPPORT_11N));
 	}
-}
 
-/*
- * Flag 'scan in progress' to withhold dynamic phy calibration
- */
-void brcms_c_scan_start(struct brcms_c_info *wlc)
-{
-	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
-}
+	/*
+	 * update antenna config due to
+	 * wlc->stf->txant/txchain/ant_rx_ovr change
+	 */
+	brcms_c_stf_phy_txant_upd(wlc);
 
-void brcms_c_scan_stop(struct brcms_c_info *wlc)
-{
-	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
-}
+	/* attach each modules */
+	err = brcms_c_attach_module(wlc);
+	if (err != 0)
+		goto fail;
 
-void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
-{
-	wlc->pub->associated = state;
-	wlc->bsscfg->associated = state;
-}
+	if (!brcms_c_timers_init(wlc, unit)) {
+		wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit,
+			  __func__);
+		err = 32;
+		goto fail;
+	}
 
-/*
- * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
- * AMPDU traffic, packets pending in hardware have to be invalidated so that
- * when later on hardware releases them, they can be handled appropriately.
- */
-void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
-			       struct ieee80211_sta *sta,
-			       void (*dma_callback_fn))
-{
-	struct dma_pub *dmah;
-	int i;
-	for (i = 0; i < NFIFO; i++) {
-		dmah = hw->di[i];
-		if (dmah != NULL)
-			dma_walk_packets(dmah, dma_callback_fn, sta);
+	/* depend on rateset, gmode */
+	wlc->cmi = brcms_c_channel_mgr_attach(wlc);
+	if (!wlc->cmi) {
+		wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed"
+			  "\n", unit, __func__);
+		err = 33;
+		goto fail;
 	}
-}
 
-int brcms_c_get_curband(struct brcms_c_info *wlc)
-{
-	return wlc->band->bandunit;
-}
+	/* init default when all parameters are ready, i.e. ->rateset */
+	brcms_c_bss_default_init(wlc);
 
-void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
-{
-	/* flush packet queue when requested */
-	if (drop)
-		brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
+	/*
+	 * Complete the wlc default state initializations..
+	 */
 
-	/* wait for queue and DMA fifos to run dry */
-	while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0)
-		brcms_msleep(wlc->wl, 1);
-}
+	/* allocate our initial queue */
+	wlc->pkt_queue = brcms_c_txq_alloc(wlc);
+	if (wlc->pkt_queue == NULL) {
+		wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n",
+			  unit, __func__);
+		err = 100;
+		goto fail;
+	}
 
-void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
-{
-	wlc->bcn_li_bcn = interval;
-	if (wlc->pub->up)
-		brcms_c_bcn_li_upd(wlc);
-}
+	wlc->bsscfg->wlc = wlc;
 
-int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr)
-{
-	uint qdbm;
+	wlc->mimoft = FT_HT;
+	wlc->mimo_40txbw = AUTO;
+	wlc->ofdm_40txbw = AUTO;
+	wlc->cck_40txbw = AUTO;
+	brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G);
 
-	/* Remove override bit and clip to max qdbm value */
-	qdbm = min_t(uint, txpwr * BRCMS_TXPWR_DB_FACTOR, 0xff);
-	return wlc_phy_txpower_set(wlc->band->pi, qdbm, false);
-}
+	/* Set default values of SGI */
+	if (BRCMS_SGI_CAP_PHY(wlc)) {
+		brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
+					       BRCMS_N_SGI_40));
+	} else if (BRCMS_ISSSLPNPHY(wlc->band)) {
+		brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
+					       BRCMS_N_SGI_40));
+	} else {
+		brcms_c_ht_update_sgi_rx(wlc, 0);
+	}
 
-int brcms_c_get_tx_power(struct brcms_c_info *wlc)
-{
-	uint qdbm;
-	bool override;
+	/* initialize radio_mpc_disable according to wlc->mpc */
+	brcms_c_radio_mpc_upd(wlc);
+	brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail);
 
-	wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override);
+	if (perr)
+		*perr = 0;
 
-	/* Return qdbm units */
-	return (int)(qdbm / BRCMS_TXPWR_DB_FACTOR);
-}
+	return wlc;
 
-void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc)
-{
-	wlc->mpc = mpc;
-	brcms_c_radio_mpc_upd(wlc);
+ fail:
+	wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n",
+		  unit, __func__, err);
+	if (wlc)
+		brcms_c_detach(wlc);
+
+	if (perr)
+		*perr = err;
+	return NULL;
 }
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index 7a2554f..c0e0fcf 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
@@ -653,9 +653,6 @@ struct brcms_bss_cfg {
 	struct brcms_bss_info *current_bss;
 };
 
-extern void brcms_c_fatal_error(struct brcms_c_info *wlc);
-extern void brcms_b_rpc_watchdog(struct brcms_c_info *wlc);
-extern void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p);
 extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo,
 			   struct sk_buff *p,
 			   bool commit, s8 txpktpend);
@@ -663,47 +660,22 @@ extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo,
 				    s8 txpktpend);
 extern void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb,
 			    struct sk_buff *sdu, uint prec);
-extern void brcms_c_info_init(struct brcms_c_info *wlc, int unit);
 extern void brcms_c_print_txstatus(struct tx_status *txs);
 extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
 		   uint *blocks);
 
 #if defined(BCMDBG)
-extern void brcms_c_print_rxh(struct d11rxhdr *rxh);
 extern void brcms_c_print_txdesc(struct d11txh *txh);
 #else
 #define brcms_c_print_txdesc(a)
 #endif
 
-extern void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit);
-extern void brcms_c_coredisable(struct brcms_hardware *wlc_hw);
-
-extern bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rate,
-			       int band, bool verbose);
-extern void brcms_c_ap_upd(struct brcms_c_info *wlc);
-
-/* helper functions */
-extern void brcms_c_shm_ssid_upd(struct brcms_c_info *wlc,
-				 struct brcms_bss_cfg *cfg);
 extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
-
 extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc,
 					   bool promisc);
-extern void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc);
-extern void brcms_c_mac_promisc(struct brcms_c_info *wlc);
-extern void brcms_c_txflowcontrol(struct brcms_c_info *wlc,
-				  struct brcms_txq_info *qi,
-				  bool on, int prio);
-extern void brcms_c_txflowcontrol_override(struct brcms_c_info *wlc,
-				       struct brcms_txq_info *qi,
-				       bool on, uint override);
-extern bool brcms_c_txflowcontrol_prio_isset(struct brcms_c_info *wlc,
-					     struct brcms_txq_info *qi,
-					     int prio);
 extern void brcms_c_send_q(struct brcms_c_info *wlc);
 extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu,
 			    uint *fifo);
-
 extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
 				uint mac_len);
 extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc,
@@ -715,82 +687,26 @@ extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
 				      u8 rts_preamble_type,
 				      u8 frame_preamble_type, uint frame_len,
 				      bool ba);
-
-extern void brcms_c_tbtt(struct brcms_c_info *wlc);
 extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
 			       struct ieee80211_sta *sta,
 			       void (*dma_callback_fn));
-
-/* Shared memory access */
-extern void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset,
-			       const void *buf, int len);
-
 extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
-
 extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
-extern void brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
-					  struct brcms_bss_cfg *cfg,
-					  bool suspend);
-extern bool brcms_c_ismpc(struct brcms_c_info *wlc);
-extern bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc);
-extern void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc);
-extern bool brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
-			      struct sk_buff *pkt, int prec, bool head);
-extern u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec);
-extern void brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rate,
-				 uint length, u8 *plcp);
-extern uint brcms_c_calc_frame_time(struct brcms_c_info *wlc,
-				    u32 ratespec,
-				    u8 preamble_type, uint mac_len);
-
-extern void brcms_c_set_chanspec(struct brcms_c_info *wlc,
-				 u16 chanspec);
-
-extern bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit);
-
 extern int brcms_c_set_nmode(struct brcms_c_info *wlc);
-extern void brcms_c_mimops_action_ht_send(struct brcms_c_info *wlc,
-				      struct brcms_bss_cfg *bsscfg,
-				      u8 mimops_mode);
-
-extern void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot);
-extern void brcms_c_set_bssid(struct brcms_bss_cfg *cfg);
-extern void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend);
-
-extern void brcms_c_set_ratetable(struct brcms_c_info *wlc);
-extern int brcms_c_set_mac(struct brcms_bss_cfg *cfg);
 extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
 					  u32 bcn_rate);
-extern void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc,
-					   uint frame_len);
-extern u32 brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc,
-					     struct brcms_c_rateset *rs);
-extern void brcms_c_radio_disable(struct brcms_c_info *wlc);
-extern void brcms_c_bcn_li_upd(struct brcms_c_info *wlc);
-extern void brcms_c_set_home_chanspec(struct brcms_c_info *wlc,
-				      u16 chanspec);
-extern bool brcms_c_ps_allowed(struct brcms_c_info *wlc);
-extern bool brcms_c_stay_awake(struct brcms_c_info *wlc);
-
 extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw,
 				     u8 antsel_type);
-
-/* chanspec, ucode interface */
 extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw,
 				  u16 chanspec,
 				  bool mute, struct txpwr_limits *txpwr);
-
 extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset,
 			      u16 v);
 extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
-
 extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask,
 			u16 val, int bands);
-
 extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
-
 extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
-
 extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
 extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
 extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index 3942f47..37bb2dc 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
@@ -563,7 +563,7 @@ struct brcms_antselcfg {
 };
 
 /* common functions for every port */
-struct brcms_c_info *
+extern struct brcms_c_info *
 brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
 	       bool piomode, void __iomem *regsva, struct pci_dev *btparam,
 	       uint *perr);
@@ -585,14 +585,9 @@ extern void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc,
 				     struct sk_buff *sdu,
 				     struct ieee80211_hw *hw);
 extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid);
-
-/* helper functions */
-extern void brcms_c_statsupd(struct brcms_c_info *wlc);
 extern void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx,
 				   int val);
 extern int brcms_c_get_header_len(void);
-extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc,
-					   bool promisc);
 extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc,
 				  int match_reg_offset,
 				  const u8 *addr);
@@ -600,26 +595,12 @@ extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
 			      const struct ieee80211_tx_queue_params *arg,
 			      bool suspend);
 extern struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc);
-
-/* common functions for every port */
-extern void brcms_c_mhf(struct brcms_c_info *wlc, u8 idx, u16 mask, u16 val,
-		    int bands);
-extern void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
-				     struct brcms_c_rateset *rateset);
-extern void brcms_default_rateset(struct brcms_c_info *wlc,
-				  struct brcms_c_rateset *rs);
-
 extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
 			    struct ieee80211_sta *sta, u16 tid);
 extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
 					 u8 ba_wsize, uint max_rx_ampdu_bytes);
 extern char *getvar(struct si_pub *sih, enum brcms_srom_id id);
 extern int getintvar(struct si_pub *sih, enum brcms_srom_id id);
-
-/* wlc_phy.c helper functions */
-extern void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc);
-extern void brcms_c_mctrl(struct brcms_c_info *wlc, u32 mask, u32 val);
-
 extern int brcms_c_module_register(struct brcms_pub *pub,
 				   const char *name, struct brcms_info *hdl,
 				   int (*down_fn)(void *handle));
@@ -633,23 +614,21 @@ extern void brcms_c_scan_stop(struct brcms_c_info *wlc);
 extern int brcms_c_get_curband(struct brcms_c_info *wlc);
 extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc,
 					   bool drop);
-
-int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
-int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
-void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
+extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
+extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
+extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
 				 struct brcm_rateset *currs);
-int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs);
-int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period);
-u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx);
-void brcms_c_set_shortslot_override(struct brcms_c_info *wlc,
+extern int brcms_c_set_rateset(struct brcms_c_info *wlc,
+					struct brcm_rateset *rs);
+extern int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period);
+extern u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx);
+extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc,
 				    s8 sslot_override);
-void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval);
-int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
-int brcms_c_get_tx_power(struct brcms_c_info *wlc);
-void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc);
-
-/* helper functions */
+extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
+					u8 interval);
+extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
+extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
+extern void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc);
 extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
-extern bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc);
 
 #endif				/* _BRCM_PUB_H_ */
-- 
1.7.4.1



^ permalink raw reply related

* [PATCH 15/22] brcm80211: removed unused functions
From: Arend van Spriel @ 2011-10-12 18:51 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Alwin Beukers, Arend van Spriel
In-Reply-To: <1318445492-24207-1-git-send-email-arend@broadcom.com>

From: Alwin Beukers <alwin@broadcom.com>

Removed brcmu_bitcount, brcmu_mhz2channel, brcmu_chspec_ctlchan.

Reported-by: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: Roland Vossen <rvossen@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmsmac/stf.c      |    2 -
 drivers/net/wireless/brcm80211/brcmutil/utils.c    |   14 ---
 drivers/net/wireless/brcm80211/brcmutil/wifi.c     |   93 --------------------
 .../net/wireless/brcm80211/include/brcmu_utils.h   |    1 -
 .../net/wireless/brcm80211/include/brcmu_wifi.h    |   28 ------
 5 files changed, 0 insertions(+), 138 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/stf.c b/drivers/net/wireless/brcm80211/brcmsmac/stf.c
index f1bd1bf..d8f528e 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/stf.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.c
@@ -30,8 +30,6 @@
 #define BRCMS_STF_SS_STBC_RX(wlc) (BRCMS_ISNPHY(wlc->band) && \
 	NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6))
 
-#define BRCMS_BITSCNT(x)	brcmu_bitcount((u8 *)&(x), sizeof(u8))
-
 #define NSTS_1	1
 #define NSTS_2	2
 #define NSTS_3	3
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index e96bdbf..990cb2e 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -585,17 +585,3 @@ u8 brcmu_mw_to_qdbm(u16 mw)
 }
 EXPORT_SYMBOL(brcmu_mw_to_qdbm);
 
-uint brcmu_bitcount(u8 *bitmap, uint length)
-{
-	uint bitcount = 0, i;
-	u8 tmp;
-	for (i = 0; i < length; i++) {
-		tmp = bitmap[i];
-		while (tmp) {
-			bitcount++;
-			tmp &= (tmp - 1);
-		}
-	}
-	return bitcount;
-}
-EXPORT_SYMBOL(brcmu_bitcount);
diff --git a/drivers/net/wireless/brcm80211/brcmutil/wifi.c b/drivers/net/wireless/brcm80211/brcmutil/wifi.c
index 509e25c..e8d3bf2 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/wifi.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/wifi.c
@@ -41,96 +41,3 @@ bool brcmu_chspec_malformed(u16 chanspec)
 	return false;
 }
 EXPORT_SYMBOL(brcmu_chspec_malformed);
-
-/*
- * This function returns the channel number that control traffic is being sent
- * on, for legacy channels this is just the channel number, for 40MHZ channels
- * it is the upper or lower 20MHZ sideband depending on the chanspec selected.
- */
-u8 brcmu_chspec_ctlchan(u16 chspec)
-{
-	u8 ctl_chan;
-
-	/* Is there a sideband ? */
-	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) {
-		return CHSPEC_CHANNEL(chspec);
-	} else {
-		/*
-		 * we only support 40MHZ with sidebands. chanspec channel holds
-		 * the centre frequency, use that and the side band information
-		 * to reconstruct the control channel number
-		 */
-		if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
-			/*
-			 * control chan is the upper 20 MHZ SB of the
-			 * 40MHZ channel
-			 */
-			ctl_chan = upper_20_sb(CHSPEC_CHANNEL(chspec));
-		else
-			/*
-			 * control chan is the lower 20 MHZ SB of the
-			 * 40MHZ channel
-			 */
-			ctl_chan = lower_20_sb(CHSPEC_CHANNEL(chspec));
-	}
-
-	return ctl_chan;
-}
-EXPORT_SYMBOL(brcmu_chspec_ctlchan);
-
-/*
- * Return the channel number for a given frequency and base frequency.
- * The returned channel number is relative to the given base frequency.
- * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
- * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
- *
- * Frequency is specified in MHz.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- *
- * The returned channel will be in the range [1, 14] in the 2.4 GHz band
- * and [0, 200] otherwise.
- * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
- * frequency is not a 2.4 GHz channel, or if the frequency is not and even
- * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-int brcmu_mhz2channel(uint freq, uint start_factor)
-{
-	int ch = -1;
-	uint base;
-	int offset;
-
-	/* take the default channel start frequency */
-	if (start_factor == 0) {
-		if (freq >= 2400 && freq <= 2500)
-			start_factor = WF_CHAN_FACTOR_2_4_G;
-		else if (freq >= 5000 && freq <= 6000)
-			start_factor = WF_CHAN_FACTOR_5_G;
-	}
-
-	if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G)
-		return 14;
-
-	base = start_factor / 2;
-
-	/* check that the frequency is in 1GHz range of the base */
-	if ((freq < base) || (freq > base + 1000))
-		return -1;
-
-	offset = freq - base;
-	ch = offset / 5;
-
-	/* check that frequency is a 5MHz multiple from the base */
-	if (offset != (ch * 5))
-		return -1;
-
-	/* restricted channel range check for 2.4G */
-	if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13))
-		return -1;
-
-	return ch;
-}
-EXPORT_SYMBOL(brcmu_mhz2channel);
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
index a7d3df2..96f05d7 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -218,6 +218,5 @@ extern u8 brcmu_mw_to_qdbm(u16 mw);
 
 extern uint brcmu_mkiovar(char *name, char *data, uint datalen,
 			  char *buf, uint len);
-extern uint brcmu_bitcount(u8 *bitmap, uint bytelength);
 
 #endif				/* _BRCMU_UTILS_H_ */
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
index 452bd42..5b1aca7 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
@@ -176,34 +176,6 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
  */
 extern bool brcmu_chspec_malformed(u16 chanspec);
 
-/*
- * This function returns the channel number that control traffic is being sent
- * on, for legacy channels this is just the channel number, for 40MHZ channels
- * it is the upper or lower 20MHZ sideband depending on the chanspec selected.
- */
-extern u8 brcmu_chspec_ctlchan(u16 chspec);
-
-/*
- * Return the channel number for a given frequency and base frequency.
- * The returned channel number is relative to the given base frequency.
- * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
- * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
- *
- * Frequency is specified in MHz.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- *
- * The returned channel will be in the range [1, 14] in the 2.4 GHz band
- * and [0, 200] otherwise.
- * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
- * frequency is not a 2.4 GHz channel, or if the frequency is not and even
- * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-extern int brcmu_mhz2channel(uint freq, uint start_factor);
-
 /* Enumerate crypto algorithms */
 #define	CRYPTO_ALGO_OFF			0
 #define	CRYPTO_ALGO_WEP1		1
-- 
1.7.4.1



^ permalink raw reply related

* [PATCH 18/22] brcm80211: moved function brcmu_parse_tlvs
From: Arend van Spriel @ 2011-10-12 18:51 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Alwin Beukers, Arend van Spriel
In-Reply-To: <1318445492-24207-1-git-send-email-arend@broadcom.com>

From: Alwin Beukers <alwin@broadcom.com>

Moved the brcmu_parse_tlvs function and brcmu_tlv structure into
the only file using them. Names were adjusted accordingly.

Reported-by: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: Roland Vossen <rvossen@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |   39 +++++++++++++++++++-
 drivers/net/wireless/brcm80211/brcmutil/utils.c    |   30 ---------------
 .../net/wireless/brcm80211/include/brcmu_utils.h   |   10 -----
 3 files changed, 37 insertions(+), 42 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index db9176d..857b328 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -247,6 +247,13 @@ static const u32 __wl_cipher_suites[] = {
 	WLAN_CIPHER_SUITE_AES_CMAC,
 };
 
+/* tag_ID/length/value_buffer tuple */
+struct brcmf_tlv {
+	u8 id;
+	u8 len;
+	u8 data[1];
+};
+
 /* Quarter dBm units to mW
  * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
  * Table is offset so the last entry is largest mW value that fits in
@@ -2151,11 +2158,39 @@ static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
 	return cfg_priv->conf->mode == WL_MODE_IBSS;
 }
 
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
+{
+	struct brcmf_tlv *elt;
+	int totlen;
+
+	elt = (struct brcmf_tlv *) buf;
+	totlen = buflen;
+
+	/* find tagged parameter */
+	while (totlen >= 2) {
+		int len = elt->len;
+
+		/* validate remaining totlen */
+		if ((elt->id == key) && (totlen >= (len + 2)))
+			return elt;
+
+		elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2));
+		totlen -= (len + 2);
+	}
+
+	return NULL;
+}
+
 static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
 {
 	struct brcmf_bss_info *bi;
 	struct brcmf_ssid *ssid;
-	struct brcmu_tlv *tim;
+	struct brcmf_tlv *tim;
 	u16 beacon_interval;
 	u8 dtim_period;
 	size_t ie_len;
@@ -2185,7 +2220,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
 	ie_len = le32_to_cpu(bi->ie_length);
 	beacon_interval = le16_to_cpu(bi->beacon_period);
 
-	tim = brcmu_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
+	tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
 	if (tim)
 		dtim_period = tim->data[1];
 	else {
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index 28480e7..2d903ba 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -365,36 +365,6 @@ void brcmu_prpkt(const char *msg, struct sk_buff *p0)
 EXPORT_SYMBOL(brcmu_prpkt);
 #endif				/* defined(BCMDBG) */
 
-/*
- * Traverse a string of 1-byte tag/1-byte length/variable-length value
- * triples, returning a pointer to the substring whose first element
- * matches tag
- */
-struct brcmu_tlv *brcmu_parse_tlvs(void *buf, int buflen, uint key)
-{
-	struct brcmu_tlv *elt;
-	int totlen;
-
-	elt = (struct brcmu_tlv *) buf;
-	totlen = buflen;
-
-	/* find tagged parameter */
-	while (totlen >= 2) {
-		int len = elt->len;
-
-		/* validate remaining totlen */
-		if ((elt->id == key) && (totlen >= (len + 2)))
-			return elt;
-
-		elt = (struct brcmu_tlv *) ((u8 *) elt + (len + 2));
-		totlen -= (len + 2);
-	}
-
-	return NULL;
-}
-EXPORT_SYMBOL(brcmu_parse_tlvs);
-
-
 #if defined(BCMDBG)
 int
 brcmu_format_flags(const struct brcmu_bit_desc *bd, u32 flags, char *buf,
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
index e53883c..c19490c 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -192,13 +192,6 @@ struct brcmu_bit_desc {
 	const char *name;
 };
 
-/* tag_ID/length/value_buffer tuple */
-struct brcmu_tlv {
-	u8 id;
-	u8 len;
-	u8 data[1];
-};
-
 /* externs */
 /* format/print */
 #if defined(BCMDBG)
@@ -207,9 +200,6 @@ extern int brcmu_format_flags(const struct brcmu_bit_desc *bd, u32 flags,
 extern int brcmu_format_hex(char *str, const void *bytes, int len);
 #endif
 
-extern struct brcmu_tlv *brcmu_parse_tlvs(void *buf, int buflen,
-					  uint key);
-
 extern uint brcmu_mkiovar(char *name, char *data, uint datalen,
 			  char *buf, uint len);
 
-- 
1.7.4.1



^ permalink raw reply related

* [PATCH 20/22] brcm80211: moved function brcmu_mkiovar
From: Arend van Spriel @ 2011-10-12 18:51 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Alwin Beukers, Arend van Spriel
In-Reply-To: <1318445492-24207-1-git-send-email-arend@broadcom.com>

From: Alwin Beukers <alwin@broadcom.com>

Moved the brcmu_mkiovar function into fmac, adjusting the
name accordingly.

Reported-by: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: Roland Vossen <rvossen@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/dhd.h      |    3 ++
 .../net/wireless/brcm80211/brcmfmac/dhd_common.c   |   39 +++++++++++++++-----
 .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |    6 ++--
 .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |   24 ++++++------
 drivers/net/wireless/brcm80211/brcmutil/utils.c    |   20 ----------
 .../net/wireless/brcm80211/include/brcmu_utils.h   |    3 --
 6 files changed, 48 insertions(+), 47 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 951910e..4645766 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -680,6 +680,9 @@ struct bcmevent_name {
 
 extern const struct bcmevent_name bcmevent_names[];
 
+extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
+			  char *buf, uint len);
+
 /* Indication from bus module regarding presence/insertion of dongle.
  * Return struct brcmf_pub pointer, used as handle to OS module in later calls.
  * Returned structure should have bus and prot pointers filled in.
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index a43b3da..8918261 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -65,6 +65,26 @@ struct msgtrace_hdr {
 				 because of trace overflow */
 } __packed;
 
+
+uint
+brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
+{
+	uint len;
+
+	len = strlen(name) + 1;
+
+	if ((len + datalen) > buflen)
+		return 0;
+
+	strncpy(buf, name, buflen);
+
+	/* append data onto the end of the name string */
+	memcpy(&buf[len], data, datalen);
+	len += datalen;
+
+	return len;
+}
+
 void brcmf_c_init(void)
 {
 	/* Init global variables at run-time, not as part of the declaration.
@@ -607,7 +627,7 @@ brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
 
 	/* Contorl the master mode */
 	mmode_le = cpu_to_le32(master_mode);
-	brcmu_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf,
+	brcmf_c_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf,
 		    sizeof(buf));
 	rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf,
 				       sizeof(buf));
@@ -756,7 +776,7 @@ static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
 	char iovbuf[32];
 	int retcode;
 
-	brcmu_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
+	brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
 	retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
 				   iovbuf, sizeof(iovbuf));
 	retcode = retcode >= 0 ? 0 : retcode;
@@ -773,7 +793,8 @@ static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
 	char iovbuf[32];
 	int retcode;
 
-	brcmu_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
+	brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4,
+			iovbuf, sizeof(iovbuf));
 	retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
 				   iovbuf, sizeof(iovbuf));
 	retcode = retcode >= 0 ? 0 : retcode;
@@ -812,33 +833,33 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
 	/* query for 'ver' to get version info from firmware */
 	memset(buf, 0, sizeof(buf));
 	ptr = buf;
-	brcmu_mkiovar("ver", NULL, 0, buf, sizeof(buf));
+	brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf));
 	brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf));
 	strsep(&ptr, "\n");
 	/* Print fw version info */
 	brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
 
 	/* Match Host and Dongle rx alignment */
-	brcmu_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
+	brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
 		    sizeof(iovbuf));
 	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
 				  sizeof(iovbuf));
 
 	/* disable glom option per default */
-	brcmu_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
+	brcmf_c_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
 	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
 				  sizeof(iovbuf));
 
 	/* Setup timeout if Beacons are lost and roam is off to report
 		 link down */
-	brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
+	brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
 		    sizeof(iovbuf));
 	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
 				  sizeof(iovbuf));
 
 	/* Enable/Disable build-in roaming to allowed ext supplicant to take
 		 of romaing */
-	brcmu_mkiovar("roam_off", (char *)&roaming, 4,
+	brcmf_c_mkiovar("roam_off", (char *)&roaming, 4,
 		      iovbuf, sizeof(iovbuf));
 	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
 				  sizeof(iovbuf));
@@ -847,7 +868,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
 	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up));
 
 	/* Setup event_msgs */
-	brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
+	brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
 		      iovbuf, sizeof(iovbuf));
 	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
 				  sizeof(iovbuf));
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index b05f177..4acbac5 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -204,7 +204,7 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
 
 	dcmd_le_value = cpu_to_le32(dcmd_value);
 
-	if (!brcmu_mkiovar
+	if (!brcmf_c_mkiovar
 	    ("allmulti", (void *)&dcmd_le_value,
 	    sizeof(dcmd_le_value), buf, buflen)) {
 		brcmf_dbg(ERROR, "%s: mkiovar failed for allmulti, datalen %d buflen %u\n",
@@ -260,7 +260,7 @@ _brcmf_set_mac_address(struct work_struct *work)
 						    setmacaddr_work);
 
 	brcmf_dbg(TRACE, "enter\n");
-	if (!brcmu_mkiovar("cur_etheraddr", (char *)drvr_priv->macvalue,
+	if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr_priv->macvalue,
 			   ETH_ALEN, buf, 32)) {
 		brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n",
 			  brcmf_ifname(&drvr_priv->pub, 0));
@@ -1084,7 +1084,7 @@ int brcmf_bus_start(struct brcmf_pub *drvr)
 		return -ENODEV;
 	}
 
-	brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
+	brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
 		      iovbuf, sizeof(iovbuf));
 	brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf,
 				    sizeof(iovbuf));
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 857b328..5eddabe 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -437,7 +437,7 @@ static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val)
 	__le32 val_le;
 
 	val_le = cpu_to_le32(val);
-	len = brcmu_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf,
+	len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf,
 			    sizeof(buf));
 	BUG_ON(!len);
 
@@ -460,7 +460,7 @@ brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval)
 	s32 err = 0;
 
 	len =
-	    brcmu_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
+	    brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
 			sizeof(var.buf));
 	BUG_ON(!len);
 	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len);
@@ -508,7 +508,7 @@ brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param,
 {
 	s32 iolen;
 
-	iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
+	iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
 	BUG_ON(!iolen);
 
 	return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen);
@@ -520,7 +520,7 @@ brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param,
 {
 	s32 iolen;
 
-	iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
+	iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
 	BUG_ON(!iolen);
 
 	return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen);
@@ -2554,7 +2554,7 @@ brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
 	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
 	u32 buflen;
 
-	buflen = brcmu_mkiovar(name, buf, len, cfg_priv->dcmd_buf,
+	buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf,
 			       WL_DCMD_LEN_MAX);
 	BUG_ON(!buflen);
 
@@ -2570,7 +2570,7 @@ brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
 	u32 len;
 	s32 err = 0;
 
-	len = brcmu_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf,
+	len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf,
 			    WL_DCMD_LEN_MAX);
 	BUG_ON(!len);
 	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf,
@@ -3513,8 +3513,8 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
 	WL_TRACE("Enter\n");
 
 	/* Setup event_msgs */
-	brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
-		    sizeof(iovbuf));
+	brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
+			iovbuf, sizeof(iovbuf));
 	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
 	if (err) {
 		WL_ERR("Get event_msgs error (%d)\n", err);
@@ -3542,8 +3542,8 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
 	setbit(eventmask, BRCMF_E_JOIN_START);
 	setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
 
-	brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
-		    sizeof(iovbuf));
+	brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
+			iovbuf, sizeof(iovbuf));
 	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
 	if (err) {
 		WL_ERR("Set event_msgs error (%d)\n", err);
@@ -3571,7 +3571,7 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 	 */
 	if (roamvar) {
 		bcn_to_le = cpu_to_le32(bcn_timeout);
-		brcmu_mkiovar("bcn_timeout", (char *)&bcn_to_le,
+		brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le,
 			sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
 		err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
 				   iovbuf, sizeof(iovbuf));
@@ -3587,7 +3587,7 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 	 */
 	WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
 	roamvar_le = cpu_to_le32(roamvar);
-	brcmu_mkiovar("roam_off", (char *)&roamvar_le,
+	brcmf_c_mkiovar("roam_off", (char *)&roamvar_le,
 				sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
 	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
 	if (err) {
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index 2d903ba..d55595a 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -439,23 +439,3 @@ int brcmu_format_hex(char *str, const void *bytes, int len)
 }
 EXPORT_SYMBOL(brcmu_format_hex);
 #endif				/* defined(BCMDBG) */
-
-uint brcmu_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
-{
-	uint len;
-
-	len = strlen(name) + 1;
-
-	if ((len + datalen) > buflen)
-		return 0;
-
-	strncpy(buf, name, buflen);
-
-	/* append data onto the end of the name string */
-	memcpy(&buf[len], data, datalen);
-	len += datalen;
-
-	return len;
-}
-EXPORT_SYMBOL(brcmu_mkiovar);
-
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
index c19490c..f8664b2 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -200,7 +200,4 @@ extern int brcmu_format_flags(const struct brcmu_bit_desc *bd, u32 flags,
 extern int brcmu_format_hex(char *str, const void *bytes, int len);
 #endif
 
-extern uint brcmu_mkiovar(char *name, char *data, uint datalen,
-			  char *buf, uint len);
-
 #endif				/* _BRCMU_UTILS_H_ */
-- 
1.7.4.1



^ permalink raw reply related

* [PATCH 19/22] brcm80211: moved function brcmu_chspec_malformed
From: Arend van Spriel @ 2011-10-12 18:51 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Alwin Beukers, Arend van Spriel
In-Reply-To: <1318445492-24207-1-git-send-email-arend@broadcom.com>

From: Alwin Beukers <alwin@broadcom.com>

Moved brcmu_chspec_malformed into the only file using it. The
function name was adjusted accordingly.

Reported-by: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: Roland Vossen <rvossen@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmsmac/channel.c  |   28 +++++++++++++++++++-
 drivers/net/wireless/brcm80211/brcmutil/wifi.c     |   27 -------------------
 .../net/wireless/brcm80211/include/brcmu_wifi.h    |    8 -----
 3 files changed, 27 insertions(+), 36 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index a1b415d..89ad1b7 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -1485,6 +1485,32 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
 }
 
 /*
+ * Verify the chanspec is using a legal set of parameters, i.e. that the
+ * chanspec specified a band, bw, ctl_sb and channel and that the
+ * combination could be legal given any set of circumstances.
+ * RETURNS: true is the chanspec is malformed, false if it looks good.
+ */
+static bool brcms_c_chspec_malformed(u16 chanspec)
+{
+	/* must be 2G or 5G band */
+	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
+		return true;
+	/* must be 20 or 40 bandwidth */
+	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
+		return true;
+
+	/* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
+	if (CHSPEC_IS20(chanspec)) {
+		if (!CHSPEC_SB_NONE(chanspec))
+			return true;
+	} else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) {
+		return true;
+	}
+
+	return false;
+}
+
+/*
  * Validate the chanspec for this locale, for 40MHZ we need to also
  * check that the sidebands are valid 20MZH channels in this locale
  * and they are also a legal HT combination
@@ -1497,7 +1523,7 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
 	u8 channel = CHSPEC_CHANNEL(chspec);
 
 	/* check the chanspec */
-	if (brcmu_chspec_malformed(chspec)) {
+	if (brcms_c_chspec_malformed(chspec)) {
 		wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
 			wlc->pub->unit, chspec);
 		return false;
diff --git a/drivers/net/wireless/brcm80211/brcmutil/wifi.c b/drivers/net/wireless/brcm80211/brcmutil/wifi.c
index e8d3bf2..8483f24 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/wifi.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/wifi.c
@@ -14,30 +14,3 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 #include <brcmu_wifi.h>
-
-/*
- * Verify the chanspec is using a legal set of parameters, i.e. that the
- * chanspec specified a band, bw, ctl_sb and channel and that the
- * combination could be legal given any set of circumstances.
- * RETURNS: true is the chanspec is malformed, false if it looks good.
- */
-bool brcmu_chspec_malformed(u16 chanspec)
-{
-	/* must be 2G or 5G band */
-	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
-		return true;
-	/* must be 20 or 40 bandwidth */
-	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
-		return true;
-
-	/* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
-	if (CHSPEC_IS20(chanspec)) {
-		if (!CHSPEC_SB_NONE(chanspec))
-			return true;
-	} else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) {
-		return true;
-	}
-
-	return false;
-}
-EXPORT_SYMBOL(brcmu_chspec_malformed);
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
index 5b1aca7..f10d302 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
@@ -168,14 +168,6 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
 	return (bitmap & (1 << (prec))) != 0;
 }
 
-/*
- * Verify the chanspec is using a legal set of parameters, i.e. that the
- * chanspec specified a band, bw, ctl_sb and channel and that the
- * combination could be legal given any set of circumstances.
- * RETURNS: true is the chanspec is malformed, false if it looks good.
- */
-extern bool brcmu_chspec_malformed(u16 chanspec);
-
 /* Enumerate crypto algorithms */
 #define	CRYPTO_ALGO_OFF			0
 #define	CRYPTO_ALGO_WEP1		1
-- 
1.7.4.1



^ permalink raw reply related

* [PATCH 05/22] brcm80211: fix sparse endianess error in mac80211_if.c
From: Arend van Spriel @ 2011-10-12 18:51 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1318445492-24207-1-git-send-email-arend@broadcom.com>

The ht capabilities provided upon registration with mac80211 must
be in little endian. This was fixed adding cpu_to_le16() conversion.

Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmsmac/mac80211_if.c  |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 6ce773a..ac8d02b 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -963,7 +963,7 @@ static int ieee_hw_rate_init(struct ieee80211_hw *hw)
 		if (phy_type == PHY_TYPE_LCN) {
 			/* Single stream */
 			band->ht_cap.mcs.rx_mask[1] = 0;
-			band->ht_cap.mcs.rx_highest = 72;
+			band->ht_cap.mcs.rx_highest = cpu_to_le16(72);
 		}
 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band;
 	} else {
-- 
1.7.4.1



^ permalink raw reply related

* Re: [PATCH 00/34] update for 3.2
From: Guy, Wey-Yi @ 2011-10-12 18:00 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <20111012182440.GD18764@tuxdriver.com>

Hi John,

On Wed, 2011-10-12 at 11:24 -0700, John W. Linville wrote:
> On Mon, Oct 10, 2011 at 07:26:45AM -0700, Wey-Yi Guy wrote:
> > We address the performance issue cause by earlier path which disable too many calibration.
> > We include few more bugs fix and enhancement patches for WoWLAN operations
> > We continue remove un-needed code and clean up after driver split
> > We also include new SKUs for both 6005 and 105 series of devices
> 
> Applying: iwlagn: separate init calib and rt calib
> error: patch failed: drivers/net/wireless/iwlwifi/iwl-agn.c:1222
> error: drivers/net/wireless/iwlwifi/iwl-agn.c: patch does not apply
> error: patch failed: drivers/net/wireless/iwlwifi/iwl-commands.h:3216
> error: drivers/net/wireless/iwlwifi/iwl-commands.h: patch does not apply
> 

My mistake, I believe this patch already in the tree:
commit#af4dc88c56559c1ebf53628ddcc18dde23924e33 iwlagn: separate init
calib and rt calib


Thanks
Wey


^ permalink raw reply

* wl12xx.git is back on git.kernel.org
From: Luciano Coelho @ 2011-10-12 18:46 UTC (permalink / raw)
  To: linux-wireless

Hi,

Now that git.kernel.org is working again and I got my account back, the
official wl12xx.git tree is back to it's original place:

git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git

And the usual branches are back, master (used for development) and
wl12xx-next (used by me for integration).  All wl12xx tags were also
pushed back to to repository.

I'll keep updating the wl12xx.git repo in github for a while, but I
don't know for how long, so I don't recommend using it anymore.

-- 
Cheers,
Luca.


^ permalink raw reply

* Re: [PATCH] ath9k_hw: Fix ASPM L1 issue for AR9462
From: John W. Linville @ 2011-10-12 18:40 UTC (permalink / raw)
  To: Rajkumar Manoharan; +Cc: linux-wireless, stable
In-Reply-To: <1318226145-7772-1-git-send-email-rmanohar@qca.qualcomm.com>

On Mon, Oct 10, 2011 at 11:25:45AM +0530, Rajkumar Manoharan wrote:
> Because of not clearing Bit 14 of AR_WA, the ASPM L1 is not
> enabled when entering into sleep mode. AR9462 does not need
> bit 14 to be set.
> 
> Cc: stable@kernel.org
> Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>

  CC [M]  drivers/net/wireless/ath/ath9k/hw.o
drivers/net/wireless/ath/ath9k/hw.c: In function ‘__ath9k_hw_init’:
drivers/net/wireless/ath/ath9k/hw.c:544:2: error: implicit declaration of function ‘AR_SREV_9462’

Missing a patch dependency?

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [PATCH 4/5 V2] rtlwifi: rtl8192se: Updates from latest Realtek driver version - Part II
From: John W. Linville @ 2011-10-12 18:32 UTC (permalink / raw)
  To: Larry Finger; +Cc: Chaoming Li, linux-wireless
In-Reply-To: <1318386531-5859-5-git-send-email-Larry.Finger@lwfinger.net>

On Tue, Oct 11, 2011 at 09:28:50PM -0500, Larry Finger wrote:
> From: Chaoming Li <chaoming_li@realsil.com.cn>
> 
> This patch incorporate the differences between the 06/20/2011 and
> 08/16/2011 Realtek releases of the rtl8192se driver.
> 
> The changes include:
> 
> 1. Fixing some typos in register usage.
> 2. A change in the handling of decryption status for 802.11w packets.
> 
> Signed-off-by: Chaoming Li <chaoming_li@realsil.com.cn>
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>

> Index: wireless-testing-new/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
> ===================================================================
> --- wireless-testing-new.orig/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
> +++ wireless-testing-new/drivers/net/wireless/rtlwifi/rtl8192se/trx.c

> @@ -539,29 +540,39 @@ bool rtl92se_rx_query_desc(struct ieee80
>  	rx_status->freq = hw->conf.channel->center_freq;
>  	rx_status->band = hw->conf.channel->band;
>  
> -	if (GET_RX_STATUS_DESC_CRC32(pdesc))
> -		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
> +	hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size
> +	      + stats->rx_bufshift);
>  
> -	if (!GET_RX_STATUS_DESC_SWDEC(pdesc))
> -		rx_status->flag |= RX_FLAG_DECRYPTED;
> +	if (stats->crc)
> +		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
>  
> -	if (GET_RX_STATUS_DESC_BW(pdesc))
> +	if (stats->rx_is40Mhzpacket)
>  		rx_status->flag |= RX_FLAG_40MHZ;
>  
> -	if (GET_RX_STATUS_DESC_RX_HT(pdesc))
> +	if (stats->is_ht)
>  		rx_status->flag |= RX_FLAG_HT;
>  
>  	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
>  
> -	if (stats->decrypted)
> -		rx_status->flag |= RX_FLAG_DECRYPTED;
> +	/* hw will set stats->decrypted true, if it finds the
> +	 * frame is open data frame or mgmt frame,
> +	 * hw will not decrypt robust managment frame
> +	 * for IEEE80211w but still set stats->decrypted
> +	 * true, so here we should set it back to undecrypted
> +	 * for IEEE80211w frame, and mac80211 sw will help
> +	 * to decrypt it */
> +	if (stats->decrypted) {
> +		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
> +			(ieee80211_has_protected(hdr->frame_control)))
> +			rx_status->flag &= ~RX_FLAG_DECRYPTED;
> +		else
> +			rx_status->flag |= RX_FLAG_DECRYPTED;
> +	}
>  
>  	rx_status->rate_idx = rtlwifi_rate_mapping(hw,
> -				(bool)GET_RX_STATUS_DESC_RX_HT(pdesc),
> -				(u8)GET_RX_STATUS_DESC_RX_MCS(pdesc));
> -
> +			     stats->is_ht, stats->rate);
>  
> -	rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc);
> +	rx_status->mactime = stats->timestamp_low;
>  	if (phystatus) {
>  		p_drvinfo = (struct rx_fwinfo *)(skb->data +
>  						 stats->rx_bufshift);

The above hunk doesn't apply, because I have this:

        rx_status->rate_idx = rtlwifi_rate_mapping(hw,
                                (bool)GET_RX_STATUS_DESC_RX_HT(pdesc),
                                (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc),
                                (bool)GET_RX_STATUS_DESC_PAGGR(pdesc));

Do you perhaps have another patch applied which you haven't sent?

John

P.S.  Please note that my trees are still on infradead -- be sure to
pull the latest from there.
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [PATCH 00/34] update for 3.2
From: John W. Linville @ 2011-10-12 18:24 UTC (permalink / raw)
  To: Wey-Yi Guy; +Cc: linux-wireless
In-Reply-To: <1318256839-31837-1-git-send-email-wey-yi.w.guy@intel.com>

On Mon, Oct 10, 2011 at 07:26:45AM -0700, Wey-Yi Guy wrote:
> We address the performance issue cause by earlier path which disable too many calibration.
> We include few more bugs fix and enhancement patches for WoWLAN operations
> We continue remove un-needed code and clean up after driver split
> We also include new SKUs for both 6005 and 105 series of devices

Applying: iwlagn: separate init calib and rt calib
error: patch failed: drivers/net/wireless/iwlwifi/iwl-agn.c:1222
error: drivers/net/wireless/iwlwifi/iwl-agn.c: patch does not apply
error: patch failed: drivers/net/wireless/iwlwifi/iwl-commands.h:3216
error: drivers/net/wireless/iwlwifi/iwl-commands.h: patch does not apply

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [PATCH v2 01/13] ath9k_hw: Updated ar9003 initval table for AR9380
From: John W. Linville @ 2011-10-12 18:21 UTC (permalink / raw)
  To: Rajkumar Manoharan; +Cc: linux-wireless
In-Reply-To: <1318225878-7283-1-git-send-email-rmanohar@qca.qualcomm.com>

At least three of the patches in this series don't apply to either
wireless-next or wireless-testing.  Please only send me patch sets
that apply cleanly to recent kernels.

John

On Mon, Oct 10, 2011 at 11:21:06AM +0530, Rajkumar Manoharan wrote:
> The ar9003 table is updated to increase XLNA BIAS
> output driver strengh.
> 
> Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
> ---
>  .../net/wireless/ath/ath9k/ar9003_2p2_initvals.h   |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
> index 08e9341..02be24e 100644
> --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
> +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
> @@ -24,11 +24,11 @@ static const u32 ar9300_2p2_radio_postamble[][5] = {
>  	{0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31},
>  	{0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
>  	{0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
> -	{0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
> +	{0x0001610c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
>  	{0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
> -	{0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
> +	{0x0001650c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
>  	{0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
> -	{0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
> +	{0x0001690c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
>  	{0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
>  };
>  
> -- 
> 1.7.7
> 
> 

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: r8712u driver - on ARM
From: Larry Finger @ 2011-10-12 17:28 UTC (permalink / raw)
  To: Ian Jeffray; +Cc: linux-wireless
In-Reply-To: <4E95B299.8050006@emobix.co.uk>

On 10/12/2011 10:30 AM, Ian Jeffray wrote:
> On 02/10/2011 00:24, Ian Jeffray wrote:
>> On 01/10/2011 20:24, Larry Finger wrote:
>>
>>> BTW, netperf shows that r8712u can transmit at ~80 and receive at ~60
>>> Mbps when connected to a 270 Mbps AP. As Realtek lists this as capable
>>> of 150 Mbps, x86_64 is getting the max transmit rate that we might
>>> expect.
>>
>> On x86 32bit, I get a sustained 94Mbps transmit to a 300Mbps AP, which
>> seems pretty good - why I'm keen to get this to work for my ARM target.
>
> Larry, just a little more info on this issue, FYI.
>
> It would seem the problem is certainly specific to the 'Inventra' mUSB
> host found in recent TI ARM products and ADI Blackfin devices.
>
> I have added a PCI express NEC USB 2.0 host controller card to my ARM
> Cortex A8 system, and the r8712u devices work just fine when connected
> via that host controller. (Albeit only at 20MBps rate, but that's
> because the host controller is rather poor in general).
>
> We have now raised this problem with TI USB experts.

Thanks for the update. Good luck with finding the real problem and let me know 
if I can be of help.

Larry


^ permalink raw reply

* Re: [PATCH v2] mac80211: pass vif param to conf_tx() callback
From: Johannes Berg @ 2011-10-12 15:31 UTC (permalink / raw)
  To: Eliad Peller; +Cc: linux-wireless
In-Reply-To: <1317543352-29019-1-git-send-email-eliad@wizery.com>

On Sun, 2011-10-02 at 10:15 +0200, Eliad Peller wrote:
> tx params should be configured per interface.
> add ieee80211_vif param to the conf_tx callback,
> and change all the drivers that use this callback.

For the record, I said this to you on IRC but you weren't around I
guess. This patch (with the other ones) is now passing a bogus sdata/vif
pointer to drivers -- e.g. for monitor mode interfaces from
ieee80211_do_open -> ieee80211_set_wmm_default -> drv_conf_tx.

I suspect the way to fix this would be to move the call to
ieee80211_set_wmm_default into the last switch statement in do_open,
could you please look into it?

Thx,
johannes


^ permalink raw reply

* Re: r8712u driver - on ARM
From: Ian Jeffray @ 2011-10-12 15:30 UTC (permalink / raw)
  To: Larry Finger; +Cc: linux-wireless
In-Reply-To: <4E87A110.6030201@emobix.co.uk>

On 02/10/2011 00:24, Ian Jeffray wrote:
> On 01/10/2011 20:24, Larry Finger wrote:
>
>> BTW, netperf shows that r8712u can transmit at ~80 and receive at ~60
>> Mbps when connected to a 270 Mbps AP. As Realtek lists this as capable
>> of 150 Mbps, x86_64 is getting the max transmit rate that we might
>> expect.
>
> On x86 32bit, I get a sustained 94Mbps transmit to a 300Mbps AP, which
> seems pretty good - why I'm keen to get this to work for my ARM target.

Larry, just a little more info on this issue, FYI.

It would seem the problem is certainly specific to the 'Inventra' mUSB
host found in recent TI ARM products and ADI Blackfin devices.

I have added a PCI express NEC USB 2.0 host controller card to my ARM
Cortex A8 system, and the r8712u devices work just fine when connected
via that host controller.  (Albeit only at 20MBps rate, but that's
because the host controller is rather poor in general).

We have now raised this problem with TI USB experts.

Regards,

Ian.

^ permalink raw reply

* [PATCH] mac80211: reformat TX unauthorised check
From: Johannes Berg @ 2011-10-12 15:28 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

Reformat the check, the indentation is completely strange.
Also change the last part of the condition to make the
code shorter.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
Yes, it runs a bit over 80 cols but is easier to read than broken up.

 net/mac80211/tx.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

--- a/net/mac80211/tx.c	2011-10-12 17:11:32.000000000 +0200
+++ b/net/mac80211/tx.c	2011-10-12 17:27:00.000000000 +0200
@@ -1896,11 +1896,10 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 	 * Drop unicast frames to unauthorised stations unless they are
 	 * EAPOL frames from the local station.
 	 */
-	if (!ieee80211_vif_is_mesh(&sdata->vif) &&
-		unlikely(!is_multicast_ether_addr(hdr.addr1) && !authorized &&
-		      !(cpu_to_be16(ethertype) == sdata->control_port_protocol &&
-		       compare_ether_addr(sdata->vif.addr,
-					  skb->data + ETH_ALEN) == 0))) {
+	if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) &&
+		     !is_multicast_ether_addr(hdr.addr1) && !authorized &&
+		     (cpu_to_be16(ethertype) != sdata->control_port_protocol ||
+		      compare_ether_addr(sdata->vif.addr, skb->data + ETH_ALEN)))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 		if (net_ratelimit())
 			printk(KERN_DEBUG "%s: dropped frame to %pM"



^ permalink raw reply

* Re: [PATCH 1/5 V2] rtlwifi: Change PCI drivers to use the new PM framework
From: Larry Finger @ 2011-10-12 15:20 UTC (permalink / raw)
  To: Mark Einon; +Cc: linville, linux-wireless
In-Reply-To: <CANK3SE1zJDKry-r-M384jqo7rQezgj2FzbXBLS6SCMiaL934kw@mail.gmail.com>

On 10/12/2011 09:02 AM, Mark Einon wrote:
> On 12 October 2011 03:28, Larry Finger<Larry.Finger@lwfinger.net>  wrote:
>
>>
>> +static const struct dev_pm_ops rtlwifi_pm_ops = {
>> +       .suspend = rtl_pci_suspend,
>> +       .resume = rtl_pci_resume,
>> +       .freeze = rtl_pci_suspend,
>> +       .thaw = rtl_pci_resume,
>> +       .poweroff = rtl_pci_suspend,
>> +       .restore = rtl_pci_resume,
>> +};
>> +
>
> Hi Larry,
>
> You can save a few lines of code here, and in the other files where it
> is done - there is a convenience macro for simplifying creating a
> pm_ops struct like this, see SIMPLE_DEV_PM_OPS() in pm.h.

Mark,

Thanks for the tip.

Larry


^ permalink raw reply

* Re: [PATCH] staging: brcm80211: remove brcm80211 driver from the staging tree
From: Arend van Spriel @ 2011-10-12 15:08 UTC (permalink / raw)
  To: Greg KH
  Cc: devel@linuxdriverproject.org, linux-wireless@vger.kernel.org,
	John W. Linville
In-Reply-To: <20111012143600.GA17938@suse.de>

On 10/12/2011 04:36 PM, Greg KH wrote:
> On Wed, Oct 12, 2011 at 04:18:57PM +0200, Arend van Spriel wrote:
>> Hi Greg,
>>
>> John recommended to do the delete through your staging tree. Thanks for
>> the ride. It has been a learning experience for all of us here. Apart
>> from the significant cleanup (which needs ongoing work for sure) it took
>> some time to find the right way of working in coordinating our changes
>> with community patches.
>>
>> The removal patch was just as big as the mainline patch so it has been
>> uploaded to linuxwireless.org:
>>
>> http://linuxwireless.org/en/users/Drivers/brcm80211?action=AttachFile&do=view&target=0001-staging-brcm80211-remove-brcm80211-driver-from-the-s.patch
> 
> So I'm taking it that the driver is now in the wireless-next tree?
> That's great, I'll queue the patch up later today.

It is. From the day I sent the mainline patch for wireless-next we have
been staring at our inbox for the green light :-D

> And thanks so much for working with us, I know it can be hard at times,
> but I hope you will agree that the end result is much better than what
> we started out with.
> 
> greg k-h
> 

Yep. We got rid of a lot of redundant code that was not needed in the
mac80211 framework and the different level of abstractions. The are
still i's to dot and features to add.

Thanks again.

Gr. AvS


^ permalink raw reply

* Re: [PATCH] staging: brcm80211: remove brcm80211 driver from the staging tree
From: Greg KH @ 2011-10-12 14:36 UTC (permalink / raw)
  To: Arend van Spriel
  Cc: devel@linuxdriverproject.org, linux-wireless@vger.kernel.org,
	John W. Linville
In-Reply-To: <4E95A1D1.8010602@broadcom.com>

On Wed, Oct 12, 2011 at 04:18:57PM +0200, Arend van Spriel wrote:
> Hi Greg,
> 
> John recommended to do the delete through your staging tree. Thanks for
> the ride. It has been a learning experience for all of us here. Apart
> from the significant cleanup (which needs ongoing work for sure) it took
> some time to find the right way of working in coordinating our changes
> with community patches.
> 
> The removal patch was just as big as the mainline patch so it has been
> uploaded to linuxwireless.org:
> 
> http://linuxwireless.org/en/users/Drivers/brcm80211?action=AttachFile&do=view&target=0001-staging-brcm80211-remove-brcm80211-driver-from-the-s.patch

So I'm taking it that the driver is now in the wireless-next tree?
That's great, I'll queue the patch up later today.

And thanks so much for working with us, I know it can be hard at times,
but I hope you will agree that the end result is much better than what
we started out with.

greg k-h

^ permalink raw reply

* Re: Driver for Intel Pro/Wireless 2200BG
From: Guy, Wey-Yi @ 2011-10-12 13:36 UTC (permalink / raw)
  To: Jayanthi Venugopal; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <CAFvH45QeG7DQeLORkf4io=gfVAhuiKh1KtWGEwZscg1LY7hM8Q@mail.gmail.com>

On Wed, 2011-10-12 at 05:58 -0700, Jayanthi Venugopal wrote:
> Hi,
> I would like to download and install the above driver .I am not able
> to download the driver from
> http://ipw2200.sourceforge.net/index.php
> 
> I would like the driver and the installation instruction as well.
> 
> Looking forward for your reply,
> 

is not ipw2200 part of kernel release?

drivers/net/wireless/ipw2x00

Thanks
Wey


^ permalink raw reply

* [PATCH] staging: brcm80211: remove brcm80211 driver from the staging tree
From: Arend van Spriel @ 2011-10-12 14:18 UTC (permalink / raw)
  To: gregkh@suse.de
  Cc: devel@linuxdriverproject.org, linux-wireless@vger.kernel.org,
	John W. Linville

Hi Greg,

John recommended to do the delete through your staging tree. Thanks for
the ride. It has been a learning experience for all of us here. Apart
from the significant cleanup (which needs ongoing work for sure) it took
some time to find the right way of working in coordinating our changes
with community patches.

The removal patch was just as big as the mainline patch so it has been
uploaded to linuxwireless.org:

http://linuxwireless.org/en/users/Drivers/brcm80211?action=AttachFile&do=view&target=0001-staging-brcm80211-remove-brcm80211-driver-from-the-s.patch

Regards,
Arend van Spriel


^ permalink raw reply

* Re: [PATCH] iwlagn: fix priv->cfg->ht_params NULL pointer dereference
From: Guy, Wey-Yi @ 2011-10-12 13:26 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: linux-wireless@vger.kernel.org, John W. Linville
In-Reply-To: <20111012081634.GA2675@redhat.com>

On Wed, 2011-10-12 at 01:16 -0700, Stanislaw Gruszka wrote:
> This fix regression introduced by commit:
> 
> commit 15b3f3b006b42a678523cad989bfd60b76bf4403
> Author: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> Date:   Fri Jun 3 07:54:13 2011 -0700
> 
>     iwlagn: set smps mode after assoc for 1000 device
> 
> Also remove unneeded brackets on the way.
> 
> Address:
> https://bugzilla.redhat.com/show_bug.cgi?id=744155
> 
> If fix will not get 3.1 release, it should be applied in 3.1 stable.
> 
> Cc: stable@kernel.org # 3.1+
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Acked-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> ---
>  drivers/net/wireless/iwlwifi/iwl-agn-rxon.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
Thanks a lot
Wey


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox