Merge remote branch 'wireless-next/master' into ath6kl-next
diff --git a/Documentation/networking/mac80211-auth-assoc-deauth.txt b/Documentation/networking/mac80211-auth-assoc-deauth.txt
new file mode 100644
index 0000000..e0a2aa58
--- /dev/null
+++ b/Documentation/networking/mac80211-auth-assoc-deauth.txt
@@ -0,0 +1,99 @@
+#
+# This outlines the Linux authentication/association and
+# deauthentication/disassociation flows.
+#
+# This can be converted into a diagram using the service
+# at http://www.websequencediagrams.com/
+#
+
+participant userspace
+participant mac80211
+participant driver
+
+alt authentication needed (not FT)
+userspace->mac80211: authenticate
+
+alt authenticated/authenticating already
+mac80211->driver: sta_state(AP, not-exists)
+mac80211->driver: bss_info_changed(clear BSSID)
+else associated
+note over mac80211,driver
+like deauth/disassoc, without sending the
+BA session stop & deauth/disassoc frames
+end note
+end
+
+mac80211->driver: config(channel, non-HT)
+mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap)
+mac80211->driver: sta_state(AP, exists)
+
+alt no probe request data known
+mac80211->driver: TX directed probe request
+driver->mac80211: RX probe response
+end
+
+mac80211->driver: TX auth frame
+driver->mac80211: RX auth frame
+
+alt WEP shared key auth
+mac80211->driver: TX auth frame
+driver->mac80211: RX auth frame
+end
+
+mac80211->driver: sta_state(AP, authenticated)
+mac80211->userspace: RX auth frame
+
+end
+
+userspace->mac80211: associate
+alt authenticated or associated
+note over mac80211,driver: cleanup like for authenticate
+end
+
+alt not previously authenticated (FT)
+mac80211->driver: config(channel, non-HT)
+mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap)
+mac80211->driver: sta_state(AP, exists)
+mac80211->driver: sta_state(AP, authenticated)
+end
+mac80211->driver: TX assoc
+driver->mac80211: RX assoc response
+note over mac80211: init rate control
+mac80211->driver: sta_state(AP, associated)
+
+alt not using WPA
+mac80211->driver: sta_state(AP, authorized)
+end
+
+mac80211->driver: set up QoS parameters
+
+alt is HT channel
+mac80211->driver: config(channel, HT params)
+end
+
+mac80211->driver: bss_info_changed(QoS, HT, associated with AID)
+mac80211->userspace: associated
+
+note left of userspace: associated now
+
+alt using WPA
+note over userspace
+do 4-way-handshake
+(data frames)
+end note
+userspace->mac80211: authorized
+mac80211->driver: sta_state(AP, authorized)
+end
+
+userspace->mac80211: deauthenticate/disassociate
+mac80211->driver: stop BA sessions
+mac80211->driver: TX deauth/disassoc
+mac80211->driver: flush frames
+mac80211->driver: sta_state(AP,associated)
+mac80211->driver: sta_state(AP,authenticated)
+mac80211->driver: sta_state(AP,exists)
+mac80211->driver: sta_state(AP,not-exists)
+mac80211->driver: turn off powersave
+mac80211->driver: bss_info_changed(clear BSSID, not associated, no QoS, ...)
+mac80211->driver: config(non-HT channel type)
+mac80211->userspace: disconnected
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index 4add173..4389de1 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,5 +3,5 @@
 # under Linux.
 #
 
-obj-y 				+= gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
+obj-y 				+= gpio.o irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
 obj-$(CONFIG_BCM47XX_SSB)	+= wgt634u.o
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
index a84e3bb..d43ceff 100644
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -107,8 +107,7 @@
 		value = eq + 1;
 		if ((eq - var) == strlen(name) &&
 			strncmp(var, name, (eq - var)) == 0) {
-			snprintf(val, val_len, "%s", value);
-			return 0;
+			return snprintf(val, val_len, "%s", value);
 		}
 	}
 	return NVRAM_ERR_ENVNOTFOUND;
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index aab6b0c..19780aa9 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -3,7 +3,7 @@
  *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
  *  Copyright (C) 2006 Michael Buesch <m@bues.ch>
  *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
- *  Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
+ *  Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -85,156 +85,7 @@
 }
 
 #ifdef CONFIG_BCM47XX_SSB
-#define READ_FROM_NVRAM(_outvar, name, buf) \
-	if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
-		sprom->_outvar = simple_strtoul(buf, NULL, 0);
-
-#define READ_FROM_NVRAM2(_outvar, name1, name2, buf) \
-	if (nvram_getprefix(prefix, name1, buf, sizeof(buf)) >= 0 || \
-	    nvram_getprefix(prefix, name2, buf, sizeof(buf)) >= 0)\
-		sprom->_outvar = simple_strtoul(buf, NULL, 0);
-
-static inline int nvram_getprefix(const char *prefix, char *name,
-				  char *buf, int len)
-{
-	if (prefix) {
-		char key[100];
-
-		snprintf(key, sizeof(key), "%s%s", prefix, name);
-		return nvram_getenv(key, buf, len);
-	}
-
-	return nvram_getenv(name, buf, len);
-}
-
-static u32 nvram_getu32(const char *name, char *buf, int len)
-{
-	int rv;
-	char key[100];
-	u16 var0, var1;
-
-	snprintf(key, sizeof(key), "%s0", name);
-	rv = nvram_getenv(key, buf, len);
-	/* return 0 here so this looks like unset */
-	if (rv < 0)
-		return 0;
-	var0 = simple_strtoul(buf, NULL, 0);
-
-	snprintf(key, sizeof(key), "%s1", name);
-	rv = nvram_getenv(key, buf, len);
-	if (rv < 0)
-		return 0;
-	var1 = simple_strtoul(buf, NULL, 0);
-	return var1 << 16 | var0;
-}
-
-static void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
-{
-	char buf[100];
-	u32 boardflags;
-
-	memset(sprom, 0, sizeof(struct ssb_sprom));
-
-	sprom->revision = 1; /* Fallback: Old hardware does not define this. */
-	READ_FROM_NVRAM(revision, "sromrev", buf);
-	if (nvram_getprefix(prefix, "il0macaddr", buf, sizeof(buf)) >= 0 ||
-	    nvram_getprefix(prefix, "macaddr", buf, sizeof(buf)) >= 0)
-		nvram_parse_macaddr(buf, sprom->il0mac);
-	if (nvram_getprefix(prefix, "et0macaddr", buf, sizeof(buf)) >= 0)
-		nvram_parse_macaddr(buf, sprom->et0mac);
-	if (nvram_getprefix(prefix, "et1macaddr", buf, sizeof(buf)) >= 0)
-		nvram_parse_macaddr(buf, sprom->et1mac);
-	READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
-	READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
-	READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf);
-	READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf);
-	READ_FROM_NVRAM(board_rev, "boardrev", buf);
-	READ_FROM_NVRAM(country_code, "ccode", buf);
-	READ_FROM_NVRAM(ant_available_a, "aa5g", buf);
-	READ_FROM_NVRAM(ant_available_bg, "aa2g", buf);
-	READ_FROM_NVRAM(pa0b0, "pa0b0", buf);
-	READ_FROM_NVRAM(pa0b1, "pa0b1", buf);
-	READ_FROM_NVRAM(pa0b2, "pa0b2", buf);
-	READ_FROM_NVRAM(pa1b0, "pa1b0", buf);
-	READ_FROM_NVRAM(pa1b1, "pa1b1", buf);
-	READ_FROM_NVRAM(pa1b2, "pa1b2", buf);
-	READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf);
-	READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf);
-	READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf);
-	READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
-	READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
-	READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
-	READ_FROM_NVRAM2(gpio0, "ledbh0", "wl0gpio0", buf);
-	READ_FROM_NVRAM2(gpio1, "ledbh1", "wl0gpio1", buf);
-	READ_FROM_NVRAM2(gpio2, "ledbh2", "wl0gpio2", buf);
-	READ_FROM_NVRAM2(gpio3, "ledbh3", "wl0gpio3", buf);
-	READ_FROM_NVRAM2(maxpwr_bg, "maxp2ga0", "pa0maxpwr", buf);
-	READ_FROM_NVRAM2(maxpwr_al, "maxp5gla0", "pa1lomaxpwr", buf);
-	READ_FROM_NVRAM2(maxpwr_a, "maxp5ga0", "pa1maxpwr", buf);
-	READ_FROM_NVRAM2(maxpwr_ah, "maxp5gha0", "pa1himaxpwr", buf);
-	READ_FROM_NVRAM2(itssi_bg, "itt5ga0", "pa0itssit", buf);
-	READ_FROM_NVRAM2(itssi_a, "itt2ga0", "pa1itssit", buf);
-	READ_FROM_NVRAM(tri2g, "tri2g", buf);
-	READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
-	READ_FROM_NVRAM(tri5g, "tri5g", buf);
-	READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
-	READ_FROM_NVRAM(txpid2g[0], "txpid2ga0", buf);
-	READ_FROM_NVRAM(txpid2g[1], "txpid2ga1", buf);
-	READ_FROM_NVRAM(txpid2g[2], "txpid2ga2", buf);
-	READ_FROM_NVRAM(txpid2g[3], "txpid2ga3", buf);
-	READ_FROM_NVRAM(txpid5g[0], "txpid5ga0", buf);
-	READ_FROM_NVRAM(txpid5g[1], "txpid5ga1", buf);
-	READ_FROM_NVRAM(txpid5g[2], "txpid5ga2", buf);
-	READ_FROM_NVRAM(txpid5g[3], "txpid5ga3", buf);
-	READ_FROM_NVRAM(txpid5gl[0], "txpid5gla0", buf);
-	READ_FROM_NVRAM(txpid5gl[1], "txpid5gla1", buf);
-	READ_FROM_NVRAM(txpid5gl[2], "txpid5gla2", buf);
-	READ_FROM_NVRAM(txpid5gl[3], "txpid5gla3", buf);
-	READ_FROM_NVRAM(txpid5gh[0], "txpid5gha0", buf);
-	READ_FROM_NVRAM(txpid5gh[1], "txpid5gha1", buf);
-	READ_FROM_NVRAM(txpid5gh[2], "txpid5gha2", buf);
-	READ_FROM_NVRAM(txpid5gh[3], "txpid5gha3", buf);
-	READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
-	READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
-	READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
-	READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf);
-	READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf);
-	READ_FROM_NVRAM(bxa2g, "bxa2g", buf);
-	READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf);
-	READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf);
-	READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
-	READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
-	READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
-
-	sprom->ofdm2gpo = nvram_getu32("ofdm2gpo", buf, sizeof(buf));
-	sprom->ofdm5glpo = nvram_getu32("ofdm5glpo", buf, sizeof(buf));
-	sprom->ofdm5gpo = nvram_getu32("ofdm5gpo", buf, sizeof(buf));
-	sprom->ofdm5ghpo = nvram_getu32("ofdm5ghpo", buf, sizeof(buf));
-
-	READ_FROM_NVRAM(antenna_gain.ghz24.a0, "ag0", buf);
-	READ_FROM_NVRAM(antenna_gain.ghz24.a1, "ag1", buf);
-	READ_FROM_NVRAM(antenna_gain.ghz24.a2, "ag2", buf);
-	READ_FROM_NVRAM(antenna_gain.ghz24.a3, "ag3", buf);
-	memcpy(&sprom->antenna_gain.ghz5, &sprom->antenna_gain.ghz24,
-	       sizeof(sprom->antenna_gain.ghz5));
-
-	if (nvram_getprefix(prefix, "boardflags", buf, sizeof(buf)) >= 0) {
-		boardflags = simple_strtoul(buf, NULL, 0);
-		if (boardflags) {
-			sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
-			sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
-		}
-	}
-	if (nvram_getprefix(prefix, "boardflags2", buf, sizeof(buf)) >= 0) {
-		boardflags = simple_strtoul(buf, NULL, 0);
-		if (boardflags) {
-			sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
-			sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16;
-		}
-	}
-}
-
-int bcm47xx_get_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
+static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
 {
 	char prefix[10];
 
@@ -251,7 +102,7 @@
 }
 
 static int bcm47xx_get_invariants(struct ssb_bus *bus,
-				   struct ssb_init_invariants *iv)
+				  struct ssb_init_invariants *iv)
 {
 	char buf[20];
 
@@ -281,7 +132,7 @@
 	char buf[100];
 	struct ssb_mipscore *mcore;
 
-	err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom);
+	err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb);
 	if (err)
 		printk(KERN_WARNING "bcm47xx: someone else already registered"
 			" a ssb SPROM callback handler (err %d)\n", err);
@@ -308,10 +159,41 @@
 #endif
 
 #ifdef CONFIG_BCM47XX_BCMA
+static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
+{
+	char prefix[10];
+	struct bcma_device *core;
+
+	switch (bus->hosttype) {
+	case BCMA_HOSTTYPE_PCI:
+		snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
+			 bus->host_pci->bus->number + 1,
+			 PCI_SLOT(bus->host_pci->devfn));
+		bcm47xx_fill_sprom(out, prefix);
+		return 0;
+	case BCMA_HOSTTYPE_SOC:
+		bcm47xx_fill_sprom_ethernet(out, NULL);
+		core = bcma_find_core(bus, BCMA_CORE_80211);
+		if (core) {
+			snprintf(prefix, sizeof(prefix), "sb/%u/",
+				 core->core_index);
+			bcm47xx_fill_sprom(out, prefix);
+		}
+		return 0;
+	default:
+		pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
+		return -EINVAL;
+	}
+}
+
 static void __init bcm47xx_register_bcma(void)
 {
 	int err;
 
+	err = bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma);
+	if (err)
+		pr_warn("bcm47xx: someone else already registered a bcma SPROM callback handler (err %d)\n", err);
+
 	err = bcma_host_soc_register(&bcm47xx_bus.bcma);
 	if (err)
 		panic("Failed to initialize BCMA bus (err %d)", err);
diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c
new file mode 100644
index 0000000..5c8dcd2
--- /dev/null
+++ b/arch/mips/bcm47xx/sprom.c
@@ -0,0 +1,620 @@
+/*
+ *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
+ *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ *  Copyright (C) 2006 Michael Buesch <m@bues.ch>
+ *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
+ *  Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <bcm47xx.h>
+#include <nvram.h>
+
+static void create_key(const char *prefix, const char *postfix,
+		       const char *name, char *buf, int len)
+{
+	if (prefix && postfix)
+		snprintf(buf, len, "%s%s%s", prefix, name, postfix);
+	else if (prefix)
+		snprintf(buf, len, "%s%s", prefix, name);
+	else if (postfix)
+		snprintf(buf, len, "%s%s", name, postfix);
+	else
+		snprintf(buf, len, "%s", name);
+}
+
+#define NVRAM_READ_VAL(type)						\
+static void nvram_read_ ## type (const char *prefix,			\
+				 const char *postfix, const char *name,	\
+				 type *val, type allset)		\
+{									\
+	char buf[100];							\
+	char key[40];							\
+	int err;							\
+	type var;							\
+									\
+	create_key(prefix, postfix, name, key, sizeof(key));		\
+									\
+	err = nvram_getenv(key, buf, sizeof(buf));			\
+	if (err < 0)							\
+		return;							\
+	err = kstrto ## type (buf, 0, &var);				\
+	if (err) {							\
+		pr_warn("can not parse nvram name %s with value %s"	\
+			" got %i", key, buf, err);			\
+		return;							\
+	}								\
+	if (allset && var == allset)					\
+		return;							\
+	*val = var;							\
+}
+
+NVRAM_READ_VAL(u8)
+NVRAM_READ_VAL(s8)
+NVRAM_READ_VAL(u16)
+NVRAM_READ_VAL(u32)
+
+#undef NVRAM_READ_VAL
+
+static void nvram_read_u32_2(const char *prefix, const char *name,
+			     u16 *val_lo, u16 *val_hi)
+{
+	char buf[100];
+	char key[40];
+	int err;
+	u32 val;
+
+	create_key(prefix, NULL, name, key, sizeof(key));
+
+	err = nvram_getenv(key, buf, sizeof(buf));
+	if (err < 0)
+		return;
+	err = kstrtou32(buf, 0, &val);
+	if (err) {
+		pr_warn("can not parse nvram name %s with value %s got %i",
+			key, buf, err);
+		return;
+	}
+	*val_lo = (val & 0x0000FFFFU);
+	*val_hi = (val & 0xFFFF0000U) >> 16;
+}
+
+static void nvram_read_leddc(const char *prefix, const char *name,
+			     u8 *leddc_on_time, u8 *leddc_off_time)
+{
+	char buf[100];
+	char key[40];
+	int err;
+	u32 val;
+
+	create_key(prefix, NULL, name, key, sizeof(key));
+
+	err = nvram_getenv(key, buf, sizeof(buf));
+	if (err < 0)
+		return;
+	err = kstrtou32(buf, 0, &val);
+	if (err) {
+		pr_warn("can not parse nvram name %s with value %s got %i",
+			key, buf, err);
+		return;
+	}
+
+	if (val == 0xffff || val == 0xffffffff)
+		return;
+
+	*leddc_on_time = val & 0xff;
+	*leddc_off_time = (val >> 16) & 0xff;
+}
+
+static void nvram_read_macaddr(const char *prefix, const char *name,
+			       u8 (*val)[6])
+{
+	char buf[100];
+	char key[40];
+	int err;
+
+	create_key(prefix, NULL, name, key, sizeof(key));
+
+	err = nvram_getenv(key, buf, sizeof(buf));
+	if (err < 0)
+		return;
+	nvram_parse_macaddr(buf, *val);
+}
+
+static void nvram_read_alpha2(const char *prefix, const char *name,
+			     char (*val)[2])
+{
+	char buf[10];
+	char key[40];
+	int err;
+
+	create_key(prefix, NULL, name, key, sizeof(key));
+
+	err = nvram_getenv(key, buf, sizeof(buf));
+	if (err < 0)
+		return;
+	if (buf[0] == '0')
+		return;
+	if (strlen(buf) > 2) {
+		pr_warn("alpha2 is too long %s", buf);
+		return;
+	}
+	memcpy(val, buf, sizeof(val));
+}
+
+static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
+					const char *prefix)
+{
+	nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0);
+	nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0);
+	nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff);
+	nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff);
+	nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff);
+	nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff);
+	nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0);
+	nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0);
+	nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0);
+	nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0);
+	nvram_read_alpha2(prefix, "ccode", &sprom->alpha2);
+}
+
+static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom,
+				      const char *prefix)
+{
+	nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0);
+	nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0);
+	nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0);
+	nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0);
+	nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0);
+	nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0);
+	nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0);
+	nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0);
+	nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0);
+	nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0);
+}
+
+static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix)
+{
+	nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0);
+	nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0);
+}
+
+static void bcm47xx_fill_sprom_r2389(struct ssb_sprom *sprom,
+				     const char *prefix)
+{
+	nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0);
+	nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0);
+	nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0);
+	nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0);
+	nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0);
+	nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0);
+	nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0);
+	nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0);
+	nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0);
+}
+
+static void bcm47xx_fill_sprom_r2(struct ssb_sprom *sprom, const char *prefix)
+{
+	nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
+			 &sprom->boardflags_hi);
+	nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
+}
+
+static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix)
+{
+	nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0);
+	nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0);
+	nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0);
+	nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0);
+	nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0);
+	nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0);
+	nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0);
+	nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0);
+	nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0);
+	nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0);
+	nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0);
+	nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0);
+	nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0);
+	nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0);
+}
+
+static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix)
+{
+	nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
+			 &sprom->boardflags_hi);
+	nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
+	nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
+	nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
+			 &sprom->leddc_off_time);
+}
+
+static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom,
+				     const char *prefix)
+{
+	nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
+			 &sprom->boardflags_hi);
+	nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
+			 &sprom->boardflags2_hi);
+	nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
+	nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
+	nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0);
+	nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0);
+	nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf);
+	nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf);
+	nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff);
+	nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
+			 &sprom->leddc_off_time);
+}
+
+static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix)
+{
+	nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0);
+	nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0);
+	nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0);
+	nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0);
+	nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0);
+	nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0);
+	nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0);
+	nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0);
+	nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0);
+	nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0);
+	nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0);
+	nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0);
+	nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0);
+	nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0);
+	nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0);
+	nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0);
+	nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0);
+	nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0);
+	nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0);
+	nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0);
+	nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0);
+	nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0);
+	nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0);
+	nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0);
+	nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0);
+	nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0);
+	nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0);
+	nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0);
+	nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0);
+	nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0);
+	nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0);
+	nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0);
+	nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0);
+}
+
+static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix)
+{
+	nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0);
+	nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0);
+	nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0);
+	nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0);
+	nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0);
+	nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0);
+	nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0);
+	nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0);
+	nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0);
+	nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0);
+	nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0);
+	nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0);
+	nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0);
+	nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0);
+	nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0);
+	nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0);
+}
+
+static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix)
+{
+	nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0);
+	nvram_read_u8(prefix, NULL, "extpagain2g",
+		      &sprom->fem.ghz2.extpa_gain, 0);
+	nvram_read_u8(prefix, NULL, "pdetrange2g",
+		      &sprom->fem.ghz2.pdet_range, 0);
+	nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0);
+	nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0);
+	nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0);
+	nvram_read_u8(prefix, NULL, "extpagain5g",
+		      &sprom->fem.ghz5.extpa_gain, 0);
+	nvram_read_u8(prefix, NULL, "pdetrange5g",
+		      &sprom->fem.ghz5.pdet_range, 0);
+	nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0);
+	nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0);
+	nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0);
+	nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0);
+	nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0);
+	nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0);
+	nvram_read_u8(prefix, NULL, "tempsense_slope",
+		      &sprom->tempsense_slope, 0);
+	nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0);
+	nvram_read_u8(prefix, NULL, "tempsense_option",
+		      &sprom->tempsense_option, 0);
+	nvram_read_u8(prefix, NULL, "freqoffset_corr",
+		      &sprom->freqoffset_corr, 0);
+	nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0);
+	nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0);
+	nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0);
+	nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0);
+	nvram_read_u8(prefix, NULL, "phycal_tempdelta",
+		      &sprom->phycal_tempdelta, 0);
+	nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0);
+	nvram_read_u8(prefix, NULL, "temps_hysteresis",
+		      &sprom->temps_hysteresis, 0);
+	nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0);
+	nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr2ga0",
+		      &sprom->rxgainerr2ga[0], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr2ga1",
+		      &sprom->rxgainerr2ga[1], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr2ga2",
+		      &sprom->rxgainerr2ga[2], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gla0",
+		      &sprom->rxgainerr5gla[0], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gla1",
+		      &sprom->rxgainerr5gla[1], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gla2",
+		      &sprom->rxgainerr5gla[2], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gma0",
+		      &sprom->rxgainerr5gma[0], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gma1",
+		      &sprom->rxgainerr5gma[1], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gma2",
+		      &sprom->rxgainerr5gma[2], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gha0",
+		      &sprom->rxgainerr5gha[0], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gha1",
+		      &sprom->rxgainerr5gha[1], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gha2",
+		      &sprom->rxgainerr5gha[2], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gua0",
+		      &sprom->rxgainerr5gua[0], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gua1",
+		      &sprom->rxgainerr5gua[1], 0);
+	nvram_read_u8(prefix, NULL, "rxgainerr5gua2",
+		      &sprom->rxgainerr5gua[2], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gla0",
+		      &sprom->noiselvl5gla[0], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gla1",
+		      &sprom->noiselvl5gla[1], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gla2",
+		      &sprom->noiselvl5gla[2], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gma0",
+		      &sprom->noiselvl5gma[0], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gma1",
+		      &sprom->noiselvl5gma[1], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gma2",
+		      &sprom->noiselvl5gma[2], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gha0",
+		      &sprom->noiselvl5gha[0], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gha1",
+		      &sprom->noiselvl5gha[1], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gha2",
+		      &sprom->noiselvl5gha[2], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gua0",
+		      &sprom->noiselvl5gua[0], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gua1",
+		      &sprom->noiselvl5gua[1], 0);
+	nvram_read_u8(prefix, NULL, "noiselvl5gua2",
+		      &sprom->noiselvl5gua[2], 0);
+	nvram_read_u8(prefix, NULL, "pcieingress_war",
+		      &sprom->pcieingress_war, 0);
+}
+
+static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix)
+{
+	nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0);
+	nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0);
+	nvram_read_u32(prefix, NULL, "legofdmbw202gpo",
+		       &sprom->legofdmbw202gpo, 0);
+	nvram_read_u32(prefix, NULL, "legofdmbw20ul2gpo",
+		       &sprom->legofdmbw20ul2gpo, 0);
+	nvram_read_u32(prefix, NULL, "legofdmbw205glpo",
+		       &sprom->legofdmbw205glpo, 0);
+	nvram_read_u32(prefix, NULL, "legofdmbw20ul5glpo",
+		       &sprom->legofdmbw20ul5glpo, 0);
+	nvram_read_u32(prefix, NULL, "legofdmbw205gmpo",
+		       &sprom->legofdmbw205gmpo, 0);
+	nvram_read_u32(prefix, NULL, "legofdmbw20ul5gmpo",
+		       &sprom->legofdmbw20ul5gmpo, 0);
+	nvram_read_u32(prefix, NULL, "legofdmbw205ghpo",
+		       &sprom->legofdmbw205ghpo, 0);
+	nvram_read_u32(prefix, NULL, "legofdmbw20ul5ghpo",
+		       &sprom->legofdmbw20ul5ghpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw20ul5glpo",
+		       &sprom->mcsbw20ul5glpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw20ul5gmpo",
+		       &sprom->mcsbw20ul5gmpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw20ul5ghpo",
+		       &sprom->mcsbw20ul5ghpo, 0);
+	nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0);
+	nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0);
+	nvram_read_u16(prefix, NULL, "legofdm40duppo",
+		       &sprom->legofdm40duppo, 0);
+	nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0);
+	nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0);
+}
+
+static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
+					  const char *prefix)
+{
+	char postfix[2];
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
+		struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+		snprintf(postfix, sizeof(postfix), "%i", i);
+		nvram_read_u8(prefix, postfix, "maxp2ga",
+			      &pwr_info->maxpwr_2g, 0);
+		nvram_read_u8(prefix, postfix, "itt2ga",
+			      &pwr_info->itssi_2g, 0);
+		nvram_read_u8(prefix, postfix, "itt5ga",
+			      &pwr_info->itssi_5g, 0);
+		nvram_read_u16(prefix, postfix, "pa2gw0a",
+			       &pwr_info->pa_2g[0], 0);
+		nvram_read_u16(prefix, postfix, "pa2gw1a",
+			       &pwr_info->pa_2g[1], 0);
+		nvram_read_u16(prefix, postfix, "pa2gw2a",
+			       &pwr_info->pa_2g[2], 0);
+		nvram_read_u8(prefix, postfix, "maxp5ga",
+			      &pwr_info->maxpwr_5g, 0);
+		nvram_read_u8(prefix, postfix, "maxp5gha",
+			      &pwr_info->maxpwr_5gh, 0);
+		nvram_read_u8(prefix, postfix, "maxp5gla",
+			      &pwr_info->maxpwr_5gl, 0);
+		nvram_read_u16(prefix, postfix, "pa5gw0a",
+			       &pwr_info->pa_5g[0], 0);
+		nvram_read_u16(prefix, postfix, "pa5gw1a",
+			       &pwr_info->pa_5g[1], 0);
+		nvram_read_u16(prefix, postfix, "pa5gw2a",
+			       &pwr_info->pa_5g[2], 0);
+		nvram_read_u16(prefix, postfix, "pa5glw0a",
+			       &pwr_info->pa_5gl[0], 0);
+		nvram_read_u16(prefix, postfix, "pa5glw1a",
+			       &pwr_info->pa_5gl[1], 0);
+		nvram_read_u16(prefix, postfix, "pa5glw2a",
+			       &pwr_info->pa_5gl[2], 0);
+		nvram_read_u16(prefix, postfix, "pa5ghw0a",
+			       &pwr_info->pa_5gh[0], 0);
+		nvram_read_u16(prefix, postfix, "pa5ghw1a",
+			       &pwr_info->pa_5gh[1], 0);
+		nvram_read_u16(prefix, postfix, "pa5ghw2a",
+			       &pwr_info->pa_5gh[2], 0);
+	}
+}
+
+static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
+					const char *prefix)
+{
+	char postfix[2];
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
+		struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+		snprintf(postfix, sizeof(postfix), "%i", i);
+		nvram_read_u16(prefix, postfix, "pa2gw3a",
+			       &pwr_info->pa_2g[3], 0);
+		nvram_read_u16(prefix, postfix, "pa5gw3a",
+			       &pwr_info->pa_5g[3], 0);
+		nvram_read_u16(prefix, postfix, "pa5glw3a",
+			       &pwr_info->pa_5gl[3], 0);
+		nvram_read_u16(prefix, postfix, "pa5ghw3a",
+			       &pwr_info->pa_5gh[3], 0);
+	}
+}
+
+void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix)
+{
+	nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac);
+	nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0);
+	nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0);
+
+	nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac);
+	nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0);
+	nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0);
+
+	nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac);
+	nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac);
+}
+
+void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
+{
+	memset(sprom, 0, sizeof(struct ssb_sprom));
+
+	bcm47xx_fill_sprom_ethernet(sprom, prefix);
+
+	nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0);
+
+	switch (sprom->revision) {
+	case 1:
+		bcm47xx_fill_sprom_r1234589(sprom, prefix);
+		bcm47xx_fill_sprom_r12389(sprom, prefix);
+		bcm47xx_fill_sprom_r1(sprom, prefix);
+		break;
+	case 2:
+		bcm47xx_fill_sprom_r1234589(sprom, prefix);
+		bcm47xx_fill_sprom_r12389(sprom, prefix);
+		bcm47xx_fill_sprom_r2389(sprom, prefix);
+		bcm47xx_fill_sprom_r2(sprom, prefix);
+		break;
+	case 3:
+		bcm47xx_fill_sprom_r1234589(sprom, prefix);
+		bcm47xx_fill_sprom_r12389(sprom, prefix);
+		bcm47xx_fill_sprom_r2389(sprom, prefix);
+		bcm47xx_fill_sprom_r389(sprom, prefix);
+		bcm47xx_fill_sprom_r3(sprom, prefix);
+		break;
+	case 4:
+	case 5:
+		bcm47xx_fill_sprom_r1234589(sprom, prefix);
+		bcm47xx_fill_sprom_r4589(sprom, prefix);
+		bcm47xx_fill_sprom_r458(sprom, prefix);
+		bcm47xx_fill_sprom_r45(sprom, prefix);
+		bcm47xx_fill_sprom_path_r4589(sprom, prefix);
+		bcm47xx_fill_sprom_path_r45(sprom, prefix);
+		break;
+	case 8:
+		bcm47xx_fill_sprom_r1234589(sprom, prefix);
+		bcm47xx_fill_sprom_r12389(sprom, prefix);
+		bcm47xx_fill_sprom_r2389(sprom, prefix);
+		bcm47xx_fill_sprom_r389(sprom, prefix);
+		bcm47xx_fill_sprom_r4589(sprom, prefix);
+		bcm47xx_fill_sprom_r458(sprom, prefix);
+		bcm47xx_fill_sprom_r89(sprom, prefix);
+		bcm47xx_fill_sprom_path_r4589(sprom, prefix);
+		break;
+	case 9:
+		bcm47xx_fill_sprom_r1234589(sprom, prefix);
+		bcm47xx_fill_sprom_r12389(sprom, prefix);
+		bcm47xx_fill_sprom_r2389(sprom, prefix);
+		bcm47xx_fill_sprom_r389(sprom, prefix);
+		bcm47xx_fill_sprom_r4589(sprom, prefix);
+		bcm47xx_fill_sprom_r89(sprom, prefix);
+		bcm47xx_fill_sprom_r9(sprom, prefix);
+		bcm47xx_fill_sprom_path_r4589(sprom, prefix);
+		break;
+	default:
+		pr_warn("Unsupported SPROM revision %d detected. Will extract"
+			" v1\n", sprom->revision);
+		sprom->revision = 1;
+		bcm47xx_fill_sprom_r1234589(sprom, prefix);
+		bcm47xx_fill_sprom_r12389(sprom, prefix);
+		bcm47xx_fill_sprom_r1(sprom, prefix);
+	}
+}
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
index de95e07..5ecaf47 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -44,4 +44,7 @@
 extern union bcm47xx_bus bcm47xx_bus;
 extern enum bcm47xx_bus_type bcm47xx_bus_type;
 
+void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix);
+void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix);
+
 #endif /* __ASM_BCM47XX_H */
diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h
index 184d5ec..69ef3ef 100644
--- a/arch/mips/include/asm/mach-bcm47xx/nvram.h
+++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h
@@ -37,7 +37,7 @@
 
 extern int nvram_getenv(char *name, char *val, size_t val_len);
 
-static inline void nvram_parse_macaddr(char *buf, u8 *macaddr)
+static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6])
 {
 	if (strchr(buf, ':'))
 		sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 800163c..a058842 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -80,6 +80,7 @@
 		min_msk = 0x200D;
 		max_msk = 0xFFFF;
 		break;
+	case 0x4331:
 	case 43224:
 	case 43225:
 		break;
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index b8379b9..7e138ec 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -61,7 +61,7 @@
 	.dev_attrs	= bcma_device_attrs,
 };
 
-static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
+struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
 {
 	struct bcma_device *core;
 
@@ -71,6 +71,7 @@
 	}
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(bcma_find_core);
 
 static void bcma_release_core_dev(struct device *dev)
 {
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index ca77525..cdcf75c 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -2,6 +2,8 @@
  * Broadcom specific AMBA
  * SPROM reading
  *
+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
 
@@ -14,6 +16,58 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 
+static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
+
+/**
+ * bcma_arch_register_fallback_sprom - Registers a method providing a
+ * fallback SPROM if no SPROM is found.
+ *
+ * @sprom_callback: The callback function.
+ *
+ * With this function the architecture implementation may register a
+ * callback handler which fills the SPROM data structure. The fallback is
+ * used for PCI based BCMA devices, where no valid SPROM can be found
+ * in the shadow registers and to provide the SPROM for SoCs where BCMA is
+ * to controll the system bus.
+ *
+ * This function is useful for weird architectures that have a half-assed
+ * BCMA device hardwired to their PCI bus.
+ *
+ * This function is available for architecture code, only. So it is not
+ * exported.
+ */
+int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus,
+				     struct ssb_sprom *out))
+{
+	if (get_fallback_sprom)
+		return -EEXIST;
+	get_fallback_sprom = sprom_callback;
+
+	return 0;
+}
+
+static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
+					 struct ssb_sprom *out)
+{
+	int err;
+
+	if (!get_fallback_sprom) {
+		err = -ENOENT;
+		goto fail;
+	}
+
+	err = get_fallback_sprom(bus, out);
+	if (err)
+		goto fail;
+
+	pr_debug("Using SPROM revision %d provided by"
+		 " platform.\n", bus->sprom.revision);
+	return 0;
+fail:
+	pr_warn("Using fallback SPROM failed (err %d)\n", err);
+	return err;
+}
+
 /**************************************************
  * R/W ops.
  **************************************************/
@@ -246,23 +300,128 @@
 	     SSB_SROM8_FEM_ANTSWLUT_SHIFT);
 }
 
+/*
+ * Indicates the presence of external SPROM.
+ */
+static bool bcma_sprom_ext_available(struct bcma_bus *bus)
+{
+	u32 chip_status;
+	u32 srom_control;
+	u32 present_mask;
+
+	if (bus->drv_cc.core->id.rev >= 31) {
+		if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
+			return false;
+
+		srom_control = bcma_read32(bus->drv_cc.core,
+					   BCMA_CC_SROM_CONTROL);
+		return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
+	}
+
+	/* older chipcommon revisions use chip status register */
+	chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
+	switch (bus->chipinfo.id) {
+	case 0x4313:
+		present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
+		break;
+
+	case 0x4331:
+		present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
+		break;
+
+	default:
+		return true;
+	}
+
+	return chip_status & present_mask;
+}
+
+/*
+ * Indicates that on-chip OTP memory is present and enabled.
+ */
+static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
+{
+	u32 chip_status;
+	u32 otpsize = 0;
+	bool present;
+
+	chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
+	switch (bus->chipinfo.id) {
+	case 0x4313:
+		present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
+		break;
+
+	case 0x4331:
+		present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
+		break;
+
+	case 43224:
+	case 43225:
+		/* for these chips OTP is always available */
+		present = true;
+		break;
+
+	default:
+		present = false;
+		break;
+	}
+
+	if (present) {
+		otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
+		otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
+	}
+
+	return otpsize != 0;
+}
+
+/*
+ * Verify OTP is filled and determine the byte
+ * offset where SPROM data is located.
+ *
+ * On error, returns 0; byte offset otherwise.
+ */
+static int bcma_sprom_onchip_offset(struct bcma_bus *bus)
+{
+	struct bcma_device *cc = bus->drv_cc.core;
+	u32 offset;
+
+	/* verify OTP status */
+	if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0)
+		return 0;
+
+	/* obtain bit offset from otplayout register */
+	offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET);
+	return BCMA_CC_SPROM + (offset >> 3);
+}
+
 int bcma_sprom_get(struct bcma_bus *bus)
 {
-	u16 offset;
+	u16 offset = BCMA_CC_SPROM;
 	u16 *sprom;
-	u32 sromctrl;
 	int err = 0;
 
 	if (!bus->drv_cc.core)
 		return -EOPNOTSUPP;
 
-	if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
-		return -ENOENT;
-
-	if (bus->drv_cc.core->id.rev >= 32) {
-		sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
-		if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT))
-			return -ENOENT;
+	if (!bcma_sprom_ext_available(bus)) {
+		/*
+		 * External SPROM takes precedence so check
+		 * on-chip OTP only when no external SPROM
+		 * is present.
+		 */
+		if (bcma_sprom_onchip_available(bus)) {
+			/* determine offset */
+			offset = bcma_sprom_onchip_offset(bus);
+		}
+		if (!offset) {
+			/*
+			 * Maybe there is no SPROM on the device?
+			 * Now we ask the arch code if there is some sprom
+			 * available for this device in some other storage.
+			 */
+			err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
+			return err;
+		}
 	}
 
 	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
@@ -273,11 +432,6 @@
 	if (bus->chipinfo.id == 0x4331)
 		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
 
-	/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
-	 * According to brcm80211 this applies to cards with PCIe rev >= 6
-	 * TODO: understand this condition and use it */
-	offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
-		BCMA_CC_SPROM_PCIE6;
 	pr_debug("SPROM offset 0x%x\n", offset);
 	bcma_sprom_read(bus, offset, sprom);
 
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 1c008c6..ddc061d 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1869,7 +1869,7 @@
 
 static void try_auto_wep(struct airo_info *ai)
 {
-	if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) {
+	if (auto_wep && !test_bit(FLAG_RADIO_DOWN, &ai->flags)) {
 		ai->expires = RUN_AT(3*HZ);
 		wake_up_interruptible(&ai->thr_wait);
 	}
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index efc0111..c54b7d37 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -174,28 +174,24 @@
 void ath_hw_cycle_counters_update(struct ath_common *common);
 int32_t ath_hw_get_listen_time(struct ath_common *common);
 
-extern __printf(2, 3) void ath_printk(const char *level, const char *fmt, ...);
-
-#define _ath_printk(level, common, fmt, ...)			\
-do {								\
-	__always_unused struct ath_common *unused = common;	\
-	ath_printk(level, fmt, ##__VA_ARGS__);			\
-} while (0)
+__printf(3, 4)
+void ath_printk(const char *level, const struct ath_common *common,
+		const char *fmt, ...);
 
 #define ath_emerg(common, fmt, ...)				\
-	_ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__)
+	ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__)
 #define ath_alert(common, fmt, ...)				\
-	_ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__)
+	ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__)
 #define ath_crit(common, fmt, ...)				\
-	_ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__)
+	ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__)
 #define ath_err(common, fmt, ...)				\
-	_ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__)
+	ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__)
 #define ath_warn(common, fmt, ...)				\
-	_ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__)
+	ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__)
 #define ath_notice(common, fmt, ...)				\
-	_ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__)
+	ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__)
 #define ath_info(common, fmt, ...)				\
-	_ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__)
+	ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__)
 
 /**
  * enum ath_debug_level - atheros wireless debug level
@@ -256,7 +252,7 @@
 #define ath_dbg(common, dbg_mask, fmt, ...)				\
 do {									\
 	if ((common)->debug_mask & ATH_DBG_##dbg_mask)			\
-		_ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__);	\
+		ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__);	\
 } while (0)
 
 #define ATH_DBG_WARN(foo, arg...) WARN(foo, arg)
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 6640326..8d434b8f 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1320,6 +1320,7 @@
 	struct ieee80211_vif	*bslot[ATH_BCBUF];
 	u16			num_ap_vifs;
 	u16			num_adhoc_vifs;
+	u16			num_mesh_vifs;
 	unsigned int		bhalq,		/* SW q for outgoing beacons */
 				bmisscount,	/* missed beacon transmits */
 				bintval,	/* beacon interval in TU */
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index a339693..0e643b0 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1867,7 +1867,8 @@
 		ah->bmisscount = 0;
 	}
 
-	if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) ||
+	if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
+			ah->num_mesh_vifs > 1) ||
 			ah->opmode == NL80211_IFTYPE_MESH_POINT) {
 		u64 tsf = ath5k_hw_get_tsf64(ah);
 		u32 tsftu = TSF_TO_TU(tsf);
@@ -1952,7 +1953,8 @@
 	u64 hw_tsf;
 
 	intval = ah->bintval & AR5K_BEACON_PERIOD;
-	if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) {
+	if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
+		+ ah->num_mesh_vifs > 1) {
 		intval /= ATH_BCBUF;	/* staggered multi-bss beacons */
 		if (intval < 15)
 			ATH5K_WARN(ah, "intval %u is too low, min 15\n",
@@ -2330,15 +2332,6 @@
 					"got new rfgain, resetting\n");
 			ieee80211_queue_work(ah->hw, &ah->reset_work);
 		}
-
-		/* TODO: On full calibration we should stop TX here,
-		 * so that it doesn't interfere (mostly due to gain_f
-		 * calibration that messes with tx packets -see phy.c).
-		 *
-		 * NOTE: Stopping the queues from above is not enough
-		 * to stop TX but saves us from disconecting (at least
-		 * we don't lose packets). */
-		ieee80211_stop_queues(ah->hw);
 	} else
 		ah->ah_cal_mask |= AR5K_CALIBRATION_SHORT;
 
@@ -2353,10 +2346,9 @@
 				ah->curchan->center_freq));
 
 	/* Clear calibration flags */
-	if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) {
-		ieee80211_wake_queues(ah->hw);
+	if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL)
 		ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;
-	} else if (ah->ah_cal_mask & AR5K_CALIBRATION_SHORT)
+	else if (ah->ah_cal_mask & AR5K_CALIBRATION_SHORT)
 		ah->ah_cal_mask &= ~AR5K_CALIBRATION_SHORT;
 }
 
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index af4c7ec..5c53299 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -134,6 +134,8 @@
 			ah->num_ap_vifs++;
 		else if (avf->opmode == NL80211_IFTYPE_ADHOC)
 			ah->num_adhoc_vifs++;
+		else if (avf->opmode == NL80211_IFTYPE_MESH_POINT)
+			ah->num_mesh_vifs++;
 	}
 
 	/* Any MAC address is fine, all others are included through the
@@ -175,6 +177,8 @@
 		ah->num_ap_vifs--;
 	else if (avf->opmode == NL80211_IFTYPE_ADHOC)
 		ah->num_adhoc_vifs--;
+	else if (avf->opmode == NL80211_IFTYPE_MESH_POINT)
+		ah->num_mesh_vifs--;
 
 	ath5k_update_bssid_mask_and_opmode(ah, NULL);
 	mutex_unlock(&ah->lock);
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index e1f8613..3a28454 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1871,31 +1871,15 @@
 		ret = 0;
 	}
 
-	/* On full calibration do an AGC calibration and
-	 * request a PAPD probe for gainf calibration if
-	 * needed */
-	if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) {
+	/* On full calibration request a PAPD probe for
+	 * gainf calibration if needed */
+	if ((ah->ah_cal_mask & AR5K_CALIBRATION_FULL) &&
+	    (ah->ah_radio == AR5K_RF5111 ||
+	     ah->ah_radio == AR5K_RF5112) &&
+	    channel->hw_value != AR5K_MODE_11B)
+		ath5k_hw_request_rfgain_probe(ah);
 
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
-					AR5K_PHY_AGCCTL_CAL);
-
-		ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
-			AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF,
-			0, false);
-		if (ret) {
-			ATH5K_ERR(ah,
-				"gain calibration timeout (%uMHz)\n",
-				channel->center_freq);
-		}
-
-		if ((ah->ah_radio == AR5K_RF5111 ||
-			ah->ah_radio == AR5K_RF5112)
-			&& (channel->hw_value != AR5K_MODE_11B))
-			ath5k_hw_request_rfgain_probe(ah);
-	}
-
-	/* Update noise floor
-	 * XXX: Only do this after AGC calibration */
+	/* Update noise floor */
 	if (!(ah->ah_cal_mask & AR5K_CALIBRATION_NF))
 		ath5k_hw_update_noise_floor(ah);
 
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 16e4e5a..7654e8e 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -557,7 +557,8 @@
 		   dlen, freq, vif->probe_req_report);
 
 	if (vif->probe_req_report || vif->nw_type == AP_NETWORK)
-		cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC);
+		cfg80211_rx_mgmt(vif->ndev, freq, 0,
+				 ev->data, dlen, GFP_ATOMIC);
 
 	return 0;
 }
@@ -596,7 +597,8 @@
 		return -EINVAL;
 	}
 	ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
-	cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC);
+	cfg80211_rx_mgmt(vif->ndev, freq, 0,
+			 ev->data, dlen, GFP_ATOMIC);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 595a272..e507e78 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -81,6 +81,14 @@
 	  developed. At this point enabling this option won't do anything
 	  except increase code size.
 
+config ATH9K_MAC_DEBUG
+	bool "Atheros MAC statistics"
+	depends on ATH9K_DEBUGFS
+	default y
+	---help---
+	  This option enables collection of statistics for Rx/Tx status
+	  data and some other MAC related statistics
+
 config ATH9K_RATE_CONTROL
 	bool "Atheros ath9k rate control"
 	depends on ATH9K
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 86a891f..d7d8e91 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -834,9 +834,10 @@
 	    AR_SREV_9287_11_OR_LATER(ah))
 		REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
 
-	if (AR_SREV_9271_10(ah))
-		REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only,
-				modesIndex, regWrites);
+	if (AR_SREV_9271_10(ah)) {
+		REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENA);
+		REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_ADC_ON, 0xa);
+	}
 
 	ENABLE_REGWRITE_BUFFER(ah);
 
@@ -858,21 +859,11 @@
 
 	REGWRITE_BUFFER_FLUSH(ah);
 
-	if (AR_SREV_9271(ah)) {
-		if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1)
-			REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
-					modesIndex, regWrites);
-		else
-			REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
-					modesIndex, regWrites);
-	}
-
 	REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
 
-	if (IS_CHAN_A_FAST_CLOCK(ah, chan)) {
-		REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
+	if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+		REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex,
 				regWrites);
-	}
 
 	ar5008_hw_override_ini(ah, chan);
 	ar5008_hw_set_channel_regs(ah, chan);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index e3f2689..d9a69fc 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -34,23 +34,8 @@
 			       ARRAY_SIZE(ar9271Modes_9271), 5);
 		INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
 			       ARRAY_SIZE(ar9271Common_9271), 2);
-		INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
-			       ar9287Common_normal_cck_fir_coeff_9287_1_1,
-			       ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_9287_1_1), 2);
-		INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271,
-			       ar9287Common_japan_2484_cck_fir_coeff_9287_1_1,
-			       ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_9287_1_1), 2);
-		INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
-			       ar9271Modes_9271_1_0_only,
-			       ARRAY_SIZE(ar9271Modes_9271_1_0_only), 5);
 		INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
 			       ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5);
-		INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
-			       ar9271Modes_high_power_tx_gain_9271,
-			       ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
-		INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
-			       ar9271Modes_normal_power_tx_gain_9271,
-			       ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
 		return;
 	}
 
@@ -79,7 +64,7 @@
 		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
 			       ARRAY_SIZE(ar9280Common_9280_2), 2);
 
-		INIT_INI_ARRAY(&ah->iniModesAdditional,
+		INIT_INI_ARRAY(&ah->iniModesFastClock,
 			       ar9280Modes_fast_clock_9280_2,
 			       ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
 	} else if (AR_SREV_9160_10_OR_LATER(ah)) {
@@ -160,11 +145,6 @@
 			INI_RA(addac, 31,1) = 0;
 		}
 	}
-}
-
-/* Support for Japan ch.14 (2484) spread */
-void ar9002_hw_cck_chan14_spread(struct ath_hw *ah)
-{
 	if (AR_SREV_9287_11_OR_LATER(ah)) {
 		INIT_INI_ARRAY(&ah->iniCckfirNormal,
 		       ar9287Common_normal_cck_fir_coeff_9287_1_1,
@@ -204,14 +184,10 @@
 	}
 }
 
-static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
+static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
 {
-	u32 txgain_type;
-
 	if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
 	    AR5416_EEP_MINOR_VER_19) {
-		txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
-
 		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 			ar9280Modes_high_power_tx_gain_9280_2,
@@ -227,8 +203,22 @@
 	}
 }
 
+static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
+{
+	if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+			       ar9271Modes_high_power_tx_gain_9271,
+			       ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
+	else
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+			       ar9271Modes_normal_power_tx_gain_9271,
+			       ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
+}
+
 static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
 {
+	u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
+
 	if (AR_SREV_9287_11_OR_LATER(ah))
 		INIT_INI_ARRAY(&ah->iniModesRxGain,
 		ar9287Modes_rx_gain_9287_1_1,
@@ -236,15 +226,15 @@
 	else if (AR_SREV_9280_20(ah))
 		ar9280_20_hw_init_rxgain_ini(ah);
 
-	if (AR_SREV_9287_11_OR_LATER(ah)) {
+	if (AR_SREV_9271(ah)) {
+		ar9271_hw_init_txgain_ini(ah, txgain_type);
+	} else if (AR_SREV_9287_11_OR_LATER(ah)) {
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 		ar9287Modes_tx_gain_9287_1_1,
 		ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5);
 	} else if (AR_SREV_9280_20(ah)) {
-		ar9280_20_hw_init_txgain_ini(ah);
+		ar9280_20_hw_init_txgain_ini(ah, txgain_type);
 	} else if (AR_SREV_9285_12_OR_LATER(ah)) {
-		u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
-
 		/* txgain table */
 		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
 			if (AR_SREV_9285E_20(ah)) {
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
index d571c32..4d18c66 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
@@ -3092,12 +3092,6 @@
 	{0x0000d384, 0xf3307ff0},
 };
 
-static const u32 ar9271Modes_9271_1_0_only[][5] = {
-	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311},
-	{0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
-};
-
 static const u32 ar9271Modes_9271_ANI_reg[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
 	{0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 7b6417b..aa2abaf 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -347,15 +347,12 @@
 			  u32 size, u32 flags)
 {
 	struct ar5416_desc *ads = AR5416DESC(ds);
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
 
 	ads->ds_ctl1 = size & AR_BufLen;
 	if (flags & ATH9K_RXDESC_INTREQ)
 		ads->ds_ctl1 |= AR_RxIntrReq;
 
-	ads->ds_rxstatus8 &= ~AR_RxDone;
-	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
-		memset(&(ads->u), 0, sizeof(ads->u));
+	memset(&ads->u.rx, 0, sizeof(ads->u.rx));
 }
 EXPORT_SYMBOL(ath9k_hw_setuprxdesc);
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
index 453af6d..f9eb2c3 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
@@ -60,6 +60,8 @@
 #define AR_PHY_RF_CTL3                  0x9828
 #define AR_PHY_TX_END_TO_A2_RX_ON       0x00FF0000
 #define AR_PHY_TX_END_TO_A2_RX_ON_S     16
+#define AR_PHY_TX_END_TO_ADC_ON         0xFF000000
+#define AR_PHY_TX_END_TO_ADC_ON_S       24
 
 #define AR_PHY_ADC_CTL                  0x982C
 #define AR_PHY_ADC_CTL_OFF_INBUFGAIN    0x00000003
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
index 026f9de..46c79a3 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
@@ -295,266 +295,6 @@
 	{0x00016bd4, 0x00000000},
 };
 
-static const u32 ar9300Common_rx_gain_table_merlin_2p2[][2] = {
-	/* Addr      allmodes  */
-	{0x0000a000, 0x02000101},
-	{0x0000a004, 0x02000102},
-	{0x0000a008, 0x02000103},
-	{0x0000a00c, 0x02000104},
-	{0x0000a010, 0x02000200},
-	{0x0000a014, 0x02000201},
-	{0x0000a018, 0x02000202},
-	{0x0000a01c, 0x02000203},
-	{0x0000a020, 0x02000204},
-	{0x0000a024, 0x02000205},
-	{0x0000a028, 0x02000208},
-	{0x0000a02c, 0x02000302},
-	{0x0000a030, 0x02000303},
-	{0x0000a034, 0x02000304},
-	{0x0000a038, 0x02000400},
-	{0x0000a03c, 0x02010300},
-	{0x0000a040, 0x02010301},
-	{0x0000a044, 0x02010302},
-	{0x0000a048, 0x02000500},
-	{0x0000a04c, 0x02010400},
-	{0x0000a050, 0x02020300},
-	{0x0000a054, 0x02020301},
-	{0x0000a058, 0x02020302},
-	{0x0000a05c, 0x02020303},
-	{0x0000a060, 0x02020400},
-	{0x0000a064, 0x02030300},
-	{0x0000a068, 0x02030301},
-	{0x0000a06c, 0x02030302},
-	{0x0000a070, 0x02030303},
-	{0x0000a074, 0x02030400},
-	{0x0000a078, 0x02040300},
-	{0x0000a07c, 0x02040301},
-	{0x0000a080, 0x02040302},
-	{0x0000a084, 0x02040303},
-	{0x0000a088, 0x02030500},
-	{0x0000a08c, 0x02040400},
-	{0x0000a090, 0x02050203},
-	{0x0000a094, 0x02050204},
-	{0x0000a098, 0x02050205},
-	{0x0000a09c, 0x02040500},
-	{0x0000a0a0, 0x02050301},
-	{0x0000a0a4, 0x02050302},
-	{0x0000a0a8, 0x02050303},
-	{0x0000a0ac, 0x02050400},
-	{0x0000a0b0, 0x02050401},
-	{0x0000a0b4, 0x02050402},
-	{0x0000a0b8, 0x02050403},
-	{0x0000a0bc, 0x02050500},
-	{0x0000a0c0, 0x02050501},
-	{0x0000a0c4, 0x02050502},
-	{0x0000a0c8, 0x02050503},
-	{0x0000a0cc, 0x02050504},
-	{0x0000a0d0, 0x02050600},
-	{0x0000a0d4, 0x02050601},
-	{0x0000a0d8, 0x02050602},
-	{0x0000a0dc, 0x02050603},
-	{0x0000a0e0, 0x02050604},
-	{0x0000a0e4, 0x02050700},
-	{0x0000a0e8, 0x02050701},
-	{0x0000a0ec, 0x02050702},
-	{0x0000a0f0, 0x02050703},
-	{0x0000a0f4, 0x02050704},
-	{0x0000a0f8, 0x02050705},
-	{0x0000a0fc, 0x02050708},
-	{0x0000a100, 0x02050709},
-	{0x0000a104, 0x0205070a},
-	{0x0000a108, 0x0205070b},
-	{0x0000a10c, 0x0205070c},
-	{0x0000a110, 0x0205070d},
-	{0x0000a114, 0x02050710},
-	{0x0000a118, 0x02050711},
-	{0x0000a11c, 0x02050712},
-	{0x0000a120, 0x02050713},
-	{0x0000a124, 0x02050714},
-	{0x0000a128, 0x02050715},
-	{0x0000a12c, 0x02050730},
-	{0x0000a130, 0x02050731},
-	{0x0000a134, 0x02050732},
-	{0x0000a138, 0x02050733},
-	{0x0000a13c, 0x02050734},
-	{0x0000a140, 0x02050735},
-	{0x0000a144, 0x02050750},
-	{0x0000a148, 0x02050751},
-	{0x0000a14c, 0x02050752},
-	{0x0000a150, 0x02050753},
-	{0x0000a154, 0x02050754},
-	{0x0000a158, 0x02050755},
-	{0x0000a15c, 0x02050770},
-	{0x0000a160, 0x02050771},
-	{0x0000a164, 0x02050772},
-	{0x0000a168, 0x02050773},
-	{0x0000a16c, 0x02050774},
-	{0x0000a170, 0x02050775},
-	{0x0000a174, 0x00000776},
-	{0x0000a178, 0x00000776},
-	{0x0000a17c, 0x00000776},
-	{0x0000a180, 0x00000776},
-	{0x0000a184, 0x00000776},
-	{0x0000a188, 0x00000776},
-	{0x0000a18c, 0x00000776},
-	{0x0000a190, 0x00000776},
-	{0x0000a194, 0x00000776},
-	{0x0000a198, 0x00000776},
-	{0x0000a19c, 0x00000776},
-	{0x0000a1a0, 0x00000776},
-	{0x0000a1a4, 0x00000776},
-	{0x0000a1a8, 0x00000776},
-	{0x0000a1ac, 0x00000776},
-	{0x0000a1b0, 0x00000776},
-	{0x0000a1b4, 0x00000776},
-	{0x0000a1b8, 0x00000776},
-	{0x0000a1bc, 0x00000776},
-	{0x0000a1c0, 0x00000776},
-	{0x0000a1c4, 0x00000776},
-	{0x0000a1c8, 0x00000776},
-	{0x0000a1cc, 0x00000776},
-	{0x0000a1d0, 0x00000776},
-	{0x0000a1d4, 0x00000776},
-	{0x0000a1d8, 0x00000776},
-	{0x0000a1dc, 0x00000776},
-	{0x0000a1e0, 0x00000776},
-	{0x0000a1e4, 0x00000776},
-	{0x0000a1e8, 0x00000776},
-	{0x0000a1ec, 0x00000776},
-	{0x0000a1f0, 0x00000776},
-	{0x0000a1f4, 0x00000776},
-	{0x0000a1f8, 0x00000776},
-	{0x0000a1fc, 0x00000776},
-	{0x0000b000, 0x02000101},
-	{0x0000b004, 0x02000102},
-	{0x0000b008, 0x02000103},
-	{0x0000b00c, 0x02000104},
-	{0x0000b010, 0x02000200},
-	{0x0000b014, 0x02000201},
-	{0x0000b018, 0x02000202},
-	{0x0000b01c, 0x02000203},
-	{0x0000b020, 0x02000204},
-	{0x0000b024, 0x02000205},
-	{0x0000b028, 0x02000208},
-	{0x0000b02c, 0x02000302},
-	{0x0000b030, 0x02000303},
-	{0x0000b034, 0x02000304},
-	{0x0000b038, 0x02000400},
-	{0x0000b03c, 0x02010300},
-	{0x0000b040, 0x02010301},
-	{0x0000b044, 0x02010302},
-	{0x0000b048, 0x02000500},
-	{0x0000b04c, 0x02010400},
-	{0x0000b050, 0x02020300},
-	{0x0000b054, 0x02020301},
-	{0x0000b058, 0x02020302},
-	{0x0000b05c, 0x02020303},
-	{0x0000b060, 0x02020400},
-	{0x0000b064, 0x02030300},
-	{0x0000b068, 0x02030301},
-	{0x0000b06c, 0x02030302},
-	{0x0000b070, 0x02030303},
-	{0x0000b074, 0x02030400},
-	{0x0000b078, 0x02040300},
-	{0x0000b07c, 0x02040301},
-	{0x0000b080, 0x02040302},
-	{0x0000b084, 0x02040303},
-	{0x0000b088, 0x02030500},
-	{0x0000b08c, 0x02040400},
-	{0x0000b090, 0x02050203},
-	{0x0000b094, 0x02050204},
-	{0x0000b098, 0x02050205},
-	{0x0000b09c, 0x02040500},
-	{0x0000b0a0, 0x02050301},
-	{0x0000b0a4, 0x02050302},
-	{0x0000b0a8, 0x02050303},
-	{0x0000b0ac, 0x02050400},
-	{0x0000b0b0, 0x02050401},
-	{0x0000b0b4, 0x02050402},
-	{0x0000b0b8, 0x02050403},
-	{0x0000b0bc, 0x02050500},
-	{0x0000b0c0, 0x02050501},
-	{0x0000b0c4, 0x02050502},
-	{0x0000b0c8, 0x02050503},
-	{0x0000b0cc, 0x02050504},
-	{0x0000b0d0, 0x02050600},
-	{0x0000b0d4, 0x02050601},
-	{0x0000b0d8, 0x02050602},
-	{0x0000b0dc, 0x02050603},
-	{0x0000b0e0, 0x02050604},
-	{0x0000b0e4, 0x02050700},
-	{0x0000b0e8, 0x02050701},
-	{0x0000b0ec, 0x02050702},
-	{0x0000b0f0, 0x02050703},
-	{0x0000b0f4, 0x02050704},
-	{0x0000b0f8, 0x02050705},
-	{0x0000b0fc, 0x02050708},
-	{0x0000b100, 0x02050709},
-	{0x0000b104, 0x0205070a},
-	{0x0000b108, 0x0205070b},
-	{0x0000b10c, 0x0205070c},
-	{0x0000b110, 0x0205070d},
-	{0x0000b114, 0x02050710},
-	{0x0000b118, 0x02050711},
-	{0x0000b11c, 0x02050712},
-	{0x0000b120, 0x02050713},
-	{0x0000b124, 0x02050714},
-	{0x0000b128, 0x02050715},
-	{0x0000b12c, 0x02050730},
-	{0x0000b130, 0x02050731},
-	{0x0000b134, 0x02050732},
-	{0x0000b138, 0x02050733},
-	{0x0000b13c, 0x02050734},
-	{0x0000b140, 0x02050735},
-	{0x0000b144, 0x02050750},
-	{0x0000b148, 0x02050751},
-	{0x0000b14c, 0x02050752},
-	{0x0000b150, 0x02050753},
-	{0x0000b154, 0x02050754},
-	{0x0000b158, 0x02050755},
-	{0x0000b15c, 0x02050770},
-	{0x0000b160, 0x02050771},
-	{0x0000b164, 0x02050772},
-	{0x0000b168, 0x02050773},
-	{0x0000b16c, 0x02050774},
-	{0x0000b170, 0x02050775},
-	{0x0000b174, 0x00000776},
-	{0x0000b178, 0x00000776},
-	{0x0000b17c, 0x00000776},
-	{0x0000b180, 0x00000776},
-	{0x0000b184, 0x00000776},
-	{0x0000b188, 0x00000776},
-	{0x0000b18c, 0x00000776},
-	{0x0000b190, 0x00000776},
-	{0x0000b194, 0x00000776},
-	{0x0000b198, 0x00000776},
-	{0x0000b19c, 0x00000776},
-	{0x0000b1a0, 0x00000776},
-	{0x0000b1a4, 0x00000776},
-	{0x0000b1a8, 0x00000776},
-	{0x0000b1ac, 0x00000776},
-	{0x0000b1b0, 0x00000776},
-	{0x0000b1b4, 0x00000776},
-	{0x0000b1b8, 0x00000776},
-	{0x0000b1bc, 0x00000776},
-	{0x0000b1c0, 0x00000776},
-	{0x0000b1c4, 0x00000776},
-	{0x0000b1c8, 0x00000776},
-	{0x0000b1cc, 0x00000776},
-	{0x0000b1d0, 0x00000776},
-	{0x0000b1d4, 0x00000776},
-	{0x0000b1d8, 0x00000776},
-	{0x0000b1dc, 0x00000776},
-	{0x0000b1e0, 0x00000776},
-	{0x0000b1e4, 0x00000776},
-	{0x0000b1e8, 0x00000776},
-	{0x0000b1ec, 0x00000776},
-	{0x0000b1f0, 0x00000776},
-	{0x0000b1f4, 0x00000776},
-	{0x0000b1f8, 0x00000776},
-	{0x0000b1fc, 0x00000776},
-};
-
 static const u32 ar9300_2p2_mac_postamble[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
 	{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
@@ -572,48 +312,6 @@
 	{0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
 };
 
-static const u32 ar9200_merlin_2p2_radio_core[][2] = {
-	/* Addr      allmodes  */
-	{0x00007800, 0x00040000},
-	{0x00007804, 0xdb005012},
-	{0x00007808, 0x04924914},
-	{0x0000780c, 0x21084210},
-	{0x00007810, 0x6d801300},
-	{0x00007814, 0x0019beff},
-	{0x00007818, 0x07e41000},
-	{0x0000781c, 0x00392000},
-	{0x00007820, 0x92592480},
-	{0x00007824, 0x00040000},
-	{0x00007828, 0xdb005012},
-	{0x0000782c, 0x04924914},
-	{0x00007830, 0x21084210},
-	{0x00007834, 0x6d801300},
-	{0x00007838, 0x0019beff},
-	{0x0000783c, 0x07e40000},
-	{0x00007840, 0x00392000},
-	{0x00007844, 0x92592480},
-	{0x00007848, 0x00100000},
-	{0x0000784c, 0x773f0567},
-	{0x00007850, 0x54214514},
-	{0x00007854, 0x12035828},
-	{0x00007858, 0x92592692},
-	{0x0000785c, 0x00000000},
-	{0x00007860, 0x56400000},
-	{0x00007864, 0x0a8e370e},
-	{0x00007868, 0xc0102850},
-	{0x0000786c, 0x812d4000},
-	{0x00007870, 0x807ec400},
-	{0x00007874, 0x001b6db0},
-	{0x00007878, 0x00376b63},
-	{0x0000787c, 0x06db6db6},
-	{0x00007880, 0x006d8000},
-	{0x00007884, 0xffeffffe},
-	{0x00007888, 0xffeffffe},
-	{0x0000788c, 0x00010000},
-	{0x00007890, 0x02060aeb},
-	{0x00007894, 0x5a108000},
-};
-
 static const u32 ar9300_2p2_baseband_postamble[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
 	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 7b4aa00..0f56e32 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -87,11 +87,11 @@
 
 		/* additional clock settings */
 		if (ah->is_clk_25mhz)
-			INIT_INI_ARRAY(&ah->iniModesAdditional,
+			INIT_INI_ARRAY(&ah->iniAdditional,
 					ar9331_1p1_xtal_25M,
 					ARRAY_SIZE(ar9331_1p1_xtal_25M), 2);
 		else
-			INIT_INI_ARRAY(&ah->iniModesAdditional,
+			INIT_INI_ARRAY(&ah->iniAdditional,
 					ar9331_1p1_xtal_40M,
 					ARRAY_SIZE(ar9331_1p1_xtal_40M), 2);
 	} else if (AR_SREV_9330_12(ah)) {
@@ -140,11 +140,11 @@
 
 		/* additional clock settings */
 		if (ah->is_clk_25mhz)
-			INIT_INI_ARRAY(&ah->iniModesAdditional,
+			INIT_INI_ARRAY(&ah->iniAdditional,
 					ar9331_1p2_xtal_25M,
 					ARRAY_SIZE(ar9331_1p2_xtal_25M), 2);
 		else
-			INIT_INI_ARRAY(&ah->iniModesAdditional,
+			INIT_INI_ARRAY(&ah->iniAdditional,
 					ar9331_1p2_xtal_40M,
 					ARRAY_SIZE(ar9331_1p2_xtal_40M), 2);
 	} else if (AR_SREV_9340(ah)) {
@@ -194,15 +194,16 @@
 				ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0),
 				5);
 
-		INIT_INI_ARRAY(&ah->iniModesAdditional,
+		INIT_INI_ARRAY(&ah->iniModesFastClock,
 				ar9340Modes_fast_clock_1p0,
 				ARRAY_SIZE(ar9340Modes_fast_clock_1p0),
 				3);
 
-		INIT_INI_ARRAY(&ah->iniModesAdditional_40M,
-				ar9340_1p0_radio_core_40M,
-				ARRAY_SIZE(ar9340_1p0_radio_core_40M),
-				2);
+		if (!ah->is_clk_25mhz)
+			INIT_INI_ARRAY(&ah->iniAdditional,
+				       ar9340_1p0_radio_core_40M,
+				       ARRAY_SIZE(ar9340_1p0_radio_core_40M),
+				       2);
 	} else if (AR_SREV_9485_11(ah)) {
 		/* mac */
 		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@@ -321,7 +322,7 @@
 				2);
 
 		/* Fast clock modal settings */
-		INIT_INI_ARRAY(&ah->iniModesAdditional,
+		INIT_INI_ARRAY(&ah->iniModesFastClock,
 				ar9462_modes_fast_clock_2p0,
 				ARRAY_SIZE(ar9462_modes_fast_clock_2p0), 3);
 
@@ -378,7 +379,7 @@
 				ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
 				5);
 
-		INIT_INI_ARRAY(&ah->iniModesAdditional,
+		INIT_INI_ARRAY(&ah->iniModesFastClock,
 				ar9580_1p0_modes_fast_clock,
 				ARRAY_SIZE(ar9580_1p0_modes_fast_clock),
 				3);
@@ -445,7 +446,7 @@
 				2);
 
 		/* Fast clock modal settings */
-		INIT_INI_ARRAY(&ah->iniModesAdditional,
+		INIT_INI_ARRAY(&ah->iniModesFastClock,
 				ar9300Modes_fast_clock_2p2,
 				ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
 				3);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 8d1bca0..a66a13b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -326,7 +326,6 @@
 static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 				 struct ath_tx_status *ts)
 {
-	struct ar9003_txc *txc = (struct ar9003_txc *) ds;
 	struct ar9003_txs *ads;
 	u32 status;
 
@@ -336,11 +335,7 @@
 	if ((status & AR_TxDone) == 0)
 		return -EINPROGRESS;
 
-	ts->qid = MS(ads->ds_info, AR_TxQcuNum);
-	if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
-		ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
-	else
-		return -ENOENT;
+	ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
 
 	if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
 	    (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
@@ -354,6 +349,7 @@
 	ts->ts_seqnum = MS(status, AR_SeqNum);
 	ts->tid = MS(status, AR_TxTid);
 
+	ts->qid = MS(ads->ds_info, AR_TxQcuNum);
 	ts->desc_id = MS(ads->status1, AR_TxDescId);
 	ts->ts_tstamp = ads->status4;
 	ts->ts_status = 0;
@@ -440,20 +436,14 @@
 	struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr;
 	unsigned int phyerr;
 
-	/* TODO: byte swap on big endian for ar9300_10 */
+	if ((rxsp->status11 & AR_RxDone) == 0)
+		return -EINPROGRESS;
 
-	if (!rxs) {
-		if ((rxsp->status11 & AR_RxDone) == 0)
-			return -EINPROGRESS;
+	if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
+		return -EINVAL;
 
-		if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
-			return -EINVAL;
-
-		if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
-			return -EINPROGRESS;
-
-		return 0;
-	}
+	if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
+		return -EINPROGRESS;
 
 	rxs->rs_status = 0;
 	rxs->rs_flags =  0;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 70e27d2..bc992b2 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -679,18 +679,17 @@
 	 * different modal values.
 	 */
 	if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-		REG_WRITE_ARRAY(&ah->iniModesAdditional,
+		REG_WRITE_ARRAY(&ah->iniModesFastClock,
 				modesIndex, regWrites);
 
-	if (AR_SREV_9330(ah))
-		REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
-
-	if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
-		REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
+	REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
 
 	if (AR_SREV_9462(ah))
 		ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1);
 
+	if (chan->channel == 2484)
+		ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1);
+
 	ah->modes_index = modesIndex;
 	ar9003_hw_override_ini(ah);
 	ar9003_hw_set_channel_regs(ah, chan);
@@ -1320,13 +1319,9 @@
 	 * different modal values.
 	 */
 	if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-		REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites);
+		REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex, regWrites);
 
-	if (AR_SREV_9330(ah))
-		REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
-
-	if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
-		REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
+	REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
 
 	ah->modes_index = modesIndex;
 	*ini_reloaded = true;
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index c2ccba6..8c84049 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -299,7 +299,6 @@
 
 struct ath_rx_edma {
 	struct sk_buff_head rx_fifo;
-	struct sk_buff_head rx_buffers;
 	u32 rx_fifo_hwsize;
 };
 
@@ -584,19 +583,13 @@
 
 #define SC_OP_INVALID                BIT(0)
 #define SC_OP_BEACONS                BIT(1)
-#define SC_OP_RXAGGR                 BIT(2)
-#define SC_OP_TXAGGR                 BIT(3)
-#define SC_OP_OFFCHANNEL             BIT(4)
-#define SC_OP_PREAMBLE_SHORT         BIT(5)
-#define SC_OP_PROTECT_ENABLE         BIT(6)
-#define SC_OP_RXFLUSH                BIT(7)
-#define SC_OP_LED_ASSOCIATED         BIT(8)
-#define SC_OP_LED_ON                 BIT(9)
-#define SC_OP_TSF_RESET              BIT(11)
-#define SC_OP_BT_PRIORITY_DETECTED   BIT(12)
-#define SC_OP_BT_SCAN		     BIT(13)
-#define SC_OP_ANI_RUN		     BIT(14)
-#define SC_OP_PRIM_STA_VIF	     BIT(15)
+#define SC_OP_OFFCHANNEL             BIT(2)
+#define SC_OP_RXFLUSH                BIT(3)
+#define SC_OP_TSF_RESET              BIT(4)
+#define SC_OP_BT_PRIORITY_DETECTED   BIT(5)
+#define SC_OP_BT_SCAN                BIT(6)
+#define SC_OP_ANI_RUN                BIT(7)
+#define SC_OP_PRIM_STA_VIF           BIT(8)
 
 /* Powersave flags */
 #define PS_WAIT_FOR_BEACON        BIT(0)
@@ -618,15 +611,12 @@
 	int nstations; /* number of station vifs */
 	int nwds;      /* number of WDS vifs */
 	int nadhocs;   /* number of adhoc vifs */
-	int nothers;   /* number of vifs not specified above. */
 };
 
 struct ath_softc {
 	struct ieee80211_hw *hw;
 	struct device *dev;
 
-	int chan_idx;
-	int chan_is_ht;
 	struct survey_info *cur_survey;
 	struct survey_info survey[ATH9K_NUM_CHANNELS];
 
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index b8967e4..6264182 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -67,7 +67,7 @@
  *  up rate codes, and channel flags. Beacons are always sent out at the
  *  lowest rate, and are not retried.
 */
-static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
+static void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
 			     struct ath_buf *bf, int rateidx)
 {
 	struct sk_buff *skb = bf->bf_mpdu;
@@ -82,7 +82,7 @@
 
 	sband = &sc->sbands[common->hw->conf.channel->band];
 	rate = sband->bitrates[rateidx].hw_value;
-	if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+	if (vif->bss_conf.use_short_preamble)
 		rate |= sband->bitrates[rateidx].hw_value_short;
 
 	memset(&info, 0, sizeof(info));
@@ -91,7 +91,7 @@
 	info.txpower = MAX_RATE_POWER;
 	info.keyix = ATH9K_TXKEYIX_INVALID;
 	info.keytype = ATH9K_KEY_TYPE_CLEAR;
-	info.flags = ATH9K_TXDESC_NOACK;
+	info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_INTREQ;
 
 	info.buf_addr[0] = bf->bf_buf_addr;
 	info.buf_len[0] = roundup(skb->len, 4);
@@ -209,7 +209,7 @@
 		}
 	}
 
-	ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx);
+	ath_beacon_setup(sc, vif, bf, info->control.rates[0].idx);
 
 	while (skb) {
 		ath_tx_cabq(hw, skb);
@@ -355,7 +355,6 @@
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_buf *bf = NULL;
 	struct ieee80211_vif *vif;
-	struct ath_tx_status ts;
 	bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
 	int slot;
 	u32 bfaddr, bc = 0;
@@ -462,11 +461,6 @@
 			ath9k_hw_txstart(ah, sc->beacon.beaconq);
 
 		sc->beacon.ast_be_xmit += bc;     /* XXX per-vif? */
-		if (edma) {
-			spin_lock_bh(&sc->sc_pcu_lock);
-			ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
-			spin_unlock_bh(&sc->sc_pcu_lock);
-		}
 	}
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 228c181..35d1c8e 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -738,9 +738,9 @@
 
 	len += snprintf(buf + len, sizeof(buf) - len,
 			"VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i"
-			" ADHOC: %i OTHER: %i TOTAL: %hi BEACON-VIF: %hi\n",
+			" ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
 			iter_data.naps, iter_data.nstations, iter_data.nmeshes,
-			iter_data.nwds, iter_data.nadhocs, iter_data.nothers,
+			iter_data.nwds, iter_data.nadhocs,
 			sc->nvifs, sc->nbcnvifs);
 
 	if (len > sizeof(buf))
@@ -818,6 +818,7 @@
 	if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
 		TX_STAT_INC(qnum, delim_underrun);
 
+#ifdef CONFIG_ATH9K_MAC_DEBUG
 	spin_lock(&sc->debug.samp_lock);
 	TX_SAMP_DBG(jiffies) = jiffies;
 	TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0;
@@ -844,6 +845,7 @@
 
 	sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES;
 	spin_unlock(&sc->debug.samp_lock);
+#endif
 
 #undef TX_SAMP_DBG
 }
@@ -942,27 +944,6 @@
 	PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
 
 	len += snprintf(buf + len, size - len,
-			"%22s : %10d\n", "RSSI-CTL0",
-			sc->debug.stats.rxstats.rs_rssi_ctl0);
-	len += snprintf(buf + len, size - len,
-			"%22s : %10d\n", "RSSI-CTL1",
-			sc->debug.stats.rxstats.rs_rssi_ctl1);
-	len += snprintf(buf + len, size - len,
-			"%22s : %10d\n", "RSSI-CTL2",
-			sc->debug.stats.rxstats.rs_rssi_ctl2);
-	len += snprintf(buf + len, size - len,
-			"%22s : %10d\n", "RSSI-EXT0",
-			sc->debug.stats.rxstats.rs_rssi_ext0);
-	len += snprintf(buf + len, size - len,
-			"%22s : %10d\n", "RSSI-EXT1",
-			sc->debug.stats.rxstats.rs_rssi_ext1);
-	len += snprintf(buf + len, size - len,
-			"%22s : %10d\n", "RSSI-EXT2",
-			sc->debug.stats.rxstats.rs_rssi_ext2);
-	len += snprintf(buf + len, size - len,
-			"%22s : %10d\n", "Rx Antenna",
-			sc->debug.stats.rxstats.rs_antenna);
-	len += snprintf(buf + len, size - len,
 			"%22s : %10u\n", "RX-Pkts-All",
 			sc->debug.stats.rxstats.rx_pkts_all);
 	len += snprintf(buf + len, size - len,
@@ -1009,16 +990,7 @@
 			RX_PHY_ERR_INC(rs->rs_phyerr);
 	}
 
-	sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0;
-	sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1;
-	sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2;
-
-	sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0;
-	sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1;
-	sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2;
-
-	sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna;
-
+#ifdef CONFIG_ATH9K_MAC_DEBUG
 	spin_lock(&sc->debug.samp_lock);
 	RX_SAMP_DBG(jiffies) = jiffies;
 	RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
@@ -1035,6 +1007,8 @@
 	sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES;
 	spin_unlock(&sc->debug.samp_lock);
 
+#endif
+
 #undef RX_STAT_INC
 #undef RX_PHY_ERR_INC
 #undef RX_SAMP_DBG
@@ -1278,6 +1252,8 @@
 	.llseek = default_llseek,
 };
 
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+
 void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
 {
 #define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c)
@@ -1551,6 +1527,7 @@
 	.llseek = default_llseek,
 };
 
+#endif
 
 int ath9k_init_debug(struct ath_hw *ah)
 {
@@ -1604,8 +1581,10 @@
 			    &fops_base_eeprom);
 	debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
 			    &fops_modal_eeprom);
+#ifdef CONFIG_ATH9K_MAC_DEBUG
 	debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
 			    &fops_samps);
+#endif
 
 	debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
 			   sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 776a24a..64fcfad 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -165,13 +165,6 @@
 	u32 post_delim_crc_err;
 	u32 decrypt_busy_err;
 	u32 phy_err_stats[ATH9K_PHYERR_MAX];
-	int8_t rs_rssi_ctl0;
-	int8_t rs_rssi_ctl1;
-	int8_t rs_rssi_ctl2;
-	int8_t rs_rssi_ext0;
-	int8_t rs_rssi_ext1;
-	int8_t rs_rssi_ext2;
-	u8 rs_antenna;
 };
 
 enum ath_reset_type {
@@ -235,16 +228,17 @@
 	struct dentry *debugfs_phy;
 	u32 regidx;
 	struct ath_stats stats;
+#ifdef CONFIG_ATH9K_MAC_DEBUG
 	spinlock_t samp_lock;
 	struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES];
 	u8 sampidx;
 	u8 tsidx;
 	u8 rsidx;
+#endif
 };
 
 int ath9k_init_debug(struct ath_hw *ah);
 
-void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
 		       struct ath_tx_status *ts, struct ath_txq *txq,
@@ -258,10 +252,6 @@
 	return 0;
 }
 
-static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
-{
-}
-
 static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
 					    enum ath9k_int status)
 {
@@ -282,4 +272,17 @@
 
 #endif /* CONFIG_ATH9K_DEBUGFS */
 
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+
+void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
+
+#else
+
+static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
+{
+}
+
+#endif
+
+
 #endif /* DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 63e4c4b1..fbe23de 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -362,7 +362,8 @@
 		ath9k_hw_btcoex_disable(ah);
 		if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
 			ath9k_btcoex_timer_pause(sc);
-		ath_mci_flush_profile(&sc->btcoex.mci);
+		if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_MCI)
+			ath_mci_flush_profile(&sc->btcoex.mci);
 	}
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 2a29a7c..2b8f61c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -919,7 +919,6 @@
 	/* setup initial channel */
 	init_channel = ath9k_cmn_get_curchannel(hw, ah);
 
-	ath9k_hw_htc_resetinit(ah);
 	ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
 	if (ret) {
 		ath_err(common,
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 8c840ca..3022c4e 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -449,6 +449,7 @@
 	ah->slottime = ATH9K_SLOT_TIME_9;
 	ah->globaltxtimeout = (u32) -1;
 	ah->power_mode = ATH9K_PM_UNDEFINED;
+	ah->htc_reset_init = true;
 }
 
 static int ath9k_hw_init_macaddr(struct ath_hw *ah)
@@ -555,7 +556,7 @@
 		return -EIO;
 	}
 
-	if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
+	if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
 		if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
 		    ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
 		     !ah->is_pciexpress)) {
@@ -619,9 +620,6 @@
 	if (!ah->is_pciexpress)
 		ath9k_hw_disablepcie(ah);
 
-	if (!AR_SREV_9300_20_OR_LATER(ah))
-		ar9002_hw_cck_chan14_spread(ah);
-
 	r = ath9k_hw_post_init(ah);
 	if (r)
 		return r;
@@ -1386,10 +1384,16 @@
 static bool ath9k_hw_chip_reset(struct ath_hw *ah,
 				struct ath9k_channel *chan)
 {
-	if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) {
-		if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
-			return false;
-	} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
+	int reset_type = ATH9K_RESET_WARM;
+
+	if (AR_SREV_9280(ah)) {
+		if (ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+			reset_type = ATH9K_RESET_POWER_ON;
+		else
+			reset_type = ATH9K_RESET_COLD;
+	}
+
+	if (!ath9k_hw_set_reset_reg(ah, reset_type))
 		return false;
 
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
@@ -1515,17 +1519,81 @@
 }
 EXPORT_SYMBOL(ath9k_hw_check_alive);
 
+/*
+ * Fast channel change:
+ * (Change synthesizer based on channel freq without resetting chip)
+ *
+ * Don't do FCC when
+ *   - Flag is not set
+ *   - Chip is just coming out of full sleep
+ *   - Channel to be set is same as current channel
+ *   - Channel flags are different, (eg.,moving from 2GHz to 5GHz channel)
+ */
+static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	int ret;
+
+	if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
+		goto fail;
+
+	if (ah->chip_fullsleep)
+		goto fail;
+
+	if (!ah->curchan)
+		goto fail;
+
+	if (chan->channel == ah->curchan->channel)
+		goto fail;
+
+	if ((chan->channelFlags & CHANNEL_ALL) !=
+	    (ah->curchan->channelFlags & CHANNEL_ALL))
+		goto fail;
+
+	if (!ath9k_hw_check_alive(ah))
+		goto fail;
+
+	/*
+	 * For AR9462, make sure that calibration data for
+	 * re-using are present.
+	 */
+	if (AR_SREV_9462(ah) && (!ah->caldata ||
+				 !ah->caldata->done_txiqcal_once ||
+				 !ah->caldata->done_txclcal_once ||
+				 !ah->caldata->rtt_hist.num_readings))
+		goto fail;
+
+	ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n",
+		ah->curchan->channel, chan->channel);
+
+	ret = ath9k_hw_channel_change(ah, chan);
+	if (!ret)
+		goto fail;
+
+	ath9k_hw_loadnf(ah, ah->curchan);
+	ath9k_hw_start_nfcal(ah, true);
+
+	if ((ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && ar9003_mci_is_ready(ah))
+		ar9003_mci_2g5g_switch(ah, true);
+
+	if (AR_SREV_9271(ah))
+		ar9002_hw_load_ani_reg(ah, chan);
+
+	return 0;
+fail:
+	return -EINVAL;
+}
+
 int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
-		   struct ath9k_hw_cal_data *caldata, bool bChannelChange)
+		   struct ath9k_hw_cal_data *caldata, bool fastcc)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 	u32 saveLedState;
-	struct ath9k_channel *curchan = ah->curchan;
 	u32 saveDefAntenna;
 	u32 macStaId1;
 	u64 tsf = 0;
 	int i, r;
-	bool allow_fbs = false, start_mci_reset = false;
+	bool start_mci_reset = false;
 	bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
 	bool save_fullsleep = ah->chip_fullsleep;
 
@@ -1538,8 +1606,8 @@
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
 		return -EIO;
 
-	if (curchan && !ah->chip_fullsleep)
-		ath9k_hw_getnf(ah, curchan);
+	if (ah->curchan && !ah->chip_fullsleep)
+		ath9k_hw_getnf(ah, ah->curchan);
 
 	ah->caldata = caldata;
 	if (caldata &&
@@ -1552,32 +1620,10 @@
 	}
 	ah->noise = ath9k_hw_getchan_noise(ah, chan);
 
-	if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
-		bChannelChange = false;
-
-	if (caldata &&
-	    caldata->done_txiqcal_once &&
-	    caldata->done_txclcal_once &&
-	    caldata->rtt_hist.num_readings)
-		allow_fbs = true;
-
-	if (bChannelChange &&
-	    (ah->chip_fullsleep != true) &&
-	    (ah->curchan != NULL) &&
-	    (chan->channel != ah->curchan->channel) &&
-	    (allow_fbs ||
-	     ((chan->channelFlags & CHANNEL_ALL) ==
-	      (ah->curchan->channelFlags & CHANNEL_ALL)))) {
-		if (ath9k_hw_channel_change(ah, chan)) {
-			ath9k_hw_loadnf(ah, ah->curchan);
-			ath9k_hw_start_nfcal(ah, true);
-			if (mci && ar9003_mci_is_ready(ah))
-				ar9003_mci_2g5g_switch(ah, true);
-
-			if (AR_SREV_9271(ah))
-				ar9002_hw_load_ani_reg(ah, chan);
-			return 0;
-		}
+	if (fastcc) {
+		r = ath9k_hw_do_fastcc(ah, chan);
+		if (!r)
+			return r;
 	}
 
 	if (mci)
@@ -2384,8 +2430,17 @@
 		if (AR_SREV_9485_OR_LATER(ah))
 			ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
 	}
-	if (AR_SREV_9462(ah))
-		pCap->hw_caps |= ATH9K_HW_CAP_RTT | ATH9K_HW_CAP_MCI;
+
+	if (AR_SREV_9462(ah)) {
+
+		if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE))
+			pCap->hw_caps |= ATH9K_HW_CAP_MCI;
+
+		if (AR_SREV_9462_20(ah))
+			pCap->hw_caps |= ATH9K_HW_CAP_RTT;
+
+	}
+
 
 	return 0;
 }
@@ -2511,12 +2566,6 @@
 }
 EXPORT_SYMBOL(ath9k_hw_set_gpio);
 
-u32 ath9k_hw_getdefantenna(struct ath_hw *ah)
-{
-	return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
-}
-EXPORT_SYMBOL(ath9k_hw_getdefantenna);
-
 void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
 {
 	REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
@@ -2574,6 +2623,7 @@
 		return false;
 
 	ath9k_hw_init_pll(ah, NULL);
+	ah->htc_reset_init = true;
 	return true;
 }
 EXPORT_SYMBOL(ath9k_hw_phy_disable);
@@ -2934,12 +2984,6 @@
 /* HTC  */
 /********/
 
-void ath9k_hw_htc_resetinit(struct ath_hw *ah)
-{
-	ah->htc_reset_init = true;
-}
-EXPORT_SYMBOL(ath9k_hw_htc_resetinit);
-
 static struct {
 	u32 version;
 	const char * name;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 1707137..aa1680a 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -827,19 +827,14 @@
 	struct ar5416IniArray iniAddac;
 	struct ar5416IniArray iniPcieSerdes;
 	struct ar5416IniArray iniPcieSerdesLowPower;
-	struct ar5416IniArray iniModesAdditional;
-	struct ar5416IniArray iniModesAdditional_40M;
+	struct ar5416IniArray iniModesFastClock;
+	struct ar5416IniArray iniAdditional;
 	struct ar5416IniArray iniModesRxGain;
 	struct ar5416IniArray iniModesTxGain;
-	struct ar5416IniArray iniModes_9271_1_0_only;
 	struct ar5416IniArray iniCckfirNormal;
 	struct ar5416IniArray iniCckfirJapan2484;
 	struct ar5416IniArray ini_japan2484;
-	struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271;
-	struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271;
 	struct ar5416IniArray iniModes_9271_ANI_reg;
-	struct ar5416IniArray iniModes_high_power_tx_gain_9271;
-	struct ar5416IniArray iniModes_normal_power_tx_gain_9271;
 	struct ar5416IniArray ini_radio_post_sys2ant;
 	struct ar5416IniArray ini_BTCOEX_MAX_TXPWR;
 
@@ -924,7 +919,7 @@
 void ath9k_hw_deinit(struct ath_hw *ah);
 int ath9k_hw_init(struct ath_hw *ah);
 int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
-		   struct ath9k_hw_cal_data *caldata, bool bChannelChange);
+		   struct ath9k_hw_cal_data *caldata, bool fastcc);
 int ath9k_hw_fill_cap_info(struct ath_hw *ah);
 u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
 
@@ -934,7 +929,6 @@
 void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
 			 u32 ah_signal_type);
 void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
-u32 ath9k_hw_getdefantenna(struct ath_hw *ah);
 void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
 
 /* General Operation */
@@ -988,9 +982,6 @@
 
 void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
 
-/* HTC */
-void ath9k_hw_htc_resetinit(struct ath_hw *ah);
-
 /* PHY */
 void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
 				   u32 *coef_mantissa, u32 *coef_exponent);
@@ -1000,7 +991,6 @@
  * Code Specific to AR5008, AR9001 or AR9002,
  * we stuff these here to avoid callbacks for AR9003.
  */
-void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
 int ar9002_hw_rf_claim(struct ath_hw *ah);
 void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
 
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index d8b0596..60159f4 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -172,7 +172,7 @@
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_softc *sc = (struct ath_softc *) common->priv;
 
-	if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
+	if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
 		unsigned long flags;
 		spin_lock_irqsave(&sc->sc_serial_rw, flags);
 		iowrite32(val, sc->mem + reg_offset);
@@ -188,7 +188,7 @@
 	struct ath_softc *sc = (struct ath_softc *) common->priv;
 	u32 val;
 
-	if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
+	if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
 		unsigned long flags;
 		spin_lock_irqsave(&sc->sc_serial_rw, flags);
 		val = ioread32(sc->mem + reg_offset);
@@ -219,7 +219,7 @@
 	unsigned long uninitialized_var(flags);
 	u32 val;
 
-	if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
+	if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
 		spin_lock_irqsave(&sc->sc_serial_rw, flags);
 		val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
 		spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
@@ -484,19 +484,11 @@
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int i = 0;
+
 	setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
 
 	sc->config.txpowlimit = ATH_TXPOWER_MAX;
-
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
-		sc->sc_flags |= SC_OP_TXAGGR;
-		sc->sc_flags |= SC_OP_RXAGGR;
-	}
-
-	sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
-
 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
-
 	sc->beacon.slottime = ATH9K_SLOT_TIME_9;
 
 	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
@@ -555,9 +547,11 @@
 	mutex_init(&sc->mutex);
 #ifdef CONFIG_ATH9K_DEBUGFS
 	spin_lock_init(&sc->nodes_lock);
-	spin_lock_init(&sc->debug.samp_lock);
 	INIT_LIST_HEAD(&sc->nodes);
 #endif
+#ifdef CONFIG_ATH9K_MAC_DEBUG
+	spin_lock_init(&sc->debug.samp_lock);
+#endif
 	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
 	tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
 		     (unsigned long)sc);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index e196aba..f7bd253 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -185,13 +185,6 @@
 }
 EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
 
-void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
-{
-	*txqs &= ah->intr_txqs;
-	ah->intr_txqs &= ~(*txqs);
-}
-EXPORT_SYMBOL(ath9k_hw_gettxintrtxqs);
-
 bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
 			    const struct ath9k_tx_queue_info *qinfo)
 {
@@ -340,6 +333,15 @@
 }
 EXPORT_SYMBOL(ath9k_hw_setuptxqueue);
 
+static void ath9k_hw_clear_queue_interrupts(struct ath_hw *ah, u32 q)
+{
+	ah->txok_interrupt_mask &= ~(1 << q);
+	ah->txerr_interrupt_mask &= ~(1 << q);
+	ah->txdesc_interrupt_mask &= ~(1 << q);
+	ah->txeol_interrupt_mask &= ~(1 << q);
+	ah->txurn_interrupt_mask &= ~(1 << q);
+}
+
 bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -354,11 +356,7 @@
 	ath_dbg(common, QUEUE, "Release TX queue: %u\n", q);
 
 	qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
-	ah->txok_interrupt_mask &= ~(1 << q);
-	ah->txerr_interrupt_mask &= ~(1 << q);
-	ah->txdesc_interrupt_mask &= ~(1 << q);
-	ah->txeol_interrupt_mask &= ~(1 << q);
-	ah->txurn_interrupt_mask &= ~(1 << q);
+	ath9k_hw_clear_queue_interrupts(ah, q);
 	ath9k_hw_set_txq_interrupts(ah, qi);
 
 	return true;
@@ -510,26 +508,17 @@
 	if (AR_SREV_9300_20_OR_LATER(ah))
 		REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);
 
-	if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
+	ath9k_hw_clear_queue_interrupts(ah, q);
+	if (qi->tqi_qflags & TXQ_FLAG_TXINT_ENABLE) {
 		ah->txok_interrupt_mask |= 1 << q;
-	else
-		ah->txok_interrupt_mask &= ~(1 << q);
-	if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
 		ah->txerr_interrupt_mask |= 1 << q;
-	else
-		ah->txerr_interrupt_mask &= ~(1 << q);
+	}
 	if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
 		ah->txdesc_interrupt_mask |= 1 << q;
-	else
-		ah->txdesc_interrupt_mask &= ~(1 << q);
 	if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
 		ah->txeol_interrupt_mask |= 1 << q;
-	else
-		ah->txeol_interrupt_mask &= ~(1 << q);
 	if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
 		ah->txurn_interrupt_mask |= 1 << q;
-	else
-		ah->txurn_interrupt_mask &= ~(1 << q);
 	ath9k_hw_set_txq_interrupts(ah, qi);
 
 	return true;
@@ -745,7 +734,10 @@
 	qi.tqi_aifs = 1;
 	qi.tqi_cwmin = 0;
 	qi.tqi_cwmax = 0;
-	/* NB: don't enable any interrupts */
+
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+		qi.tqi_qflags = TXQ_FLAG_TXINT_ENABLE;
+
 	return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
 }
 EXPORT_SYMBOL(ath9k_hw_beaconq_setup);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 11dbd14..21c9556 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -583,8 +583,7 @@
 #define ATH9K_WME_UPSD	4
 
 enum ath9k_tx_queue_flags {
-	TXQ_FLAG_TXOKINT_ENABLE = 0x0001,
-	TXQ_FLAG_TXERRINT_ENABLE = 0x0001,
+	TXQ_FLAG_TXINT_ENABLE = 0x0001,
 	TXQ_FLAG_TXDESCINT_ENABLE = 0x0002,
 	TXQ_FLAG_TXEOLINT_ENABLE = 0x0004,
 	TXQ_FLAG_TXURNINT_ENABLE = 0x0008,
@@ -714,7 +713,6 @@
 bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
 bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
 void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
-void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
 bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
 			    const struct ath9k_tx_queue_info *qinfo);
 bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 02e95c8..3879485 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -118,13 +118,15 @@
 	if (--sc->ps_usecount != 0)
 		goto unlock;
 
-	if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK))
+	if (sc->ps_flags & PS_WAIT_FOR_TX_ACK)
+		goto unlock;
+
+	if (sc->ps_idle)
 		mode = ATH9K_PM_FULL_SLEEP;
 	else if (sc->ps_enabled &&
 		 !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
 			      PS_WAIT_FOR_CAB |
-			      PS_WAIT_FOR_PSPOLL_DATA |
-			      PS_WAIT_FOR_TX_ACK)))
+			      PS_WAIT_FOR_PSPOLL_DATA)))
 		mode = ATH9K_PM_NETWORK_SLEEP;
 	else
 		goto unlock;
@@ -332,10 +334,6 @@
 		hchan = ah->curchan;
 	}
 
-	if (fastcc && (ah->chip_fullsleep ||
-	    !ath9k_hw_check_alive(ah)))
-		fastcc = false;
-
 	if (!ath_prepare_reset(sc, retry_tx, flush))
 		fastcc = false;
 
@@ -641,7 +639,8 @@
 #endif
 	an->sta = sta;
 	an->vif = vif;
-	if (sc->sc_flags & SC_OP_TXAGGR) {
+
+	if (sta->ht_cap.ht_supported) {
 		ath_tx_node_init(sc, an);
 		an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
 				     sta->ht_cap.ampdu_factor);
@@ -660,7 +659,7 @@
 	an->sta = NULL;
 #endif
 
-	if (sc->sc_flags & SC_OP_TXAGGR)
+	if (sta->ht_cap.ht_supported)
 		ath_tx_node_cleanup(sc, an);
 }
 
@@ -993,12 +992,8 @@
 		curchan->center_freq);
 
 	ath9k_ps_wakeup(sc);
-
 	mutex_lock(&sc->mutex);
 
-	/* setup initial channel */
-	sc->chan_idx = curchan->hw_value;
-
 	init_channel = ath9k_cmn_get_curchannel(hw, ah);
 
 	/* Reset SERDES registers */
@@ -1047,9 +1042,6 @@
 	sc->sc_flags &= ~SC_OP_INVALID;
 	sc->sc_ah->is_monitoring = false;
 
-	/* Disable BMISS interrupt when we're not associated */
-	ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
-
 	if (!ath_complete_reset(sc, false)) {
 		r = -EIO;
 		spin_unlock_bh(&sc->sc_pcu_lock);
@@ -1277,7 +1269,6 @@
 		iter_data->nwds++;
 		break;
 	default:
-		iter_data->nothers++;
 		break;
 	}
 }
@@ -1761,7 +1752,7 @@
 	struct ath_softc *sc = hw->priv;
 	struct ath_node *an = (struct ath_node *) sta->drv_priv;
 
-	if (!(sc->sc_flags & SC_OP_TXAGGR))
+	if (!sta->ht_cap.ht_supported)
 		return;
 
 	switch (cmd) {
@@ -1973,7 +1964,7 @@
 	ath9k_ps_wakeup(sc);
 	mutex_lock(&sc->mutex);
 
-	if (changed & BSS_CHANGED_BSSID) {
+	if (changed & BSS_CHANGED_ASSOC) {
 		ath9k_config_bss(sc, vif);
 
 		ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n",
@@ -2053,25 +2044,6 @@
 			ath_beacon_config(sc, vif);
 	}
 
-	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		ath_dbg(common, CONFIG, "BSS Changed PREAMBLE %d\n",
-			bss_conf->use_short_preamble);
-		if (bss_conf->use_short_preamble)
-			sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
-		else
-			sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
-	}
-
-	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		ath_dbg(common, CONFIG, "BSS Changed CTS PROT %d\n",
-			bss_conf->use_cts_prot);
-		if (bss_conf->use_cts_prot &&
-		    hw->conf.channel->band != IEEE80211_BAND_5GHZ)
-			sc->sc_flags |= SC_OP_PROTECT_ENABLE;
-		else
-			sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
-	}
-
 	mutex_unlock(&sc->mutex);
 	ath9k_ps_restore(sc);
 }
@@ -2129,15 +2101,10 @@
 
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
-		if (!(sc->sc_flags & SC_OP_RXAGGR))
-			ret = -ENOTSUPP;
 		break;
 	case IEEE80211_AMPDU_RX_STOP:
 		break;
 	case IEEE80211_AMPDU_TX_START:
-		if (!(sc->sc_flags & SC_OP_TXAGGR))
-			return -EOPNOTSUPP;
-
 		ath9k_ps_wakeup(sc);
 		ret = ath_tx_aggr_start(sc, sta, tid, ssn);
 		if (!ret)
@@ -2300,6 +2267,7 @@
 	struct ath_vif *avp;
 	struct ath_buf *bf;
 	struct ath_tx_status ts;
+	bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
 	int status;
 
 	vif = sc->beacon.bslot[0];
@@ -2310,7 +2278,7 @@
 	if (!avp->is_bslot_active)
 		return 0;
 
-	if (!sc->beacon.tx_processed) {
+	if (!sc->beacon.tx_processed && !edma) {
 		tasklet_disable(&sc->bcon_tasklet);
 
 		bf = avp->av_bcbuf;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index b8c6c38..4f84849 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -748,7 +748,8 @@
 	 * If 802.11g protection is enabled, determine whether to use RTS/CTS or
 	 * just CTS.  Note that this is only done for OFDM/HT unicast frames.
 	 */
-	if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) &&
+	if ((tx_info->control.vif &&
+	     tx_info->control.vif->bss_conf.use_cts_prot) &&
 	    (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM ||
 	     WLAN_RC_PHY_HT(rate_table->info[rix].phy))) {
 		rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT;
@@ -1226,7 +1227,7 @@
 	ath_rc_init_valid_rate_idx(ath_rc_priv);
 
 	for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
-		for (j = 0; j < MAX_TX_RATE_PHY; j++)
+		for (j = 0; j < RATE_TABLE_SIZE; j++)
 			ath_rc_priv->valid_phy_rateidx[i][j] = 0;
 		ath_rc_priv->valid_phy_ratecnt[i] = 0;
 	}
@@ -1298,12 +1299,13 @@
 	return caps;
 }
 
-static bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an,
+static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta,
 			      u8 tidno)
 {
+	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 	struct ath_atx_tid *txtid;
 
-	if (!(sc->sc_flags & SC_OP_TXAGGR))
+	if (!sta->ht_cap.ht_supported)
 		return false;
 
 	txtid = ATH_AN_2_TID(an, tidno);
@@ -1374,13 +1376,11 @@
 		if (ieee80211_is_data_qos(fc) &&
 		    skb_get_queue_mapping(skb) != IEEE80211_AC_VO) {
 			u8 *qc, tid;
-			struct ath_node *an;
 
 			qc = ieee80211_get_qos_ctl(hdr);
 			tid = qc[0] & 0xf;
-			an = (struct ath_node *)sta->drv_priv;
 
-			if(ath_tx_aggr_check(sc, an, tid))
+			if(ath_tx_aggr_check(sc, sta, tid))
 				ieee80211_start_tx_ba_session(sta, tid, 0);
 		}
 	}
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index b7a4bcd..75f8e9b 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -25,8 +25,6 @@
 
 #define ATH_RATE_MAX     30
 #define RATE_TABLE_SIZE  72
-#define MAX_TX_RATE_PHY  48
-
 
 #define RC_INVALID	0x0000
 #define RC_LEGACY	0x0001
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 7e1a91a..f4ae3ba 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -169,22 +169,17 @@
 				  enum ath9k_rx_qtype qtype, int size)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	u32 nbuf = 0;
+	struct ath_buf *bf, *tbf;
 
 	if (list_empty(&sc->rx.rxbuf)) {
 		ath_dbg(common, QUEUE, "No free rx buf available\n");
 		return;
 	}
 
-	while (!list_empty(&sc->rx.rxbuf)) {
-		nbuf++;
-
+	list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list)
 		if (!ath_rx_edma_buf_link(sc, qtype))
 			break;
 
-		if (nbuf >= size)
-			break;
-	}
 }
 
 static void ath_rx_remove_buffer(struct ath_softc *sc,
@@ -232,7 +227,6 @@
 static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size)
 {
 	skb_queue_head_init(&rx_edma->rx_fifo);
-	skb_queue_head_init(&rx_edma->rx_buffers);
 	rx_edma->rx_fifo_hwsize = size;
 }
 
@@ -658,7 +652,9 @@
 }
 
 static bool ath_edma_get_buffers(struct ath_softc *sc,
-				 enum ath9k_rx_qtype qtype)
+				 enum ath9k_rx_qtype qtype,
+				 struct ath_rx_status *rs,
+				 struct ath_buf **dest)
 {
 	struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
 	struct ath_hw *ah = sc->sc_ah;
@@ -677,7 +673,7 @@
 	dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
 				common->rx_bufsize, DMA_FROM_DEVICE);
 
-	ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data);
+	ret = ath9k_hw_process_rxdesc_edma(ah, rs, skb->data);
 	if (ret == -EINPROGRESS) {
 		/*let device gain the buffer again*/
 		dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
@@ -690,20 +686,21 @@
 		/* corrupt descriptor, skip this one and the following one */
 		list_add_tail(&bf->list, &sc->rx.rxbuf);
 		ath_rx_edma_buf_link(sc, qtype);
+
 		skb = skb_peek(&rx_edma->rx_fifo);
-		if (!skb)
-			return true;
+		if (skb) {
+			bf = SKB_CB_ATHBUF(skb);
+			BUG_ON(!bf);
 
-		bf = SKB_CB_ATHBUF(skb);
-		BUG_ON(!bf);
-
-		__skb_unlink(skb, &rx_edma->rx_fifo);
-		list_add_tail(&bf->list, &sc->rx.rxbuf);
-		ath_rx_edma_buf_link(sc, qtype);
-		return true;
+			__skb_unlink(skb, &rx_edma->rx_fifo);
+			list_add_tail(&bf->list, &sc->rx.rxbuf);
+			ath_rx_edma_buf_link(sc, qtype);
+		} else {
+			bf = NULL;
+		}
 	}
-	skb_queue_tail(&rx_edma->rx_buffers, skb);
 
+	*dest = bf;
 	return true;
 }
 
@@ -711,18 +708,15 @@
 						struct ath_rx_status *rs,
 						enum ath9k_rx_qtype qtype)
 {
-	struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
-	struct sk_buff *skb;
-	struct ath_buf *bf;
+	struct ath_buf *bf = NULL;
 
-	while (ath_edma_get_buffers(sc, qtype));
-	skb = __skb_dequeue(&rx_edma->rx_buffers);
-	if (!skb)
-		return NULL;
+	while (ath_edma_get_buffers(sc, qtype, rs, &bf)) {
+		if (!bf)
+			continue;
 
-	bf = SKB_CB_ATHBUF(skb);
-	ath9k_hw_process_rxdesc_edma(sc->sc_ah, rs, skb->data);
-	return bf;
+		return bf;
+	}
+	return NULL;
 }
 
 static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
@@ -954,6 +948,7 @@
 	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = common->ah;
 	int last_rssi;
+	int rssi = rx_stats->rs_rssi;
 
 	if (!rx_stats->is_mybeacon ||
 	    ((ah->opmode != NL80211_IFTYPE_STATION) &&
@@ -965,13 +960,12 @@
 
 	last_rssi = sc->last_rssi;
 	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-		rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
-					      ATH_RSSI_EP_MULTIPLIER);
-	if (rx_stats->rs_rssi < 0)
-		rx_stats->rs_rssi = 0;
+		rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
+	if (rssi < 0)
+		rssi = 0;
 
 	/* Update Beacon RSSI, this is used by ANI. */
-	ah->stats.avgbrssi = rx_stats->rs_rssi;
+	ah->stats.avgbrssi = rssi;
 }
 
 /*
@@ -988,8 +982,6 @@
 {
 	struct ath_hw *ah = common->ah;
 
-	memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
-
 	/*
 	 * everything but the rate is checked here, the rate check is done
 	 * separately to avoid doing two lookups for a rate for each frame.
@@ -1011,6 +1003,8 @@
 	rx_status->signal = ah->noise + rx_stats->rs_rssi;
 	rx_status->antenna = rx_stats->rs_antenna;
 	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	if (rx_stats->rs_moreaggr)
+		rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
 
 	return 0;
 }
@@ -1845,6 +1839,8 @@
 		if (sc->sc_flags & SC_OP_RXFLUSH)
 			goto requeue_drop_frag;
 
+		memset(rxs, 0, sizeof(struct ieee80211_rx_status));
+
 		rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
 		if (rs.rs_tstamp > tsf_lower &&
 		    unlikely(rs.rs_tstamp - tsf_lower > 0x10000000))
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 80b1856..458f81b 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1151,6 +1151,7 @@
 #define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
 #define AR_ENT_OTP		  0x40d8
 #define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000
+#define AR_ENT_OTP_49GHZ_DISABLE		0x00100000
 #define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE		0x00800000
 
 #define AR_CH0_BB_DPLL1		 0x16180
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 5dd27d2..834e6bc 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -955,7 +955,9 @@
 	 */
 	rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
 	info->rtscts_rate = rate->hw_value;
-	if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+
+	if (tx_info->control.vif &&
+	    tx_info->control.vif->bss_conf.use_short_preamble)
 		info->rtscts_rate |= rate->hw_value_short;
 
 	for (i = 0; i < 4; i++) {
@@ -1290,14 +1292,11 @@
 
 	an = (struct ath_node *)sta->drv_priv;
 
-	if (sc->sc_flags & SC_OP_TXAGGR) {
-		txtid = ATH_AN_2_TID(an, tid);
-		txtid->baw_size =
-			IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
-		txtid->state |= AGGR_ADDBA_COMPLETE;
-		txtid->state &= ~AGGR_ADDBA_PROGRESS;
-		ath_tx_resume_tid(sc, txtid);
-	}
+	txtid = ATH_AN_2_TID(an, tid);
+	txtid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
+	txtid->state |= AGGR_ADDBA_COMPLETE;
+	txtid->state &= ~AGGR_ADDBA_PROGRESS;
+	ath_tx_resume_tid(sc, txtid);
 }
 
 /********************/
@@ -1356,8 +1355,7 @@
 	 * based intr on the EOSP frames.
 	 */
 	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
-		qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE |
-				TXQ_FLAG_TXERRINT_ENABLE;
+		qi.tqi_qflags = TXQ_FLAG_TXINT_ENABLE;
 	} else {
 		if (qtype == ATH9K_TX_QUEUE_UAPSD)
 			qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
@@ -1523,7 +1521,7 @@
 	ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
 
 	/* flush any pending frames if aggregation is enabled */
-	if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
+	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !retry_tx)
 		ath_txq_drain_pending_buffers(sc, txq);
 
 	ath_txq_unlock_complete(sc, txq);
@@ -1871,7 +1869,7 @@
 	struct ath_buf *bf;
 	u8 tidno;
 
-	if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
+	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && txctl->an &&
 		ieee80211_is_data_qos(hdr->frame_control)) {
 		tidno = ieee80211_get_qos_ctl(hdr)[0] &
 			IEEE80211_QOS_CTL_TID_MASK;
@@ -2141,7 +2139,7 @@
 	} else
 		ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
 
-	if (sc->sc_flags & SC_OP_TXAGGR)
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
 		ath_txq_schedule(sc, txq);
 }
 
@@ -2166,7 +2164,7 @@
 
 		if (list_empty(&txq->axq_q)) {
 			txq->axq_link = NULL;
-			if (sc->sc_flags & SC_OP_TXAGGR)
+			if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
 				ath_txq_schedule(sc, txq);
 			break;
 		}
@@ -2263,10 +2261,9 @@
 
 void ath_tx_tasklet(struct ath_softc *sc)
 {
+	struct ath_hw *ah = sc->sc_ah;
+	u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1) & ah->intr_txqs;
 	int i;
-	u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
-
-	ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
 
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
 		if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
@@ -2296,9 +2293,12 @@
 			break;
 		}
 
-		/* Skip beacon completions */
-		if (ts.qid == sc->beacon.beaconq)
+		/* Process beacon completions separately */
+		if (ts.qid == sc->beacon.beaconq) {
+			sc->beacon.tx_processed = true;
+			sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
 			continue;
+		}
 
 		txq = &sc->tx.txq[ts.qid];
 
diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c
index d9218fe..ea2c737 100644
--- a/drivers/net/wireless/ath/main.c
+++ b/drivers/net/wireless/ath/main.c
@@ -57,7 +57,8 @@
 }
 EXPORT_SYMBOL(ath_rxbuf_alloc);
 
-void ath_printk(const char *level, const char *fmt, ...)
+void ath_printk(const char *level, const struct ath_common* common,
+		const char *fmt, ...)
 {
 	struct va_format vaf;
 	va_list args;
@@ -67,7 +68,11 @@
 	vaf.fmt = fmt;
 	vaf.va = &args;
 
-	printk("%sath: %pV", level, &vaf);
+	if (common && common->hw && common->hw->wiphy)
+		printk("%sath: %s: %pV",
+		       level, wiphy_name(common->hw->wiphy), &vaf);
+	else
+		printk("%sath: %pV", level, &vaf);
 
 	va_end(args);
 }
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 835462d..67c13af 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -932,6 +932,9 @@
 	/* Flag that implement the queues stopping. */
 	bool tx_queue_stopped[B43_QOS_QUEUE_NUM];
 
+	/* firmware loading work */
+	struct work_struct firmware_load;
+
 	/* The device LEDs. */
 	struct b43_leds leds;
 
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 5189cf3..c79e663 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2390,8 +2390,14 @@
 	return err;
 }
 
-static int b43_request_firmware(struct b43_wldev *dev)
+static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl);
+static void b43_one_core_detach(struct b43_bus_dev *dev);
+
+static void b43_request_firmware(struct work_struct *work)
 {
+	struct b43_wl *wl = container_of(work,
+			    struct b43_wl, firmware_load);
+	struct b43_wldev *dev = wl->current_dev;
 	struct b43_request_fw_context *ctx;
 	unsigned int i;
 	int err;
@@ -2399,23 +2405,23 @@
 
 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
-		return -ENOMEM;
+		return;
 	ctx->dev = dev;
 
 	ctx->req_type = B43_FWTYPE_PROPRIETARY;
 	err = b43_try_request_fw(ctx);
 	if (!err)
-		goto out; /* Successfully loaded it. */
-	err = ctx->fatal_failure;
-	if (err)
+		goto start_ieee80211; /* Successfully loaded it. */
+	/* Was fw version known? */
+	if (ctx->fatal_failure)
 		goto out;
 
+	/* proprietary fw not found, try open source */
 	ctx->req_type = B43_FWTYPE_OPENSOURCE;
 	err = b43_try_request_fw(ctx);
 	if (!err)
-		goto out; /* Successfully loaded it. */
-	err = ctx->fatal_failure;
-	if (err)
+		goto start_ieee80211; /* Successfully loaded it. */
+	if(ctx->fatal_failure)
 		goto out;
 
 	/* Could not find a usable firmware. Print the errors. */
@@ -2425,11 +2431,20 @@
 			b43err(dev->wl, errmsg);
 	}
 	b43_print_fw_helptext(dev->wl, 1);
-	err = -ENOENT;
+	goto out;
+
+start_ieee80211:
+	err = ieee80211_register_hw(wl->hw);
+	if (err)
+		goto err_one_core_detach;
+	b43_leds_register(wl->current_dev);
+	goto out;
+
+err_one_core_detach:
+	b43_one_core_detach(dev->dev);
 
 out:
 	kfree(ctx);
-	return err;
 }
 
 static int b43_upload_microcode(struct b43_wldev *dev)
@@ -2706,6 +2721,8 @@
 		mask |= 0x0060;
 		set |= 0x0060;
 	}
+	if (dev->dev->chip_id == 0x5354)
+		set &= 0xff02;
 	if (0 /* FIXME: conditional unknown */ ) {
 		b43_write16(dev, B43_MMIO_GPIO_MASK,
 			    b43_read16(dev, B43_MMIO_GPIO_MASK)
@@ -3021,9 +3038,6 @@
 	macctl |= B43_MACCTL_INFRA;
 	b43_write32(dev, B43_MMIO_MACCTL, macctl);
 
-	err = b43_request_firmware(dev);
-	if (err)
-		goto out;
 	err = b43_upload_microcode(dev);
 	if (err)
 		goto out;	/* firmware is released later */
@@ -4153,6 +4167,7 @@
 	mutex_unlock(&wl->mutex);
 	cancel_delayed_work_sync(&dev->periodic_work);
 	cancel_work_sync(&wl->tx_work);
+	cancel_work_sync(&wl->firmware_load);
 	mutex_lock(&wl->mutex);
 	dev = wl->current_dev;
 	if (!dev || b43_status(dev) < B43_STAT_STARTED) {
@@ -5312,16 +5327,13 @@
 	if (err)
 		goto bcma_err_wireless_exit;
 
-	err = ieee80211_register_hw(wl->hw);
-	if (err)
-		goto bcma_err_one_core_detach;
-	b43_leds_register(wl->current_dev);
+	/* setup and start work to load firmware */
+	INIT_WORK(&wl->firmware_load, b43_request_firmware);
+	schedule_work(&wl->firmware_load);
 
 bcma_out:
 	return err;
 
-bcma_err_one_core_detach:
-	b43_one_core_detach(dev);
 bcma_err_wireless_exit:
 	ieee80211_free_hw(wl->hw);
 	return err;
@@ -5388,18 +5400,13 @@
 	if (err)
 		goto err_wireless_exit;
 
-	if (first) {
-		err = ieee80211_register_hw(wl->hw);
-		if (err)
-			goto err_one_core_detach;
-		b43_leds_register(wl->current_dev);
-	}
+	/* setup and start work to load firmware */
+	INIT_WORK(&wl->firmware_load, b43_request_firmware);
+	schedule_work(&wl->firmware_load);
 
       out:
 	return err;
 
-      err_one_core_detach:
-	b43_one_core_detach(dev);
       err_wireless_exit:
 	if (first)
 		b43_wireless_exit(dev, wl);
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index 98e3d44..a29da67 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -581,6 +581,9 @@
 	struct mutex mutex;		/* locks wireless core state */
 	spinlock_t leds_lock;		/* lock for leds */
 
+	/* firmware loading work */
+	struct work_struct firmware_load;
+
 	/* We can only have one operating interface (802.11 core)
 	 * at a time. General information about this interface follows.
 	 */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 75e70bc..df7e16d 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1557,8 +1557,15 @@
 	return -EPROTO;
 }
 
-static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
+static int b43legacy_one_core_attach(struct ssb_device *dev,
+				     struct b43legacy_wl *wl);
+static void b43legacy_one_core_detach(struct ssb_device *dev);
+
+static void b43legacy_request_firmware(struct work_struct *work)
 {
+	struct b43legacy_wl *wl = container_of(work,
+				  struct b43legacy_wl, firmware_load);
+	struct b43legacy_wldev *dev = wl->current_dev;
 	struct b43legacy_firmware *fw = &dev->fw;
 	const u8 rev = dev->dev->id.revision;
 	const char *filename;
@@ -1624,8 +1631,14 @@
 		if (err)
 			goto err_load;
 	}
+	err = ieee80211_register_hw(wl->hw);
+	if (err)
+		goto err_one_core_detach;
+	return;
 
-	return 0;
+err_one_core_detach:
+	b43legacy_one_core_detach(dev->dev);
+	goto error;
 
 err_load:
 	b43legacy_print_fw_helptext(dev->wl);
@@ -1639,7 +1652,7 @@
 
 error:
 	b43legacy_release_firmware(dev);
-	return err;
+	return;
 }
 
 static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
@@ -2153,9 +2166,6 @@
 	macctl |= B43legacy_MACCTL_INFRA;
 	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
 
-	err = b43legacy_request_firmware(dev);
-	if (err)
-		goto out;
 	err = b43legacy_upload_microcode(dev);
 	if (err)
 		goto out; /* firmware is released later */
@@ -3860,17 +3870,13 @@
 	if (err)
 		goto err_wireless_exit;
 
-	if (first) {
-		err = ieee80211_register_hw(wl->hw);
-		if (err)
-			goto err_one_core_detach;
-	}
+	/* setup and start work to load firmware */
+	INIT_WORK(&wl->firmware_load, b43legacy_request_firmware);
+	schedule_work(&wl->firmware_load);
 
 out:
 	return err;
 
-err_one_core_detach:
-	b43legacy_one_core_detach(dev);
 err_wireless_exit:
 	if (first)
 		b43legacy_wireless_exit(dev, wl);
@@ -3885,6 +3891,7 @@
 	/* We must cancel any work here before unregistering from ieee80211,
 	 * as the ieee80211 unreg will destroy the workqueue. */
 	cancel_work_sync(&wldev->restart_work);
+	cancel_work_sync(&wl->firmware_load);
 
 	B43legacy_WARN_ON(!wl);
 	if (wl->current_dev == wldev)
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 96faaef..9503341 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -1860,7 +1860,7 @@
 	 * which accounts for the factor of 4 */
 #define REG_MAX_PWR 20
 	max_pwr = min(REG_MAX_PWR * 4
-		      - dev->dev->bus->sprom.antenna_gain.ghz24.a0
+		      - dev->dev->bus->sprom.antenna_gain.a0
 		      - 0x6, max_pwr);
 
 	/* find the desired power in Q5.2 - power_level is in dBm
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 83ca3cc..4688904 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -604,7 +604,7 @@
 	sdio_unregister_driver(&brcmf_sdmmc_driver);
 }
 
-int brcmf_sdio_init(void)
+void brcmf_sdio_init(void)
 {
 	int ret;
 
@@ -614,6 +614,4 @@
 
 	if (ret)
 		brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
-
-	return ret;
 }
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index b7671b3..3669164 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -108,11 +108,11 @@
 
 #ifdef CONFIG_BRCMFMAC_SDIO
 extern void brcmf_sdio_exit(void);
-extern int brcmf_sdio_init(void);
+extern void brcmf_sdio_init(void);
 #endif
 #ifdef CONFIG_BRCMFMAC_USB
 extern void brcmf_usb_exit(void);
-extern int brcmf_usb_init(void);
+extern void brcmf_usb_init(void);
 #endif
 
 #endif				/* _BRCMF_BUS_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index c4da058..2a1e5ae 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -1181,27 +1181,29 @@
 }
 #endif				/* DEBUG */
 
-static int __init brcmfmac_init(void)
+static void brcmf_driver_init(struct work_struct *work)
 {
-	int ret = 0;
-
 #ifdef CONFIG_BRCMFMAC_SDIO
-	ret = brcmf_sdio_init();
-	if (ret)
-		goto fail;
+	brcmf_sdio_init();
 #endif
 #ifdef CONFIG_BRCMFMAC_USB
-	ret = brcmf_usb_init();
-	if (ret)
-		goto fail;
+	brcmf_usb_init();
 #endif
+}
+static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);
 
-fail:
-	return ret;
+static int __init brcmfmac_module_init(void)
+{
+	if (!schedule_work(&brcmf_driver_work))
+		return -EBUSY;
+
+	return 0;
 }
 
-static void __exit brcmfmac_exit(void)
+static void __exit brcmfmac_module_exit(void)
 {
+	cancel_work_sync(&brcmf_driver_work);
+
 #ifdef CONFIG_BRCMFMAC_SDIO
 	brcmf_sdio_exit();
 #endif
@@ -1210,5 +1212,5 @@
 #endif
 }
 
-module_init(brcmfmac_init);
-module_exit(brcmfmac_exit);
+module_init(brcmfmac_module_init);
+module_exit(brcmfmac_module_exit);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index d4a9e8e..8236422 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -514,9 +514,9 @@
 
 	brcmf_usb_del_fromq(devinfo, req);
 	if (urb->status == 0)
-		devinfo->bus_pub.stats.tx_packets++;
+		devinfo->bus_pub.bus->dstats.tx_packets++;
 	else
-		devinfo->bus_pub.stats.tx_errors++;
+		devinfo->bus_pub.bus->dstats.tx_errors++;
 
 	dev_kfree_skb(req->skb);
 	req->skb = NULL;
@@ -536,9 +536,9 @@
 	req->skb = NULL;
 
 	if (urb->status == 0) {
-		devinfo->bus_pub.stats.rx_packets++;
+		devinfo->bus_pub.bus->dstats.rx_packets++;
 	} else {
-		devinfo->bus_pub.stats.rx_errors++;
+		devinfo->bus_pub.bus->dstats.rx_errors++;
 		dev_kfree_skb(skb);
 		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
 		return;
@@ -712,9 +712,6 @@
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
 	u16 ifnum;
 
-	if (devinfo == NULL)
-		return -EINVAL;
-
 	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
 		return 0;
 
@@ -900,8 +897,8 @@
 			sizeof(struct bootrom_id_le));
 		return false;
 	} else {
-		devinfo->bus_pub.attrib.devid = chipid;
-		devinfo->bus_pub.attrib.chiprev = chiprev;
+		devinfo->bus_pub.devid = chipid;
+		devinfo->bus_pub.chiprev = chiprev;
 	}
 	return true;
 }
@@ -1067,7 +1064,7 @@
 	if (devinfo == NULL)
 		return -EINVAL;
 
-	if (devinfo->bus_pub.attrib.devid == 0xDEAD)
+	if (devinfo->bus_pub.devid == 0xDEAD)
 		return -EINVAL;
 
 	err = brcmf_usb_dl_writeimage(devinfo, fw, len);
@@ -1088,7 +1085,7 @@
 	if (!devinfo)
 		return -EINVAL;
 
-	if (devinfo->bus_pub.attrib.devid == 0xDEAD)
+	if (devinfo->bus_pub.devid == 0xDEAD)
 		return -EINVAL;
 
 	/* Check we are runnable */
@@ -1127,18 +1124,19 @@
 static int
 brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
 {
-	struct brcmf_usb_attrib *attr;
+	int devid, chiprev;
 	int err;
 
 	brcmf_dbg(TRACE, "enter\n");
 	if (devinfo == NULL)
 		return -ENODEV;
 
-	attr = &devinfo->bus_pub.attrib;
+	devid = devinfo->bus_pub.devid;
+	chiprev = devinfo->bus_pub.chiprev;
 
-	if (!brcmf_usb_chip_support(attr->devid, attr->chiprev)) {
+	if (!brcmf_usb_chip_support(devid, chiprev)) {
 		brcmf_dbg(ERROR, "unsupported chip %d rev %d\n",
-			  attr->devid, attr->chiprev);
+			  devid, chiprev);
 		return -EINVAL;
 	}
 
@@ -1617,7 +1615,7 @@
 	g_image.len = 0;
 }
 
-int brcmf_usb_init(void)
+void brcmf_usb_init(void)
 {
-	return usb_register(&brcmf_usbdrvr);
+	usb_register(&brcmf_usbdrvr);
 }
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
index b31da7b..acfa5e8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
@@ -33,36 +33,12 @@
 };
 
 struct brcmf_stats {
-	u32 tx_errors;
-	u32 tx_packets;
-	u32 tx_multicast;
 	u32 tx_ctlpkts;
 	u32 tx_ctlerrs;
-	u32 tx_dropped;
-	u32 tx_flushed;
-	u32 rx_errors;
-	u32 rx_packets;
-	u32 rx_multicast;
 	u32 rx_ctlpkts;
 	u32 rx_ctlerrs;
-	u32 rx_dropped;
-	u32 rx_flushed;
-
 };
 
-struct brcmf_usb_attrib {
-	int bustype;
-	int vid;
-	int pid;
-	int devid;
-	int chiprev; /* chip revsion number */
-	int mtu;
-	int nchan; /* Data Channels */
-	int has_2nd_bulk_in_ep;
-};
-
-struct brcmf_usbdev_info;
-
 struct brcmf_usbdev {
 	struct brcmf_bus *bus;
 	struct brcmf_usbdev_info *devinfo;
@@ -70,7 +46,8 @@
 	struct brcmf_stats stats;
 	int ntxq, nrxq, rxsize;
 	u32 bus_mtu;
-	struct brcmf_usb_attrib attrib;
+	int devid;
+	int chiprev; /* chip revsion number */
 };
 
 /* IO Request Block (IRB) */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 15d7f00..d13ae9c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -2003,7 +2003,6 @@
 	s32 err = 0;
 	u16 channel;
 	u32 freq;
-	u64 notify_timestamp;
 	u16 notify_capability;
 	u16 notify_interval;
 	u8 *notify_ie;
@@ -2026,7 +2025,6 @@
 	freq = ieee80211_channel_to_frequency(channel, band->band);
 	notify_channel = ieee80211_get_channel(wiphy, freq);
 
-	notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
 	notify_capability = le16_to_cpu(bi->capability);
 	notify_interval = le16_to_cpu(bi->beacon_period);
 	notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
@@ -2040,10 +2038,9 @@
 	WL_CONN("Capability: %X\n", notify_capability);
 	WL_CONN("Beacon interval: %d\n", notify_interval);
 	WL_CONN("Signal: %d\n", notify_signal);
-	WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
 
 	bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
-		notify_timestamp, notify_capability, notify_interval, notify_ie,
+		0, notify_capability, notify_interval, notify_ie,
 		notify_ielen, notify_signal, GFP_KERNEL);
 
 	if (!bss)
@@ -2098,7 +2095,6 @@
 	s32 err = 0;
 	u16 channel;
 	u32 freq;
-	u64 notify_timestamp;
 	u16 notify_capability;
 	u16 notify_interval;
 	u8 *notify_ie;
@@ -2134,7 +2130,6 @@
 	freq = ieee80211_channel_to_frequency(channel, band->band);
 	notify_channel = ieee80211_get_channel(wiphy, freq);
 
-	notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
 	notify_capability = le16_to_cpu(bi->capability);
 	notify_interval = le16_to_cpu(bi->beacon_period);
 	notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
@@ -2145,10 +2140,9 @@
 	WL_CONN("capability: %X\n", notify_capability);
 	WL_CONN("beacon interval: %d\n", notify_interval);
 	WL_CONN("signal: %d\n", notify_signal);
-	WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
 
 	bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
-		notify_timestamp, notify_capability, notify_interval,
+		0, notify_capability, notify_interval,
 		notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
 
 	if (!bss) {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index dbee696..95b5902 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -959,14 +959,13 @@
 		if (supr_status) {
 			update_rate = false;
 			if (supr_status == TX_STATUS_SUPR_BADCH) {
-				wiphy_err(wiphy, "%s: Pkt tx suppressed, "
-					  "illegal channel possibly %d\n",
+				wiphy_err(wiphy,
+					  "%s: Pkt tx suppressed, illegal channel possibly %d\n",
 					  __func__, CHSPEC_CHANNEL(
 					  wlc->default_bss->chanspec));
 			} else {
 				if (supr_status != TX_STATUS_SUPR_FRAG)
-					wiphy_err(wiphy, "%s:"
-						  "supr_status 0x%x\n",
+					wiphy_err(wiphy, "%s: supr_status 0x%x\n",
 						  __func__, supr_status);
 			}
 			/* no need to retry for badch; will fail again */
@@ -988,9 +987,8 @@
 			}
 		} else if (txs->phyerr) {
 			update_rate = false;
-			wiphy_err(wiphy, "wl%d: ampdu tx phy "
-				  "error (0x%x)\n", wlc->pub->unit,
-				  txs->phyerr);
+			wiphy_err(wiphy, "%s: ampdu tx phy error (0x%x)\n",
+				  __func__, txs->phyerr);
 
 			if (brcm_msg_level & LOG_ERROR_VAL) {
 				brcmu_prpkt("txpkt (AMPDU)", p);
@@ -1018,10 +1016,10 @@
 		ack_recd = false;
 		if (ba_recd) {
 			bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
-			BCMMSG(wlc->wiphy, "tid %d seq %d,"
-				" start_seq %d, bindex %d set %d, index %d\n",
-				tid, seq, start_seq, bindex,
-				isset(bitmap, bindex), index);
+			BCMMSG(wiphy,
+			       "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
+			       tid, seq, start_seq, bindex,
+			       isset(bitmap, bindex), index);
 			/* if acked then clear bit and free packet */
 			if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
 			    && isset(bitmap, bindex)) {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index fec0f10..569ab8a 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -1169,25 +1169,31 @@
 /**
  * This is the main entry point for the brcmsmac driver.
  *
- * This function determines if a device pointed to by pdev is a WL device,
- * and if so, performs a brcms_attach() on it.
- *
+ * This function is scheduled upon module initialization and
+ * does the driver registration, which result in brcms_bcma_probe()
+ * call resulting in the driver bringup.
  */
+static void brcms_driver_init(struct work_struct *work)
+{
+	int error;
+
+	error = bcma_driver_register(&brcms_bcma_driver);
+	if (error)
+		pr_err("%s: register returned %d\n", __func__, error);
+}
+
+static DECLARE_WORK(brcms_driver_work, brcms_driver_init);
+
 static int __init brcms_module_init(void)
 {
-	int error = -ENODEV;
-
 #ifdef DEBUG
 	if (msglevel != 0xdeadbeef)
 		brcm_msg_level = msglevel;
-#endif				/* DEBUG */
+#endif
+	if (!schedule_work(&brcms_driver_work))
+		return -EBUSY;
 
-	error = bcma_driver_register(&brcms_bcma_driver);
-	pr_err("%s: register returned %d\n", __func__, error);
-	if (!error)
-		return 0;
-
-	return error;
+	return 0;
 }
 
 /**
@@ -1199,6 +1205,7 @@
  */
 static void __exit brcms_module_exit(void)
 {
+	cancel_work_sync(&brcms_driver_work);
 	bcma_driver_unregister(&brcms_bcma_driver);
 }
 
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 5d7e97e..ddf340f 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -298,8 +298,6 @@
 };
 #endif
 
-#define WEXT_USECHANNELS 1
-
 static const long ipw2100_frequencies[] = {
 	2412, 2417, 2422, 2427,
 	2432, 2437, 2442, 2447,
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h
index ecb561d..570d6fb 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.h
+++ b/drivers/net/wireless/ipw2x00/ipw2200.h
@@ -27,8 +27,6 @@
 #ifndef __ipw2200_h__
 #define __ipw2200_h__
 
-#define WEXT_USECHANNELS 1
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -1999,18 +1997,6 @@
 #define CFG_SYS_ANTENNA_B               0x03	/* force antenna B */
 #define CFG_SYS_ANTENNA_SLOW_DIV        0x02	/* consider background noise */
 
-/*
- * The definitions below were lifted off the ipw2100 driver, which only
- * supports 'b' mode, so I'm sure these are not exactly correct.
- *
- * Somebody fix these!!
- */
-#define REG_MIN_CHANNEL             0
-#define REG_MAX_CHANNEL             14
-
-#define REG_CHANNEL_MASK            0x00003FFF
-#define IPW_IBSS_11B_DEFAULT_MASK   0x87ff
-
 #define IPW_MAX_CONFIG_RETRIES 10
 
 #endif				/* __ipw2200_h__ */
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index b42052b..e5ac047 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -5355,7 +5355,7 @@
 	if (changes & BSS_CHANGED_ASSOC) {
 		D_MAC80211("ASSOC %d\n", bss_conf->assoc);
 		if (bss_conf->assoc) {
-			il->timestamp = bss_conf->timestamp;
+			il->timestamp = bss_conf->last_tsf;
 
 			if (!il_is_rfkill(il))
 				il->ops->post_associate(il);
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index ae08498..2fe6273 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -1,6 +1,6 @@
 config IWLWIFI
 	tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
-	depends on PCI && MAC80211
+	depends on PCI && MAC80211 && HAS_IOMEM
 	select FW_LOADER
 	select NEW_LEDS
 	select LEDS_CLASS
@@ -127,3 +127,12 @@
          support when it is loaded.
 
          Say Y only if you want to experiment with P2P.
+
+config IWLWIFI_EXPERIMENTAL_MFP
+	bool "support MFP (802.11w) even if uCode doesn't advertise"
+	depends on IWLWIFI
+	help
+	  This option enables experimental MFP (802.11W) support
+	  even if the microcode doesn't advertise it.
+
+	  Say Y only if you want to experiment with MFP.
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index afa0bb8..85d163e 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -14,7 +14,7 @@
 iwlwifi-objs		+= iwl-2000.o
 iwlwifi-objs		+= iwl-pci.o
 iwlwifi-objs		+= iwl-drv.o
-iwlwifi-objs		+= iwl-trans.o
+iwlwifi-objs		+= iwl-notif-wait.o
 iwlwifi-objs		+= iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
 
 iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 605ee3d..5b0d888 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -43,6 +43,7 @@
 #include "iwl-agn-hw.h"
 #include "iwl-shared.h"
 #include "iwl-cfg.h"
+#include "iwl-prph.h"
 
 /* Highest firmware API version supported */
 #define IWL1000_UCODE_API_MAX 6
@@ -95,9 +96,8 @@
 				~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
 }
 
-static struct iwl_sensitivity_ranges iwl1000_sensitivity = {
+static const struct iwl_sensitivity_ranges iwl1000_sensitivity = {
 	.min_nrg_cck = 95,
-	.max_nrg_cck = 0, /* not used, set to 0 */
 	.auto_corr_min_ofdm = 90,
 	.auto_corr_min_ofdm_mrc = 170,
 	.auto_corr_min_ofdm_x1 = 120,
@@ -122,23 +122,15 @@
 
 static void iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 {
-	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
-	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
-		cfg(priv)->base_params->num_of_queues =
-			iwlagn_mod_params.num_of_queues;
-
-	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-
 	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ);
 
-	hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+	hw_params(priv).tx_chains_num =
+		num_of_ant(hw_params(priv).valid_tx_ant);
 	if (cfg(priv)->rx_with_siso_diversity)
 		hw_params(priv).rx_chains_num = 1;
 	else
 		hw_params(priv).rx_chains_num =
-			num_of_ant(cfg(priv)->valid_rx_ant);
-	hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
-	hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+			num_of_ant(hw_params(priv).valid_rx_ant);
 
 	iwl1000_set_ct_threshold(priv);
 
@@ -163,7 +155,7 @@
 	.temperature = iwlagn_temperature,
 };
 
-static struct iwl_base_params iwl1000_base_params = {
+static const struct iwl_base_params iwl1000_base_params = {
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
@@ -178,7 +170,8 @@
 	.max_event_log_size = 128,
 	.wd_disable = true,
 };
-static struct iwl_ht_params iwl1000_ht_params = {
+
+static const struct iwl_ht_params iwl1000_ht_params = {
 	.ht_greenfield_support = true,
 	.use_rts_for_aggregation = true, /* use rts/cts protection */
 	.smps_mode = IEEE80211_SMPS_DYNAMIC,
@@ -197,13 +190,13 @@
 	.base_params = &iwl1000_base_params,			\
 	.led_mode = IWL_LED_BLINK
 
-struct iwl_cfg iwl1000_bgn_cfg = {
+const struct iwl_cfg iwl1000_bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
 	IWL_DEVICE_1000,
 	.ht_params = &iwl1000_ht_params,
 };
 
-struct iwl_cfg iwl1000_bg_cfg = {
+const struct iwl_cfg iwl1000_bg_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
 	IWL_DEVICE_1000,
 };
@@ -222,13 +215,13 @@
 	.led_mode = IWL_LED_RF_STATE,				\
 	.rx_with_siso_diversity = true
 
-struct iwl_cfg iwl100_bgn_cfg = {
+const struct iwl_cfg iwl100_bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
 	IWL_DEVICE_100,
 	.ht_params = &iwl1000_ht_params,
 };
 
-struct iwl_cfg iwl100_bg_cfg = {
+const struct iwl_cfg iwl100_bg_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 100 BG",
 	IWL_DEVICE_100,
 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index e6e8c79..5635b9e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -91,9 +91,8 @@
 			    CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
 }
 
-static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
+static const struct iwl_sensitivity_ranges iwl2000_sensitivity = {
 	.min_nrg_cck = 97,
-	.max_nrg_cck = 0, /* not used, set to 0 */
 	.auto_corr_min_ofdm = 80,
 	.auto_corr_min_ofdm_mrc = 128,
 	.auto_corr_min_ofdm_x1 = 105,
@@ -118,23 +117,15 @@
 
 static void iwl2000_hw_set_hw_params(struct iwl_priv *priv)
 {
-	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
-	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
-		cfg(priv)->base_params->num_of_queues =
-			iwlagn_mod_params.num_of_queues;
-
-	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-
 	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ);
 
-	hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+	hw_params(priv).tx_chains_num =
+		num_of_ant(hw_params(priv).valid_tx_ant);
 	if (cfg(priv)->rx_with_siso_diversity)
 		hw_params(priv).rx_chains_num = 1;
 	else
 		hw_params(priv).rx_chains_num =
-			num_of_ant(cfg(priv)->valid_rx_ant);
-	hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
-	hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+			num_of_ant(hw_params(priv).valid_rx_ant);
 
 	iwl2000_set_ct_threshold(priv);
 
@@ -155,16 +146,13 @@
 			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REGULATORY_BAND_NO_HT40,
 		},
-		.update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
+		.enhanced_txpower = true,
 	},
 	.temperature = iwlagn_temperature,
 };
 
 static struct iwl_lib_ops iwl2030_lib = {
 	.set_hw_params = iwl2000_hw_set_hw_params,
-	.bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
-	.bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
-	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
 	.nic_config = iwl2000_nic_config,
 	.eeprom_ops = {
 		.regulatory_bands = {
@@ -176,12 +164,12 @@
 			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REGULATORY_BAND_NO_HT40,
 		},
-		.update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
+		.enhanced_txpower = true,
 	},
 	.temperature = iwlagn_temperature,
 };
 
-static struct iwl_base_params iwl2000_base_params = {
+static const struct iwl_base_params iwl2000_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -200,7 +188,7 @@
 };
 
 
-static struct iwl_base_params iwl2030_base_params = {
+static const struct iwl_base_params iwl2030_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -218,12 +206,12 @@
 	.hd_v2 = true,
 };
 
-static struct iwl_ht_params iwl2000_ht_params = {
+static const struct iwl_ht_params iwl2000_ht_params = {
 	.ht_greenfield_support = true,
 	.use_rts_for_aggregation = true, /* use rts/cts protection */
 };
 
-static struct iwl_bt_params iwl2030_bt_params = {
+static const struct iwl_bt_params iwl2030_bt_params = {
 	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
 	.advanced_bt_coexist = true,
 	.agg_time_limit = BT_AGG_THRESHOLD_DEF,
@@ -249,13 +237,13 @@
 	.led_mode = IWL_LED_RF_STATE,				\
 	.iq_invert = true					\
 
-struct iwl_cfg iwl2000_2bgn_cfg = {
+const struct iwl_cfg iwl2000_2bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
 	IWL_DEVICE_2000,
 	.ht_params = &iwl2000_ht_params,
 };
 
-struct iwl_cfg iwl2000_2bgn_d_cfg = {
+const struct iwl_cfg iwl2000_2bgn_d_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 2200D BGN",
 	IWL_DEVICE_2000,
 	.ht_params = &iwl2000_ht_params,
@@ -279,7 +267,7 @@
 	.adv_pm = true,						\
 	.iq_invert = true					\
 
-struct iwl_cfg iwl2030_2bgn_cfg = {
+const struct iwl_cfg iwl2030_2bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
 	IWL_DEVICE_2030,
 	.ht_params = &iwl2000_ht_params,
@@ -303,13 +291,13 @@
 	.rx_with_siso_diversity = true,				\
 	.iq_invert = true					\
 
-struct iwl_cfg iwl105_bgn_cfg = {
+const struct iwl_cfg iwl105_bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
 	IWL_DEVICE_105,
 	.ht_params = &iwl2000_ht_params,
 };
 
-struct iwl_cfg iwl105_bgn_d_cfg = {
+const struct iwl_cfg iwl105_bgn_d_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 105D BGN",
 	IWL_DEVICE_105,
 	.ht_params = &iwl2000_ht_params,
@@ -334,7 +322,7 @@
 	.rx_with_siso_diversity = true,				\
 	.iq_invert = true					\
 
-struct iwl_cfg iwl135_bgn_cfg = {
+const struct iwl_cfg iwl135_bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
 	IWL_DEVICE_135,
 	.ht_params = &iwl2000_ht_params,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 1527dec..a805e97 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -45,6 +45,7 @@
 #include "iwl-trans.h"
 #include "iwl-shared.h"
 #include "iwl-cfg.h"
+#include "iwl-prph.h"
 
 /* Highest firmware API version supported */
 #define IWL5000_UCODE_API_MAX 5
@@ -63,12 +64,8 @@
 /* NIC configuration for 5000 series */
 static void iwl5000_nic_config(struct iwl_priv *priv)
 {
-	unsigned long flags;
-
 	iwl_rf_config(priv);
 
-	spin_lock_irqsave(&priv->shrd->lock, flags);
-
 	/* W/A : NIC is stuck in a reset state after Early PCIe power off
 	 * (PCIe power is lost before PERST# is asserted),
 	 * causing ME FW to lose ownership and not being able to obtain it back.
@@ -76,14 +73,10 @@
 	iwl_set_bits_mask_prph(trans(priv), APMG_PS_CTRL_REG,
 				APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
 				~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
-
-
-	spin_unlock_irqrestore(&priv->shrd->lock, flags);
 }
 
-static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
+static const struct iwl_sensitivity_ranges iwl5000_sensitivity = {
 	.min_nrg_cck = 100,
-	.max_nrg_cck = 0, /* not used, set to 0 */
 	.auto_corr_min_ofdm = 90,
 	.auto_corr_min_ofdm_mrc = 170,
 	.auto_corr_min_ofdm_x1 = 105,
@@ -108,7 +101,6 @@
 
 static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
 	.min_nrg_cck = 95,
-	.max_nrg_cck = 0, /* not used, set to 0 */
 	.auto_corr_min_ofdm = 90,
 	.auto_corr_min_ofdm_mrc = 170,
 	.auto_corr_min_ofdm_x1 = 105,
@@ -164,20 +156,13 @@
 
 static void iwl5000_hw_set_hw_params(struct iwl_priv *priv)
 {
-	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
-	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
-		cfg(priv)->base_params->num_of_queues =
-			iwlagn_mod_params.num_of_queues;
-
-	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-
 	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
 
-	hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
-	hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant);
-	hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
-	hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+	hw_params(priv).tx_chains_num =
+		num_of_ant(hw_params(priv).valid_tx_ant);
+	hw_params(priv).rx_chains_num =
+		num_of_ant(hw_params(priv).valid_rx_ant);
 
 	iwl5000_set_ct_threshold(priv);
 
@@ -187,20 +172,13 @@
 
 static void iwl5150_hw_set_hw_params(struct iwl_priv *priv)
 {
-	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
-	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
-		cfg(priv)->base_params->num_of_queues =
-			iwlagn_mod_params.num_of_queues;
-
-	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-
 	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
 
-	hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
-	hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant);
-	hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
-	hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+	hw_params(priv).tx_chains_num =
+		num_of_ant(hw_params(priv).valid_tx_ant);
+	hw_params(priv).rx_chains_num =
+		num_of_ant(hw_params(priv).valid_rx_ant);
 
 	iwl5150_set_ct_threshold(priv);
 
@@ -288,7 +266,7 @@
 		return -EFAULT;
 	}
 
-	return iwl_trans_send_cmd(trans(priv), &hcmd);
+	return iwl_dvm_send_cmd(priv, &hcmd);
 }
 
 static struct iwl_lib_ops iwl5000_lib = {
@@ -327,7 +305,7 @@
 	.temperature = iwl5150_temperature,
 };
 
-static struct iwl_base_params iwl5000_base_params = {
+static const struct iwl_base_params iwl5000_base_params = {
 	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -340,7 +318,8 @@
 	.no_idle_support = true,
 	.wd_disable = true,
 };
-static struct iwl_ht_params iwl5000_ht_params = {
+
+static const struct iwl_ht_params iwl5000_ht_params = {
 	.ht_greenfield_support = true,
 };
 
@@ -356,7 +335,7 @@
 	.base_params = &iwl5000_base_params,			\
 	.led_mode = IWL_LED_BLINK
 
-struct iwl_cfg iwl5300_agn_cfg = {
+const struct iwl_cfg iwl5300_agn_cfg = {
 	.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
 	IWL_DEVICE_5000,
 	/* at least EEPROM 0x11A has wrong info */
@@ -365,7 +344,7 @@
 	.ht_params = &iwl5000_ht_params,
 };
 
-struct iwl_cfg iwl5100_bgn_cfg = {
+const struct iwl_cfg iwl5100_bgn_cfg = {
 	.name = "Intel(R) WiFi Link 5100 BGN",
 	IWL_DEVICE_5000,
 	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
@@ -373,14 +352,14 @@
 	.ht_params = &iwl5000_ht_params,
 };
 
-struct iwl_cfg iwl5100_abg_cfg = {
+const struct iwl_cfg iwl5100_abg_cfg = {
 	.name = "Intel(R) WiFi Link 5100 ABG",
 	IWL_DEVICE_5000,
 	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
 	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
 };
 
-struct iwl_cfg iwl5100_agn_cfg = {
+const struct iwl_cfg iwl5100_agn_cfg = {
 	.name = "Intel(R) WiFi Link 5100 AGN",
 	IWL_DEVICE_5000,
 	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
@@ -388,7 +367,7 @@
 	.ht_params = &iwl5000_ht_params,
 };
 
-struct iwl_cfg iwl5350_agn_cfg = {
+const struct iwl_cfg iwl5350_agn_cfg = {
 	.name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
 	.fw_name_pre = IWL5000_FW_PRE,
 	.ucode_api_max = IWL5000_UCODE_API_MAX,
@@ -418,14 +397,14 @@
 	.led_mode = IWL_LED_BLINK,				\
 	.internal_wimax_coex = true
 
-struct iwl_cfg iwl5150_agn_cfg = {
+const struct iwl_cfg iwl5150_agn_cfg = {
 	.name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
 	IWL_DEVICE_5150,
 	.ht_params = &iwl5000_ht_params,
 
 };
 
-struct iwl_cfg iwl5150_abg_cfg = {
+const struct iwl_cfg iwl5150_abg_cfg = {
 	.name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
 	IWL_DEVICE_5150,
 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 223e60a..64060cd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -96,25 +96,25 @@
 		    CSR_GP_DRIVER_REG_BIT_6050_1x2);
 }
 
+static void iwl6000i_additional_nic_config(struct iwl_priv *priv)
+{
+	/* 2x2 IPA phy type */
+	iwl_write32(trans(priv), CSR_GP_DRIVER_REG,
+		     CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
+}
+
 /* NIC configuration for 6000 series */
 static void iwl6000_nic_config(struct iwl_priv *priv)
 {
 	iwl_rf_config(priv);
 
-	/* no locking required for register write */
-	if (cfg(priv)->pa_type == IWL_PA_INTERNAL) {
-		/* 2x2 IPA phy type */
-		iwl_write32(trans(priv), CSR_GP_DRIVER_REG,
-			     CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
-	}
 	/* do additional nic configuration if needed */
 	if (cfg(priv)->additional_nic_config)
-			cfg(priv)->additional_nic_config(priv);
+		cfg(priv)->additional_nic_config(priv);
 }
 
-static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
+static const struct iwl_sensitivity_ranges iwl6000_sensitivity = {
 	.min_nrg_cck = 110,
-	.max_nrg_cck = 0, /* not used, set to 0 */
 	.auto_corr_min_ofdm = 80,
 	.auto_corr_min_ofdm_mrc = 128,
 	.auto_corr_min_ofdm_x1 = 105,
@@ -139,24 +139,16 @@
 
 static void iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 {
-	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
-	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
-		cfg(priv)->base_params->num_of_queues =
-			iwlagn_mod_params.num_of_queues;
-
-	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-
 	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
 
-	hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+	hw_params(priv).tx_chains_num =
+		num_of_ant(hw_params(priv).valid_tx_ant);
 	if (cfg(priv)->rx_with_siso_diversity)
 		hw_params(priv).rx_chains_num = 1;
 	else
 		hw_params(priv).rx_chains_num =
-			num_of_ant(cfg(priv)->valid_rx_ant);
-	hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
-	hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+			num_of_ant(hw_params(priv).valid_rx_ant);
 
 	iwl6000_set_ct_threshold(priv);
 
@@ -233,7 +225,7 @@
 		return -EFAULT;
 	}
 
-	return iwl_trans_send_cmd(trans(priv), &hcmd);
+	return iwl_dvm_send_cmd(priv, &hcmd);
 }
 
 static struct iwl_lib_ops iwl6000_lib = {
@@ -250,16 +242,13 @@
 			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REG_BAND_52_HT40_CHANNELS
 		},
-		.update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
+		.enhanced_txpower = true,
 	},
 	.temperature = iwlagn_temperature,
 };
 
 static struct iwl_lib_ops iwl6030_lib = {
 	.set_hw_params = iwl6000_hw_set_hw_params,
-	.bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
-	.bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
-	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
 	.set_channel_switch = iwl6000_hw_channel_switch,
 	.nic_config = iwl6000_nic_config,
 	.eeprom_ops = {
@@ -272,12 +261,12 @@
 			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REG_BAND_52_HT40_CHANNELS
 		},
-		.update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
+		.enhanced_txpower = true,
 	},
 	.temperature = iwlagn_temperature,
 };
 
-static struct iwl_base_params iwl6000_base_params = {
+static const struct iwl_base_params iwl6000_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -294,7 +283,7 @@
 	.shadow_reg_enable = true,
 };
 
-static struct iwl_base_params iwl6050_base_params = {
+static const struct iwl_base_params iwl6050_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -310,7 +299,8 @@
 	.max_event_log_size = 1024,
 	.shadow_reg_enable = true,
 };
-static struct iwl_base_params iwl6000_g2_base_params = {
+
+static const struct iwl_base_params iwl6000_g2_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@@ -327,12 +317,12 @@
 	.shadow_reg_enable = true,
 };
 
-static struct iwl_ht_params iwl6000_ht_params = {
+static const struct iwl_ht_params iwl6000_ht_params = {
 	.ht_greenfield_support = true,
 	.use_rts_for_aggregation = true, /* use rts/cts protection */
 };
 
-static struct iwl_bt_params iwl6000_bt_params = {
+static const struct iwl_bt_params iwl6000_bt_params = {
 	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
 	.advanced_bt_coexist = true,
 	.agg_time_limit = BT_AGG_THRESHOLD_DEF,
@@ -355,40 +345,41 @@
 	.need_temp_offset_calib = true,				\
 	.led_mode = IWL_LED_RF_STATE
 
-struct iwl_cfg iwl6005_2agn_cfg = {
+const struct iwl_cfg iwl6005_2agn_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
 	IWL_DEVICE_6005,
 	.ht_params = &iwl6000_ht_params,
 };
 
-struct iwl_cfg iwl6005_2abg_cfg = {
+const struct iwl_cfg iwl6005_2abg_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
 	IWL_DEVICE_6005,
 };
 
-struct iwl_cfg iwl6005_2bg_cfg = {
+const struct iwl_cfg iwl6005_2bg_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
 	IWL_DEVICE_6005,
 };
 
-struct iwl_cfg iwl6005_2agn_sff_cfg = {
+const struct iwl_cfg iwl6005_2agn_sff_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6205S AGN",
 	IWL_DEVICE_6005,
 	.ht_params = &iwl6000_ht_params,
 };
 
-struct iwl_cfg iwl6005_2agn_d_cfg = {
+const struct iwl_cfg iwl6005_2agn_d_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6205D AGN",
 	IWL_DEVICE_6005,
 	.ht_params = &iwl6000_ht_params,
 };
 
-struct iwl_cfg iwl6005_2agn_mow1_cfg = {
+const struct iwl_cfg iwl6005_2agn_mow1_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6206 AGN",
 	IWL_DEVICE_6005,
 	.ht_params = &iwl6000_ht_params,
 };
-struct iwl_cfg iwl6005_2agn_mow2_cfg = {
+
+const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6207 AGN",
 	IWL_DEVICE_6005,
 	.ht_params = &iwl6000_ht_params,
@@ -410,53 +401,53 @@
 	.led_mode = IWL_LED_RF_STATE,				\
 	.adv_pm = true						\
 
-struct iwl_cfg iwl6030_2agn_cfg = {
+const struct iwl_cfg iwl6030_2agn_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
 	IWL_DEVICE_6030,
 	.ht_params = &iwl6000_ht_params,
 };
 
-struct iwl_cfg iwl6030_2abg_cfg = {
+const struct iwl_cfg iwl6030_2abg_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
 	IWL_DEVICE_6030,
 };
 
-struct iwl_cfg iwl6030_2bgn_cfg = {
+const struct iwl_cfg iwl6030_2bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6230 BGN",
 	IWL_DEVICE_6030,
 	.ht_params = &iwl6000_ht_params,
 };
 
-struct iwl_cfg iwl6030_2bg_cfg = {
+const struct iwl_cfg iwl6030_2bg_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
 	IWL_DEVICE_6030,
 };
 
-struct iwl_cfg iwl6035_2agn_cfg = {
+const struct iwl_cfg iwl6035_2agn_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
 	IWL_DEVICE_6030,
 	.ht_params = &iwl6000_ht_params,
 };
 
-struct iwl_cfg iwl1030_bgn_cfg = {
+const struct iwl_cfg iwl1030_bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
 	IWL_DEVICE_6030,
 	.ht_params = &iwl6000_ht_params,
 };
 
-struct iwl_cfg iwl1030_bg_cfg = {
+const struct iwl_cfg iwl1030_bg_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
 	IWL_DEVICE_6030,
 };
 
-struct iwl_cfg iwl130_bgn_cfg = {
+const struct iwl_cfg iwl130_bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
 	IWL_DEVICE_6030,
 	.ht_params = &iwl6000_ht_params,
 	.rx_with_siso_diversity = true,
 };
 
-struct iwl_cfg iwl130_bg_cfg = {
+const struct iwl_cfg iwl130_bg_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 130 BG",
 	IWL_DEVICE_6030,
 	.rx_with_siso_diversity = true,
@@ -477,22 +468,22 @@
 	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,	\
 	.lib = &iwl6000_lib,					\
+	.additional_nic_config = iwl6000i_additional_nic_config,\
 	.base_params = &iwl6000_base_params,			\
-	.pa_type = IWL_PA_INTERNAL,				\
 	.led_mode = IWL_LED_BLINK
 
-struct iwl_cfg iwl6000i_2agn_cfg = {
+const struct iwl_cfg iwl6000i_2agn_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
 	IWL_DEVICE_6000i,
 	.ht_params = &iwl6000_ht_params,
 };
 
-struct iwl_cfg iwl6000i_2abg_cfg = {
+const struct iwl_cfg iwl6000i_2abg_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
 	IWL_DEVICE_6000i,
 };
 
-struct iwl_cfg iwl6000i_2bg_cfg = {
+const struct iwl_cfg iwl6000i_2bg_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
 	IWL_DEVICE_6000i,
 };
@@ -513,13 +504,13 @@
 	.led_mode = IWL_LED_BLINK,				\
 	.internal_wimax_coex = true
 
-struct iwl_cfg iwl6050_2agn_cfg = {
+const struct iwl_cfg iwl6050_2agn_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
 	IWL_DEVICE_6050,
 	.ht_params = &iwl6000_ht_params,
 };
 
-struct iwl_cfg iwl6050_2abg_cfg = {
+const struct iwl_cfg iwl6050_2abg_cfg = {
 	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
 	IWL_DEVICE_6050,
 };
@@ -538,18 +529,18 @@
 	.led_mode = IWL_LED_BLINK,				\
 	.internal_wimax_coex = true
 
-struct iwl_cfg iwl6150_bgn_cfg = {
+const struct iwl_cfg iwl6150_bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
 	IWL_DEVICE_6150,
 	.ht_params = &iwl6000_ht_params,
 };
 
-struct iwl_cfg iwl6150_bg_cfg = {
+const struct iwl_cfg iwl6150_bg_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG",
 	IWL_DEVICE_6150,
 };
 
-struct iwl_cfg iwl6000_3agn_cfg = {
+const struct iwl_cfg iwl6000_3agn_cfg = {
 	.name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN",
 	.fw_name_pre = IWL6000_FW_PRE,
 	.ucode_api_max = IWL6000_UCODE_API_MAX,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index 988ee45..84cbe7b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -68,13 +68,19 @@
 #include "iwl-agn-calib.h"
 #include "iwl-trans.h"
 #include "iwl-agn.h"
-#include "iwl-wifi.h"
-#include "iwl-ucode.h"
 
 /*****************************************************************************
  * INIT calibrations framework
  *****************************************************************************/
 
+/* Opaque calibration results */
+struct iwl_calib_result {
+	struct list_head list;
+	size_t cmd_len;
+	struct iwl_calib_hdr hdr;
+	/* data follows */
+};
+
 struct statistics_general_data {
 	u32 beacon_silence_rssi_a;
 	u32 beacon_silence_rssi_b;
@@ -84,7 +90,7 @@
 	u32 beacon_energy_c;
 };
 
-int iwl_send_calib_results(struct iwl_trans *trans)
+int iwl_send_calib_results(struct iwl_priv *priv)
 {
 	struct iwl_host_cmd hcmd = {
 		.id = REPLY_PHY_CALIBRATION_CMD,
@@ -92,15 +98,15 @@
 	};
 	struct iwl_calib_result *res;
 
-	list_for_each_entry(res, &trans->calib_results, list) {
+	list_for_each_entry(res, &priv->calib_results, list) {
 		int ret;
 
 		hcmd.len[0] = res->cmd_len;
 		hcmd.data[0] = &res->hdr;
 		hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
-		ret = iwl_trans_send_cmd(trans, &hcmd);
+		ret = iwl_dvm_send_cmd(priv, &hcmd);
 		if (ret) {
-			IWL_ERR(trans, "Error %d on calib cmd %d\n",
+			IWL_ERR(priv, "Error %d on calib cmd %d\n",
 				ret, res->hdr.op_code);
 			return ret;
 		}
@@ -109,7 +115,7 @@
 	return 0;
 }
 
-int iwl_calib_set(struct iwl_trans *trans,
+int iwl_calib_set(struct iwl_priv *priv,
 		  const struct iwl_calib_hdr *cmd, int len)
 {
 	struct iwl_calib_result *res, *tmp;
@@ -121,7 +127,7 @@
 	memcpy(&res->hdr, cmd, len);
 	res->cmd_len = len;
 
-	list_for_each_entry(tmp, &trans->calib_results, list) {
+	list_for_each_entry(tmp, &priv->calib_results, list) {
 		if (tmp->hdr.op_code == res->hdr.op_code) {
 			list_replace(&tmp->list, &res->list);
 			kfree(tmp);
@@ -130,16 +136,16 @@
 	}
 
 	/* wasn't in list already */
-	list_add_tail(&res->list, &trans->calib_results);
+	list_add_tail(&res->list, &priv->calib_results);
 
 	return 0;
 }
 
-void iwl_calib_free_results(struct iwl_trans *trans)
+void iwl_calib_free_results(struct iwl_priv *priv)
 {
 	struct iwl_calib_result *res, *tmp;
 
-	list_for_each_entry_safe(res, tmp, &trans->calib_results, list) {
+	list_for_each_entry_safe(res, tmp, &priv->calib_results, list) {
 		list_del(&res->list);
 		kfree(res);
 	}
@@ -494,7 +500,7 @@
 	memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
 	       sizeof(u16)*HD_TABLE_SIZE);
 
-	return iwl_trans_send_cmd(trans(priv), &cmd_out);
+	return iwl_dvm_send_cmd(priv, &cmd_out);
 }
 
 /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
@@ -583,7 +589,7 @@
 	       &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]),
 	       sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES);
 
-	return iwl_trans_send_cmd(trans(priv), &cmd_out);
+	return iwl_dvm_send_cmd(priv, &cmd_out);
 }
 
 void iwl_init_sensitivity(struct iwl_priv *priv)
@@ -636,7 +642,7 @@
 	data->last_bad_plcp_cnt_cck = 0;
 	data->last_fa_cnt_cck = 0;
 
-	if (nic(priv)->fw.enhance_sensitivity_table)
+	if (priv->fw->enhance_sensitivity_table)
 		ret |= iwl_enhance_sensitivity_write(priv);
 	else
 		ret |= iwl_sensitivity_write(priv);
@@ -655,7 +661,6 @@
 	struct iwl_sensitivity_data *data = NULL;
 	struct statistics_rx_non_phy *rx_info;
 	struct statistics_rx_phy *ofdm, *cck;
-	unsigned long flags;
 	struct statistics_general_data statis;
 
 	if (priv->disable_sens_cal)
@@ -668,13 +673,13 @@
 		return;
 	}
 
-	spin_lock_irqsave(&priv->shrd->lock, flags);
+	spin_lock_bh(&priv->statistics.lock);
 	rx_info = &priv->statistics.rx_non_phy;
 	ofdm = &priv->statistics.rx_ofdm;
 	cck = &priv->statistics.rx_cck;
 	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
 		IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
-		spin_unlock_irqrestore(&priv->shrd->lock, flags);
+		spin_unlock_bh(&priv->statistics.lock);
 		return;
 	}
 
@@ -698,7 +703,7 @@
 	statis.beacon_energy_c =
 			le32_to_cpu(rx_info->beacon_energy_c);
 
-	spin_unlock_irqrestore(&priv->shrd->lock, flags);
+	spin_unlock_bh(&priv->statistics.lock);
 
 	IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
 
@@ -747,7 +752,7 @@
 
 	iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
 	iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
-	if (nic(priv)->fw.enhance_sensitivity_table)
+	if (priv->fw->enhance_sensitivity_table)
 		iwl_enhance_sensitivity_write(priv);
 	else
 		iwl_sensitivity_write(priv);
@@ -849,7 +854,7 @@
 			 * connect the first valid tx chain
 			 */
 			first_chain =
-				find_first_chain(cfg(priv)->valid_tx_ant);
+				find_first_chain(hw_params(priv).valid_tx_ant);
 			data->disconn_array[first_chain] = 0;
 			active_chains |= BIT(first_chain);
 			IWL_DEBUG_CALIB(priv,
@@ -874,10 +879,8 @@
 }
 
 static void iwlagn_gain_computation(struct iwl_priv *priv,
-		u32 average_noise[NUM_RX_CHAINS],
-		u16 min_average_noise_antenna_i,
-		u32 min_average_noise,
-		u8 default_chain)
+				    u32 average_noise[NUM_RX_CHAINS],
+				    u8 default_chain)
 {
 	int i;
 	s32 delta_g;
@@ -925,7 +928,7 @@
 			priv->phy_calib_chain_noise_gain_cmd);
 		cmd.delta_gain_1 = data->delta_gain_code[1];
 		cmd.delta_gain_2 = data->delta_gain_code[2];
-		iwl_trans_send_cmd_pdu(trans(priv), REPLY_PHY_CALIBRATION_CMD,
+		iwl_dvm_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
 			CMD_ASYNC, sizeof(cmd), &cmd);
 
 		data->radio_write = 1;
@@ -958,7 +961,6 @@
 	u16 stat_chnum = INITIALIZATION_VALUE;
 	u8 rxon_band24;
 	u8 stat_band24;
-	unsigned long flags;
 	struct statistics_rx_non_phy *rx_info;
 
 	/*
@@ -983,13 +985,13 @@
 		return;
 	}
 
-	spin_lock_irqsave(&priv->shrd->lock, flags);
+	spin_lock_bh(&priv->statistics.lock);
 
 	rx_info = &priv->statistics.rx_non_phy;
 
 	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
 		IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
-		spin_unlock_irqrestore(&priv->shrd->lock, flags);
+		spin_unlock_bh(&priv->statistics.lock);
 		return;
 	}
 
@@ -1004,7 +1006,7 @@
 	if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
 		IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
 				rxon_chnum, rxon_band24);
-		spin_unlock_irqrestore(&priv->shrd->lock, flags);
+		spin_unlock_bh(&priv->statistics.lock);
 		return;
 	}
 
@@ -1023,7 +1025,7 @@
 	chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
 	chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
 
-	spin_unlock_irqrestore(&priv->shrd->lock, flags);
+	spin_unlock_bh(&priv->statistics.lock);
 
 	data->beacon_count++;
 
@@ -1083,8 +1085,7 @@
 			min_average_noise, min_average_noise_antenna_i);
 
 	iwlagn_gain_computation(priv, average_noise,
-				min_average_noise_antenna_i, min_average_noise,
-				find_first_chain(cfg(priv)->valid_rx_ant));
+				find_first_chain(hw_params(priv).valid_rx_ant));
 
 	/* Some power changes may have been made during the calibration.
 	 * Update and commit the RXON
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 5be0d36..3e1698d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -32,7 +32,6 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 
-#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
@@ -52,7 +51,7 @@
 	struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
 	u8 tx_ant_cfg_cmd;
 
-	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status),
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
 		      "TX Power requested while scanning!\n"))
 		return -EAGAIN;
 
@@ -77,17 +76,19 @@
 	tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED;
 	tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO;
 
-	if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) == 1)
+	if (IWL_UCODE_API(priv->fw->ucode_ver) == 1)
 		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
 	else
 		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
 
-	return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC,
+	return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC,
 			sizeof(tx_power_cmd), &tx_power_cmd);
 }
 
 void iwlagn_temperature(struct iwl_priv *priv)
 {
+	lockdep_assert_held(&priv->statistics.lock);
+
 	/* store temperature from correct statistics (in Celsius) */
 	priv->temperature = le32_to_cpu(priv->statistics.common.temperature);
 	iwl_tt_handler(priv);
@@ -233,19 +234,19 @@
 				IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
 				IWL_PAN_SCD_MULTICAST_MSK;
 
-	if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
+	if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
 		flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
 
 	IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
 		       flush_cmd.fifo_control);
 	flush_cmd.flush_control = cpu_to_le16(flush_control);
 
-	return iwl_trans_send_cmd(trans(priv), &cmd);
+	return iwl_dvm_send_cmd(priv, &cmd);
 }
 
 void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
 {
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	ieee80211_stop_queues(priv->hw);
 	if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
 		IWL_ERR(priv, "flush request fail\n");
@@ -255,7 +256,7 @@
 	iwl_trans_wait_tx_queue_empty(trans(priv));
 done:
 	ieee80211_wake_queues(priv->hw);
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 /*
@@ -434,12 +435,12 @@
 	if (cfg(priv)->bt_params->bt_session_2) {
 		memcpy(&bt_cmd_2000.basic, &basic,
 			sizeof(basic));
-		ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
+		ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
 			CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
 	} else {
 		memcpy(&bt_cmd_6000.basic, &basic,
 			sizeof(basic));
-		ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
+		ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
 			CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
 	}
 	if (ret)
@@ -452,7 +453,7 @@
 	struct iwl_rxon_context *ctx, *found_ctx = NULL;
 	bool found_ap = false;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	/* Check whether AP or GO mode is active. */
 	if (rssi_ena) {
@@ -565,7 +566,7 @@
 		break;
 	}
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	/*
 	 * We can not send command to firmware while scanning. When the scan
@@ -574,7 +575,7 @@
 	 * STATUS_SCANNING to avoid race when queue_work two times from
 	 * different notifications, but quit and not perform any work at all.
 	 */
-	if (test_bit(STATUS_SCAN_HW, &priv->shrd->status))
+	if (test_bit(STATUS_SCAN_HW, &priv->status))
 		goto out;
 
 	iwl_update_chain_flags(priv);
@@ -593,7 +594,7 @@
 	 */
 	iwlagn_bt_coex_rssi_monitor(priv);
 out:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 /*
@@ -705,12 +706,11 @@
 }
 
 int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
-				  struct iwl_rx_mem_buffer *rxb,
+				  struct iwl_rx_cmd_buffer *rxb,
 				  struct iwl_device_cmd *cmd)
 {
-	unsigned long flags;
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
+	struct iwl_bt_coex_profile_notif *coex = (void *)pkt->data;
 	struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
 
 	if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
@@ -754,9 +754,7 @@
 
 	/* FIXME: based on notification, adjust the prio_boost */
 
-	spin_lock_irqsave(&priv->shrd->lock, flags);
 	priv->bt_ci_compliance = coex->bt_ci_compliance;
-	spin_unlock_irqrestore(&priv->shrd->lock, flags);
 	return 0;
 }
 
@@ -971,7 +969,7 @@
 	u16 p1k[IWLAGN_P1K_SIZE];
 	int ret, i;
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
 	     key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
@@ -1077,7 +1075,7 @@
 		break;
 	}
 
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 int iwlagn_send_patterns(struct iwl_priv *priv,
@@ -1117,13 +1115,12 @@
 	}
 
 	cmd.data[0] = pattern_cmd;
-	err = iwl_trans_send_cmd(trans(priv), &cmd);
+	err = iwl_dvm_send_cmd(priv, &cmd);
 	kfree(pattern_cmd);
 	return err;
 }
 
-int iwlagn_suspend(struct iwl_priv *priv,
-		struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
+int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
 {
 	struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd;
 	struct iwl_rxon_cmd rxon;
@@ -1192,11 +1189,12 @@
 
 	memcpy(&rxon, &ctx->active, sizeof(rxon));
 
+	priv->ucode_loaded = false;
 	iwl_trans_stop_device(trans(priv));
 
-	priv->shrd->wowlan = true;
+	priv->wowlan = true;
 
-	ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_WOWLAN);
+	ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
 	if (ret)
 		goto out;
 
@@ -1224,11 +1222,11 @@
 		 * constraints. Since we're in the suspend path
 		 * that isn't really a problem though.
 		 */
-		mutex_unlock(&priv->shrd->mutex);
+		mutex_unlock(&priv->mutex);
 		ieee80211_iter_keys(priv->hw, ctx->vif,
 				    iwlagn_wowlan_program_keys,
 				    &key_data);
-		mutex_lock(&priv->shrd->mutex);
+		mutex_lock(&priv->mutex);
 		if (key_data.error) {
 			ret = -EIO;
 			goto out;
@@ -1243,13 +1241,13 @@
 				.len[0] = sizeof(key_data.rsc_tsc),
 			};
 
-			ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd);
+			ret = iwl_dvm_send_cmd(priv, &rsc_tsc_cmd);
 			if (ret)
 				goto out;
 		}
 
 		if (key_data.use_tkip) {
-			ret = iwl_trans_send_cmd_pdu(trans(priv),
+			ret = iwl_dvm_send_cmd_pdu(priv,
 						 REPLY_WOWLAN_TKIP_PARAMS,
 						 CMD_SYNC, sizeof(tkip_cmd),
 						 &tkip_cmd);
@@ -1265,7 +1263,7 @@
 			kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
 			kek_kck_cmd.replay_ctr = priv->replay_ctr;
 
-			ret = iwl_trans_send_cmd_pdu(trans(priv),
+			ret = iwl_dvm_send_cmd_pdu(priv,
 						 REPLY_WOWLAN_KEK_KCK_MATERIAL,
 						 CMD_SYNC, sizeof(kek_kck_cmd),
 						 &kek_kck_cmd);
@@ -1274,12 +1272,12 @@
 		}
 	}
 
-	ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_D3_CONFIG, CMD_SYNC,
+	ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, CMD_SYNC,
 				     sizeof(d3_cfg_cmd), &d3_cfg_cmd);
 	if (ret)
 		goto out;
 
-	ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER,
+	ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_WAKEUP_FILTER,
 				 CMD_SYNC, sizeof(wakeup_filter_cmd),
 				 &wakeup_filter_cmd);
 	if (ret)
@@ -1291,3 +1289,41 @@
 	return ret;
 }
 #endif
+
+int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
+		IWL_WARN(priv, "Not sending command - %s KILL\n",
+			 iwl_is_rfkill(priv) ? "RF" : "CT");
+		return -EIO;
+	}
+
+	/*
+	 * Synchronous commands from this op-mode must hold
+	 * the mutex, this ensures we don't try to send two
+	 * (or more) synchronous commands at a time.
+	 */
+	if (cmd->flags & CMD_SYNC)
+		lockdep_assert_held(&priv->mutex);
+
+	if (priv->ucode_owner == IWL_OWNERSHIP_TM &&
+	    !(cmd->flags & CMD_ON_DEMAND)) {
+		IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n");
+		return -EIO;
+	}
+
+	return iwl_trans_send_cmd(trans(priv), cmd);
+}
+
+int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id,
+			 u32 flags, u16 len, const void *data)
+{
+	struct iwl_host_cmd cmd = {
+		.id = id,
+		.len = { len, },
+		.data = { data, },
+		.flags = flags,
+	};
+
+	return iwl_dvm_send_cmd(priv, &cmd);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index a7d6713..53f8c51 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -870,19 +870,16 @@
 {
 	struct iwl_scale_tbl_info *tbl;
 	bool full_concurrent = priv->bt_full_concurrent;
-	unsigned long flags;
 
 	if (priv->bt_ant_couple_ok) {
 		/*
 		 * Is there a need to switch between
 		 * full concurrency and 3-wire?
 		 */
-		spin_lock_irqsave(&priv->shrd->lock, flags);
 		if (priv->bt_ci_compliance && priv->bt_ant_couple_ok)
 			full_concurrent = true;
 		else
 			full_concurrent = false;
-		spin_unlock_irqrestore(&priv->shrd->lock, flags);
 	}
 	if ((priv->bt_traffic_load != priv->last_bt_traffic_load) ||
 	    (priv->bt_full_concurrent != full_concurrent)) {
@@ -2680,7 +2677,6 @@
  *       which requires station table entry to exist).
  */
 static void rs_initialize_lq(struct iwl_priv *priv,
-			     struct ieee80211_conf *conf,
 			     struct ieee80211_sta *sta,
 			     struct iwl_lq_sta *lq_sta)
 {
@@ -2915,7 +2911,7 @@
 	lq_sta->dbg_fixed_rate = 0;
 #endif
 
-	rs_initialize_lq(priv, conf, sta, lq_sta);
+	rs_initialize_lq(priv, sta, lq_sta);
 }
 
 static void rs_fill_link_cmd(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 30bb5bb..44c6f71 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -131,26 +131,27 @@
  ******************************************************************************/
 
 static int iwlagn_rx_reply_error(struct iwl_priv *priv,
-			       struct iwl_rx_mem_buffer *rxb,
+			       struct iwl_rx_cmd_buffer *rxb,
 			       struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_error_resp *err_resp = (void *)pkt->data;
 
 	IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
 		"seq 0x%04X ser 0x%08X\n",
-		le32_to_cpu(pkt->u.err_resp.error_type),
-		get_cmd_string(pkt->u.err_resp.cmd_id),
-		pkt->u.err_resp.cmd_id,
-		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
-		le32_to_cpu(pkt->u.err_resp.error_info));
+		le32_to_cpu(err_resp->error_type),
+		get_cmd_string(err_resp->cmd_id),
+		err_resp->cmd_id,
+		le16_to_cpu(err_resp->bad_cmd_seq_num),
+		le32_to_cpu(err_resp->error_info));
 	return 0;
 }
 
-static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 			       struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
+	struct iwl_csa_notification *csa = (void *)pkt->data;
 	/*
 	 * MULTI-FIXME
 	 * See iwlagn_mac_channel_switch.
@@ -158,7 +159,7 @@
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 	struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
 
-	if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
+	if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
 		return 0;
 
 	if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
@@ -177,11 +178,11 @@
 
 
 static int iwlagn_rx_spectrum_measure_notif(struct iwl_priv *priv,
-					  struct iwl_rx_mem_buffer *rxb,
+					  struct iwl_rx_cmd_buffer *rxb,
 					  struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
+	struct iwl_spectrum_notification *report = (void *)pkt->data;
 
 	if (!report->state) {
 		IWL_DEBUG_11H(priv,
@@ -195,12 +196,12 @@
 }
 
 static int iwlagn_rx_pm_sleep_notif(struct iwl_priv *priv,
-				  struct iwl_rx_mem_buffer *rxb,
+				  struct iwl_rx_cmd_buffer *rxb,
 				  struct iwl_device_cmd *cmd)
 {
 #ifdef CONFIG_IWLWIFI_DEBUG
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
+	struct iwl_sleep_notification *sleep = (void *)pkt->data;
 	IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
 		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
 #endif
@@ -208,7 +209,7 @@
 }
 
 static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
-					     struct iwl_rx_mem_buffer *rxb,
+					     struct iwl_rx_cmd_buffer *rxb,
 					     struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -217,16 +218,16 @@
 	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
 			"notification for %s:\n", len,
 			get_cmd_string(pkt->hdr.cmd));
-	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->data, len);
 	return 0;
 }
 
 static int iwlagn_rx_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb,
+				struct iwl_rx_cmd_buffer *rxb,
 				struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw;
+	struct iwlagn_beacon_notif *beacon = (void *)pkt->data;
 #ifdef CONFIG_IWLWIFI_DEBUG
 	u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status);
 	u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
@@ -266,6 +267,8 @@
 	if (priv->agg_tids_count)
 		return true;
 
+	lockdep_assert_held(&priv->statistics.lock);
+
 	old = &priv->statistics.tx;
 
 	actual_delta = le32_to_cpu(cur->actual_ack_cnt) -
@@ -318,7 +321,7 @@
 				 unsigned int msecs)
 {
 	int delta;
-	int threshold = cfg(priv)->base_params->plcp_delta_threshold;
+	int threshold = priv->plcp_delta_threshold;
 
 	if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
 		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
@@ -352,7 +355,7 @@
 {
 	unsigned int msecs;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
@@ -487,7 +490,7 @@
 #endif
 
 static int iwlagn_rx_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb,
+			      struct iwl_rx_cmd_buffer *rxb,
 			      struct iwl_device_cmd *cmd)
 {
 	unsigned long stamp = jiffies;
@@ -509,9 +512,11 @@
 	IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n",
 		     len);
 
+	spin_lock(&priv->statistics.lock);
+
 	if (len == sizeof(struct iwl_bt_notif_statistics)) {
 		struct iwl_bt_notif_statistics *stats;
-		stats = &pkt->u.stats_bt;
+		stats = (void *)&pkt->data;
 		flag = &stats->flag;
 		common = &stats->general.common;
 		rx_non_phy = &stats->rx.general.common;
@@ -529,7 +534,7 @@
 #endif
 	} else if (len == sizeof(struct iwl_notif_statistics)) {
 		struct iwl_notif_statistics *stats;
-		stats = &pkt->u.stats;
+		stats = (void *)&pkt->data;
 		flag = &stats->flag;
 		common = &stats->general.common;
 		rx_non_phy = &stats->rx.general;
@@ -542,6 +547,7 @@
 		WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n",
 			  len, sizeof(struct iwl_bt_notif_statistics),
 			  sizeof(struct iwl_notif_statistics));
+		spin_unlock(&priv->statistics.lock);
 		return 0;
 	}
 
@@ -569,7 +575,7 @@
 
 	priv->rx_statistics_jiffies = stamp;
 
-	set_bit(STATUS_STATISTICS, &priv->shrd->status);
+	set_bit(STATUS_STATISTICS, &priv->status);
 
 	/* Reschedule the statistics timer to occur in
 	 * reg_recalib_period seconds to ensure we get a
@@ -578,23 +584,27 @@
 	mod_timer(&priv->statistics_periodic, jiffies +
 		  msecs_to_jiffies(reg_recalib_period * 1000));
 
-	if (unlikely(!test_bit(STATUS_SCANNING, &priv->shrd->status)) &&
+	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
 	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
 		iwlagn_rx_calc_noise(priv);
 		queue_work(priv->workqueue, &priv->run_time_calib_work);
 	}
 	if (cfg(priv)->lib->temperature && change)
 		cfg(priv)->lib->temperature(priv);
+
+	spin_unlock(&priv->statistics.lock);
+
 	return 0;
 }
 
 static int iwlagn_rx_reply_statistics(struct iwl_priv *priv,
-				    struct iwl_rx_mem_buffer *rxb,
+				    struct iwl_rx_cmd_buffer *rxb,
 				    struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_notif_statistics *stats = (void *)pkt->data;
 
-	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
+	if (le32_to_cpu(stats->flag) & UCODE_STATISTICS_CLEAR_MSK) {
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 		memset(&priv->accum_stats, 0,
 			sizeof(priv->accum_stats));
@@ -612,12 +622,13 @@
 /* Handle notification from uCode that card's power state is changing
  * due to software, hardware, or critical temperature RFKILL */
 static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
-				    struct iwl_rx_mem_buffer *rxb,
+				    struct iwl_rx_cmd_buffer *rxb,
 				    struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
-	unsigned long status = priv->shrd->status;
+	struct iwl_card_state_notif *card_state_notif = (void *)pkt->data;
+	u32 flags = le32_to_cpu(card_state_notif->flags);
+	unsigned long status = priv->status;
 
 	IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
 			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
@@ -647,32 +658,31 @@
 		iwl_tt_exit_ct_kill(priv);
 
 	if (flags & HW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
 	else
-		clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
 
 	if (!(flags & RXON_CARD_DISABLED))
 		iwl_scan_cancel(priv);
 
 	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-	     test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)))
+	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
 		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
-			test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
+			test_bit(STATUS_RF_KILL_HW, &priv->status));
 	else
-		wake_up(&priv->shrd->wait_command_queue);
+		wake_up(&trans(priv)->wait_command_queue);
 	return 0;
 }
 
 static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv,
-				       struct iwl_rx_mem_buffer *rxb,
+				       struct iwl_rx_cmd_buffer *rxb,
 				       struct iwl_device_cmd *cmd)
 
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_missed_beacon_notif *missed_beacon;
+	struct iwl_missed_beacon_notif *missed_beacon = (void *)pkt->data;
 
-	missed_beacon = &pkt->u.missed_beacon;
 	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
 	    priv->missed_beacon_threshold) {
 		IWL_DEBUG_CALIB(priv,
@@ -681,7 +691,7 @@
 		    le32_to_cpu(missed_beacon->total_missed_becons),
 		    le32_to_cpu(missed_beacon->num_recvd_beacons),
 		    le32_to_cpu(missed_beacon->num_expected_beacons));
-		if (!test_bit(STATUS_SCANNING, &priv->shrd->status))
+		if (!test_bit(STATUS_SCANNING, &priv->status))
 			iwl_init_sensitivity(priv);
 	}
 	return 0;
@@ -690,13 +700,13 @@
 /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
  * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
 static int iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb,
+				struct iwl_rx_cmd_buffer *rxb,
 				struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 
 	priv->last_phy_res_valid = true;
-	memcpy(&priv->last_phy_res, pkt->u.raw,
+	memcpy(&priv->last_phy_res, pkt->data,
 	       sizeof(struct iwl_rx_phy_res));
 	return 0;
 }
@@ -757,12 +767,14 @@
 					struct ieee80211_hdr *hdr,
 					u16 len,
 					u32 ampdu_status,
-					struct iwl_rx_mem_buffer *rxb,
+					struct iwl_rx_cmd_buffer *rxb,
 					struct ieee80211_rx_status *stats)
 {
 	struct sk_buff *skb;
 	__le16 fc = hdr->frame_control;
 	struct iwl_rxon_context *ctx;
+	struct page *p;
+	int offset;
 
 	/* We only process data packets if the interface is open */
 	if (unlikely(!priv->is_open)) {
@@ -782,7 +794,9 @@
 		return;
 	}
 
-	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
+	offset = (void *)hdr - rxb_addr(rxb);
+	p = rxb_steal_page(rxb);
+	skb_add_rx_frag(skb, 0, p, offset, len);
 
 	iwl_update_stats(priv, false, fc, len);
 
@@ -793,23 +807,18 @@
 	* sometimes even after already having transmitted frames for the
 	* association because the new RXON may reset the information.
 	*/
-	if (unlikely(ieee80211_is_beacon(fc))) {
+	if (unlikely(ieee80211_is_beacon(fc) && priv->passive_no_rx)) {
 		for_each_context(priv, ctx) {
-			if (!ctx->last_tx_rejected)
-				continue;
 			if (compare_ether_addr(hdr->addr3,
 					       ctx->active.bssid_addr))
 				continue;
-			ctx->last_tx_rejected = false;
-			iwl_trans_wake_any_queue(trans(priv), ctx->ctxid,
-				"channel got active");
+			iwlagn_lift_passive_no_rx(priv);
 		}
 	}
 
 	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
 
 	ieee80211_rx(priv->hw, skb);
-	rxb->page = NULL;
 }
 
 static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
@@ -915,7 +924,7 @@
 /* Called for REPLY_RX (legacy ABG frames), or
  * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
 static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
-			    struct iwl_rx_mem_buffer *rxb,
+			    struct iwl_rx_cmd_buffer *rxb,
 			    struct iwl_device_cmd *cmd)
 {
 	struct ieee80211_hdr *header;
@@ -938,12 +947,12 @@
 	 * received.
 	 */
 	if (pkt->hdr.cmd == REPLY_RX) {
-		phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
-		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
+		phy_res = (struct iwl_rx_phy_res *)pkt->data;
+		header = (struct ieee80211_hdr *)(pkt->data + sizeof(*phy_res)
 				+ phy_res->cfg_phy_cnt);
 
 		len = le16_to_cpu(phy_res->byte_count);
-		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
+		rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*phy_res) +
 				phy_res->cfg_phy_cnt + len);
 		ampdu_status = le32_to_cpu(rx_pkt_status);
 	} else {
@@ -952,10 +961,10 @@
 			return 0;
 		}
 		phy_res = &priv->last_phy_res;
-		amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
-		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
+		amsdu = (struct iwl_rx_mpdu_res_start *)pkt->data;
+		header = (struct ieee80211_hdr *)(pkt->data + sizeof(*amsdu));
 		len = le16_to_cpu(amsdu->byte_count);
-		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
+		rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*amsdu) + len);
 		ampdu_status = iwlagn_translate_rx_status(priv,
 						le32_to_cpu(rx_pkt_status));
 	}
@@ -1035,12 +1044,12 @@
 }
 
 static int iwlagn_rx_noa_notification(struct iwl_priv *priv,
-				      struct iwl_rx_mem_buffer *rxb,
+				      struct iwl_rx_cmd_buffer *rxb,
 				      struct iwl_device_cmd *cmd)
 {
 	struct iwl_wipan_noa_data *new_data, *old_data;
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->u.raw;
+	struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->data;
 
 	/* no condition -- we're in softirq */
 	old_data = rcu_dereference_protected(priv->noa_data, true);
@@ -1086,7 +1095,7 @@
  */
 void iwl_setup_rx_handlers(struct iwl_priv *priv)
 {
-	int (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+	int (**handlers)(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 			       struct iwl_device_cmd *cmd);
 
 	handlers = priv->rx_handlers;
@@ -1131,21 +1140,20 @@
 	priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
 
 	/* set up notification wait support */
-	spin_lock_init(&priv->shrd->notif_wait_lock);
-	INIT_LIST_HEAD(&priv->shrd->notif_waits);
-	init_waitqueue_head(&priv->shrd->notif_waitq);
+	iwl_notification_wait_init(&priv->notif_wait);
 
 	/* Set up BT Rx handlers */
-	if (cfg(priv)->lib->bt_rx_handler_setup)
-		cfg(priv)->lib->bt_rx_handler_setup(priv);
-
+	if (cfg(priv)->bt_params)
+		iwlagn_bt_rx_handler_setup(priv);
 }
 
-int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb,
-		     struct iwl_device_cmd *cmd)
+int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
+		    struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+	void (*pre_rx_handler)(struct iwl_priv *,
+			       struct iwl_rx_cmd_buffer *);
 	int err = 0;
 
 	/*
@@ -1153,30 +1161,22 @@
 	 * even if the RX handler consumes the RXB we have
 	 * access to it in the notification wait entry.
 	 */
-	if (!list_empty(&priv->shrd->notif_waits)) {
-		struct iwl_notification_wait *w;
+	iwl_notification_wait_notify(&priv->notif_wait, pkt);
 
-		spin_lock(&priv->shrd->notif_wait_lock);
-		list_for_each_entry(w, &priv->shrd->notif_waits, list) {
-			if (w->cmd != pkt->hdr.cmd)
-				continue;
-			IWL_DEBUG_RX(priv,
-				"Notif: %s, 0x%02x - wake the callers up\n",
-				get_cmd_string(pkt->hdr.cmd),
-				pkt->hdr.cmd);
-			w->triggered = true;
-			if (w->fn)
-				w->fn(trans(priv), pkt, w->fn_data);
-		}
-		spin_unlock(&priv->shrd->notif_wait_lock);
-
-		wake_up_all(&priv->shrd->notif_waitq);
-	}
-
-	if (priv->pre_rx_handler &&
-	    priv->shrd->ucode_owner == IWL_OWNERSHIP_TM)
-		priv->pre_rx_handler(priv, rxb);
-	else {
+	/* RX data may be forwarded to userspace (using pre_rx_handler) in one
+	 * of two cases: the first, that the user owns the uCode through
+	 * testmode - in such case the pre_rx_handler is set and no further
+	 * processing takes place. The other case is when the user want to
+	 * monitor the rx w/o affecting the regular flow - the pre_rx_handler
+	 * will be set but the ownership flag != IWL_OWNERSHIP_TM and the flow
+	 * continues.
+	 * We need to use ACCESS_ONCE to prevent a case where the handler
+	 * changes between the check and the call.
+	 */
+	pre_rx_handler = ACCESS_ONCE(priv->pre_rx_handler);
+	if (pre_rx_handler)
+		pre_rx_handler(priv, rxb);
+	if (priv->ucode_owner != IWL_OWNERSHIP_TM) {
 		/* Based on type of command response or notification,
 		 *   handle those that need handling via function in
 		 *   rx_handlers table.  See iwl_setup_rx_handlers() */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 73653a6..2e1a317 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -39,7 +39,7 @@
 	int ret;
 
 	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd,
+	ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd,
 				CMD_SYNC, sizeof(*send), send);
 
 	send->filter_flags = old_filter;
@@ -60,13 +60,13 @@
 	u8 old_dev_type = send->dev_type;
 	int ret;
 
-	iwl_init_notification_wait(priv->shrd, &disable_wait,
-				      REPLY_WIPAN_DEACTIVATION_COMPLETE,
-				      NULL, NULL);
+	iwl_init_notification_wait(&priv->notif_wait, &disable_wait,
+				   REPLY_WIPAN_DEACTIVATION_COMPLETE,
+				   NULL, NULL);
 
 	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 	send->dev_type = RXON_DEV_TYPE_P2P;
-	ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd,
+	ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd,
 				CMD_SYNC, sizeof(*send), send);
 
 	send->filter_flags = old_filter;
@@ -74,9 +74,10 @@
 
 	if (ret) {
 		IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
-		iwl_remove_notification(priv->shrd, &disable_wait);
+		iwl_remove_notification(&priv->notif_wait, &disable_wait);
 	} else {
-		ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ);
+		ret = iwl_wait_notification(&priv->notif_wait,
+					    &disable_wait, HZ);
 		if (ret)
 			IWL_ERR(priv, "Timed out waiting for PAN disable\n");
 	}
@@ -92,7 +93,7 @@
 	int ret;
 
 	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC,
+	ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,
 				sizeof(*send), send);
 
 	send->filter_flags = old_filter;
@@ -121,7 +122,7 @@
 		      ctx->qos_data.qos_active,
 		      ctx->qos_data.def_qos_parm.qos_flags);
 
-	ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->qos_cmd, CMD_SYNC,
+	ret = iwl_dvm_send_cmd_pdu(priv, ctx->qos_cmd, CMD_SYNC,
 			       sizeof(struct iwl_qosparam_cmd),
 			       &ctx->qos_data.def_qos_parm);
 	if (ret)
@@ -131,7 +132,7 @@
 static int iwlagn_update_beacon(struct iwl_priv *priv,
 				struct ieee80211_vif *vif)
 {
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	dev_kfree_skb(priv->beacon_skb);
 	priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif);
@@ -180,7 +181,7 @@
 		 ctx->staging.ofdm_ht_triple_stream_basic_rates;
 	rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
 
-	ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_assoc_cmd,
+	ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_assoc_cmd,
 				CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc);
 	return ret;
 }
@@ -266,7 +267,7 @@
 	 * Associated RXON doesn't clear the station table in uCode,
 	 * so we don't need to restore stations etc. after this.
 	 */
-	ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC,
+	ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,
 		      sizeof(struct iwl_rxon_cmd), &ctx->staging);
 	if (ret) {
 		IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
@@ -274,8 +275,6 @@
 	}
 	memcpy(active, &ctx->staging, sizeof(*active));
 
-	iwl_reprogram_ap_sta(priv, ctx);
-
 	/* IBSS beacon needs to be sent after setting assoc */
 	if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
 		if (iwlagn_update_beacon(priv, ctx->vif))
@@ -315,7 +314,7 @@
 
 	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
 	ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
@@ -362,7 +361,7 @@
 		slot0 = bcnint / 2;
 		slot1 = bcnint - slot0;
 
-		if (test_bit(STATUS_SCAN_HW, &priv->shrd->status) ||
+		if (test_bit(STATUS_SCAN_HW, &priv->status) ||
 		    (!ctx_bss->vif->bss_conf.idle &&
 		     !ctx_bss->vif->bss_conf.assoc)) {
 			slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
@@ -378,7 +377,7 @@
 					ctx_pan->beacon_int;
 		slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
 
-		if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
+		if (test_bit(STATUS_SCAN_HW, &priv->status)) {
 			slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
 			slot1 = IWL_MIN_SLOT_TIME;
 		}
@@ -387,7 +386,7 @@
 	cmd.slots[0].width = cpu_to_le16(slot0);
 	cmd.slots[1].width = cpu_to_le16(slot1);
 
-	ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WIPAN_PARAMS, CMD_SYNC,
+	ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, CMD_SYNC,
 			sizeof(cmd), &cmd);
 	if (ret)
 		IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
@@ -420,12 +419,9 @@
 	bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
 	int ret;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
-		return -EINVAL;
-
-	if (!iwl_is_alive(priv->shrd))
+	if (!iwl_is_alive(priv))
 		return -EBUSY;
 
 	/* This function hardcodes a bunch of dual-mode assumptions */
@@ -434,10 +430,6 @@
 	if (!ctx->is_active)
 		return 0;
 
-	/* override BSSID if necessary due to preauth */
-	if (ctx->preauth_bssid)
-		memcpy(ctx->staging.bssid_addr, ctx->bssid, ETH_ALEN);
-
 	/* always get timestamp with Rx frame */
 	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
 
@@ -445,8 +437,7 @@
 	 * force CTS-to-self frames protection if RTS-CTS is not preferred
 	 * one aggregation protection method
 	 */
-	if (!(cfg(priv)->ht_params &&
-	      cfg(priv)->ht_params->use_rts_for_aggregation))
+	if (!hw_params(priv).use_rts_for_aggregation)
 		ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
 
 	if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
@@ -466,7 +457,7 @@
 	 * receive commit_rxon request
 	 * abort any previous channel switch if still in process
 	 */
-	if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status) &&
+	if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) &&
 	    (priv->switch_channel != ctx->staging.channel)) {
 		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
 			      le16_to_cpu(priv->switch_channel));
@@ -558,17 +549,14 @@
 
 	IWL_DEBUG_MAC80211(priv, "enter: changed %#x", changed);
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
-		goto out;
-
-	if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) {
+	if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
 		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
 		goto out;
 	}
 
-	if (!iwl_is_ready(priv->shrd)) {
+	if (!iwl_is_ready(priv)) {
 		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
 		goto out;
 	}
@@ -590,8 +578,6 @@
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-		unsigned long flags;
-
 		ch_info = iwl_get_channel_info(priv, channel->band,
 					       channel->hw_value);
 		if (!is_channel_valid(ch_info)) {
@@ -600,8 +586,6 @@
 			goto out;
 		}
 
-		spin_lock_irqsave(&priv->shrd->lock, flags);
-
 		for_each_context(priv, ctx) {
 			/* Configure HT40 channels */
 			if (ctx->ht.enabled != conf_is_ht(conf))
@@ -636,8 +620,6 @@
 					       ctx->vif);
 		}
 
-		spin_unlock_irqrestore(&priv->shrd->lock, flags);
-
 		iwl_update_bcast_stations(priv);
 
 		/*
@@ -668,7 +650,7 @@
 		iwlagn_commit_rxon(priv, ctx);
 	}
  out:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 	return ret;
@@ -685,7 +667,7 @@
 	struct ieee80211_sta_ht_cap *ht_cap;
 	bool need_multiple;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
@@ -789,7 +771,7 @@
 		memset(&cmd, 0, sizeof(cmd));
 		iwl_set_calib_hdr(&cmd.hdr,
 			priv->phy_calib_chain_noise_reset_cmd);
-		ret = iwl_trans_send_cmd_pdu(trans(priv),
+		ret = iwl_dvm_send_cmd_pdu(priv,
 					REPLY_PHY_CALIBRATION_CMD,
 					CMD_SYNC, sizeof(cmd), &cmd);
 		if (ret)
@@ -810,17 +792,17 @@
 	int ret;
 	bool force = false;
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
-	if (unlikely(!iwl_is_ready(priv->shrd))) {
+	if (unlikely(!iwl_is_ready(priv))) {
 		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		mutex_unlock(&priv->shrd->mutex);
+		mutex_unlock(&priv->mutex);
 		return;
         }
 
 	if (unlikely(!ctx->vif)) {
 		IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n");
-		mutex_unlock(&priv->shrd->mutex);
+		mutex_unlock(&priv->mutex);
 		return;
 	}
 
@@ -840,7 +822,7 @@
 
 	if (changes & BSS_CHANGED_ASSOC) {
 		if (bss_conf->assoc) {
-			priv->timestamp = bss_conf->timestamp;
+			priv->timestamp = bss_conf->last_tsf;
 			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 		} else {
 			/*
@@ -851,12 +833,8 @@
 			 * not get stuck in this case either since it
 			 * can happen if userspace gets confused.
 			 */
-			if (ctx->last_tx_rejected) {
-				ctx->last_tx_rejected = false;
-				iwl_trans_wake_any_queue(trans(priv),
-							 ctx->ctxid,
-							 "Disassoc: flush queue");
-			}
+			iwlagn_lift_passive_no_rx(priv);
+
 			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 
 			if (ctx->ctxid == IWL_RXON_CTX_BSS)
@@ -932,7 +910,6 @@
 		if (!priv->disable_chain_noise_cal)
 			iwlagn_chain_noise_reset(priv);
 		priv->start_calib = 1;
-		WARN_ON(ctx->preauth_bssid);
 	}
 
 	if (changes & BSS_CHANGED_IBSS) {
@@ -950,7 +927,7 @@
 			IWL_ERR(priv, "Error sending IBSS beacon\n");
 	}
 
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 void iwlagn_post_scan(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index f1298cd..c417560 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -26,7 +26,7 @@
  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  *
  *****************************************************************************/
-
+#include <linux/etherdevice.h>
 #include <net/mac80211.h>
 
 #include "iwl-dev.h"
@@ -34,9 +34,10 @@
 #include "iwl-agn.h"
 #include "iwl-trans.h"
 
-/* priv->shrd->sta_lock must be held */
 static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
 {
+	lockdep_assert_held(&priv->sta_lock);
+
 	if (sta_id >= IWLAGN_STATION_COUNT) {
 		IWL_ERR(priv, "invalid sta_id %u", sta_id);
 		return -EINVAL;
@@ -63,8 +64,8 @@
 				    struct iwl_addsta_cmd *addsta,
 				    struct iwl_rx_packet *pkt)
 {
+	struct iwl_add_sta_resp *add_sta_resp = (void *)pkt->data;
 	u8 sta_id = addsta->sta.sta_id;
-	unsigned long flags;
 	int ret = -EIO;
 
 	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
@@ -76,9 +77,9 @@
 	IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
 		       sta_id);
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock(&priv->sta_lock);
 
-	switch (pkt->u.add_sta.status) {
+	switch (add_sta_resp->status) {
 	case ADD_STA_SUCCESS_MSK:
 		IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
 		ret = iwl_sta_ucode_activate(priv, sta_id);
@@ -97,7 +98,7 @@
 		break;
 	default:
 		IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
-				pkt->u.add_sta.status);
+				add_sta_resp->status);
 		break;
 	}
 
@@ -118,12 +119,12 @@
 		       priv->stations[sta_id].sta.mode ==
 		       STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
 		       addsta->sta.addr);
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock(&priv->sta_lock);
 
 	return ret;
 }
 
-int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 			       struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -153,14 +154,14 @@
 		might_sleep();
 	}
 
-	ret = iwl_trans_send_cmd(trans(priv), &cmd);
+	ret = iwl_dvm_send_cmd(priv, &cmd);
 
 	if (ret || (flags & CMD_ASYNC))
 		return ret;
 	/*else the command was successfully sent in SYNC mode, need to free
 	 * the reply page */
 
-	iwl_free_pages(priv->shrd, cmd.reply_page);
+	iwl_free_resp(&cmd);
 
 	if (cmd.handler_status)
 		IWL_ERR(priv, "%s - error in the CMD response %d", __func__,
@@ -169,34 +170,38 @@
 	return cmd.handler_status;
 }
 
-static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
-				   struct ieee80211_sta *sta,
-				   struct iwl_rxon_context *ctx)
+static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
+				  struct ieee80211_sta *sta,
+				  struct iwl_rxon_context *ctx,
+				  __le32 *flags, __le32 *mask)
 {
 	struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
-	__le32 sta_flags;
 	u8 mimo_ps_mode;
 
+	*mask = STA_FLG_RTS_MIMO_PROT_MSK |
+		STA_FLG_MIMO_DIS_MSK |
+		STA_FLG_HT40_EN_MSK |
+		STA_FLG_MAX_AGG_SIZE_MSK |
+		STA_FLG_AGG_MPDU_DENSITY_MSK;
+	*flags = 0;
+
 	if (!sta || !sta_ht_inf->ht_supported)
-		goto done;
+		return;
 
 	mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
-	IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
+
+	IWL_DEBUG_INFO(priv, "STA %pM SM PS mode: %s\n",
 			(mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
 			"static" :
 			(mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
 			"dynamic" : "disabled");
 
-	sta_flags = priv->stations[index].sta.station_flags;
-
-	sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
-
 	switch (mimo_ps_mode) {
 	case WLAN_HT_CAP_SM_PS_STATIC:
-		sta_flags |= STA_FLG_MIMO_DIS_MSK;
+		*flags |= STA_FLG_MIMO_DIS_MSK;
 		break;
 	case WLAN_HT_CAP_SM_PS_DYNAMIC:
-		sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
+		*flags |= STA_FLG_RTS_MIMO_PROT_MSK;
 		break;
 	case WLAN_HT_CAP_SM_PS_DISABLED:
 		break;
@@ -205,20 +210,53 @@
 		break;
 	}
 
-	sta_flags |= cpu_to_le32(
-	      (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
+	*flags |= cpu_to_le32(
+		(u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
 
-	sta_flags |= cpu_to_le32(
-	      (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
+	*flags |= cpu_to_le32(
+		(u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
 
 	if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
-		sta_flags |= STA_FLG_HT40_EN_MSK;
-	else
-		sta_flags &= ~STA_FLG_HT40_EN_MSK;
+		*flags |= STA_FLG_HT40_EN_MSK;
+}
 
-	priv->stations[index].sta.station_flags = sta_flags;
- done:
-	return;
+int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+		      struct ieee80211_sta *sta)
+{
+	u8 sta_id = iwl_sta_id(sta);
+	__le32 flags, mask;
+	struct iwl_addsta_cmd cmd;
+
+	if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION))
+		return -EINVAL;
+
+	iwl_sta_calc_ht_flags(priv, sta, ctx, &flags, &mask);
+
+	spin_lock_bh(&priv->sta_lock);
+	priv->stations[sta_id].sta.station_flags &= ~mask;
+	priv->stations[sta_id].sta.station_flags |= flags;
+	spin_unlock_bh(&priv->sta_lock);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.mode = STA_CONTROL_MODIFY_MSK;
+	cmd.station_flags_msk = mask;
+	cmd.station_flags = flags;
+	cmd.sta.sta_id = sta_id;
+
+	return iwl_send_add_sta(priv, &cmd, CMD_SYNC);
+}
+
+static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
+				   struct ieee80211_sta *sta,
+				   struct iwl_rxon_context *ctx)
+{
+	__le32 flags, mask;
+
+	iwl_sta_calc_ht_flags(priv, sta, ctx, &flags, &mask);
+
+	lockdep_assert_held(&priv->sta_lock);
+	priv->stations[index].sta.station_flags &= ~mask;
+	priv->stations[index].sta.station_flags |= flags;
 }
 
 /**
@@ -317,18 +355,17 @@
 			   const u8 *addr, bool is_ap,
 			   struct ieee80211_sta *sta, u8 *sta_id_r)
 {
-	unsigned long flags_spin;
 	int ret = 0;
 	u8 sta_id;
 	struct iwl_addsta_cmd sta_cmd;
 
 	*sta_id_r = 0;
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+	spin_lock_bh(&priv->sta_lock);
 	sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta);
 	if (sta_id == IWL_INVALID_STATION) {
 		IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
 			addr);
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+		spin_unlock_bh(&priv->sta_lock);
 		return -EINVAL;
 	}
 
@@ -340,7 +377,7 @@
 	if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
 		IWL_DEBUG_INFO(priv, "STA %d already in process of being "
 			       "added.\n", sta_id);
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+		spin_unlock_bh(&priv->sta_lock);
 		return -EEXIST;
 	}
 
@@ -348,24 +385,24 @@
 	    (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
 		IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not "
 				"adding again.\n", sta_id, addr);
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+		spin_unlock_bh(&priv->sta_lock);
 		return -EEXIST;
 	}
 
 	priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
 	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
 	       sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+	spin_unlock_bh(&priv->sta_lock);
 
 	/* Add station to device's station table */
 	ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 	if (ret) {
-		spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+		spin_lock_bh(&priv->sta_lock);
 		IWL_ERR(priv, "Adding station %pM failed.\n",
 			priv->stations[sta_id].sta.sta.addr);
 		priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
 		priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+		spin_unlock_bh(&priv->sta_lock);
 	}
 	*sta_id_r = sta_id;
 	return ret;
@@ -373,11 +410,11 @@
 
 /**
  * iwl_sta_ucode_deactivate - deactivate ucode status for a station
- *
- * priv->shrd->sta_lock must be held
  */
 static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
 {
+	lockdep_assert_held(&priv->sta_lock);
+
 	/* Ucode must be active and driver must be non active */
 	if ((priv->stations[sta_id].used &
 	     (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) !=
@@ -396,8 +433,6 @@
 {
 	struct iwl_rx_packet *pkt;
 	int ret;
-
-	unsigned long flags_spin;
 	struct iwl_rem_sta_cmd rm_sta_cmd;
 
 	struct iwl_host_cmd cmd = {
@@ -413,12 +448,12 @@
 
 	cmd.flags |= CMD_WANT_SKB;
 
-	ret = iwl_trans_send_cmd(trans(priv), &cmd);
+	ret = iwl_dvm_send_cmd(priv, &cmd);
 
 	if (ret)
 		return ret;
 
-	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	pkt = cmd.resp_pkt;
 	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
 		IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
 			  pkt->hdr.flags);
@@ -426,14 +461,13 @@
 	}
 
 	if (!ret) {
-		switch (pkt->u.rem_sta.status) {
+		struct iwl_rem_sta_resp *rem_sta_resp = (void *)pkt->data;
+		switch (rem_sta_resp->status) {
 		case REM_STA_SUCCESS_MSK:
 			if (!temporary) {
-				spin_lock_irqsave(&priv->shrd->sta_lock,
-					flags_spin);
+				spin_lock_bh(&priv->sta_lock);
 				iwl_sta_ucode_deactivate(priv, sta_id);
-				spin_unlock_irqrestore(&priv->shrd->sta_lock,
-					flags_spin);
+				spin_unlock_bh(&priv->sta_lock);
 			}
 			IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
 			break;
@@ -443,7 +477,7 @@
 			break;
 		}
 	}
-	iwl_free_pages(priv->shrd, cmd.reply_page);
+	iwl_free_resp(&cmd);
 
 	return ret;
 }
@@ -454,10 +488,9 @@
 int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
 		       const u8 *addr)
 {
-	unsigned long flags;
 	u8 tid;
 
-	if (!iwl_is_ready(priv->shrd)) {
+	if (!iwl_is_ready(priv)) {
 		IWL_DEBUG_INFO(priv,
 			"Unable to remove station %pM, device not ready.\n",
 			addr);
@@ -475,7 +508,7 @@
 	if (WARN_ON(sta_id == IWL_INVALID_STATION))
 		return -EINVAL;
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 
 	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
 		IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
@@ -505,14 +538,49 @@
 	if (WARN_ON(priv->num_stations < 0))
 		priv->num_stations = 0;
 
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	return iwl_send_remove_station(priv, addr, sta_id, false);
 out_err:
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 	return -EINVAL;
 }
 
+void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
+			    const u8 *addr)
+{
+	u8 tid;
+
+	if (!iwl_is_ready(priv)) {
+		IWL_DEBUG_INFO(priv,
+			"Unable to remove station %pM, device not ready.\n",
+			addr);
+		return;
+	}
+
+	IWL_DEBUG_ASSOC(priv, "Deactivating STA: %pM (%d)\n", addr, sta_id);
+
+	if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION))
+		return;
+
+	spin_lock_bh(&priv->sta_lock);
+
+	WARN_ON_ONCE(!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE));
+
+	for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
+		memset(&priv->tid_data[sta_id][tid], 0,
+			sizeof(priv->tid_data[sta_id][tid]));
+
+	priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+
+	priv->num_stations--;
+
+	if (WARN_ON_ONCE(priv->num_stations < 0))
+		priv->num_stations = 0;
+
+	spin_unlock_bh(&priv->sta_lock);
+}
+
 /**
  * iwl_clear_ucode_stations - clear ucode station table bits
  *
@@ -525,12 +593,11 @@
 			      struct iwl_rxon_context *ctx)
 {
 	int i;
-	unsigned long flags_spin;
 	bool cleared = false;
 
 	IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+	spin_lock_bh(&priv->sta_lock);
 	for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
 		if (ctx && ctx->ctxid != priv->stations[i].ctxid)
 			continue;
@@ -542,7 +609,7 @@
 			cleared = true;
 		}
 	}
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+	spin_unlock_bh(&priv->sta_lock);
 
 	if (!cleared)
 		IWL_DEBUG_INFO(priv,
@@ -561,20 +628,19 @@
 {
 	struct iwl_addsta_cmd sta_cmd;
 	struct iwl_link_quality_cmd lq;
-	unsigned long flags_spin;
 	int i;
 	bool found = false;
 	int ret;
 	bool send_lq;
 
-	if (!iwl_is_ready(priv->shrd)) {
+	if (!iwl_is_ready(priv)) {
 		IWL_DEBUG_INFO(priv,
 			       "Not ready yet, not restoring any stations.\n");
 		return;
 	}
 
 	IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+	spin_lock_bh(&priv->sta_lock);
 	for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
 		if (ctx->ctxid != priv->stations[i].ctxid)
 			continue;
@@ -594,27 +660,24 @@
 			       sizeof(struct iwl_addsta_cmd));
 			send_lq = false;
 			if (priv->stations[i].lq) {
-				if (priv->shrd->wowlan)
+				if (priv->wowlan)
 					iwl_sta_fill_lq(priv, ctx, i, &lq);
 				else
 					memcpy(&lq, priv->stations[i].lq,
 					       sizeof(struct iwl_link_quality_cmd));
 				send_lq = true;
 			}
-			spin_unlock_irqrestore(&priv->shrd->sta_lock,
-					       flags_spin);
+			spin_unlock_bh(&priv->sta_lock);
 			ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 			if (ret) {
-				spin_lock_irqsave(&priv->shrd->sta_lock,
-						  flags_spin);
+				spin_lock_bh(&priv->sta_lock);
 				IWL_ERR(priv, "Adding station %pM failed.\n",
 					priv->stations[i].sta.sta.addr);
 				priv->stations[i].used &=
 						~IWL_STA_DRIVER_ACTIVE;
 				priv->stations[i].used &=
 						~IWL_STA_UCODE_INPROGRESS;
-				spin_unlock_irqrestore(&priv->shrd->sta_lock,
-						       flags_spin);
+				spin_unlock_bh(&priv->sta_lock);
 			}
 			/*
 			 * Rate scaling has already been initialized, send
@@ -623,12 +686,12 @@
 			if (send_lq)
 				iwl_send_lq_cmd(priv, ctx, &lq,
 						CMD_SYNC, true);
-			spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+			spin_lock_bh(&priv->sta_lock);
 			priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
 		}
 	}
 
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+	spin_unlock_bh(&priv->sta_lock);
 	if (!found)
 		IWL_DEBUG_INFO(priv, "Restoring all known stations .... "
 			"no stations to be restored.\n");
@@ -637,52 +700,6 @@
 			"complete.\n");
 }
 
-void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	unsigned long flags;
-	int sta_id = ctx->ap_sta_id;
-	int ret;
-	struct iwl_addsta_cmd sta_cmd;
-	struct iwl_link_quality_cmd lq;
-	bool active, have_lq = false;
-
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
-	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-		return;
-	}
-
-	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
-	sta_cmd.mode = 0;
-	if (priv->stations[sta_id].lq) {
-		memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq));
-		have_lq = true;
-	}
-
-	active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
-	priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-
-	if (active) {
-		ret = iwl_send_remove_station(
-			priv, priv->stations[sta_id].sta.sta.addr,
-			sta_id, true);
-		if (ret)
-			IWL_ERR(priv, "failed to remove STA %pM (%d)\n",
-				priv->stations[sta_id].sta.sta.addr, ret);
-	}
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
-	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-
-	ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-	if (ret)
-		IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
-			priv->stations[sta_id].sta.sta.addr, ret);
-	if (have_lq)
-		iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
-}
-
 int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
 {
 	int i;
@@ -696,10 +713,9 @@
 
 void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
 {
-	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
 		if (!(priv->stations[i].used & IWL_STA_BCAST))
 			continue;
@@ -711,7 +727,7 @@
 		kfree(priv->stations[i].lq);
 		priv->stations[i].lq = NULL;
 	}
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -783,8 +799,6 @@
 		    struct iwl_link_quality_cmd *lq, u8 flags, bool init)
 {
 	int ret = 0;
-	unsigned long flags_spin;
-
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_TX_LINK_QUALITY_CMD,
 		.len = { sizeof(struct iwl_link_quality_cmd), },
@@ -796,19 +810,19 @@
 		return -EINVAL;
 
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+	spin_lock_bh(&priv->sta_lock);
 	if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+		spin_unlock_bh(&priv->sta_lock);
 		return -EINVAL;
 	}
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+	spin_unlock_bh(&priv->sta_lock);
 
 	iwl_dump_lq_cmd(priv, lq);
 	if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
 		return -EINVAL;
 
 	if (is_lq_table_valid(priv, ctx, lq))
-		ret = iwl_trans_send_cmd(trans(priv), &cmd);
+		ret = iwl_dvm_send_cmd(priv, &cmd);
 	else
 		ret = -EINVAL;
 
@@ -819,9 +833,9 @@
 		IWL_DEBUG_INFO(priv, "init LQ command complete, "
 			       "clearing sta addition status for sta %d\n",
 			       lq->sta_id);
-		spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
+		spin_lock_bh(&priv->sta_lock);
 		priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
+		spin_unlock_bh(&priv->sta_lock);
 	}
 	return ret;
 }
@@ -834,7 +848,7 @@
 	u32 rate_flags = 0;
 	__le32 rate_n_flags;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	memset(link_cmd, 0, sizeof(*link_cmd));
 
@@ -906,7 +920,6 @@
 	int ret;
 	u8 sta_id;
 	struct iwl_link_quality_cmd *link_cmd;
-	unsigned long flags;
 
 	if (sta_id_r)
 		*sta_id_r = IWL_INVALID_STATION;
@@ -920,9 +933,9 @@
 	if (sta_id_r)
 		*sta_id_r = sta_id;
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	priv->stations[sta_id].used |= IWL_STA_LOCAL;
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	/* Set up default rate scaling table in device's station table */
 	link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
@@ -937,9 +950,9 @@
 	if (ret)
 		IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	priv->stations[sta_id].lq = link_cmd;
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	return 0;
 }
@@ -994,7 +1007,7 @@
 	cmd.len[0] = cmd_size;
 
 	if (not_empty || send_if_empty)
-		return iwl_trans_send_cmd(trans(priv), &cmd);
+		return iwl_dvm_send_cmd(priv, &cmd);
 	else
 		return 0;
 }
@@ -1002,7 +1015,7 @@
 int iwl_restore_default_wep_keys(struct iwl_priv *priv,
 				 struct iwl_rxon_context *ctx)
 {
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	return iwl_send_static_wepkey_cmd(priv, ctx, false);
 }
@@ -1013,13 +1026,13 @@
 {
 	int ret;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
 		      keyconf->keyidx);
 
 	memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
-	if (iwl_is_rfkill(priv->shrd)) {
+	if (iwl_is_rfkill(priv)) {
 		IWL_DEBUG_WEP(priv,
 			"Not sending REPLY_WEPKEY command due to RFKILL.\n");
 		/* but keys in device are clear anyway so return success */
@@ -1038,7 +1051,7 @@
 {
 	int ret;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	if (keyconf->keylen != WEP_KEY_LEN_128 &&
 	    keyconf->keylen != WEP_KEY_LEN_64) {
@@ -1080,32 +1093,19 @@
 			    struct ieee80211_sta *sta)
 {
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-	u8 sta_id = IWL_INVALID_STATION;
 
 	if (sta)
-		sta_id = iwl_sta_id(sta);
+		return iwl_sta_id(sta);
 
 	/*
 	 * The device expects GTKs for station interfaces to be
 	 * installed as GTKs for the AP station. If we have no
 	 * station ID, then use the ap_sta_id in that case.
 	 */
-	if (!sta && vif && vif_priv->ctx) {
-		switch (vif->type) {
-		case NL80211_IFTYPE_STATION:
-			sta_id = vif_priv->ctx->ap_sta_id;
-			break;
-		default:
-			/*
-			 * In all other cases, the key will be
-			 * used either for TX only or is bound
-			 * to a station already.
-			 */
-			break;
-		}
-	}
+	if (vif->type == NL80211_IFTYPE_STATION && vif_priv->ctx)
+		return vif_priv->ctx->ap_sta_id;
 
-	return sta_id;
+	return IWL_INVALID_STATION;
 }
 
 static int iwlagn_send_sta_key(struct iwl_priv *priv,
@@ -1113,14 +1113,13 @@
 			       u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
 			       u32 cmd_flags)
 {
-	unsigned long flags;
 	__le16 key_flags;
 	struct iwl_addsta_cmd sta_cmd;
 	int i;
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
 	key_flags |= STA_KEY_FLG_MAP_KEY_MSK;
@@ -1187,7 +1186,6 @@
 			   struct ieee80211_key_conf *keyconf,
 			   struct ieee80211_sta *sta)
 {
-	unsigned long flags;
 	struct iwl_addsta_cmd sta_cmd;
 	u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
 	__le16 key_flags;
@@ -1196,16 +1194,16 @@
 	if (sta_id == IWL_INVALID_STATION)
 		return -ENOENT;
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
 	if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE))
 		sta_id = IWL_INVALID_STATION;
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	if (sta_id == IWL_INVALID_STATION)
 		return 0;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	ctx->key_mapping_keys--;
 
@@ -1245,7 +1243,7 @@
 	if (sta_id == IWL_INVALID_STATION)
 		return -EINVAL;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv);
 	if (keyconf->hw_key_idx == WEP_INVALID_OFFSET)
@@ -1300,21 +1298,20 @@
 			       struct iwl_rxon_context *ctx)
 {
 	struct iwl_link_quality_cmd *link_cmd;
-	unsigned long flags;
 	u8 sta_id;
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
 	if (sta_id == IWL_INVALID_STATION) {
 		IWL_ERR(priv, "Unable to prepare broadcast station\n");
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+		spin_unlock_bh(&priv->sta_lock);
 
 		return -EINVAL;
 	}
 
 	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
 	priv->stations[sta_id].used |= IWL_STA_BCAST;
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
 	if (!link_cmd) {
@@ -1323,9 +1320,9 @@
 		return -ENOMEM;
 	}
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	priv->stations[sta_id].lq = link_cmd;
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	return 0;
 }
@@ -1339,7 +1336,6 @@
 int iwl_update_bcast_station(struct iwl_priv *priv,
 			     struct iwl_rxon_context *ctx)
 {
-	unsigned long flags;
 	struct iwl_link_quality_cmd *link_cmd;
 	u8 sta_id = ctx->bcast_sta_id;
 
@@ -1349,13 +1345,13 @@
 		return -ENOMEM;
 	}
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	if (priv->stations[sta_id].lq)
 		kfree(priv->stations[sta_id].lq);
 	else
 		IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
 	priv->stations[sta_id].lq = link_cmd;
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	return 0;
 }
@@ -1379,18 +1375,17 @@
  */
 int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
 {
-	unsigned long flags;
 	struct iwl_addsta_cmd sta_cmd;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	/* Remove "disable" flag, to enable Tx for this TID */
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
 	priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
@@ -1398,24 +1393,23 @@
 int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
 			 int tid, u16 ssn)
 {
-	unsigned long flags;
 	int sta_id;
 	struct iwl_addsta_cmd sta_cmd;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	sta_id = iwl_sta_id(sta);
 	if (sta_id == IWL_INVALID_STATION)
 		return -ENXIO;
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	priv->stations[sta_id].sta.station_flags_msk = 0;
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
 	priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
 	priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
@@ -1423,11 +1417,10 @@
 int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
 			int tid)
 {
-	unsigned long flags;
 	int sta_id;
 	struct iwl_addsta_cmd sta_cmd;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	sta_id = iwl_sta_id(sta);
 	if (sta_id == IWL_INVALID_STATION) {
@@ -1435,13 +1428,13 @@
 		return -ENXIO;
 	}
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	priv->stations[sta_id].sta.station_flags_msk = 0;
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
 	priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
@@ -1450,16 +1443,14 @@
 
 void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
 {
-	unsigned long flags;
+	struct iwl_addsta_cmd cmd = {
+		.mode = STA_CONTROL_MODIFY_MSK,
+		.station_flags = STA_FLG_PWR_SAVE_MSK,
+		.station_flags_msk = STA_FLG_PWR_SAVE_MSK,
+		.sta.sta_id = sta_id,
+		.sta.modify_mask = STA_MODIFY_SLEEP_TX_COUNT_MSK,
+		.sleep_tx_count = cpu_to_le16(cnt),
+	};
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
-	priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
-	priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
-	priv->stations[sta_id].sta.sta.modify_mask =
-					STA_MODIFY_SLEEP_TX_COUNT_MSK;
-	priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-
+	iwl_send_add_sta(priv, &cmd, CMD_ASYNC);
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
index 56d7c0e..baaf5ba 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
@@ -34,6 +34,7 @@
 
 #include <net/mac80211.h>
 
+#include "iwl-agn.h"
 #include "iwl-eeprom.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
@@ -173,7 +174,7 @@
 	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	unsigned long flags;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	if (tt->state == IWL_TI_CT_KILL) {
@@ -188,7 +189,7 @@
 		}
 		iwl_read32(trans(priv), CSR_UCODE_DRV_GP1);
 		spin_lock_irqsave(&trans(priv)->reg_lock, flags);
-		if (!iwl_grab_nic_access(trans(priv)))
+		if (likely(iwl_grab_nic_access(trans(priv))))
 			iwl_release_nic_access(trans(priv));
 		spin_unlock_irqrestore(&trans(priv)->reg_lock, flags);
 
@@ -224,7 +225,7 @@
 	struct iwl_priv *priv = (struct iwl_priv *)data;
 	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	/* temperature timer expired, ready to go into CT_KILL state */
@@ -232,7 +233,7 @@
 		IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "
 				"temperature timer expired\n");
 		tt->state = IWL_TI_CT_KILL;
-		set_bit(STATUS_CT_KILL, &priv->shrd->status);
+		set_bit(STATUS_CT_KILL, &priv->status);
 		iwl_perform_ct_kill_task(priv, true);
 	}
 }
@@ -310,24 +311,23 @@
 			tt->tt_power_mode = IWL_POWER_INDEX_5;
 			break;
 		}
-		mutex_lock(&priv->shrd->mutex);
+		mutex_lock(&priv->mutex);
 		if (old_state == IWL_TI_CT_KILL)
-			clear_bit(STATUS_CT_KILL, &priv->shrd->status);
+			clear_bit(STATUS_CT_KILL, &priv->status);
 		if (tt->state != IWL_TI_CT_KILL &&
 		    iwl_power_update_mode(priv, true)) {
 			/* TT state not updated
 			 * try again during next temperature read
 			 */
 			if (old_state == IWL_TI_CT_KILL)
-				set_bit(STATUS_CT_KILL, &priv->shrd->status);
+				set_bit(STATUS_CT_KILL, &priv->status);
 			tt->state = old_state;
 			IWL_ERR(priv, "Cannot update power mode, "
 					"TT state not updated\n");
 		} else {
 			if (tt->state == IWL_TI_CT_KILL) {
 				if (force) {
-					set_bit(STATUS_CT_KILL,
-						&priv->shrd->status);
+					set_bit(STATUS_CT_KILL, &priv->status);
 					iwl_perform_ct_kill_task(priv, true);
 				} else {
 					iwl_prepare_ct_kill_task(priv);
@@ -341,7 +341,7 @@
 			IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
 					tt->tt_power_mode);
 		}
-		mutex_unlock(&priv->shrd->mutex);
+		mutex_unlock(&priv->mutex);
 	}
 }
 
@@ -451,9 +451,9 @@
 			 * in case get disabled before */
 			iwl_set_rxon_ht(priv, &priv->current_ht_config);
 		}
-		mutex_lock(&priv->shrd->mutex);
+		mutex_lock(&priv->mutex);
 		if (old_state == IWL_TI_CT_KILL)
-			clear_bit(STATUS_CT_KILL, &priv->shrd->status);
+			clear_bit(STATUS_CT_KILL, &priv->status);
 		if (tt->state != IWL_TI_CT_KILL &&
 		    iwl_power_update_mode(priv, true)) {
 			/* TT state not updated
@@ -462,7 +462,7 @@
 			IWL_ERR(priv, "Cannot update power mode, "
 					"TT state not updated\n");
 			if (old_state == IWL_TI_CT_KILL)
-				set_bit(STATUS_CT_KILL, &priv->shrd->status);
+				set_bit(STATUS_CT_KILL, &priv->status);
 			tt->state = old_state;
 		} else {
 			IWL_DEBUG_TEMP(priv,
@@ -473,8 +473,7 @@
 				if (force) {
 					IWL_DEBUG_TEMP(priv,
 						"Enter IWL_TI_CT_KILL\n");
-					set_bit(STATUS_CT_KILL,
-						&priv->shrd->status);
+					set_bit(STATUS_CT_KILL, &priv->status);
 					iwl_perform_ct_kill_task(priv, true);
 				} else {
 					iwl_prepare_ct_kill_task(priv);
@@ -486,7 +485,7 @@
 				iwl_perform_ct_kill_task(priv, false);
 			}
 		}
-		mutex_unlock(&priv->shrd->mutex);
+		mutex_unlock(&priv->mutex);
 	}
 }
 
@@ -505,10 +504,10 @@
 	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
 	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	if (!iwl_is_ready(priv->shrd))
+	if (!iwl_is_ready(priv))
 		return;
 
 	if (tt->state != IWL_TI_CT_KILL) {
@@ -534,10 +533,10 @@
 	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
 	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	if (!iwl_is_ready(priv->shrd))
+	if (!iwl_is_ready(priv))
 		return;
 
 	/* stop ct_kill_exit_tm timer */
@@ -564,7 +563,7 @@
 
 void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
 {
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
@@ -573,7 +572,7 @@
 
 void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
 {
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
@@ -585,7 +584,7 @@
 	struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
 	s32 temp = priv->temperature; /* degrees CELSIUS except specified */
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	if (!priv->thermal_throttle.advanced_tt)
@@ -596,7 +595,7 @@
 
 void iwl_tt_handler(struct iwl_priv *priv)
 {
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 5f78567..34adedc7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -126,7 +126,7 @@
 	u8 data_retry_limit;
 	u8 rate_plcp;
 
-	if (priv->shrd->wowlan) {
+	if (priv->wowlan) {
 		rts_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
 		data_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
 	} else {
@@ -208,10 +208,9 @@
 }
 
 static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
-				      struct ieee80211_tx_info *info,
-				      struct iwl_tx_cmd *tx_cmd,
-				      struct sk_buff *skb_frag,
-				      int sta_id)
+					 struct ieee80211_tx_info *info,
+					 struct iwl_tx_cmd *tx_cmd,
+					 struct sk_buff *skb_frag)
 {
 	struct ieee80211_key_conf *keyconf = info->control.hw_key;
 
@@ -249,6 +248,35 @@
 	}
 }
 
+/**
+ * iwl_sta_id_or_broadcast - return sta_id or broadcast sta
+ * @context: the current context
+ * @sta: mac80211 station
+ *
+ * In certain circumstances mac80211 passes a station pointer
+ * that may be %NULL, for example during TX or key setup. In
+ * that case, we need to use the broadcast station, so this
+ * inline wraps that pattern.
+ */
+static int iwl_sta_id_or_broadcast(struct iwl_rxon_context *context,
+				   struct ieee80211_sta *sta)
+{
+	int sta_id;
+
+	if (!sta)
+		return context->bcast_sta_id;
+
+	sta_id = iwl_sta_id(sta);
+
+	/*
+	 * mac80211 should not be passing a partially
+	 * initialised station!
+	 */
+	WARN_ON(sta_id == IWL_INVALID_STATION);
+
+	return sta_id;
+}
+
 /*
  * start REPLY_TX command process
  */
@@ -260,19 +288,16 @@
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 	struct iwl_device_cmd *dev_cmd = NULL;
 	struct iwl_tx_cmd *tx_cmd;
-
 	__le16 fc;
 	u8 hdr_len;
 	u16 len, seq_number = 0;
 	u8 sta_id, tid = IWL_MAX_TID_COUNT;
-	unsigned long flags;
 	bool is_agg = false;
 
 	if (info->control.vif)
 		ctx = iwl_rxon_ctx_from_vif(info->control.vif);
 
-	spin_lock_irqsave(&priv->shrd->lock, flags);
-	if (iwl_is_rfkill(priv->shrd)) {
+	if (iwl_is_rfkill(priv)) {
 		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
 		goto drop_unlock_priv;
 	}
@@ -308,7 +333,7 @@
 		sta_id = ctx->bcast_sta_id;
 	else {
 		/* Find index into station table for destination station */
-		sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
+		sta_id = iwl_sta_id_or_broadcast(ctx, info->control.sta);
 		if (sta_id == IWL_INVALID_STATION) {
 			IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
 				       hdr->addr1);
@@ -342,13 +367,10 @@
 	if (info->flags & IEEE80211_TX_CTL_AMPDU)
 		is_agg = true;
 
-	/* irqs already disabled/saved above when locking priv->shrd->lock */
-	spin_lock(&priv->shrd->sta_lock);
-
-	dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC);
+	dev_cmd = kmem_cache_alloc(iwl_tx_cmd_pool, GFP_ATOMIC);
 
 	if (unlikely(!dev_cmd))
-		goto drop_unlock_sta;
+		goto drop_unlock_priv;
 
 	memset(dev_cmd, 0, sizeof(*dev_cmd));
 	tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
@@ -358,7 +380,7 @@
 	tx_cmd->len = cpu_to_le16(len);
 
 	if (info->control.hw_key)
-		iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
+		iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb);
 
 	/* TODO need this for burst mode later on */
 	iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id);
@@ -373,6 +395,8 @@
 	info->driver_data[0] = ctx;
 	info->driver_data[1] = dev_cmd;
 
+	spin_lock(&priv->sta_lock);
+
 	if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
 		u8 *qc = NULL;
 		struct iwl_tid_data *tid_data;
@@ -418,8 +442,7 @@
 	    !ieee80211_has_morefrags(fc))
 		priv->tid_data[sta_id][tid].seq_number = seq_number;
 
-	spin_unlock(&priv->shrd->sta_lock);
-	spin_unlock_irqrestore(&priv->shrd->lock, flags);
+	spin_unlock(&priv->sta_lock);
 
 	/*
 	 * Avoid atomic ops if it isn't an associated client.
@@ -435,10 +458,9 @@
 
 drop_unlock_sta:
 	if (dev_cmd)
-		kmem_cache_free(priv->tx_cmd_pool, dev_cmd);
-	spin_unlock(&priv->shrd->sta_lock);
+		kmem_cache_free(iwl_tx_cmd_pool, dev_cmd);
+	spin_unlock(&priv->sta_lock);
 drop_unlock_priv:
-	spin_unlock_irqrestore(&priv->shrd->lock, flags);
 	return -1;
 }
 
@@ -446,7 +468,6 @@
 			struct ieee80211_sta *sta, u16 tid)
 {
 	struct iwl_tid_data *tid_data;
-	unsigned long flags;
 	int sta_id;
 
 	sta_id = iwl_sta_id(sta);
@@ -456,7 +477,7 @@
 		return -ENXIO;
 	}
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 
 	tid_data = &priv->tid_data[sta_id][tid];
 
@@ -476,7 +497,7 @@
 		IWL_WARN(priv, "Stopping AGG while state not ON "
 			 "or starting for %d on %d (%d)\n", sta_id, tid,
 			 priv->tid_data[sta_id][tid].agg.state);
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+		spin_unlock_bh(&priv->sta_lock);
 		return 0;
 	}
 
@@ -490,7 +511,7 @@
 				    tid_data->next_reclaimed);
 		priv->tid_data[sta_id][tid].agg.state =
 			IWL_EMPTYING_HW_QUEUE_DELBA;
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+		spin_unlock_bh(&priv->sta_lock);
 		return 0;
 	}
 
@@ -499,14 +520,10 @@
 turn_off:
 	priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
 
-	/* do not restore/save irqs */
-	spin_unlock(&priv->shrd->sta_lock);
-	spin_lock(&priv->shrd->lock);
+	spin_unlock_bh(&priv->sta_lock);
 
 	iwl_trans_tx_agg_disable(trans(priv), sta_id, tid);
 
-	spin_unlock_irqrestore(&priv->shrd->lock, flags);
-
 	ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 
 	return 0;
@@ -516,7 +533,6 @@
 			struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
 	struct iwl_tid_data *tid_data;
-	unsigned long flags;
 	int sta_id;
 	int ret;
 
@@ -540,7 +556,7 @@
 	if (ret)
 		return ret;
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 
 	tid_data = &priv->tid_data[sta_id][tid];
 	tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number);
@@ -549,7 +565,7 @@
 
 	ret = iwl_trans_tx_agg_alloc(trans(priv), sta_id, tid);
 	if (ret) {
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+		spin_unlock_bh(&priv->sta_lock);
 		return ret;
 	}
 
@@ -566,7 +582,7 @@
 		tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
 	}
 
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	return ret;
 }
@@ -576,14 +592,13 @@
 {
 	struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
 	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-	unsigned long flags;
 	u16 ssn;
 
 	buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock_bh(&priv->sta_lock);
 	ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn;
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock_bh(&priv->sta_lock);
 
 	iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, sta_priv->sta_id, tid,
 			       buf_size, ssn);
@@ -608,8 +623,7 @@
 	sta_priv->max_agg_bufsize =
 		min(sta_priv->max_agg_bufsize, buf_size);
 
-	if (cfg(priv)->ht_params &&
-	    cfg(priv)->ht_params->use_rts_for_aggregation) {
+	if (hw_params(priv).use_rts_for_aggregation) {
 		/*
 		 * switch to RTS/CTS if it is the prefer protection
 		 * method for HT traffic
@@ -639,7 +653,7 @@
 	struct ieee80211_vif *vif;
 	u8 *addr;
 
-	lockdep_assert_held(&priv->shrd->sta_lock);
+	lockdep_assert_held(&priv->sta_lock);
 
 	addr = priv->stations[sta_id].sta.sta.addr;
 	ctx = priv->stations[sta_id].ctxid;
@@ -986,19 +1000,19 @@
 {
 	if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
 		IWL_ERR(priv, "Tx flush command to flush out all frames\n");
-		if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
 			queue_work(priv->workqueue, &priv->tx_flush);
 	}
 }
 
-int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 			       struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
 	int txq_id = SEQ_TO_QUEUE(sequence);
 	int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence);
-	struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+	struct iwlagn_tx_resp *tx_resp = (void *)pkt->data;
 	struct ieee80211_hdr *hdr;
 	u32 status = le16_to_cpu(tx_resp->status.status);
 	u16 ssn = iwlagn_get_scd_ssn(tx_resp);
@@ -1006,7 +1020,6 @@
 	int sta_id;
 	int freed;
 	struct ieee80211_tx_info *info;
-	unsigned long flags;
 	struct sk_buff_head skbs;
 	struct sk_buff *skb;
 	struct iwl_rxon_context *ctx;
@@ -1017,11 +1030,13 @@
 	sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
 		IWLAGN_TX_RES_RA_POS;
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock(&priv->sta_lock);
 
 	if (is_agg)
 		iwl_rx_reply_tx_agg(priv, tx_resp);
 
+	__skb_queue_head_init(&skbs);
+
 	if (tx_resp->frame_count == 1) {
 		u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
 		next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10);
@@ -1041,8 +1056,6 @@
 			next_reclaimed = ssn;
 		}
 
-		__skb_queue_head_init(&skbs);
-
 		if (tid != IWL_TID_NON_QOS) {
 			priv->tid_data[sta_id][tid].next_reclaimed =
 				next_reclaimed;
@@ -1051,12 +1064,13 @@
 		}
 
 		/*we can free until ssn % q.n_bd not inclusive */
-		WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
-				  ssn, status, &skbs));
+		WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid,
+					  txq_id, ssn, &skbs));
 		iwlagn_check_ratid_empty(priv, sta_id, tid);
 		freed = 0;
-		while (!skb_queue_empty(&skbs)) {
-			skb = __skb_dequeue(&skbs);
+
+		/* process frames */
+		skb_queue_walk(&skbs, skb) {
 			hdr = (struct ieee80211_hdr *)skb->data;
 
 			if (!ieee80211_is_data_qos(hdr->frame_control))
@@ -1064,7 +1078,7 @@
 
 			info = IEEE80211_SKB_CB(skb);
 			ctx = info->driver_data[0];
-			kmem_cache_free(priv->tx_cmd_pool,
+			kmem_cache_free(iwl_tx_cmd_pool,
 					(info->driver_data[1]));
 
 			memset(&info->status, 0, sizeof(info->status));
@@ -1072,9 +1086,11 @@
 			if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
 			    iwl_is_associated_ctx(ctx) && ctx->vif &&
 			    ctx->vif->type == NL80211_IFTYPE_STATION) {
-				ctx->last_tx_rejected = true;
-				iwl_trans_stop_queue(trans(priv), txq_id,
-					"Tx on passive channel");
+				/* block and stop all queues */
+				priv->passive_no_rx = true;
+				IWL_DEBUG_TX_QUEUES(priv, "stop all queues: "
+						    "passive channel");
+				ieee80211_stop_queues(priv->hw);
 
 				IWL_DEBUG_TX_REPLY(priv,
 					   "TXQ %d status %s (0x%08x) "
@@ -1098,8 +1114,6 @@
 			if (!is_agg)
 				iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
 
-			ieee80211_tx_status_irqsafe(priv->hw, skb);
-
 			freed++;
 		}
 
@@ -1107,7 +1121,13 @@
 	}
 
 	iwl_check_abort_status(priv, tx_resp->frame_count, status);
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock(&priv->sta_lock);
+
+	while (!skb_queue_empty(&skbs)) {
+		skb = __skb_dequeue(&skbs);
+		ieee80211_tx_status(priv->hw, skb);
+	}
+
 	return 0;
 }
 
@@ -1118,17 +1138,16 @@
  * of frames sent via aggregation.
  */
 int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
-				   struct iwl_rx_mem_buffer *rxb,
+				   struct iwl_rx_cmd_buffer *rxb,
 				   struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
+	struct iwl_compressed_ba_resp *ba_resp = (void *)pkt->data;
 	struct iwl_ht_agg *agg;
 	struct sk_buff_head reclaimed_skbs;
 	struct ieee80211_tx_info *info;
 	struct ieee80211_hdr *hdr;
 	struct sk_buff *skb;
-	unsigned long flags;
 	int sta_id;
 	int tid;
 	int freed;
@@ -1140,7 +1159,7 @@
 	 * (in Tx queue's circular buffer) of first TFD/frame in window */
 	u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
 
-	if (scd_flow >= hw_params(priv).max_txq_num) {
+	if (scd_flow >= cfg(priv)->base_params->num_of_queues) {
 		IWL_ERR(priv,
 			"BUG_ON scd_flow is bigger than number of queues\n");
 		return 0;
@@ -1150,12 +1169,12 @@
 	tid = ba_resp->tid;
 	agg = &priv->tid_data[sta_id][tid].agg;
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+	spin_lock(&priv->sta_lock);
 
 	if (unlikely(!agg->wait_for_ba)) {
 		if (unlikely(ba_resp->bitmap))
 			IWL_ERR(priv, "Received BA when not expected\n");
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+		spin_unlock(&priv->sta_lock);
 		return 0;
 	}
 
@@ -1165,8 +1184,8 @@
 	 * block-ack window (we assume that they've been successfully
 	 * transmitted ... if not, it's too late anyway). */
 	if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow,
-			      ba_resp_scd_ssn, 0, &reclaimed_skbs)) {
-		spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+			      ba_resp_scd_ssn, &reclaimed_skbs)) {
+		spin_unlock(&priv->sta_lock);
 		return 0;
 	}
 
@@ -1202,9 +1221,8 @@
 
 	iwlagn_check_ratid_empty(priv, sta_id, tid);
 	freed = 0;
-	while (!skb_queue_empty(&reclaimed_skbs)) {
 
-		skb = __skb_dequeue(&reclaimed_skbs);
+	skb_queue_walk(&reclaimed_skbs, skb) {
 		hdr = (struct ieee80211_hdr *)skb->data;
 
 		if (ieee80211_is_data_qos(hdr->frame_control))
@@ -1213,7 +1231,7 @@
 			WARN_ON_ONCE(1);
 
 		info = IEEE80211_SKB_CB(skb);
-		kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
+		kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
 
 		if (freed == 1) {
 			/* this is the first skb we deliver in this batch */
@@ -1227,10 +1245,14 @@
 			iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags,
 						    info);
 		}
-
-		ieee80211_tx_status_irqsafe(priv->hw, skb);
 	}
 
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+	spin_unlock(&priv->sta_lock);
+
+	while (!skb_queue_empty(&reclaimed_skbs)) {
+		skb = __skb_dequeue(&reclaimed_skbs);
+		ieee80211_tx_status(priv->hw, skb);
+	}
+
 	return 0;
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index e0fef9f..f1226dbf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -41,9 +41,7 @@
 
 #include <asm/div64.h>
 
-#include "iwl-ucode.h"
 #include "iwl-eeprom.h"
-#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
@@ -134,7 +132,7 @@
 	 * beacon contents.
 	 */
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	if (!priv->beacon_ctx) {
 		IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
@@ -199,7 +197,7 @@
 	cmd.data[1] = priv->beacon_skb->data;
 	cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
 
-	return iwl_trans_send_cmd(trans(priv), &cmd);
+	return iwl_dvm_send_cmd(priv, &cmd);
 }
 
 static void iwl_bg_beacon_update(struct work_struct *work)
@@ -208,7 +206,7 @@
 		container_of(work, struct iwl_priv, beacon_update);
 	struct sk_buff *beacon;
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	if (!priv->beacon_ctx) {
 		IWL_ERR(priv, "updating beacon w/o beacon context!\n");
 		goto out;
@@ -238,7 +236,7 @@
 
 	iwlagn_send_beacon_cmd(priv);
  out:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 static void iwl_bg_bt_runtime_config(struct work_struct *work)
@@ -246,11 +244,11 @@
 	struct iwl_priv *priv =
 		container_of(work, struct iwl_priv, bt_runtime_config);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	/* dont send host command if rf-kill is on */
-	if (!iwl_is_ready_rf(priv->shrd))
+	if (!iwl_is_ready_rf(priv))
 		return;
 	iwlagn_send_advance_bt_config(priv);
 }
@@ -261,13 +259,13 @@
 		container_of(work, struct iwl_priv, bt_full_concurrency);
 	struct iwl_rxon_context *ctx;
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		goto out;
 
 	/* dont send host command if rf-kill is on */
-	if (!iwl_is_ready_rf(priv->shrd))
+	if (!iwl_is_ready_rf(priv))
 		goto out;
 
 	IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
@@ -285,7 +283,7 @@
 
 	iwlagn_send_advance_bt_config(priv);
 out:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 /**
@@ -302,11 +300,11 @@
 {
 	struct iwl_priv *priv = (struct iwl_priv *)data;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	/* dont send host command if rf-kill is on */
-	if (!iwl_is_ready_rf(priv->shrd))
+	if (!iwl_is_ready_rf(priv))
 		return;
 
 	iwl_send_statistics_request(priv, CMD_ASYNC, false);
@@ -329,14 +327,13 @@
 
 	/* Make sure device is powered up for SRAM reads */
 	spin_lock_irqsave(&trans(priv)->reg_lock, reg_flags);
-	if (iwl_grab_nic_access(trans(priv))) {
+	if (unlikely(!iwl_grab_nic_access(trans(priv)))) {
 		spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags);
 		return;
 	}
 
 	/* Set starting address; reads will auto-increment */
 	iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, ptr);
-	rmb();
 
 	/*
 	 * Refuse to read more than would have fit into the log from
@@ -355,11 +352,12 @@
 		ev = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
 		time = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
 		if (mode == 0) {
-			trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev);
+			trace_iwlwifi_dev_ucode_cont_event(
+					trans(priv)->dev, 0, time, ev);
 		} else {
 			data = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
-			trace_iwlwifi_dev_ucode_cont_event(priv, time,
-							   data, ev);
+			trace_iwlwifi_dev_ucode_cont_event(
+					trans(priv)->dev, time, data, ev);
 		}
 	}
 	/* Allow device to power down */
@@ -424,7 +422,7 @@
 		else
 			priv->event_log.wraps_once_count++;
 
-		trace_iwlwifi_dev_ucode_wrap_event(priv,
+		trace_iwlwifi_dev_ucode_wrap_event(trans(priv)->dev,
 				num_wraps - priv->event_log.num_wraps,
 				next_entry, priv->event_log.next_entry);
 
@@ -463,7 +461,7 @@
 {
 	struct iwl_priv *priv = (struct iwl_priv *)data;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	if (priv->event_log.ucode_trace) {
@@ -479,18 +477,18 @@
 	struct iwl_priv *priv =
 		container_of(work, struct iwl_priv, tx_flush);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	/* do nothing if rf-kill is on */
-	if (!iwl_is_ready_rf(priv->shrd))
+	if (!iwl_is_ready_rf(priv))
 		return;
 
 	IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
 	iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
 }
 
-void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
+static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
 {
 	int i;
 
@@ -552,13 +550,11 @@
 {
 	struct iwl_ct_kill_config cmd;
 	struct iwl_ct_kill_throttling_config adv_cmd;
-	unsigned long flags;
 	int ret = 0;
 
-	spin_lock_irqsave(&priv->shrd->lock, flags);
 	iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR,
 		    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-	spin_unlock_irqrestore(&priv->shrd->lock, flags);
+
 	priv->thermal_throttle.ct_kill_toggle = false;
 
 	if (cfg(priv)->base_params->support_ct_kill_exit) {
@@ -567,7 +563,7 @@
 		adv_cmd.critical_temperature_exit =
 			cpu_to_le32(hw_params(priv).ct_kill_exit_threshold);
 
-		ret = iwl_trans_send_cmd_pdu(trans(priv),
+		ret = iwl_dvm_send_cmd_pdu(priv,
 				       REPLY_CT_KILL_CONFIG_CMD,
 				       CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
 		if (ret)
@@ -582,7 +578,7 @@
 		cmd.critical_temperature_R =
 			cpu_to_le32(hw_params(priv).ct_kill_threshold);
 
-		ret = iwl_trans_send_cmd_pdu(trans(priv),
+		ret = iwl_dvm_send_cmd_pdu(priv,
 				       REPLY_CT_KILL_CONFIG_CMD,
 				       CMD_SYNC, sizeof(cmd), &cmd);
 		if (ret)
@@ -608,7 +604,7 @@
 	calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_RT_CFG_ALL;
 	calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
 
-	return iwl_trans_send_cmd(trans(priv), &cmd);
+	return iwl_dvm_send_cmd(priv, &cmd);
 }
 
 
@@ -618,9 +614,9 @@
 	  .valid = cpu_to_le32(valid_tx_ant),
 	};
 
-	if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) > 1) {
+	if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) {
 		IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
-		return iwl_trans_send_cmd_pdu(trans(priv),
+		return iwl_dvm_send_cmd_pdu(priv,
 					TX_ANT_CONFIGURATION_CMD,
 					CMD_SYNC,
 					sizeof(struct iwl_tx_ant_config_cmd),
@@ -644,12 +640,12 @@
 	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
 
 	/* After the ALIVE response, we can send host commands to the uCode */
-	set_bit(STATUS_ALIVE, &priv->shrd->status);
+	set_bit(STATUS_ALIVE, &priv->status);
 
 	/* Enable watchdog to monitor the driver tx queues */
 	iwl_setup_watchdog(priv);
 
-	if (iwl_is_rfkill(priv->shrd))
+	if (iwl_is_rfkill(priv))
 		return -ERFKILL;
 
 	if (priv->event_log.ucode_trace) {
@@ -673,14 +669,14 @@
 		priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
 		priv->cur_rssi_ctx = NULL;
 
-		iwl_send_prio_tbl(trans(priv));
+		iwl_send_prio_tbl(priv);
 
 		/* FIXME: w/a to force change uCode BT state machine */
-		ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN,
+		ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
 					 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
 		if (ret)
 			return ret;
-		ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_CLOSE,
+		ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
 					 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
 		if (ret)
 			return ret;
@@ -701,9 +697,9 @@
 	priv->active_rate = IWL_RATES_MASK;
 
 	/* Configure Tx antenna selection based on H/W config */
-	iwlagn_send_tx_ant_config(priv, cfg(priv)->valid_tx_ant);
+	iwlagn_send_tx_ant_config(priv, hw_params(priv).valid_tx_ant);
 
-	if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) {
+	if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
 		struct iwl_rxon_cmd *active_rxon =
 				(struct iwl_rxon_cmd *)&ctx->active;
 		/* apply any changes in staging */
@@ -718,12 +714,12 @@
 		iwlagn_set_rxon_chain(priv, ctx);
 	}
 
-	if (!priv->shrd->wowlan) {
+	if (!priv->wowlan) {
 		/* WoWLAN ucode will not reply in the same way, skip it */
 		iwl_reset_run_time_calib(priv);
 	}
 
-	set_bit(STATUS_READY, &priv->shrd->status);
+	set_bit(STATUS_READY, &priv->status);
 
 	/* Configure the adapter for unassociated operation */
 	ret = iwlagn_commit_rxon(priv, ctx);
@@ -738,13 +734,47 @@
 	return iwl_power_update_mode(priv, true);
 }
 
+/**
+ * iwl_clear_driver_stations - clear knowledge of all stations from driver
+ * @priv: iwl priv struct
+ *
+ * This is called during iwl_down() to make sure that in the case
+ * we're coming there from a hardware restart mac80211 will be
+ * able to reconfigure stations -- if we're getting there in the
+ * normal down flow then the stations will already be cleared.
+ */
+static void iwl_clear_driver_stations(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+
+	spin_lock_bh(&priv->sta_lock);
+	memset(priv->stations, 0, sizeof(priv->stations));
+	priv->num_stations = 0;
+
+	priv->ucode_key_table = 0;
+
+	for_each_context(priv, ctx) {
+		/*
+		 * Remove all key information that is not stored as part
+		 * of station information since mac80211 may not have had
+		 * a chance to remove all the keys. When device is
+		 * reconfigured by mac80211 after an error all keys will
+		 * be reconfigured.
+		 */
+		memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
+		ctx->key_mapping_keys = 0;
+	}
+
+	spin_unlock_bh(&priv->sta_lock);
+}
+
 void iwl_down(struct iwl_priv *priv)
 {
 	int exit_pending;
 
 	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	iwl_scan_cancel_timeout(priv, 200);
 
@@ -756,7 +786,7 @@
 	ieee80211_remain_on_channel_expired(priv->hw);
 
 	exit_pending =
-		test_and_set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
+		test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
 
 	/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
 	 * to prevent rearm timer */
@@ -781,23 +811,24 @@
 	/* Wipe out the EXIT_PENDING status bit if we are not actually
 	 * exiting the module */
 	if (!exit_pending)
-		clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
+		clear_bit(STATUS_EXIT_PENDING, &priv->status);
 
 	if (priv->mac80211_registered)
 		ieee80211_stop_queues(priv->hw);
 
+	priv->ucode_loaded = false;
 	iwl_trans_stop_device(trans(priv));
 
 	/* Clear out all status bits but a few that are stable across reset */
-	priv->shrd->status &=
-			test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) <<
+	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 				STATUS_RF_KILL_HW |
-			test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) <<
+			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 				STATUS_GEO_CONFIGURED |
-			test_bit(STATUS_FW_ERROR, &priv->shrd->status) <<
-				STATUS_FW_ERROR |
-			test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) <<
+			test_bit(STATUS_EXIT_PENDING, &priv->status) <<
 				STATUS_EXIT_PENDING;
+	priv->shrd->status &=
+			test_bit(STATUS_FW_ERROR, &priv->shrd->status) <<
+				STATUS_FW_ERROR;
 
 	dev_kfree_skb(priv->beacon_skb);
 	priv->beacon_skb = NULL;
@@ -814,11 +845,11 @@
 	struct iwl_priv *priv = container_of(work, struct iwl_priv,
 			run_time_calib_work);
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) ||
-	    test_bit(STATUS_SCANNING, &priv->shrd->status)) {
-		mutex_unlock(&priv->shrd->mutex);
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+	    test_bit(STATUS_SCANNING, &priv->status)) {
+		mutex_unlock(&priv->mutex);
 		return;
 	}
 
@@ -827,7 +858,7 @@
 		iwl_sensitivity_calibration(priv);
 	}
 
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 void iwlagn_prepare_restart(struct iwl_priv *priv)
@@ -839,7 +870,7 @@
 	u8 bt_status;
 	bool bt_is_sco;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	for_each_context(priv, ctx)
 		ctx->vif = NULL;
@@ -873,13 +904,13 @@
 {
 	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) {
-		mutex_lock(&priv->shrd->mutex);
+		mutex_lock(&priv->mutex);
 		iwlagn_prepare_restart(priv);
-		mutex_unlock(&priv->shrd->mutex);
+		mutex_unlock(&priv->mutex);
 		iwl_cancel_deferred_work(priv);
 		ieee80211_restart_hw(priv->hw);
 	} else {
@@ -894,7 +925,7 @@
 {
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	if (!priv->hw_roc_setup)
 		return;
@@ -917,9 +948,9 @@
 	struct iwl_priv *priv = container_of(work, struct iwl_priv,
 					     hw_roc_disable_work.work);
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	iwlagn_disable_roc(priv);
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 /*****************************************************************************
@@ -932,8 +963,6 @@
 {
 	priv->workqueue = create_singlethread_workqueue(DRV_NAME);
 
-	init_waitqueue_head(&priv->shrd->wait_command_queue);
-
 	INIT_WORK(&priv->restart, iwl_bg_restart);
 	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
 	INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
@@ -945,8 +974,8 @@
 
 	iwl_setup_scan_deferred_work(priv);
 
-	if (cfg(priv)->lib->bt_setup_deferred_work)
-		cfg(priv)->lib->bt_setup_deferred_work(priv);
+	if (cfg(priv)->bt_params)
+		iwlagn_bt_setup_deferred_work(priv);
 
 	init_timer(&priv->statistics_periodic);
 	priv->statistics_periodic.data = (unsigned long)priv;
@@ -963,8 +992,8 @@
 
 void iwl_cancel_deferred_work(struct iwl_priv *priv)
 {
-	if (cfg(priv)->lib->cancel_deferred_work)
-		cfg(priv)->lib->cancel_deferred_work(priv);
+	if (cfg(priv)->bt_params)
+		iwlagn_bt_cancel_deferred_work(priv);
 
 	cancel_work_sync(&priv->run_time_calib_work);
 	cancel_work_sync(&priv->beacon_update);
@@ -979,8 +1008,7 @@
 	del_timer_sync(&priv->ucode_trace);
 }
 
-static void iwl_init_hw_rates(struct iwl_priv *priv,
-			      struct ieee80211_rate *rates)
+static void iwl_init_hw_rates(struct ieee80211_rate *rates)
 {
 	int i;
 
@@ -1004,21 +1032,26 @@
 {
 	int ret;
 
-	spin_lock_init(&priv->shrd->sta_lock);
+	spin_lock_init(&priv->sta_lock);
 
-	mutex_init(&priv->shrd->mutex);
+	mutex_init(&priv->mutex);
 
-	INIT_LIST_HEAD(&trans(priv)->calib_results);
+	INIT_LIST_HEAD(&priv->calib_results);
 
 	priv->ieee_channels = NULL;
 	priv->ieee_rates = NULL;
 	priv->band = IEEE80211_BAND_2GHZ;
 
+	priv->plcp_delta_threshold =
+		cfg(priv)->base_params->plcp_delta_threshold;
+
 	priv->iw_mode = NL80211_IFTYPE_STATION;
 	priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
 	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
 	priv->agg_tids_count = 0;
 
+	priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
+
 	/* initialize force reset */
 	priv->force_reset[IWL_RF_RESET].reset_duration =
 		IWL_DELAY_NEXT_FORCE_RF_RESET;
@@ -1054,7 +1087,7 @@
 		IWL_ERR(priv, "initializing geos failed: %d\n", ret);
 		goto err_free_channel_map;
 	}
-	iwl_init_hw_rates(priv, priv->ieee_rates);
+	iwl_init_hw_rates(priv->ieee_rates);
 
 	return 0;
 
@@ -1068,11 +1101,10 @@
 {
 	iwl_free_geos(priv);
 	iwl_free_channel_map(priv);
-	if (priv->tx_cmd_pool)
-		kmem_cache_destroy(priv->tx_cmd_pool);
 	kfree(priv->scan_cmd);
 	kfree(priv->beacon_cmd);
 	kfree(rcu_dereference_raw(priv->noa_data));
+	iwl_calib_free_results(priv);
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 	kfree(priv->wowlan_sram);
 #endif
@@ -1084,6 +1116,10 @@
 
 static void iwl_set_hw_params(struct iwl_priv *priv)
 {
+	if (cfg(priv)->ht_params)
+		hw_params(priv).use_rts_for_aggregation =
+			cfg(priv)->ht_params->use_rts_for_aggregation;
+
 	if (iwlagn_mod_params.amsdu_size_8K)
 		hw_params(priv).rx_page_order =
 			get_order(IWL_RX_BUF_SIZE_8K);
@@ -1092,13 +1128,10 @@
 			get_order(IWL_RX_BUF_SIZE_4K);
 
 	if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
-		cfg(priv)->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
+		hw_params(priv).sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
 
 	hw_params(priv).num_ampdu_queues =
 		cfg(priv)->base_params->num_of_ampdu_queues;
-	hw_params(priv).shadow_reg_enable =
-		cfg(priv)->base_params->shadow_reg_enable;
-	hw_params(priv).sku = cfg(priv)->sku;
 	hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
 
 	/* Device-specific setup */
@@ -1142,15 +1175,24 @@
 #endif
 }
 
-static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
+static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
+						 const struct iwl_fw *fw)
 {
-	struct iwl_fw *fw = &nic(trans)->fw;
 	int err = 0;
 	struct iwl_priv *priv;
 	struct ieee80211_hw *hw;
 	struct iwl_op_mode *op_mode;
 	u16 num_mac;
 	u32 ucode_flags;
+	struct iwl_trans_config trans_cfg;
+	static const u8 no_reclaim_cmds[] = {
+		REPLY_RX_PHY_CMD,
+		REPLY_RX,
+		REPLY_RX_MPDU_CMD,
+		REPLY_COMPRESSED_BA,
+		STATISTICS_NOTIFICATION,
+		REPLY_TX,
+	};
 
 	/************************
 	 * 1. Allocating HW data
@@ -1167,9 +1209,34 @@
 	op_mode->ops = &iwl_dvm_ops;
 	priv = IWL_OP_MODE_GET_DVM(op_mode);
 	priv->shrd = trans->shrd;
-	priv->shrd->priv = priv;
+	priv->fw = fw;
+	/* TODO: remove fw from shared data later */
+	priv->shrd->fw = fw;
 
-	iwl_trans_configure(trans(priv), op_mode);
+	/*
+	 * Populate the state variables that the transport layer needs
+	 * to know about.
+	 */
+	trans_cfg.op_mode = op_mode;
+	trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
+	trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
+
+	ucode_flags = fw->ucode_capa.flags;
+
+#ifndef CONFIG_IWLWIFI_P2P
+	ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+#endif
+
+	if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
+		priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
+		trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
+	} else {
+		priv->sta_key_max_num = STA_KEY_MAX_NUM;
+		trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+	}
+
+	/* Configure transport layer */
+	iwl_trans_configure(trans(priv), &trans_cfg);
 
 	/* At this point both hw and priv are allocated. */
 
@@ -1198,10 +1265,10 @@
 	 * we should init now
 	 */
 	spin_lock_init(&trans(priv)->reg_lock);
-	spin_lock_init(&priv->shrd->lock);
+	spin_lock_init(&priv->statistics.lock);
 
 	/***********************
-	 * 3. Read REV register
+	 * 2. Read REV register
 	 ***********************/
 	IWL_INFO(priv, "Detected %s, REV=0x%X\n",
 		cfg(priv)->name, trans(priv)->hw_rev);
@@ -1211,9 +1278,8 @@
 		goto out_free_traffic_mem;
 
 	/*****************
-	 * 4. Read EEPROM
+	 * 3. Read EEPROM
 	 *****************/
-	/* Read the EEPROM */
 	err = iwl_eeprom_init(trans(priv), trans(priv)->hw_rev);
 	/* Reset chip to save power until we load uCode during "up". */
 	iwl_trans_stop_hw(trans(priv));
@@ -1225,7 +1291,7 @@
 	if (err)
 		goto out_free_eeprom;
 
-	err = iwl_eeprom_check_sku(priv);
+	err = iwl_eeprom_init_hw_params(priv);
 	if (err)
 		goto out_free_eeprom;
 
@@ -1243,28 +1309,27 @@
 	}
 
 	/************************
-	 * 5. Setup HW constants
+	 * 4. Setup HW constants
 	 ************************/
 	iwl_set_hw_params(priv);
 
-	ucode_flags = fw->ucode_capa.flags;
-
-#ifndef CONFIG_IWLWIFI_P2P
-	ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
-#endif
-	if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE))
+	if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
+		IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN");
 		ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
-
-	/*
-	 * if not PAN, then don't support P2P -- might be a uCode
-	 * packaging bug or due to the eeprom check above
-	 */
-	if (!(ucode_flags & IWL_UCODE_TLV_FLAGS_PAN))
+		/*
+		 * if not PAN, then don't support P2P -- might be a uCode
+		 * packaging bug or due to the eeprom check above
+		 */
 		ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
+		priv->sta_key_max_num = STA_KEY_MAX_NUM;
+		trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
 
+		/* Configure transport layer again*/
+		iwl_trans_configure(trans(priv), &trans_cfg);
+	}
 
 	/*******************
-	 * 6. Setup priv
+	 * 5. Setup priv
 	 *******************/
 
 	err = iwl_init_drv(priv);
@@ -1273,7 +1338,7 @@
 	/* At this point both hw and priv are initialized. */
 
 	/********************
-	 * 7. Setup services
+	 * 6. Setup services
 	 ********************/
 	iwl_setup_deferred_work(priv);
 	iwl_setup_rx_handlers(priv);
@@ -1289,14 +1354,6 @@
 	priv->new_scan_threshold_behaviour =
 		!!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
 
-	if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
-		priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
-		priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
-	} else {
-		priv->sta_key_max_num = STA_KEY_MAX_NUM;
-		priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
-	}
-
 	priv->phy_calib_chain_noise_reset_cmd =
 		fw->ucode_capa.standard_phy_calibration_size;
 	priv->phy_calib_chain_noise_gain_cmd =
@@ -1308,7 +1365,7 @@
 	/**************************************************
 	 * This is still part of probe() in a sense...
 	 *
-	 * 9. Setup and register with mac80211 and debugfs
+	 * 7. Setup and register with mac80211 and debugfs
 	 **************************************************/
 	err = iwlagn_mac_setup_register(priv, &fw->ucode_capa);
 	if (err)
@@ -1340,28 +1397,19 @@
 {
 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
 
-	wait_for_completion(&nic(priv)->request_firmware_complete);
-
 	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
 	iwl_dbgfs_unregister(priv);
 
-	/* ieee80211_unregister_hw call wil cause iwlagn_mac_stop to
-	 * to be called and iwl_down since we are removing the device
-	 * we need to set STATUS_EXIT_PENDING bit.
-	 */
-	set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
-
 	iwl_testmode_cleanup(priv);
 	iwlagn_mac_unregister(priv);
 
 	iwl_tt_exit(priv);
 
 	/*This will stop the queues, move the device to low power state */
+	priv->ucode_loaded = false;
 	iwl_trans_stop_device(trans(priv));
 
-	iwl_dealloc_ucode(nic(priv));
-
 	iwl_eeprom_free(priv->shrd);
 
 	/*netif_stop_queue(dev); */
@@ -1381,6 +1429,60 @@
 	ieee80211_free_hw(priv->hw);
 }
 
+static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
+{
+	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+	if (!iwl_check_for_ct_kill(priv)) {
+		IWL_ERR(priv, "Restarting adapter queue is full\n");
+		iwl_nic_error(op_mode);
+	}
+}
+
+static void iwl_nic_config(struct iwl_op_mode *op_mode)
+{
+	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+	cfg(priv)->lib->nic_config(priv);
+}
+
+static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
+{
+	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+	set_bit(ac, &priv->transport_queue_stop);
+	ieee80211_stop_queue(priv->hw, ac);
+}
+
+static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
+{
+	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+	clear_bit(ac, &priv->transport_queue_stop);
+
+	if (!priv->passive_no_rx)
+		ieee80211_wake_queue(priv->hw, ac);
+}
+
+void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
+{
+	int ac;
+
+	if (!priv->passive_no_rx)
+		return;
+
+	for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) {
+		if (!test_bit(ac, &priv->transport_queue_stop)) {
+			IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d");
+			ieee80211_wake_queue(priv->hw, ac);
+		} else {
+			IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d");
+		}
+	}
+
+	priv->passive_no_rx = false;
+}
+
 const struct iwl_op_mode_ops iwl_dvm_ops = {
 	.start = iwl_op_mode_dvm_start,
 	.stop = iwl_op_mode_dvm_stop,
@@ -1390,6 +1492,8 @@
 	.hw_rf_kill = iwl_set_hw_rfkill_state,
 	.free_skb = iwl_free_skb,
 	.nic_error = iwl_nic_error,
+	.cmd_queue_full = iwl_cmd_queue_full,
+	.nic_config = iwl_nic_config,
 };
 
 /*****************************************************************************
@@ -1397,6 +1501,9 @@
  * driver and module entry point
  *
  *****************************************************************************/
+
+struct kmem_cache *iwl_tx_cmd_pool;
+
 static int __init iwl_init(void)
 {
 
@@ -1404,20 +1511,27 @@
 	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
 	pr_info(DRV_COPYRIGHT "\n");
 
+	iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd",
+					    sizeof(struct iwl_device_cmd),
+					    sizeof(void *), 0, NULL);
+	if (!iwl_tx_cmd_pool)
+		return -ENOMEM;
+
 	ret = iwlagn_rate_control_register();
 	if (ret) {
 		pr_err("Unable to register rate control algorithm: %d\n", ret);
-		return ret;
+		goto error_rc_register;
 	}
 
 	ret = iwl_pci_register_driver();
-
 	if (ret)
-		goto error_register;
+		goto error_pci_register;
 	return ret;
 
-error_register:
+error_pci_register:
 	iwlagn_rate_control_unregister();
+error_rc_register:
+	kmem_cache_destroy(iwl_tx_cmd_pool);
 	return ret;
 }
 
@@ -1425,6 +1539,7 @@
 {
 	iwl_pci_unregister_driver();
 	iwlagn_rate_control_unregister();
+	kmem_cache_destroy(iwl_tx_cmd_pool);
 }
 
 module_exit(iwl_exit);
@@ -1438,8 +1553,6 @@
 
 module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO);
 MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
-module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO);
-MODULE_PARM_DESC(queues_num, "number of hw queues.");
 module_param_named(11n_disable, iwlagn_mod_params.disable_11n, uint, S_IRUGO);
 MODULE_PARM_DESC(11n_disable,
 	"disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index cb484e2..3780a03 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -82,20 +82,26 @@
 void iwlagn_prepare_restart(struct iwl_priv *priv);
 void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb);
 int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode,
-				 struct iwl_rx_mem_buffer *rxb,
+				 struct iwl_rx_cmd_buffer *rxb,
 				 struct iwl_device_cmd *cmd);
-void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
-void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
 void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state);
-void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
 void iwl_nic_error(struct iwl_op_mode *op_mode);
 
+bool iwl_check_for_ct_kill(struct iwl_priv *priv);
+
+void iwlagn_lift_passive_no_rx(struct iwl_priv *priv);
+
 /* MAC80211 */
 struct ieee80211_hw *iwl_alloc_all(void);
 int iwlagn_mac_setup_register(struct iwl_priv *priv,
-			      struct iwl_ucode_capabilities *capa);
+			      const struct iwl_ucode_capabilities *capa);
 void iwlagn_mac_unregister(struct iwl_priv *priv);
 
+/* commands */
+int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id,
+			 u32 flags, u16 len, const void *data);
+
 /* RXON */
 int iwlagn_set_pan_params(struct iwl_priv *priv);
 int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@@ -110,9 +116,18 @@
 
 /* uCode */
 int iwlagn_rx_calib_result(struct iwl_priv *priv,
-			    struct iwl_rx_mem_buffer *rxb,
+			    struct iwl_rx_cmd_buffer *rxb,
 			    struct iwl_device_cmd *cmd);
-void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags);
+int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
+void iwl_send_prio_tbl(struct iwl_priv *priv);
+int iwl_init_alive_start(struct iwl_priv *priv);
+int iwl_run_init_ucode(struct iwl_priv *priv);
+int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
+			      enum iwl_ucode_type ucode_type);
+int iwl_send_calib_results(struct iwl_priv *priv);
+int iwl_calib_set(struct iwl_priv *priv,
+		  const struct iwl_calib_hdr *cmd, int len);
+void iwl_calib_free_results(struct iwl_priv *priv);
 
 /* lib */
 int iwlagn_send_tx_power(struct iwl_priv *priv);
@@ -124,8 +139,7 @@
 #ifdef CONFIG_PM_SLEEP
 int iwlagn_send_patterns(struct iwl_priv *priv,
 			 struct cfg80211_wowlan *wowlan);
-int iwlagn_suspend(struct iwl_priv *priv,
-		   struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
+int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan);
 #endif
 
 /* rx */
@@ -142,9 +156,9 @@
 int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta, u16 tid);
 int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
-				   struct iwl_rx_mem_buffer *rxb,
+				   struct iwl_rx_cmd_buffer *rxb,
 				   struct iwl_device_cmd *cmd);
-int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 			       struct iwl_device_cmd *cmd);
 
 static inline u32 iwl_tx_status_to_mac80211(u32 status)
@@ -179,7 +193,7 @@
 /* bt coex */
 void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
 int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
-				  struct iwl_rx_mem_buffer *rxb,
+				  struct iwl_rx_cmd_buffer *rxb,
 				  struct iwl_device_cmd *cmd);
 void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
 void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
@@ -220,6 +234,8 @@
 			   struct ieee80211_sta *sta, u8 *sta_id_r);
 int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
 		       const u8 *addr);
+void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
+			    const u8 *addr);
 u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 		    const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
 
@@ -227,46 +243,12 @@
 		     u8 sta_id, struct iwl_link_quality_cmd *link_cmd);
 int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 		    struct iwl_link_quality_cmd *lq, u8 flags, bool init);
-void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 			       struct iwl_device_cmd *cmd);
+int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+		      struct ieee80211_sta *sta);
 
 
-/**
- * iwl_clear_driver_stations - clear knowledge of all stations from driver
- * @priv: iwl priv struct
- *
- * This is called during iwl_down() to make sure that in the case
- * we're coming there from a hardware restart mac80211 will be
- * able to reconfigure stations -- if we're getting there in the
- * normal down flow then the stations will already be cleared.
- */
-static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
-{
-	unsigned long flags;
-	struct iwl_rxon_context *ctx;
-
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
-	memset(priv->stations, 0, sizeof(priv->stations));
-	priv->num_stations = 0;
-
-	priv->ucode_key_table = 0;
-
-	for_each_context(priv, ctx) {
-		/*
-		 * Remove all key information that is not stored as part
-		 * of station information since mac80211 may not have had
-		 * a chance to remove all the keys. When device is
-		 * reconfigured by mac80211 after an error all keys will
-		 * be reconfigured.
-		 */
-		memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
-		ctx->key_mapping_keys = 0;
-	}
-
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-}
-
 static inline int iwl_sta_id(struct ieee80211_sta *sta)
 {
 	if (WARN_ON(!sta))
@@ -275,37 +257,6 @@
 	return ((struct iwl_station_priv *)sta->drv_priv)->sta_id;
 }
 
-/**
- * iwl_sta_id_or_broadcast - return sta_id or broadcast sta
- * @priv: iwl priv
- * @context: the current context
- * @sta: mac80211 station
- *
- * In certain circumstances mac80211 passes a station pointer
- * that may be %NULL, for example during TX or key setup. In
- * that case, we need to use the broadcast station, so this
- * inline wraps that pattern.
- */
-static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv,
-					  struct iwl_rxon_context *context,
-					  struct ieee80211_sta *sta)
-{
-	int sta_id;
-
-	if (!sta)
-		return context->bcast_sta_id;
-
-	sta_id = iwl_sta_id(sta);
-
-	/*
-	 * mac80211 should not be passing a partially
-	 * initialised station!
-	 */
-	WARN_ON(sta_id == IWL_INVALID_STATION);
-
-	return sta_id;
-}
-
 int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
 			       struct iwl_rxon_context *ctx);
 int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
@@ -355,7 +306,6 @@
 }
 
 /* eeprom */
-void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
 void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac);
 
 extern int iwl_alive_start(struct iwl_priv *priv);
@@ -402,4 +352,58 @@
 }
 #endif
 
+/* status checks */
+
+static inline int iwl_is_ready(struct iwl_priv *priv)
+{
+	/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
+	 * set but EXIT_PENDING is not */
+	return test_bit(STATUS_READY, &priv->status) &&
+	       test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
+	       !test_bit(STATUS_EXIT_PENDING, &priv->status);
+}
+
+static inline int iwl_is_alive(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_ALIVE, &priv->status);
+}
+
+static inline int iwl_is_rfkill(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_RF_KILL_HW, &priv->status);
+}
+
+static inline int iwl_is_ctkill(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_CT_KILL, &priv->status);
+}
+
+static inline int iwl_is_ready_rf(struct iwl_priv *priv)
+{
+	if (iwl_is_rfkill(priv))
+		return 0;
+
+	return iwl_is_ready(priv);
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...)	\
+do {									\
+	if (!iwl_is_rfkill((m)))					\
+		IWL_ERR(m, fmt, ##args);				\
+	else								\
+		__iwl_err(trans(m)->dev, true,				\
+			  !iwl_have_debug_level(IWL_DL_RADIO),		\
+			  fmt, ##args);					\
+} while (0)
+#else
+#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...)	\
+do {									\
+	if (!iwl_is_rfkill((m)))					\
+		IWL_ERR(m, fmt, ##args);				\
+	else								\
+		__iwl_err(trans(m)->dev, true, true, fmt, ##args);	\
+} while (0)
+#endif				/* CONFIG_IWLWIFI_DEBUG */
+
 #endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-cfg.h b/drivers/net/wireless/iwlwifi/iwl-cfg.h
index 1ad14bb..82152311 100644
--- a/drivers/net/wireless/iwlwifi/iwl-cfg.h
+++ b/drivers/net/wireless/iwlwifi/iwl-cfg.h
@@ -68,46 +68,46 @@
  * This file declares the config structures for all devices.
  */
 
-extern struct iwl_cfg iwl5300_agn_cfg;
-extern struct iwl_cfg iwl5100_agn_cfg;
-extern struct iwl_cfg iwl5350_agn_cfg;
-extern struct iwl_cfg iwl5100_bgn_cfg;
-extern struct iwl_cfg iwl5100_abg_cfg;
-extern struct iwl_cfg iwl5150_agn_cfg;
-extern struct iwl_cfg iwl5150_abg_cfg;
-extern struct iwl_cfg iwl6005_2agn_cfg;
-extern struct iwl_cfg iwl6005_2abg_cfg;
-extern struct iwl_cfg iwl6005_2bg_cfg;
-extern struct iwl_cfg iwl6005_2agn_sff_cfg;
-extern struct iwl_cfg iwl6005_2agn_d_cfg;
-extern struct iwl_cfg iwl6005_2agn_mow1_cfg;
-extern struct iwl_cfg iwl6005_2agn_mow2_cfg;
-extern struct iwl_cfg iwl1030_bgn_cfg;
-extern struct iwl_cfg iwl1030_bg_cfg;
-extern struct iwl_cfg iwl6030_2agn_cfg;
-extern struct iwl_cfg iwl6030_2abg_cfg;
-extern struct iwl_cfg iwl6030_2bgn_cfg;
-extern struct iwl_cfg iwl6030_2bg_cfg;
-extern struct iwl_cfg iwl6000i_2agn_cfg;
-extern struct iwl_cfg iwl6000i_2abg_cfg;
-extern struct iwl_cfg iwl6000i_2bg_cfg;
-extern struct iwl_cfg iwl6000_3agn_cfg;
-extern struct iwl_cfg iwl6050_2agn_cfg;
-extern struct iwl_cfg iwl6050_2abg_cfg;
-extern struct iwl_cfg iwl6150_bgn_cfg;
-extern struct iwl_cfg iwl6150_bg_cfg;
-extern struct iwl_cfg iwl1000_bgn_cfg;
-extern struct iwl_cfg iwl1000_bg_cfg;
-extern struct iwl_cfg iwl100_bgn_cfg;
-extern struct iwl_cfg iwl100_bg_cfg;
-extern struct iwl_cfg iwl130_bgn_cfg;
-extern struct iwl_cfg iwl130_bg_cfg;
-extern struct iwl_cfg iwl2000_2bgn_cfg;
-extern struct iwl_cfg iwl2000_2bgn_d_cfg;
-extern struct iwl_cfg iwl2030_2bgn_cfg;
-extern struct iwl_cfg iwl6035_2agn_cfg;
-extern struct iwl_cfg iwl105_bgn_cfg;
-extern struct iwl_cfg iwl105_bgn_d_cfg;
-extern struct iwl_cfg iwl135_bgn_cfg;
+extern const struct iwl_cfg iwl5300_agn_cfg;
+extern const struct iwl_cfg iwl5100_agn_cfg;
+extern const struct iwl_cfg iwl5350_agn_cfg;
+extern const struct iwl_cfg iwl5100_bgn_cfg;
+extern const struct iwl_cfg iwl5100_abg_cfg;
+extern const struct iwl_cfg iwl5150_agn_cfg;
+extern const struct iwl_cfg iwl5150_abg_cfg;
+extern const struct iwl_cfg iwl6005_2agn_cfg;
+extern const struct iwl_cfg iwl6005_2abg_cfg;
+extern const struct iwl_cfg iwl6005_2bg_cfg;
+extern const struct iwl_cfg iwl6005_2agn_sff_cfg;
+extern const struct iwl_cfg iwl6005_2agn_d_cfg;
+extern const struct iwl_cfg iwl6005_2agn_mow1_cfg;
+extern const struct iwl_cfg iwl6005_2agn_mow2_cfg;
+extern const struct iwl_cfg iwl1030_bgn_cfg;
+extern const struct iwl_cfg iwl1030_bg_cfg;
+extern const struct iwl_cfg iwl6030_2agn_cfg;
+extern const struct iwl_cfg iwl6030_2abg_cfg;
+extern const struct iwl_cfg iwl6030_2bgn_cfg;
+extern const struct iwl_cfg iwl6030_2bg_cfg;
+extern const struct iwl_cfg iwl6000i_2agn_cfg;
+extern const struct iwl_cfg iwl6000i_2abg_cfg;
+extern const struct iwl_cfg iwl6000i_2bg_cfg;
+extern const struct iwl_cfg iwl6000_3agn_cfg;
+extern const struct iwl_cfg iwl6050_2agn_cfg;
+extern const struct iwl_cfg iwl6050_2abg_cfg;
+extern const struct iwl_cfg iwl6150_bgn_cfg;
+extern const struct iwl_cfg iwl6150_bg_cfg;
+extern const struct iwl_cfg iwl1000_bgn_cfg;
+extern const struct iwl_cfg iwl1000_bg_cfg;
+extern const struct iwl_cfg iwl100_bgn_cfg;
+extern const struct iwl_cfg iwl100_bg_cfg;
+extern const struct iwl_cfg iwl130_bgn_cfg;
+extern const struct iwl_cfg iwl130_bg_cfg;
+extern const struct iwl_cfg iwl2000_2bgn_cfg;
+extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
+extern const struct iwl_cfg iwl2030_2bgn_cfg;
+extern const struct iwl_cfg iwl6035_2agn_cfg;
+extern const struct iwl_cfg iwl105_bgn_cfg;
+extern const struct iwl_cfg iwl105_bgn_d_cfg;
+extern const struct iwl_cfg iwl135_bgn_cfg;
 
 #endif /* __iwl_pci_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index c20618d..9ed73e5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -69,22 +69,9 @@
 #ifndef __iwl_commands_h__
 #define __iwl_commands_h__
 
-#include <linux/etherdevice.h>
 #include <linux/ieee80211.h>
+#include <linux/types.h>
 
-struct iwl_priv;
-
-/* uCode version contains 4 values: Major/Minor/API/Serial */
-#define IWL_UCODE_MAJOR(ver)	(((ver) & 0xFF000000) >> 24)
-#define IWL_UCODE_MINOR(ver)	(((ver) & 0x00FF0000) >> 16)
-#define IWL_UCODE_API(ver)	(((ver) & 0x0000FF00) >> 8)
-#define IWL_UCODE_SERIAL(ver)	((ver) & 0x000000FF)
-
-
-/* Tx rates */
-#define IWL_CCK_RATES	4
-#define IWL_OFDM_RATES	8
-#define IWL_MAX_RATES	(IWL_CCK_RATES + IWL_OFDM_RATES)
 
 enum {
 	REPLY_ALIVE = 0x1,
@@ -213,48 +200,6 @@
 /* iwl_cmd_header flags value */
 #define IWL_CMD_FAILED_MSK 0x40
 
-#define SEQ_TO_QUEUE(s)	(((s) >> 8) & 0x1f)
-#define QUEUE_TO_SEQ(q)	(((q) & 0x1f) << 8)
-#define SEQ_TO_INDEX(s)	((s) & 0xff)
-#define INDEX_TO_SEQ(i)	((i) & 0xff)
-#define SEQ_RX_FRAME	cpu_to_le16(0x8000)
-
-/**
- * struct iwl_cmd_header
- *
- * This header format appears in the beginning of each command sent from the
- * driver, and each response/notification received from uCode.
- */
-struct iwl_cmd_header {
-	u8 cmd;		/* Command ID:  REPLY_RXON, etc. */
-	u8 flags;	/* 0:5 reserved, 6 abort, 7 internal */
-	/*
-	 * The driver sets up the sequence number to values of its choosing.
-	 * uCode does not use this value, but passes it back to the driver
-	 * when sending the response to each driver-originated command, so
-	 * the driver can match the response to the command.  Since the values
-	 * don't get used by uCode, the driver may set up an arbitrary format.
-	 *
-	 * There is one exception:  uCode sets bit 15 when it originates
-	 * the response/notification, i.e. when the response/notification
-	 * is not a direct response to a command sent by the driver.  For
-	 * example, uCode issues REPLY_RX when it sends a received frame
-	 * to the driver; it is not a direct response to any driver command.
-	 *
-	 * The Linux driver uses the following format:
-	 *
-	 *  0:7		tfd index - position within TX queue
-	 *  8:12	TX queue id
-	 *  13:14	reserved
-	 *  15		unsolicited RX or uCode-originated notification
-	 */
-	__le16 sequence;
-
-	/* command or response/notification data follows immediately */
-	u8 data[0];
-} __packed;
-
-
 /**
  * iwlagn rate_n_flags bit fields
  *
@@ -3151,8 +3096,6 @@
  */
 
 /* Phy calibration command for series */
-/* The default calibrate table size if not specified by firmware */
-#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE	18
 enum {
 	IWL_PHY_CALIBRATE_DC_CMD		= 8,
 	IWL_PHY_CALIBRATE_LO_CMD		= 9,
@@ -3161,11 +3104,8 @@
 	IWL_PHY_CALIBRATE_BASE_BAND_CMD		= 16,
 	IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD	= 17,
 	IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD	= 18,
-	IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE	= 19,
 };
 
-#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE		(253)
-
 /* This enum defines the bitmap of various calibrations to enable in both
  * init ucode and runtime ucode through CALIBRATION_CFG_CMD.
  */
@@ -3905,50 +3845,6 @@
 	__le64	replay_ctr;
 } __packed;
 
-/******************************************************************************
- * (13)
- * Union of all expected notifications/responses:
- *
- *****************************************************************************/
-#define FH_RSCSR_FRAME_SIZE_MSK	(0x00003FFF)	/* bits 0-13 */
-
-struct iwl_rx_packet {
-	/*
-	 * The first 4 bytes of the RX frame header contain both the RX frame
-	 * size and some flags.
-	 * Bit fields:
-	 * 31:    flag flush RB request
-	 * 30:    flag ignore TC (terminal counter) request
-	 * 29:    flag fast IRQ request
-	 * 28-14: Reserved
-	 * 13-00: RX frame size
-	 */
-	__le32 len_n_flags;
-	struct iwl_cmd_header hdr;
-	union {
-		struct iwl_alive_resp alive_frame;
-		struct iwl_spectrum_notification spectrum_notif;
-		struct iwl_csa_notification csa_notif;
-		struct iwl_error_resp err_resp;
-		struct iwl_card_state_notif card_state_notif;
-		struct iwl_add_sta_resp add_sta;
-		struct iwl_rem_sta_resp rem_sta;
-		struct iwl_sleep_notification sleep_notif;
-		struct iwl_spectrum_resp spectrum;
-		struct iwl_notif_statistics stats;
-		struct iwl_bt_notif_statistics stats_bt;
-		struct iwl_compressed_ba_resp compressed_ba;
-		struct iwl_missed_beacon_notif missed_beacon;
-		struct iwl_coex_medium_notification coex_medium_notif;
-		struct iwl_coex_event_resp coex_event;
-		struct iwl_bt_coex_profile_notif bt_coex_profile_notif;
-		__le32 status;
-		u8 raw[0];
-	} u;
-} __packed;
-
-int iwl_agn_check_rxon_cmd(struct iwl_priv *priv);
-
 /*
  * REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification)
  */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 275e089..46490d3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -41,7 +41,6 @@
 #include "iwl-shared.h"
 #include "iwl-agn.h"
 #include "iwl-trans.h"
-#include "iwl-wifi.h"
 
 const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 
@@ -114,7 +113,7 @@
 	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
 	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
 		IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
-		set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
+		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
 		return 0;
 	}
 
@@ -137,7 +136,7 @@
 	sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
 	sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
 
-	if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
+	if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
 		iwl_init_ht_hw_capab(priv, &sband->ht_cap,
 					 IEEE80211_BAND_5GHZ);
 
@@ -147,7 +146,7 @@
 	sband->bitrates = rates;
 	sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
 
-	if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
+	if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
 		iwl_init_ht_hw_capab(priv, &sband->ht_cap,
 					 IEEE80211_BAND_2GHZ);
 
@@ -202,18 +201,18 @@
 	priv->tx_power_next = max_tx_power;
 
 	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
-	     cfg(priv)->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
+	     hw_params(priv).sku & EEPROM_SKU_CAP_BAND_52GHZ) {
 		IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
 			"Please send your %s to maintainer.\n",
 			trans(priv)->hw_id_str);
-		cfg(priv)->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
+		hw_params(priv).sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
 	}
 
 	IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
 		   priv->bands[IEEE80211_BAND_2GHZ].n_channels,
 		   priv->bands[IEEE80211_BAND_5GHZ].n_channels);
 
-	set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
+	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
 
 	return 0;
 }
@@ -225,7 +224,7 @@
 {
 	kfree(priv->ieee_channels);
 	kfree(priv->ieee_rates);
-	clear_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
+	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
 }
 
 static bool iwl_is_channel_extension(struct iwl_priv *priv,
@@ -317,7 +316,7 @@
 
 	conf = &priv->hw->conf;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
 
@@ -370,7 +369,7 @@
 			le32_to_cpu(ctx->timing.beacon_init_val),
 			le16_to_cpu(ctx->timing.atim_window));
 
-	return iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_timing_cmd,
+	return iwl_dvm_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
 				CMD_SYNC, sizeof(ctx->timing), &ctx->timing);
 }
 
@@ -799,11 +798,10 @@
 	 */
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
-				&priv->shrd->status))
+	if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
 		ieee80211_chswitch_done(ctx->vif, is_success);
 }
 
@@ -836,23 +834,26 @@
 	unsigned long reload_jiffies;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS)
+	if (iwl_have_debug_level(IWL_DL_FW_ERRORS))
 		iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
 #endif
 
+	/* uCode is no longer loaded. */
+	priv->ucode_loaded = false;
+
 	/* Set the FW error flag -- cleared on iwl_down */
 	set_bit(STATUS_FW_ERROR, &priv->shrd->status);
 
 	/* Cancel currently queued command. */
 	clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status);
 
-	iwl_abort_notification_waits(priv->shrd);
+	iwl_abort_notification_waits(&priv->notif_wait);
 
 	/* Keep the restart process from trying to send host
 	 * commands by clearing the ready bit */
-	clear_bit(STATUS_READY, &priv->shrd->status);
+	clear_bit(STATUS_READY, &priv->status);
 
-	wake_up(&priv->shrd->wait_command_queue);
+	wake_up(&trans(priv)->wait_command_queue);
 
 	if (!ondemand) {
 		/*
@@ -875,7 +876,7 @@
 			priv->reload_count = 0;
 	}
 
-	if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
+	if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
 		if (iwlagn_mod_params.restart_fw) {
 			IWL_DEBUG_FW_ERRORS(priv,
 				  "Restarting adapter due to uCode error.\n");
@@ -893,7 +894,7 @@
 	bool defer;
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	if (priv->tx_power_user_lmt == tx_power && !force)
 		return 0;
@@ -913,7 +914,7 @@
 		return -EINVAL;
 	}
 
-	if (!iwl_is_ready_rf(priv->shrd))
+	if (!iwl_is_ready_rf(priv))
 		return -EIO;
 
 	/* scan complete and commit_rxon use tx_power_next value,
@@ -921,7 +922,7 @@
 	priv->tx_power_next = tx_power;
 
 	/* do not set tx power when scanning or channel changing */
-	defer = test_bit(STATUS_SCANNING, &priv->shrd->status) ||
+	defer = test_bit(STATUS_SCANNING, &priv->status) ||
 		memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
 	if (defer && !force) {
 		IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
@@ -959,7 +960,7 @@
 	IWL_DEBUG_INFO(priv, "BT coex %s\n",
 		(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
 
-	if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
+	if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
 			     CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
 		IWL_ERR(priv, "failed to send BT Coex Config\n");
 }
@@ -972,12 +973,12 @@
 	};
 
 	if (flags & CMD_ASYNC)
-		return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD,
+		return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
 					      CMD_ASYNC,
 					       sizeof(struct iwl_statistics_cmd),
 					       &statistics_cmd);
 	else
-		return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD,
+		return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
 					CMD_SYNC,
 					sizeof(struct iwl_statistics_cmd),
 					&statistics_cmd);
@@ -1004,7 +1005,7 @@
 {
 	u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
 
-	if (iwl_get_debug_level(priv->shrd) & IWL_DL_TX) {
+	if (iwl_have_debug_level(IWL_DL_TX)) {
 		if (!priv->tx_traffic) {
 			priv->tx_traffic =
 				kzalloc(traffic_size, GFP_KERNEL);
@@ -1012,7 +1013,7 @@
 				return -ENOMEM;
 		}
 	}
-	if (iwl_get_debug_level(priv->shrd) & IWL_DL_RX) {
+	if (iwl_have_debug_level(IWL_DL_RX)) {
 		if (!priv->rx_traffic) {
 			priv->rx_traffic =
 				kzalloc(traffic_size, GFP_KERNEL);
@@ -1039,7 +1040,7 @@
 	__le16 fc;
 	u16 len;
 
-	if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_TX)))
+	if (likely(!iwl_have_debug_level(IWL_DL_TX)))
 		return;
 
 	if (!priv->tx_traffic)
@@ -1063,7 +1064,7 @@
 	__le16 fc;
 	u16 len;
 
-	if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_RX)))
+	if (likely(!iwl_have_debug_level(IWL_DL_RX)))
 		return;
 
 	if (!priv->rx_traffic)
@@ -1220,7 +1221,7 @@
 
 static void iwl_force_rf_reset(struct iwl_priv *priv)
 {
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	if (!iwl_is_any_associated(priv)) {
@@ -1245,7 +1246,7 @@
 {
 	struct iwl_force_reset *force_reset;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return -EINVAL;
 
 	if (mode >= IWL_MAX_FORCE_RESET) {
@@ -1301,7 +1302,7 @@
 		.flags = CMD_SYNC,
 	};
 
-	ret = iwl_trans_send_cmd(trans(priv), &cmd);
+	ret = iwl_dvm_send_cmd(priv, &cmd);
 	if (ret)
 		IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);
 	else
@@ -1335,30 +1336,20 @@
 	int cnt;
 	unsigned long timeout;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	if (iwl_is_rfkill(priv->shrd))
+	if (iwl_is_rfkill(priv))
 		return;
 
-	timeout = cfg(priv)->base_params->wd_timeout;
+	timeout = hw_params(priv).wd_timeout;
 	if (timeout == 0)
 		return;
 
-	/* monitor and check for stuck cmd queue */
-	if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue))
-		return;
-
-	/* monitor and check for other stuck queues */
-	if (iwl_is_any_associated(priv)) {
-		for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) {
-			/* skip as we already checked the command queue */
-			if (cnt == priv->shrd->cmd_queue)
-				continue;
-			if (iwl_check_stuck_queue(priv, cnt))
-				return;
-		}
-	}
+	/* monitor and check for stuck queues */
+	for (cnt = 0; cnt < cfg(priv)->base_params->num_of_queues; cnt++)
+		if (iwl_check_stuck_queue(priv, cnt))
+			return;
 
 	mod_timer(&priv->watchdog, jiffies +
 		  msecs_to_jiffies(IWL_WD_TICK(timeout)));
@@ -1366,7 +1357,7 @@
 
 void iwl_setup_watchdog(struct iwl_priv *priv)
 {
-	unsigned int timeout = cfg(priv)->base_params->wd_timeout;
+	unsigned int timeout = hw_params(priv).wd_timeout;
 
 	if (!iwlagn_mod_params.wd_disable) {
 		/* use system default */
@@ -1471,34 +1462,19 @@
 {
 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
 
-	wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
-}
+	if (state)
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
-void iwl_nic_config(struct iwl_priv *priv)
-{
-	cfg(priv)->lib->nic_config(priv);
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
 }
 
 void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
 {
-	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
 	struct ieee80211_tx_info *info;
 
 	info = IEEE80211_SKB_CB(skb);
-	kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
+	kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
 	dev_kfree_skb_any(skb);
 }
-
-void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
-{
-	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
-
-	ieee80211_stop_queue(priv->hw, ac);
-}
-
-void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
-{
-	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
-
-	ieee80211_wake_queue(priv->hw, ac);
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 42630f5e..635eb68 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -77,12 +77,6 @@
 struct iwl_lib_ops {
 	/* set hw dependent parameters */
 	void (*set_hw_params)(struct iwl_priv *priv);
-	/* setup BT Rx handler */
-	void (*bt_rx_handler_setup)(struct iwl_priv *priv);
-	/* setup BT related deferred work */
-	void (*bt_setup_deferred_work)(struct iwl_priv *priv);
-	/* cancel deferred work */
-	void (*cancel_deferred_work)(struct iwl_priv *priv);
 	int (*set_channel_switch)(struct iwl_priv *priv,
 				  struct ieee80211_channel_switch *ch_switch);
 	/* device specific configuration */
@@ -95,72 +89,6 @@
 	void (*temperature)(struct iwl_priv *priv);
 };
 
-/*
- * @max_ll_items: max number of OTP blocks
- * @shadow_ram_support: shadow support for OTP memory
- * @led_compensation: compensate on the led on/off time per HW according
- *	to the deviation to achieve the desired led frequency.
- *	The detail algorithm is described in iwl-led.c
- * @chain_noise_num_beacons: number of beacons used to compute chain noise
- * @adv_thermal_throttle: support advance thermal throttle
- * @support_ct_kill_exit: support ct kill exit condition
- * @support_wimax_coexist: support wimax/wifi co-exist
- * @plcp_delta_threshold: plcp error rate threshold used to trigger
- *	radio tuning when there is a high receiving plcp error rate
- * @chain_noise_scale: default chain noise scale used for gain computation
- * @wd_timeout: TX queues watchdog timeout
- * @max_event_log_size: size of event log buffer size for ucode event logging
- * @shadow_reg_enable: HW shadhow register bit
- * @no_idle_support: do not support idle mode
- * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
- * wd_disable: disable watchdog timer
- */
-struct iwl_base_params {
-	int eeprom_size;
-	int num_of_queues;	/* def: HW dependent */
-	int num_of_ampdu_queues;/* def: HW dependent */
-	/* for iwl_apm_init() */
-	u32 pll_cfg_val;
-
-	const u16 max_ll_items;
-	const bool shadow_ram_support;
-	u16 led_compensation;
-	bool adv_thermal_throttle;
-	bool support_ct_kill_exit;
-	const bool support_wimax_coexist;
-	u8 plcp_delta_threshold;
-	s32 chain_noise_scale;
-	unsigned int wd_timeout;
-	u32 max_event_log_size;
-	const bool shadow_reg_enable;
-	const bool no_idle_support;
-	const bool hd_v2;
-	const bool wd_disable;
-};
-/*
- * @advanced_bt_coexist: support advanced bt coexist
- * @bt_init_traffic_load: specify initial bt traffic load
- * @bt_prio_boost: default bt priority boost value
- * @agg_time_limit: maximum number of uSec in aggregation
- * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
- */
-struct iwl_bt_params {
-	bool advanced_bt_coexist;
-	u8 bt_init_traffic_load;
-	u8 bt_prio_boost;
-	u16 agg_time_limit;
-	bool bt_sco_disable;
-	bool bt_session_2;
-};
-/*
- * @use_rts_for_aggregation: use rts/cts protection for HT traffic
- */
-struct iwl_ht_params {
-	const bool ht_greenfield_support; /* if used set to true */
-	bool use_rts_for_aggregation;
-	enum ieee80211_smps_mode smps_mode;
-};
-
 /***************************
  *   L i b                 *
  ***************************/
@@ -244,8 +172,6 @@
 void iwl_force_scan_end(struct iwl_priv *priv);
 void iwl_internal_short_hw_scan(struct iwl_priv *priv);
 int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
-u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
-		       const u8 *ta, const u8 *ie, int ie_len, int left);
 void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
 void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
 void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
@@ -265,6 +191,10 @@
 
 #define IWL_SCAN_CHECK_WATCHDOG		(HZ * 7)
 
+/* traffic log definitions */
+#define IWL_TRAFFIC_ENTRIES	(256)
+#define IWL_TRAFFIC_ENTRY_SIZE  (64)
+
 /*****************************************************
  *   S e n d i n g     H o s t     C o m m a n d s   *
  *****************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c
index 4bc2e70..059efab 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.c
@@ -104,7 +104,7 @@
 }
 
 #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
-void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
+void __iwl_dbg(struct device *dev,
 	       u32 level, bool limit, const char *function,
 	       const char *fmt, ...)
 {
@@ -116,7 +116,7 @@
 	va_start(args, fmt);
 	vaf.va = &args;
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(shared) & level &&
+	if (iwl_have_debug_level(level) &&
 	    (!limit || net_ratelimit()))
 		dev_err(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U',
 			function, &vaf);
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 01b2330..a6b32a1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -47,12 +47,12 @@
 #define IWL_CRIT(m, f, a...) __iwl_crit(trans(m)->dev, f, ## a)
 
 #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
-void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
+void __iwl_dbg(struct device *dev,
 	       u32 level, bool limit, const char *function,
 	       const char *fmt, ...);
 #else
 static inline void
-__iwl_dbg(struct iwl_shared *shared, struct device *dev,
+__iwl_dbg(struct device *dev,
 	  u32 level, bool limit, const char *function,
 	  const char *fmt, ...)
 {}
@@ -65,35 +65,19 @@
 } while (0)
 
 #define IWL_DEBUG(m, level, fmt, args...)				\
-	__iwl_dbg((m)->shrd, trans(m)->dev, level, false, __func__, fmt, ##args)
+	__iwl_dbg(trans(m)->dev, level, false, __func__, fmt, ##args)
 #define IWL_DEBUG_LIMIT(m, level, fmt, args...)				\
-	__iwl_dbg((m)->shrd, trans(m)->dev, level, true, __func__, fmt, ##args)
+	__iwl_dbg(trans(m)->dev, level, true, __func__, fmt, ##args)
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 #define iwl_print_hex_dump(m, level, p, len)				\
 do {                                            			\
-	if (iwl_get_debug_level((m)->shrd) & level)			\
+	if (iwl_have_debug_level(level))				\
 		print_hex_dump(KERN_DEBUG, "iwl data: ",		\
 			       DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);	\
 } while (0)
-#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...)	\
-do {									\
-	if (!iwl_is_rfkill((m)->shrd))					\
-		IWL_ERR(m, fmt, ##args);				\
-	else								\
-		__iwl_err(trans(m)->dev, true,				\
-			  !(iwl_get_debug_level((m)->shrd) & IWL_DL_RADIO),\
-			  fmt, ##args);					\
-} while (0)
 #else
 #define iwl_print_hex_dump(m, level, p, len)
-#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...)	\
-do {									\
-	if (!iwl_is_rfkill((m)->shrd))					\
-		IWL_ERR(m, fmt, ##args);				\
-	else								\
-		__iwl_err(trans(m)->dev, true, true, fmt, ##args);	\
-} while (0)
 #endif				/* CONFIG_IWLWIFI_DEBUG */
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index ad74138e..b7b1c04 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -40,7 +40,6 @@
 #include "iwl-core.h"
 #include "iwl-io.h"
 #include "iwl-agn.h"
-#include "iwl-wifi.h"
 
 /* create and remove of files */
 #define DEBUGFS_ADD_FILE(name, parent, mode) do {			\
@@ -231,16 +230,18 @@
 	int pos = 0;
 	int sram;
 	struct iwl_priv *priv = file->private_data;
+	const struct fw_img *img;
 	size_t bufsz;
 
 	/* default is to dump the entire data segment */
 	if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
-		struct iwl_nic *nic = nic(priv);
 		priv->dbgfs_sram_offset = 0x800000;
-		if (nic->shrd->ucode_type == IWL_UCODE_INIT)
-			priv->dbgfs_sram_len = nic->fw.ucode_init.data.len;
-		else
-			priv->dbgfs_sram_len = nic->fw.ucode_rt.data.len;
+		if (!priv->ucode_loaded) {
+			IWL_ERR(priv, "No uCode has been loadded.\n");
+			return -EINVAL;
+		}
+		img = &priv->fw->img[priv->shrd->ucode_type];
+		priv->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
 	}
 	len = priv->dbgfs_sram_len;
 
@@ -337,13 +338,14 @@
 					  size_t count, loff_t *ppos)
 {
 	struct iwl_priv *priv = file->private_data;
+	const struct fw_img *img = &priv->fw->img[IWL_UCODE_WOWLAN];
 
 	if (!priv->wowlan_sram)
 		return -ENODATA;
 
 	return simple_read_from_buffer(user_buf, count, ppos,
 				       priv->wowlan_sram,
-				       nic(priv)->fw.ucode_wowlan.data.len);
+				       img->sec[IWL_UCODE_SECTION_DATA].len);
 }
 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
 					size_t count, loff_t *ppos)
@@ -456,7 +458,7 @@
 	char *buf;
 	ssize_t ret;
 
-	if (!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status))
+	if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
 		return -EAGAIN;
 
 	buf = kzalloc(bufsz, GFP_KERNEL);
@@ -527,32 +529,26 @@
 
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
 		test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status));
-	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
-		test_bit(STATUS_INT_ENABLED, &priv->shrd->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
-		test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
+		test_bit(STATUS_RF_KILL_HW, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
-		test_bit(STATUS_CT_KILL, &priv->shrd->status));
-	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
-		test_bit(STATUS_INIT, &priv->shrd->status));
+		test_bit(STATUS_CT_KILL, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
-		test_bit(STATUS_ALIVE, &priv->shrd->status));
+		test_bit(STATUS_ALIVE, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
-		test_bit(STATUS_READY, &priv->shrd->status));
-	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
-		test_bit(STATUS_TEMPERATURE, &priv->shrd->status));
+		test_bit(STATUS_READY, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
-		test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status));
+		test_bit(STATUS_GEO_CONFIGURED, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
-		test_bit(STATUS_EXIT_PENDING, &priv->shrd->status));
+		test_bit(STATUS_EXIT_PENDING, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
-		test_bit(STATUS_STATISTICS, &priv->shrd->status));
+		test_bit(STATUS_STATISTICS, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
-		test_bit(STATUS_SCANNING, &priv->shrd->status));
+		test_bit(STATUS_SCANNING, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
-		test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status));
+		test_bit(STATUS_SCAN_ABORTING, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
-		test_bit(STATUS_SCAN_HW, &priv->shrd->status));
+		test_bit(STATUS_SCAN_HW, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
 		test_bit(STATUS_POWER_PMI, &priv->shrd->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
@@ -758,14 +754,14 @@
 	if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
 		return -EINVAL;
 
-	if (!iwl_is_ready_rf(priv->shrd))
+	if (!iwl_is_ready_rf(priv))
 		return -EAGAIN;
 
 	priv->power_data.debug_sleep_level_override = value;
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	iwl_power_update_mode(priv, true);
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 
 	return count;
 }
@@ -836,7 +832,7 @@
 
 	char *buf;
 	int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
-		(hw_params(priv).max_txq_num * 32 * 8) + 400;
+		(cfg(priv)->base_params->num_of_queues * 32 * 8) + 400;
 	const u8 *ptr;
 	ssize_t ret;
 
@@ -845,8 +841,7 @@
 		IWL_ERR(priv, "Can not allocate buffer\n");
 		return -ENOMEM;
 	}
-	if (priv->tx_traffic &&
-		(iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) {
+	if (priv->tx_traffic && iwl_have_debug_level(IWL_DL_TX)) {
 		ptr = priv->tx_traffic;
 		pos += scnprintf(buf + pos, bufsz - pos,
 				"Tx Traffic idx: %u\n", priv->tx_traffic_idx);
@@ -864,8 +859,7 @@
 		}
 	}
 
-	if (priv->rx_traffic &&
-		(iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) {
+	if (priv->rx_traffic && iwl_have_debug_level(IWL_DL_RX)) {
 		ptr = priv->rx_traffic;
 		pos += scnprintf(buf + pos, bufsz - pos,
 				"Rx Traffic idx: %u\n", priv->rx_traffic_idx);
@@ -920,6 +914,8 @@
 	int p = 0;
 	u32 flag;
 
+	lockdep_assert_held(&priv->statistics.lock);
+
 	flag = le32_to_cpu(priv->statistics.flag);
 
 	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
@@ -953,7 +949,7 @@
 	struct statistics_rx_non_phy *delta_general, *max_general;
 	struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
 
-	if (!iwl_is_alive(priv->shrd))
+	if (!iwl_is_alive(priv))
 		return -EAGAIN;
 
 	buf = kzalloc(bufsz, GFP_KERNEL);
@@ -967,6 +963,7 @@
 	 * the last statistics notification from uCode
 	 * might not reflect the current uCode activity
 	 */
+	spin_lock_bh(&priv->statistics.lock);
 	ofdm = &priv->statistics.rx_ofdm;
 	cck = &priv->statistics.rx_cck;
 	general = &priv->statistics.rx_non_phy;
@@ -1363,6 +1360,8 @@
 			 accum_ht->unsupport_mcs,
 			 delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
 
+	spin_unlock_bh(&priv->statistics.lock);
+
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 	kfree(buf);
 	return ret;
@@ -1379,7 +1378,7 @@
 	ssize_t ret;
 	struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
 
-	if (!iwl_is_alive(priv->shrd))
+	if (!iwl_is_alive(priv))
 		return -EAGAIN;
 
 	buf = kzalloc(bufsz, GFP_KERNEL);
@@ -1392,6 +1391,8 @@
 	 * the last statistics notification from uCode
 	 * might not reflect the current uCode activity
 	 */
+	spin_lock_bh(&priv->statistics.lock);
+
 	tx = &priv->statistics.tx;
 	accum_tx = &priv->accum_stats.tx;
 	delta_tx = &priv->delta_stats.tx;
@@ -1541,19 +1542,25 @@
 	if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
 		pos += scnprintf(buf + pos, bufsz - pos,
 			"tx power: (1/2 dB step)\n");
-		if ((cfg(priv)->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
+		if ((hw_params(priv).valid_tx_ant & ANT_A) &&
+		    tx->tx_power.ant_a)
 			pos += scnprintf(buf + pos, bufsz - pos,
 					fmt_hex, "antenna A:",
 					tx->tx_power.ant_a);
-		if ((cfg(priv)->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
+		if ((hw_params(priv).valid_tx_ant & ANT_B) &&
+		    tx->tx_power.ant_b)
 			pos += scnprintf(buf + pos, bufsz - pos,
 					fmt_hex, "antenna B:",
 					tx->tx_power.ant_b);
-		if ((cfg(priv)->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
+		if ((hw_params(priv).valid_tx_ant & ANT_C) &&
+		    tx->tx_power.ant_c)
 			pos += scnprintf(buf + pos, bufsz - pos,
 					fmt_hex, "antenna C:",
 					tx->tx_power.ant_c);
 	}
+
+	spin_unlock_bh(&priv->statistics.lock);
+
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 	kfree(buf);
 	return ret;
@@ -1573,7 +1580,7 @@
 	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
 	struct statistics_div *div, *accum_div, *delta_div, *max_div;
 
-	if (!iwl_is_alive(priv->shrd))
+	if (!iwl_is_alive(priv))
 		return -EAGAIN;
 
 	buf = kzalloc(bufsz, GFP_KERNEL);
@@ -1586,6 +1593,9 @@
 	 * the last statistics notification from uCode
 	 * might not reflect the current uCode activity
 	 */
+
+	spin_lock_bh(&priv->statistics.lock);
+
 	general = &priv->statistics.common;
 	dbg = &priv->statistics.common.dbg;
 	div = &priv->statistics.common.div;
@@ -1670,6 +1680,9 @@
 			 accum_general->num_of_sos_states,
 			 delta_general->num_of_sos_states,
 			 max_general->num_of_sos_states);
+
+	spin_unlock_bh(&priv->statistics.lock);
+
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 	kfree(buf);
 	return ret;
@@ -1686,16 +1699,16 @@
 	ssize_t ret;
 	struct statistics_bt_activity *bt, *accum_bt;
 
-	if (!iwl_is_alive(priv->shrd))
+	if (!iwl_is_alive(priv))
 		return -EAGAIN;
 
 	if (!priv->bt_enable_flag)
 		return -EINVAL;
 
 	/* make request to uCode to retrieve statistics information */
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 
 	if (ret) {
 		IWL_ERR(priv,
@@ -1713,6 +1726,9 @@
 	 * the last statistics notification from uCode
 	 * might not reflect the current uCode activity
 	 */
+
+	spin_lock_bh(&priv->statistics.lock);
+
 	bt = &priv->statistics.bt_activity;
 	accum_bt = &priv->accum_stats.bt_activity;
 
@@ -1758,6 +1774,8 @@
 			 le32_to_cpu(priv->statistics.num_bt_kills),
 			 priv->statistics.accum_num_bt_kills);
 
+	spin_unlock_bh(&priv->statistics.lock);
+
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 	kfree(buf);
 	return ret;
@@ -1774,7 +1792,7 @@
 		(sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;
 	ssize_t ret;
 
-	if (!iwl_is_alive(priv->shrd))
+	if (!iwl_is_alive(priv))
 		return -EAGAIN;
 
 	buf = kzalloc(bufsz, GFP_KERNEL);
@@ -2086,9 +2104,9 @@
 		return -EFAULT;
 
 	/* make request to uCode to retrieve statistics information */
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	iwl_send_statistics_request(priv, CMD_SYNC, true);
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 
 	return count;
 }
@@ -2132,7 +2150,7 @@
 
 	if (trace) {
 		priv->event_log.ucode_trace = true;
-		if (iwl_is_alive(priv->shrd)) {
+		if (iwl_is_alive(priv)) {
 			/* start collecting data now */
 			mod_timer(&priv->ucode_trace, jiffies);
 		}
@@ -2221,7 +2239,7 @@
 	const size_t bufsz = sizeof(buf);
 
 	pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
-			cfg(priv)->base_params->plcp_delta_threshold);
+			priv->plcp_delta_threshold);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
@@ -2243,10 +2261,10 @@
 		return -EINVAL;
 	if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
 		(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
-		cfg(priv)->base_params->plcp_delta_threshold =
+		priv->plcp_delta_threshold =
 			IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
 	else
-		cfg(priv)->base_params->plcp_delta_threshold = plcp;
+		priv->plcp_delta_threshold = plcp;
 	return count;
 }
 
@@ -2322,7 +2340,7 @@
 	if (sscanf(buf, "%d", &flush) != 1)
 		return -EINVAL;
 
-	if (iwl_is_rfkill(priv->shrd))
+	if (iwl_is_rfkill(priv))
 		return -EFAULT;
 
 	iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
@@ -2348,7 +2366,7 @@
 	if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
 		timeout = IWL_DEF_WD_TIMEOUT;
 
-	cfg(priv)->base_params->wd_timeout = timeout;
+	hw_params(priv).wd_timeout = timeout;
 	iwl_setup_watchdog(priv);
 	return count;
 }
@@ -2411,7 +2429,7 @@
 	if (cfg(priv)->ht_params)
 		pos += scnprintf(buf + pos, bufsz - pos,
 			 "use %s for aggregation\n",
-			 (cfg(priv)->ht_params->use_rts_for_aggregation) ?
+			 (hw_params(priv).use_rts_for_aggregation) ?
 				"rts/cts" : "cts-to-self");
 	else
 		pos += scnprintf(buf + pos, bufsz - pos, "N/A");
@@ -2438,9 +2456,9 @@
 	if (sscanf(buf, "%d", &rts) != 1)
 		return -EINVAL;
 	if (rts)
-		cfg(priv)->ht_params->use_rts_for_aggregation = true;
+		hw_params(priv).use_rts_for_aggregation = true;
 	else
-		cfg(priv)->ht_params->use_rts_for_aggregation = false;
+		hw_params(priv).use_rts_for_aggregation = false;
 	return count;
 }
 
@@ -2486,52 +2504,6 @@
 DEBUGFS_READ_FILE_OPS(reply_tx_error);
 DEBUGFS_WRITE_FILE_OPS(echo_test);
 
-#ifdef CONFIG_IWLWIFI_DEBUG
-static ssize_t iwl_dbgfs_debug_level_read(struct file *file,
-					  char __user *user_buf,
-					  size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	struct iwl_shared *shrd = priv->shrd;
-	char buf[11];
-	int len;
-
-	len = scnprintf(buf, sizeof(buf), "0x%.8x",
-			iwl_get_debug_level(shrd));
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t iwl_dbgfs_debug_level_write(struct file *file,
-					   const char __user *user_buf,
-					   size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	struct iwl_shared *shrd = priv->shrd;
-	char buf[11];
-	unsigned long val;
-	int ret;
-
-	if (count > sizeof(buf))
-		return -EINVAL;
-
-	memset(buf, 0, sizeof(buf));
-	if (copy_from_user(buf, user_buf, count))
-		return -EFAULT;
-
-	ret = strict_strtoul(buf, 0, &val);
-	if (ret)
-		return ret;
-
-	shrd->dbg_level_dev = val;
-	if (iwl_alloc_traffic_mem(priv))
-		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
-
-	return count;
-}
-DEBUGFS_READ_WRITE_FILE_OPS(debug_level);
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
 /*
  * Create the debugfs files and directories
  *
@@ -2596,9 +2568,6 @@
 	DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR);
 	if (iwl_advanced_bt_coexist(priv))
 		DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
-#ifdef CONFIG_IWLWIFI_DEBUG
-	DEBUGFS_ADD_FILE(debug_level, dir_debug, S_IRUSR | S_IWUSR);
-#endif
 
 	DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
 			 &priv->disable_sens_cal);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 6e5bf0a..16956b7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -36,11 +36,10 @@
 #include <linux/wait.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
-#include <net/ieee80211_radiotap.h>
+#include <linux/mutex.h>
 
 #include "iwl-eeprom.h"
 #include "iwl-csr.h"
-#include "iwl-prph.h"
 #include "iwl-debug.h"
 #include "iwl-agn-hw.h"
 #include "iwl-led.h"
@@ -50,6 +49,7 @@
 #include "iwl-trans.h"
 #include "iwl-shared.h"
 #include "iwl-op-mode.h"
+#include "iwl-notif-wait.h"
 
 struct iwl_tx_queue;
 
@@ -294,7 +294,6 @@
 
 struct iwl_sensitivity_ranges {
 	u16 min_nrg_cck;
-	u16 max_nrg_cck;
 
 	u16 nrg_th_cck;
 	u16 nrg_th_ofdm;
@@ -670,11 +669,6 @@
 		bool enabled, is_40mhz;
 		u8 extension_chan_offset;
 	} ht;
-
-	u8 bssid[ETH_ALEN];
-	bool preauth_bssid;
-
-	bool last_tx_rejected;
 };
 
 enum iwl_scan_type {
@@ -718,29 +712,44 @@
 
 	/*data shared among all the driver's layers */
 	struct iwl_shared *shrd;
+	const struct iwl_fw *fw;
+	unsigned long status;
+
+	spinlock_t sta_lock;
+	struct mutex mutex;
+
+	unsigned long transport_queue_stop;
+	bool passive_no_rx;
 
 	/* ieee device used by generic ieee processing code */
 	struct ieee80211_hw *hw;
 	struct ieee80211_channel *ieee_channels;
 	struct ieee80211_rate *ieee_rates;
-	struct kmem_cache *tx_cmd_pool;
+
+	struct list_head calib_results;
 
 	struct workqueue_struct *workqueue;
 
 	enum ieee80211_band band;
 
 	void (*pre_rx_handler)(struct iwl_priv *priv,
-			       struct iwl_rx_mem_buffer *rxb);
+			       struct iwl_rx_cmd_buffer *rxb);
 	int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
-				       struct iwl_rx_mem_buffer *rxb,
+				       struct iwl_rx_cmd_buffer *rxb,
 				       struct iwl_device_cmd *cmd);
 
+	struct iwl_notif_wait_data notif_wait;
+
 	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
 
 	/* spectrum measurement report caching */
 	struct iwl_spectrum_notification measure_report;
 	u8 measurement_status;
 
+#define IWL_OWNERSHIP_DRIVER	0
+#define IWL_OWNERSHIP_TM	1
+	u8 ucode_owner;
+
 	/* ucode beacon time */
 	u32 ucode_beacon_time;
 	int missed_beacon_threshold;
@@ -760,12 +769,16 @@
 	/* firmware reload counter and timestamp */
 	unsigned long reload_jiffies;
 	int reload_count;
+	bool ucode_loaded;
+	bool init_ucode_run;		/* Don't run init uCode again */
 
 	/* we allocate array of iwl_channel_info for NIC's valid channels.
 	 *    Access via channel # using indirect index array */
 	struct iwl_channel_info *channel_info;	/* channel info array */
 	u8 channel_count;	/* # of channels */
 
+	u8 plcp_delta_threshold;
+
 	/* thermal calibration */
 	s32 temperature;	/* Celsius */
 	s32 last_temperature;
@@ -788,6 +801,8 @@
 
 	bool new_scan_threshold_behaviour;
 
+	bool wowlan;
+
 	/* EEPROM MAC addresses */
 	struct mac_address addresses[2];
 
@@ -845,6 +860,7 @@
 		struct statistics_bt_activity bt_activity;
 		__le32 num_bt_kills, accum_num_bt_kills;
 #endif
+		spinlock_t lock;
 	} statistics;
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 	struct {
@@ -968,6 +984,7 @@
 	bool have_rekey_data;
 }; /*iwl_priv */
 
+extern struct kmem_cache *iwl_tx_cmd_pool;
 extern struct iwl_mod_params iwlagn_mod_params;
 
 static inline struct iwl_rxon_context *
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index 96e6233..06203d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -41,130 +41,134 @@
 static inline void trace_ ## name(proto) {}
 #endif
 
-#define PRIV_ENTRY	__field(void *, priv)
-#define PRIV_ASSIGN	__entry->priv = priv
+#define DEV_ENTRY	__string(dev, dev_name(dev))
+#define DEV_ASSIGN	__assign_str(dev, dev_name(dev))
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi_io
 
 TRACE_EVENT(iwlwifi_dev_ioread32,
-	TP_PROTO(void *priv, u32 offs, u32 val),
-	TP_ARGS(priv, offs, val),
+	TP_PROTO(const struct device *dev, u32 offs, u32 val),
+	TP_ARGS(dev, offs, val),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 		__field(u32, offs)
 		__field(u32, val)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		__entry->offs = offs;
 		__entry->val = val;
 	),
-	TP_printk("[%p] read io[%#x] = %#x", __entry->priv, __entry->offs, __entry->val)
+	TP_printk("[%s] read io[%#x] = %#x",
+		  __get_str(dev), __entry->offs, __entry->val)
 );
 
 TRACE_EVENT(iwlwifi_dev_iowrite8,
-	TP_PROTO(void *priv, u32 offs, u8 val),
-	TP_ARGS(priv, offs, val),
+	TP_PROTO(const struct device *dev, u32 offs, u8 val),
+	TP_ARGS(dev, offs, val),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 		__field(u32, offs)
 		__field(u8, val)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		__entry->offs = offs;
 		__entry->val = val;
 	),
-	TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val)
+	TP_printk("[%s] write io[%#x] = %#x)",
+		  __get_str(dev), __entry->offs, __entry->val)
 );
 
 TRACE_EVENT(iwlwifi_dev_iowrite32,
-	TP_PROTO(void *priv, u32 offs, u32 val),
-	TP_ARGS(priv, offs, val),
+	TP_PROTO(const struct device *dev, u32 offs, u32 val),
+	TP_ARGS(dev, offs, val),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 		__field(u32, offs)
 		__field(u32, val)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		__entry->offs = offs;
 		__entry->val = val;
 	),
-	TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val)
+	TP_printk("[%s] write io[%#x] = %#x)",
+		  __get_str(dev), __entry->offs, __entry->val)
 );
 
 TRACE_EVENT(iwlwifi_dev_irq,
-	TP_PROTO(void *priv),
-	TP_ARGS(priv),
+	TP_PROTO(const struct device *dev),
+	TP_ARGS(dev),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 	),
 	/* TP_printk("") doesn't compile */
 	TP_printk("%d", 0)
 );
 
 TRACE_EVENT(iwlwifi_dev_ict_read,
-	TP_PROTO(void *priv, u32 index, u32 value),
-	TP_ARGS(priv, index, value),
+	TP_PROTO(const struct device *dev, u32 index, u32 value),
+	TP_ARGS(dev, index, value),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 		__field(u32, index)
 		__field(u32, value)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		__entry->index = index;
 		__entry->value = value;
 	),
-	TP_printk("read ict[%d] = %#.8x", __entry->index, __entry->value)
+	TP_printk("[%s] read ict[%d] = %#.8x",
+		  __get_str(dev), __entry->index, __entry->value)
 );
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi_ucode
 
 TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
-	TP_PROTO(void *priv, u32 time, u32 data, u32 ev),
-	TP_ARGS(priv, time, data, ev),
+	TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
+	TP_ARGS(dev, time, data, ev),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 
 		__field(u32, time)
 		__field(u32, data)
 		__field(u32, ev)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		__entry->time = time;
 		__entry->data = data;
 		__entry->ev = ev;
 	),
-	TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
-		  __entry->priv, __entry->time, __entry->data, __entry->ev)
+	TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
+		  __get_str(dev), __entry->time, __entry->data, __entry->ev)
 );
 
 TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
-	TP_PROTO(void *priv, u32 wraps, u32 n_entry, u32 p_entry),
-	TP_ARGS(priv, wraps, n_entry, p_entry),
+	TP_PROTO(const struct device *dev, u32 wraps, u32 n_entry, u32 p_entry),
+	TP_ARGS(dev, wraps, n_entry, p_entry),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 
 		__field(u32, wraps)
 		__field(u32, n_entry)
 		__field(u32, p_entry)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		__entry->wraps = wraps;
 		__entry->n_entry = n_entry;
 		__entry->p_entry = p_entry;
 	),
-	TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
-		  __entry->priv, __entry->wraps, __entry->n_entry,
+	TP_printk("[%s] wraps=#%02d n=0x%X p=0x%X",
+		  __get_str(dev), __entry->wraps, __entry->n_entry,
 		  __entry->p_entry)
 );
 
@@ -232,52 +236,52 @@
 #define TRACE_SYSTEM iwlwifi
 
 TRACE_EVENT(iwlwifi_dev_hcmd,
-	TP_PROTO(void *priv, u32 flags,
+	TP_PROTO(const struct device *dev, u32 flags,
 		 const void *hcmd0, size_t len0,
 		 const void *hcmd1, size_t len1,
 		 const void *hcmd2, size_t len2),
-	TP_ARGS(priv, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2),
+	TP_ARGS(dev, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 		__dynamic_array(u8, hcmd0, len0)
 		__dynamic_array(u8, hcmd1, len1)
 		__dynamic_array(u8, hcmd2, len2)
 		__field(u32, flags)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		memcpy(__get_dynamic_array(hcmd0), hcmd0, len0);
 		memcpy(__get_dynamic_array(hcmd1), hcmd1, len1);
 		memcpy(__get_dynamic_array(hcmd2), hcmd2, len2);
 		__entry->flags = flags;
 	),
-	TP_printk("[%p] hcmd %#.2x (%ssync)",
-		  __entry->priv, ((u8 *)__get_dynamic_array(hcmd0))[0],
+	TP_printk("[%s] hcmd %#.2x (%ssync)",
+		  __get_str(dev), ((u8 *)__get_dynamic_array(hcmd0))[0],
 		  __entry->flags & CMD_ASYNC ? "a" : "")
 );
 
 TRACE_EVENT(iwlwifi_dev_rx,
-	TP_PROTO(void *priv, void *rxbuf, size_t len),
-	TP_ARGS(priv, rxbuf, len),
+	TP_PROTO(const struct device *dev, void *rxbuf, size_t len),
+	TP_ARGS(dev, rxbuf, len),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 		__dynamic_array(u8, rxbuf, len)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
 	),
-	TP_printk("[%p] RX cmd %#.2x",
-		  __entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4])
+	TP_printk("[%s] RX cmd %#.2x",
+		  __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
 );
 
 TRACE_EVENT(iwlwifi_dev_tx,
-	TP_PROTO(void *priv, void *tfd, size_t tfdlen,
+	TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen,
 		 void *buf0, size_t buf0_len,
 		 void *buf1, size_t buf1_len),
-	TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
+	TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 
 		__field(size_t, framelen)
 		__dynamic_array(u8, tfd, tfdlen)
@@ -291,29 +295,28 @@
 		__dynamic_array(u8, buf1, buf1_len)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		__entry->framelen = buf0_len + buf1_len;
 		memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
 		memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
 		memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
 	),
-	TP_printk("[%p] TX %.2x (%zu bytes)",
-		  __entry->priv,
-		  ((u8 *)__get_dynamic_array(buf0))[0],
+	TP_printk("[%s] TX %.2x (%zu bytes)",
+		  __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
 		  __entry->framelen)
 );
 
 TRACE_EVENT(iwlwifi_dev_ucode_error,
-	TP_PROTO(void *priv, u32 desc, u32 tsf_low,
+	TP_PROTO(const struct device *dev, u32 desc, u32 tsf_low,
 		 u32 data1, u32 data2, u32 line, u32 blink1,
 		 u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time,
 		 u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver,
 		 u32 brd_ver),
-	TP_ARGS(priv, desc, tsf_low, data1, data2, line,
+	TP_ARGS(dev, desc, tsf_low, data1, data2, line,
 		blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2,
 		gp3, ucode_ver, hw_ver, brd_ver),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 		__field(u32, desc)
 		__field(u32, tsf_low)
 		__field(u32, data1)
@@ -332,7 +335,7 @@
 		__field(u32, brd_ver)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		__entry->desc = desc;
 		__entry->tsf_low = tsf_low;
 		__entry->data1 = data1;
@@ -350,11 +353,11 @@
 		__entry->hw_ver = hw_ver;
 		__entry->brd_ver = brd_ver;
 	),
-	TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, "
+	TP_printk("[%s] #%02d %010u data 0x%08X 0x%08X line %u, "
 		  "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X "
 		  "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X "
 		  "hw 0x%08X brd 0x%08X",
-		  __entry->priv, __entry->desc, __entry->tsf_low,
+		  __get_str(dev), __entry->desc, __entry->tsf_low,
 		  __entry->data1,
 		  __entry->data2, __entry->line, __entry->blink1,
 		  __entry->blink2, __entry->ilink1, __entry->ilink2,
@@ -364,23 +367,23 @@
 );
 
 TRACE_EVENT(iwlwifi_dev_ucode_event,
-	TP_PROTO(void *priv, u32 time, u32 data, u32 ev),
-	TP_ARGS(priv, time, data, ev),
+	TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
+	TP_ARGS(dev, time, data, ev),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		DEV_ENTRY
 
 		__field(u32, time)
 		__field(u32, data)
 		__field(u32, ev)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		DEV_ASSIGN;
 		__entry->time = time;
 		__entry->data = data;
 		__entry->ev = ev;
 	),
-	TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
-		  __entry->priv, __entry->time, __entry->data, __entry->ev)
+	TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
+		  __get_str(dev), __entry->time, __entry->data, __entry->ev)
 );
 #endif /* __IWLWIFI_DEVICE_TRACE */
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 8ff5256..6f312c7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -61,33 +61,916 @@
  *
  *****************************************************************************/
 #include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
 
 #include "iwl-drv.h"
 #include "iwl-trans.h"
-#include "iwl-wifi.h"
+#include "iwl-shared.h"
 #include "iwl-op-mode.h"
+#include "iwl-agn-hw.h"
+
+/* private includes */
+#include "iwl-fw-file.h"
+
+/**
+ * struct iwl_drv - drv common data
+ * @fw: the iwl_fw structure
+ * @shrd: pointer to common shared structure
+ * @op_mode: the running op_mode
+ * @fw_index: firmware revision to try loading
+ * @firmware_name: composite filename of ucode file to load
+ * @request_firmware_complete: the firmware has been obtained from user space
+ */
+struct iwl_drv {
+	struct iwl_fw fw;
+
+	struct iwl_shared *shrd;
+	struct iwl_op_mode *op_mode;
+
+	int fw_index;                   /* firmware we're trying to load */
+	char firmware_name[25];         /* name of firmware file to load */
+
+	struct completion request_firmware_complete;
+};
+
+
+
+/*
+ * struct fw_sec: Just for the image parsing proccess.
+ * For the fw storage we are using struct fw_desc.
+ */
+struct fw_sec {
+	const void *data;		/* the sec data */
+	size_t size;			/* section size */
+	u32 offset;			/* offset of writing in the device */
+};
+
+static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc)
+{
+	if (desc->v_addr)
+		dma_free_coherent(trans(drv)->dev, desc->len,
+				  desc->v_addr, desc->p_addr);
+	desc->v_addr = NULL;
+	desc->len = 0;
+}
+
+static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img)
+{
+	int i;
+	for (i = 0; i < IWL_UCODE_SECTION_MAX; i++)
+		iwl_free_fw_desc(drv, &img->sec[i]);
+}
+
+static void iwl_dealloc_ucode(struct iwl_drv *drv)
+{
+	int i;
+	for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
+		iwl_free_fw_img(drv, drv->fw.img + i);
+}
+
+static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
+		      struct fw_sec *sec)
+{
+	if (!sec || !sec->size) {
+		desc->v_addr = NULL;
+		return -EINVAL;
+	}
+
+	desc->v_addr = dma_alloc_coherent(trans(drv)->dev, sec->size,
+					  &desc->p_addr, GFP_KERNEL);
+	if (!desc->v_addr)
+		return -ENOMEM;
+
+	desc->len = sec->size;
+	desc->offset = sec->offset;
+	memcpy(desc->v_addr, sec->data, sec->size);
+	return 0;
+}
+
+static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
+
+#define UCODE_EXPERIMENTAL_INDEX	100
+#define UCODE_EXPERIMENTAL_TAG		"exp"
+
+static int iwl_request_firmware(struct iwl_drv *drv, bool first)
+{
+	const struct iwl_cfg *cfg = cfg(drv);
+	const char *name_pre = cfg->fw_name_pre;
+	char tag[8];
+
+	if (first) {
+#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
+		drv->fw_index = UCODE_EXPERIMENTAL_INDEX;
+		strcpy(tag, UCODE_EXPERIMENTAL_TAG);
+	} else if (drv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
+#endif
+		drv->fw_index = cfg->ucode_api_max;
+		sprintf(tag, "%d", drv->fw_index);
+	} else {
+		drv->fw_index--;
+		sprintf(tag, "%d", drv->fw_index);
+	}
+
+	if (drv->fw_index < cfg->ucode_api_min) {
+		IWL_ERR(drv, "no suitable firmware found!\n");
+		return -ENOENT;
+	}
+
+	sprintf(drv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
+
+	IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n",
+		       (drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+				? "EXPERIMENTAL " : "",
+		       drv->firmware_name);
+
+	return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name,
+				       trans(drv)->dev,
+				       GFP_KERNEL, drv, iwl_ucode_callback);
+}
+
+struct fw_img_parsing {
+	struct fw_sec sec[IWL_UCODE_SECTION_MAX];
+	int sec_counter;
+};
+
+/*
+ * struct fw_sec_parsing: to extract fw section and it's offset from tlv
+ */
+struct fw_sec_parsing {
+	__le32 offset;
+	const u8 data[];
+} __packed;
+
+/**
+ * struct iwl_tlv_calib_data - parse the default calib data from TLV
+ *
+ * @ucode_type: the uCode to which the following default calib relates.
+ * @calib: default calibrations.
+ */
+struct iwl_tlv_calib_data {
+	__le32 ucode_type;
+	__le64 calib;
+} __packed;
+
+struct iwl_firmware_pieces {
+	struct fw_img_parsing img[IWL_UCODE_TYPE_MAX];
+
+	u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
+	u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
+};
+
+/*
+ * These functions are just to extract uCode section data from the pieces
+ * structure.
+ */
+static struct fw_sec *get_sec(struct iwl_firmware_pieces *pieces,
+			      enum iwl_ucode_type type,
+			      int  sec)
+{
+	return &pieces->img[type].sec[sec];
+}
+
+static void set_sec_data(struct iwl_firmware_pieces *pieces,
+			 enum iwl_ucode_type type,
+			 int sec,
+			 const void *data)
+{
+	pieces->img[type].sec[sec].data = data;
+}
+
+static void set_sec_size(struct iwl_firmware_pieces *pieces,
+			 enum iwl_ucode_type type,
+			 int sec,
+			 size_t size)
+{
+	pieces->img[type].sec[sec].size = size;
+}
+
+static size_t get_sec_size(struct iwl_firmware_pieces *pieces,
+			   enum iwl_ucode_type type,
+			   int sec)
+{
+	return pieces->img[type].sec[sec].size;
+}
+
+static void set_sec_offset(struct iwl_firmware_pieces *pieces,
+			   enum iwl_ucode_type type,
+			   int sec,
+			   u32 offset)
+{
+	pieces->img[type].sec[sec].offset = offset;
+}
+
+/*
+ * Gets uCode section from tlv.
+ */
+static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces,
+			       const void *data, enum iwl_ucode_type type,
+			       int size)
+{
+	struct fw_img_parsing *img;
+	struct fw_sec *sec;
+	struct fw_sec_parsing *sec_parse;
+
+	if (WARN_ON(!pieces || !data || type >= IWL_UCODE_TYPE_MAX))
+		return -1;
+
+	sec_parse = (struct fw_sec_parsing *)data;
+
+	img = &pieces->img[type];
+	sec = &img->sec[img->sec_counter];
+
+	sec->offset = le32_to_cpu(sec_parse->offset);
+	sec->data = sec_parse->data;
+
+	++img->sec_counter;
+
+	return 0;
+}
+
+static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data)
+{
+	struct iwl_tlv_calib_data *def_calib =
+					(struct iwl_tlv_calib_data *)data;
+	u32 ucode_type = le32_to_cpu(def_calib->ucode_type);
+	if (ucode_type >= IWL_UCODE_TYPE_MAX) {
+		IWL_ERR(drv, "Wrong ucode_type %u for default calibration.\n",
+			ucode_type);
+		return -EINVAL;
+	}
+	drv->fw.default_calib[ucode_type] = le64_to_cpu(def_calib->calib);
+	return 0;
+}
+
+static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
+				    const struct firmware *ucode_raw,
+				    struct iwl_firmware_pieces *pieces)
+{
+	struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
+	u32 api_ver, hdr_size, build;
+	char buildstr[25];
+	const u8 *src;
+
+	drv->fw.ucode_ver = le32_to_cpu(ucode->ver);
+	api_ver = IWL_UCODE_API(drv->fw.ucode_ver);
+
+	switch (api_ver) {
+	default:
+		hdr_size = 28;
+		if (ucode_raw->size < hdr_size) {
+			IWL_ERR(drv, "File size too small!\n");
+			return -EINVAL;
+		}
+		build = le32_to_cpu(ucode->u.v2.build);
+		set_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST,
+			     le32_to_cpu(ucode->u.v2.inst_size));
+		set_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA,
+			     le32_to_cpu(ucode->u.v2.data_size));
+		set_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST,
+			     le32_to_cpu(ucode->u.v2.init_size));
+		set_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA,
+			     le32_to_cpu(ucode->u.v2.init_data_size));
+		src = ucode->u.v2.data;
+		break;
+	case 0:
+	case 1:
+	case 2:
+		hdr_size = 24;
+		if (ucode_raw->size < hdr_size) {
+			IWL_ERR(drv, "File size too small!\n");
+			return -EINVAL;
+		}
+		build = 0;
+		set_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST,
+			     le32_to_cpu(ucode->u.v1.inst_size));
+		set_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA,
+			     le32_to_cpu(ucode->u.v1.data_size));
+		set_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST,
+			     le32_to_cpu(ucode->u.v1.init_size));
+		set_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA,
+			     le32_to_cpu(ucode->u.v1.init_data_size));
+		src = ucode->u.v1.data;
+		break;
+	}
+
+	if (build)
+		sprintf(buildstr, " build %u%s", build,
+		       (drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+				? " (EXP)" : "");
+	else
+		buildstr[0] = '\0';
+
+	snprintf(drv->fw.fw_version,
+		 sizeof(drv->fw.fw_version),
+		 "%u.%u.%u.%u%s",
+		 IWL_UCODE_MAJOR(drv->fw.ucode_ver),
+		 IWL_UCODE_MINOR(drv->fw.ucode_ver),
+		 IWL_UCODE_API(drv->fw.ucode_ver),
+		 IWL_UCODE_SERIAL(drv->fw.ucode_ver),
+		 buildstr);
+
+	/* Verify size of file vs. image size info in file's header */
+
+	if (ucode_raw->size != hdr_size +
+	    get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST) +
+	    get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA) +
+	    get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST) +
+	    get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA)) {
+
+		IWL_ERR(drv,
+			"uCode file size %d does not match expected size\n",
+			(int)ucode_raw->size);
+		return -EINVAL;
+	}
+
+
+	set_sec_data(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST, src);
+	src += get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST);
+	set_sec_offset(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST,
+		       IWLAGN_RTC_INST_LOWER_BOUND);
+	set_sec_data(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA, src);
+	src += get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA);
+	set_sec_offset(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA,
+		       IWLAGN_RTC_DATA_LOWER_BOUND);
+	set_sec_data(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST, src);
+	src += get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST);
+	set_sec_offset(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST,
+		       IWLAGN_RTC_INST_LOWER_BOUND);
+	set_sec_data(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA, src);
+	src += get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA);
+	set_sec_offset(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA,
+		       IWLAGN_RTC_DATA_LOWER_BOUND);
+	return 0;
+}
+
+static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
+				const struct firmware *ucode_raw,
+				struct iwl_firmware_pieces *pieces,
+				struct iwl_ucode_capabilities *capa)
+{
+	struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
+	struct iwl_ucode_tlv *tlv;
+	size_t len = ucode_raw->size;
+	const u8 *data;
+	int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative;
+	int tmp;
+	u64 alternatives;
+	u32 tlv_len;
+	enum iwl_ucode_tlv_type tlv_type;
+	const u8 *tlv_data;
+	char buildstr[25];
+	u32 build;
+
+	if (len < sizeof(*ucode)) {
+		IWL_ERR(drv, "uCode has invalid length: %zd\n", len);
+		return -EINVAL;
+	}
+
+	if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) {
+		IWL_ERR(drv, "invalid uCode magic: 0X%x\n",
+			le32_to_cpu(ucode->magic));
+		return -EINVAL;
+	}
+
+	/*
+	 * Check which alternatives are present, and "downgrade"
+	 * when the chosen alternative is not present, warning
+	 * the user when that happens. Some files may not have
+	 * any alternatives, so don't warn in that case.
+	 */
+	alternatives = le64_to_cpu(ucode->alternatives);
+	tmp = wanted_alternative;
+	if (wanted_alternative > 63)
+		wanted_alternative = 63;
+	while (wanted_alternative && !(alternatives & BIT(wanted_alternative)))
+		wanted_alternative--;
+	if (wanted_alternative && wanted_alternative != tmp)
+		IWL_WARN(drv,
+			 "uCode alternative %d not available, choosing %d\n",
+			 tmp, wanted_alternative);
+
+	drv->fw.ucode_ver = le32_to_cpu(ucode->ver);
+	build = le32_to_cpu(ucode->build);
+
+	if (build)
+		sprintf(buildstr, " build %u%s", build,
+		       (drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+				? " (EXP)" : "");
+	else
+		buildstr[0] = '\0';
+
+	snprintf(drv->fw.fw_version,
+		 sizeof(drv->fw.fw_version),
+		 "%u.%u.%u.%u%s",
+		 IWL_UCODE_MAJOR(drv->fw.ucode_ver),
+		 IWL_UCODE_MINOR(drv->fw.ucode_ver),
+		 IWL_UCODE_API(drv->fw.ucode_ver),
+		 IWL_UCODE_SERIAL(drv->fw.ucode_ver),
+		 buildstr);
+
+	data = ucode->data;
+
+	len -= sizeof(*ucode);
+
+	while (len >= sizeof(*tlv)) {
+		u16 tlv_alt;
+
+		len -= sizeof(*tlv);
+		tlv = (void *)data;
+
+		tlv_len = le32_to_cpu(tlv->length);
+		tlv_type = le16_to_cpu(tlv->type);
+		tlv_alt = le16_to_cpu(tlv->alternative);
+		tlv_data = tlv->data;
+
+		if (len < tlv_len) {
+			IWL_ERR(drv, "invalid TLV len: %zd/%u\n",
+				len, tlv_len);
+			return -EINVAL;
+		}
+		len -= ALIGN(tlv_len, 4);
+		data += sizeof(*tlv) + ALIGN(tlv_len, 4);
+
+		/*
+		 * Alternative 0 is always valid.
+		 *
+		 * Skip alternative TLVs that are not selected.
+		 */
+		if (tlv_alt != 0 && tlv_alt != wanted_alternative)
+			continue;
+
+		switch (tlv_type) {
+		case IWL_UCODE_TLV_INST:
+			set_sec_data(pieces, IWL_UCODE_REGULAR,
+				     IWL_UCODE_SECTION_INST, tlv_data);
+			set_sec_size(pieces, IWL_UCODE_REGULAR,
+				     IWL_UCODE_SECTION_INST, tlv_len);
+			set_sec_offset(pieces, IWL_UCODE_REGULAR,
+				       IWL_UCODE_SECTION_INST,
+				       IWLAGN_RTC_INST_LOWER_BOUND);
+			break;
+		case IWL_UCODE_TLV_DATA:
+			set_sec_data(pieces, IWL_UCODE_REGULAR,
+				     IWL_UCODE_SECTION_DATA, tlv_data);
+			set_sec_size(pieces, IWL_UCODE_REGULAR,
+				     IWL_UCODE_SECTION_DATA, tlv_len);
+			set_sec_offset(pieces, IWL_UCODE_REGULAR,
+				       IWL_UCODE_SECTION_DATA,
+				       IWLAGN_RTC_DATA_LOWER_BOUND);
+			break;
+		case IWL_UCODE_TLV_INIT:
+			set_sec_data(pieces, IWL_UCODE_INIT,
+				     IWL_UCODE_SECTION_INST, tlv_data);
+			set_sec_size(pieces, IWL_UCODE_INIT,
+				     IWL_UCODE_SECTION_INST, tlv_len);
+			set_sec_offset(pieces, IWL_UCODE_INIT,
+				       IWL_UCODE_SECTION_INST,
+				       IWLAGN_RTC_INST_LOWER_BOUND);
+			break;
+		case IWL_UCODE_TLV_INIT_DATA:
+			set_sec_data(pieces, IWL_UCODE_INIT,
+				     IWL_UCODE_SECTION_DATA, tlv_data);
+			set_sec_size(pieces, IWL_UCODE_INIT,
+				     IWL_UCODE_SECTION_DATA, tlv_len);
+			set_sec_offset(pieces, IWL_UCODE_INIT,
+				       IWL_UCODE_SECTION_DATA,
+				       IWLAGN_RTC_DATA_LOWER_BOUND);
+			break;
+		case IWL_UCODE_TLV_BOOT:
+			IWL_ERR(drv, "Found unexpected BOOT ucode\n");
+			break;
+		case IWL_UCODE_TLV_PROBE_MAX_LEN:
+			if (tlv_len != sizeof(u32))
+				goto invalid_tlv_len;
+			capa->max_probe_length =
+					le32_to_cpup((__le32 *)tlv_data);
+			break;
+		case IWL_UCODE_TLV_PAN:
+			if (tlv_len)
+				goto invalid_tlv_len;
+			capa->flags |= IWL_UCODE_TLV_FLAGS_PAN;
+			break;
+		case IWL_UCODE_TLV_FLAGS:
+			/* must be at least one u32 */
+			if (tlv_len < sizeof(u32))
+				goto invalid_tlv_len;
+			/* and a proper number of u32s */
+			if (tlv_len % sizeof(u32))
+				goto invalid_tlv_len;
+			/*
+			 * This driver only reads the first u32 as
+			 * right now no more features are defined,
+			 * if that changes then either the driver
+			 * will not work with the new firmware, or
+			 * it'll not take advantage of new features.
+			 */
+			capa->flags = le32_to_cpup((__le32 *)tlv_data);
+			break;
+		case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
+			if (tlv_len != sizeof(u32))
+				goto invalid_tlv_len;
+			pieces->init_evtlog_ptr =
+					le32_to_cpup((__le32 *)tlv_data);
+			break;
+		case IWL_UCODE_TLV_INIT_EVTLOG_SIZE:
+			if (tlv_len != sizeof(u32))
+				goto invalid_tlv_len;
+			pieces->init_evtlog_size =
+					le32_to_cpup((__le32 *)tlv_data);
+			break;
+		case IWL_UCODE_TLV_INIT_ERRLOG_PTR:
+			if (tlv_len != sizeof(u32))
+				goto invalid_tlv_len;
+			pieces->init_errlog_ptr =
+					le32_to_cpup((__le32 *)tlv_data);
+			break;
+		case IWL_UCODE_TLV_RUNT_EVTLOG_PTR:
+			if (tlv_len != sizeof(u32))
+				goto invalid_tlv_len;
+			pieces->inst_evtlog_ptr =
+					le32_to_cpup((__le32 *)tlv_data);
+			break;
+		case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE:
+			if (tlv_len != sizeof(u32))
+				goto invalid_tlv_len;
+			pieces->inst_evtlog_size =
+					le32_to_cpup((__le32 *)tlv_data);
+			break;
+		case IWL_UCODE_TLV_RUNT_ERRLOG_PTR:
+			if (tlv_len != sizeof(u32))
+				goto invalid_tlv_len;
+			pieces->inst_errlog_ptr =
+					le32_to_cpup((__le32 *)tlv_data);
+			break;
+		case IWL_UCODE_TLV_ENHANCE_SENS_TBL:
+			if (tlv_len)
+				goto invalid_tlv_len;
+			drv->fw.enhance_sensitivity_table = true;
+			break;
+		case IWL_UCODE_TLV_WOWLAN_INST:
+			set_sec_data(pieces, IWL_UCODE_WOWLAN,
+				     IWL_UCODE_SECTION_INST, tlv_data);
+			set_sec_size(pieces, IWL_UCODE_WOWLAN,
+				     IWL_UCODE_SECTION_INST, tlv_len);
+			set_sec_offset(pieces, IWL_UCODE_WOWLAN,
+				       IWL_UCODE_SECTION_INST,
+				       IWLAGN_RTC_INST_LOWER_BOUND);
+			break;
+		case IWL_UCODE_TLV_WOWLAN_DATA:
+			set_sec_data(pieces, IWL_UCODE_WOWLAN,
+				     IWL_UCODE_SECTION_DATA, tlv_data);
+			set_sec_size(pieces, IWL_UCODE_WOWLAN,
+				     IWL_UCODE_SECTION_DATA, tlv_len);
+			set_sec_offset(pieces, IWL_UCODE_WOWLAN,
+				       IWL_UCODE_SECTION_DATA,
+				       IWLAGN_RTC_DATA_LOWER_BOUND);
+			break;
+		case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE:
+			if (tlv_len != sizeof(u32))
+				goto invalid_tlv_len;
+			capa->standard_phy_calibration_size =
+					le32_to_cpup((__le32 *)tlv_data);
+			break;
+		 case IWL_UCODE_TLV_SEC_RT:
+			iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
+					    tlv_len);
+			drv->fw.mvm_fw = true;
+			break;
+		case IWL_UCODE_TLV_SEC_INIT:
+			iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT,
+					    tlv_len);
+			drv->fw.mvm_fw = true;
+			break;
+		case IWL_UCODE_TLV_SEC_WOWLAN:
+			iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN,
+					    tlv_len);
+			drv->fw.mvm_fw = true;
+			break;
+		case IWL_UCODE_TLV_DEF_CALIB:
+			if (tlv_len != sizeof(struct iwl_tlv_calib_data))
+				goto invalid_tlv_len;
+			if (iwl_set_default_calib(drv, tlv_data))
+				goto tlv_error;
+			break;
+		case IWL_UCODE_TLV_PHY_SKU:
+			if (tlv_len != sizeof(u32))
+				goto invalid_tlv_len;
+			drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data);
+			break;
+		default:
+			IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
+			break;
+		}
+	}
+
+	if (len) {
+		IWL_ERR(drv, "invalid TLV after parsing: %zd\n", len);
+		iwl_print_hex_dump(drv, IWL_DL_FW, (u8 *)data, len);
+		return -EINVAL;
+	}
+
+	return 0;
+
+ invalid_tlv_len:
+	IWL_ERR(drv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
+ tlv_error:
+	iwl_print_hex_dump(drv, IWL_DL_FW, tlv_data, tlv_len);
+
+	return -EINVAL;
+}
+
+static int alloc_pci_desc(struct iwl_drv *drv,
+			  struct iwl_firmware_pieces *pieces,
+			  enum iwl_ucode_type type)
+{
+	int i;
+	for (i = 0;
+	     i < IWL_UCODE_SECTION_MAX && get_sec_size(pieces, type, i);
+	     i++)
+		if (iwl_alloc_fw_desc(drv, &(drv->fw.img[type].sec[i]),
+						get_sec(pieces, type, i)))
+			return -1;
+	return 0;
+}
+
+static int validate_sec_sizes(struct iwl_drv *drv,
+			      struct iwl_firmware_pieces *pieces,
+			      const struct iwl_cfg *cfg)
+{
+	IWL_DEBUG_INFO(drv, "f/w package hdr runtime inst size = %Zd\n",
+		get_sec_size(pieces, IWL_UCODE_REGULAR,
+			     IWL_UCODE_SECTION_INST));
+	IWL_DEBUG_INFO(drv, "f/w package hdr runtime data size = %Zd\n",
+		get_sec_size(pieces, IWL_UCODE_REGULAR,
+			     IWL_UCODE_SECTION_DATA));
+	IWL_DEBUG_INFO(drv, "f/w package hdr init inst size = %Zd\n",
+		get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST));
+	IWL_DEBUG_INFO(drv, "f/w package hdr init data size = %Zd\n",
+		get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA));
+
+	/* Verify that uCode images will fit in card's SRAM. */
+	if (get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST) >
+							cfg->max_inst_size) {
+		IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n",
+			get_sec_size(pieces, IWL_UCODE_REGULAR,
+						IWL_UCODE_SECTION_INST));
+		return -1;
+	}
+
+	if (get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA) >
+							cfg->max_data_size) {
+		IWL_ERR(drv, "uCode data len %Zd too large to fit in\n",
+			get_sec_size(pieces, IWL_UCODE_REGULAR,
+						IWL_UCODE_SECTION_DATA));
+		return -1;
+	}
+
+	 if (get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST) >
+							cfg->max_inst_size) {
+		IWL_ERR(drv, "uCode init instr len %Zd too large to fit in\n",
+			get_sec_size(pieces, IWL_UCODE_INIT,
+						IWL_UCODE_SECTION_INST));
+		return -1;
+	}
+
+	if (get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA) >
+							cfg->max_data_size) {
+		IWL_ERR(drv, "uCode init data len %Zd too large to fit in\n",
+			get_sec_size(pieces, IWL_UCODE_REGULAR,
+						IWL_UCODE_SECTION_DATA));
+		return -1;
+	}
+	return 0;
+}
+
+
+/**
+ * iwl_ucode_callback - callback when firmware was loaded
+ *
+ * If loaded successfully, copies the firmware into buffers
+ * for the card to fetch (via DMA).
+ */
+static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
+{
+	struct iwl_drv *drv = context;
+	const struct iwl_cfg *cfg = cfg(drv);
+	struct iwl_fw *fw = &drv->fw;
+	struct iwl_ucode_header *ucode;
+	int err;
+	struct iwl_firmware_pieces pieces;
+	const unsigned int api_max = cfg->ucode_api_max;
+	unsigned int api_ok = cfg->ucode_api_ok;
+	const unsigned int api_min = cfg->ucode_api_min;
+	u32 api_ver;
+	int i;
+
+	fw->ucode_capa.max_probe_length = 200;
+	fw->ucode_capa.standard_phy_calibration_size =
+			IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+
+	if (!api_ok)
+		api_ok = api_max;
+
+	memset(&pieces, 0, sizeof(pieces));
+
+	if (!ucode_raw) {
+		if (drv->fw_index <= api_ok)
+			IWL_ERR(drv,
+				"request for firmware file '%s' failed.\n",
+				drv->firmware_name);
+		goto try_again;
+	}
+
+	IWL_DEBUG_INFO(drv, "Loaded firmware file '%s' (%zd bytes).\n",
+		       drv->firmware_name, ucode_raw->size);
+
+	/* Make sure that we got at least the API version number */
+	if (ucode_raw->size < 4) {
+		IWL_ERR(drv, "File size way too small!\n");
+		goto try_again;
+	}
+
+	/* Data from ucode file:  header followed by uCode images */
+	ucode = (struct iwl_ucode_header *)ucode_raw->data;
+
+	if (ucode->ver)
+		err = iwl_parse_v1_v2_firmware(drv, ucode_raw, &pieces);
+	else
+		err = iwl_parse_tlv_firmware(drv, ucode_raw, &pieces,
+					   &fw->ucode_capa);
+
+	if (err)
+		goto try_again;
+
+	api_ver = IWL_UCODE_API(drv->fw.ucode_ver);
+
+	/*
+	 * api_ver should match the api version forming part of the
+	 * firmware filename ... but we don't check for that and only rely
+	 * on the API version read from firmware header from here on forward
+	 */
+	/* no api version check required for experimental uCode */
+	if (drv->fw_index != UCODE_EXPERIMENTAL_INDEX) {
+		if (api_ver < api_min || api_ver > api_max) {
+			IWL_ERR(drv,
+				"Driver unable to support your firmware API. "
+				"Driver supports v%u, firmware is v%u.\n",
+				api_max, api_ver);
+			goto try_again;
+		}
+
+		if (api_ver < api_ok) {
+			if (api_ok != api_max)
+				IWL_ERR(drv, "Firmware has old API version, "
+					"expected v%u through v%u, got v%u.\n",
+					api_ok, api_max, api_ver);
+			else
+				IWL_ERR(drv, "Firmware has old API version, "
+					"expected v%u, got v%u.\n",
+					api_max, api_ver);
+			IWL_ERR(drv, "New firmware can be obtained from "
+				      "http://www.intellinuxwireless.org/.\n");
+		}
+	}
+
+	IWL_INFO(drv, "loaded firmware version %s", drv->fw.fw_version);
+
+	/*
+	 * For any of the failures below (before allocating pci memory)
+	 * we will try to load a version with a smaller API -- maybe the
+	 * user just got a corrupted version of the latest API.
+	 */
+
+	IWL_DEBUG_INFO(drv, "f/w package hdr ucode version raw = 0x%x\n",
+		       drv->fw.ucode_ver);
+	IWL_DEBUG_INFO(drv, "f/w package hdr runtime inst size = %Zd\n",
+		get_sec_size(&pieces, IWL_UCODE_REGULAR,
+			     IWL_UCODE_SECTION_INST));
+	IWL_DEBUG_INFO(drv, "f/w package hdr runtime data size = %Zd\n",
+		get_sec_size(&pieces, IWL_UCODE_REGULAR,
+			     IWL_UCODE_SECTION_DATA));
+	IWL_DEBUG_INFO(drv, "f/w package hdr init inst size = %Zd\n",
+		get_sec_size(&pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST));
+	IWL_DEBUG_INFO(drv, "f/w package hdr init data size = %Zd\n",
+		get_sec_size(&pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA));
+
+	/* Verify that uCode images will fit in card's SRAM */
+	if (get_sec_size(&pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST) >
+							cfg->max_inst_size) {
+		IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n",
+			get_sec_size(&pieces, IWL_UCODE_REGULAR,
+				     IWL_UCODE_SECTION_INST));
+		goto try_again;
+	}
+
+	if (get_sec_size(&pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA) >
+							cfg->max_data_size) {
+		IWL_ERR(drv, "uCode data len %Zd too large to fit in\n",
+			get_sec_size(&pieces, IWL_UCODE_REGULAR,
+				     IWL_UCODE_SECTION_DATA));
+		goto try_again;
+	}
+
+	/*
+	 * In mvm uCode there is no difference between data and instructions
+	 * sections.
+	 */
+	if (!fw->mvm_fw && validate_sec_sizes(drv, &pieces, cfg))
+		goto try_again;
+
+	/* Allocate ucode buffers for card's bus-master loading ... */
+
+	/* Runtime instructions and 2 copies of data:
+	 * 1) unmodified from disk
+	 * 2) backup cache for save/restore during power-downs */
+	for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
+		if (alloc_pci_desc(drv, &pieces, i))
+			goto err_pci_alloc;
+
+	/* Now that we can no longer fail, copy information */
+
+	/*
+	 * The (size - 16) / 12 formula is based on the information recorded
+	 * for each event, which is of mode 1 (including timestamp) for all
+	 * new microcodes that include this information.
+	 */
+	fw->init_evtlog_ptr = pieces.init_evtlog_ptr;
+	if (pieces.init_evtlog_size)
+		fw->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
+	else
+		fw->init_evtlog_size =
+			cfg->base_params->max_event_log_size;
+	fw->init_errlog_ptr = pieces.init_errlog_ptr;
+	fw->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
+	if (pieces.inst_evtlog_size)
+		fw->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
+	else
+		fw->inst_evtlog_size =
+			cfg->base_params->max_event_log_size;
+	fw->inst_errlog_ptr = pieces.inst_errlog_ptr;
+
+	/*
+	 * figure out the offset of chain noise reset and gain commands
+	 * base on the size of standard phy calibration commands table size
+	 */
+	if (fw->ucode_capa.standard_phy_calibration_size >
+	    IWL_MAX_PHY_CALIBRATE_TBL_SIZE)
+		fw->ucode_capa.standard_phy_calibration_size =
+			IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+
+	/* We have our copies now, allow OS release its copies */
+	release_firmware(ucode_raw);
+	complete(&drv->request_firmware_complete);
+
+	drv->op_mode = iwl_dvm_ops.start(drv->shrd->trans, &drv->fw);
+
+	if (!drv->op_mode)
+		goto out_unbind;
+
+	return;
+
+ try_again:
+	/* try next, if any */
+	release_firmware(ucode_raw);
+	if (iwl_request_firmware(drv, false))
+		goto out_unbind;
+	return;
+
+ err_pci_alloc:
+	IWL_ERR(drv, "failed to allocate pci memory\n");
+	iwl_dealloc_ucode(drv);
+	release_firmware(ucode_raw);
+ out_unbind:
+	complete(&drv->request_firmware_complete);
+	device_release_driver(trans(drv)->dev);
+}
 
 int iwl_drv_start(struct iwl_shared *shrd,
-		  struct iwl_trans *trans, struct iwl_cfg *cfg)
+		  struct iwl_trans *trans, const struct iwl_cfg *cfg)
 {
+	struct iwl_drv *drv;
 	int ret;
 
 	shrd->cfg = cfg;
 
-	shrd->nic = kzalloc(sizeof(*shrd->nic), GFP_KERNEL);
-	if (!shrd->nic) {
-		dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_nic");
+	drv = kzalloc(sizeof(*drv), GFP_KERNEL);
+	if (!drv) {
+		dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_drv");
 		return -ENOMEM;
 	}
-	shrd->nic->shrd = shrd;
+	drv->shrd = shrd;
+	shrd->drv = drv;
 
-	init_completion(&shrd->nic->request_firmware_complete);
+	init_completion(&drv->request_firmware_complete);
 
-	ret = iwl_request_firmware(shrd->nic, true);
+	ret = iwl_request_firmware(drv, true);
 
 	if (ret) {
 		dev_printk(KERN_ERR, trans->dev, "Couldn't request the fw");
-		kfree(shrd->nic);
+		kfree(drv);
+		shrd->drv = NULL;
 	}
 
 	return ret;
@@ -95,9 +978,16 @@
 
 void iwl_drv_stop(struct iwl_shared *shrd)
 {
-	/* op_mode can be NULL if its start failed */
-	if (shrd->nic->op_mode)
-		iwl_op_mode_stop(shrd->nic->op_mode);
+	struct iwl_drv *drv = shrd->drv;
 
-	kfree(shrd->nic);
+	wait_for_completion(&drv->request_firmware_complete);
+
+	/* op_mode can be NULL if its start failed */
+	if (drv->op_mode)
+		iwl_op_mode_stop(drv->op_mode);
+
+	iwl_dealloc_ucode(drv);
+
+	kfree(drv);
+	shrd->drv = NULL;
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h
index 90534a2..3b771c1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.h
@@ -105,7 +105,7 @@
  * function.
  */
 int iwl_drv_start(struct iwl_shared *shrd,
-		  struct iwl_trans *trans, struct iwl_cfg *cfg);
+		  struct iwl_trans *trans, const struct iwl_cfg *cfg);
 
 /**
  * iwl_drv_stop - stop the drv
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 07e93787..23cea42 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -75,6 +75,7 @@
 #include "iwl-agn.h"
 #include "iwl-eeprom.h"
 #include "iwl-io.h"
+#include "iwl-prph.h"
 
 /************************** EEPROM BANDS ****************************
  *
@@ -252,46 +253,46 @@
 
 }
 
-int iwl_eeprom_check_sku(struct iwl_priv *priv)
+int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
 {
 	struct iwl_shared *shrd = priv->shrd;
 	u16 radio_cfg;
 
-	if (!cfg(priv)->sku) {
-		/* not using sku overwrite */
-		cfg(priv)->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
-		if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE &&
-		    !cfg(priv)->ht_params) {
-			IWL_ERR(priv, "Invalid 11n configuration\n");
-			return -EINVAL;
-		}
+	hw_params(priv).sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
+	if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE &&
+	    !cfg(priv)->ht_params) {
+		IWL_ERR(priv, "Invalid 11n configuration\n");
+		return -EINVAL;
 	}
-	if (!cfg(priv)->sku) {
+
+	if (!hw_params(priv).sku) {
 		IWL_ERR(priv, "Invalid device sku\n");
 		return -EINVAL;
 	}
 
-	IWL_INFO(priv, "Device SKU: 0x%X\n", cfg(priv)->sku);
+	IWL_INFO(priv, "Device SKU: 0x%X\n", hw_params(priv).sku);
 
-	if (!cfg(priv)->valid_tx_ant && !cfg(priv)->valid_rx_ant) {
-		/* not using .cfg overwrite */
-		radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
-		cfg(priv)->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
-		cfg(priv)->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
-		if (!cfg(priv)->valid_tx_ant || !cfg(priv)->valid_rx_ant) {
-			IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n",
-				cfg(priv)->valid_tx_ant,
-				cfg(priv)->valid_rx_ant);
-			return -EINVAL;
-		}
-		IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
-			 cfg(priv)->valid_tx_ant, cfg(priv)->valid_rx_ant);
+	radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
+
+	hw_params(priv).valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
+	hw_params(priv).valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
+
+	/* check overrides (some devices have wrong EEPROM) */
+	if (cfg(priv)->valid_tx_ant)
+		hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
+	if (cfg(priv)->valid_rx_ant)
+		hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
+
+	if (!hw_params(priv).valid_tx_ant || !hw_params(priv).valid_rx_ant) {
+		IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n",
+			hw_params(priv).valid_tx_ant,
+			hw_params(priv).valid_rx_ant);
+		return -EINVAL;
 	}
-	/*
-	 * for some special cases,
-	 * EEPROM did not reflect the correct antenna setting
-	 * so overwrite the valid tx/rx antenna from .cfg
-	 */
+
+	IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
+		 hw_params(priv).valid_tx_ant, hw_params(priv).valid_rx_ant);
+
 	return 0;
 }
 
@@ -512,7 +513,7 @@
  * iwl_get_max_txpower_avg - get the highest tx power from all chains.
  *     find the highest tx power from all chains for the channel
  */
-static s8 iwl_get_max_txpower_avg(struct iwl_cfg *cfg,
+static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg,
 		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
 		int element, s8 *max_txpower_in_half_dbm)
 {
@@ -588,7 +589,7 @@
 #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
 			    ? # x " " : "")
 
-void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
+static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
 {
 	struct iwl_shared *shrd = priv->shrd;
 	struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
@@ -1024,8 +1025,8 @@
 	 * driver need to process addition information
 	 * to determine the max channel tx power limits
 	 */
-	if (cfg(priv)->lib->eeprom_ops.update_enhanced_txpower)
-		cfg(priv)->lib->eeprom_ops.update_enhanced_txpower(priv);
+	if (cfg(priv)->lib->eeprom_ops.enhanced_txpower)
+		iwl_eeprom_enhanced_txpower(priv);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index cbb8611..e4a7583 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -302,14 +302,14 @@
 
 struct iwl_eeprom_ops {
 	const u32 regulatory_bands[7];
-	void (*update_enhanced_txpower) (struct iwl_priv *priv);
+	bool enhanced_txpower;
 };
 
 
 int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev);
 void iwl_eeprom_free(struct iwl_shared *shrd);
 int  iwl_eeprom_check_version(struct iwl_priv *priv);
-int  iwl_eeprom_check_sku(struct iwl_priv *priv);
+int iwl_eeprom_init_hw_params(struct iwl_priv *priv);
 const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset);
 u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset);
 int iwl_init_channel_map(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
similarity index 76%
rename from drivers/net/wireless/iwlwifi/iwl-ucode.h
rename to drivers/net/wireless/iwlwifi/iwl-fw-file.h
index 8bebeb0..c924ccb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-ucode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
@@ -60,8 +60,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
-#ifndef __iwl_ucode_h__
-#define __iwl_ucode_h__
+#ifndef __iwl_fw_file_h__
+#define __iwl_fw_file_h__
 
 #include <linux/netdevice.h>
 
@@ -124,22 +124,11 @@
 	IWL_UCODE_TLV_WOWLAN_INST	= 16,
 	IWL_UCODE_TLV_WOWLAN_DATA	= 17,
 	IWL_UCODE_TLV_FLAGS		= 18,
-};
-
-/**
- * enum iwl_ucode_tlv_flag - ucode API flags
- * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
- *	was a separate TLV but moved here to save space.
- * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
- *	treats good CRC threshold as a boolean
- * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
- * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
- */
-enum iwl_ucode_tlv_flag {
-	IWL_UCODE_TLV_FLAGS_PAN		= BIT(0),
-	IWL_UCODE_TLV_FLAGS_NEWSCAN	= BIT(1),
-	IWL_UCODE_TLV_FLAGS_MFP		= BIT(2),
-	IWL_UCODE_TLV_FLAGS_P2P		= BIT(3),
+	IWL_UCODE_TLV_SEC_RT		= 19,
+	IWL_UCODE_TLV_SEC_INIT		= 20,
+	IWL_UCODE_TLV_SEC_WOWLAN	= 21,
+	IWL_UCODE_TLV_DEF_CALIB		= 22,
+	IWL_UCODE_TLV_PHY_SKU		= 23,
 };
 
 struct iwl_ucode_tlv {
@@ -173,48 +162,4 @@
 	u8 data[0];
 };
 
-struct iwl_ucode_capabilities {
-	u32 max_probe_length;
-	u32 standard_phy_calibration_size;
-	u32 flags;
-};
-
-/* one for each uCode image (inst/data, boot/init/runtime) */
-struct fw_desc {
-	dma_addr_t p_addr;	/* hardware address */
-	void *v_addr;		/* software address */
-	u32 len;		/* size in bytes */
-};
-
-struct fw_img {
-	struct fw_desc code;	/* firmware code image */
-	struct fw_desc data;	/* firmware data image */
-};
-
-/**
- * struct iwl_fw - variables associated with the firmware
- *
- * @ucode_ver: ucode version from the ucode file
- * @fw_version: firmware version string
- * @ucode_rt: run time ucode image
- * @ucode_init: init ucode image
- * @ucode_wowlan: wake on wireless ucode image (optional)
- * @ucode_capa: capabilities parsed from the ucode file.
- * @enhance_sensitivity_table: device can do enhanced sensitivity.
- */
-struct iwl_fw {
-
-	u32 ucode_ver;
-
-	char fw_version[ETHTOOL_BUSINFO_LEN];
-
-	/* ucode images */
-	struct fw_img ucode_rt;
-	struct fw_img ucode_init;
-	struct fw_img ucode_wowlan;
-
-	struct iwl_ucode_capabilities ucode_capa;
-	bool enhance_sensitivity_table;
-};
-
-#endif  /* __iwl_ucode_h__ */
+#endif  /* __iwl_fw_file_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
new file mode 100644
index 0000000..8e36bdc
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -0,0 +1,177 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef __iwl_fw_h__
+#define __iwl_fw_h__
+#include <linux/types.h>
+
+/**
+ * enum iwl_ucode_tlv_flag - ucode API flags
+ * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
+ *	was a separate TLV but moved here to save space.
+ * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
+ *	treats good CRC threshold as a boolean
+ * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
+ * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
+ */
+enum iwl_ucode_tlv_flag {
+	IWL_UCODE_TLV_FLAGS_PAN		= BIT(0),
+	IWL_UCODE_TLV_FLAGS_NEWSCAN	= BIT(1),
+	IWL_UCODE_TLV_FLAGS_MFP		= BIT(2),
+	IWL_UCODE_TLV_FLAGS_P2P		= BIT(3),
+};
+
+/* The default calibrate table size if not specified by firmware file */
+#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE	18
+#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE		19
+#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE			253
+
+/**
+ * enum iwl_ucode_type
+ *
+ * The type of ucode.
+ *
+ * @IWL_UCODE_REGULAR: Normal runtime ucode
+ * @IWL_UCODE_INIT: Initial ucode
+ * @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode
+ */
+enum iwl_ucode_type {
+	IWL_UCODE_REGULAR,
+	IWL_UCODE_INIT,
+	IWL_UCODE_WOWLAN,
+	IWL_UCODE_TYPE_MAX,
+};
+
+/*
+ * enumeration of ucode section.
+ * This enumeration is used for legacy tlv style (before 16.0 uCode).
+ */
+enum iwl_ucode_sec {
+	IWL_UCODE_SECTION_INST,
+	IWL_UCODE_SECTION_DATA,
+};
+/*
+ * For 16.0 uCode and above, there is no differentiation between sections,
+ * just an offset to the HW address.
+ */
+#define IWL_UCODE_SECTION_MAX 4
+
+struct iwl_ucode_capabilities {
+	u32 max_probe_length;
+	u32 standard_phy_calibration_size;
+	u32 flags;
+};
+
+/* one for each uCode image (inst/data, init/runtime/wowlan) */
+struct fw_desc {
+	dma_addr_t p_addr;	/* hardware address */
+	void *v_addr;		/* software address */
+	u32 len;		/* size in bytes */
+	u32 offset;		/* offset in the device */
+};
+
+struct fw_img {
+	struct fw_desc sec[IWL_UCODE_SECTION_MAX];
+};
+
+/* uCode version contains 4 values: Major/Minor/API/Serial */
+#define IWL_UCODE_MAJOR(ver)	(((ver) & 0xFF000000) >> 24)
+#define IWL_UCODE_MINOR(ver)	(((ver) & 0x00FF0000) >> 16)
+#define IWL_UCODE_API(ver)	(((ver) & 0x0000FF00) >> 8)
+#define IWL_UCODE_SERIAL(ver)	((ver) & 0x000000FF)
+
+/**
+ * struct iwl_fw - variables associated with the firmware
+ *
+ * @ucode_ver: ucode version from the ucode file
+ * @fw_version: firmware version string
+ * @img: ucode image like ucode_rt, ucode_init, ucode_wowlan.
+ * @ucode_capa: capabilities parsed from the ucode file.
+ * @enhance_sensitivity_table: device can do enhanced sensitivity.
+ * @init_evtlog_ptr: event log offset for init ucode.
+ * @init_evtlog_size: event log size for init ucode.
+ * @init_errlog_ptr: error log offfset for init ucode.
+ * @inst_evtlog_ptr: event log offset for runtime ucode.
+ * @inst_evtlog_size: event log size for runtime ucode.
+ * @inst_errlog_ptr: error log offfset for runtime ucode.
+ */
+struct iwl_fw {
+	u32 ucode_ver;
+
+	char fw_version[ETHTOOL_BUSINFO_LEN];
+
+	/* ucode images */
+	struct fw_img img[IWL_UCODE_TYPE_MAX];
+
+	struct iwl_ucode_capabilities ucode_capa;
+	bool enhance_sensitivity_table;
+
+	u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
+	u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
+
+	u64 default_calib[IWL_UCODE_TYPE_MAX];
+	u32 phy_config;
+
+	bool mvm_fw;
+};
+
+#endif  /* __iwl_fw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index e2e3b5c..081dd34 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -118,16 +118,17 @@
 	return 0;
 }
 
-int iwl_grab_nic_access(struct iwl_trans *trans)
+bool iwl_grab_nic_access(struct iwl_trans *trans)
 {
 	int ret = iwl_grab_nic_access_silent(trans);
-	if (ret) {
+	if (unlikely(ret)) {
 		u32 val = iwl_read32(trans, CSR_GP_CNTRL);
-		IWL_ERR(trans,
-			"MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val);
+		WARN_ONCE(1, "Timeout waiting for hardware access "
+			     "(CSR_GP_CNTRL 0x%08x)\n", val);
+		return false;
 	}
 
-	return ret;
+	return true;
 }
 
 void iwl_release_nic_access(struct iwl_trans *trans)
@@ -135,6 +136,13 @@
 	lockdep_assert_held(&trans->reg_lock);
 	__iwl_clear_bit(trans, CSR_GP_CNTRL,
 			CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+	/*
+	 * Above we read the CSR_GP_CNTRL register, which will flush
+	 * any previous writes, but we need the write that clears the
+	 * MAC_ACCESS_REQ bit to be performed before any other writes
+	 * scheduled on different CPUs (after we drop reg_lock).
+	 */
+	mmiowb();
 }
 
 u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
@@ -156,7 +164,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&trans->reg_lock, flags);
-	if (!iwl_grab_nic_access(trans)) {
+	if (likely(iwl_grab_nic_access(trans))) {
 		iwl_write32(trans, reg, value);
 		iwl_release_nic_access(trans);
 	}
@@ -181,7 +189,6 @@
 static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg)
 {
 	iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
-	rmb();
 	return iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
 }
 
@@ -189,7 +196,6 @@
 {
 	iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
 		    ((addr & 0x0000FFFF) | (3 << 24)));
-	wmb();
 	iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
 }
 
@@ -211,7 +217,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&trans->reg_lock, flags);
-	if (!iwl_grab_nic_access(trans)) {
+	if (likely(iwl_grab_nic_access(trans))) {
 		__iwl_write_prph(trans, addr, val);
 		iwl_release_nic_access(trans);
 	}
@@ -223,9 +229,11 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&trans->reg_lock, flags);
-	iwl_grab_nic_access(trans);
-	__iwl_write_prph(trans, reg, __iwl_read_prph(trans, reg) | mask);
-	iwl_release_nic_access(trans);
+	if (likely(iwl_grab_nic_access(trans))) {
+		__iwl_write_prph(trans, reg,
+				 __iwl_read_prph(trans, reg) | mask);
+		iwl_release_nic_access(trans);
+	}
 	spin_unlock_irqrestore(&trans->reg_lock, flags);
 }
 
@@ -235,10 +243,11 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&trans->reg_lock, flags);
-	iwl_grab_nic_access(trans);
-	__iwl_write_prph(trans, reg,
-			 (__iwl_read_prph(trans, reg) & mask) | bits);
-	iwl_release_nic_access(trans);
+	if (likely(iwl_grab_nic_access(trans))) {
+		__iwl_write_prph(trans, reg,
+				 (__iwl_read_prph(trans, reg) & mask) | bits);
+		iwl_release_nic_access(trans);
+	}
 	spin_unlock_irqrestore(&trans->reg_lock, flags);
 }
 
@@ -248,10 +257,11 @@
 	u32 val;
 
 	spin_lock_irqsave(&trans->reg_lock, flags);
-	iwl_grab_nic_access(trans);
-	val = __iwl_read_prph(trans, reg);
-	__iwl_write_prph(trans, reg, (val & ~mask));
-	iwl_release_nic_access(trans);
+	if (likely(iwl_grab_nic_access(trans))) {
+		val = __iwl_read_prph(trans, reg);
+		__iwl_write_prph(trans, reg, (val & ~mask));
+		iwl_release_nic_access(trans);
+	}
 	spin_unlock_irqrestore(&trans->reg_lock, flags);
 }
 
@@ -263,15 +273,12 @@
 	u32 *vals = buf;
 
 	spin_lock_irqsave(&trans->reg_lock, flags);
-	iwl_grab_nic_access(trans);
-
-	iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
-	rmb();
-
-	for (offs = 0; offs < words; offs++)
-		vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
-
-	iwl_release_nic_access(trans);
+	if (likely(iwl_grab_nic_access(trans))) {
+		iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
+		for (offs = 0; offs < words; offs++)
+			vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
+		iwl_release_nic_access(trans);
+	}
 	spin_unlock_irqrestore(&trans->reg_lock, flags);
 }
 
@@ -292,10 +299,8 @@
 	u32 *vals = buf;
 
 	spin_lock_irqsave(&trans->reg_lock, flags);
-	if (!iwl_grab_nic_access(trans)) {
+	if (likely(iwl_grab_nic_access(trans))) {
 		iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
-		wmb();
-
 		for (offs = 0; offs < words; offs++)
 			iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]);
 		iwl_release_nic_access(trans);
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 782486f..09b8567 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -35,20 +35,20 @@
 
 static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
 {
-	trace_iwlwifi_dev_iowrite8(priv(trans), ofs, val);
+	trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
 	iwl_trans_write8(trans, ofs, val);
 }
 
 static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val)
 {
-	trace_iwlwifi_dev_iowrite32(priv(trans), ofs, val);
+	trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val);
 	iwl_trans_write32(trans, ofs, val);
 }
 
 static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
 {
 	u32 val = iwl_trans_read32(trans, ofs);
-	trace_iwlwifi_dev_ioread32(priv(trans), ofs, val);
+	trace_iwlwifi_dev_ioread32(trans->dev, ofs, val);
 	return val;
 }
 
@@ -61,7 +61,7 @@
 			int timeout);
 
 int iwl_grab_nic_access_silent(struct iwl_trans *trans);
-int iwl_grab_nic_access(struct iwl_trans *trans);
+bool iwl_grab_nic_access(struct iwl_trans *trans);
 void iwl_release_nic_access(struct iwl_trans *trans);
 
 u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 5c7741f..1993a2b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -112,7 +112,7 @@
 		iwl_write32(trans(priv), CSR_LED_REG,
 			    reg & CSR_LED_BSM_CTRL_MSK);
 
-	return iwl_trans_send_cmd(trans(priv), &cmd);
+	return iwl_dvm_send_cmd(priv, &cmd);
 }
 
 /* Set led pattern command */
@@ -126,7 +126,7 @@
 	};
 	int ret;
 
-	if (!test_bit(STATUS_READY, &priv->shrd->status))
+	if (!test_bit(STATUS_READY, &priv->status))
 		return -EBUSY;
 
 	if (priv->blink_on == on && priv->blink_off == off)
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
index 03f7705..b6805f8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c
+++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
@@ -42,9 +42,7 @@
 
 #include <asm/div64.h>
 
-#include "iwl-ucode.h"
 #include "iwl-eeprom.h"
-#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
@@ -136,7 +134,7 @@
  * other mac80211 functions grouped here.
  */
 int iwlagn_mac_setup_register(struct iwl_priv *priv,
-				  struct iwl_ucode_capabilities *capa)
+			      const struct iwl_ucode_capabilities *capa)
 {
 	int ret;
 	struct ieee80211_hw *hw = priv->hw;
@@ -161,11 +159,14 @@
 	hw->flags |= IEEE80211_HW_SUPPORTS_PS |
 		     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
-	if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
+	if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
 		hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
 			     IEEE80211_HW_SUPPORTS_STATIC_SMPS;
 
+#ifndef CONFIG_IWLWIFI_EXPERIMENTAL_MFP
+	/* enable 11w if the uCode advertise */
 	if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP)
+#endif /* !CONFIG_IWLWIFI_EXPERIMENTAL_MFP */
 		hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
 	hw->sta_data_size = sizeof(struct iwl_station_priv);
@@ -195,7 +196,8 @@
 			    WIPHY_FLAG_DISABLE_BEACON_HINTS |
 			    WIPHY_FLAG_IBSS_RSN;
 
-	if (nic(priv)->fw.ucode_wowlan.code.len &&
+	if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
+	    trans(priv)->ops->wowlan_suspend &&
 	    device_can_wakeup(trans(priv)->dev)) {
 		hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
 					  WIPHY_WOWLAN_DISCONNECT |
@@ -262,9 +264,9 @@
 	struct iwl_rxon_context *ctx;
 	int ret;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
 		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
 		return -EIO;
 	}
@@ -277,13 +279,13 @@
 		}
 	}
 
-	ret = iwl_run_init_ucode(trans(priv));
+	ret = iwl_run_init_ucode(priv);
 	if (ret) {
 		IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret);
 		goto error;
 	}
 
-	ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_REGULAR);
+	ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
 	if (ret) {
 		IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
 		goto error;
@@ -295,9 +297,9 @@
 	return 0;
 
  error:
-	set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
+	set_bit(STATUS_EXIT_PENDING, &priv->status);
 	iwl_down(priv);
-	clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
+	clear_bit(STATUS_EXIT_PENDING, &priv->status);
 
 	IWL_ERR(priv, "Unable to initialize device.\n");
 	return ret;
@@ -311,16 +313,16 @@
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
 	/* we should be verifying the device is ready to be opened */
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	ret = __iwl_up(priv);
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	if (ret)
 		return ret;
 
 	IWL_DEBUG_INFO(priv, "Start UP work done.\n");
 
 	/* Now we should be done, and the READY bit should be set. */
-	if (WARN_ON(!test_bit(STATUS_READY, &priv->shrd->status)))
+	if (WARN_ON(!test_bit(STATUS_READY, &priv->status)))
 		ret = -EIO;
 
 	iwlagn_led_enable(priv);
@@ -341,9 +343,9 @@
 
 	priv->is_open = 0;
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	iwl_down(priv);
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 
 	iwl_cancel_deferred_work(priv);
 
@@ -368,7 +370,7 @@
 		return;
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif)
 		goto out;
@@ -380,7 +382,7 @@
 	priv->have_rekey_data = true;
 
  out:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
@@ -397,7 +399,7 @@
 		return -EINVAL;
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	/* Don't attempt WoWLAN when not associated, tear down instead. */
 	if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION ||
@@ -406,24 +408,22 @@
 		goto out;
 	}
 
-	ret = iwlagn_suspend(priv, hw, wowlan);
+	ret = iwlagn_suspend(priv, wowlan);
 	if (ret)
 		goto error;
 
 	device_set_wakeup_enable(trans(priv)->dev, true);
 
-	/* Now let the ucode operate on its own */
-	iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET,
-			  CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
+	iwl_trans_wowlan_suspend(trans(priv));
 
 	goto out;
 
  error:
-	priv->shrd->wowlan = false;
+	priv->wowlan = false;
 	iwlagn_prepare_restart(priv);
 	ieee80211_restart_hw(priv->hw);
  out:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 	return ret;
@@ -437,9 +437,10 @@
 	unsigned long flags;
 	u32 base, status = 0xffffffff;
 	int ret = -EIO;
+	const struct fw_img *img;
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR,
 			  CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
@@ -448,7 +449,7 @@
 	if (iwlagn_hw_valid_rtc_data_addr(base)) {
 		spin_lock_irqsave(&trans(priv)->reg_lock, flags);
 		ret = iwl_grab_nic_access_silent(trans(priv));
-		if (ret == 0) {
+		if (likely(ret == 0)) {
 			iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, base);
 			status = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
 			iwl_release_nic_access(trans(priv));
@@ -457,17 +458,18 @@
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 		if (ret == 0) {
-			struct iwl_nic *nic = nic(priv);
-			if (!priv->wowlan_sram)
+			img = &(priv->fw->img[IWL_UCODE_WOWLAN]);
+			if (!priv->wowlan_sram) {
 				priv->wowlan_sram =
-					kzalloc(nic->fw.ucode_wowlan.data.len,
+				   kzalloc(img->sec[IWL_UCODE_SECTION_DATA].len,
 						GFP_KERNEL);
+			}
 
 			if (priv->wowlan_sram)
 				_iwl_read_targ_mem_words(
-					trans(priv), 0x800000,
-					priv->wowlan_sram,
-					nic->fw.ucode_wowlan.data.len / 4);
+				      trans(priv), 0x800000,
+				      priv->wowlan_sram,
+				      img->sec[IWL_UCODE_SECTION_DATA].len / 4);
 		}
 #endif
 	}
@@ -475,7 +477,7 @@
 	/* we'll clear ctx->vif during iwlagn_prepare_restart() */
 	vif = ctx->vif;
 
-	priv->shrd->wowlan = false;
+	priv->wowlan = false;
 
 	device_set_wakeup_enable(trans(priv)->dev, false);
 
@@ -485,7 +487,7 @@
 	iwl_connection_init_rx_config(priv, ctx);
 	iwlagn_set_rxon_chain(priv, ctx);
 
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 	ieee80211_resume_disconnect(vif);
@@ -563,7 +565,7 @@
 	if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET)
 		return 0;
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	iwl_scan_cancel_timeout(priv, 100);
 
 	BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT);
@@ -614,7 +616,7 @@
 		ret = -EINVAL;
 	}
 
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 	return ret;
@@ -633,11 +635,11 @@
 	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
 		     sta->addr, tid);
 
-	if (!(cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE))
+	if (!(hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE))
 		return -EACCES;
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
@@ -649,8 +651,6 @@
 	case IEEE80211_AMPDU_RX_STOP:
 		IWL_DEBUG_HT(priv, "stop Rx\n");
 		ret = iwl_sta_rx_agg_stop(priv, sta, tid);
-		if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
-			ret = 0;
 		break;
 	case IEEE80211_AMPDU_TX_START:
 		if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
@@ -666,10 +666,8 @@
 			IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
 				     priv->agg_tids_count);
 		}
-		if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
-			ret = 0;
-		if (!priv->agg_tids_count && cfg(priv)->ht_params &&
-		    cfg(priv)->ht_params->use_rts_for_aggregation) {
+		if (!priv->agg_tids_count &&
+		    hw_params(priv).use_rts_for_aggregation) {
 			/*
 			 * switch off RTS/CTS if it was previously enabled
 			 */
@@ -683,7 +681,7 @@
 		ret = iwlagn_tx_agg_oper(priv, vif, sta, tid, buf_size);
 		break;
 	}
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	return ret;
 }
@@ -696,12 +694,9 @@
 	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 	bool is_ap = vif->type == NL80211_IFTYPE_STATION;
-	int ret = 0;
+	int ret;
 	u8 sta_id;
 
-	IWL_DEBUG_MAC80211(priv, "received request to add station %pM\n",
-			sta->addr);
-	mutex_lock(&priv->shrd->mutex);
 	IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
 			sta->addr);
 	sta_priv->sta_id = IWL_INVALID_STATION;
@@ -716,17 +711,119 @@
 		IWL_ERR(priv, "Unable to add station %pM (%d)\n",
 			sta->addr, ret);
 		/* Should we return success if return code is EEXIST ? */
-		goto out;
+		return ret;
 	}
 
 	sta_priv->sta_id = sta_id;
 
-	/* Initialize rate scaling */
-	IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
-		       sta->addr);
-	iwl_rs_rate_init(priv, sta, sta_id);
- out:
-	mutex_unlock(&priv->shrd->mutex);
+	return 0;
+}
+
+static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
+				 struct ieee80211_vif *vif,
+				 struct ieee80211_sta *sta)
+{
+	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	int ret;
+
+	IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", sta->addr);
+
+	if (vif->type == NL80211_IFTYPE_STATION) {
+		/*
+		 * Station will be removed from device when the RXON
+		 * is set to unassociated -- just deactivate it here
+		 * to avoid re-programming it.
+		 */
+		ret = 0;
+		iwl_deactivate_station(priv, sta_priv->sta_id, sta->addr);
+	} else {
+		ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr);
+		if (ret)
+			IWL_DEBUG_QUIET_RFKILL(priv,
+				"Error removing station %pM\n", sta->addr);
+	}
+	return ret;
+}
+
+static int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_sta *sta,
+				enum ieee80211_sta_state old_state,
+				enum ieee80211_sta_state new_state)
+{
+	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	enum {
+		NONE, ADD, REMOVE, HT_RATE_INIT, ADD_RATE_INIT,
+	} op = NONE;
+	int ret;
+
+	IWL_DEBUG_MAC80211(priv, "station %pM state change %d->%d\n",
+			   sta->addr, old_state, new_state);
+
+	mutex_lock(&priv->mutex);
+	if (vif->type == NL80211_IFTYPE_STATION) {
+		if (old_state == IEEE80211_STA_NOTEXIST &&
+		    new_state == IEEE80211_STA_NONE)
+			op = ADD;
+		else if (old_state == IEEE80211_STA_NONE &&
+			 new_state == IEEE80211_STA_NOTEXIST)
+			op = REMOVE;
+		else if (old_state == IEEE80211_STA_AUTH &&
+			 new_state == IEEE80211_STA_ASSOC)
+			op = HT_RATE_INIT;
+	} else {
+		if (old_state == IEEE80211_STA_AUTH &&
+		    new_state == IEEE80211_STA_ASSOC)
+			op = ADD_RATE_INIT;
+		else if (old_state == IEEE80211_STA_ASSOC &&
+			 new_state == IEEE80211_STA_AUTH)
+			op = REMOVE;
+	}
+
+	switch (op) {
+	case ADD:
+		ret = iwlagn_mac_sta_add(hw, vif, sta);
+		break;
+	case REMOVE:
+		ret = iwlagn_mac_sta_remove(hw, vif, sta);
+		break;
+	case ADD_RATE_INIT:
+		ret = iwlagn_mac_sta_add(hw, vif, sta);
+		if (ret)
+			break;
+		/* Initialize rate scaling */
+		IWL_DEBUG_INFO(priv,
+			       "Initializing rate scaling for station %pM\n",
+			       sta->addr);
+		iwl_rs_rate_init(priv, sta, iwl_sta_id(sta));
+		ret = 0;
+		break;
+	case HT_RATE_INIT:
+		/* Initialize rate scaling */
+		ret = iwl_sta_update_ht(priv, vif_priv->ctx, sta);
+		if (ret)
+			break;
+		IWL_DEBUG_INFO(priv,
+			       "Initializing rate scaling for station %pM\n",
+			       sta->addr);
+		iwl_rs_rate_init(priv, sta, iwl_sta_id(sta));
+		ret = 0;
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+
+	/*
+	 * mac80211 might WARN if we fail, but due the way we
+	 * (badly) handle hard rfkill, we might fail here
+	 */
+	if (iwl_is_rfkill(priv))
+		ret = 0;
+
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 	return ret;
@@ -753,14 +850,14 @@
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
-	if (iwl_is_rfkill(priv->shrd))
+	if (iwl_is_rfkill(priv))
 		goto out;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) ||
-	    test_bit(STATUS_SCANNING, &priv->shrd->status) ||
-	    test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+	    test_bit(STATUS_SCANNING, &priv->status) ||
+	    test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
 		goto out;
 
 	if (!iwl_is_associated_ctx(ctx))
@@ -779,8 +876,6 @@
 		goto out;
 	}
 
-	spin_lock_irq(&priv->shrd->lock);
-
 	priv->current_ht_config.smps = conf->smps_mode;
 
 	/* Configure HT40 channels */
@@ -797,23 +892,21 @@
 	iwl_set_rxon_ht(priv, ht_conf);
 	iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
 
-	spin_unlock_irq(&priv->shrd->lock);
-
 	iwl_set_rate(priv);
 	/*
 	 * at this point, staging_rxon has the
 	 * configuration for channel switch
 	 */
-	set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
+	set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
 	priv->switch_channel = cpu_to_le16(ch);
 	if (cfg(priv)->lib->set_channel_switch(priv, ch_switch)) {
-		clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
+		clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
 		priv->switch_channel = 0;
 		ieee80211_chswitch_done(ctx->vif, false);
 	}
 
 out:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
@@ -843,7 +936,7 @@
 
 #undef CHK
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	for_each_context(priv, ctx) {
 		ctx->staging.filter_flags &= ~filter_nand;
@@ -855,7 +948,7 @@
 		 */
 	}
 
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 
 	/*
 	 * Receiving all multicast frames is always enabled by the
@@ -871,14 +964,14 @@
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
 		IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
 		goto done;
 	}
-	if (iwl_is_rfkill(priv->shrd)) {
+	if (iwl_is_rfkill(priv)) {
 		IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n");
 		goto done;
 	}
@@ -897,7 +990,7 @@
 	IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
 	iwl_trans_wait_tx_queue_empty(trans(priv));
 done:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
@@ -917,9 +1010,9 @@
 		return -EOPNOTSUPP;
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
-	if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
+	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
 		err = -EBUSY;
 		goto out;
 	}
@@ -988,7 +1081,7 @@
 		iwlagn_disable_roc(priv);
 
  out:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 	return err;
@@ -1002,102 +1095,22 @@
 		return -EOPNOTSUPP;
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	iwl_scan_cancel_timeout(priv, priv->hw_roc_duration);
 	iwlagn_disable_roc(priv);
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 	return 0;
 }
 
-static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw,
-			      struct ieee80211_vif *vif,
-			      const u8 *bssid,
-			      enum ieee80211_tx_sync_type type)
-{
-	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
-	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-	struct iwl_rxon_context *ctx = vif_priv->ctx;
-	int ret;
-	u8 sta_id;
-
-	if (ctx->ctxid != IWL_RXON_CTX_PAN)
-		return 0;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->shrd->mutex);
-
-	if (iwl_is_associated_ctx(ctx)) {
-		ret = 0;
-		goto out;
-	}
-
-	if (ctx->preauth_bssid || test_bit(STATUS_SCAN_HW,
-	    &priv->shrd->status)) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	ret = iwl_add_station_common(priv, ctx, bssid, true, NULL, &sta_id);
-	if (ret)
-		goto out;
-
-	if (WARN_ON(sta_id != ctx->ap_sta_id)) {
-		ret = -EIO;
-		goto out_remove_sta;
-	}
-
-	memcpy(ctx->bssid, bssid, ETH_ALEN);
-	ctx->preauth_bssid = true;
-
-	ret = iwlagn_commit_rxon(priv, ctx);
-
-	if (ret == 0)
-		goto out;
-
- out_remove_sta:
-	iwl_remove_station(priv, sta_id, bssid);
- out:
-	mutex_unlock(&priv->shrd->mutex);
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-	return ret;
-}
-
-static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif,
-				   const u8 *bssid,
-				   enum ieee80211_tx_sync_type type)
-{
-	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
-	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-	struct iwl_rxon_context *ctx = vif_priv->ctx;
-
-	if (ctx->ctxid != IWL_RXON_CTX_PAN)
-		return;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->shrd->mutex);
-
-	if (iwl_is_associated_ctx(ctx))
-		goto out;
-
-	iwl_remove_station(priv, ctx->ap_sta_id, bssid);
-	ctx->preauth_bssid = false;
-	/* no need to commit */
- out:
-	mutex_unlock(&priv->shrd->mutex);
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
 static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
 			   enum ieee80211_rssi_event rssi_event)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	if (cfg(priv)->bt_params &&
 			cfg(priv)->bt_params->advanced_bt_coexist) {
@@ -1112,7 +1125,7 @@
 				"ignoring RSSI callback\n");
 	}
 
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
@@ -1133,7 +1146,6 @@
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 	struct iwl_rxon_context *ctx = vif_priv->ctx;
-	unsigned long flags;
 	int q;
 
 	if (WARN_ON(!ctx))
@@ -1141,7 +1153,7 @@
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
-	if (!iwl_is_ready_rf(priv->shrd)) {
+	if (!iwl_is_ready_rf(priv)) {
 		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
 		return -EIO;
 	}
@@ -1153,7 +1165,7 @@
 
 	q = AC_NUM - 1 - queue;
 
-	spin_lock_irqsave(&priv->shrd->lock, flags);
+	mutex_lock(&priv->mutex);
 
 	ctx->qos_data.def_qos_parm.ac[q].cw_min =
 		cpu_to_le16(params->cw_min);
@@ -1165,7 +1177,7 @@
 
 	ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
 
-	spin_unlock_irqrestore(&priv->shrd->lock, flags);
+	mutex_unlock(&priv->mutex);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	return 0;
@@ -1193,7 +1205,7 @@
 	struct ieee80211_vif *vif = ctx->vif;
 	int err;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	/*
 	 * This variable will be correct only when there's just
@@ -1238,11 +1250,11 @@
 
 	cancel_delayed_work_sync(&priv->hw_roc_disable_work);
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	iwlagn_disable_roc(priv);
 
-	if (!iwl_is_ready_rf(priv->shrd)) {
+	if (!iwl_is_ready_rf(priv)) {
 		IWL_WARN(priv, "Try to add interface when device not ready\n");
 		err = -EINVAL;
 		goto out;
@@ -1285,7 +1297,7 @@
 	ctx->vif = NULL;
 	priv->iw_mode = NL80211_IFTYPE_STATION;
  out:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	return err;
@@ -1297,7 +1309,7 @@
 {
 	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	if (priv->scan_vif == vif) {
 		iwl_scan_cancel_timeout(priv, 200);
@@ -1329,7 +1341,7 @@
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	if (WARN_ON(ctx->vif != vif)) {
 		struct iwl_rxon_context *tmp;
@@ -1342,7 +1354,7 @@
 
 	iwl_teardown_interface(priv, vif, false);
 
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
@@ -1364,9 +1376,9 @@
 
 	newtype = ieee80211_iftype_p2p(newtype, newp2p);
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
-	if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) {
+	if (!ctx->vif || !iwl_is_ready_rf(priv)) {
 		/*
 		 * Huh? But wait ... this can maybe happen when
 		 * we're in the middle of a firmware restart!
@@ -1428,7 +1440,7 @@
 	err = 0;
 
  out:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 	return err;
@@ -1446,7 +1458,7 @@
 	if (req->n_channels == 0)
 		return -EINVAL;
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	/*
 	 * If an internal scan is in progress, just set
@@ -1475,47 +1487,20 @@
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
-	mutex_unlock(&priv->shrd->mutex);
-
-	return ret;
-}
-
-static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
-		       struct ieee80211_vif *vif,
-		       struct ieee80211_sta *sta)
-{
-	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
-	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-	int ret;
-
-	IWL_DEBUG_MAC80211(priv, "enter: received request to remove "
-			   "station %pM\n", sta->addr);
-	mutex_lock(&priv->shrd->mutex);
-	IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
-			sta->addr);
-	ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr);
-	if (ret)
-		IWL_DEBUG_QUIET_RFKILL(priv, "Error removing station %pM\n",
-			sta->addr);
-	mutex_unlock(&priv->shrd->mutex);
-	IWL_DEBUG_MAC80211(priv, "leave\n");
+	mutex_unlock(&priv->mutex);
 
 	return ret;
 }
 
 static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
 {
-	unsigned long flags;
+	struct iwl_addsta_cmd cmd = {
+		.mode = STA_CONTROL_MODIFY_MSK,
+		.station_flags_msk = STA_FLG_PWR_SAVE_MSK,
+		.sta.sta_id = sta_id,
+	};
 
-	spin_lock_irqsave(&priv->shrd->sta_lock, flags);
-	priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
-	priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
-	priv->stations[sta_id].sta.sta.modify_mask = 0;
-	priv->stations[sta_id].sta.sleep_tx_count = 0;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-	spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-
+	iwl_send_add_sta(priv, &cmd, CMD_ASYNC);
 }
 
 static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
@@ -1572,8 +1557,7 @@
 	.ampdu_action = iwlagn_mac_ampdu_action,
 	.hw_scan = iwlagn_mac_hw_scan,
 	.sta_notify = iwlagn_mac_sta_notify,
-	.sta_add = iwlagn_mac_sta_add,
-	.sta_remove = iwlagn_mac_sta_remove,
+	.sta_state = iwlagn_mac_sta_state,
 	.channel_switch = iwlagn_mac_channel_switch,
 	.flush = iwlagn_mac_flush,
 	.tx_last_beacon = iwlagn_mac_tx_last_beacon,
@@ -1582,8 +1566,6 @@
 	.rssi_callback = iwlagn_mac_rssi_callback,
 	CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd)
 	CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump)
-	.tx_sync = iwlagn_mac_tx_sync,
-	.finish_tx_sync = iwlagn_mac_finish_tx_sync,
 	.set_tim = iwlagn_mac_set_tim,
 };
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c
new file mode 100644
index 0000000..88dc4a0
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c
@@ -0,0 +1,157 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#include <linux/sched.h>
+
+#include "iwl-notif-wait.h"
+
+
+void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait)
+{
+	spin_lock_init(&notif_wait->notif_wait_lock);
+	INIT_LIST_HEAD(&notif_wait->notif_waits);
+	init_waitqueue_head(&notif_wait->notif_waitq);
+}
+
+void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait,
+				  struct iwl_rx_packet *pkt)
+{
+	if (!list_empty(&notif_wait->notif_waits)) {
+		struct iwl_notification_wait *w;
+
+		spin_lock(&notif_wait->notif_wait_lock);
+		list_for_each_entry(w, &notif_wait->notif_waits, list) {
+			if (w->cmd != pkt->hdr.cmd)
+				continue;
+			w->triggered = true;
+			if (w->fn)
+				w->fn(notif_wait, pkt, w->fn_data);
+		}
+		spin_unlock(&notif_wait->notif_wait_lock);
+
+		wake_up_all(&notif_wait->notif_waitq);
+	}
+}
+
+void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait)
+{
+	unsigned long flags;
+	struct iwl_notification_wait *wait_entry;
+
+	spin_lock_irqsave(&notif_wait->notif_wait_lock, flags);
+	list_for_each_entry(wait_entry, &notif_wait->notif_waits, list)
+		wait_entry->aborted = true;
+	spin_unlock_irqrestore(&notif_wait->notif_wait_lock, flags);
+
+	wake_up_all(&notif_wait->notif_waitq);
+}
+
+
+void
+iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait,
+			   struct iwl_notification_wait *wait_entry,
+			   u8 cmd,
+			   void (*fn)(struct iwl_notif_wait_data *notif_wait,
+				      struct iwl_rx_packet *pkt, void *data),
+			   void *fn_data)
+{
+	wait_entry->fn = fn;
+	wait_entry->fn_data = fn_data;
+	wait_entry->cmd = cmd;
+	wait_entry->triggered = false;
+	wait_entry->aborted = false;
+
+	spin_lock_bh(&notif_wait->notif_wait_lock);
+	list_add(&wait_entry->list, &notif_wait->notif_waits);
+	spin_unlock_bh(&notif_wait->notif_wait_lock);
+}
+
+int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait,
+			  struct iwl_notification_wait *wait_entry,
+			  unsigned long timeout)
+{
+	int ret;
+
+	ret = wait_event_timeout(notif_wait->notif_waitq,
+				 wait_entry->triggered || wait_entry->aborted,
+				 timeout);
+
+	spin_lock_bh(&notif_wait->notif_wait_lock);
+	list_del(&wait_entry->list);
+	spin_unlock_bh(&notif_wait->notif_wait_lock);
+
+	if (wait_entry->aborted)
+		return -EIO;
+
+	/* return value is always >= 0 */
+	if (ret <= 0)
+		return -ETIMEDOUT;
+	return 0;
+}
+
+void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait,
+			     struct iwl_notification_wait *wait_entry)
+{
+	spin_lock_bh(&notif_wait->notif_wait_lock);
+	list_del(&wait_entry->list);
+	spin_unlock_bh(&notif_wait->notif_wait_lock);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h
new file mode 100644
index 0000000..5e8af95
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_notif_wait_h__
+#define __iwl_notif_wait_h__
+
+#include <linux/wait.h>
+
+#include "iwl-trans.h"
+
+struct iwl_notif_wait_data {
+	struct list_head notif_waits;
+	spinlock_t notif_wait_lock;
+	wait_queue_head_t notif_waitq;
+};
+
+/**
+ * struct iwl_notification_wait - notification wait entry
+ * @list: list head for global list
+ * @fn: function called with the notification
+ * @cmd: command ID
+ *
+ * This structure is not used directly, to wait for a
+ * notification declare it on the stack, and call
+ * iwlagn_init_notification_wait() with appropriate
+ * parameters. Then do whatever will cause the ucode
+ * to notify the driver, and to wait for that then
+ * call iwlagn_wait_notification().
+ *
+ * Each notification is one-shot. If at some point we
+ * need to support multi-shot notifications (which
+ * can't be allocated on the stack) we need to modify
+ * the code for them.
+ */
+struct iwl_notification_wait {
+	struct list_head list;
+
+	void (*fn)(struct iwl_notif_wait_data *notif_data,
+		   struct iwl_rx_packet *pkt, void *data);
+	void *fn_data;
+
+	u8 cmd;
+	bool triggered, aborted;
+};
+
+
+/* caller functions */
+void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_data);
+void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_data,
+				  struct iwl_rx_packet *pkt);
+void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_data);
+
+/* user functions */
+void __acquires(wait_entry)
+iwl_init_notification_wait(struct iwl_notif_wait_data *notif_data,
+			   struct iwl_notification_wait *wait_entry,
+			   u8 cmd,
+			   void (*fn)(struct iwl_notif_wait_data *notif_data,
+				      struct iwl_rx_packet *pkt, void *data),
+			   void *fn_data);
+
+int __must_check __releases(wait_entry)
+iwl_wait_notification(struct iwl_notif_wait_data *notif_data,
+		      struct iwl_notification_wait *wait_entry,
+		      unsigned long timeout);
+
+void __releases(wait_entry)
+iwl_remove_notification(struct iwl_notif_wait_data *notif_data,
+			struct iwl_notification_wait *wait_entry);
+
+#endif /* __iwl_notif_wait_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index d4fc9be..6ea4163 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -67,7 +67,8 @@
 struct iwl_trans;
 struct sk_buff;
 struct iwl_device_cmd;
-struct iwl_rx_mem_buffer;
+struct iwl_rx_cmd_buffer;
+struct iwl_fw;
 
 /**
  * DOC: Operational mode - what is it ?
@@ -121,17 +122,23 @@
  *	there are Tx packets pending in the transport layer.
  *	Must be atomic
  * @nic_error: error notification. Must be atomic
+ * @cmd_queue_full: Called when the command queue gets full. Must be atomic.
+ * @nic_config: configure NIC, called before firmware is started.
+ *	May sleep
  */
 struct iwl_op_mode_ops {
-	struct iwl_op_mode *(*start)(struct iwl_trans *trans);
+	struct iwl_op_mode *(*start)(struct iwl_trans *trans,
+				     const struct iwl_fw *fw);
 	void (*stop)(struct iwl_op_mode *op_mode);
-	int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb,
+	int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
 		  struct iwl_device_cmd *cmd);
 	void (*queue_full)(struct iwl_op_mode *op_mode, u8 ac);
 	void (*queue_not_full)(struct iwl_op_mode *op_mode, u8 ac);
 	void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
 	void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
 	void (*nic_error)(struct iwl_op_mode *op_mode);
+	void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
+	void (*nic_config)(struct iwl_op_mode *op_mode);
 };
 
 /**
@@ -156,7 +163,7 @@
 }
 
 static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode,
-				  struct iwl_rx_mem_buffer *rxb,
+				  struct iwl_rx_cmd_buffer *rxb,
 				  struct iwl_device_cmd *cmd)
 {
 	return op_mode->ops->rx(op_mode, rxb, cmd);
@@ -190,6 +197,17 @@
 	op_mode->ops->nic_error(op_mode);
 }
 
+static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode)
+{
+	op_mode->ops->cmd_queue_full(op_mode);
+}
+
+static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode)
+{
+	might_sleep();
+	op_mode->ops->nic_config(op_mode);
+}
+
 /*****************************************************
 * Op mode layers implementations
 ******************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c
index 06e0041..c5e339e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-pci.c
+++ b/drivers/net/wireless/iwlwifi/iwl-pci.c
@@ -263,7 +263,7 @@
 
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+	const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
 	struct iwl_shared *shrd;
 	struct iwl_trans *iwl_trans;
 	int err;
@@ -278,17 +278,9 @@
 
 #ifdef CONFIG_IWLWIFI_IDI
 	iwl_trans = iwl_trans_idi_alloc(shrd, pdev, ent);
-	if (iwl_trans == NULL) {
-		err = -ENOMEM;
-		goto out_free_bus;
-	}
-
-	shrd->trans = iwl_trans;
-	pci_set_drvdata(pdev, iwl_trans);
-
-	err = iwl_drv_start(shrd, iwl_trans, cfg);
 #else
 	iwl_trans = iwl_trans_pcie_alloc(shrd, pdev, ent);
+#endif
 	if (iwl_trans == NULL) {
 		err = -ENOMEM;
 		goto out_free_bus;
@@ -298,7 +290,6 @@
 	pci_set_drvdata(pdev, iwl_trans);
 
 	err = iwl_drv_start(shrd, iwl_trans, cfg);
-#endif
 	if (err)
 		goto out_free_trans;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index fd008c4..958d9d0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -215,7 +215,7 @@
 	else
 		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
 
-	if (hw_params(priv).shadow_reg_enable)
+	if (cfg(priv)->base_params->shadow_reg_enable)
 		cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
 	else
 		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
@@ -301,7 +301,7 @@
 	if (priv->power_data.bus_pm)
 		cmd->flags |= IWL_POWER_PCI_PM_MSK;
 
-	if (hw_params(priv).shadow_reg_enable)
+	if (cfg(priv)->base_params->shadow_reg_enable)
 		cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
 	else
 		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
@@ -336,7 +336,7 @@
 			le32_to_cpu(cmd->sleep_interval[3]),
 			le32_to_cpu(cmd->sleep_interval[4]));
 
-	return iwl_trans_send_cmd_pdu(trans(priv), POWER_TABLE_CMD, CMD_SYNC,
+	return iwl_dvm_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC,
 				sizeof(struct iwl_powertable_cmd), cmd);
 }
 
@@ -348,7 +348,7 @@
 
 	dtimper = priv->hw->conf.ps_dtim_period ?: 1;
 
-	if (priv->shrd->wowlan)
+	if (priv->wowlan)
 		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
 	else if (!cfg(priv)->base_params->no_idle_support &&
 		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
@@ -383,7 +383,7 @@
 	int ret;
 	bool update_chains;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	/* Don't update the RX chain when chain noise calibration is running */
 	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
@@ -392,12 +392,12 @@
 	if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
 		return 0;
 
-	if (!iwl_is_ready_rf(priv->shrd))
+	if (!iwl_is_ready_rf(priv))
 		return -EIO;
 
 	/* scan complete use sleep_power_next, need to be updated */
 	memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
-	if (test_bit(STATUS_SCANNING, &priv->shrd->status) && !force) {
+	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
 		IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
 		return 0;
 	}
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index a4d1101..75dc20b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -216,10 +216,6 @@
 #define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
 	((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
 
-#define SCD_QUEUECHAIN_SEL_ALL(priv)	\
-	(((1<<hw_params(priv).max_txq_num) - 1) &\
-	(~(1<<(priv)->shrd->cmd_queue)))
-
 #define SCD_BASE			(PRPH_BASE + 0xa02c00)
 
 #define SCD_SRAM_BASE_ADDR	(SCD_BASE + 0x0)
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 42ee1c4..902efe4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -57,39 +57,39 @@
 static int iwl_send_scan_abort(struct iwl_priv *priv)
 {
 	int ret;
-	struct iwl_rx_packet *pkt;
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_SCAN_ABORT_CMD,
 		.flags = CMD_SYNC | CMD_WANT_SKB,
 	};
+	__le32 *status;
 
 	/* Exit instantly with error when device is not ready
 	 * to receive scan abort command or it does not perform
 	 * hardware scan currently */
-	if (!test_bit(STATUS_READY, &priv->shrd->status) ||
-	    !test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) ||
-	    !test_bit(STATUS_SCAN_HW, &priv->shrd->status) ||
-	    test_bit(STATUS_FW_ERROR, &priv->shrd->status) ||
-	    test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
+	if (!test_bit(STATUS_READY, &priv->status) ||
+	    !test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
+	    !test_bit(STATUS_SCAN_HW, &priv->status) ||
+	    test_bit(STATUS_FW_ERROR, &priv->shrd->status))
 		return -EIO;
 
-	ret = iwl_trans_send_cmd(trans(priv), &cmd);
+	ret = iwl_dvm_send_cmd(priv, &cmd);
 	if (ret)
 		return ret;
 
-	pkt = (struct iwl_rx_packet *)cmd.reply_page;
-	if (pkt->u.status != CAN_ABORT_STATUS) {
+	status = (void *)cmd.resp_pkt->data;
+	if (*status != CAN_ABORT_STATUS) {
 		/* The scan abort will return 1 for success or
 		 * 2 for "failure".  A failure condition can be
 		 * due to simply not being in an active scan which
 		 * can occur if we send the scan abort before we
 		 * the microcode has notified us that a scan is
 		 * completed. */
-		IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
+		IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n",
+			       le32_to_cpu(*status));
 		ret = -EIO;
 	}
 
-	iwl_free_pages(priv->shrd, cmd.reply_page);
+	iwl_free_resp(&cmd);
 	return ret;
 }
 
@@ -116,20 +116,20 @@
 {
 	bool aborted;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
-	if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status))
+	if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->status))
 		return;
 
 	IWL_DEBUG_SCAN(priv, "Completed scan.\n");
 
 	cancel_delayed_work(&priv->scan_check);
 
-	aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
+	aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status);
 	if (aborted)
 		IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
 
-	if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) {
+	if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) {
 		IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
 		goto out_settings;
 	}
@@ -165,7 +165,7 @@
 
 out_settings:
 	/* Can we still talk to firmware ? */
-	if (!iwl_is_ready_rf(priv->shrd))
+	if (!iwl_is_ready_rf(priv))
 		return;
 
 	iwlagn_post_scan(priv);
@@ -173,18 +173,18 @@
 
 void iwl_force_scan_end(struct iwl_priv *priv)
 {
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
-	if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) {
+	if (!test_bit(STATUS_SCANNING, &priv->status)) {
 		IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
 		return;
 	}
 
 	IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
-	clear_bit(STATUS_SCANNING, &priv->shrd->status);
-	clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
-	clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
-	clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
+	clear_bit(STATUS_SCANNING, &priv->status);
+	clear_bit(STATUS_SCAN_HW, &priv->status);
+	clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+	clear_bit(STATUS_SCAN_COMPLETE, &priv->status);
 	iwl_complete_scan(priv, true);
 }
 
@@ -192,14 +192,14 @@
 {
 	int ret;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
-	if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) {
+	if (!test_bit(STATUS_SCANNING, &priv->status)) {
 		IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
 		return;
 	}
 
-	if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) {
+	if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
 		IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
 		return;
 	}
@@ -231,14 +231,14 @@
 {
 	unsigned long timeout = jiffies + msecs_to_jiffies(ms);
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
 
 	iwl_do_scan_abort(priv);
 
 	while (time_before_eq(jiffies, timeout)) {
-		if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status))
+		if (!test_bit(STATUS_SCAN_HW, &priv->status))
 			goto finished;
 		msleep(20);
 	}
@@ -261,13 +261,12 @@
 
 /* Service response to REPLY_SCAN_CMD (0x80) */
 static int iwl_rx_reply_scan(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb,
+			      struct iwl_rx_cmd_buffer *rxb,
 			      struct iwl_device_cmd *cmd)
 {
 #ifdef CONFIG_IWLWIFI_DEBUG
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_scanreq_notification *notif =
-	    (struct iwl_scanreq_notification *)pkt->u.raw;
+	struct iwl_scanreq_notification *notif = (void *)pkt->data;
 
 	IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
 #endif
@@ -276,12 +275,12 @@
 
 /* Service SCAN_START_NOTIFICATION (0x82) */
 static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
-				    struct iwl_rx_mem_buffer *rxb,
+				    struct iwl_rx_cmd_buffer *rxb,
 				    struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_scanstart_notification *notif =
-	    (struct iwl_scanstart_notification *)pkt->u.raw;
+	struct iwl_scanstart_notification *notif = (void *)pkt->data;
+
 	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
 	IWL_DEBUG_SCAN(priv, "Scan start: "
 		       "%d [802.11%s] "
@@ -303,13 +302,12 @@
 
 /* Service SCAN_RESULTS_NOTIFICATION (0x83) */
 static int iwl_rx_scan_results_notif(struct iwl_priv *priv,
-				      struct iwl_rx_mem_buffer *rxb,
+				      struct iwl_rx_cmd_buffer *rxb,
 				      struct iwl_device_cmd *cmd)
 {
 #ifdef CONFIG_IWLWIFI_DEBUG
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_scanresults_notification *notif =
-	    (struct iwl_scanresults_notification *)pkt->u.raw;
+	struct iwl_scanresults_notification *notif = (void *)pkt->data;
 
 	IWL_DEBUG_SCAN(priv, "Scan ch.res: "
 		       "%d [802.11%s] "
@@ -329,11 +327,11 @@
 
 /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
 static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
-				       struct iwl_rx_mem_buffer *rxb,
+				       struct iwl_rx_cmd_buffer *rxb,
 				       struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
+	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->data;
 
 	IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
 		       scan_notif->scanned_channels,
@@ -352,8 +350,8 @@
 	 * to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW
 	 * to avoid a race there.
 	 */
-	set_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
-	clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
+	set_bit(STATUS_SCAN_COMPLETE, &priv->status);
+	clear_bit(STATUS_SCAN_HW, &priv->status);
 	queue_work(priv->workqueue, &priv->scan_completed);
 
 	if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
@@ -574,6 +572,53 @@
 	return added;
 }
 
+/**
+ * iwl_fill_probe_req - fill in all required fields and IE for probe request
+ */
+
+static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
+			      const u8 *ies, int ie_len, int left)
+{
+	int len = 0;
+	u8 *pos = NULL;
+
+	/* Make sure there is enough space for the probe request,
+	 * two mandatory IEs and the data */
+	left -= 24;
+	if (left < 0)
+		return 0;
+
+	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
+	memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
+	memcpy(frame->sa, ta, ETH_ALEN);
+	memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
+	frame->seq_ctrl = 0;
+
+	len += 24;
+
+	/* ...next IE... */
+	pos = &frame->u.probe_req.variable[0];
+
+	/* fill in our indirect SSID IE */
+	left -= 2;
+	if (left < 0)
+		return 0;
+	*pos++ = WLAN_EID_SSID;
+	*pos++ = 0;
+
+	len += 2;
+
+	if (WARN_ON(left < ie_len))
+		return len;
+
+	if (ies && ie_len) {
+		memcpy(pos, ies, ie_len);
+		len += ie_len;
+	}
+
+	return (u16)len;
+}
+
 static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
 	struct iwl_host_cmd cmd = {
@@ -596,7 +641,7 @@
 	u8 scan_tx_antennas = hw_params(priv).valid_tx_ant;
 	int ret;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	if (vif)
 		ctx = iwl_rxon_ctx_from_vif(vif);
@@ -793,7 +838,7 @@
 	scan->rx_chain = cpu_to_le16(rx_chain);
 	switch (priv->scan_type) {
 	case IWL_SCAN_NORMAL:
-		cmd_len = iwl_fill_probe_req(priv,
+		cmd_len = iwl_fill_probe_req(
 					(struct ieee80211_mgmt *)scan->data,
 					vif->addr,
 					priv->scan_request->ie,
@@ -803,7 +848,7 @@
 	case IWL_SCAN_RADIO_RESET:
 	case IWL_SCAN_ROC:
 		/* use bcast addr, will not be transmitted but must be valid */
-		cmd_len = iwl_fill_probe_req(priv,
+		cmd_len = iwl_fill_probe_req(
 					(struct ieee80211_mgmt *)scan->data,
 					iwl_bcast_addr, NULL, 0,
 					IWL_MAX_SCAN_SIZE - sizeof(*scan));
@@ -882,15 +927,15 @@
 	scan->len = cpu_to_le16(cmd.len[0]);
 
 	/* set scan bit here for PAN params */
-	set_bit(STATUS_SCAN_HW, &priv->shrd->status);
+	set_bit(STATUS_SCAN_HW, &priv->status);
 
 	ret = iwlagn_set_pan_params(priv);
 	if (ret)
 		return ret;
 
-	ret = iwl_trans_send_cmd(trans(priv), &cmd);
+	ret = iwl_dvm_send_cmd(priv, &cmd);
 	if (ret) {
-		clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
+		clear_bit(STATUS_SCAN_HW, &priv->status);
 		iwlagn_set_pan_params(priv);
 	}
 
@@ -913,22 +958,22 @@
 {
 	int ret;
 
-	lockdep_assert_held(&priv->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	cancel_delayed_work(&priv->scan_check);
 
-	if (!iwl_is_ready_rf(priv->shrd)) {
+	if (!iwl_is_ready_rf(priv)) {
 		IWL_WARN(priv, "Request scan called when driver not ready.\n");
 		return -EIO;
 	}
 
-	if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
+	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
 		IWL_DEBUG_SCAN(priv,
 			"Multiple concurrent scan requests in parallel.\n");
 		return -EBUSY;
 	}
 
-	if (test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) {
+	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
 		IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n");
 		return -EBUSY;
 	}
@@ -938,14 +983,14 @@
 			scan_type == IWL_SCAN_ROC ? "remain-on-channel " :
 			"internal short ");
 
-	set_bit(STATUS_SCANNING, &priv->shrd->status);
+	set_bit(STATUS_SCANNING, &priv->status);
 	priv->scan_type = scan_type;
 	priv->scan_start = jiffies;
 	priv->scan_band = band;
 
 	ret = iwlagn_request_scan(priv, vif);
 	if (ret) {
-		clear_bit(STATUS_SCANNING, &priv->shrd->status);
+		clear_bit(STATUS_SCANNING, &priv->status);
 		priv->scan_type = IWL_SCAN_NORMAL;
 		return ret;
 	}
@@ -973,14 +1018,14 @@
 
 	IWL_DEBUG_SCAN(priv, "Start internal scan\n");
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	if (priv->scan_type == IWL_SCAN_RADIO_RESET) {
 		IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
 		goto unlock;
 	}
 
-	if (test_bit(STATUS_SCANNING, &priv->shrd->status)) {
+	if (test_bit(STATUS_SCANNING, &priv->status)) {
 		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
 		goto unlock;
 	}
@@ -988,7 +1033,7 @@
 	if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band))
 		IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
  unlock:
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 static void iwl_bg_scan_check(struct work_struct *data)
@@ -1001,56 +1046,9 @@
 	/* Since we are here firmware does not finish scan and
 	 * most likely is in bad shape, so we don't bother to
 	 * send abort command, just force scan complete to mac80211 */
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	iwl_force_scan_end(priv);
-	mutex_unlock(&priv->shrd->mutex);
-}
-
-/**
- * iwl_fill_probe_req - fill in all required fields and IE for probe request
- */
-
-u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
-		       const u8 *ta, const u8 *ies, int ie_len, int left)
-{
-	int len = 0;
-	u8 *pos = NULL;
-
-	/* Make sure there is enough space for the probe request,
-	 * two mandatory IEs and the data */
-	left -= 24;
-	if (left < 0)
-		return 0;
-
-	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
-	memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
-	memcpy(frame->sa, ta, ETH_ALEN);
-	memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
-	frame->seq_ctrl = 0;
-
-	len += 24;
-
-	/* ...next IE... */
-	pos = &frame->u.probe_req.variable[0];
-
-	/* fill in our indirect SSID IE */
-	left -= 2;
-	if (left < 0)
-		return 0;
-	*pos++ = WLAN_EID_SSID;
-	*pos++ = 0;
-
-	len += 2;
-
-	if (WARN_ON(left < ie_len))
-		return len;
-
-	if (ies && ie_len) {
-		memcpy(pos, ies, ie_len);
-		len += ie_len;
-	}
-
-	return (u16)len;
+	mutex_unlock(&priv->mutex);
 }
 
 static void iwl_bg_abort_scan(struct work_struct *work)
@@ -1061,9 +1059,9 @@
 
 	/* We keep scan_check work queued in case when firmware will not
 	 * report back scan completed notification */
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	iwl_scan_cancel_timeout(priv, 200);
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 static void iwl_bg_scan_completed(struct work_struct *work)
@@ -1071,9 +1069,9 @@
 	struct iwl_priv *priv =
 		container_of(work, struct iwl_priv, scan_completed);
 
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	iwl_process_scan_complete(priv);
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 }
 
 void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
@@ -1091,8 +1089,8 @@
 	cancel_work_sync(&priv->scan_completed);
 
 	if (cancel_delayed_work_sync(&priv->scan_check)) {
-		mutex_lock(&priv->shrd->mutex);
+		mutex_lock(&priv->mutex);
 		iwl_force_scan_end(priv);
-		mutex_unlock(&priv->shrd->mutex);
+		mutex_unlock(&priv->mutex);
 	}
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h
index a644162..b515d65 100644
--- a/drivers/net/wireless/iwlwifi/iwl-shared.h
+++ b/drivers/net/wireless/iwlwifi/iwl-shared.h
@@ -65,12 +65,11 @@
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
-#include <linux/mutex.h>
 #include <linux/gfp.h>
-#include <linux/mm.h> /* for page_address */
 #include <net/mac80211.h>
 
 #include "iwl-commands.h"
+#include "iwl-fw.h"
 
 /**
  * DOC: shared area - role and goal
@@ -116,7 +115,6 @@
  * Holds the module parameters
  *
  * @sw_crypto: using hardware encryption, default = 0
- * @num_of_queues: number of tx queue, HW dependent
  * @disable_11n: disable 11n capabilities, default = 0,
  *	use IWL_DISABLE_HT_* constants
  * @amsdu_size_8K: enable 8K amsdu size, default = 1
@@ -138,7 +136,6 @@
  */
 struct iwl_mod_params {
 	int sw_crypto;
-	int num_of_queues;
 	unsigned int disable_11n;
 	int amsdu_size_8K;
 	int antenna;
@@ -163,7 +160,6 @@
  *
  * Holds the module parameters
  *
- * @max_txq_num: Max # Tx queues supported
  * @num_ampdu_queues: num of ampdu queues
  * @tx_chains_num: Number of TX chains
  * @rx_chains_num: Number of RX chains
@@ -177,16 +173,16 @@
  *	relevant for 1000, 6000 and up
  * @wd_timeout: TX queues watchdog timeout
  * @struct iwl_sensitivity_ranges: range of sensitivity values
+ * @use_rts_for_aggregation: use rts/cts protection for HT traffic
  */
 struct iwl_hw_params {
-	u8  max_txq_num;
 	u8  num_ampdu_queues;
 	u8  tx_chains_num;
 	u8  rx_chains_num;
 	u8  valid_tx_ant;
 	u8  valid_rx_ant;
 	u8  ht40_channel;
-	bool shadow_reg_enable;
+	bool use_rts_for_aggregation;
 	u16 sku;
 	u32 rx_page_order;
 	u32 ct_kill_threshold;
@@ -196,62 +192,6 @@
 	const struct iwl_sensitivity_ranges *sens;
 };
 
-/**
- * enum iwl_ucode_type
- *
- * The type of ucode currently loaded on the hardware.
- *
- * @IWL_UCODE_NONE: No ucode loaded
- * @IWL_UCODE_REGULAR: Normal runtime ucode
- * @IWL_UCODE_INIT: Initial ucode
- * @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode
- */
-enum iwl_ucode_type {
-	IWL_UCODE_NONE,
-	IWL_UCODE_REGULAR,
-	IWL_UCODE_INIT,
-	IWL_UCODE_WOWLAN,
-};
-
-/**
- * struct iwl_notification_wait - notification wait entry
- * @list: list head for global list
- * @fn: function called with the notification
- * @cmd: command ID
- *
- * This structure is not used directly, to wait for a
- * notification declare it on the stack, and call
- * iwlagn_init_notification_wait() with appropriate
- * parameters. Then do whatever will cause the ucode
- * to notify the driver, and to wait for that then
- * call iwlagn_wait_notification().
- *
- * Each notification is one-shot. If at some point we
- * need to support multi-shot notifications (which
- * can't be allocated on the stack) we need to modify
- * the code for them.
- */
-struct iwl_notification_wait {
-	struct list_head list;
-
-	void (*fn)(struct iwl_trans *trans, struct iwl_rx_packet *pkt,
-		   void *data);
-	void *fn_data;
-
-	u8 cmd;
-	bool triggered, aborted;
-};
-
-/**
- * enum iwl_pa_type - Power Amplifier type
- * @IWL_PA_SYSTEM:  based on uCode configuration
- * @IWL_PA_INTERNAL: use Internal only
- */
-enum iwl_pa_type {
-	IWL_PA_SYSTEM = 0,
-	IWL_PA_INTERNAL = 1,
-};
-
 /*
  * LED mode
  *    IWL_LED_DEFAULT:  use device default
@@ -268,6 +208,73 @@
 	IWL_LED_DISABLE,
 };
 
+/*
+ * @max_ll_items: max number of OTP blocks
+ * @shadow_ram_support: shadow support for OTP memory
+ * @led_compensation: compensate on the led on/off time per HW according
+ *	to the deviation to achieve the desired led frequency.
+ *	The detail algorithm is described in iwl-led.c
+ * @chain_noise_num_beacons: number of beacons used to compute chain noise
+ * @adv_thermal_throttle: support advance thermal throttle
+ * @support_ct_kill_exit: support ct kill exit condition
+ * @support_wimax_coexist: support wimax/wifi co-exist
+ * @plcp_delta_threshold: plcp error rate threshold used to trigger
+ *	radio tuning when there is a high receiving plcp error rate
+ * @chain_noise_scale: default chain noise scale used for gain computation
+ * @wd_timeout: TX queues watchdog timeout
+ * @max_event_log_size: size of event log buffer size for ucode event logging
+ * @shadow_reg_enable: HW shadhow register bit
+ * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
+ * @no_idle_support: do not support idle mode
+ * wd_disable: disable watchdog timer
+ */
+struct iwl_base_params {
+	int eeprom_size;
+	int num_of_queues;	/* def: HW dependent */
+	int num_of_ampdu_queues;/* def: HW dependent */
+	/* for iwl_apm_init() */
+	u32 pll_cfg_val;
+
+	const u16 max_ll_items;
+	const bool shadow_ram_support;
+	u16 led_compensation;
+	bool adv_thermal_throttle;
+	bool support_ct_kill_exit;
+	const bool support_wimax_coexist;
+	u8 plcp_delta_threshold;
+	s32 chain_noise_scale;
+	unsigned int wd_timeout;
+	u32 max_event_log_size;
+	const bool shadow_reg_enable;
+	const bool hd_v2;
+	const bool no_idle_support;
+	const bool wd_disable;
+};
+
+/*
+ * @advanced_bt_coexist: support advanced bt coexist
+ * @bt_init_traffic_load: specify initial bt traffic load
+ * @bt_prio_boost: default bt priority boost value
+ * @agg_time_limit: maximum number of uSec in aggregation
+ * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
+ */
+struct iwl_bt_params {
+	bool advanced_bt_coexist;
+	u8 bt_init_traffic_load;
+	u8 bt_prio_boost;
+	u16 agg_time_limit;
+	bool bt_sco_disable;
+	bool bt_session_2;
+};
+/*
+ * @use_rts_for_aggregation: use rts/cts protection for HT traffic
+ */
+struct iwl_ht_params {
+	const bool ht_greenfield_support; /* if used set to true */
+	bool use_rts_for_aggregation;
+	enum ieee80211_smps_mode smps_mode;
+};
+
 /**
  * struct iwl_cfg
  * @name: Offical name of the device
@@ -282,7 +289,6 @@
  * @max_data_size: The maximal length of the fw data section
  * @valid_tx_ant: valid transmit antenna
  * @valid_rx_ant: valid receive antenna
- * @sku: sku information from EEPROM
  * @eeprom_ver: EEPROM version
  * @eeprom_calib_ver: EEPROM calibration version
  * @lib: pointer to the lib ops
@@ -290,7 +296,6 @@
  * @base_params: pointer to basic parameters
  * @ht_params: point to ht patameters
  * @bt_params: pointer to bt parameters
- * @pa_type: used by 6000 series only to identify the type of Power Amplifier
  * @need_temp_offset_calib: need to perform temperature offset calibration
  * @no_xtal_calib: some devices do not need crystal calibration data,
  *	don't send it to those
@@ -321,17 +326,15 @@
 	const u32 max_inst_size;
 	u8   valid_tx_ant;
 	u8   valid_rx_ant;
-	u16  sku;
 	u16  eeprom_ver;
 	u16  eeprom_calib_ver;
 	const struct iwl_lib_ops *lib;
 	void (*additional_nic_config)(struct iwl_priv *priv);
 	/* params not likely to change within a device family */
-	struct iwl_base_params *base_params;
+	const struct iwl_base_params *base_params;
 	/* params likely to change within a device family */
-	struct iwl_ht_params *ht_params;
-	struct iwl_bt_params *bt_params;
-	enum iwl_pa_type pa_type;	  /* if used set to IWL_PA_SYSTEM */
+	const struct iwl_ht_params *ht_params;
+	const struct iwl_bt_params *bt_params;
 	const bool need_temp_offset_calib; /* if used set to true */
 	const bool no_xtal_calib;
 	u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
@@ -346,10 +349,6 @@
 /**
  * struct iwl_shared - shared fields for all the layers of the driver
  *
- * @dbg_level_dev: dbg level set per device. Prevails on
- *	iwlagn_mod_params.debug_level if set (!= 0)
- * @ucode_owner: IWL_OWNERSHIP_*
- * @cmd_queue: command queue number
  * @status: STATUS_*
  * @wowlan: are we running wowlan uCode
  * @valid_contexts: microcode/device supports multiple contexts
@@ -360,41 +359,19 @@
  * @nic: pointer to the nic data
  * @hw_params: see struct iwl_hw_params
  * @lock: protect general shared data
- * @sta_lock: protects the station table.
- *	If lock and sta_lock are needed, lock must be acquired first.
- * @mutex:
- * @wait_command_queue: the wait_queue for SYNC host command nad uCode load
  * @eeprom: pointer to the eeprom/OTP image
  * @ucode_type: indicator of loaded ucode image
- * @notif_waits: things waiting for notification
- * @notif_wait_lock: lock protecting notification
- * @notif_waitq: head of notification wait queue
  * @device_pointers: pointers to ucode event tables
  */
 struct iwl_shared {
-#ifdef CONFIG_IWLWIFI_DEBUG
-	u32 dbg_level_dev;
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
-#define IWL_OWNERSHIP_DRIVER	0
-#define IWL_OWNERSHIP_TM	1
-	u8 ucode_owner;
-	u8 cmd_queue;
 	unsigned long status;
-	bool wowlan;
 	u8 valid_contexts;
 
-	struct iwl_cfg *cfg;
-	struct iwl_priv *priv;
+	const struct iwl_cfg *cfg;
 	struct iwl_trans *trans;
-	struct iwl_nic *nic;
+	void *drv;
 	struct iwl_hw_params hw_params;
-
-	spinlock_t lock;
-	spinlock_t sta_lock;
-	struct mutex mutex;
-
-	wait_queue_head_t wait_command_queue;
+	const struct iwl_fw *fw;
 
 	/* eeprom -- this is in the card's little endian byte order */
 	u8 *eeprom;
@@ -402,11 +379,6 @@
 	/* ucode related variables */
 	enum iwl_ucode_type ucode_type;
 
-	/* notification wait support */
-	struct list_head notif_waits;
-	spinlock_t notif_wait_lock;
-	wait_queue_head_t notif_waitq;
-
 	struct {
 		u32 error_event_table;
 		u32 log_event_table;
@@ -415,111 +387,13 @@
 };
 
 /*Whatever _m is (iwl_trans, iwl_priv, these macros will work */
-#define priv(_m)	((_m)->shrd->priv)
 #define cfg(_m)		((_m)->shrd->cfg)
-#define nic(_m)		((_m)->shrd->nic)
 #define trans(_m)	((_m)->shrd->trans)
 #define hw_params(_m)	((_m)->shrd->hw_params)
 
-#ifdef CONFIG_IWLWIFI_DEBUG
-/*
- * iwl_get_debug_level: Return active debug level for device
- *
- * Using sysfs it is possible to set per device debug level. This debug
- * level will be used if set, otherwise the global debug level which can be
- * set via module parameter is used.
- */
-static inline u32 iwl_get_debug_level(struct iwl_shared *shrd)
+static inline bool iwl_have_debug_level(u32 level)
 {
-	if (shrd->dbg_level_dev)
-		return shrd->dbg_level_dev;
-	else
-		return iwlagn_mod_params.debug_level;
-}
-#else
-static inline u32 iwl_get_debug_level(struct iwl_shared *shrd)
-{
-	return iwlagn_mod_params.debug_level;
-}
-#endif
-
-static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page)
-{
-	free_pages(page, shrd->hw_params.rx_page_order);
-}
-
-/**
- * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl_queue_inc_wrap(int index, int n_bd)
-{
-	return ++index & (n_bd - 1);
-}
-
-/**
- * iwl_queue_dec_wrap - decrement queue index, wrap back to end
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl_queue_dec_wrap(int index, int n_bd)
-{
-	return --index & (n_bd - 1);
-}
-
-struct iwl_rx_mem_buffer {
-	dma_addr_t page_dma;
-	struct page *page;
-	struct list_head list;
-};
-
-#define rxb_addr(r) page_address(r->page)
-
-/*
- * mac80211 queues, ACs, hardware queues, FIFOs.
- *
- * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
- *
- * Mac80211 uses the following numbers, which we get as from it
- * by way of skb_get_queue_mapping(skb):
- *
- *	VO	0
- *	VI	1
- *	BE	2
- *	BK	3
- *
- *
- * Regular (not A-MPDU) frames are put into hardware queues corresponding
- * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
- * own queue per aggregation session (RA/TID combination), such queues are
- * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
- * order to map frames to the right queue, we also need an AC->hw queue
- * mapping. This is implemented here.
- *
- * Due to the way hw queues are set up (by the hw specific modules like
- * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity
- * mapping.
- */
-
-static const u8 tid_to_ac[] = {
-	IEEE80211_AC_BE,
-	IEEE80211_AC_BK,
-	IEEE80211_AC_BK,
-	IEEE80211_AC_BE,
-	IEEE80211_AC_VI,
-	IEEE80211_AC_VI,
-	IEEE80211_AC_VO,
-	IEEE80211_AC_VO
-};
-
-static inline int get_ac_from_tid(u16 tid)
-{
-	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
-		return tid_to_ac[tid];
-
-	/* no support for TIDs 8-15 yet */
-	return -EINVAL;
+	return iwlagn_mod_params.debug_level & level;
 }
 
 enum iwl_rxon_context_id {
@@ -530,34 +404,9 @@
 };
 
 int iwlagn_hw_valid_rtc_data_addr(u32 addr);
-void iwl_nic_config(struct iwl_priv *priv);
 const char *get_cmd_string(u8 cmd);
-bool iwl_check_for_ct_kill(struct iwl_priv *priv);
-
-
-/* notification wait support */
-void iwl_abort_notification_waits(struct iwl_shared *shrd);
-void __acquires(wait_entry)
-iwl_init_notification_wait(struct iwl_shared *shrd,
-			      struct iwl_notification_wait *wait_entry,
-			      u8 cmd,
-			      void (*fn)(struct iwl_trans *trans,
-					 struct iwl_rx_packet *pkt,
-					 void *data),
-			      void *fn_data);
-int __must_check __releases(wait_entry)
-iwl_wait_notification(struct iwl_shared *shrd,
-			 struct iwl_notification_wait *wait_entry,
-			 unsigned long timeout);
-void __releases(wait_entry)
-iwl_remove_notification(struct iwl_shared *shrd,
-			   struct iwl_notification_wait *wait_entry);
 
 #define IWL_CMD(x) case x: return #x
-#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
-
-#define IWL_TRAFFIC_ENTRIES	(256)
-#define IWL_TRAFFIC_ENTRY_SIZE  (64)
 
 /*****************************************************
 * DRIVER STATUS FUNCTIONS
@@ -583,46 +432,4 @@
 #define STATUS_CHANNEL_SWITCH_PENDING 19
 #define STATUS_SCAN_COMPLETE	20
 
-static inline int iwl_is_ready(struct iwl_shared *shrd)
-{
-	/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
-	 * set but EXIT_PENDING is not */
-	return test_bit(STATUS_READY, &shrd->status) &&
-	       test_bit(STATUS_GEO_CONFIGURED, &shrd->status) &&
-	       !test_bit(STATUS_EXIT_PENDING, &shrd->status);
-}
-
-static inline int iwl_is_alive(struct iwl_shared *shrd)
-{
-	return test_bit(STATUS_ALIVE, &shrd->status);
-}
-
-static inline int iwl_is_init(struct iwl_shared *shrd)
-{
-	return test_bit(STATUS_INIT, &shrd->status);
-}
-
-static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd)
-{
-	return test_bit(STATUS_RF_KILL_HW, &shrd->status);
-}
-
-static inline int iwl_is_rfkill(struct iwl_shared *shrd)
-{
-	return iwl_is_rfkill_hw(shrd);
-}
-
-static inline int iwl_is_ctkill(struct iwl_shared *shrd)
-{
-	return test_bit(STATUS_CT_KILL, &shrd->status);
-}
-
-static inline int iwl_is_ready_rf(struct iwl_shared *shrd)
-{
-	if (iwl_is_rfkill(shrd))
-		return 0;
-
-	return iwl_is_ready(shrd);
-}
-
 #endif /* #__iwl_shared_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c
index 23eea06..76f7f92 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c
@@ -70,7 +70,6 @@
 #include <net/mac80211.h>
 #include <net/netlink.h>
 
-#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-debug.h"
@@ -79,6 +78,7 @@
 #include "iwl-testmode.h"
 #include "iwl-trans.h"
 #include "iwl-fh.h"
+#include "iwl-prph.h"
 
 
 /* Periphery registers absolute lower bound. This is used in order to
@@ -125,13 +125,15 @@
 	[IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, },
 	[IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, },
 	[IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, },
+
+	[IWL_TM_ATTR_ENABLE_NOTIFICATION] = {.type = NLA_FLAG, },
 };
 
 /*
  * See the struct iwl_rx_packet in iwl-commands.h for the format of the
  * received events from the device
  */
-static inline int get_event_length(struct iwl_rx_mem_buffer *rxb)
+static inline int get_event_length(struct iwl_rx_cmd_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	if (pkt)
@@ -162,7 +164,7 @@
  */
 
 static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
+				      struct iwl_rx_cmd_buffer *rxb)
 {
 	struct ieee80211_hw *hw = priv->hw;
 	struct sk_buff *skb;
@@ -183,7 +185,8 @@
 		return;
 	}
 	NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
-	NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data);
+	/* the length doesn't include len_n_flags field, so add it manually */
+	NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length + sizeof(__le32), data);
 	cfg80211_testmode_event(skb, GFP_ATOMIC);
 	return;
 
@@ -194,7 +197,7 @@
 
 void iwl_testmode_init(struct iwl_priv *priv)
 {
-	priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
+	priv->pre_rx_handler = NULL;
 	priv->testmode_trace.trace_enabled = false;
 	priv->testmode_mem.read_in_progress = false;
 }
@@ -283,7 +286,7 @@
 	IWL_DEBUG_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
 				" len %d\n", cmd.id, cmd.flags, cmd.len[0]);
 
-	ret = iwl_trans_send_cmd(trans(priv), &cmd);
+	ret = iwl_dvm_send_cmd(priv, &cmd);
 	if (ret) {
 		IWL_ERR(priv, "Failed to send hcmd\n");
 		return ret;
@@ -292,7 +295,7 @@
 		return ret;
 
 	/* Handling return of SKB to the user */
-	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	pkt = cmd.resp_pkt;
 	if (!pkt) {
 		IWL_ERR(priv, "HCMD received a null response packet\n");
 		return ret;
@@ -309,7 +312,7 @@
 
 	/* The reply is in a page, that we cannot send to user space. */
 	memcpy(reply_buf, &(pkt->hdr), reply_len);
-	iwl_free_pages(priv->shrd, cmd.reply_page);
+	iwl_free_resp(&cmd);
 
 	NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
 	NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf);
@@ -419,23 +422,23 @@
 	struct iwl_notification_wait calib_wait;
 	int ret;
 
-	iwl_init_notification_wait(priv->shrd, &calib_wait,
-				      CALIBRATION_COMPLETE_NOTIFICATION,
-				      NULL, NULL);
-	ret = iwl_init_alive_start(trans(priv));
+	iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
+				   CALIBRATION_COMPLETE_NOTIFICATION,
+				   NULL, NULL);
+	ret = iwl_init_alive_start(priv);
 	if (ret) {
 		IWL_ERR(priv, "Fail init calibration: %d\n", ret);
 		goto cfg_init_calib_error;
 	}
 
-	ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ);
+	ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ);
 	if (ret)
 		IWL_ERR(priv, "Error detecting"
 			" CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
 	return ret;
 
 cfg_init_calib_error:
-	iwl_remove_notification(priv->shrd, &calib_wait);
+	iwl_remove_notification(&priv->notif_wait, &calib_wait);
 	return ret;
 }
 
@@ -463,6 +466,7 @@
 	unsigned char *rsp_data_ptr = NULL;
 	int status = 0, rsp_data_len = 0;
 	u32 devid, inst_size = 0, data_size = 0;
+	const struct fw_img *img;
 
 	switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
 	case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
@@ -484,18 +488,19 @@
 		break;
 
 	case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
-		status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
+		status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
 		if (status)
 			IWL_ERR(priv, "Error loading init ucode: %d\n", status);
 		break;
 
 	case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
 		iwl_testmode_cfg_init_calib(priv);
+		priv->ucode_loaded = false;
 		iwl_trans_stop_device(trans);
 		break;
 
 	case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
-		status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR);
+		status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
 		if (status) {
 			IWL_ERR(priv,
 				"Error loading runtime ucode: %d\n", status);
@@ -509,8 +514,9 @@
 
 	case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
 		iwl_scan_cancel_timeout(priv, 200);
+		priv->ucode_loaded = false;
 		iwl_trans_stop_device(trans);
-		status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN);
+		status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
 		if (status) {
 			IWL_ERR(priv,
 				"Error loading WOWLAN ucode: %d\n", status);
@@ -553,7 +559,7 @@
 
 	case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
 		IWL_INFO(priv, "uCode version raw: 0x%x\n",
-			 nic(priv)->fw.ucode_ver);
+			 priv->fw->ucode_ver);
 
 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
 		if (!skb) {
@@ -561,7 +567,7 @@
 			return -ENOMEM;
 		}
 		NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION,
-			    nic(priv)->fw.ucode_ver);
+			    priv->fw->ucode_ver);
 		status = cfg80211_testmode_reply(skb);
 		if (status < 0)
 			IWL_ERR(priv, "Error sending msg : %d\n", status);
@@ -588,25 +594,13 @@
 			IWL_ERR(priv, "Memory allocation fail\n");
 			return -ENOMEM;
 		}
-		switch (priv->shrd->ucode_type) {
-		case IWL_UCODE_REGULAR:
-			inst_size = nic(priv)->fw.ucode_rt.code.len;
-			data_size = nic(priv)->fw.ucode_rt.data.len;
-			break;
-		case IWL_UCODE_INIT:
-			inst_size = nic(priv)->fw.ucode_init.code.len;
-			data_size = nic(priv)->fw.ucode_init.data.len;
-			break;
-		case IWL_UCODE_WOWLAN:
-			inst_size = nic(priv)->fw.ucode_wowlan.code.len;
-			data_size = nic(priv)->fw.ucode_wowlan.data.len;
-			break;
-		case IWL_UCODE_NONE:
+		if (!priv->ucode_loaded) {
 			IWL_ERR(priv, "No uCode has not been loaded\n");
-			break;
-		default:
-			IWL_ERR(priv, "Unsupported uCode type\n");
-			break;
+			return -EINVAL;
+		} else {
+			img = &priv->fw->img[priv->shrd->ucode_type];
+			inst_size = img->sec[IWL_UCODE_SECTION_INST].len;
+			data_size = img->sec[IWL_UCODE_SECTION_DATA].len;
 		}
 		NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type);
 		NLA_PUT_U32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size);
@@ -713,7 +707,7 @@
 	return -EMSGSIZE;
 }
 
-static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
+static int iwl_testmode_trace_dump(struct ieee80211_hw *hw,
 				   struct sk_buff *skb,
 				   struct netlink_callback *cb)
 {
@@ -770,9 +764,13 @@
 	}
 
 	owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
-	if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
-		priv->shrd->ucode_owner = owner;
-	else {
+	if (owner == IWL_OWNERSHIP_DRIVER) {
+		priv->ucode_owner = owner;
+		priv->pre_rx_handler = NULL;
+	} else if (owner == IWL_OWNERSHIP_TM) {
+		priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
+		priv->ucode_owner = owner;
+	} else {
 		IWL_ERR(priv, "Invalid owner\n");
 		return -EINVAL;
 	}
@@ -905,9 +903,9 @@
 	}
 }
 
-static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb,
-				   struct sk_buff *skb,
-				   struct netlink_callback *cb)
+static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw,
+				    struct sk_buff *skb,
+				    struct netlink_callback *cb)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
 	int idx, length;
@@ -937,6 +935,20 @@
 	return -ENOBUFS;
 }
 
+static int iwl_testmode_notifications(struct ieee80211_hw *hw,
+	struct nlattr **tb)
+{
+	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+	bool enable;
+
+	enable = nla_get_flag(tb[IWL_TM_ATTR_ENABLE_NOTIFICATION]);
+	if (enable)
+		priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
+	else
+		priv->pre_rx_handler = NULL;
+	return 0;
+}
+
 
 /* The testmode gnl message handler that takes the gnl message from the
  * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
@@ -976,7 +988,7 @@
 		return -ENOMSG;
 	}
 	/* in case multiple accesses to the device happens */
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 
 	switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
 	case IWL_TM_CMD_APP2DEV_UCODE:
@@ -1022,13 +1034,19 @@
 		result = iwl_testmode_indirect_mem(hw, tb);
 		break;
 
+	case IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
+		IWL_DEBUG_INFO(priv, "testmode notifications cmd "
+			"to driver\n");
+		result = iwl_testmode_notifications(hw, tb);
+		break;
+
 	default:
 		IWL_ERR(priv, "Unknown testmode command\n");
 		result = -ENOSYS;
 		break;
 	}
 
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	return result;
 }
 
@@ -1063,21 +1081,21 @@
 	}
 
 	/* in case multiple accesses to the device happens */
-	mutex_lock(&priv->shrd->mutex);
+	mutex_lock(&priv->mutex);
 	switch (cmd) {
 	case IWL_TM_CMD_APP2DEV_READ_TRACE:
 		IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
-		result = iwl_testmode_trace_dump(hw, tb, skb, cb);
+		result = iwl_testmode_trace_dump(hw, skb, cb);
 		break;
 	case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP:
 		IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n");
-		result = iwl_testmode_buffer_dump(hw, tb, skb, cb);
+		result = iwl_testmode_buffer_dump(hw, skb, cb);
 		break;
 	default:
 		result = -EINVAL;
 		break;
 	}
 
-	mutex_unlock(&priv->shrd->mutex);
+	mutex_unlock(&priv->mutex);
 	return result;
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index 69b2e80..6ba211b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h
@@ -122,6 +122,9 @@
  *	Fore reading, a READ command is sent from the userspace and the data
  *	is returned when the user calls a DUMP command.
  *	For writing, only a WRITE command is used.
+ * @IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
+ *	Command to enable/disable notifications (currently RX packets) from the
+ *	driver to userspace.
  */
 enum iwl_tm_cmd_t {
 	IWL_TM_CMD_APP2DEV_UCODE		= 1,
@@ -152,7 +155,8 @@
 	IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ = 26,
 	IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP = 27,
 	IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE = 28,
-	IWL_TM_CMD_MAX				= 29,
+	IWL_TM_CMD_APP2DEV_NOTIFICATIONS	= 29,
+	IWL_TM_CMD_MAX				= 30,
 };
 
 /*
@@ -256,6 +260,10 @@
  *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE this flag
  *	indicates that the user wants to receive the response of the command
  *	in a reply SKB. If it's not present, the response is not returned.
+ * @IWL_TM_ATTR_ENABLE_NOTIFICATIONS:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_NOTIFICATIONS, this
+ *	flag enables (if present) or disables (if not) the forwarding
+ *	to userspace.
  */
 enum iwl_tm_attr_t {
 	IWL_TM_ATTR_NOT_APPLICABLE		= 0,
@@ -282,7 +290,8 @@
 	IWL_TM_ATTR_FW_INST_SIZE		= 21,
 	IWL_TM_ATTR_FW_DATA_SIZE		= 22,
 	IWL_TM_ATTR_UCODE_CMD_SKB		= 23,
-	IWL_TM_ATTR_MAX				= 24,
+	IWL_TM_ATTR_ENABLE_NOTIFICATION		= 24,
+	IWL_TM_ATTR_MAX				= 25,
 };
 
 /* uCode trace buffer */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
index 5b26b71..1c2fe87 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
@@ -32,6 +32,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/skbuff.h>
+#include <linux/wait.h>
 #include <linux/pci.h>
 
 #include "iwl-fh.h"
@@ -49,6 +50,12 @@
 /*This file includes the declaration that are internal to the
  * trans_pcie layer */
 
+struct iwl_rx_mem_buffer {
+	dma_addr_t page_dma;
+	struct page *page;
+	struct list_head list;
+};
+
 /**
  * struct isr_statistics - interrupt statistics
  *
@@ -109,6 +116,26 @@
 	size_t size;
 };
 
+/**
+ * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_queue_inc_wrap(int index, int n_bd)
+{
+	return ++index & (n_bd - 1);
+}
+
+/**
+ * iwl_queue_dec_wrap - decrement queue index, wrap back to end
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_queue_dec_wrap(int index, int n_bd)
+{
+	return --index & (n_bd - 1);
+}
+
 /*
  * This queue number is required for proper operation
  * because the ucode will stop/start the scheduler as
@@ -169,6 +196,7 @@
  * @meta: array of meta data for each command/tx buffer
  * @dma_addr_cmd: physical address of cmd/tx buffer array
  * @txb: array of per-TFD driver data
+ * lock: queue lock
  * @time_stamp: time (in jiffies) of last read_ptr change
  * @need_update: indicates need to update read/write index
  * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
@@ -187,6 +215,7 @@
 	struct iwl_device_cmd **cmd;
 	struct iwl_cmd_meta *meta;
 	struct sk_buff **skbs;
+	spinlock_t lock;
 	unsigned long time_stamp;
 	u8 need_update;
 	u8 sched_retry;
@@ -202,6 +231,7 @@
  * @rxq: all the RX queue data
  * @rx_replenish: work that will be called when buffers need to be allocated
  * @trans: pointer to the generic transport area
+ * @irq - the irq number for the device
  * @irq_requested: true when the irq has been requested
  * @scd_base_addr: scheduler sram base address in SRAM
  * @scd_bc_tbls: pointer to the byte count table of the scheduler
@@ -215,6 +245,10 @@
  * queue_stop_count: tracks what SW queue is stopped
  * @pci_dev: basic pci-network driver stuff
  * @hw_base: pci hardware address support
+ * @ucode_write_complete: indicates that the ucode has been copied.
+ * @ucode_write_waitq: wait queue for uCode load
+ * @status - transport specific status flags
+ * @cmd_queue - command queue number
  */
 struct iwl_trans_pcie {
 	struct iwl_rx_queue rxq;
@@ -231,6 +265,7 @@
 	struct tasklet_struct irq_tasklet;
 	struct isr_statistics isr_stats;
 
+	unsigned int irq;
 	spinlock_t irq_lock;
 	u32 inta_mask;
 	u32 scd_base_addr;
@@ -251,6 +286,13 @@
 	/* PCI bus related data */
 	struct pci_dev *pci_dev;
 	void __iomem *hw_base;
+
+	bool ucode_write_complete;
+	wait_queue_head_t ucode_write_waitq;
+	unsigned long status;
+	u8 cmd_queue;
+	u8 n_no_reclaim_cmds;
+	u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
 };
 
 #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
@@ -285,7 +327,7 @@
 int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id);
 int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
 void iwl_tx_cmd_complete(struct iwl_trans *trans,
-			 struct iwl_rx_mem_buffer *rxb, int handler_status);
+			 struct iwl_rx_cmd_buffer *rxb, int handler_status);
 void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
 					   struct iwl_tx_queue *txq,
 					   u16 byte_cnt);
@@ -318,7 +360,8 @@
 ******************************************************/
 static inline void iwl_disable_interrupts(struct iwl_trans *trans)
 {
-	clear_bit(STATUS_INT_ENABLED, &trans->shrd->status);
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	clear_bit(STATUS_INT_ENABLED, &trans_pcie->status);
 
 	/* disable interrupts from uCode/NIC to host */
 	iwl_write32(trans, CSR_INT_MASK, 0x00000000);
@@ -332,14 +375,19 @@
 
 static inline void iwl_enable_interrupts(struct iwl_trans *trans)
 {
-	struct iwl_trans_pcie *trans_pcie =
-		IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
 	IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
-	set_bit(STATUS_INT_ENABLED, &trans->shrd->status);
+	set_bit(STATUS_INT_ENABLED, &trans_pcie->status);
 	iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
 }
 
+static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
+{
+	IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
+	iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+}
+
 /*
  * we have 8 bits used like this:
  *
@@ -365,7 +413,7 @@
 }
 
 static inline void iwl_wake_queue(struct iwl_trans *trans,
-				  struct iwl_tx_queue *txq, const char *msg)
+				  struct iwl_tx_queue *txq)
 {
 	u8 queue = txq->swq_id;
 	u8 ac = queue & 3;
@@ -376,19 +424,19 @@
 	if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) {
 		if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) {
 			iwl_op_mode_queue_not_full(trans->op_mode, ac);
-			IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d. %s",
-					    hwq, ac, msg);
+			IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d",
+					    hwq, ac);
 		} else {
-			IWL_DEBUG_TX_QUEUES(trans, "Don't wake hwq %d ac %d"
-					    " stop count %d. %s",
-					    hwq, ac, atomic_read(&trans_pcie->
-					    queue_stop_count[ac]), msg);
+			IWL_DEBUG_TX_QUEUES(trans,
+				"Don't wake hwq %d ac %d stop count %d",
+				hwq, ac,
+				atomic_read(&trans_pcie->queue_stop_count[ac]));
 		}
 	}
 }
 
 static inline void iwl_stop_queue(struct iwl_trans *trans,
-				  struct iwl_tx_queue *txq, const char *msg)
+				  struct iwl_tx_queue *txq)
 {
 	u8 queue = txq->swq_id;
 	u8 ac = queue & 3;
@@ -399,34 +447,22 @@
 	if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) {
 		if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) {
 			iwl_op_mode_queue_full(trans->op_mode, ac);
-			IWL_DEBUG_TX_QUEUES(trans, "Stop hwq %d ac %d"
-					    " stop count %d. %s",
-					    hwq, ac, atomic_read(&trans_pcie->
-					    queue_stop_count[ac]), msg);
+			IWL_DEBUG_TX_QUEUES(trans,
+				"Stop hwq %d ac %d stop count %d",
+				hwq, ac,
+				atomic_read(&trans_pcie->queue_stop_count[ac]));
 		} else {
-			IWL_DEBUG_TX_QUEUES(trans, "Don't stop hwq %d ac %d"
-					    " stop count %d. %s",
-					    hwq, ac, atomic_read(&trans_pcie->
-					    queue_stop_count[ac]), msg);
+			IWL_DEBUG_TX_QUEUES(trans,
+				"Don't stop hwq %d ac %d stop count %d",
+				hwq, ac,
+				atomic_read(&trans_pcie->queue_stop_count[ac]));
 		}
 	} else {
-		IWL_DEBUG_TX_QUEUES(trans, "stop hwq %d, but it is stopped/ %s",
-				    hwq, msg);
+		IWL_DEBUG_TX_QUEUES(trans, "stop hwq %d, but it is stopped",
+				    hwq);
 	}
 }
 
-#ifdef ieee80211_stop_queue
-#undef ieee80211_stop_queue
-#endif
-
-#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
-
-#ifdef ieee80211_wake_queue
-#undef ieee80211_wake_queue
-#endif
-
-#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
-
 static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie,
 					int txq_id)
 {
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
index 2c910fd..8b1a798 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
@@ -30,11 +30,9 @@
 #include <linux/wait.h>
 #include <linux/gfp.h>
 
-/*TODO: Remove include to iwl-core.h*/
-#include "iwl-core.h"
+#include "iwl-prph.h"
 #include "iwl-io.h"
 #include "iwl-trans-pcie-int.h"
-#include "iwl-wifi.h"
 #include "iwl-op-mode.h"
 
 #ifdef CONFIG_IWLWIFI_IDI
@@ -142,7 +140,7 @@
 	if (q->need_update == 0)
 		goto exit_unlock;
 
-	if (hw_params(trans).shadow_reg_enable) {
+	if (cfg(trans)->base_params->shadow_reg_enable) {
 		/* shadow register enabled */
 		/* Device expects a multiple of 8 */
 		q->write_actual = (q->write & ~0x7);
@@ -358,6 +356,106 @@
 	iwlagn_rx_replenish(trans_pcie->trans);
 }
 
+static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+	struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
+	struct iwl_device_cmd *cmd;
+	unsigned long flags;
+	int len, err;
+	u16 sequence;
+	struct iwl_rx_cmd_buffer rxcb;
+	struct iwl_rx_packet *pkt;
+	bool reclaim;
+	int index, cmd_index;
+
+	if (WARN_ON(!rxb))
+		return;
+
+	dma_unmap_page(trans->dev, rxb->page_dma,
+		       PAGE_SIZE << hw_params(trans).rx_page_order,
+		       DMA_FROM_DEVICE);
+
+	rxcb._page = rxb->page;
+	pkt = rxb_addr(&rxcb);
+
+	IWL_DEBUG_RX(trans, "%s, 0x%02x\n",
+		     get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+
+
+	len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+	len += sizeof(u32); /* account for status word */
+	trace_iwlwifi_dev_rx(trans->dev, pkt, len);
+
+	/* Reclaim a command buffer only if this packet is a response
+	 *   to a (driver-originated) command.
+	 * If the packet (e.g. Rx frame) originated from uCode,
+	 *   there is no command buffer to reclaim.
+	 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
+	 *   but apparently a few don't get set; catch them here. */
+	reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME);
+	if (reclaim) {
+		int i;
+
+		for (i = 0; i < trans_pcie->n_no_reclaim_cmds; i++) {
+			if (trans_pcie->no_reclaim_cmds[i] == pkt->hdr.cmd) {
+				reclaim = false;
+				break;
+			}
+		}
+	}
+
+	sequence = le16_to_cpu(pkt->hdr.sequence);
+	index = SEQ_TO_INDEX(sequence);
+	cmd_index = get_cmd_index(&txq->q, index);
+
+	if (reclaim)
+		cmd = txq->cmd[cmd_index];
+	else
+		cmd = NULL;
+
+	err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
+
+	/*
+	 * XXX: After here, we should always check rxcb._page
+	 * against NULL before touching it or its virtual
+	 * memory (pkt). Because some rx_handler might have
+	 * already taken or freed the pages.
+	 */
+
+	if (reclaim) {
+		/* Invoke any callbacks, transfer the buffer to caller,
+		 * and fire off the (possibly) blocking
+		 * iwl_trans_send_cmd()
+		 * as we reclaim the driver command queue */
+		if (rxcb._page)
+			iwl_tx_cmd_complete(trans, &rxcb, err);
+		else
+			IWL_WARN(trans, "Claim null rxb?\n");
+	}
+
+	/* page was stolen from us */
+	if (rxcb._page == NULL)
+		rxb->page = NULL;
+
+	/* Reuse the page if possible. For notification packets and
+	 * SKBs that fail to Rx correctly, add them back into the
+	 * rx_free list for reuse later. */
+	spin_lock_irqsave(&rxq->lock, flags);
+	if (rxb->page != NULL) {
+		rxb->page_dma =
+			dma_map_page(trans->dev, rxb->page, 0,
+				PAGE_SIZE << hw_params(trans).rx_page_order,
+				DMA_FROM_DEVICE);
+		list_add_tail(&rxb->list, &rxq->rx_free);
+		rxq->free_count++;
+	} else
+		list_add_tail(&rxb->list, &rxq->rx_used);
+	spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
 /**
  * iwl_rx_handle - Main entry function for receiving responses from uCode
  *
@@ -367,20 +465,12 @@
  */
 static void iwl_rx_handle(struct iwl_trans *trans)
 {
-	struct iwl_rx_mem_buffer *rxb;
-	struct iwl_rx_packet *pkt;
-	struct iwl_trans_pcie *trans_pcie =
-		IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-	struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
-	struct iwl_device_cmd *cmd;
 	u32 r, i;
-	int reclaim;
-	unsigned long flags;
 	u8 fill_rx = 0;
 	u32 count = 8;
 	int total_empty;
-	int index, cmd_index;
 
 	/* uCode's read index (stored in shared DRAM) indicates the last Rx
 	 * buffer that the driver may process (last buffer filled by ucode). */
@@ -400,102 +490,14 @@
 		fill_rx = 1;
 
 	while (i != r) {
-		int len, err;
-		u16 sequence;
+		struct iwl_rx_mem_buffer *rxb;
 
 		rxb = rxq->queue[i];
-
-		/* If an RXB doesn't have a Rx queue slot associated with it,
-		 * then a bug has been introduced in the queue refilling
-		 * routines -- catch it here */
-		if (WARN_ON(rxb == NULL)) {
-			i = (i + 1) & RX_QUEUE_MASK;
-			continue;
-		}
-
 		rxq->queue[i] = NULL;
 
-		dma_unmap_page(trans->dev, rxb->page_dma,
-			       PAGE_SIZE << hw_params(trans).rx_page_order,
-			       DMA_FROM_DEVICE);
-		pkt = rxb_addr(rxb);
+		IWL_DEBUG_RX(trans, "rxbuf: r = %d, i = %d (%p)\n", rxb);
 
-		IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r,
-			i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
-
-		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
-		len += sizeof(u32); /* account for status word */
-		trace_iwlwifi_dev_rx(priv(trans), pkt, len);
-
-		/* Reclaim a command buffer only if this packet is a response
-		 *   to a (driver-originated) command.
-		 * If the packet (e.g. Rx frame) originated from uCode,
-		 *   there is no command buffer to reclaim.
-		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
-		 *   but apparently a few don't get set; catch them here. */
-		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
-			(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
-			(pkt->hdr.cmd != REPLY_RX) &&
-			(pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
-			(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
-			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
-			(pkt->hdr.cmd != REPLY_TX);
-
-		sequence = le16_to_cpu(pkt->hdr.sequence);
-		index = SEQ_TO_INDEX(sequence);
-		cmd_index = get_cmd_index(&txq->q, index);
-
-		if (reclaim)
-			cmd = txq->cmd[cmd_index];
-		else
-			cmd = NULL;
-
-		/* warn if this is cmd response / notification and the uCode
-		 * didn't set the SEQ_RX_FRAME for a frame that is
-		 * uCode-originated
-		 * If you saw this code after the second half of 2012, then
-		 * please remove it
-		 */
-		WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false &&
-		     (!(pkt->hdr.sequence & SEQ_RX_FRAME)),
-		     "reclaim is false, SEQ_RX_FRAME unset: %s\n",
-		     get_cmd_string(pkt->hdr.cmd));
-
-		err = iwl_op_mode_rx(trans->op_mode, rxb, cmd);
-
-		/*
-		 * XXX: After here, we should always check rxb->page
-		 * against NULL before touching it or its virtual
-		 * memory (pkt). Because some rx_handler might have
-		 * already taken or freed the pages.
-		 */
-
-		if (reclaim) {
-			/* Invoke any callbacks, transfer the buffer to caller,
-			 * and fire off the (possibly) blocking
-			 * iwl_trans_send_cmd()
-			 * as we reclaim the driver command queue */
-			if (rxb->page)
-				iwl_tx_cmd_complete(trans, rxb, err);
-			else
-				IWL_WARN(trans, "Claim null rxb?\n");
-		}
-
-		/* Reuse the page if possible. For notification packets and
-		 * SKBs that fail to Rx correctly, add them back into the
-		 * rx_free list for reuse later. */
-		spin_lock_irqsave(&rxq->lock, flags);
-		if (rxb->page != NULL) {
-			rxb->page_dma = dma_map_page(trans->dev, rxb->page,
-				0, PAGE_SIZE <<
-				    hw_params(trans).rx_page_order,
-				DMA_FROM_DEVICE);
-			list_add_tail(&rxb->list, &rxq->rx_free);
-			rxq->free_count++;
-		} else
-			list_add_tail(&rxb->list, &rxq->rx_used);
-
-		spin_unlock_irqrestore(&rxq->lock, flags);
+		iwl_rx_handle_rxbuf(trans, rxb);
 
 		i = (i + 1) & RX_QUEUE_MASK;
 		/* If there are a lot of unused frames,
@@ -591,17 +593,16 @@
 {
 	u32 base;
 	struct iwl_error_event_table table;
-	struct iwl_nic *nic = nic(trans);
 	struct iwl_trans_pcie *trans_pcie =
 		IWL_TRANS_GET_PCIE_TRANS(trans);
 
 	base = trans->shrd->device_pointers.error_event_table;
 	if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
 		if (!base)
-			base = nic->init_errlog_ptr;
+			base = trans->shrd->fw->init_errlog_ptr;
 	} else {
 		if (!base)
-			base = nic->inst_errlog_ptr;
+			base = trans->shrd->fw->inst_errlog_ptr;
 	}
 
 	if (!iwlagn_hw_valid_rtc_data_addr(base)) {
@@ -623,7 +624,7 @@
 
 	trans_pcie->isr_stats.err_code = table.error_id;
 
-	trace_iwlwifi_dev_ucode_error(priv(nic), table.error_id, table.tsf_low,
+	trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low,
 				      table.data1, table.data2, table.line,
 				      table.blink1, table.blink2, table.ilink1,
 				      table.ilink2, table.bcon_time, table.gp1,
@@ -683,13 +684,13 @@
 		 */
 		clear_bit(STATUS_READY, &trans->shrd->status);
 		clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
-		wake_up(&trans->shrd->wait_command_queue);
+		wake_up(&trans->wait_command_queue);
 		IWL_ERR(trans, "RF is used by WiMAX\n");
 		return;
 	}
 
 	IWL_ERR(trans, "Loaded firmware version: %s\n",
-		nic(trans)->fw.fw_version);
+		trans->shrd->fw->fw_version);
 
 	iwl_dump_nic_error_log(trans);
 	iwl_dump_csr(trans);
@@ -715,7 +716,6 @@
 	u32 ptr;        /* SRAM byte address of log data */
 	u32 ev, time, data; /* event log data */
 	unsigned long reg_flags;
-	struct iwl_nic *nic = nic(trans);
 
 	if (num_events == 0)
 		return pos;
@@ -723,10 +723,10 @@
 	base = trans->shrd->device_pointers.log_event_table;
 	if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
 		if (!base)
-			base = nic->init_evtlog_ptr;
+			base = trans->shrd->fw->init_evtlog_ptr;
 	} else {
 		if (!base)
-			base = nic->inst_evtlog_ptr;
+			base = trans->shrd->fw->inst_evtlog_ptr;
 	}
 
 	if (mode == 0)
@@ -738,11 +738,11 @@
 
 	/* Make sure device is powered up for SRAM reads */
 	spin_lock_irqsave(&trans->reg_lock, reg_flags);
-	iwl_grab_nic_access(trans);
+	if (unlikely(!iwl_grab_nic_access(trans)))
+		goto out_unlock;
 
 	/* Set starting address; reads will auto-increment */
 	iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr);
-	rmb();
 
 	/* "time" is actually "data" for mode 0 (no timestamp).
 	* place event id # at far right for easier visual parsing. */
@@ -756,7 +756,7 @@
 						"EVT_LOG:0x%08x:%04u\n",
 						time, ev);
 			} else {
-				trace_iwlwifi_dev_ucode_event(priv(trans), 0,
+				trace_iwlwifi_dev_ucode_event(trans->dev, 0,
 					time, ev);
 				IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n",
 					time, ev);
@@ -770,7 +770,7 @@
 			} else {
 				IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n",
 					time, data, ev);
-				trace_iwlwifi_dev_ucode_event(priv(trans), time,
+				trace_iwlwifi_dev_ucode_event(trans->dev, time,
 					data, ev);
 			}
 		}
@@ -778,6 +778,7 @@
 
 	/* Allow device to power down */
 	iwl_release_nic_access(trans);
+out_unlock:
 	spin_unlock_irqrestore(&trans->reg_lock, reg_flags);
 	return pos;
 }
@@ -832,17 +833,16 @@
 	u32 logsize;
 	int pos = 0;
 	size_t bufsz = 0;
-	struct iwl_nic *nic = nic(trans);
 
 	base = trans->shrd->device_pointers.log_event_table;
 	if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
-		logsize = nic->init_evtlog_size;
+		logsize = trans->shrd->fw->init_evtlog_size;
 		if (!base)
-			base = nic->init_evtlog_ptr;
+			base = trans->shrd->fw->init_evtlog_ptr;
 	} else {
-		logsize = nic->inst_evtlog_size;
+		logsize = trans->shrd->fw->inst_evtlog_size;
 		if (!base)
-			base = nic->inst_evtlog_ptr;
+			base = trans->shrd->fw->inst_evtlog_ptr;
 	}
 
 	if (!iwlagn_hw_valid_rtc_data_addr(base)) {
@@ -881,7 +881,7 @@
 	}
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log)
+	if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log)
 		size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
 			? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
 #else
@@ -901,7 +901,7 @@
 		if (!*buf)
 			return -ENOMEM;
 	}
-	if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) {
+	if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) {
 		/*
 		 * if uCode has wrapped back to top of log,
 		 * start at the oldest entry,
@@ -960,7 +960,7 @@
 	inta = trans_pcie->inta;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) {
+	if (iwl_have_debug_level(IWL_DL_ISR)) {
 		/* just for debug */
 		inta_mask = iwl_read32(trans, CSR_INT_MASK);
 		IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ",
@@ -989,7 +989,7 @@
 	}
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
+	if (iwl_have_debug_level(IWL_DL_ISR)) {
 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
 		if (inta & CSR_INT_BIT_SCD) {
 			IWL_DEBUG_ISR(trans, "Scheduler finished to transmit "
@@ -1009,30 +1009,16 @@
 
 	/* HW RF KILL switch toggled */
 	if (inta & CSR_INT_BIT_RF_KILL) {
-		int hw_rf_kill = 0;
-		if (!(iwl_read32(trans, CSR_GP_CNTRL) &
-				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
-			hw_rf_kill = 1;
+		bool hw_rfkill;
 
+		hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
 		IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
-				hw_rf_kill ? "disable radio" : "enable radio");
+				hw_rfkill ? "disable radio" : "enable radio");
 
 		isr_stats->rfkill++;
 
-		/* driver only loads ucode once setting the interface up.
-		 * the driver allows loading the ucode even if the radio
-		 * is killed. Hence update the killswitch state here. The
-		 * rfkill handler will care about restarting if needed.
-		 */
-		if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) {
-			if (hw_rf_kill)
-				set_bit(STATUS_RF_KILL_HW,
-					&trans->shrd->status);
-			else
-				clear_bit(STATUS_RF_KILL_HW,
-					  &trans->shrd->status);
-			iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rf_kill);
-		}
+		iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 
 		handled |= CSR_INT_BIT_RF_KILL;
 	}
@@ -1057,7 +1043,7 @@
 	if (inta & CSR_INT_BIT_WAKEUP) {
 		IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
 		iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq);
-		for (i = 0; i < hw_params(trans).max_txq_num; i++)
+		for (i = 0; i < cfg(trans)->base_params->num_of_queues; i++)
 			iwl_txq_update_write_ptr(trans,
 						 &trans_pcie->txq[i]);
 
@@ -1122,8 +1108,8 @@
 		isr_stats->tx++;
 		handled |= CSR_INT_BIT_FH_TX;
 		/* Wake up uCode load routine, now that load is complete */
-		trans->ucode_write_complete = 1;
-		wake_up(&trans->shrd->wait_command_queue);
+		trans_pcie->ucode_write_complete = true;
+		wake_up(&trans_pcie->ucode_write_waitq);
 	}
 
 	if (inta & ~handled) {
@@ -1138,13 +1124,11 @@
 
 	/* Re-enable all interrupts */
 	/* only Re-enable if disabled by irq */
-	if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status))
+	if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status))
 		iwl_enable_interrupts(trans);
 	/* Re-enable RF_KILL if it occurred */
-	else if (handled & CSR_INT_BIT_RF_KILL) {
-		IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
-		iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
-	}
+	else if (handled & CSR_INT_BIT_RF_KILL)
+		iwl_enable_rfkill_int(trans);
 }
 
 /******************************************************************************
@@ -1269,7 +1253,7 @@
 	if (!trans)
 		return IRQ_NONE;
 
-	trace_iwlwifi_dev_irq(priv(trans));
+	trace_iwlwifi_dev_irq(trans->dev);
 
 	trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
@@ -1301,7 +1285,7 @@
 	}
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
+	if (iwl_have_debug_level(IWL_DL_ISR)) {
 		inta_fh = iwl_read32(trans, CSR_FH_INT_STATUS);
 		IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, "
 			      "fh 0x%08x\n", inta, inta_mask, inta_fh);
@@ -1312,7 +1296,7 @@
 	/* iwl_irq_tasklet() will service interrupts and re-enable them */
 	if (likely(inta))
 		tasklet_schedule(&trans_pcie->irq_tasklet);
-	else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+	else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
 			!trans_pcie->inta)
 		iwl_enable_interrupts(trans);
 
@@ -1323,7 +1307,7 @@
  none:
 	/* re-enable interrupts here since we don't have anything to service. */
 	/* only Re-enable if disabled by irq  and no schedules tasklet. */
-	if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+	if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
 		!trans_pcie->inta)
 		iwl_enable_interrupts(trans);
 
@@ -1359,7 +1343,7 @@
 	if (!trans_pcie->use_ict)
 		return iwl_isr(irq, data);
 
-	trace_iwlwifi_dev_irq(priv(trans));
+	trace_iwlwifi_dev_irq(trans->dev);
 
 	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
@@ -1376,7 +1360,7 @@
 	 * This may be due to IRQ shared with another device,
 	 * or due to sporadic interrupts thrown from our NIC. */
 	read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
-	trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index, read);
+	trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read);
 	if (!read) {
 		IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
 		goto none;
@@ -1395,7 +1379,7 @@
 			iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
 
 		read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
-		trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index,
+		trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
 					   read);
 	} while (read);
 
@@ -1423,7 +1407,7 @@
 	/* iwl_irq_tasklet() will service interrupts and re-enable them */
 	if (likely(inta))
 		tasklet_schedule(&trans_pcie->irq_tasklet);
-	else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+	else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
 		 !trans_pcie->inta) {
 		/* Allow interrupt if was disabled by this handler and
 		 * no tasklet was schedules, We should not enable interrupt,
@@ -1439,7 +1423,7 @@
 	/* re-enable interrupts here since we don't have anything to service.
 	 * only Re-enable if disabled by irq.
 	 */
-	if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+	if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
 	    !trans_pcie->inta)
 		iwl_enable_interrupts(trans);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
index 82e3448..a66ad9b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
@@ -41,6 +41,43 @@
 #define IWL_TX_CRC_SIZE 4
 #define IWL_TX_DELIMITER_SIZE 4
 
+/*
+ * mac80211 queues, ACs, hardware queues, FIFOs.
+ *
+ * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
+ *
+ * Mac80211 uses the following numbers, which we get as from it
+ * by way of skb_get_queue_mapping(skb):
+ *
+ *	VO	0
+ *	VI	1
+ *	BE	2
+ *	BK	3
+ *
+ *
+ * Regular (not A-MPDU) frames are put into hardware queues corresponding
+ * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
+ * own queue per aggregation session (RA/TID combination), such queues are
+ * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
+ * order to map frames to the right queue, we also need an AC->hw queue
+ * mapping. This is implemented here.
+ *
+ * Due to the way hw queues are set up (by the hw specific code), the AC->hw
+ * queue mapping is the identity mapping.
+ */
+
+static const u8 tid_to_ac[] = {
+	IEEE80211_AC_BE,
+	IEEE80211_AC_BK,
+	IEEE80211_AC_BK,
+	IEEE80211_AC_BE,
+	IEEE80211_AC_VI,
+	IEEE80211_AC_VI,
+	IEEE80211_AC_VO,
+	IEEE80211_AC_VO
+};
+
+
 /**
  * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
  */
@@ -99,7 +136,7 @@
 	if (txq->need_update == 0)
 		return;
 
-	if (hw_params(trans).shadow_reg_enable) {
+	if (cfg(trans)->base_params->shadow_reg_enable) {
 		/* shadow register enabled */
 		iwl_write32(trans, HBUS_TARG_WRPTR,
 			    txq->q.write_ptr | (txq_id << 8));
@@ -217,6 +254,8 @@
 {
 	struct iwl_tfd *tfd_tmp = txq->tfds;
 
+	lockdep_assert_held(&txq->lock);
+
 	iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], dma_dir);
 
 	/* free SKB */
@@ -358,7 +397,7 @@
 
 	WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
 
-	if (txq_id != trans->shrd->cmd_queue)
+	if (txq_id != trans_pcie->cmd_queue)
 		sta_id = tx_cmd->sta_id;
 
 	bc_ent = cpu_to_le16(1 | (sta_id << 12));
@@ -440,6 +479,15 @@
 			scd_retry ? "BA" : "AC/CMD", txq_id);
 }
 
+static inline int get_ac_from_tid(u16 tid)
+{
+	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+		return tid_to_ac[tid];
+
+	/* no support for TIDs 8-15 yet */
+	return -EINVAL;
+}
+
 static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie,
 				    u8 ctx, u16 tid)
 {
@@ -547,7 +595,8 @@
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int txq_id;
 
-	for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
+	for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
+	     txq_id++)
 		if (!test_and_set_bit(txq_id,
 					&trans_pcie->txq_ctx_active_msk))
 			return txq_id;
@@ -616,15 +665,13 @@
 static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
+	struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
 	struct iwl_queue *q = &txq->q;
 	struct iwl_device_cmd *out_cmd;
 	struct iwl_cmd_meta *out_meta;
 	dma_addr_t phys_addr;
-	unsigned long flags;
 	u32 idx;
 	u16 copy_size, cmd_size;
-	bool is_ct_kill = false;
 	bool had_nocopy = false;
 	int i;
 	u8 *cmd_dest;
@@ -639,12 +686,6 @@
 		return -EIO;
 	}
 
-	if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) &&
-	    !(cmd->flags & CMD_ON_DEMAND)) {
-		IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n");
-		return -EIO;
-	}
-
 	copy_size = sizeof(out_cmd->hdr);
 	cmd_size = sizeof(out_cmd->hdr);
 
@@ -674,23 +715,13 @@
 	if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
 		return -EINVAL;
 
-	if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) {
-		IWL_WARN(trans, "Not sending command - %s KILL\n",
-			 iwl_is_rfkill(trans->shrd) ? "RF" : "CT");
-		return -EIO;
-	}
-
-	spin_lock_irqsave(&trans->hcmd_lock, flags);
+	spin_lock_bh(&txq->lock);
 
 	if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
-		spin_unlock_irqrestore(&trans->hcmd_lock, flags);
+		spin_unlock_bh(&txq->lock);
 
 		IWL_ERR(trans, "No space in command queue\n");
-		is_ct_kill = iwl_check_for_ct_kill(priv(trans));
-		if (!is_ct_kill) {
-			IWL_ERR(trans, "Restarting adapter queue is full\n");
-			iwl_op_mode_nic_error(trans->op_mode);
-		}
+		iwl_op_mode_cmd_queue_full(trans->op_mode);
 		return -ENOSPC;
 	}
 
@@ -707,7 +738,7 @@
 	out_cmd->hdr.cmd = cmd->id;
 	out_cmd->hdr.flags = 0;
 	out_cmd->hdr.sequence =
-		cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) |
+		cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->cmd_queue) |
 					 INDEX_TO_SEQ(q->write_ptr));
 
 	/* and copy the data that needs to be copied */
@@ -727,7 +758,7 @@
 			get_cmd_string(out_cmd->hdr.cmd),
 			out_cmd->hdr.cmd,
 			le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
-			q->write_ptr, idx, trans->shrd->cmd_queue);
+			q->write_ptr, idx, trans_pcie->cmd_queue);
 
 	phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size,
 				DMA_BIDIRECTIONAL);
@@ -779,7 +810,7 @@
 	/* check that tracing gets all possible blocks */
 	BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
 #ifdef CONFIG_IWLWIFI_DEVICE_TRACING
-	trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags,
+	trace_iwlwifi_dev_hcmd(trans->dev, cmd->flags,
 			       trace_bufs[0], trace_lens[0],
 			       trace_bufs[1], trace_lens[1],
 			       trace_bufs[2], trace_lens[2]);
@@ -790,7 +821,7 @@
 	iwl_txq_update_write_ptr(trans, txq);
 
  out:
-	spin_unlock_irqrestore(&trans->hcmd_lock, flags);
+	spin_unlock_bh(&txq->lock);
 	return idx;
 }
 
@@ -809,6 +840,8 @@
 	struct iwl_queue *q = &txq->q;
 	int nfreed = 0;
 
+	lockdep_assert_held(&txq->lock);
+
 	if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
 		IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), "
 			  "index %d is out of range [0-%d] %d %d.\n", __func__,
@@ -838,7 +871,7 @@
  * will be executed.  The attached skb (if present) will only be freed
  * if the callback returns 1
  */
-void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
+void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
 			 int handler_status)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -849,21 +882,22 @@
 	struct iwl_device_cmd *cmd;
 	struct iwl_cmd_meta *meta;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
-	unsigned long flags;
+	struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
 
 	/* If a Tx command is being handled and it isn't in the actual
 	 * command queue then there a command routing bug has been introduced
 	 * in the queue management code. */
-	if (WARN(txq_id != trans->shrd->cmd_queue,
+	if (WARN(txq_id != trans_pcie->cmd_queue,
 		 "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
-		  txq_id, trans->shrd->cmd_queue, sequence,
-		  trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr,
-		  trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) {
+		  txq_id, trans_pcie->cmd_queue, sequence,
+		  trans_pcie->txq[trans_pcie->cmd_queue].q.read_ptr,
+		  trans_pcie->txq[trans_pcie->cmd_queue].q.write_ptr)) {
 		iwl_print_hex_error(trans, pkt, 32);
 		return;
 	}
 
+	spin_lock(&txq->lock);
+
 	cmd_index = get_cmd_index(&txq->q, index);
 	cmd = txq->cmd[cmd_index];
 	meta = &txq->meta[cmd_index];
@@ -875,12 +909,13 @@
 
 	/* Input error checking is done when commands are added to queue. */
 	if (meta->flags & CMD_WANT_SKB) {
-		meta->source->reply_page = (unsigned long)rxb_addr(rxb);
-		meta->source->handler_status = handler_status;
-		rxb->page = NULL;
-	}
+		struct page *p = rxb_steal_page(rxb);
 
-	spin_lock_irqsave(&trans->hcmd_lock, flags);
+		meta->source->resp_pkt = pkt;
+		meta->source->_rx_page_addr = (unsigned long)page_address(p);
+		meta->source->_rx_page_order = hw_params(trans).rx_page_order;
+		meta->source->handler_status = handler_status;
+	}
 
 	iwl_hcmd_queue_reclaim(trans, txq_id, index);
 
@@ -893,12 +928,12 @@
 		clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
 		IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
 			       get_cmd_string(cmd->hdr.cmd));
-		wake_up(&trans->shrd->wait_command_queue);
+		wake_up(&trans->wait_command_queue);
 	}
 
 	meta->flags = 0;
 
-	spin_unlock_irqrestore(&trans->hcmd_lock, flags);
+	spin_unlock(&txq->lock);
 }
 
 #define HOST_COMPLETE_TIMEOUT (2 * HZ)
@@ -912,12 +947,9 @@
 		return -EINVAL;
 
 
-	if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
-		return -EBUSY;
-
 	ret = iwl_enqueue_hcmd(trans, cmd);
 	if (ret < 0) {
-		IWL_DEBUG_QUIET_RFKILL(trans,
+		IWL_ERR(trans,
 			"Error sending %s: enqueue_hcmd failed: %d\n",
 			  get_cmd_string(cmd->id), ret);
 		return ret;
@@ -931,26 +963,22 @@
 	int cmd_idx;
 	int ret;
 
-	lockdep_assert_held(&trans->shrd->mutex);
-
 	IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
 			get_cmd_string(cmd->id));
 
-	if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
-		return -EBUSY;
-
-
-	if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) {
-		IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n",
-			       get_cmd_string(cmd->id));
-		return -ECANCELED;
-	}
 	if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
 		IWL_ERR(trans, "Command %s failed: FW Error\n",
 			       get_cmd_string(cmd->id));
 		return -EIO;
 	}
-	set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+
+	if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE,
+				     &trans->shrd->status))) {
+		IWL_ERR(trans, "Command %s: a command is already active!\n",
+			get_cmd_string(cmd->id));
+		return -EIO;
+	}
+
 	IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
 			get_cmd_string(cmd->id));
 
@@ -958,27 +986,27 @@
 	if (cmd_idx < 0) {
 		ret = cmd_idx;
 		clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
-		IWL_DEBUG_QUIET_RFKILL(trans,
+		IWL_ERR(trans,
 			"Error sending %s: enqueue_hcmd failed: %d\n",
 			  get_cmd_string(cmd->id), ret);
 		return ret;
 	}
 
-	ret = wait_event_timeout(trans->shrd->wait_command_queue,
+	ret = wait_event_timeout(trans->wait_command_queue,
 			!test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status),
 			HOST_COMPLETE_TIMEOUT);
 	if (!ret) {
 		if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) {
 			struct iwl_tx_queue *txq =
-				&trans_pcie->txq[trans->shrd->cmd_queue];
+				&trans_pcie->txq[trans_pcie->cmd_queue];
 			struct iwl_queue *q = &txq->q;
 
-			IWL_DEBUG_QUIET_RFKILL(trans,
+			IWL_ERR(trans,
 				"Error sending %s: time out after %dms.\n",
 				get_cmd_string(cmd->id),
 				jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
 
-			IWL_DEBUG_QUIET_RFKILL(trans,
+			IWL_ERR(trans,
 				"Current CMD queue read_ptr %d write_ptr %d\n",
 				q->read_ptr, q->write_ptr);
 
@@ -990,7 +1018,7 @@
 		}
 	}
 
-	if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
+	if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) {
 		IWL_ERR(trans, "Error: Response NULL in '%s'\n",
 			  get_cmd_string(cmd->id));
 		ret = -EIO;
@@ -1007,13 +1035,13 @@
 		 * in later, it will possibly set an invalid
 		 * address (cmd->meta.source).
 		 */
-		trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &=
+		trans_pcie->txq[trans_pcie->cmd_queue].meta[cmd_idx].flags &=
 							~CMD_WANT_SKB;
 	}
 
-	if (cmd->reply_page) {
-		iwl_free_pages(trans->shrd, cmd->reply_page);
-		cmd->reply_page = 0;
+	if (cmd->resp_pkt) {
+		iwl_free_resp(cmd);
+		cmd->resp_pkt = NULL;
 	}
 
 	return ret;
@@ -1038,9 +1066,11 @@
 	int freed = 0;
 
 	/* This function is not meant to release cmd queue*/
-	if (WARN_ON(txq_id == trans->shrd->cmd_queue))
+	if (WARN_ON(txq_id == trans_pcie->cmd_queue))
 		return 0;
 
+	lockdep_assert_held(&txq->lock);
+
 	/*Since we free until index _not_ inclusive, the one before index is
 	 * the last we will free. This one must be used */
 	last_to_free = iwl_queue_dec_wrap(index, q->n_bd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index 9f8b239..b4f796c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -75,8 +75,12 @@
 #include "iwl-shared.h"
 #include "iwl-eeprom.h"
 #include "iwl-agn-hw.h"
-#include "iwl-core.h"
-#include "iwl-ucode.h"
+
+#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
+
+#define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie)	\
+	(((1<<cfg(trans)->base_params->num_of_queues) - 1) &\
+	(~(1<<(trans_pcie)->cmd_queue)))
 
 static int iwl_trans_rx_alloc(struct iwl_trans *trans)
 {
@@ -301,6 +305,7 @@
 {
 	size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
 	int i;
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
 	if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds))
 		return -EINVAL;
@@ -313,7 +318,7 @@
 	if (!txq->meta || !txq->cmd)
 		goto error;
 
-	if (txq_id == trans->shrd->cmd_queue)
+	if (txq_id == trans_pcie->cmd_queue)
 		for (i = 0; i < slots_num; i++) {
 			txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),
 						GFP_KERNEL);
@@ -324,7 +329,7 @@
 	/* Alloc driver data array and TFD circular buffer */
 	/* Driver private data, only for Tx (not command) queues,
 	 * not shared with device. */
-	if (txq_id != trans->shrd->cmd_queue) {
+	if (txq_id != trans_pcie->cmd_queue) {
 		txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->skbs[0]),
 				    GFP_KERNEL);
 		if (!txq->skbs) {
@@ -352,7 +357,7 @@
 	txq->skbs = NULL;
 	/* since txq->cmd has been zeroed,
 	 * all non allocated cmd[i] will be NULL */
-	if (txq->cmd && txq_id == trans->shrd->cmd_queue)
+	if (txq->cmd && txq_id == trans_pcie->cmd_queue)
 		for (i = 0; i < slots_num; i++)
 			kfree(txq->cmd[i]);
 	kfree(txq->meta);
@@ -390,6 +395,8 @@
 	if (ret)
 		return ret;
 
+	spin_lock_init(&txq->lock);
+
 	/*
 	 * Tell nic where to find circular buffer of Tx Frame Descriptors for
 	 * given Tx queue, and enable the DMA channel used for that queue.
@@ -409,8 +416,6 @@
 	struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
 	struct iwl_queue *q = &txq->q;
 	enum dma_data_direction dma_dir;
-	unsigned long flags;
-	spinlock_t *lock;
 
 	if (!q->n_bd)
 		return;
@@ -418,22 +423,19 @@
 	/* In the command queue, all the TBs are mapped as BIDI
 	 * so unmap them as such.
 	 */
-	if (txq_id == trans->shrd->cmd_queue) {
+	if (txq_id == trans_pcie->cmd_queue)
 		dma_dir = DMA_BIDIRECTIONAL;
-		lock = &trans->hcmd_lock;
-	} else {
+	else
 		dma_dir = DMA_TO_DEVICE;
-		lock = &trans->shrd->sta_lock;
-	}
 
-	spin_lock_irqsave(lock, flags);
+	spin_lock_bh(&txq->lock);
 	while (q->write_ptr != q->read_ptr) {
 		/* The read_ptr needs to bound by q->n_window */
 		iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr),
 				    dma_dir);
 		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
 	}
-	spin_unlock_irqrestore(lock, flags);
+	spin_unlock_bh(&txq->lock);
 }
 
 /**
@@ -457,7 +459,7 @@
 
 	/* De-alloc array of command/tx buffers */
 
-	if (txq_id == trans->shrd->cmd_queue)
+	if (txq_id == trans_pcie->cmd_queue)
 		for (i = 0; i < txq->q.n_window; i++)
 			kfree(txq->cmd[i]);
 
@@ -495,7 +497,7 @@
 	/* Tx queues */
 	if (trans_pcie->txq) {
 		for (txq_id = 0;
-		     txq_id < hw_params(trans).max_txq_num; txq_id++)
+		     txq_id < cfg(trans)->base_params->num_of_queues; txq_id++)
 			iwl_tx_queue_free(trans, txq_id);
 	}
 
@@ -520,7 +522,7 @@
 	int txq_id, slots_num;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
-	u16 scd_bc_tbls_size = hw_params(trans).max_txq_num *
+	u16 scd_bc_tbls_size = cfg(trans)->base_params->num_of_queues *
 			sizeof(struct iwlagn_scd_bc_tbl);
 
 	/*It is not allowed to alloc twice, so warn when this happens.
@@ -544,7 +546,7 @@
 		goto error;
 	}
 
-	trans_pcie->txq = kcalloc(hw_params(trans).max_txq_num,
+	trans_pcie->txq = kcalloc(cfg(trans)->base_params->num_of_queues,
 				  sizeof(struct iwl_tx_queue), GFP_KERNEL);
 	if (!trans_pcie->txq) {
 		IWL_ERR(trans, "Not enough memory for txq\n");
@@ -553,8 +555,9 @@
 	}
 
 	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
-	for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
-		slots_num = (txq_id == trans->shrd->cmd_queue) ?
+	for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
+	     txq_id++) {
+		slots_num = (txq_id == trans_pcie->cmd_queue) ?
 					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
 		ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id],
 					  slots_num, txq_id);
@@ -598,8 +601,9 @@
 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
-	for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
-		slots_num = (txq_id == trans->shrd->cmd_queue) ?
+	for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
+	     txq_id++) {
+		slots_num = (txq_id == trans_pcie->cmd_queue) ?
 					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
 		ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id],
 					 slots_num, txq_id);
@@ -687,6 +691,7 @@
  */
 static int iwl_apm_init(struct iwl_trans *trans)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int ret = 0;
 	IWL_DEBUG_INFO(trans, "Init card's basic functions\n");
 
@@ -756,7 +761,7 @@
 	iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
 			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 
-	set_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status);
+	set_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
 
 out:
 	return ret;
@@ -782,9 +787,10 @@
 
 static void iwl_apm_stop(struct iwl_trans *trans)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n");
 
-	clear_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status);
+	clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
 
 	/* Stop device's DMA activity */
 	iwl_apm_stop_master(trans);
@@ -819,7 +825,7 @@
 
 	iwl_set_pwr_vmain(trans);
 
-	iwl_nic_config(priv(trans));
+	iwl_op_mode_nic_config(trans->op_mode);
 
 #ifndef CONFIG_IWLWIFI_IDI
 	/* Allocate the RX queue, or reset if it is already allocated */
@@ -830,14 +836,12 @@
 	if (iwl_tx_init(trans))
 		return -ENOMEM;
 
-	if (hw_params(trans).shadow_reg_enable) {
+	if (cfg(trans)->base_params->shadow_reg_enable) {
 		/* enable shadow regs in HW */
 		iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL,
 			0x800FFFFF);
 	}
 
-	set_bit(STATUS_INIT, &trans->shrd->status);
-
 	return 0;
 }
 
@@ -947,14 +951,16 @@
 /*
  * ucode
  */
-static int iwl_load_section(struct iwl_trans *trans, const char *name,
-				struct fw_desc *image, u32 dst_addr)
+static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
+			    const struct fw_desc *section)
 {
-	dma_addr_t phy_addr = image->p_addr;
-	u32 byte_cnt = image->len;
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	dma_addr_t phy_addr = section->p_addr;
+	u32 byte_cnt = section->len;
+	u32 dst_addr = section->offset;
 	int ret;
 
-	trans->ucode_write_complete = 0;
+	trans_pcie->ucode_write_complete = false;
 
 	iwl_write_direct32(trans,
 		FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
@@ -984,31 +990,33 @@
 		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE	|
 		FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
 
-	IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name);
-	ret = wait_event_timeout(trans->shrd->wait_command_queue,
-				 trans->ucode_write_complete, 5 * HZ);
+	IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n",
+		     section_num);
+	ret = wait_event_timeout(trans_pcie->ucode_write_waitq,
+				 trans_pcie->ucode_write_complete, 5 * HZ);
 	if (!ret) {
-		IWL_ERR(trans, "Could not load the %s uCode section\n",
-			name);
+		IWL_ERR(trans, "Could not load the [%d] uCode section\n",
+			section_num);
 		return -ETIMEDOUT;
 	}
 
 	return 0;
 }
 
-static int iwl_load_given_ucode(struct iwl_trans *trans, struct fw_img *image)
+static int iwl_load_given_ucode(struct iwl_trans *trans,
+				const struct fw_img *image)
 {
 	int ret = 0;
+		int i;
 
-	ret = iwl_load_section(trans, "INST", &image->code,
-				   IWLAGN_RTC_INST_LOWER_BOUND);
-	if (ret)
-		return ret;
+		for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) {
+			if (!image->sec[i].p_addr)
+				break;
 
-	ret = iwl_load_section(trans, "DATA", &image->data,
-				    IWLAGN_RTC_DATA_LOWER_BOUND);
-	if (ret)
-		return ret;
+			ret = iwl_load_section(trans, i, &image->sec[i]);
+			if (ret)
+				return ret;
+		}
 
 	/* Remove all resets to allow NIC to operate */
 	iwl_write32(trans, CSR_RESET, 0);
@@ -1016,13 +1024,14 @@
 	return 0;
 }
 
-static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
+static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
+				   const struct fw_img *fw)
 {
 	int ret;
 	struct iwl_trans_pcie *trans_pcie =
 		IWL_TRANS_GET_PCIE_TRANS(trans);
+	bool hw_rfkill;
 
-	trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER;
 	trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue;
 	trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue;
 
@@ -1032,22 +1041,19 @@
 	trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0;
 	trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE;
 
-	if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) &&
-	     iwl_prepare_card_hw(trans)) {
+	/* This may fail if AMT took ownership of the device */
+	if (iwl_prepare_card_hw(trans)) {
 		IWL_WARN(trans, "Exit HW not ready\n");
 		return -EIO;
 	}
 
 	/* If platform's RF_KILL switch is NOT set to KILL */
-	if (iwl_read32(trans, CSR_GP_CNTRL) &
-			CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-		clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
-	else
-		set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+	hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
+	iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 
-	if (iwl_is_rfkill(trans->shrd)) {
-		iwl_op_mode_hw_rf_kill(trans->op_mode, true);
-		iwl_enable_interrupts(trans);
+	if (hw_rfkill) {
+		iwl_enable_rfkill_int(trans);
 		return -ERFKILL;
 	}
 
@@ -1073,9 +1079,7 @@
 	iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
 
 	/* Load the given image to the HW */
-	iwl_load_given_ucode(trans, fw);
-
-	return 0;
+	return iwl_load_given_ucode(trans, fw);
 }
 
 /*
@@ -1116,7 +1120,8 @@
 		a += 4)
 		iwl_write_targ_mem(trans, a, 0);
 	for (; a < trans_pcie->scd_base_addr +
-	       SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num);
+	       SCD_TRANS_TBL_OFFSET_QUEUE(
+				cfg(trans)->base_params->num_of_queues);
 	       a += 4)
 		iwl_write_targ_mem(trans, a, 0);
 
@@ -1135,11 +1140,11 @@
 			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
 
 	iwl_write_prph(trans, SCD_QUEUECHAIN_SEL,
-		SCD_QUEUECHAIN_SEL_ALL(trans));
+		SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie));
 	iwl_write_prph(trans, SCD_AGGR_SEL, 0);
 
 	/* initiate the queues */
-	for (i = 0; i < hw_params(trans).max_txq_num; i++) {
+	for (i = 0; i < cfg(trans)->base_params->num_of_queues; i++) {
 		iwl_write_prph(trans, SCD_QUEUE_RDPTR(i), 0);
 		iwl_write_direct32(trans, HBUS_TARG_WRPTR, 0 | (i << 8));
 		iwl_write_targ_mem(trans, trans_pcie->scd_base_addr +
@@ -1156,7 +1161,7 @@
 	}
 
 	iwl_write_prph(trans, SCD_INTERRUPT_MASK,
-			IWL_MASK(0, hw_params(trans).max_txq_num));
+			IWL_MASK(0, cfg(trans)->base_params->num_of_queues));
 
 	/* Activate all Tx DMA/FIFO channels */
 	iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7));
@@ -1167,7 +1172,7 @@
 	else
 		queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
 
-	iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0);
+	iwl_trans_set_wr_ptrs(trans, trans_pcie->cmd_queue, 0);
 
 	/* make sure all queue are not stopped */
 	memset(&trans_pcie->queue_stopped[0], 0,
@@ -1216,7 +1221,7 @@
  */
 static int iwl_trans_tx_stop(struct iwl_trans *trans)
 {
-	int ch, txq_id;
+	int ch, txq_id, ret;
 	unsigned long flags;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
@@ -1229,9 +1234,10 @@
 	for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
 		iwl_write_direct32(trans,
 				   FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
-		if (iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
+		ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
 				    FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
-				    1000))
+				    1000);
+		if (ret < 0)
 			IWL_ERR(trans, "Failing on timeout while stopping"
 			    " DMA channel %d [0x%08x]", ch,
 			    iwl_read_direct32(trans,
@@ -1245,7 +1251,8 @@
 	}
 
 	/* Unmap DMA from host system and free skb's */
-	for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
+	for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
+	     txq_id++)
 		iwl_tx_queue_unmap(trans, txq_id);
 
 	return 0;
@@ -1271,7 +1278,7 @@
 	 * restart. So don't process again if the device is
 	 * already dead.
 	 */
-	if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) {
+	if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) {
 		iwl_trans_tx_stop(trans);
 #ifndef CONFIG_IWLWIFI_IDI
 		iwl_trans_rx_stop(trans);
@@ -1297,7 +1304,7 @@
 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	/* wait to make sure we flush pending tasklet*/
-	synchronize_irq(trans->irq);
+	synchronize_irq(trans_pcie->irq);
 	tasklet_kill(&trans_pcie->irq_tasklet);
 
 	cancel_work_sync(&trans_pcie->rx_replenish);
@@ -1306,6 +1313,17 @@
 	iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 }
 
+static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans)
+{
+	/* let the ucode operate on its own */
+	iwl_write32(trans, CSR_UCODE_DRV_GP1_SET,
+		    CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
+
+	iwl_disable_interrupts(trans);
+	iwl_clear_bit(trans, CSR_GP_CNTRL,
+		      CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+}
+
 static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 		struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
 		u8 sta_id, u8 tid)
@@ -1358,6 +1376,8 @@
 	txq = &trans_pcie->txq[txq_id];
 	q = &txq->q;
 
+	spin_lock(&txq->lock);
+
 	/* In AGG mode, the index in the ring must correspond to the WiFi
 	 * sequence number. This is a HW requirements to help the SCD to parse
 	 * the BA.
@@ -1404,7 +1424,7 @@
 				    &dev_cmd->hdr, firstlen,
 				    DMA_BIDIRECTIONAL);
 	if (unlikely(dma_mapping_error(trans->dev, txcmd_phys)))
-		return -1;
+		goto out_err;
 	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
 	dma_unmap_len_set(out_meta, len, firstlen);
 
@@ -1426,7 +1446,7 @@
 					 dma_unmap_addr(out_meta, mapping),
 					 dma_unmap_len(out_meta, len),
 					 DMA_BIDIRECTIONAL);
-			return -1;
+			goto out_err;
 		}
 	}
 
@@ -1448,8 +1468,6 @@
 	IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n",
 		     le16_to_cpu(dev_cmd->hdr.sequence));
 	IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
-	iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
-	iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
 
 	/* Set up entry for this TFD in Tx byte-count array */
 	iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len));
@@ -1457,7 +1475,7 @@
 	dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
 			DMA_BIDIRECTIONAL);
 
-	trace_iwlwifi_dev_tx(priv(trans),
+	trace_iwlwifi_dev_tx(trans->dev,
 			     &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
 			     sizeof(struct iwl_tfd),
 			     &dev_cmd->hdr, firstlen,
@@ -1478,10 +1496,14 @@
 			txq->need_update = 1;
 			iwl_txq_update_write_ptr(trans, txq);
 		} else {
-			iwl_stop_queue(trans, txq, "Queue is full");
+			iwl_stop_queue(trans, txq);
 		}
 	}
+	spin_unlock(&txq->lock);
 	return 0;
+ out_err:
+	spin_unlock(&txq->lock);
+	return -1;
 }
 
 static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
@@ -1489,6 +1511,7 @@
 	struct iwl_trans_pcie *trans_pcie =
 		IWL_TRANS_GET_PCIE_TRANS(trans);
 	int err;
+	bool hw_rfkill;
 
 	trans_pcie->inta_mask = CSR_INI_SET_MASK;
 
@@ -1498,11 +1521,11 @@
 
 		iwl_alloc_isr_ict(trans);
 
-		err = request_irq(trans->irq, iwl_isr_ict, IRQF_SHARED,
+		err = request_irq(trans_pcie->irq, iwl_isr_ict, IRQF_SHARED,
 			DRV_NAME, trans);
 		if (err) {
 			IWL_ERR(trans, "Error allocating IRQ %d\n",
-				trans->irq);
+				trans_pcie->irq);
 			goto error;
 		}
 
@@ -1518,21 +1541,14 @@
 
 	iwl_apm_init(trans);
 
-	/* If platform's RF_KILL switch is NOT set to KILL */
-	if (iwl_read32(trans,
-			CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-		clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
-	else
-		set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
-
-	iwl_op_mode_hw_rf_kill(trans->op_mode,
-				test_bit(STATUS_RF_KILL_HW,
-					 &trans->shrd->status));
+	hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
+	iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 
 	return err;
 
 err_free_irq:
-	free_irq(trans->irq, trans);
+	free_irq(trans_pcie->irq, trans);
 error:
 	iwl_free_isr_ict(trans);
 	tasklet_kill(&trans_pcie->irq_tasklet);
@@ -1546,13 +1562,11 @@
 	iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
 
 	/* Even if we stop the HW, we still want the RF kill interrupt */
-	IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
-	iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+	iwl_enable_rfkill_int(trans);
 }
 
 static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
-		      int txq_id, int ssn, u32 status,
-		      struct sk_buff_head *skbs)
+		      int txq_id, int ssn, struct sk_buff_head *skbs)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
@@ -1560,6 +1574,8 @@
 	int tfd_num = ssn & (txq->q.n_bd - 1);
 	int freed = 0;
 
+	spin_lock(&txq->lock);
+
 	txq->time_stamp = jiffies;
 
 	if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE &&
@@ -1574,6 +1590,7 @@
 		IWL_DEBUG_TX_QUEUES(trans, "Bad queue mapping txq_id %d, "
 			"agg_txq[sta_id[tid] %d", txq_id,
 			trans_pcie->agg_txq[sta_id][tid]);
+		spin_unlock(&txq->lock);
 		return 1;
 	}
 
@@ -1582,28 +1599,42 @@
 				txq_id, iwl_get_queue_ac(txq), txq->q.read_ptr,
 				tfd_num, ssn);
 		freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
-		if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
-		   (!txq->sched_retry ||
-		   status != TX_STATUS_FAIL_PASSIVE_NO_RX))
-			iwl_wake_queue(trans, txq, "Packets reclaimed");
+		if (iwl_queue_space(&txq->q) > txq->q.low_mark)
+			iwl_wake_queue(trans, txq);
 	}
+
+	spin_unlock(&txq->lock);
 	return 0;
 }
 
 static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val)
 {
-	iowrite8(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
+	writeb(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
 }
 
 static void iwl_trans_pcie_write32(struct iwl_trans *trans, u32 ofs, u32 val)
 {
-	iowrite32(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
+	writel(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
 }
 
 static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs)
 {
-	u32 val = ioread32(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
-	return val;
+	return readl(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
+}
+
+static void iwl_trans_pcie_configure(struct iwl_trans *trans,
+			      const struct iwl_trans_config *trans_cfg)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+	trans_pcie->cmd_queue = trans_cfg->cmd_queue;
+	if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS))
+		trans_pcie->n_no_reclaim_cmds = 0;
+	else
+		trans_pcie->n_no_reclaim_cmds = trans_cfg->n_no_reclaim_cmds;
+	if (trans_pcie->n_no_reclaim_cmds)
+		memcpy(trans_pcie->no_reclaim_cmds, trans_cfg->no_reclaim_cmds,
+		       trans_pcie->n_no_reclaim_cmds * sizeof(u8));
 }
 
 static void iwl_trans_pcie_free(struct iwl_trans *trans)
@@ -1611,18 +1642,17 @@
 	struct iwl_trans_pcie *trans_pcie =
 		IWL_TRANS_GET_PCIE_TRANS(trans);
 
-	iwl_calib_free_results(trans);
 	iwl_trans_pcie_tx_free(trans);
 #ifndef CONFIG_IWLWIFI_IDI
 	iwl_trans_pcie_rx_free(trans);
 #endif
 	if (trans_pcie->irq_requested == true) {
-		free_irq(trans->irq, trans);
+		free_irq(trans_pcie->irq, trans);
 		iwl_free_isr_ict(trans);
 	}
 
 	pci_disable_msi(trans_pcie->pci_dev);
-	pci_iounmap(trans_pcie->pci_dev, trans_pcie->hw_base);
+	iounmap(trans_pcie->hw_base);
 	pci_release_regions(trans_pcie->pci_dev);
 	pci_disable_device(trans_pcie->pci_dev);
 
@@ -1633,42 +1663,20 @@
 #ifdef CONFIG_PM_SLEEP
 static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
 {
-	/*
-	 * This function is called when system goes into suspend state
-	 * mac80211 will call iwlagn_mac_stop() from the mac80211 suspend
-	 * function first but since iwlagn_mac_stop() has no knowledge of
-	 * who the caller is,
-	 * it will not call apm_ops.stop() to stop the DMA operation.
-	 * Calling apm_ops.stop here to make sure we stop the DMA.
-	 *
-	 * But of course ... if we have configured WoWLAN then we did other
-	 * things already :-)
-	 */
-	if (!trans->shrd->wowlan) {
-		iwl_apm_stop(trans);
-	} else {
-		iwl_disable_interrupts(trans);
-		iwl_clear_bit(trans, CSR_GP_CNTRL,
-			      CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-	}
-
 	return 0;
 }
 
 static int iwl_trans_pcie_resume(struct iwl_trans *trans)
 {
-	bool hw_rfkill = false;
+	bool hw_rfkill;
 
-	iwl_enable_interrupts(trans);
-
-	if (!(iwl_read32(trans, CSR_GP_CNTRL) &
-				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
-		hw_rfkill = true;
+	hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
 
 	if (hw_rfkill)
-		set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+		iwl_enable_rfkill_int(trans);
 	else
-		clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+		iwl_enable_interrupts(trans);
 
 	iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 
@@ -1676,32 +1684,6 @@
 }
 #endif /* CONFIG_PM_SLEEP */
 
-static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans,
-					  enum iwl_rxon_context_id ctx,
-					  const char *msg)
-{
-	u8 ac, txq_id;
-	struct iwl_trans_pcie *trans_pcie =
-		IWL_TRANS_GET_PCIE_TRANS(trans);
-
-	for (ac = 0; ac < AC_NUM; ac++) {
-		txq_id = trans_pcie->ac_to_queue[ctx][ac];
-		IWL_DEBUG_TX_QUEUES(trans, "Queue Status: Q[%d] %s\n",
-			ac,
-			(atomic_read(&trans_pcie->queue_stop_count[ac]) > 0)
-			      ? "stopped" : "awake");
-		iwl_wake_queue(trans, &trans_pcie->txq[txq_id], msg);
-	}
-}
-
-static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id,
-				      const char *msg)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-	iwl_stop_queue(trans, &trans_pcie->txq[txq_id], msg);
-}
-
 #define IWL_FLUSH_WAIT_MS	2000
 
 static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
@@ -1714,8 +1696,8 @@
 	int ret = 0;
 
 	/* waiting for all the tx frames complete might take a while */
-	for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
-		if (cnt == trans->shrd->cmd_queue)
+	for (cnt = 0; cnt < cfg(trans)->base_params->num_of_queues; cnt++) {
+		if (cnt == trans_pcie->cmd_queue)
 			continue;
 		txq = &trans_pcie->txq[cnt];
 		q = &txq->q;
@@ -1960,7 +1942,9 @@
 	int pos = 0;
 	int cnt;
 	int ret;
-	const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num;
+	size_t bufsz;
+
+	bufsz = sizeof(char) * 64 * cfg(trans)->base_params->num_of_queues;
 
 	if (!trans_pcie->txq) {
 		IWL_ERR(trans, "txq not ready\n");
@@ -1970,7 +1954,7 @@
 	if (!buf)
 		return -ENOMEM;
 
-	for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
+	for (cnt = 0; cnt < cfg(trans)->base_params->num_of_queues; cnt++) {
 		txq = &trans_pcie->txq[cnt];
 		q = &txq->q;
 		pos += scnprintf(buf + pos, bufsz - pos,
@@ -2219,7 +2203,7 @@
 	.start_fw = iwl_trans_pcie_start_fw,
 	.stop_device = iwl_trans_pcie_stop_device,
 
-	.wake_any_queue = iwl_trans_pcie_wake_any_queue,
+	.wowlan_suspend = iwl_trans_pcie_wowlan_suspend,
 
 	.send_cmd = iwl_trans_pcie_send_cmd,
 
@@ -2231,7 +2215,6 @@
 	.tx_agg_setup = iwl_trans_pcie_tx_agg_setup,
 
 	.free = iwl_trans_pcie_free,
-	.stop_queue = iwl_trans_pcie_stop_queue,
 
 	.dbgfs_register = iwl_trans_pcie_dbgfs_register,
 
@@ -2245,6 +2228,7 @@
 	.write8 = iwl_trans_pcie_write8,
 	.write32 = iwl_trans_pcie_write32,
 	.read32 = iwl_trans_pcie_read32,
+	.configure = iwl_trans_pcie_configure,
 };
 
 struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
@@ -2267,8 +2251,8 @@
 	trans->ops = &trans_ops_pcie;
 	trans->shrd = shrd;
 	trans_pcie->trans = trans;
-	spin_lock_init(&trans->hcmd_lock);
 	spin_lock_init(&trans_pcie->irq_lock);
+	init_waitqueue_head(&trans_pcie->ucode_write_waitq);
 
 	/* W/A - seems to solve weird behavior. We need to remove this if we
 	 * don't want to stay in L1 all the time. This wastes a lot of power */
@@ -2304,9 +2288,9 @@
 		goto out_pci_disable_device;
 	}
 
-	trans_pcie->hw_base = pci_iomap(pdev, 0, 0);
+	trans_pcie->hw_base = pci_ioremap_bar(pdev, 0);
 	if (!trans_pcie->hw_base) {
-		dev_printk(KERN_ERR, &pdev->dev, "pci_iomap failed");
+		dev_printk(KERN_ERR, &pdev->dev, "pci_ioremap_bar failed");
 		err = -ENODEV;
 		goto out_pci_release_regions;
 	}
@@ -2330,7 +2314,7 @@
 			"pci_enable_msi failed(0X%x)", err);
 
 	trans->dev = &pdev->dev;
-	trans->irq = pdev->irq;
+	trans_pcie->irq = pdev->irq;
 	trans_pcie->pci_dev = pdev;
 	trans->hw_rev = iwl_read32(trans, CSR_HW_REV);
 	trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
@@ -2345,6 +2329,9 @@
 		pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
 	}
 
+	/* Initialize the wait queue for commands */
+	init_waitqueue_head(&trans->wait_command_queue);
+
 	return trans;
 
 out_pci_release_regions:
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
deleted file mode 100644
index 506c062..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *  * Neither the name Intel Corporation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *****************************************************************************/
-
-#include "iwl-trans.h"
-
-int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
-			   u32 flags, u16 len, const void *data)
-{
-	struct iwl_host_cmd cmd = {
-		.id = id,
-		.len = { len, },
-		.data = { data, },
-		.flags = flags,
-	};
-
-	return iwl_trans_send_cmd(trans, &cmd);
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 4e7e6c0..0c81cba 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -64,6 +64,7 @@
 #define __iwl_trans_h__
 
 #include <linux/ieee80211.h>
+#include <linux/mm.h> /* for page_address */
 
 #include "iwl-shared.h"
 #include "iwl-debug.h"
@@ -121,6 +122,62 @@
 #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
 #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
 #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
+#define SEQ_TO_QUEUE(s)	(((s) >> 8) & 0x1f)
+#define QUEUE_TO_SEQ(q)	(((q) & 0x1f) << 8)
+#define SEQ_TO_INDEX(s)	((s) & 0xff)
+#define INDEX_TO_SEQ(i)	((i) & 0xff)
+#define SEQ_RX_FRAME	cpu_to_le16(0x8000)
+
+/**
+ * struct iwl_cmd_header
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ */
+struct iwl_cmd_header {
+	u8 cmd;		/* Command ID:  REPLY_RXON, etc. */
+	u8 flags;	/* 0:5 reserved, 6 abort, 7 internal */
+	/*
+	 * The driver sets up the sequence number to values of its choosing.
+	 * uCode does not use this value, but passes it back to the driver
+	 * when sending the response to each driver-originated command, so
+	 * the driver can match the response to the command.  Since the values
+	 * don't get used by uCode, the driver may set up an arbitrary format.
+	 *
+	 * There is one exception:  uCode sets bit 15 when it originates
+	 * the response/notification, i.e. when the response/notification
+	 * is not a direct response to a command sent by the driver.  For
+	 * example, uCode issues REPLY_RX when it sends a received frame
+	 * to the driver; it is not a direct response to any driver command.
+	 *
+	 * The Linux driver uses the following format:
+	 *
+	 *  0:7		tfd index - position within TX queue
+	 *  8:12	TX queue id
+	 *  13:14	reserved
+	 *  15		unsolicited RX or uCode-originated notification
+	 */
+	__le16 sequence;
+} __packed;
+
+
+#define FH_RSCSR_FRAME_SIZE_MSK		0x00003FFF	/* bits 0-13 */
+
+struct iwl_rx_packet {
+	/*
+	 * The first 4 bytes of the RX frame header contain both the RX frame
+	 * size and some flags.
+	 * Bit fields:
+	 * 31:    flag flush RB request
+	 * 30:    flag ignore TC (terminal counter) request
+	 * 29:    flag fast IRQ request
+	 * 28-14: Reserved
+	 * 13-00: RX frame size
+	 */
+	__le32 len_n_flags;
+	struct iwl_cmd_header hdr;
+	u8 data[];
+} __packed;
 
 /**
  * enum CMD_MODE - how to send the host commands ?
@@ -173,7 +230,9 @@
  * struct iwl_host_cmd - Host command to the uCode
  *
  * @data: array of chunks that composes the data of the host command
- * @reply_page: pointer to the page that holds the response to the host command
+ * @resp_pkt: response packet, if %CMD_WANT_SKB was set
+ * @_rx_page_order: (internally used to free response packet)
+ * @_rx_page_addr: (internally used to free response packet)
  * @handler_status: return value of the handler of the command
  *	(put in setup_rx_handlers) - valid for SYNC mode only
  * @flags: can be CMD_*
@@ -183,7 +242,9 @@
  */
 struct iwl_host_cmd {
 	const void *data[IWL_MAX_CMD_TFDS];
-	unsigned long reply_page;
+	struct iwl_rx_packet *resp_pkt;
+	unsigned long _rx_page_addr;
+	u32 _rx_page_order;
 	int handler_status;
 
 	u32 flags;
@@ -192,6 +253,49 @@
 	u8 id;
 };
 
+static inline void iwl_free_resp(struct iwl_host_cmd *cmd)
+{
+	free_pages(cmd->_rx_page_addr, cmd->_rx_page_order);
+}
+
+struct iwl_rx_cmd_buffer {
+	struct page *_page;
+};
+
+static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
+{
+	return page_address(r->_page);
+}
+
+static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
+{
+	struct page *p = r->_page;
+	r->_page = NULL;
+	return p;
+}
+
+#define MAX_NO_RECLAIM_CMDS	6
+
+/**
+ * struct iwl_trans_config - transport configuration
+ *
+ * @op_mode: pointer to the upper layer.
+ *	Must be set before any other call.
+ * @cmd_queue: the index of the command queue.
+ *	Must be set before start_fw.
+ * @no_reclaim_cmds: Some devices erroneously don't set the
+ *	SEQ_RX_FRAME bit on some notifications, this is the
+ *	list of such notifications to filter. Max length is
+ *	%MAX_NO_RECLAIM_CMDS.
+ * @n_no_reclaim_cmds: # of commands in list
+ */
+struct iwl_trans_config {
+	struct iwl_op_mode *op_mode;
+	u8 cmd_queue;
+	const u8 *no_reclaim_cmds;
+	int n_no_reclaim_cmds;
+};
+
 /**
  * struct iwl_trans_ops - transport specific operations
  *
@@ -207,9 +311,11 @@
  *	May sleep
  * @fw_alive: called when the fw sends alive notification
  *	May sleep
- * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
  * @stop_device:stops the whole device (embedded CPU put to reset)
  *	May sleep
+ * @wowlan_suspend: put the device into the correct mode for WoWLAN during
+ *	suspend. This is optional, if not implemented WoWLAN will not be
+ *	supported. This callback may sleep.
  * @send_cmd:send a host command
  *	May sleep only if CMD_SYNC is set
  * @tx: send an skb
@@ -217,17 +323,16 @@
  * @reclaim: free packet until ssn. Returns a list of freed packets.
  *	Must be atomic
  * @tx_agg_alloc: allocate resources for a TX BA session
- *	May sleep
+ *	Must be atomic
  * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
  *	ready and a successful ADDBA response has been received.
  *	May sleep
  * @tx_agg_disable: de-configure a Tx queue to send AMPDUs
- *	May sleep
+ *	Must be atomic
  * @free: release all the ressource for the transport layer itself such as
  *	irq, tasklet etc... From this point on, the device may not issue
  *	any interrupt (incl. RFKILL).
  *	May sleep
- * @stop_queue: stop a specific queue
  * @check_stuck_queue: check if a specific queue is stuck
  * @wait_tx_queue_empty: wait until all tx queues are empty
  *	May sleep
@@ -238,18 +343,19 @@
  * @write8: write a u8 to a register at offset ofs from the BAR
  * @write32: write a u32 to a register at offset ofs from the BAR
  * @read32: read a u32 register at offset ofs from the BAR
+ * @configure: configure parameters required by the transport layer from
+ *	the op_mode. May be called several times before start_fw, can't be
+ *	called after that.
  */
 struct iwl_trans_ops {
 
 	int (*start_hw)(struct iwl_trans *iwl_trans);
 	void (*stop_hw)(struct iwl_trans *iwl_trans);
-	int (*start_fw)(struct iwl_trans *trans, struct fw_img *fw);
+	int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
 	void (*fw_alive)(struct iwl_trans *trans);
 	void (*stop_device)(struct iwl_trans *trans);
 
-	void (*wake_any_queue)(struct iwl_trans *trans,
-			       enum iwl_rxon_context_id ctx,
-			       const char *msg);
+	void (*wowlan_suspend)(struct iwl_trans *trans);
 
 	int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
 
@@ -257,8 +363,7 @@
 		struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
 		u8 sta_id, u8 tid);
 	int (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
-			int txq_id, int ssn, u32 status,
-			struct sk_buff_head *skbs);
+			int txq_id, int ssn, struct sk_buff_head *skbs);
 
 	int (*tx_agg_disable)(struct iwl_trans *trans,
 			      int sta_id, int tid);
@@ -270,8 +375,6 @@
 
 	void (*free)(struct iwl_trans *trans);
 
-	void (*stop_queue)(struct iwl_trans *trans, int q, const char *msg);
-
 	int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
 	int (*check_stuck_queue)(struct iwl_trans *trans, int q);
 	int (*wait_tx_queue_empty)(struct iwl_trans *trans);
@@ -282,14 +385,8 @@
 	void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val);
 	void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val);
 	u32 (*read32)(struct iwl_trans *trans, u32 ofs);
-};
-
-/* Opaque calibration results */
-struct iwl_calib_result {
-	struct list_head list;
-	size_t cmd_len;
-	struct iwl_calib_hdr hdr;
-	/* data follows */
+	void (*configure)(struct iwl_trans *trans,
+			  const struct iwl_trans_config *trans_cfg);
 };
 
 /**
@@ -309,38 +406,31 @@
  * @ops - pointer to iwl_trans_ops
  * @op_mode - pointer to the op_mode
  * @shrd - pointer to iwl_shared which holds shared data from the upper layer
- * @hcmd_lock: protects HCMD
  * @reg_lock - protect hw register access
  * @dev - pointer to struct device * that represents the device
- * @irq - the irq number for the device
  * @hw_id: a u32 with the ID of the device / subdevice.
  *	Set during transport allocation.
  * @hw_id_str: a string with info about HW ID. Set during transport allocation.
- * @ucode_write_complete: indicates that the ucode has been copied.
  * @nvm_device_type: indicates OTP or eeprom
  * @pm_support: set to true in start_hw if link pm is supported
- * @calib_results: list head for init calibration results
+ * @wait_command_queue: the wait_queue for SYNC host commands
  */
 struct iwl_trans {
 	const struct iwl_trans_ops *ops;
 	struct iwl_op_mode *op_mode;
 	struct iwl_shared *shrd;
 	enum iwl_trans_state state;
-	spinlock_t hcmd_lock;
 	spinlock_t reg_lock;
 
 	struct device *dev;
-	unsigned int irq;
 	u32 hw_rev;
 	u32 hw_id;
 	char hw_id_str[52];
 
-	u8 ucode_write_complete;
-
 	int    nvm_device_type;
 	bool pm_support;
 
-	struct list_head calib_results;
+	wait_queue_head_t wait_command_queue;
 
 	/* pointer to trans specific struct */
 	/*Ensure that this pointer will always be aligned to sizeof pointer */
@@ -348,13 +438,15 @@
 };
 
 static inline void iwl_trans_configure(struct iwl_trans *trans,
-				       struct iwl_op_mode *op_mode)
+				       const struct iwl_trans_config *trans_cfg)
 {
 	/*
 	 * only set the op_mode for the moment. Later on, this function will do
 	 * more
 	 */
-	trans->op_mode = op_mode;
+	trans->op_mode = trans_cfg->op_mode;
+
+	trans->ops->configure(trans, trans_cfg);
 }
 
 static inline int iwl_trans_start_hw(struct iwl_trans *trans)
@@ -382,7 +474,8 @@
 	trans->state = IWL_TRANS_FW_ALIVE;
 }
 
-static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw)
+static inline int iwl_trans_start_fw(struct iwl_trans *trans,
+				     const struct fw_img *fw)
 {
 	might_sleep();
 
@@ -398,29 +491,21 @@
 	trans->state = IWL_TRANS_NO_FW;
 }
 
-static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
-					    enum iwl_rxon_context_id ctx,
-					    const char *msg)
+static inline void iwl_trans_wowlan_suspend(struct iwl_trans *trans)
 {
-	if (trans->state != IWL_TRANS_FW_ALIVE)
-		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
-
-	trans->ops->wake_any_queue(trans, ctx, msg);
+	might_sleep();
+	trans->ops->wowlan_suspend(trans);
 }
 
-
 static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
 				struct iwl_host_cmd *cmd)
 {
-	if (trans->state != IWL_TRANS_FW_ALIVE)
-		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
+		  "%s bad state = %d", __func__, trans->state);
 
 	return trans->ops->send_cmd(trans, cmd);
 }
 
-int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
-			   u32 flags, u16 len, const void *data);
-
 static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
 		struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
 		u8 sta_id, u8 tid)
@@ -432,23 +517,20 @@
 }
 
 static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
-				 int tid, int txq_id, int ssn, u32 status,
+				 int tid, int txq_id, int ssn,
 				 struct sk_buff_head *skbs)
 {
-	if (trans->state != IWL_TRANS_FW_ALIVE)
-		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
+		  "%s bad state = %d", __func__, trans->state);
 
-	return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn,
-				   status, skbs);
+	return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, skbs);
 }
 
 static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
 					    int sta_id, int tid)
 {
-	might_sleep();
-
-	if (trans->state != IWL_TRANS_FW_ALIVE)
-		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
+		  "%s bad state = %d", __func__, trans->state);
 
 	return trans->ops->tx_agg_disable(trans, sta_id, tid);
 }
@@ -456,10 +538,8 @@
 static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans,
 					 int sta_id, int tid)
 {
-	might_sleep();
-
-	if (trans->state != IWL_TRANS_FW_ALIVE)
-		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
+		  "%s bad state = %d", __func__, trans->state);
 
 	return trans->ops->tx_agg_alloc(trans, sta_id, tid);
 }
@@ -472,8 +552,8 @@
 {
 	might_sleep();
 
-	if (trans->state != IWL_TRANS_FW_ALIVE)
-		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
+		  "%s bad state = %d", __func__, trans->state);
 
 	trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn);
 }
@@ -483,27 +563,18 @@
 	trans->ops->free(trans);
 }
 
-static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q,
-					const char *msg)
-{
-	if (trans->state != IWL_TRANS_FW_ALIVE)
-		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
-
-	trans->ops->stop_queue(trans, q, msg);
-}
-
 static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
 {
-	if (trans->state != IWL_TRANS_FW_ALIVE)
-		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
+		  "%s bad state = %d", __func__, trans->state);
 
 	return trans->ops->wait_tx_queue_empty(trans);
 }
 
 static inline int iwl_trans_check_stuck_queue(struct iwl_trans *trans, int q)
 {
-	if (trans->state != IWL_TRANS_FW_ALIVE)
-		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
+		  "%s bad state = %d", __func__, trans->state);
 
 	return trans->ops->check_stuck_queue(trans, q);
 }
@@ -541,14 +612,6 @@
 }
 
 /*****************************************************
-* Utils functions
-******************************************************/
-int iwl_send_calib_results(struct iwl_trans *trans);
-int iwl_calib_set(struct iwl_trans *trans,
-		  const struct iwl_calib_hdr *cmd, int len);
-void iwl_calib_free_results(struct iwl_trans *trans);
-
-/*****************************************************
 * Transport layers implementations + their allocation function
 ******************************************************/
 struct pci_dev;
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c
index b16efc0..2528287 100644
--- a/drivers/net/wireless/iwlwifi/iwl-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c
@@ -28,14 +28,8 @@
  *****************************************************************************/
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/dma-mapping.h>
-#include <linux/firmware.h>
 
-#include "iwl-ucode.h"
-#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
@@ -83,82 +77,35 @@
  *
  ******************************************************************************/
 
-static void iwl_free_fw_desc(struct iwl_nic *nic, struct fw_desc *desc)
+static inline const struct fw_img *
+iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type)
 {
-	if (desc->v_addr)
-		dma_free_coherent(trans(nic)->dev, desc->len,
-				  desc->v_addr, desc->p_addr);
-	desc->v_addr = NULL;
-	desc->len = 0;
-}
+	if (ucode_type >= IWL_UCODE_TYPE_MAX)
+		return NULL;
 
-static void iwl_free_fw_img(struct iwl_nic *nic, struct fw_img *img)
-{
-	iwl_free_fw_desc(nic, &img->code);
-	iwl_free_fw_desc(nic, &img->data);
-}
-
-void iwl_dealloc_ucode(struct iwl_nic *nic)
-{
-	iwl_free_fw_img(nic, &nic->fw.ucode_rt);
-	iwl_free_fw_img(nic, &nic->fw.ucode_init);
-	iwl_free_fw_img(nic, &nic->fw.ucode_wowlan);
-}
-
-static int iwl_alloc_fw_desc(struct iwl_nic *nic, struct fw_desc *desc,
-		      const void *data, size_t len)
-{
-	if (!len) {
-		desc->v_addr = NULL;
-		return -EINVAL;
-	}
-
-	desc->v_addr = dma_alloc_coherent(trans(nic)->dev, len,
-					  &desc->p_addr, GFP_KERNEL);
-	if (!desc->v_addr)
-		return -ENOMEM;
-
-	desc->len = len;
-	memcpy(desc->v_addr, data, len);
-	return 0;
-}
-
-static inline struct fw_img *iwl_get_ucode_image(struct iwl_nic *nic,
-					enum iwl_ucode_type ucode_type)
-{
-	switch (ucode_type) {
-	case IWL_UCODE_INIT:
-		return &nic->fw.ucode_init;
-	case IWL_UCODE_WOWLAN:
-		return &nic->fw.ucode_wowlan;
-	case IWL_UCODE_REGULAR:
-		return &nic->fw.ucode_rt;
-	case IWL_UCODE_NONE:
-		break;
-	}
-	return NULL;
+	return &priv->fw->img[ucode_type];
 }
 
 /*
  *  Calibration
  */
-static int iwl_set_Xtal_calib(struct iwl_trans *trans)
+static int iwl_set_Xtal_calib(struct iwl_priv *priv)
 {
 	struct iwl_calib_xtal_freq_cmd cmd;
 	__le16 *xtal_calib =
-		(__le16 *)iwl_eeprom_query_addr(trans->shrd, EEPROM_XTAL);
+		(__le16 *)iwl_eeprom_query_addr(priv->shrd, EEPROM_XTAL);
 
 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
 	cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
 	cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
-	return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
+	return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
 }
 
-static int iwl_set_temperature_offset_calib(struct iwl_trans *trans)
+static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
 {
 	struct iwl_calib_temperature_offset_cmd cmd;
 	__le16 *offset_calib =
-		(__le16 *)iwl_eeprom_query_addr(trans->shrd,
+		(__le16 *)iwl_eeprom_query_addr(priv->shrd,
 						EEPROM_RAW_TEMPERATURE);
 
 	memset(&cmd, 0, sizeof(cmd));
@@ -167,48 +114,48 @@
 	if (!(cmd.radio_sensor_offset))
 		cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
 
-	IWL_DEBUG_CALIB(trans, "Radio sensor offset: %d\n",
+	IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
 			le16_to_cpu(cmd.radio_sensor_offset));
-	return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
+	return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
 }
 
-static int iwl_set_temperature_offset_calib_v2(struct iwl_trans *trans)
+static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
 {
 	struct iwl_calib_temperature_offset_v2_cmd cmd;
-	__le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(trans->shrd,
+	__le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv->shrd,
 				     EEPROM_KELVIN_TEMPERATURE);
 	__le16 *offset_calib_low =
-		(__le16 *)iwl_eeprom_query_addr(trans->shrd,
+		(__le16 *)iwl_eeprom_query_addr(priv->shrd,
 						EEPROM_RAW_TEMPERATURE);
 	struct iwl_eeprom_calib_hdr *hdr;
 
 	memset(&cmd, 0, sizeof(cmd));
 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
-	hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(trans->shrd,
+	hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv->shrd,
 							EEPROM_CALIB_ALL);
 	memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
 		sizeof(*offset_calib_high));
 	memcpy(&cmd.radio_sensor_offset_low, offset_calib_low,
 		sizeof(*offset_calib_low));
 	if (!(cmd.radio_sensor_offset_low)) {
-		IWL_DEBUG_CALIB(trans, "no info in EEPROM, use default\n");
+		IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n");
 		cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
 		cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
 	}
 	memcpy(&cmd.burntVoltageRef, &hdr->voltage,
 		sizeof(hdr->voltage));
 
-	IWL_DEBUG_CALIB(trans, "Radio sensor offset high: %d\n",
+	IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n",
 			le16_to_cpu(cmd.radio_sensor_offset_high));
-	IWL_DEBUG_CALIB(trans, "Radio sensor offset low: %d\n",
+	IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n",
 			le16_to_cpu(cmd.radio_sensor_offset_low));
-	IWL_DEBUG_CALIB(trans, "Voltage Ref: %d\n",
+	IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
 			le16_to_cpu(cmd.burntVoltageRef));
 
-	return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
+	return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
 }
 
-static int iwl_send_calib_cfg(struct iwl_trans *trans)
+static int iwl_send_calib_cfg(struct iwl_priv *priv)
 {
 	struct iwl_calib_cfg_cmd calib_cfg_cmd;
 	struct iwl_host_cmd cmd = {
@@ -224,47 +171,47 @@
 	calib_cfg_cmd.ucd_calib_cfg.flags =
 		IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK;
 
-	return iwl_trans_send_cmd(trans, &cmd);
+	return iwl_dvm_send_cmd(priv, &cmd);
 }
 
 int iwlagn_rx_calib_result(struct iwl_priv *priv,
-			    struct iwl_rx_mem_buffer *rxb,
+			    struct iwl_rx_cmd_buffer *rxb,
 			    struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
+	struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->data;
 	int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
 
 	/* reduce the size of the length field itself */
 	len -= 4;
 
-	if (iwl_calib_set(trans(priv), hdr, len))
+	if (iwl_calib_set(priv, hdr, len))
 		IWL_ERR(priv, "Failed to record calibration data %d\n",
 			hdr->op_code);
 
 	return 0;
 }
 
-int iwl_init_alive_start(struct iwl_trans *trans)
+int iwl_init_alive_start(struct iwl_priv *priv)
 {
 	int ret;
 
-	if (cfg(trans)->bt_params &&
-	    cfg(trans)->bt_params->advanced_bt_coexist) {
+	if (cfg(priv)->bt_params &&
+	    cfg(priv)->bt_params->advanced_bt_coexist) {
 		/*
 		 * Tell uCode we are ready to perform calibration
 		 * need to perform this before any calibration
 		 * no need to close the envlope since we are going
 		 * to load the runtime uCode later.
 		 */
-		ret = iwl_send_bt_env(trans, IWL_BT_COEX_ENV_OPEN,
+		ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
 			BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
 		if (ret)
 			return ret;
 
 	}
 
-	ret = iwl_send_calib_cfg(trans);
+	ret = iwl_send_calib_cfg(priv);
 	if (ret)
 		return ret;
 
@@ -272,21 +219,21 @@
 	 * temperature offset calibration is only needed for runtime ucode,
 	 * so prepare the value now.
 	 */
-	if (cfg(trans)->need_temp_offset_calib) {
-		if (cfg(trans)->temp_offset_v2)
-			return iwl_set_temperature_offset_calib_v2(trans);
+	if (cfg(priv)->need_temp_offset_calib) {
+		if (cfg(priv)->temp_offset_v2)
+			return iwl_set_temperature_offset_calib_v2(priv);
 		else
-			return iwl_set_temperature_offset_calib(trans);
+			return iwl_set_temperature_offset_calib(priv);
 	}
 
 	return 0;
 }
 
-static int iwl_send_wimax_coex(struct iwl_trans *trans)
+static int iwl_send_wimax_coex(struct iwl_priv *priv)
 {
 	struct iwl_wimax_coex_cmd coex_cmd;
 
-	if (cfg(trans)->base_params->support_wimax_coexist) {
+	if (cfg(priv)->base_params->support_wimax_coexist) {
 		/* UnMask wake up src at associated sleep */
 		coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
 
@@ -305,7 +252,7 @@
 		/* coexistence is disabled */
 		memset(&coex_cmd, 0, sizeof(coex_cmd));
 	}
-	return iwl_trans_send_cmd_pdu(trans,
+	return iwl_dvm_send_cmd_pdu(priv,
 				COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
 				sizeof(coex_cmd), &coex_cmd);
 }
@@ -332,64 +279,54 @@
 	0, 0, 0, 0, 0, 0, 0
 };
 
-void iwl_send_prio_tbl(struct iwl_trans *trans)
+void iwl_send_prio_tbl(struct iwl_priv *priv)
 {
 	struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd;
 
 	memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl,
 		sizeof(iwl_bt_prio_tbl));
-	if (iwl_trans_send_cmd_pdu(trans,
+	if (iwl_dvm_send_cmd_pdu(priv,
 				REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,
 				sizeof(prio_tbl_cmd), &prio_tbl_cmd))
-		IWL_ERR(trans, "failed to send BT prio tbl command\n");
+		IWL_ERR(priv, "failed to send BT prio tbl command\n");
 }
 
-int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type)
+int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
 {
 	struct iwl_bt_coex_prot_env_cmd env_cmd;
 	int ret;
 
 	env_cmd.action = action;
 	env_cmd.type = type;
-	ret = iwl_trans_send_cmd_pdu(trans,
+	ret = iwl_dvm_send_cmd_pdu(priv,
 			       REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
 			       sizeof(env_cmd), &env_cmd);
 	if (ret)
-		IWL_ERR(trans, "failed to send BT env command\n");
+		IWL_ERR(priv, "failed to send BT env command\n");
 	return ret;
 }
 
 
-static int iwl_alive_notify(struct iwl_trans *trans)
+static int iwl_alive_notify(struct iwl_priv *priv)
 {
-	struct iwl_priv *priv = priv(trans);
-	struct iwl_rxon_context *ctx;
 	int ret;
 
-	if (!priv->tx_cmd_pool)
-		priv->tx_cmd_pool =
-			kmem_cache_create("iwl_dev_cmd",
-					  sizeof(struct iwl_device_cmd),
-					  sizeof(void *), 0, NULL);
+	iwl_trans_fw_alive(trans(priv));
 
-	if (!priv->tx_cmd_pool)
-		return -ENOMEM;
+	priv->passive_no_rx = false;
+	priv->transport_queue_stop = 0;
 
-	iwl_trans_fw_alive(trans);
-	for_each_context(priv, ctx)
-		ctx->last_tx_rejected = false;
-
-	ret = iwl_send_wimax_coex(trans);
+	ret = iwl_send_wimax_coex(priv);
 	if (ret)
 		return ret;
 
 	if (!cfg(priv)->no_xtal_calib) {
-		ret = iwl_set_Xtal_calib(trans);
+		ret = iwl_set_Xtal_calib(priv);
 		if (ret)
 			return ret;
 	}
 
-	return iwl_send_calib_results(trans);
+	return iwl_send_calib_results(priv);
 }
 
 
@@ -398,24 +335,23 @@
  *   using sample data 100 bytes apart.  If these sample points are good,
  *   it's a pretty good bet that everything between them is good, too.
  */
-static int iwl_verify_inst_sparse(struct iwl_nic *nic,
-				      struct fw_desc *fw_desc)
+static int iwl_verify_sec_sparse(struct iwl_priv *priv,
+				  const struct fw_desc *fw_desc)
 {
-	struct iwl_trans *trans = trans(nic);
 	__le32 *image = (__le32 *)fw_desc->v_addr;
 	u32 len = fw_desc->len;
 	u32 val;
 	u32 i;
 
-	IWL_DEBUG_FW(nic, "ucode inst image size is %u\n", len);
+	IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
 
 	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
 		/* read data comes through single port, auto-incr addr */
 		/* NOTE: Use the debugless read so we don't flood kernel log
 		 * if IWL_DL_IO is set */
-		iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR,
-			i + IWLAGN_RTC_INST_LOWER_BOUND);
-		val = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
+		iwl_write_direct32(trans(priv), HBUS_TARG_MEM_RADDR,
+			i + fw_desc->offset);
+		val = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
 		if (val != le32_to_cpu(*image))
 			return -EIO;
 	}
@@ -423,28 +359,27 @@
 	return 0;
 }
 
-static void iwl_print_mismatch_inst(struct iwl_nic *nic,
-				    struct fw_desc *fw_desc)
+static void iwl_print_mismatch_sec(struct iwl_priv *priv,
+				    const struct fw_desc *fw_desc)
 {
-	struct iwl_trans *trans = trans(nic);
 	__le32 *image = (__le32 *)fw_desc->v_addr;
 	u32 len = fw_desc->len;
 	u32 val;
 	u32 offs;
 	int errors = 0;
 
-	IWL_DEBUG_FW(nic, "ucode inst image size is %u\n", len);
+	IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
 
-	iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR,
-			   IWLAGN_RTC_INST_LOWER_BOUND);
+	iwl_write_direct32(trans(priv), HBUS_TARG_MEM_RADDR,
+				fw_desc->offset);
 
 	for (offs = 0;
 	     offs < len && errors < 20;
 	     offs += sizeof(u32), image++) {
 		/* read data comes through single port, auto-incr addr */
-		val = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
+		val = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
 		if (val != le32_to_cpu(*image)) {
-			IWL_ERR(nic, "uCode INST section at "
+			IWL_ERR(priv, "uCode INST section at "
 				"offset 0x%x, is 0x%x, s/b 0x%x\n",
 				offs, val, le32_to_cpu(*image));
 			errors++;
@@ -456,24 +391,24 @@
  * iwl_verify_ucode - determine which instruction image is in SRAM,
  *    and verify its contents
  */
-static int iwl_verify_ucode(struct iwl_nic *nic,
+static int iwl_verify_ucode(struct iwl_priv *priv,
 			    enum iwl_ucode_type ucode_type)
 {
-	struct fw_img *img = iwl_get_ucode_image(nic, ucode_type);
+	const struct fw_img *img = iwl_get_ucode_image(priv, ucode_type);
 
 	if (!img) {
-		IWL_ERR(nic, "Invalid ucode requested (%d)\n", ucode_type);
+		IWL_ERR(priv, "Invalid ucode requested (%d)\n", ucode_type);
 		return -EINVAL;
 	}
 
-	if (!iwl_verify_inst_sparse(nic, &img->code)) {
-		IWL_DEBUG_FW(nic, "uCode is good in inst SRAM\n");
+	if (!iwl_verify_sec_sparse(priv, &img->sec[IWL_UCODE_SECTION_INST])) {
+		IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
 		return 0;
 	}
 
-	IWL_ERR(nic, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
+	IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
 
-	iwl_print_mismatch_inst(nic, &img->code);
+	iwl_print_mismatch_sec(priv, &img->sec[IWL_UCODE_SECTION_INST]);
 	return -EIO;
 }
 
@@ -482,119 +417,59 @@
 	u8 subtype;
 };
 
-static void iwl_alive_fn(struct iwl_trans *trans,
+static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
 			    struct iwl_rx_packet *pkt,
 			    void *data)
 {
+	struct iwl_priv *priv =
+		container_of(notif_wait, struct iwl_priv, notif_wait);
 	struct iwl_alive_data *alive_data = data;
 	struct iwl_alive_resp *palive;
 
-	palive = &pkt->u.alive_frame;
+	palive = (void *)pkt->data;
 
-	IWL_DEBUG_FW(trans, "Alive ucode status 0x%08X revision "
+	IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision "
 		       "0x%01X 0x%01X\n",
 		       palive->is_valid, palive->ver_type,
 		       palive->ver_subtype);
 
-	trans->shrd->device_pointers.error_event_table =
+	priv->shrd->device_pointers.error_event_table =
 		le32_to_cpu(palive->error_event_table_ptr);
-	trans->shrd->device_pointers.log_event_table =
+	priv->shrd->device_pointers.log_event_table =
 		le32_to_cpu(palive->log_event_table_ptr);
 
 	alive_data->subtype = palive->ver_subtype;
 	alive_data->valid = palive->is_valid == UCODE_VALID_OK;
 }
 
-/* notification wait support */
-void iwl_init_notification_wait(struct iwl_shared *shrd,
-				   struct iwl_notification_wait *wait_entry,
-				   u8 cmd,
-				   void (*fn)(struct iwl_trans *trans,
-					      struct iwl_rx_packet *pkt,
-					      void *data),
-				   void *fn_data)
-{
-	wait_entry->fn = fn;
-	wait_entry->fn_data = fn_data;
-	wait_entry->cmd = cmd;
-	wait_entry->triggered = false;
-	wait_entry->aborted = false;
-
-	spin_lock_bh(&shrd->notif_wait_lock);
-	list_add(&wait_entry->list, &shrd->notif_waits);
-	spin_unlock_bh(&shrd->notif_wait_lock);
-}
-
-int iwl_wait_notification(struct iwl_shared *shrd,
-			     struct iwl_notification_wait *wait_entry,
-			     unsigned long timeout)
-{
-	int ret;
-
-	ret = wait_event_timeout(shrd->notif_waitq,
-				 wait_entry->triggered || wait_entry->aborted,
-				 timeout);
-
-	spin_lock_bh(&shrd->notif_wait_lock);
-	list_del(&wait_entry->list);
-	spin_unlock_bh(&shrd->notif_wait_lock);
-
-	if (wait_entry->aborted)
-		return -EIO;
-
-	/* return value is always >= 0 */
-	if (ret <= 0)
-		return -ETIMEDOUT;
-	return 0;
-}
-
-void iwl_remove_notification(struct iwl_shared *shrd,
-				struct iwl_notification_wait *wait_entry)
-{
-	spin_lock_bh(&shrd->notif_wait_lock);
-	list_del(&wait_entry->list);
-	spin_unlock_bh(&shrd->notif_wait_lock);
-}
-
-void iwl_abort_notification_waits(struct iwl_shared *shrd)
-{
-	unsigned long flags;
-	struct iwl_notification_wait *wait_entry;
-
-	spin_lock_irqsave(&shrd->notif_wait_lock, flags);
-	list_for_each_entry(wait_entry, &shrd->notif_waits, list)
-		wait_entry->aborted = true;
-	spin_unlock_irqrestore(&shrd->notif_wait_lock, flags);
-
-	wake_up_all(&shrd->notif_waitq);
-}
-
 #define UCODE_ALIVE_TIMEOUT	HZ
 #define UCODE_CALIB_TIMEOUT	(2*HZ)
 
-int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
+int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
 				 enum iwl_ucode_type ucode_type)
 {
 	struct iwl_notification_wait alive_wait;
 	struct iwl_alive_data alive_data;
-	struct fw_img *fw;
+	const struct fw_img *fw;
 	int ret;
 	enum iwl_ucode_type old_type;
 
-	iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE,
-				      iwl_alive_fn, &alive_data);
+	old_type = priv->shrd->ucode_type;
+	priv->shrd->ucode_type = ucode_type;
+	fw = iwl_get_ucode_image(priv, ucode_type);
 
-	old_type = trans->shrd->ucode_type;
-	trans->shrd->ucode_type = ucode_type;
-	fw = iwl_get_ucode_image(nic(trans), ucode_type);
+	priv->ucode_loaded = false;
 
 	if (!fw)
 		return -EINVAL;
 
-	ret = iwl_trans_start_fw(trans, fw);
+	iwl_init_notification_wait(&priv->notif_wait, &alive_wait, REPLY_ALIVE,
+				      iwl_alive_fn, &alive_data);
+
+	ret = iwl_trans_start_fw(trans(priv), fw);
 	if (ret) {
-		trans->shrd->ucode_type = old_type;
-		iwl_remove_notification(trans->shrd, &alive_wait);
+		priv->shrd->ucode_type = old_type;
+		iwl_remove_notification(&priv->notif_wait, &alive_wait);
 		return ret;
 	}
 
@@ -602,16 +477,16 @@
 	 * Some things may run in the background now, but we
 	 * just wait for the ALIVE notification here.
 	 */
-	ret = iwl_wait_notification(trans->shrd, &alive_wait,
+	ret = iwl_wait_notification(&priv->notif_wait, &alive_wait,
 					UCODE_ALIVE_TIMEOUT);
 	if (ret) {
-		trans->shrd->ucode_type = old_type;
+		priv->shrd->ucode_type = old_type;
 		return ret;
 	}
 
 	if (!alive_data.valid) {
-		IWL_ERR(trans, "Loaded ucode is not valid!\n");
-		trans->shrd->ucode_type = old_type;
+		IWL_ERR(priv, "Loaded ucode is not valid!\n");
+		priv->shrd->ucode_type = old_type;
 		return -EIO;
 	}
 
@@ -621,9 +496,9 @@
 	 * skip it for WoWLAN.
 	 */
 	if (ucode_type != IWL_UCODE_WOWLAN) {
-		ret = iwl_verify_ucode(nic(trans), ucode_type);
+		ret = iwl_verify_ucode(priv, ucode_type);
 		if (ret) {
-			trans->shrd->ucode_type = old_type;
+			priv->shrd->ucode_type = old_type;
 			return ret;
 		}
 
@@ -631,41 +506,43 @@
 		msleep(5);
 	}
 
-	ret = iwl_alive_notify(trans);
+	ret = iwl_alive_notify(priv);
 	if (ret) {
-		IWL_WARN(trans,
+		IWL_WARN(priv,
 			"Could not complete ALIVE transition: %d\n", ret);
-		trans->shrd->ucode_type = old_type;
+		priv->shrd->ucode_type = old_type;
 		return ret;
 	}
 
+	priv->ucode_loaded = true;
+
 	return 0;
 }
 
-int iwl_run_init_ucode(struct iwl_trans *trans)
+int iwl_run_init_ucode(struct iwl_priv *priv)
 {
 	struct iwl_notification_wait calib_wait;
 	int ret;
 
-	lockdep_assert_held(&trans->shrd->mutex);
+	lockdep_assert_held(&priv->mutex);
 
 	/* No init ucode required? Curious, but maybe ok */
-	if (!nic(trans)->fw.ucode_init.code.len)
+	if (!priv->fw->img[IWL_UCODE_INIT].sec[0].len)
 		return 0;
 
-	if (trans->shrd->ucode_type != IWL_UCODE_NONE)
+	if (priv->init_ucode_run)
 		return 0;
 
-	iwl_init_notification_wait(trans->shrd, &calib_wait,
+	iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
 				      CALIBRATION_COMPLETE_NOTIFICATION,
 				      NULL, NULL);
 
 	/* Will also start the device */
-	ret = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
+	ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
 	if (ret)
 		goto error;
 
-	ret = iwl_init_alive_start(trans);
+	ret = iwl_init_alive_start(priv);
 	if (ret)
 		goto error;
 
@@ -673,594 +550,19 @@
 	 * Some things may run in the background now, but we
 	 * just wait for the calibration complete notification.
 	 */
-	ret = iwl_wait_notification(trans->shrd, &calib_wait,
+	ret = iwl_wait_notification(&priv->notif_wait, &calib_wait,
 					UCODE_CALIB_TIMEOUT);
+	if (!ret)
+		priv->init_ucode_run = true;
 
 	goto out;
 
  error:
-	iwl_remove_notification(trans->shrd, &calib_wait);
+	iwl_remove_notification(&priv->notif_wait, &calib_wait);
  out:
 	/* Whatever happened, stop the device */
-	iwl_trans_stop_device(trans);
+	iwl_trans_stop_device(trans(priv));
+	priv->ucode_loaded = false;
+
 	return ret;
 }
-
-static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
-
-#define UCODE_EXPERIMENTAL_TAG		"exp"
-
-int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first)
-{
-	struct iwl_cfg *cfg = cfg(nic);
-	const char *name_pre = cfg->fw_name_pre;
-	char tag[8];
-
-	if (first) {
-#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
-		nic->fw_index = UCODE_EXPERIMENTAL_INDEX;
-		strcpy(tag, UCODE_EXPERIMENTAL_TAG);
-	} else if (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) {
-#endif
-		nic->fw_index = cfg->ucode_api_max;
-		sprintf(tag, "%d", nic->fw_index);
-	} else {
-		nic->fw_index--;
-		sprintf(tag, "%d", nic->fw_index);
-	}
-
-	if (nic->fw_index < cfg->ucode_api_min) {
-		IWL_ERR(nic, "no suitable firmware found!\n");
-		return -ENOENT;
-	}
-
-	sprintf(nic->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
-
-	IWL_DEBUG_INFO(nic, "attempting to load firmware %s'%s'\n",
-		       (nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
-				? "EXPERIMENTAL " : "",
-		       nic->firmware_name);
-
-	return request_firmware_nowait(THIS_MODULE, 1, nic->firmware_name,
-				       trans(nic)->dev,
-				       GFP_KERNEL, nic, iwl_ucode_callback);
-}
-
-struct iwlagn_firmware_pieces {
-	const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data;
-	size_t inst_size, data_size, init_size, init_data_size,
-	       wowlan_inst_size, wowlan_data_size;
-
-	u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
-	u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
-};
-
-static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic,
-				       const struct firmware *ucode_raw,
-				       struct iwlagn_firmware_pieces *pieces)
-{
-	struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
-	u32 api_ver, hdr_size, build;
-	char buildstr[25];
-	const u8 *src;
-
-	nic->fw.ucode_ver = le32_to_cpu(ucode->ver);
-	api_ver = IWL_UCODE_API(nic->fw.ucode_ver);
-
-	switch (api_ver) {
-	default:
-		hdr_size = 28;
-		if (ucode_raw->size < hdr_size) {
-			IWL_ERR(nic, "File size too small!\n");
-			return -EINVAL;
-		}
-		build = le32_to_cpu(ucode->u.v2.build);
-		pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size);
-		pieces->data_size = le32_to_cpu(ucode->u.v2.data_size);
-		pieces->init_size = le32_to_cpu(ucode->u.v2.init_size);
-		pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size);
-		src = ucode->u.v2.data;
-		break;
-	case 0:
-	case 1:
-	case 2:
-		hdr_size = 24;
-		if (ucode_raw->size < hdr_size) {
-			IWL_ERR(nic, "File size too small!\n");
-			return -EINVAL;
-		}
-		build = 0;
-		pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size);
-		pieces->data_size = le32_to_cpu(ucode->u.v1.data_size);
-		pieces->init_size = le32_to_cpu(ucode->u.v1.init_size);
-		pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size);
-		src = ucode->u.v1.data;
-		break;
-	}
-
-	if (build)
-		sprintf(buildstr, " build %u%s", build,
-		       (nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
-				? " (EXP)" : "");
-	else
-		buildstr[0] = '\0';
-
-	snprintf(nic->fw.fw_version,
-		 sizeof(nic->fw.fw_version),
-		 "%u.%u.%u.%u%s",
-		 IWL_UCODE_MAJOR(nic->fw.ucode_ver),
-		 IWL_UCODE_MINOR(nic->fw.ucode_ver),
-		 IWL_UCODE_API(nic->fw.ucode_ver),
-		 IWL_UCODE_SERIAL(nic->fw.ucode_ver),
-		 buildstr);
-
-	/* Verify size of file vs. image size info in file's header */
-	if (ucode_raw->size != hdr_size + pieces->inst_size +
-				pieces->data_size + pieces->init_size +
-				pieces->init_data_size) {
-
-		IWL_ERR(nic,
-			"uCode file size %d does not match expected size\n",
-			(int)ucode_raw->size);
-		return -EINVAL;
-	}
-
-	pieces->inst = src;
-	src += pieces->inst_size;
-	pieces->data = src;
-	src += pieces->data_size;
-	pieces->init = src;
-	src += pieces->init_size;
-	pieces->init_data = src;
-	src += pieces->init_data_size;
-
-	return 0;
-}
-
-static int iwl_parse_tlv_firmware(struct iwl_nic *nic,
-				const struct firmware *ucode_raw,
-				struct iwlagn_firmware_pieces *pieces,
-				struct iwl_ucode_capabilities *capa)
-{
-	struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
-	struct iwl_ucode_tlv *tlv;
-	size_t len = ucode_raw->size;
-	const u8 *data;
-	int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative;
-	int tmp;
-	u64 alternatives;
-	u32 tlv_len;
-	enum iwl_ucode_tlv_type tlv_type;
-	const u8 *tlv_data;
-	char buildstr[25];
-	u32 build;
-
-	if (len < sizeof(*ucode)) {
-		IWL_ERR(nic, "uCode has invalid length: %zd\n", len);
-		return -EINVAL;
-	}
-
-	if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) {
-		IWL_ERR(nic, "invalid uCode magic: 0X%x\n",
-			le32_to_cpu(ucode->magic));
-		return -EINVAL;
-	}
-
-	/*
-	 * Check which alternatives are present, and "downgrade"
-	 * when the chosen alternative is not present, warning
-	 * the user when that happens. Some files may not have
-	 * any alternatives, so don't warn in that case.
-	 */
-	alternatives = le64_to_cpu(ucode->alternatives);
-	tmp = wanted_alternative;
-	if (wanted_alternative > 63)
-		wanted_alternative = 63;
-	while (wanted_alternative && !(alternatives & BIT(wanted_alternative)))
-		wanted_alternative--;
-	if (wanted_alternative && wanted_alternative != tmp)
-		IWL_WARN(nic,
-			 "uCode alternative %d not available, choosing %d\n",
-			 tmp, wanted_alternative);
-
-	nic->fw.ucode_ver = le32_to_cpu(ucode->ver);
-	build = le32_to_cpu(ucode->build);
-
-	if (build)
-		sprintf(buildstr, " build %u%s", build,
-		       (nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
-				? " (EXP)" : "");
-	else
-		buildstr[0] = '\0';
-
-	snprintf(nic->fw.fw_version,
-		 sizeof(nic->fw.fw_version),
-		 "%u.%u.%u.%u%s",
-		 IWL_UCODE_MAJOR(nic->fw.ucode_ver),
-		 IWL_UCODE_MINOR(nic->fw.ucode_ver),
-		 IWL_UCODE_API(nic->fw.ucode_ver),
-		 IWL_UCODE_SERIAL(nic->fw.ucode_ver),
-		 buildstr);
-
-	data = ucode->data;
-
-	len -= sizeof(*ucode);
-
-	while (len >= sizeof(*tlv)) {
-		u16 tlv_alt;
-
-		len -= sizeof(*tlv);
-		tlv = (void *)data;
-
-		tlv_len = le32_to_cpu(tlv->length);
-		tlv_type = le16_to_cpu(tlv->type);
-		tlv_alt = le16_to_cpu(tlv->alternative);
-		tlv_data = tlv->data;
-
-		if (len < tlv_len) {
-			IWL_ERR(nic, "invalid TLV len: %zd/%u\n",
-				len, tlv_len);
-			return -EINVAL;
-		}
-		len -= ALIGN(tlv_len, 4);
-		data += sizeof(*tlv) + ALIGN(tlv_len, 4);
-
-		/*
-		 * Alternative 0 is always valid.
-		 *
-		 * Skip alternative TLVs that are not selected.
-		 */
-		if (tlv_alt != 0 && tlv_alt != wanted_alternative)
-			continue;
-
-		switch (tlv_type) {
-		case IWL_UCODE_TLV_INST:
-			pieces->inst = tlv_data;
-			pieces->inst_size = tlv_len;
-			break;
-		case IWL_UCODE_TLV_DATA:
-			pieces->data = tlv_data;
-			pieces->data_size = tlv_len;
-			break;
-		case IWL_UCODE_TLV_INIT:
-			pieces->init = tlv_data;
-			pieces->init_size = tlv_len;
-			break;
-		case IWL_UCODE_TLV_INIT_DATA:
-			pieces->init_data = tlv_data;
-			pieces->init_data_size = tlv_len;
-			break;
-		case IWL_UCODE_TLV_BOOT:
-			IWL_ERR(nic, "Found unexpected BOOT ucode\n");
-			break;
-		case IWL_UCODE_TLV_PROBE_MAX_LEN:
-			if (tlv_len != sizeof(u32))
-				goto invalid_tlv_len;
-			capa->max_probe_length =
-					le32_to_cpup((__le32 *)tlv_data);
-			break;
-		case IWL_UCODE_TLV_PAN:
-			if (tlv_len)
-				goto invalid_tlv_len;
-			capa->flags |= IWL_UCODE_TLV_FLAGS_PAN;
-			break;
-		case IWL_UCODE_TLV_FLAGS:
-			/* must be at least one u32 */
-			if (tlv_len < sizeof(u32))
-				goto invalid_tlv_len;
-			/* and a proper number of u32s */
-			if (tlv_len % sizeof(u32))
-				goto invalid_tlv_len;
-			/*
-			 * This driver only reads the first u32 as
-			 * right now no more features are defined,
-			 * if that changes then either the driver
-			 * will not work with the new firmware, or
-			 * it'll not take advantage of new features.
-			 */
-			capa->flags = le32_to_cpup((__le32 *)tlv_data);
-			break;
-		case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
-			if (tlv_len != sizeof(u32))
-				goto invalid_tlv_len;
-			pieces->init_evtlog_ptr =
-					le32_to_cpup((__le32 *)tlv_data);
-			break;
-		case IWL_UCODE_TLV_INIT_EVTLOG_SIZE:
-			if (tlv_len != sizeof(u32))
-				goto invalid_tlv_len;
-			pieces->init_evtlog_size =
-					le32_to_cpup((__le32 *)tlv_data);
-			break;
-		case IWL_UCODE_TLV_INIT_ERRLOG_PTR:
-			if (tlv_len != sizeof(u32))
-				goto invalid_tlv_len;
-			pieces->init_errlog_ptr =
-					le32_to_cpup((__le32 *)tlv_data);
-			break;
-		case IWL_UCODE_TLV_RUNT_EVTLOG_PTR:
-			if (tlv_len != sizeof(u32))
-				goto invalid_tlv_len;
-			pieces->inst_evtlog_ptr =
-					le32_to_cpup((__le32 *)tlv_data);
-			break;
-		case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE:
-			if (tlv_len != sizeof(u32))
-				goto invalid_tlv_len;
-			pieces->inst_evtlog_size =
-					le32_to_cpup((__le32 *)tlv_data);
-			break;
-		case IWL_UCODE_TLV_RUNT_ERRLOG_PTR:
-			if (tlv_len != sizeof(u32))
-				goto invalid_tlv_len;
-			pieces->inst_errlog_ptr =
-					le32_to_cpup((__le32 *)tlv_data);
-			break;
-		case IWL_UCODE_TLV_ENHANCE_SENS_TBL:
-			if (tlv_len)
-				goto invalid_tlv_len;
-			nic->fw.enhance_sensitivity_table = true;
-			break;
-		case IWL_UCODE_TLV_WOWLAN_INST:
-			pieces->wowlan_inst = tlv_data;
-			pieces->wowlan_inst_size = tlv_len;
-			break;
-		case IWL_UCODE_TLV_WOWLAN_DATA:
-			pieces->wowlan_data = tlv_data;
-			pieces->wowlan_data_size = tlv_len;
-			break;
-		case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE:
-			if (tlv_len != sizeof(u32))
-				goto invalid_tlv_len;
-			capa->standard_phy_calibration_size =
-					le32_to_cpup((__le32 *)tlv_data);
-			break;
-		default:
-			IWL_DEBUG_INFO(nic, "unknown TLV: %d\n", tlv_type);
-			break;
-		}
-	}
-
-	if (len) {
-		IWL_ERR(nic, "invalid TLV after parsing: %zd\n", len);
-		iwl_print_hex_dump(nic, IWL_DL_FW, (u8 *)data, len);
-		return -EINVAL;
-	}
-
-	return 0;
-
- invalid_tlv_len:
-	IWL_ERR(nic, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
-	iwl_print_hex_dump(nic, IWL_DL_FW, tlv_data, tlv_len);
-
-	return -EINVAL;
-}
-
-/**
- * iwl_ucode_callback - callback when firmware was loaded
- *
- * If loaded successfully, copies the firmware into buffers
- * for the card to fetch (via DMA).
- */
-static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
-{
-	struct iwl_nic *nic = context;
-	struct iwl_cfg *cfg = cfg(nic);
-	struct iwl_fw *fw = &nic->fw;
-	struct iwl_ucode_header *ucode;
-	int err;
-	struct iwlagn_firmware_pieces pieces;
-	const unsigned int api_max = cfg->ucode_api_max;
-	unsigned int api_ok = cfg->ucode_api_ok;
-	const unsigned int api_min = cfg->ucode_api_min;
-	u32 api_ver;
-
-	fw->ucode_capa.max_probe_length = 200;
-	fw->ucode_capa.standard_phy_calibration_size =
-			IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
-
-	if (!api_ok)
-		api_ok = api_max;
-
-	memset(&pieces, 0, sizeof(pieces));
-
-	if (!ucode_raw) {
-		if (nic->fw_index <= api_ok)
-			IWL_ERR(nic,
-				"request for firmware file '%s' failed.\n",
-				nic->firmware_name);
-		goto try_again;
-	}
-
-	IWL_DEBUG_INFO(nic, "Loaded firmware file '%s' (%zd bytes).\n",
-		       nic->firmware_name, ucode_raw->size);
-
-	/* Make sure that we got at least the API version number */
-	if (ucode_raw->size < 4) {
-		IWL_ERR(nic, "File size way too small!\n");
-		goto try_again;
-	}
-
-	/* Data from ucode file:  header followed by uCode images */
-	ucode = (struct iwl_ucode_header *)ucode_raw->data;
-
-	if (ucode->ver)
-		err = iwl_parse_v1_v2_firmware(nic, ucode_raw, &pieces);
-	else
-		err = iwl_parse_tlv_firmware(nic, ucode_raw, &pieces,
-					   &fw->ucode_capa);
-
-	if (err)
-		goto try_again;
-
-	api_ver = IWL_UCODE_API(nic->fw.ucode_ver);
-
-	/*
-	 * api_ver should match the api version forming part of the
-	 * firmware filename ... but we don't check for that and only rely
-	 * on the API version read from firmware header from here on forward
-	 */
-	/* no api version check required for experimental uCode */
-	if (nic->fw_index != UCODE_EXPERIMENTAL_INDEX) {
-		if (api_ver < api_min || api_ver > api_max) {
-			IWL_ERR(nic,
-				"Driver unable to support your firmware API. "
-				"Driver supports v%u, firmware is v%u.\n",
-				api_max, api_ver);
-			goto try_again;
-		}
-
-		if (api_ver < api_ok) {
-			if (api_ok != api_max)
-				IWL_ERR(nic, "Firmware has old API version, "
-					"expected v%u through v%u, got v%u.\n",
-					api_ok, api_max, api_ver);
-			else
-				IWL_ERR(nic, "Firmware has old API version, "
-					"expected v%u, got v%u.\n",
-					api_max, api_ver);
-			IWL_ERR(nic, "New firmware can be obtained from "
-				      "http://www.intellinuxwireless.org/.\n");
-		}
-	}
-
-	IWL_INFO(nic, "loaded firmware version %s", nic->fw.fw_version);
-
-	/*
-	 * For any of the failures below (before allocating pci memory)
-	 * we will try to load a version with a smaller API -- maybe the
-	 * user just got a corrupted version of the latest API.
-	 */
-
-	IWL_DEBUG_INFO(nic, "f/w package hdr ucode version raw = 0x%x\n",
-		       nic->fw.ucode_ver);
-	IWL_DEBUG_INFO(nic, "f/w package hdr runtime inst size = %Zd\n",
-		       pieces.inst_size);
-	IWL_DEBUG_INFO(nic, "f/w package hdr runtime data size = %Zd\n",
-		       pieces.data_size);
-	IWL_DEBUG_INFO(nic, "f/w package hdr init inst size = %Zd\n",
-		       pieces.init_size);
-	IWL_DEBUG_INFO(nic, "f/w package hdr init data size = %Zd\n",
-		       pieces.init_data_size);
-
-	/* Verify that uCode images will fit in card's SRAM */
-	if (pieces.inst_size > cfg->max_inst_size) {
-		IWL_ERR(nic, "uCode instr len %Zd too large to fit in\n",
-			pieces.inst_size);
-		goto try_again;
-	}
-
-	if (pieces.data_size > cfg->max_data_size) {
-		IWL_ERR(nic, "uCode data len %Zd too large to fit in\n",
-			pieces.data_size);
-		goto try_again;
-	}
-
-	if (pieces.init_size > cfg->max_inst_size) {
-		IWL_ERR(nic, "uCode init instr len %Zd too large to fit in\n",
-			pieces.init_size);
-		goto try_again;
-	}
-
-	if (pieces.init_data_size > cfg->max_data_size) {
-		IWL_ERR(nic, "uCode init data len %Zd too large to fit in\n",
-			pieces.init_data_size);
-		goto try_again;
-	}
-
-	/* Allocate ucode buffers for card's bus-master loading ... */
-
-	/* Runtime instructions and 2 copies of data:
-	 * 1) unmodified from disk
-	 * 2) backup cache for save/restore during power-downs */
-	if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.code,
-			      pieces.inst, pieces.inst_size))
-		goto err_pci_alloc;
-	if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.data,
-			      pieces.data, pieces.data_size))
-		goto err_pci_alloc;
-
-	/* Initialization instructions and data */
-	if (pieces.init_size && pieces.init_data_size) {
-		if (iwl_alloc_fw_desc(nic,
-				      &nic->fw.ucode_init.code,
-				      pieces.init, pieces.init_size))
-			goto err_pci_alloc;
-		if (iwl_alloc_fw_desc(nic,
-				      &nic->fw.ucode_init.data,
-				      pieces.init_data, pieces.init_data_size))
-			goto err_pci_alloc;
-	}
-
-	/* WoWLAN instructions and data */
-	if (pieces.wowlan_inst_size && pieces.wowlan_data_size) {
-		if (iwl_alloc_fw_desc(nic,
-				      &nic->fw.ucode_wowlan.code,
-				      pieces.wowlan_inst,
-				      pieces.wowlan_inst_size))
-			goto err_pci_alloc;
-		if (iwl_alloc_fw_desc(nic,
-				      &nic->fw.ucode_wowlan.data,
-				      pieces.wowlan_data,
-				      pieces.wowlan_data_size))
-			goto err_pci_alloc;
-	}
-
-	/* Now that we can no longer fail, copy information */
-
-	/*
-	 * The (size - 16) / 12 formula is based on the information recorded
-	 * for each event, which is of mode 1 (including timestamp) for all
-	 * new microcodes that include this information.
-	 */
-	nic->init_evtlog_ptr = pieces.init_evtlog_ptr;
-	if (pieces.init_evtlog_size)
-		nic->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
-	else
-		nic->init_evtlog_size =
-			cfg->base_params->max_event_log_size;
-	nic->init_errlog_ptr = pieces.init_errlog_ptr;
-	nic->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
-	if (pieces.inst_evtlog_size)
-		nic->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
-	else
-		nic->inst_evtlog_size =
-			cfg->base_params->max_event_log_size;
-	nic->inst_errlog_ptr = pieces.inst_errlog_ptr;
-
-	/*
-	 * figure out the offset of chain noise reset and gain commands
-	 * base on the size of standard phy calibration commands table size
-	 */
-	if (fw->ucode_capa.standard_phy_calibration_size >
-	    IWL_MAX_PHY_CALIBRATE_TBL_SIZE)
-		fw->ucode_capa.standard_phy_calibration_size =
-			IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
-
-	/* We have our copies now, allow OS release its copies */
-	release_firmware(ucode_raw);
-	complete(&nic->request_firmware_complete);
-
-	nic->op_mode = iwl_dvm_ops.start(nic->shrd->trans);
-
-	if (!nic->op_mode)
-		goto out_unbind;
-
-	return;
-
- try_again:
-	/* try next, if any */
-	release_firmware(ucode_raw);
-	if (iwl_request_firmware(nic, false))
-		goto out_unbind;
-	return;
-
- err_pci_alloc:
-	IWL_ERR(nic, "failed to allocate pci memory\n");
-	iwl_dealloc_ucode(nic);
-	release_firmware(ucode_raw);
- out_unbind:
-	complete(&nic->request_firmware_complete);
-	device_release_driver(trans(nic)->dev);
-}
-
diff --git a/drivers/net/wireless/iwlwifi/iwl-wifi.h b/drivers/net/wireless/iwlwifi/iwl-wifi.h
deleted file mode 100644
index d5cba07..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-wifi.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *  * Neither the name Intel Corporation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
-
-#ifndef __iwl_wifi_h__
-#define __iwl_wifi_h__
-
-#include "iwl-shared.h"
-#include "iwl-ucode.h"
-
-#define UCODE_EXPERIMENTAL_INDEX	100
-
-/**
- * struct iwl_nic - nic common data
- * @fw: the iwl_fw structure
- * @shrd: pointer to common shared structure
- * @op_mode: the running op_mode
- * @fw_index: firmware revision to try loading
- * @firmware_name: composite filename of ucode file to load
- * @init_evtlog_ptr: event log offset for init ucode.
- * @init_evtlog_size: event log size for init ucode.
- * @init_errlog_ptr: error log offfset for init ucode.
- * @inst_evtlog_ptr: event log offset for runtime ucode.
- * @inst_evtlog_size: event log size for runtime ucode.
- * @inst_errlog_ptr: error log offfset for runtime ucode.
- * @request_firmware_complete: the firmware has been obtained from user space
- */
-struct iwl_nic {
-	struct iwl_fw fw;
-
-	struct iwl_shared *shrd;
-	struct iwl_op_mode *op_mode;
-
-	int fw_index;                   /* firmware we're trying to load */
-	char firmware_name[25];         /* name of firmware file to load */
-
-	u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
-	u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
-
-	struct completion request_firmware_complete;
-};
-
-
-int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first);
-void iwl_dealloc_ucode(struct iwl_nic *nic);
-
-int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type);
-void iwl_send_prio_tbl(struct iwl_trans *trans);
-int iwl_init_alive_start(struct iwl_trans *trans);
-int iwl_run_init_ucode(struct iwl_trans *trans);
-int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
-				 enum iwl_ucode_type ucode_type);
-#endif  /* __iwl_wifi_h__ */
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index a7cd311..3fa1ece 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -1631,42 +1631,6 @@
 
 
 /*
- * "Site survey", here just current channel and noise level
- */
-
-static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
-	int idx, struct survey_info *survey)
-{
-	struct lbs_private *priv = wiphy_priv(wiphy);
-	s8 signal, noise;
-	int ret;
-
-	if (dev == priv->mesh_dev)
-		return -EOPNOTSUPP;
-
-	if (idx != 0)
-		ret = -ENOENT;
-
-	lbs_deb_enter(LBS_DEB_CFG80211);
-
-	survey->channel = ieee80211_get_channel(wiphy,
-		ieee80211_channel_to_frequency(priv->channel,
-					       IEEE80211_BAND_2GHZ));
-
-	ret = lbs_get_rssi(priv, &signal, &noise);
-	if (ret == 0) {
-		survey->filled = SURVEY_INFO_NOISE_DBM;
-		survey->noise = noise;
-	}
-
-	lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
-	return ret;
-}
-
-
-
-
-/*
  * Change interface
  */
 
@@ -2068,7 +2032,6 @@
 	.del_key = lbs_cfg_del_key,
 	.set_default_key = lbs_cfg_set_default_key,
 	.get_station = lbs_cfg_get_station,
-	.dump_survey = lbs_get_survey,
 	.change_virtual_intf = lbs_change_intf,
 	.join_ibss = lbs_join_ibss,
 	.leave_ibss = lbs_leave_ibss,
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index ba16f05..b7ce6a6 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -27,6 +27,7 @@
 #include <linux/etherdevice.h>
 #include <linux/debugfs.h>
 #include <linux/module.h>
+#include <linux/ktime.h>
 #include <net/genetlink.h>
 #include "mac80211_hwsim.h"
 
@@ -321,11 +322,15 @@
 	struct dentry *debugfs_group;
 
 	int power_level;
+
+	/* difference between this hw's clock and the real clock, in usecs */
+	u64 tsf_offset;
 };
 
 
 struct hwsim_radiotap_hdr {
 	struct ieee80211_radiotap_header hdr;
+	__le64 rt_tsft;
 	u8 rt_flags;
 	u8 rt_rate;
 	__le16 rt_channel;
@@ -367,6 +372,28 @@
 	return NETDEV_TX_OK;
 }
 
+static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data)
+{
+	struct timeval tv = ktime_to_timeval(ktime_get_real());
+	u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
+	return cpu_to_le64(now + data->tsf_offset);
+}
+
+static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw,
+		struct ieee80211_vif *vif)
+{
+	struct mac80211_hwsim_data *data = hw->priv;
+	return le64_to_cpu(__mac80211_hwsim_get_tsf(data));
+}
+
+static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
+		struct ieee80211_vif *vif, u64 tsf)
+{
+	struct mac80211_hwsim_data *data = hw->priv;
+	struct timeval tv = ktime_to_timeval(ktime_get_real());
+	u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
+	data->tsf_offset = tsf - now;
+}
 
 static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
 				      struct sk_buff *tx_skb)
@@ -391,7 +418,9 @@
 	hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr));
 	hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
 					  (1 << IEEE80211_RADIOTAP_RATE) |
+					  (1 << IEEE80211_RADIOTAP_TSFT) |
 					  (1 << IEEE80211_RADIOTAP_CHANNEL));
+	hdr->rt_tsft = __mac80211_hwsim_get_tsf(data);
 	hdr->rt_flags = 0;
 	hdr->rt_rate = txrate->bitrate / 5;
 	hdr->rt_channel = cpu_to_le16(data->channel->center_freq);
@@ -610,7 +639,7 @@
 	}
 
 	memset(&rx_status, 0, sizeof(rx_status));
-	/* TODO: set mactime */
+	rx_status.flag |= RX_FLAG_MACTIME_MPDU;
 	rx_status.freq = data->channel->center_freq;
 	rx_status.band = data->channel->band;
 	rx_status.rate_idx = info->control.rates[0].idx;
@@ -654,6 +683,8 @@
 
 		if (mac80211_hwsim_addr_match(data2, hdr->addr1))
 			ack = true;
+		rx_status.mactime =
+			le64_to_cpu(__mac80211_hwsim_get_tsf(data2));
 		memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
 		ieee80211_rx_irqsafe(data2->hw, nskb);
 	}
@@ -667,6 +698,12 @@
 	bool ack;
 	struct ieee80211_tx_info *txi;
 	u32 _pid;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
+	struct mac80211_hwsim_data *data = hw->priv;
+
+	if (ieee80211_is_beacon(mgmt->frame_control) ||
+	    ieee80211_is_probe_resp(mgmt->frame_control))
+		mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data);
 
 	mac80211_hwsim_monitor_rx(hw, skb);
 
@@ -763,9 +800,11 @@
 				     struct ieee80211_vif *vif)
 {
 	struct ieee80211_hw *hw = arg;
+	struct mac80211_hwsim_data *data = hw->priv;
 	struct sk_buff *skb;
 	struct ieee80211_tx_info *info;
 	u32 _pid;
+	struct ieee80211_mgmt *mgmt;
 
 	hwsim_check_magic(vif);
 
@@ -779,6 +818,9 @@
 		return;
 	info = IEEE80211_SKB_CB(skb);
 
+	mgmt = (struct ieee80211_mgmt *) skb->data;
+	mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data);
+
 	mac80211_hwsim_monitor_rx(hw, skb);
 
 	/* wmediumd mode check */
@@ -1199,6 +1241,8 @@
 	.sw_scan_start = mac80211_hwsim_sw_scan,
 	.sw_scan_complete = mac80211_hwsim_sw_scan_complete,
 	.flush = mac80211_hwsim_flush,
+	.get_tsf = mac80211_hwsim_get_tsf,
+	.set_tsf = mac80211_hwsim_set_tsf,
 };
 
 
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 34bba52..a5e182b 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -44,16 +44,16 @@
 
 	ht_cap->ht_cap.ampdu_params_info =
 		(sband->ht_cap.ampdu_factor &
-		 IEEE80211_HT_AMPDU_PARM_FACTOR)|
+		 IEEE80211_HT_AMPDU_PARM_FACTOR) |
 		((sband->ht_cap.ampdu_density <<
 		 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) &
 		 IEEE80211_HT_AMPDU_PARM_DENSITY);
 
 	memcpy((u8 *) &ht_cap->ht_cap.mcs, &sband->ht_cap.mcs,
-						sizeof(sband->ht_cap.mcs));
+	       sizeof(sband->ht_cap.mcs));
 
 	if (priv->bss_mode == NL80211_IFTYPE_STATION ||
-			(sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
+	    sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
 		/* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
 		SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask);
 
@@ -69,8 +69,8 @@
  * table which matches the requested BA status.
  */
 static struct mwifiex_tx_ba_stream_tbl *
-mwifiex_11n_get_tx_ba_stream_status(struct mwifiex_private *priv,
-				  enum mwifiex_ba_status ba_status)
+mwifiex_get_ba_status(struct mwifiex_private *priv,
+		      enum mwifiex_ba_status ba_status)
 {
 	struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
 	unsigned long flags;
@@ -107,12 +107,11 @@
 
 	tid = del_ba_param_set >> DELBA_TID_POS;
 	if (del_ba->del_result == BA_RESULT_SUCCESS) {
-		mwifiex_11n_delete_ba_stream_tbl(priv, tid,
-				del_ba->peer_mac_addr, TYPE_DELBA_SENT,
-				INITIATOR_BIT(del_ba_param_set));
+		mwifiex_del_ba_tbl(priv, tid, del_ba->peer_mac_addr,
+				   TYPE_DELBA_SENT,
+				   INITIATOR_BIT(del_ba_param_set));
 
-		tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_status(priv,
-						BA_STREAM_SETUP_INPROGRESS);
+		tx_ba_tbl = mwifiex_get_ba_status(priv, BA_SETUP_INPROGRESS);
 		if (tx_ba_tbl)
 			mwifiex_send_addba(priv, tx_ba_tbl->tid,
 					   tx_ba_tbl->ra);
@@ -120,18 +119,17 @@
 		  * In case of failure, recreate the deleted stream in case
 		  * we initiated the ADDBA
 		  */
-		if (INITIATOR_BIT(del_ba_param_set)) {
-			mwifiex_11n_create_tx_ba_stream_tbl(priv,
-					del_ba->peer_mac_addr, tid,
-					BA_STREAM_SETUP_INPROGRESS);
+		if (!INITIATOR_BIT(del_ba_param_set))
+			return 0;
 
-			tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_status(priv,
-					BA_STREAM_SETUP_INPROGRESS);
-			if (tx_ba_tbl)
-				mwifiex_11n_delete_ba_stream_tbl(priv,
-						tx_ba_tbl->tid, tx_ba_tbl->ra,
-						TYPE_DELBA_SENT, true);
-		}
+		mwifiex_create_ba_tbl(priv, del_ba->peer_mac_addr, tid,
+				      BA_SETUP_INPROGRESS);
+
+		tx_ba_tbl = mwifiex_get_ba_status(priv, BA_SETUP_INPROGRESS);
+
+		if (tx_ba_tbl)
+			mwifiex_del_ba_tbl(priv, tx_ba_tbl->tid, tx_ba_tbl->ra,
+					   TYPE_DELBA_SENT, true);
 	}
 
 	return 0;
@@ -160,18 +158,17 @@
 		& IEEE80211_ADDBA_PARAM_TID_MASK)
 		>> BLOCKACKPARAM_TID_POS;
 	if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) {
-		tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid,
+		tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid,
 						add_ba_rsp->peer_mac_addr);
 		if (tx_ba_tbl) {
 			dev_dbg(priv->adapter->dev, "info: BA stream complete\n");
-			tx_ba_tbl->ba_status = BA_STREAM_SETUP_COMPLETE;
+			tx_ba_tbl->ba_status = BA_SETUP_COMPLETE;
 		} else {
 			dev_err(priv->adapter->dev, "BA stream not created\n");
 		}
 	} else {
-		mwifiex_11n_delete_ba_stream_tbl(priv, tid,
-						add_ba_rsp->peer_mac_addr,
-						TYPE_DELBA_SENT, true);
+		mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr,
+				   TYPE_DELBA_SENT, true);
 		if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT)
 			priv->aggr_prio_tbl[tid].ampdu_ap =
 				BA_STREAM_NOT_ALLOWED;
@@ -392,9 +389,9 @@
 		chan_list->chan_scan_param[0].radio_type =
 			mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
 
-		if ((sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
-			&& (bss_desc->bcn_ht_info->ht_param &
-				IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
+		if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
+		    bss_desc->bcn_ht_info->ht_param &
+		    IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)
 			SET_SECONDARYCHAN(chan_list->chan_scan_param[0].
 					  radio_type,
 					  (bss_desc->bcn_ht_info->ht_param &
@@ -467,7 +464,7 @@
 	tx_buf = min(priv->adapter->max_tx_buf_size, max_amsdu);
 
 	dev_dbg(priv->adapter->dev, "info: max_amsdu=%d, max_tx_buf=%d\n",
-			max_amsdu, priv->adapter->max_tx_buf_size);
+		max_amsdu, priv->adapter->max_tx_buf_size);
 
 	if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_2K)
 		curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
@@ -507,7 +504,7 @@
 				struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl)
 {
 	if (!tx_ba_tsr_tbl &&
-			mwifiex_is_tx_ba_stream_ptr_valid(priv, tx_ba_tsr_tbl))
+	    mwifiex_is_tx_ba_stream_ptr_valid(priv, tx_ba_tsr_tbl))
 		return;
 
 	dev_dbg(priv->adapter->dev, "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl);
@@ -544,16 +541,15 @@
  * table which matches the given RA/TID pair.
  */
 struct mwifiex_tx_ba_stream_tbl *
-mwifiex_11n_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
-				 int tid, u8 *ra)
+mwifiex_get_ba_tbl(struct mwifiex_private *priv, int tid, u8 *ra)
 {
 	struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl;
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
 	list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
-		if ((!memcmp(tx_ba_tsr_tbl->ra, ra, ETH_ALEN))
-		    && (tx_ba_tsr_tbl->tid == tid)) {
+		if (!memcmp(tx_ba_tsr_tbl->ra, ra, ETH_ALEN) &&
+		    tx_ba_tsr_tbl->tid == tid) {
 			spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
 					       flags);
 			return tx_ba_tsr_tbl;
@@ -567,14 +563,13 @@
  * This function creates an entry in Tx BA stream table for the
  * given RA/TID pair.
  */
-void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv,
-					 u8 *ra, int tid,
-					 enum mwifiex_ba_status ba_status)
+void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
+			   enum mwifiex_ba_status ba_status)
 {
 	struct mwifiex_tx_ba_stream_tbl *new_node;
 	unsigned long flags;
 
-	if (!mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, ra)) {
+	if (!mwifiex_get_ba_tbl(priv, tid, ra)) {
 		new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl),
 				   GFP_ATOMIC);
 		if (!new_node) {
@@ -668,9 +663,8 @@
 
 	tid = del_ba_param_set >> DELBA_TID_POS;
 
-	mwifiex_11n_delete_ba_stream_tbl(priv, tid, cmd_del_ba->peer_mac_addr,
-					 TYPE_DELBA_RECEIVE,
-					 INITIATOR_BIT(del_ba_param_set));
+	mwifiex_del_ba_tbl(priv, tid, cmd_del_ba->peer_mac_addr,
+			   TYPE_DELBA_RECEIVE, INITIATOR_BIT(del_ba_param_set));
 }
 
 /*
@@ -724,7 +718,7 @@
 	list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
 		rx_reo_tbl->tid = (u16) tx_ba_tsr_tbl->tid;
 		dev_dbg(priv->adapter->dev, "data: %s tid=%d\n",
-						__func__, rx_reo_tbl->tid);
+			__func__, rx_reo_tbl->tid);
 		memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN);
 		rx_reo_tbl++;
 		count++;
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index 90b421e..77646d7 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -46,13 +46,12 @@
 					     struct mwifiex_tx_ba_stream_tbl
 					     *tx_tbl);
 void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv);
-struct mwifiex_tx_ba_stream_tbl *mwifiex_11n_get_tx_ba_stream_tbl(struct
+struct mwifiex_tx_ba_stream_tbl *mwifiex_get_ba_tbl(struct
 							     mwifiex_private
 							     *priv, int tid,
 							     u8 *ra);
-void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv, u8 *ra,
-				       int tid,
-				       enum mwifiex_ba_status ba_status);
+void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
+			   enum mwifiex_ba_status ba_status);
 int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac);
 int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
 		       int initiator);
@@ -87,9 +86,8 @@
 static inline u8
 mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid)
 {
-	return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)
-			&& ((priv->is_data_rate_auto)
-			|| !((priv->bitmap_rates[2]) & 0x03)))
+	return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) &&
+		 (priv->is_data_rate_auto || !(priv->bitmap_rates[2] & 0x03)))
 		? true : false);
 }
 
@@ -150,11 +148,11 @@
  */
 static inline int
 mwifiex_is_ba_stream_setup(struct mwifiex_private *priv,
-			  struct mwifiex_ra_list_tbl *ptr, int tid)
+			   struct mwifiex_ra_list_tbl *ptr, int tid)
 {
 	struct mwifiex_tx_ba_stream_tbl *tx_tbl;
 
-	tx_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, ptr->ra);
+	tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra);
 	if (tx_tbl && IS_BASTREAM_SETUP(tx_tbl))
 		return true;
 
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index ea6832d..9eefb2a 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -84,7 +84,7 @@
 	/* Add payload */
 	skb_put(skb_aggr, skb_src->len);
 	memcpy(skb_aggr->data + sizeof(*tx_header), skb_src->data,
-							skb_src->len);
+	       skb_src->len);
 	*pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len +
 						      LLC_SNAP_LEN)) & 3)) : 0;
 	skb_put(skb_aggr, *pad);
@@ -119,14 +119,14 @@
 	local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd));
 	local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU);
 	local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len -
-			sizeof(*local_tx_pd));
+						 sizeof(*local_tx_pd));
 
 	if (local_tx_pd->tx_control == 0)
 		/* TxCtrl set by user or default */
 		local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
 
-	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-		(priv->adapter->pps_uapsd_mode)) {
+	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
+	    priv->adapter->pps_uapsd_mode) {
 		if (true == mwifiex_check_last_packet_indication(priv)) {
 			priv->adapter->tx_lock_flag = true;
 			local_tx_pd->flags =
@@ -257,9 +257,8 @@
 			mwifiex_write_data_complete(adapter, skb_aggr, -1);
 			return -1;
 		}
-		if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-			(adapter->pps_uapsd_mode) &&
-			(adapter->tx_lock_flag)) {
+		if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
+		    adapter->pps_uapsd_mode && adapter->tx_lock_flag) {
 				priv->adapter->tx_lock_flag = false;
 				if (ptx_pd)
 					ptx_pd->flags = 0;
@@ -279,7 +278,7 @@
 	case -1:
 		adapter->data_sent = false;
 		dev_err(adapter->dev, "%s: host_to_card failed: %#x\n",
-						__func__, ret);
+			__func__, ret);
 		adapter->dbg.num_tx_host_to_card_failure++;
 		mwifiex_write_data_complete(adapter, skb_aggr, ret);
 		return 0;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 681d3f2..9c44088 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -27,31 +27,31 @@
 #include "11n_rxreorder.h"
 
 /*
- * This function dispatches all packets in the Rx reorder table.
+ * This function dispatches all packets in the Rx reorder table until the
+ * start window.
  *
  * There could be holes in the buffer, which are skipped by the function.
  * Since the buffer is linear, the function uses rotation to simulate
  * circular buffer.
  */
 static void
-mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,
-					 struct mwifiex_rx_reorder_tbl
-					 *rx_reor_tbl_ptr, int start_win)
+mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
+			 struct mwifiex_rx_reorder_tbl *tbl, int start_win)
 {
-	int no_pkt_to_send, i;
+	int pkt_to_send, i;
 	void *rx_tmp_ptr;
 	unsigned long flags;
 
-	no_pkt_to_send = (start_win > rx_reor_tbl_ptr->start_win) ?
-		min((start_win - rx_reor_tbl_ptr->start_win),
-		    rx_reor_tbl_ptr->win_size) : rx_reor_tbl_ptr->win_size;
+	pkt_to_send = (start_win > tbl->start_win) ?
+		      min((start_win - tbl->start_win), tbl->win_size) :
+		      tbl->win_size;
 
-	for (i = 0; i < no_pkt_to_send; ++i) {
+	for (i = 0; i < pkt_to_send; ++i) {
 		spin_lock_irqsave(&priv->rx_pkt_lock, flags);
 		rx_tmp_ptr = NULL;
-		if (rx_reor_tbl_ptr->rx_reorder_ptr[i]) {
-			rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i];
-			rx_reor_tbl_ptr->rx_reorder_ptr[i] = NULL;
+		if (tbl->rx_reorder_ptr[i]) {
+			rx_tmp_ptr = tbl->rx_reorder_ptr[i];
+			tbl->rx_reorder_ptr[i] = NULL;
 		}
 		spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
 		if (rx_tmp_ptr)
@@ -63,13 +63,12 @@
 	 * We don't have a circular buffer, hence use rotation to simulate
 	 * circular buffer
 	 */
-	for (i = 0; i < rx_reor_tbl_ptr->win_size - no_pkt_to_send; ++i) {
-		rx_reor_tbl_ptr->rx_reorder_ptr[i] =
-			rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i];
-		rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i] = NULL;
+	for (i = 0; i < tbl->win_size - pkt_to_send; ++i) {
+		tbl->rx_reorder_ptr[i] = tbl->rx_reorder_ptr[pkt_to_send + i];
+		tbl->rx_reorder_ptr[pkt_to_send + i] = NULL;
 	}
 
-	rx_reor_tbl_ptr->start_win = start_win;
+	tbl->start_win = start_win;
 	spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
 }
 
@@ -83,20 +82,20 @@
  */
 static void
 mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
-			      struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr)
+			      struct mwifiex_rx_reorder_tbl *tbl)
 {
 	int i, j, xchg;
 	void *rx_tmp_ptr;
 	unsigned long flags;
 
-	for (i = 0; i < rx_reor_tbl_ptr->win_size; ++i) {
+	for (i = 0; i < tbl->win_size; ++i) {
 		spin_lock_irqsave(&priv->rx_pkt_lock, flags);
-		if (!rx_reor_tbl_ptr->rx_reorder_ptr[i]) {
+		if (!tbl->rx_reorder_ptr[i]) {
 			spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
 			break;
 		}
-		rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i];
-		rx_reor_tbl_ptr->rx_reorder_ptr[i] = NULL;
+		rx_tmp_ptr = tbl->rx_reorder_ptr[i];
+		tbl->rx_reorder_ptr[i] = NULL;
 		spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
 		mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
 	}
@@ -107,15 +106,13 @@
 	 * circular buffer
 	 */
 	if (i > 0) {
-		xchg = rx_reor_tbl_ptr->win_size - i;
+		xchg = tbl->win_size - i;
 		for (j = 0; j < xchg; ++j) {
-			rx_reor_tbl_ptr->rx_reorder_ptr[j] =
-				rx_reor_tbl_ptr->rx_reorder_ptr[i + j];
-			rx_reor_tbl_ptr->rx_reorder_ptr[i + j] = NULL;
+			tbl->rx_reorder_ptr[j] = tbl->rx_reorder_ptr[i + j];
+			tbl->rx_reorder_ptr[i + j] = NULL;
 		}
 	}
-	rx_reor_tbl_ptr->start_win = (rx_reor_tbl_ptr->start_win + i)
-		&(MAX_TID_VALUE - 1);
+	tbl->start_win = (tbl->start_win + i) & (MAX_TID_VALUE - 1);
 	spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
 }
 
@@ -126,28 +123,25 @@
  * pending packets in the Rx reorder table before deletion.
  */
 static void
-mwifiex_11n_delete_rx_reorder_tbl_entry(struct mwifiex_private *priv,
-				       struct mwifiex_rx_reorder_tbl
-				       *rx_reor_tbl_ptr)
+mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
+			     struct mwifiex_rx_reorder_tbl *tbl)
 {
 	unsigned long flags;
 
-	if (!rx_reor_tbl_ptr)
+	if (!tbl)
 		return;
 
-	mwifiex_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr,
-						 (rx_reor_tbl_ptr->start_win +
-						  rx_reor_tbl_ptr->win_size)
-						 &(MAX_TID_VALUE - 1));
+	mwifiex_11n_dispatch_pkt(priv, tbl, (tbl->start_win + tbl->win_size) &
+					    (MAX_TID_VALUE - 1));
 
-	del_timer(&rx_reor_tbl_ptr->timer_context.timer);
+	del_timer(&tbl->timer_context.timer);
 
 	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-	list_del(&rx_reor_tbl_ptr->list);
+	list_del(&tbl->list);
 	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
 
-	kfree(rx_reor_tbl_ptr->rx_reorder_ptr);
-	kfree(rx_reor_tbl_ptr);
+	kfree(tbl->rx_reorder_ptr);
+	kfree(tbl);
 }
 
 /*
@@ -157,16 +151,15 @@
 static struct mwifiex_rx_reorder_tbl *
 mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
 {
-	struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
+	struct mwifiex_rx_reorder_tbl *tbl;
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
-	list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
-		if ((!memcmp(rx_reor_tbl_ptr->ta, ta, ETH_ALEN))
-		    && (rx_reor_tbl_ptr->tid == tid)) {
+	list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) {
+		if (!memcmp(tbl->ta, ta, ETH_ALEN) && tbl->tid == tid) {
 			spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
 					       flags);
-			return rx_reor_tbl_ptr;
+			return tbl;
 		}
 	}
 	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
@@ -200,19 +193,19 @@
 static void
 mwifiex_flush_data(unsigned long context)
 {
-	struct reorder_tmr_cnxt *reorder_cnxt =
+	struct reorder_tmr_cnxt *ctx =
 		(struct reorder_tmr_cnxt *) context;
 	int start_win;
 
-	start_win = mwifiex_11n_find_last_seq_num(reorder_cnxt->ptr);
-	if (start_win >= 0) {
-		dev_dbg(reorder_cnxt->priv->adapter->dev,
-				"info: flush data %d\n", start_win);
-		mwifiex_11n_dispatch_pkt_until_start_win(reorder_cnxt->priv,
-				reorder_cnxt->ptr,
-				((reorder_cnxt->ptr->start_win +
-				  start_win + 1) & (MAX_TID_VALUE - 1)));
-	}
+	start_win = mwifiex_11n_find_last_seq_num(ctx->ptr);
+
+	if (start_win < 0)
+		return;
+
+	dev_dbg(ctx->priv->adapter->dev, "info: flush data %d\n", start_win);
+	mwifiex_11n_dispatch_pkt(ctx->priv, ctx->ptr,
+				 (ctx->ptr->start_win + start_win + 1) &
+				 (MAX_TID_VALUE - 1));
 }
 
 /*
@@ -227,10 +220,10 @@
  */
 static void
 mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
-				 int tid, int win_size, int seq_num)
+				  int tid, int win_size, int seq_num)
 {
 	int i;
-	struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr, *new_node;
+	struct mwifiex_rx_reorder_tbl *tbl, *new_node;
 	u16 last_seq = 0;
 	unsigned long flags;
 
@@ -238,17 +231,16 @@
 	 * If we get a TID, ta pair which is already present dispatch all the
 	 * the packets and move the window size until the ssn
 	 */
-	rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
-	if (rx_reor_tbl_ptr) {
-		mwifiex_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr,
-							 seq_num);
+	tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
+	if (tbl) {
+		mwifiex_11n_dispatch_pkt(priv, tbl, seq_num);
 		return;
 	}
-	/* if !rx_reor_tbl_ptr then create one */
+	/* if !tbl then create one */
 	new_node = kzalloc(sizeof(struct mwifiex_rx_reorder_tbl), GFP_KERNEL);
 	if (!new_node) {
 		dev_err(priv->adapter->dev, "%s: failed to alloc new_node\n",
-		       __func__);
+			__func__);
 		return;
 	}
 
@@ -360,7 +352,8 @@
 	cmd_addba_req->block_ack_param_set = cpu_to_le16(block_ack_param_set);
 
 	mwifiex_11n_create_rx_reorder_tbl(priv, cmd_addba_req->peer_mac_addr,
-			    tid, win_size, le16_to_cpu(cmd_addba_req->ssn));
+					  tid, win_size,
+					  le16_to_cpu(cmd_addba_req->ssn));
 	return 0;
 }
 
@@ -401,35 +394,34 @@
 				u16 seq_num, u16 tid,
 				u8 *ta, u8 pkt_type, void *payload)
 {
-	struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
+	struct mwifiex_rx_reorder_tbl *tbl;
 	int start_win, end_win, win_size;
 	u16 pkt_index;
 
-	rx_reor_tbl_ptr =
-		mwifiex_11n_get_rx_reorder_tbl((struct mwifiex_private *) priv,
-						tid, ta);
-	if (!rx_reor_tbl_ptr) {
+	tbl = mwifiex_11n_get_rx_reorder_tbl((struct mwifiex_private *) priv,
+					     tid, ta);
+	if (!tbl) {
 		if (pkt_type != PKT_TYPE_BAR)
 			mwifiex_process_rx_packet(priv->adapter, payload);
 		return 0;
 	}
-	start_win = rx_reor_tbl_ptr->start_win;
-	win_size = rx_reor_tbl_ptr->win_size;
+	start_win = tbl->start_win;
+	win_size = tbl->win_size;
 	end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
-	del_timer(&rx_reor_tbl_ptr->timer_context.timer);
-	mod_timer(&rx_reor_tbl_ptr->timer_context.timer, jiffies
-			+ (MIN_FLUSH_TIMER_MS * win_size * HZ) / 1000);
+	del_timer(&tbl->timer_context.timer);
+	mod_timer(&tbl->timer_context.timer,
+		  jiffies + (MIN_FLUSH_TIMER_MS * win_size * HZ) / 1000);
 
 	/*
 	 * If seq_num is less then starting win then ignore and drop the
 	 * packet
 	 */
 	if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {/* Wrap */
-		if (seq_num >= ((start_win + (TWOPOW11)) & (MAX_TID_VALUE - 1))
-				&& (seq_num < start_win))
+		if (seq_num >= ((start_win + TWOPOW11) &
+				(MAX_TID_VALUE - 1)) && (seq_num < start_win))
 			return -1;
-	} else if ((seq_num < start_win)
-			|| (seq_num > (start_win + (TWOPOW11)))) {
+	} else if ((seq_num < start_win) ||
+		   (seq_num > (start_win + TWOPOW11))) {
 		return -1;
 	}
 
@@ -440,17 +432,17 @@
 	if (pkt_type == PKT_TYPE_BAR)
 		seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1);
 
-	if (((end_win < start_win)
-	     && (seq_num < (TWOPOW11 - (MAX_TID_VALUE - start_win)))
-	     && (seq_num > end_win)) || ((end_win > start_win)
-	     && ((seq_num > end_win) || (seq_num < start_win)))) {
+	if (((end_win < start_win) &&
+	     (seq_num < (TWOPOW11 - (MAX_TID_VALUE - start_win))) &&
+	     (seq_num > end_win)) ||
+	    ((end_win > start_win) && ((seq_num > end_win) ||
+				       (seq_num < start_win)))) {
 		end_win = seq_num;
 		if (((seq_num - win_size) + 1) >= 0)
 			start_win = (end_win - win_size) + 1;
 		else
 			start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1;
-		mwifiex_11n_dispatch_pkt_until_start_win(priv,
-						rx_reor_tbl_ptr, start_win);
+		mwifiex_11n_dispatch_pkt(priv, tbl, start_win);
 	}
 
 	if (pkt_type != PKT_TYPE_BAR) {
@@ -459,17 +451,17 @@
 		else
 			pkt_index = (seq_num+MAX_TID_VALUE) - start_win;
 
-		if (rx_reor_tbl_ptr->rx_reorder_ptr[pkt_index])
+		if (tbl->rx_reorder_ptr[pkt_index])
 			return -1;
 
-		rx_reor_tbl_ptr->rx_reorder_ptr[pkt_index] = payload;
+		tbl->rx_reorder_ptr[pkt_index] = payload;
 	}
 
 	/*
 	 * Dispatch all packets sequentially from start_win until a
 	 * hole is found and adjust the start_win appropriately
 	 */
-	mwifiex_11n_scan_and_dispatch(priv, rx_reor_tbl_ptr);
+	mwifiex_11n_scan_and_dispatch(priv, tbl);
 
 	return 0;
 }
@@ -480,10 +472,10 @@
  * The TID/TA are taken from del BA event body.
  */
 void
-mwifiex_11n_delete_ba_stream_tbl(struct mwifiex_private *priv, int tid,
-				u8 *peer_mac, u8 type, int initiator)
+mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
+		   u8 type, int initiator)
 {
-	struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
+	struct mwifiex_rx_reorder_tbl *tbl;
 	struct mwifiex_tx_ba_stream_tbl *ptx_tbl;
 	u8 cleanup_rx_reorder_tbl;
 	unsigned long flags;
@@ -493,23 +485,23 @@
 	else
 		cleanup_rx_reorder_tbl = (initiator) ? false : true;
 
-	dev_dbg(priv->adapter->dev, "event: DELBA: %pM tid=%d, "
-	       "initiator=%d\n", peer_mac, tid, initiator);
+	dev_dbg(priv->adapter->dev, "event: DELBA: %pM tid=%d initiator=%d\n",
+		peer_mac, tid, initiator);
 
 	if (cleanup_rx_reorder_tbl) {
-		rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
+		tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
 								 peer_mac);
-		if (!rx_reor_tbl_ptr) {
+		if (!tbl) {
 			dev_dbg(priv->adapter->dev,
-					"event: TID, TA not found in table\n");
+				"event: TID, TA not found in table\n");
 			return;
 		}
-		mwifiex_11n_delete_rx_reorder_tbl_entry(priv, rx_reor_tbl_ptr);
+		mwifiex_del_rx_reorder_entry(priv, tbl);
 	} else {
-		ptx_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, peer_mac);
+		ptx_tbl = mwifiex_get_ba_tbl(priv, tid, peer_mac);
 		if (!ptx_tbl) {
 			dev_dbg(priv->adapter->dev,
-					"event: TID, RA not found in table\n");
+				"event: TID, RA not found in table\n");
 			return;
 		}
 
@@ -532,7 +524,7 @@
 		(struct host_cmd_ds_11n_addba_rsp *)
 		&resp->params.add_ba_rsp;
 	int tid, win_size;
-	struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
+	struct mwifiex_rx_reorder_tbl *tbl;
 	uint16_t block_ack_param_set;
 
 	block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set);
@@ -548,19 +540,18 @@
 			IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
 			>> BLOCKACKPARAM_WINSIZE_POS;
 
-		dev_dbg(priv->adapter->dev, "cmd: ADDBA RSP: %pM"
-		       " tid=%d ssn=%d win_size=%d\n",
-		       add_ba_rsp->peer_mac_addr,
-		       tid, add_ba_rsp->ssn, win_size);
+		dev_dbg(priv->adapter->dev,
+			"cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n",
+			add_ba_rsp->peer_mac_addr, tid,
+			add_ba_rsp->ssn, win_size);
 	} else {
 		dev_err(priv->adapter->dev, "ADDBA RSP: failed %pM tid=%d)\n",
-					add_ba_rsp->peer_mac_addr, tid);
+			add_ba_rsp->peer_mac_addr, tid);
 
-		rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv,
-					tid, add_ba_rsp->peer_mac_addr);
-		if (rx_reor_tbl_ptr)
-			mwifiex_11n_delete_rx_reorder_tbl_entry(priv,
-				rx_reor_tbl_ptr);
+		tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
+						     add_ba_rsp->peer_mac_addr);
+		if (tbl)
+			mwifiex_del_rx_reorder_entry(priv, tbl);
 	}
 
 	return 0;
@@ -599,7 +590,7 @@
 	list_for_each_entry_safe(del_tbl_ptr, tmp_node,
 				 &priv->rx_reorder_tbl_ptr, list) {
 		spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
-		mwifiex_11n_delete_rx_reorder_tbl_entry(priv, del_tbl_ptr);
+		mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr);
 		spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
 	}
 	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index 033c8ad..f1bffeb 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -41,9 +41,8 @@
 			       u16 seqNum,
 			       u16 tid, u8 *ta,
 			       u8 pkttype, void *payload);
-void mwifiex_11n_delete_ba_stream_tbl(struct mwifiex_private *priv, int Tid,
-				     u8 *PeerMACAddr, u8 type,
-				     int initiator);
+void mwifiex_del_ba_tbl(struct mwifiex_private *priv, int Tid,
+			u8 *PeerMACAddr, u8 type, int initiator);
 void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,
 				   struct host_cmd_ds_11n_batimeout *event);
 int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index a460fb0..6505038 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -127,8 +127,7 @@
 
 	if (timeout)
 		wiphy_dbg(wiphy,
-			"info: ignoring the timeout value"
-			" for IEEE power save\n");
+			  "info: ignore timeout value for IEEE Power Save\n");
 
 	ps_mode = enabled;
 
@@ -168,7 +167,7 @@
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
 
 	if (mwifiex_set_encode(priv, params->key, params->key_len,
-							key_index, 0)) {
+			       key_index, 0)) {
 		wiphy_err(wiphy, "crypto keys added\n");
 		return -EFAULT;
 	}
@@ -225,7 +224,7 @@
 		}
 
 		if (ch->hw_value == next_chan + 1 &&
-				ch->max_power == max_pwr) {
+		    ch->max_power == max_pwr) {
 			next_chan++;
 			no_of_parsed_chan++;
 		} else {
@@ -252,7 +251,7 @@
 	domain_info->no_of_triplet = no_of_triplet;
 
 	if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
-				     HostCmd_ACT_GEN_SET, 0, NULL)) {
+				   HostCmd_ACT_GEN_SET, 0, NULL)) {
 		wiphy_err(wiphy, "11D: setting domain info in FW\n");
 		return -1;
 	}
@@ -271,7 +270,7 @@
  *      - Set bt Country IE
  */
 static int mwifiex_reg_notifier(struct wiphy *wiphy,
-		struct regulatory_request *request)
+				struct regulatory_request *request)
 {
 	struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
 
@@ -316,7 +315,7 @@
 		if (chan->band == IEEE80211_BAND_2GHZ) {
 			if (channel_type == NL80211_CHAN_NO_HT)
 				if (priv->adapter->config_bands == BAND_B ||
-					  priv->adapter->config_bands == BAND_G)
+				    priv->adapter->config_bands == BAND_G)
 					config_bands =
 						priv->adapter->config_bands;
 				else
@@ -336,7 +335,7 @@
 			if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
 				adapter->adhoc_start_band = config_bands;
 				if ((config_bands & BAND_GN) ||
-						(config_bands & BAND_AN))
+				    (config_bands & BAND_AN))
 					adapter->adhoc_11n_enabled = true;
 				else
 					adapter->adhoc_11n_enabled = false;
@@ -350,9 +349,8 @@
 		mwifiex_send_domain_info_cmd_fw(wiphy);
 	}
 
-	wiphy_dbg(wiphy, "info: setting band %d, channel offset %d and "
-		"mode %d\n", config_bands, adapter->sec_chan_offset,
-		priv->bss_mode);
+	wiphy_dbg(wiphy, "info: setting band %d, chan offset %d, mode %d\n",
+		  config_bands, adapter->sec_chan_offset, priv->bss_mode);
 	if (!chan)
 		return 0;
 
@@ -403,8 +401,8 @@
 {
 	int ret;
 
-	if (frag_thr < MWIFIEX_FRAG_MIN_VALUE
-	    || frag_thr > MWIFIEX_FRAG_MAX_VALUE)
+	if (frag_thr < MWIFIEX_FRAG_MIN_VALUE ||
+	    frag_thr > MWIFIEX_FRAG_MAX_VALUE)
 		return -EINVAL;
 
 	/* Send request to firmware */
@@ -613,7 +611,6 @@
 	{.bitrate = 20, .hw_value = 4, },
 	{.bitrate = 55, .hw_value = 11, },
 	{.bitrate = 110, .hw_value = 22, },
-	{.bitrate = 220, .hw_value = 44, },
 	{.bitrate = 60, .hw_value = 12, },
 	{.bitrate = 90, .hw_value = 18, },
 	{.bitrate = 120, .hw_value = 24, },
@@ -622,7 +619,6 @@
 	{.bitrate = 360, .hw_value = 72, },
 	{.bitrate = 480, .hw_value = 96, },
 	{.bitrate = 540, .hw_value = 108, },
-	{.bitrate = 720, .hw_value = 144, },
 };
 
 /* Channel definitions to be advertised to cfg80211 */
@@ -648,7 +644,7 @@
 	.channels = mwifiex_channels_2ghz,
 	.n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),
 	.bitrates = mwifiex_rates,
-	.n_bitrates = 14,
+	.n_bitrates = ARRAY_SIZE(mwifiex_rates),
 };
 
 static struct ieee80211_channel mwifiex_channels_5ghz[] = {
@@ -688,8 +684,8 @@
 static struct ieee80211_supported_band mwifiex_band_5ghz = {
 	.channels = mwifiex_channels_5ghz,
 	.n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),
-	.bitrates = mwifiex_rates - 4,
-	.n_bitrates = ARRAY_SIZE(mwifiex_rates) + 4,
+	.bitrates = mwifiex_rates + 4,
+	.n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,
 };
 
 
@@ -748,8 +744,7 @@
 	adapter->channel_type = NL80211_CHAN_NO_HT;
 
 	wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n",
-				(mode & BAND_B) ? "b" : "",
-				(mode & BAND_G) ? "g" : "");
+		    (mode & BAND_B) ? "b" : "", (mode & BAND_G) ? "g" : "");
 
 	return 0;
 }
@@ -804,8 +799,7 @@
 	ie_buf[1] = bss_info.ssid.ssid_len;
 
 	memcpy(&ie_buf[sizeof(struct ieee_types_header)],
-			&bss_info.ssid.ssid,
-			bss_info.ssid.ssid_len);
+	       &bss_info.ssid.ssid, bss_info.ssid.ssid_len);
 	ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
 
 	band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
@@ -814,8 +808,8 @@
 						       band));
 
 	bss = cfg80211_inform_bss(priv->wdev->wiphy, chan,
-		bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
-		0, ie_buf, ie_len, 0, GFP_KERNEL);
+				  bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
+				  0, ie_buf, ie_len, 0, GFP_KERNEL);
 	cfg80211_put_bss(bss);
 	memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN);
 
@@ -841,12 +835,12 @@
 		       u8 *bssid, int mode, struct ieee80211_channel *channel,
 		       struct cfg80211_connect_params *sme, bool privacy)
 {
-	struct mwifiex_802_11_ssid req_ssid;
+	struct cfg80211_ssid req_ssid;
 	int ret, auth_type = 0;
 	struct cfg80211_bss *bss = NULL;
 	u8 is_scanning_required = 0;
 
-	memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid));
+	memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
 
 	req_ssid.ssid_len = ssid_len;
 	if (ssid_len > IEEE80211_MAX_SSID_LEN) {
@@ -873,6 +867,7 @@
 	priv->sec_info.wpa2_enabled = false;
 	priv->wep_key_curr_index = 0;
 	priv->sec_info.encryption_mode = 0;
+	priv->sec_info.is_authtype_auto = 0;
 	ret = mwifiex_set_encode(priv, NULL, 0, 0, 1);
 
 	if (mode == NL80211_IFTYPE_ADHOC) {
@@ -894,11 +889,12 @@
 	}
 
 	/* Now handle infra mode. "sme" is valid for infra mode only */
-	if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC
-			|| sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
+	if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
 		auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
-	else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY)
-		auth_type = NL80211_AUTHTYPE_SHARED_KEY;
+		priv->sec_info.is_authtype_auto = 1;
+	} else {
+		auth_type = sme->auth_type;
+	}
 
 	if (sme->crypto.n_ciphers_pairwise) {
 		priv->sec_info.encryption_mode =
@@ -952,14 +948,15 @@
 
 		if (!bss) {
 			if (is_scanning_required) {
-				dev_warn(priv->adapter->dev, "assoc: requested "
-					 "bss not found in scan results\n");
+				dev_warn(priv->adapter->dev,
+					 "assoc: requested bss not found in scan results\n");
 				break;
 			}
 			is_scanning_required = 1;
 		} else {
-			dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n",
-					(char *) req_ssid.ssid, bss->bssid);
+			dev_dbg(priv->adapter->dev,
+				"info: trying to associate to '%s' bssid %pM\n",
+				(char *) req_ssid.ssid, bss->bssid);
 			memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
 			break;
 		}
@@ -999,7 +996,7 @@
 	}
 
 	wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
-	       (char *) sme->ssid, sme->bssid);
+		  (char *) sme->ssid, sme->bssid);
 
 	ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
 				     priv->bss_mode, sme->channel, sme, 0);
@@ -1041,11 +1038,11 @@
 	}
 
 	wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n",
-	       (char *) params->ssid, params->bssid);
+		  (char *) params->ssid, params->bssid);
 
 	ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
-				params->bssid, priv->bss_mode,
-				params->channel, NULL, params->privacy);
+				     params->bssid, priv->bss_mode,
+				     params->channel, NULL, params->privacy);
 done:
 	if (!ret) {
 		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
@@ -1072,7 +1069,7 @@
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
 	wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n",
-			priv->cfg_bssid);
+		  priv->cfg_bssid);
 	if (mwifiex_deauthenticate(priv, NULL))
 		return -EFAULT;
 
@@ -1101,17 +1098,15 @@
 	priv->scan_request = request;
 
 	priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
-					GFP_KERNEL);
+				      GFP_KERNEL);
 	if (!priv->user_scan_cfg) {
 		dev_err(priv->adapter->dev, "failed to alloc scan_req\n");
 		return -ENOMEM;
 	}
-	for (i = 0; i < request->n_ssids; i++) {
-		memcpy(priv->user_scan_cfg->ssid_list[i].ssid,
-			request->ssids[i].ssid, request->ssids[i].ssid_len);
-		priv->user_scan_cfg->ssid_list[i].max_len =
-			request->ssids[i].ssid_len;
-	}
+
+	priv->user_scan_cfg->num_ssids = request->n_ssids;
+	priv->user_scan_cfg->ssid_list = request->ssids;
+
 	for (i = 0; i < request->n_channels; i++) {
 		chan = request->channels[i];
 		priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
@@ -1119,10 +1114,10 @@
 
 		if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 			priv->user_scan_cfg->chan_list[i].scan_type =
-				MWIFIEX_SCAN_TYPE_PASSIVE;
+						MWIFIEX_SCAN_TYPE_PASSIVE;
 		else
 			priv->user_scan_cfg->chan_list[i].scan_type =
-				MWIFIEX_SCAN_TYPE_ACTIVE;
+						MWIFIEX_SCAN_TYPE_ACTIVE;
 
 		priv->user_scan_cfg->chan_list[i].scan_time = 0;
 	}
@@ -1193,9 +1188,9 @@
 	memset(mcs, 0xff, rx_mcs_supp);
 	/* Clear all the other values */
 	memset(&mcs[rx_mcs_supp], 0,
-			sizeof(struct ieee80211_mcs_info) - rx_mcs_supp);
+	       sizeof(struct ieee80211_mcs_info) - rx_mcs_supp);
 	if (priv->bss_mode == NL80211_IFTYPE_STATION ||
-			ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
+	    ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
 		/* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
 		SETHT_MCS32(mcs_set.rx_mask);
 
@@ -1208,10 +1203,10 @@
  *  create a new virtual interface with the given name
  */
 struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
-						char *name,
-						enum nl80211_iftype type,
-						u32 *flags,
-						struct vif_params *params)
+					    char *name,
+					    enum nl80211_iftype type,
+					    u32 *flags,
+					    struct vif_params *params)
 {
 	struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
 	struct mwifiex_adapter *adapter;
@@ -1369,11 +1364,12 @@
 	int ret;
 	void *wdev_priv;
 	struct wireless_dev *wdev;
+	struct ieee80211_sta_ht_cap *ht_info;
 
 	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
 	if (!wdev) {
 		dev_err(priv->adapter->dev, "%s: allocating wireless device\n",
-						__func__);
+			__func__);
 		return -ENOMEM;
 	}
 	wdev->wiphy =
@@ -1385,17 +1381,17 @@
 	}
 	wdev->iftype = NL80211_IFTYPE_STATION;
 	wdev->wiphy->max_scan_ssids = 10;
-	wdev->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
+	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				       BIT(NL80211_IFTYPE_ADHOC);
 
 	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
-	mwifiex_setup_ht_caps(
-		&wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);
+	ht_info = &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap;
+	mwifiex_setup_ht_caps(ht_info, priv);
 
 	if (priv->adapter->config_bands & BAND_A) {
 		wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
-		mwifiex_setup_ht_caps(
-			&wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
+		ht_info = &wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap;
+		mwifiex_setup_ht_caps(ht_info, priv);
 	} else {
 		wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
 	}
@@ -1422,13 +1418,13 @@
 	ret = wiphy_register(wdev->wiphy);
 	if (ret < 0) {
 		dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n",
-						__func__);
+			__func__);
 		wiphy_free(wdev->wiphy);
 		kfree(wdev);
 		return ret;
 	} else {
 		dev_dbg(priv->adapter->dev,
-				"info: successfully registered wiphy device\n");
+			"info: successfully registered wiphy device\n");
 	}
 
 	priv->wdev = wdev;
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c
index 1782a77..2fe1c33 100644
--- a/drivers/net/wireless/mwifiex/cfp.c
+++ b/drivers/net/wireless/mwifiex/cfp.c
@@ -163,92 +163,66 @@
 		return mwifiex_get_supported_rates(priv, rates);
 	else
 		return mwifiex_copy_rates(rates, 0,
-				       priv->curr_bss_params.data_rates,
-				       priv->curr_bss_params.num_of_rates);
+					  priv->curr_bss_params.data_rates,
+					  priv->curr_bss_params.num_of_rates);
 }
 
 /*
  * This function locates the Channel-Frequency-Power triplet based upon
- * band and channel parameters.
+ * band and channel/frequency parameters.
  */
 struct mwifiex_chan_freq_power *
-mwifiex_get_cfp_by_band_and_channel_from_cfg80211(struct mwifiex_private
-						  *priv, u8 band, u16 channel)
+mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq)
 {
 	struct mwifiex_chan_freq_power *cfp = NULL;
 	struct ieee80211_supported_band *sband;
-	struct ieee80211_channel *ch;
+	struct ieee80211_channel *ch = NULL;
 	int i;
 
+	if (!channel && !freq)
+		return cfp;
+
 	if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG)
 		sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ];
 	else
 		sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ];
 
 	if (!sband) {
-		dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d"
-				" & channel %d\n", __func__, band, channel);
+		dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d\n",
+			__func__, band);
 		return cfp;
 	}
 
 	for (i = 0; i < sband->n_channels; i++) {
 		ch = &sband->channels[i];
-		if (((ch->hw_value == channel) ||
-			(channel == FIRST_VALID_CHANNEL))
-			&& !(ch->flags & IEEE80211_CHAN_DISABLED)) {
-			priv->cfp.channel = channel;
-			priv->cfp.freq = ch->center_freq;
-			priv->cfp.max_tx_power = ch->max_power;
-			cfp = &priv->cfp;
-			break;
+
+		if (ch->flags & IEEE80211_CHAN_DISABLED)
+			continue;
+
+		if (freq) {
+			if (ch->center_freq == freq)
+				break;
+		} else {
+			/* find by valid channel*/
+			if (ch->hw_value == channel ||
+			    channel == FIRST_VALID_CHANNEL)
+				break;
 		}
 	}
-	if (i == sband->n_channels)
+	if (i == sband->n_channels) {
 		dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d"
-				" & channel %d\n", __func__, band, channel);
+			" & channel=%d freq=%d\n", __func__, band, channel,
+			freq);
+	} else {
+		if (!ch)
+			return cfp;
 
-	return cfp;
-}
-
-/*
- * This function locates the Channel-Frequency-Power triplet based upon
- * band and frequency parameters.
- */
-struct mwifiex_chan_freq_power *
-mwifiex_get_cfp_by_band_and_freq_from_cfg80211(struct mwifiex_private *priv,
-					       u8 band, u32 freq)
-{
-	struct mwifiex_chan_freq_power *cfp = NULL;
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_channel *ch;
-	int i;
-
-	if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG)
-		sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ];
-	else
-		sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ];
-
-	if (!sband) {
-		dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d"
-				" & freq %d\n", __func__, band, freq);
-		return cfp;
+		priv->cfp.channel = ch->hw_value;
+		priv->cfp.freq = ch->center_freq;
+		priv->cfp.max_tx_power = ch->max_power;
+		cfp = &priv->cfp;
 	}
 
-	for (i = 0; i < sband->n_channels; i++) {
-		ch = &sband->channels[i];
-		if ((ch->center_freq == freq) &&
-			!(ch->flags & IEEE80211_CHAN_DISABLED)) {
-			priv->cfp.channel = ch->hw_value;
-			priv->cfp.freq = freq;
-			priv->cfp.max_tx_power = ch->max_power;
-			cfp = &priv->cfp;
-			break;
-		}
-	}
-	if (i == sband->n_channels)
-		dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d"
-				" & freq %d\n", __func__, band, freq);
-
 	return cfp;
 }
 
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 6623db6..07f6e00 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -67,7 +67,7 @@
 		return NULL;
 	}
 	cmd_node = list_first_entry(&adapter->cmd_free_q,
-			struct cmd_ctrl_node, list);
+				    struct cmd_ctrl_node, list);
 	list_del(&cmd_node->list);
 	spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
 
@@ -158,8 +158,9 @@
 	/* Set command sequence number */
 	adapter->seq_num++;
 	host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
-			    (adapter->seq_num, cmd_node->priv->bss_num,
-			     cmd_node->priv->bss_type));
+					(adapter->seq_num,
+					 cmd_node->priv->bss_num,
+					 cmd_node->priv->bss_type));
 
 	spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
 	adapter->curr_cmd = cmd_node;
@@ -174,8 +175,8 @@
 	dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d,"
 		" seqno %#x\n",
 		tstamp.tv_sec, tstamp.tv_usec, cmd_code,
-	       le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size,
-	       le16_to_cpu(host_cmd->seq_num));
+		le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size,
+		le16_to_cpu(host_cmd->seq_num));
 
 	skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN);
 
@@ -200,17 +201,17 @@
 
 	/* Save the last command id and action to debug log */
 	adapter->dbg.last_cmd_index =
-		(adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM;
+			(adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM;
 	adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] = cmd_code;
 	adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] =
-		le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN));
+			le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN));
 
 	/* Clear BSS_NO_BITS from HostCmd */
 	cmd_code &= HostCmd_CMD_ID_MASK;
 
 	/* Setup the timer after transmit command */
 	mod_timer(&adapter->cmd_timer,
-		jiffies + (MWIFIEX_TIMER_10S * HZ) / 1000);
+		  jiffies + (MWIFIEX_TIMER_10S * HZ) / 1000);
 
 	return 0;
 }
@@ -230,7 +231,7 @@
 	struct mwifiex_private *priv;
 	struct mwifiex_opt_sleep_confirm *sleep_cfm_buf =
 				(struct mwifiex_opt_sleep_confirm *)
-				adapter->sleep_cfm->data;
+						adapter->sleep_cfm->data;
 	priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 
 	sleep_cfm_buf->seq_num =
@@ -250,7 +251,7 @@
 		return -1;
 	}
 	if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY))
-			== MWIFIEX_BSS_ROLE_STA) {
+	    == MWIFIEX_BSS_ROLE_STA) {
 		if (!sleep_cfm_buf->resp_ctrl)
 			/* Response is not needed for sleep
 			   confirm command */
@@ -258,12 +259,12 @@
 		else
 			adapter->ps_state = PS_STATE_SLEEP_CFM;
 
-		if (!sleep_cfm_buf->resp_ctrl
-				&& (adapter->is_hs_configured
-					&& !adapter->sleep_period.period)) {
+		if (!sleep_cfm_buf->resp_ctrl &&
+		    (adapter->is_hs_configured &&
+		     !adapter->sleep_period.period)) {
 			adapter->pm_wakeup_card_req = true;
-			mwifiex_hs_activated_event(mwifiex_get_priv(adapter,
-						MWIFIEX_BSS_ROLE_STA), true);
+			mwifiex_hs_activated_event(mwifiex_get_priv
+					(adapter, MWIFIEX_BSS_ROLE_STA), true);
 		}
 	}
 
@@ -293,7 +294,7 @@
 	cmd_array = kzalloc(buf_size, GFP_KERNEL);
 	if (!cmd_array) {
 		dev_err(adapter->dev, "%s: failed to alloc cmd_array\n",
-				__func__);
+			__func__);
 		return -ENOMEM;
 	}
 
@@ -376,9 +377,9 @@
 
 	/* Save the last event to debug log */
 	adapter->dbg.last_event_index =
-		(adapter->dbg.last_event_index + 1) % DBG_CMD_NUM;
+			(adapter->dbg.last_event_index + 1) % DBG_CMD_NUM;
 	adapter->dbg.last_event[adapter->dbg.last_event_index] =
-		(u16) eventcause;
+							(u16) eventcause;
 
 	/* Get BSS number and corresponding priv */
 	priv = mwifiex_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause),
@@ -398,7 +399,7 @@
 	if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE) {
 		do_gettimeofday(&tstamp);
 		dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n",
-		       tstamp.tv_sec, tstamp.tv_usec, eventcause);
+			tstamp.tv_sec, tstamp.tv_usec, eventcause);
 	}
 
 	ret = mwifiex_process_sta_event(priv);
@@ -509,7 +510,7 @@
 	/* Return error, since the command preparation failed */
 	if (ret) {
 		dev_err(adapter->dev, "PREP_CMD: cmd %#x preparation failed\n",
-							cmd_no);
+			cmd_no);
 		mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
 		return -1;
 	}
@@ -577,9 +578,9 @@
 	/* Exit_PS command needs to be queued in the header always. */
 	if (command == HostCmd_CMD_802_11_PS_MODE_ENH) {
 		struct host_cmd_ds_802_11_ps_mode_enh *pm =
-			&host_cmd->params.psmode_enh;
-		if ((le16_to_cpu(pm->action) == DIS_PS)
-		    || (le16_to_cpu(pm->action) == DIS_AUTO_PS)) {
+						&host_cmd->params.psmode_enh;
+		if ((le16_to_cpu(pm->action) == DIS_PS) ||
+		    (le16_to_cpu(pm->action) == DIS_AUTO_PS)) {
 			if (adapter->ps_state != PS_STATE_AWAKE)
 				add_tail = false;
 		}
@@ -692,7 +693,7 @@
 	if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) {
 		resp = (struct host_cmd_ds_command *) adapter->upld_buf;
 		dev_err(adapter->dev, "CMD_RESP: NULL curr_cmd, %#x\n",
-		       le16_to_cpu(resp->command));
+			le16_to_cpu(resp->command));
 		return -1;
 	}
 
@@ -701,7 +702,7 @@
 	resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data;
 	if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) {
 		dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n",
-				le16_to_cpu(resp->command));
+			le16_to_cpu(resp->command));
 		mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
 		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
 		adapter->curr_cmd = NULL;
@@ -725,8 +726,8 @@
 
 	/* Get BSS number and corresponding priv */
 	priv = mwifiex_get_priv_by_id(adapter,
-			HostCmd_GET_BSS_NO(le16_to_cpu(resp->seq_num)),
-			HostCmd_GET_BSS_TYPE(le16_to_cpu(resp->seq_num)));
+			     HostCmd_GET_BSS_NO(le16_to_cpu(resp->seq_num)),
+			     HostCmd_GET_BSS_TYPE(le16_to_cpu(resp->seq_num)));
 	if (!priv)
 		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 	/* Clear RET_BIT from HostCmd */
@@ -737,9 +738,9 @@
 
 	/* Save the last command response to debug log */
 	adapter->dbg.last_cmd_resp_index =
-		(adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM;
+			(adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM;
 	adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] =
-		orig_cmdresp_no;
+								orig_cmdresp_no;
 
 	do_gettimeofday(&tstamp);
 	dev_dbg(adapter->dev, "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d,"
@@ -761,8 +762,8 @@
 
 	if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
 		adapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD;
-		if ((cmdresp_result == HostCmd_RESULT_OK)
-		    && (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH))
+		if ((cmdresp_result == HostCmd_RESULT_OK) &&
+		    (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH))
 			ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
 	} else {
 		/* handle response */
@@ -771,7 +772,7 @@
 
 	/* Check init command response */
 	if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
-		if (ret == -1) {
+		if (ret) {
 			dev_err(adapter->dev, "%s: cmd %#x failed during "
 				"initialization\n", __func__, cmdresp_no);
 			mwifiex_init_fw_complete(adapter);
@@ -781,10 +782,8 @@
 	}
 
 	if (adapter->curr_cmd) {
-		if (adapter->curr_cmd->wait_q_enabled && (!ret))
-			adapter->cmd_wait_q.status = 0;
-		else if (adapter->curr_cmd->wait_q_enabled && (ret == -1))
-			adapter->cmd_wait_q.status = -1;
+		if (adapter->curr_cmd->wait_q_enabled)
+			adapter->cmd_wait_q.status = ret;
 
 		/* Clean up and put current command back to cmd_free_q */
 		mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
@@ -826,44 +825,45 @@
 		adapter->dbg.timeout_cmd_act =
 			adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index];
 		do_gettimeofday(&tstamp);
-		dev_err(adapter->dev, "%s: Timeout cmd id (%lu.%lu) = %#x,"
-			" act = %#x\n", __func__,
-		       tstamp.tv_sec, tstamp.tv_usec,
-		       adapter->dbg.timeout_cmd_id,
-		       adapter->dbg.timeout_cmd_act);
+		dev_err(adapter->dev,
+			"%s: Timeout cmd id (%lu.%lu) = %#x, act = %#x\n",
+			__func__, tstamp.tv_sec, tstamp.tv_usec,
+			adapter->dbg.timeout_cmd_id,
+			adapter->dbg.timeout_cmd_act);
 
 		dev_err(adapter->dev, "num_data_h2c_failure = %d\n",
-		       adapter->dbg.num_tx_host_to_card_failure);
+			adapter->dbg.num_tx_host_to_card_failure);
 		dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n",
-		       adapter->dbg.num_cmd_host_to_card_failure);
+			adapter->dbg.num_cmd_host_to_card_failure);
 
 		dev_err(adapter->dev, "num_cmd_timeout = %d\n",
-		       adapter->dbg.num_cmd_timeout);
+			adapter->dbg.num_cmd_timeout);
 		dev_err(adapter->dev, "num_tx_timeout = %d\n",
-		       adapter->dbg.num_tx_timeout);
+			adapter->dbg.num_tx_timeout);
 
 		dev_err(adapter->dev, "last_cmd_index = %d\n",
-		       adapter->dbg.last_cmd_index);
+			adapter->dbg.last_cmd_index);
 		print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET,
-				adapter->dbg.last_cmd_id, DBG_CMD_NUM);
+				     adapter->dbg.last_cmd_id, DBG_CMD_NUM);
 		print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET,
-				adapter->dbg.last_cmd_act, DBG_CMD_NUM);
+				     adapter->dbg.last_cmd_act, DBG_CMD_NUM);
 
 		dev_err(adapter->dev, "last_cmd_resp_index = %d\n",
-		       adapter->dbg.last_cmd_resp_index);
+			adapter->dbg.last_cmd_resp_index);
 		print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET,
-				adapter->dbg.last_cmd_resp_id, DBG_CMD_NUM);
+				     adapter->dbg.last_cmd_resp_id,
+				     DBG_CMD_NUM);
 
 		dev_err(adapter->dev, "last_event_index = %d\n",
-		       adapter->dbg.last_event_index);
+			adapter->dbg.last_event_index);
 		print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET,
-				adapter->dbg.last_event, DBG_CMD_NUM);
+				     adapter->dbg.last_event, DBG_CMD_NUM);
 
 		dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n",
-		       adapter->data_sent, adapter->cmd_sent);
+			adapter->data_sent, adapter->cmd_sent);
 
 		dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n",
-				adapter->ps_mode, adapter->ps_state);
+			adapter->ps_mode, adapter->ps_state);
 	}
 	if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
 		mwifiex_init_fw_complete(adapter);
@@ -944,7 +944,7 @@
 	uint16_t cancel_scan_cmd = false;
 
 	if ((adapter->curr_cmd) &&
-	     (adapter->curr_cmd->wait_q_enabled)) {
+	    (adapter->curr_cmd->wait_q_enabled)) {
 		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
 		cmd_node = adapter->curr_cmd;
 		cmd_node->wait_q_enabled = false;
@@ -998,9 +998,9 @@
 	else
 		dev_dbg(adapter->dev,
 			"cmd: Delay Sleep Confirm (%s%s%s)\n",
-		       (adapter->cmd_sent) ? "D" : "",
-		       (adapter->curr_cmd) ? "C" : "",
-		       (IS_CARD_RX_RCVD(adapter)) ? "R" : "");
+			(adapter->cmd_sent) ? "D" : "",
+			(adapter->curr_cmd) ? "C" : "",
+			(IS_CARD_RX_RCVD(adapter)) ? "R" : "");
 }
 
 /*
@@ -1052,8 +1052,8 @@
 		dev_dbg(adapter->dev, "cmd: CMD_RESP: HS_CFG cmd reply"
 			" result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n",
 			resp->result, conditions,
-		       phs_cfg->params.hs_config.gpio,
-		       phs_cfg->params.hs_config.gap);
+			phs_cfg->params.hs_config.gpio,
+			phs_cfg->params.hs_config.gap);
 	}
 	if (conditions != HOST_SLEEP_CFG_CANCEL) {
 		adapter->is_hs_configured = true;
@@ -1080,7 +1080,8 @@
 	adapter->hs_activated = false;
 	adapter->is_hs_configured = false;
 	mwifiex_hs_activated_event(mwifiex_get_priv(adapter,
-				   MWIFIEX_BSS_ROLE_ANY), false);
+						    MWIFIEX_BSS_ROLE_ANY),
+				   false);
 }
 
 /*
@@ -1116,22 +1117,24 @@
 	command &= HostCmd_CMD_ID_MASK;
 
 	if (command != HostCmd_CMD_802_11_PS_MODE_ENH) {
-		dev_err(adapter->dev, "%s: received unexpected response for"
-			" cmd %x, result = %x\n", __func__, command, result);
+		dev_err(adapter->dev,
+			"%s: rcvd unexpected resp for cmd %#x, result = %x\n",
+			__func__, command, result);
 		return;
 	}
 
 	if (result) {
 		dev_err(adapter->dev, "%s: sleep confirm cmd failed\n",
-						__func__);
+			__func__);
 		adapter->pm_wakeup_card_req = false;
 		adapter->ps_state = PS_STATE_AWAKE;
 		return;
 	}
 	adapter->pm_wakeup_card_req = true;
 	if (adapter->is_hs_configured)
-		mwifiex_hs_activated_event(mwifiex_get_priv(adapter,
-					   MWIFIEX_BSS_ROLE_ANY), true);
+		mwifiex_hs_activated_event(mwifiex_get_priv
+						(adapter, MWIFIEX_BSS_ROLE_ANY),
+					   true);
 	adapter->ps_state = PS_STATE_SLEEP;
 	cmd->command = cpu_to_le16(command);
 	cmd->seq_num = cpu_to_le16(seq_num);
@@ -1165,17 +1168,17 @@
 		psmode_enh->action = cpu_to_le16(DIS_AUTO_PS);
 		psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
 		cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
-				sizeof(psmode_enh->params.ps_bitmap));
+					sizeof(psmode_enh->params.ps_bitmap));
 	} else if (cmd_action == GET_PS) {
 		psmode_enh->action = cpu_to_le16(GET_PS);
 		psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
 		cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
-				sizeof(psmode_enh->params.ps_bitmap));
+					sizeof(psmode_enh->params.ps_bitmap));
 	} else if (cmd_action == EN_AUTO_PS) {
 		psmode_enh->action = cpu_to_le16(EN_AUTO_PS);
 		psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
 		cmd_size = S_DS_GEN + sizeof(psmode_enh->action) +
-				sizeof(psmode_enh->params.ps_bitmap);
+					sizeof(psmode_enh->params.ps_bitmap);
 		tlv = (u8 *) cmd + cmd_size;
 		if (ps_bitmap & BITMAP_STA_PS) {
 			struct mwifiex_adapter *adapter = priv->adapter;
@@ -1189,19 +1192,18 @@
 			tlv += sizeof(*ps_tlv);
 			dev_dbg(adapter->dev, "cmd: PS Command: Enter PS\n");
 			ps_mode->null_pkt_interval =
-				cpu_to_le16(adapter->null_pkt_interval);
+					cpu_to_le16(adapter->null_pkt_interval);
 			ps_mode->multiple_dtims =
-				cpu_to_le16(adapter->multiple_dtim);
+					cpu_to_le16(adapter->multiple_dtim);
 			ps_mode->bcn_miss_timeout =
-				cpu_to_le16(adapter->bcn_miss_time_out);
+					cpu_to_le16(adapter->bcn_miss_time_out);
 			ps_mode->local_listen_interval =
 				cpu_to_le16(adapter->local_listen_interval);
 			ps_mode->adhoc_wake_period =
 				cpu_to_le16(adapter->adhoc_awake_period);
 			ps_mode->delay_to_ps =
-				cpu_to_le16(adapter->delay_to_ps);
-			ps_mode->mode =
-				cpu_to_le16(adapter->enhanced_ps_mode);
+					cpu_to_le16(adapter->delay_to_ps);
+			ps_mode->mode = cpu_to_le16(adapter->enhanced_ps_mode);
 
 		}
 		if (ps_bitmap & BITMAP_AUTO_DS) {
@@ -1219,7 +1221,7 @@
 			if (auto_ds)
 				idletime = auto_ds->idle_time;
 			dev_dbg(priv->adapter->dev,
-					"cmd: PS Command: Enter Auto Deep Sleep\n");
+				"cmd: PS Command: Enter Auto Deep Sleep\n");
 			auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
 		}
 		cmd->size = cpu_to_le16(cmd_size);
@@ -1246,8 +1248,9 @@
 	uint16_t auto_ps_bitmap =
 		le16_to_cpu(ps_mode->params.ps_bitmap);
 
-	dev_dbg(adapter->dev, "info: %s: PS_MODE cmd reply result=%#x action=%#X\n",
-					__func__, resp->result, action);
+	dev_dbg(adapter->dev,
+		"info: %s: PS_MODE cmd reply result=%#x action=%#X\n",
+		__func__, resp->result, action);
 	if (action == EN_AUTO_PS) {
 		if (auto_ps_bitmap & BITMAP_AUTO_DS) {
 			dev_dbg(adapter->dev, "cmd: Enabled auto deep sleep\n");
@@ -1256,7 +1259,8 @@
 		if (auto_ps_bitmap & BITMAP_STA_PS) {
 			dev_dbg(adapter->dev, "cmd: Enabled STA power save\n");
 			if (adapter->sleep_period.period)
-				dev_dbg(adapter->dev, "cmd: set to uapsd/pps mode\n");
+				dev_dbg(adapter->dev,
+					"cmd: set to uapsd/pps mode\n");
 		}
 	} else if (action == DIS_AUTO_PS) {
 		if (ps_bitmap & BITMAP_AUTO_DS) {
@@ -1375,12 +1379,13 @@
 	adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna);
 
 	dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n",
-	       adapter->fw_release_number);
+		adapter->fw_release_number);
 	dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n",
-					hw_spec->permanent_addr);
-	dev_dbg(adapter->dev, "info: GET_HW_SPEC: hw_if_version=%#x  version=%#x\n",
+		hw_spec->permanent_addr);
+	dev_dbg(adapter->dev,
+		"info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n",
 		le16_to_cpu(hw_spec->hw_if_version),
-	       le16_to_cpu(hw_spec->version));
+		le16_to_cpu(hw_spec->version));
 
 	if (priv->curr_addr[0] == 0xff)
 		memmove(priv->curr_addr, hw_spec->permanent_addr, ETH_ALEN);
@@ -1395,7 +1400,8 @@
 	/* If it's unidentified region code, use the default (USA) */
 	if (i >= MWIFIEX_MAX_REGION_CODE) {
 		adapter->region_code = 0x10;
-		dev_dbg(adapter->dev, "cmd: unknown region code, use default (USA)\n");
+		dev_dbg(adapter->dev,
+			"cmd: unknown region code, use default (USA)\n");
 	}
 
 	adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap);
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 3735c77..be5fd16 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -91,11 +91,6 @@
 	u32 fw_len;
 };
 
-struct mwifiex_802_11_ssid {
-	u32 ssid_len;
-	u8 ssid[IEEE80211_MAX_SSID_LEN];
-};
-
 struct mwifiex_wait_queue {
 	wait_queue_head_t wait;
 	int status;
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index c826200..e98fc5a 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -117,8 +117,8 @@
 #define BA_STREAM_NOT_ALLOWED   0xff
 
 #define IS_11N_ENABLED(priv) ((priv->adapter->config_bands & BAND_GN || \
-			priv->adapter->config_bands & BAND_AN) \
-			&& priv->curr_bss_params.bss_descriptor.bcn_ht_cap)
+			priv->adapter->config_bands & BAND_AN) && \
+			priv->curr_bss_params.bss_descriptor.bcn_ht_cap)
 #define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) &\
 			BIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS)
 
@@ -852,11 +852,6 @@
 	u32 scan_time;
 } __packed;
 
-struct mwifiex_user_scan_ssid {
-	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
-	u8 max_len;
-} __packed;
-
 struct mwifiex_user_scan_cfg {
 	/*
 	 *  BSS mode to be sent in the firmware command
@@ -867,8 +862,9 @@
 	u8 reserved;
 	/* BSSID filter sent in the firmware command to limit the results */
 	u8 specific_bssid[ETH_ALEN];
-	/* SSID filter list used in the to limit the scan results */
-	struct mwifiex_user_scan_ssid ssid_list[MWIFIEX_MAX_SSID_LIST_LENGTH];
+	/* SSID filter list used in the firmware to limit the scan results */
+	struct cfg80211_ssid *ssid_list;
+	u8 num_ssids;
 	/* Variable number (fixed maximum) of channels to scan up */
 	struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX];
 } __packed;
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index e81bf6e..54bb483 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -35,28 +35,24 @@
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
 	struct mwifiex_bss_prio_node *bss_prio;
+	struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
 	unsigned long flags;
 
 	bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL);
 	if (!bss_prio) {
 		dev_err(adapter->dev, "%s: failed to alloc bss_prio\n",
-						__func__);
+			__func__);
 		return -ENOMEM;
 	}
 
 	bss_prio->priv = priv;
 	INIT_LIST_HEAD(&bss_prio->list);
-	if (!adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur)
-		adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur =
-			bss_prio;
+	if (!tbl[priv->bss_priority].bss_prio_cur)
+		tbl[priv->bss_priority].bss_prio_cur = bss_prio;
 
-	spin_lock_irqsave(&adapter->bss_prio_tbl[priv->bss_priority]
-			.bss_prio_lock, flags);
-	list_add_tail(&bss_prio->list,
-			&adapter->bss_prio_tbl[priv->bss_priority]
-			.bss_prio_head);
-	spin_unlock_irqrestore(&adapter->bss_prio_tbl[priv->bss_priority]
-			.bss_prio_lock, flags);
+	spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
+	list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head);
+	spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
 
 	return 0;
 }
@@ -157,13 +153,13 @@
 	ret = mwifiex_alloc_cmd_buffer(adapter);
 	if (ret) {
 		dev_err(adapter->dev, "%s: failed to alloc cmd buffer\n",
-		       __func__);
+			__func__);
 		return -1;
 	}
 
 	adapter->sleep_cfm =
 		dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
-				+ INTF_HEADER_LEN);
+			      + INTF_HEADER_LEN);
 
 	if (!adapter->sleep_cfm) {
 		dev_err(adapter->dev, "%s: failed to alloc sleep cfm"
@@ -520,7 +516,7 @@
 	struct mwifiex_adapter *adapter = priv->adapter;
 	struct mwifiex_bss_prio_node *bssprio_node, *tmp_node, **cur;
 	struct list_head *head;
-	spinlock_t *lock;
+	spinlock_t *lock; /* bss priority lock */
 	unsigned long flags;
 
 	for (i = 0; i < adapter->priv_num; ++i) {
@@ -638,7 +634,7 @@
 	ret = adapter->if_ops.check_fw_status(adapter, poll_num);
 	if (!ret) {
 		dev_notice(adapter->dev,
-				"WLAN FW already running! Skip FW download\n");
+			   "WLAN FW already running! Skip FW download\n");
 		goto done;
 	}
 	poll_num = MAX_FIRMWARE_POLL_TRIES;
@@ -646,8 +642,7 @@
 	/* Check if we are the winner for downloading FW */
 	if (!adapter->winner) {
 		dev_notice(adapter->dev,
-				"Other interface already running!"
-				" Skip FW download\n");
+			   "Other intf already running! Skip FW download\n");
 		poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
 		goto poll_fw;
 	}
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index d5d81f1..7ca4e82 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -50,7 +50,7 @@
 };
 
 struct mwifiex_ssid_bssid {
-	struct mwifiex_802_11_ssid ssid;
+	struct cfg80211_ssid ssid;
 	u8 bssid[ETH_ALEN];
 };
 
@@ -122,7 +122,7 @@
 
 struct mwifiex_bss_info {
 	u32 bss_mode;
-	struct mwifiex_802_11_ssid ssid;
+	struct cfg80211_ssid ssid;
 	u32 bss_chan;
 	u32 region_code;
 	u32 media_connected;
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index ee439fc..8f9382b 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -52,8 +52,9 @@
 	 *   parameter buffer pointer.
 	 */
 	if (priv->gen_ie_buf_len) {
-		dev_dbg(priv->adapter->dev, "info: %s: append generic %d to %p\n",
-				__func__, priv->gen_ie_buf_len, *buffer);
+		dev_dbg(priv->adapter->dev,
+			"info: %s: append generic ie len %d to %p\n",
+			__func__, priv->gen_ie_buf_len, *buffer);
 
 		/* Wrap the generic IE buffer with a pass through TLV type */
 		ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH);
@@ -123,8 +124,9 @@
 
 	memcpy(&tsf_val, bss_desc->time_stamp, sizeof(tsf_val));
 
-	dev_dbg(priv->adapter->dev, "info: %s: TSF offset calc: %016llx - "
-			"%016llx\n", __func__, tsf_val, bss_desc->network_tsf);
+	dev_dbg(priv->adapter->dev,
+		"info: %s: TSF offset calc: %016llx - %016llx\n",
+		__func__, tsf_val, bss_desc->network_tsf);
 
 	memcpy(*buffer, &tsf_val, sizeof(tsf_val));
 	*buffer += sizeof(tsf_val);
@@ -167,7 +169,7 @@
 	}
 
 	dev_dbg(priv->adapter->dev, "info: Tx data rate set to %#x\n",
-						priv->data_rate);
+		priv->data_rate);
 
 	if (!priv->is_data_rate_auto) {
 		while (*ptr) {
@@ -212,7 +214,7 @@
 				     card_rates, card_rates_size)) {
 		*out_rates_size = 0;
 		dev_err(priv->adapter->dev, "%s: cannot get common rates\n",
-						__func__);
+			__func__);
 		return -1;
 	}
 
@@ -248,7 +250,7 @@
 	 */
 	if (priv->wapi_ie_len) {
 		dev_dbg(priv->adapter->dev, "cmd: append wapi ie %d to %p\n",
-				priv->wapi_ie_len, *buffer);
+			priv->wapi_ie_len, *buffer);
 
 		/* Wrap the generic IE buffer with a pass through TLV type */
 		ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE);
@@ -293,10 +295,10 @@
 				 le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF);
 	rsn_ie_tlv->header.len = cpu_to_le16((u16) priv->wpa_ie[1]);
 	rsn_ie_tlv->header.len = cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len)
-							& 0x00FF);
+							 & 0x00FF);
 	if (le16_to_cpu(rsn_ie_tlv->header.len) <= (sizeof(priv->wpa_ie) - 2))
 		memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2],
-					le16_to_cpu(rsn_ie_tlv->header.len));
+		       le16_to_cpu(rsn_ie_tlv->header.len));
 	else
 		return -1;
 
@@ -379,7 +381,7 @@
 	ssid_tlv->header.type = cpu_to_le16(WLAN_EID_SSID);
 	ssid_tlv->header.len = cpu_to_le16((u16) bss_desc->ssid.ssid_len);
 	memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid,
-		le16_to_cpu(ssid_tlv->header.len));
+	       le16_to_cpu(ssid_tlv->header.len));
 	pos += sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len);
 
 	phy_tlv = (struct mwifiex_ie_types_phy_param_set *) pos;
@@ -411,7 +413,7 @@
 	memcpy(rates_tlv->rates, rates, rates_size);
 	pos += sizeof(rates_tlv->header) + rates_size;
 	dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: rates size = %d\n",
-					rates_size);
+		rates_size);
 
 	/* Add the Authentication type to be used for Auth frames */
 	auth_tlv = (struct mwifiex_ie_types_auth_type *) pos;
@@ -425,12 +427,12 @@
 
 	pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len);
 
-	if (IS_SUPPORT_MULTI_BANDS(priv->adapter)
-	    && !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info)
-		&& (!bss_desc->disable_11n)
-		 && (priv->adapter->config_bands & BAND_GN
-		     || priv->adapter->config_bands & BAND_AN)
-		 && (bss_desc->bcn_ht_cap)
+	if (IS_SUPPORT_MULTI_BANDS(priv->adapter) &&
+	    !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
+	    (!bss_desc->disable_11n) &&
+	    (priv->adapter->config_bands & BAND_GN ||
+	     priv->adapter->config_bands & BAND_AN) &&
+	    (bss_desc->bcn_ht_cap)
 	    )
 		) {
 		/* Append a channel TLV for the channel the attempted AP was
@@ -445,13 +447,13 @@
 		chan_tlv->chan_scan_param[0].chan_number =
 			(bss_desc->phy_param_set.ds_param_set.current_chan);
 		dev_dbg(priv->adapter->dev, "info: Assoc: TLV Chan = %d\n",
-		       chan_tlv->chan_scan_param[0].chan_number);
+			chan_tlv->chan_scan_param[0].chan_number);
 
 		chan_tlv->chan_scan_param[0].radio_type =
 			mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
 
 		dev_dbg(priv->adapter->dev, "info: Assoc: TLV Band = %d\n",
-		       chan_tlv->chan_scan_param[0].radio_type);
+			chan_tlv->chan_scan_param[0].radio_type);
 		pos += sizeof(chan_tlv->header) +
 			sizeof(struct mwifiex_chan_scan_param_set);
 	}
@@ -464,10 +466,10 @@
 			return -1;
 	}
 
-	if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info)
-		&& (!bss_desc->disable_11n)
-	    && (priv->adapter->config_bands & BAND_GN
-		|| priv->adapter->config_bands & BAND_AN))
+	if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
+	    (!bss_desc->disable_11n) &&
+	    (priv->adapter->config_bands & BAND_GN ||
+	     priv->adapter->config_bands & BAND_AN))
 		mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos);
 
 	/* Append vendor specific IE TLV */
@@ -493,7 +495,7 @@
 
 	tmp_cap &= CAPINFO_MASK;
 	dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
-	       tmp_cap, CAPINFO_MASK);
+		tmp_cap, CAPINFO_MASK);
 	assoc->cap_info_bitmap = cpu_to_le16(tmp_cap);
 
 	return 0;
@@ -573,19 +575,19 @@
 	assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params;
 
 	priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN,
-				     sizeof(priv->assoc_rsp_buf));
+				   sizeof(priv->assoc_rsp_buf));
 
 	memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size);
 
 	if (le16_to_cpu(assoc_rsp->status_code)) {
 		priv->adapter->dbg.num_cmd_assoc_failure++;
-		dev_err(priv->adapter->dev, "ASSOC_RESP: association failed, "
-		       "status code = %d, error = 0x%x, a_id = 0x%x\n",
-		       le16_to_cpu(assoc_rsp->status_code),
-		       le16_to_cpu(assoc_rsp->cap_info_bitmap),
-		       le16_to_cpu(assoc_rsp->a_id));
+		dev_err(priv->adapter->dev,
+			"ASSOC_RESP: failed, status code=%d err=%#x a_id=%#x\n",
+			le16_to_cpu(assoc_rsp->status_code),
+			le16_to_cpu(assoc_rsp->cap_info_bitmap),
+			le16_to_cpu(assoc_rsp->a_id));
 
-		ret = -1;
+		ret = le16_to_cpu(assoc_rsp->status_code);
 		goto done;
 	}
 
@@ -600,7 +602,7 @@
 	bss_desc = priv->attempted_bss_desc;
 
 	dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: %s\n",
-						bss_desc->ssid.ssid);
+		bss_desc->ssid.ssid);
 
 	/* Make a copy of current BSSID descriptor */
 	memcpy(&priv->curr_bss_params.bss_descriptor,
@@ -617,8 +619,8 @@
 	else
 		priv->curr_bss_params.wmm_enabled = false;
 
-	if ((priv->wmm_required || bss_desc->bcn_ht_cap)
-			&& priv->curr_bss_params.wmm_enabled)
+	if ((priv->wmm_required || bss_desc->bcn_ht_cap) &&
+	    priv->curr_bss_params.wmm_enabled)
 		priv->wmm_enabled = true;
 	else
 		priv->wmm_enabled = false;
@@ -631,7 +633,7 @@
 				IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0);
 
 	dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: curr_pkt_filter is %#x\n",
-	       priv->curr_pkt_filter);
+		priv->curr_pkt_filter);
 	if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
 		priv->wpa_is_gtk_set = false;
 
@@ -714,7 +716,7 @@
 int
 mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
 				struct host_cmd_ds_command *cmd,
-				struct mwifiex_802_11_ssid *req_ssid)
+				struct cfg80211_ssid *req_ssid)
 {
 	int rsn_ie_len = 0;
 	struct mwifiex_adapter *adapter = priv->adapter;
@@ -755,7 +757,7 @@
 	memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
 
 	dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n",
-				adhoc_start->ssid);
+		adhoc_start->ssid);
 
 	memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN);
 	memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len);
@@ -777,12 +779,11 @@
 	adhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID;
 	adhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN;
 
-	if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211
-			(priv, adapter->adhoc_start_band, (u16)
-				priv->adhoc_channel)) {
+	if (!mwifiex_get_cfp(priv, adapter->adhoc_start_band,
+			     (u16) priv->adhoc_channel, 0)) {
 		struct mwifiex_chan_freq_power *cfp;
-		cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
-				adapter->adhoc_start_band, FIRST_VALID_CHANNEL);
+		cfp = mwifiex_get_cfp(priv, adapter->adhoc_start_band,
+				      FIRST_VALID_CHANNEL, 0);
 		if (cfp)
 			priv->adhoc_channel = (u8) cfp->channel;
 	}
@@ -793,7 +794,7 @@
 	}
 
 	dev_dbg(adapter->dev, "info: ADHOC_S_CMD: creating ADHOC on channel %d\n",
-				priv->adhoc_channel);
+		priv->adhoc_channel);
 
 	priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel;
 	priv->curr_bss_params.band = adapter->adhoc_start_band;
@@ -814,7 +815,7 @@
 	adhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID;
 	adhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN;
 	adhoc_start->ss_param_set.ibss_param_set.atim_window
-		= cpu_to_le16(priv->atim_window);
+					= cpu_to_le16(priv->atim_window);
 	memcpy(&bss_desc->ss_param_set, &adhoc_start->ss_param_set,
 	       sizeof(union ieee_types_ss_param_set));
 
@@ -842,10 +843,10 @@
 	if ((adapter->adhoc_start_band & BAND_G) &&
 	    (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) {
 		if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL,
-					     HostCmd_ACT_GEN_SET, 0,
-					     &priv->curr_pkt_filter)) {
+					   HostCmd_ACT_GEN_SET, 0,
+					   &priv->curr_pkt_filter)) {
 			dev_err(adapter->dev,
-			       "ADHOC_S_CMD: G Protection config failed\n");
+				"ADHOC_S_CMD: G Protection config failed\n");
 			return -1;
 		}
 	}
@@ -861,8 +862,8 @@
 	       &adhoc_start->data_rate, priv->curr_bss_params.num_of_rates);
 
 	dev_dbg(adapter->dev, "info: ADHOC_S_CMD: rates=%02x %02x %02x %02x\n",
-	       adhoc_start->data_rate[0], adhoc_start->data_rate[1],
-	       adhoc_start->data_rate[2], adhoc_start->data_rate[3]);
+		adhoc_start->data_rate[0], adhoc_start->data_rate[1],
+		adhoc_start->data_rate[2], adhoc_start->data_rate[3]);
 
 	dev_dbg(adapter->dev, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n");
 
@@ -879,12 +880,12 @@
 			(u8) priv->curr_bss_params.bss_descriptor.channel;
 
 		dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Chan = %d\n",
-		       chan_tlv->chan_scan_param[0].chan_number);
+			chan_tlv->chan_scan_param[0].chan_number);
 
 		chan_tlv->chan_scan_param[0].radio_type
 		       = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
-		if (adapter->adhoc_start_band & BAND_GN
-		    || adapter->adhoc_start_band & BAND_AN) {
+		if (adapter->adhoc_start_band & BAND_GN ||
+		    adapter->adhoc_start_band & BAND_AN) {
 			if (adapter->sec_chan_offset ==
 					    IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
 				chan_tlv->chan_scan_param[0].radio_type |=
@@ -895,7 +896,7 @@
 					(IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4);
 		}
 		dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Band = %d\n",
-		       chan_tlv->chan_scan_param[0].radio_type);
+			chan_tlv->chan_scan_param[0].radio_type);
 		pos += sizeof(chan_tlv->header) +
 			sizeof(struct mwifiex_chan_scan_param_set);
 		cmd_append_size +=
@@ -926,15 +927,14 @@
 		mwifiex_fill_cap_info(priv, radio_type, ht_cap);
 
 		pos += sizeof(struct mwifiex_ie_types_htcap);
-		cmd_append_size +=
-			sizeof(struct mwifiex_ie_types_htcap);
+		cmd_append_size += sizeof(struct mwifiex_ie_types_htcap);
 
 		/* Fill HT INFORMATION */
 		ht_info = (struct mwifiex_ie_types_htinfo *) pos;
 		memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo));
 		ht_info->header.type = cpu_to_le16(WLAN_EID_HT_INFORMATION);
 		ht_info->header.len =
-			cpu_to_le16(sizeof(struct ieee80211_ht_info));
+				cpu_to_le16(sizeof(struct ieee80211_ht_info));
 
 		ht_info->ht_info.control_chan =
 			(u8) priv->curr_bss_params.bss_descriptor.channel;
@@ -948,12 +948,12 @@
 		ht_info->ht_info.basic_set[0] = 0xff;
 		pos += sizeof(struct mwifiex_ie_types_htinfo);
 		cmd_append_size +=
-			sizeof(struct mwifiex_ie_types_htinfo);
+				sizeof(struct mwifiex_ie_types_htinfo);
 	}
 
-	cmd->size = cpu_to_le16((u16)
-			    (sizeof(struct host_cmd_ds_802_11_ad_hoc_start)
-			     + S_DS_GEN + cmd_append_size));
+	cmd->size =
+		cpu_to_le16((u16)(sizeof(struct host_cmd_ds_802_11_ad_hoc_start)
+				  + S_DS_GEN + cmd_append_size));
 
 	if (adapter->adhoc_start_band == BAND_B)
 		tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
@@ -1006,10 +1006,10 @@
 			curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON;
 
 		if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL,
-					     HostCmd_ACT_GEN_SET, 0,
-					     &curr_pkt_filter)) {
+					   HostCmd_ACT_GEN_SET, 0,
+					   &curr_pkt_filter)) {
 			dev_err(priv->adapter->dev,
-			       "ADHOC_J_CMD: G Protection config failed\n");
+				"ADHOC_J_CMD: G Protection config failed\n");
 			return -1;
 		}
 	}
@@ -1040,13 +1040,14 @@
 
 	tmp_cap &= CAPINFO_MASK;
 
-	dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: tmp_cap=%4X"
-			" CAPINFO_MASK=%4lX\n", tmp_cap, CAPINFO_MASK);
+	dev_dbg(priv->adapter->dev,
+		"info: ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
+		tmp_cap, CAPINFO_MASK);
 
 	/* Information on BSSID descriptor passed to FW */
-	dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: BSSID = %pM, SSID = %s\n",
-				adhoc_join->bss_descriptor.bssid,
-				adhoc_join->bss_descriptor.ssid);
+	dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: BSSID=%pM, SSID='%s'\n",
+		adhoc_join->bss_descriptor.bssid,
+		adhoc_join->bss_descriptor.ssid);
 
 	for (i = 0; bss_desc->supported_rates[i] &&
 			i < MWIFIEX_SUPPORTED_RATES;
@@ -1083,18 +1084,18 @@
 		       sizeof(struct mwifiex_chan_scan_param_set));
 		chan_tlv->chan_scan_param[0].chan_number =
 			(bss_desc->phy_param_set.ds_param_set.current_chan);
-		dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Chan = %d\n",
-		       chan_tlv->chan_scan_param[0].chan_number);
+		dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Chan=%d\n",
+			chan_tlv->chan_scan_param[0].chan_number);
 
 		chan_tlv->chan_scan_param[0].radio_type =
 			mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
 
-		dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Band = %d\n",
-		       chan_tlv->chan_scan_param[0].radio_type);
+		dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Band=%d\n",
+			chan_tlv->chan_scan_param[0].radio_type);
 		pos += sizeof(chan_tlv->header) +
-			sizeof(struct mwifiex_chan_scan_param_set);
+				sizeof(struct mwifiex_chan_scan_param_set);
 		cmd_append_size += sizeof(chan_tlv->header) +
-			sizeof(struct mwifiex_chan_scan_param_set);
+				sizeof(struct mwifiex_chan_scan_param_set);
 	}
 
 	if (priv->sec_info.wpa_enabled)
@@ -1111,9 +1112,9 @@
 	cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv,
 			MWIFIEX_VSIE_MASK_ADHOC, &pos);
 
-	cmd->size = cpu_to_le16((u16)
-			    (sizeof(struct host_cmd_ds_802_11_ad_hoc_join)
-			     + S_DS_GEN + cmd_append_size));
+	cmd->size = cpu_to_le16
+		((u16) (sizeof(struct host_cmd_ds_802_11_ad_hoc_join)
+			+ S_DS_GEN + cmd_append_size));
 
 	adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap);
 
@@ -1158,7 +1159,7 @@
 
 	if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) {
 		dev_dbg(priv->adapter->dev, "info: ADHOC_S_RESP %s\n",
-				bss_desc->ssid.ssid);
+			bss_desc->ssid.ssid);
 
 		/* Update the created network descriptor with the new BSSID */
 		memcpy(bss_desc->mac_address,
@@ -1171,7 +1172,7 @@
 		 * If BSSID has changed use SSID to compare instead of BSSID
 		 */
 		dev_dbg(priv->adapter->dev, "info: ADHOC_J_RESP %s\n",
-				bss_desc->ssid.ssid);
+			bss_desc->ssid.ssid);
 
 		/*
 		 * Make a copy of current BSSID descriptor, only needed for
@@ -1185,9 +1186,9 @@
 	}
 
 	dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: channel = %d\n",
-				priv->adhoc_channel);
+		priv->adhoc_channel);
 	dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: BSSID = %pM\n",
-	       priv->curr_bss_params.bss_descriptor.mac_address);
+		priv->curr_bss_params.bss_descriptor.mac_address);
 
 	if (!netif_carrier_ok(priv->netdev))
 		netif_carrier_on(priv->netdev);
@@ -1245,14 +1246,14 @@
  */
 int
 mwifiex_adhoc_start(struct mwifiex_private *priv,
-		    struct mwifiex_802_11_ssid *adhoc_ssid)
+		    struct cfg80211_ssid *adhoc_ssid)
 {
 	dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n",
 		priv->adhoc_channel);
 	dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n",
-	       priv->curr_bss_params.bss_descriptor.channel);
+		priv->curr_bss_params.bss_descriptor.channel);
 	dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n",
-	       priv->curr_bss_params.band);
+		priv->curr_bss_params.band);
 
 	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START,
 				    HostCmd_ACT_GEN_SET, 0, adhoc_ssid);
@@ -1268,13 +1269,13 @@
 		       struct mwifiex_bssdescriptor *bss_desc)
 {
 	dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid =%s\n",
-	       priv->curr_bss_params.bss_descriptor.ssid.ssid);
+		priv->curr_bss_params.bss_descriptor.ssid.ssid);
 	dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid_len =%u\n",
-	       priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
+		priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
 	dev_dbg(priv->adapter->dev, "info: adhoc join: ssid =%s\n",
 		bss_desc->ssid.ssid);
 	dev_dbg(priv->adapter->dev, "info: adhoc join: ssid_len =%u\n",
-	       bss_desc->ssid.ssid_len);
+		bss_desc->ssid.ssid_len);
 
 	/* Check if the requested SSID is already joined */
 	if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len &&
@@ -1288,9 +1289,9 @@
 	}
 
 	dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n",
-	       priv->curr_bss_params.bss_descriptor.channel);
+		priv->curr_bss_params.bss_descriptor.channel);
 	dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n",
-	       priv->curr_bss_params.band);
+		priv->curr_bss_params.band);
 
 	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_JOIN,
 				    HostCmd_ACT_GEN_SET, 0, bss_desc);
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 790a379..9d1b3ca 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -64,11 +64,10 @@
 	adapter->priv_num = 0;
 
 	/* Allocate memory for private structure */
-	adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private),
-			GFP_KERNEL);
+	adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL);
 	if (!adapter->priv[0]) {
-		dev_err(adapter->dev, "%s: failed to alloc priv[0]\n",
-		       __func__);
+		dev_err(adapter->dev,
+			"%s: failed to alloc priv[0]\n", __func__);
 		goto error;
 	}
 
@@ -169,8 +168,8 @@
 		if ((adapter->ps_state == PS_STATE_SLEEP) &&
 		    (adapter->pm_wakeup_card_req &&
 		     !adapter->pm_wakeup_fw_try) &&
-		    (is_command_pending(adapter)
-		     || !mwifiex_wmm_lists_empty(adapter))) {
+		    (is_command_pending(adapter) ||
+		     !mwifiex_wmm_lists_empty(adapter))) {
 			adapter->pm_wakeup_fw_try = true;
 			adapter->if_ops.wakeup(adapter);
 			continue;
@@ -187,10 +186,10 @@
 			    adapter->tx_lock_flag)
 				break;
 
-			if (adapter->scan_processing || adapter->data_sent
-			    || mwifiex_wmm_lists_empty(adapter)) {
-				if (adapter->cmd_sent || adapter->curr_cmd
-				    || (!is_command_pending(adapter)))
+			if (adapter->scan_processing || adapter->data_sent ||
+			    mwifiex_wmm_lists_empty(adapter)) {
+				if (adapter->cmd_sent || adapter->curr_cmd ||
+				    (!is_command_pending(adapter)))
 					break;
 			}
 		}
@@ -223,10 +222,10 @@
 		/* * The ps_state may have been changed during processing of
 		 * Sleep Request event.
 		 */
-		if ((adapter->ps_state == PS_STATE_SLEEP)
-		    || (adapter->ps_state == PS_STATE_PRE_SLEEP)
-		    || (adapter->ps_state == PS_STATE_SLEEP_CFM)
-		    || adapter->tx_lock_flag)
+		if ((adapter->ps_state == PS_STATE_SLEEP) ||
+		    (adapter->ps_state == PS_STATE_PRE_SLEEP) ||
+		    (adapter->ps_state == PS_STATE_SLEEP_CFM) ||
+		    adapter->tx_lock_flag)
 			continue;
 
 		if (!adapter->cmd_sent && !adapter->curr_cmd) {
@@ -249,8 +248,8 @@
 		}
 
 		if (adapter->delay_null_pkt && !adapter->cmd_sent &&
-		    !adapter->curr_cmd && !is_command_pending(adapter)
-		    && mwifiex_wmm_lists_empty(adapter)) {
+		    !adapter->curr_cmd && !is_command_pending(adapter) &&
+		    mwifiex_wmm_lists_empty(adapter)) {
 			if (!mwifiex_send_null_packet
 			    (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
 			     MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
@@ -371,7 +370,7 @@
 		iph = ip_hdr(skb);
 		tid = IPTOS_PREC(iph->tos);
 		pr_debug("data: packet type ETH_P_IP: %04x, tid=%#x prio=%#x\n",
-		       eth->h_proto, tid, skb->priority);
+			 eth->h_proto, tid, skb->priority);
 		break;
 	case __constant_htons(ETH_P_ARP):
 		pr_debug("data: ARP packet: %04x\n", eth->h_proto);
@@ -425,7 +424,7 @@
 	struct mwifiex_txinfo *tx_info;
 
 	dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
-				jiffies, priv->bss_type, priv->bss_num);
+		jiffies, priv->bss_type, priv->bss_num);
 
 	if (priv->adapter->surprise_removed) {
 		kfree_skb(skb);
@@ -441,7 +440,7 @@
 	if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
 		dev_dbg(priv->adapter->dev,
 			"data: Tx: insufficient skb headroom %d\n",
-		       skb_headroom(skb));
+			skb_headroom(skb));
 		/* Insufficient skb headroom - allocate a new skb */
 		new_skb =
 			skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
@@ -454,7 +453,7 @@
 		kfree_skb(skb);
 		skb = new_skb;
 		dev_dbg(priv->adapter->dev, "info: new skb headroomd %d\n",
-				skb_headroom(skb));
+			skb_headroom(skb));
 	}
 
 	tx_info = MWIFIEX_SKB_TXCB(skb);
@@ -494,8 +493,8 @@
 	if (!ret)
 		memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN);
 	else
-		dev_err(priv->adapter->dev, "set mac address failed: ret=%d"
-					    "\n", ret);
+		dev_err(priv->adapter->dev,
+			"set mac address failed: ret=%d\n", ret);
 
 	memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
 
@@ -533,7 +532,7 @@
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
 	dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_type-num = %d-%d\n",
-				jiffies, priv->bss_type, priv->bss_num);
+		jiffies, priv->bss_type, priv->bss_num);
 	mwifiex_set_trans_start(dev);
 	priv->num_tx_timeout++;
 }
@@ -704,7 +703,7 @@
 	rtnl_lock();
 	/* Create station interface by default */
 	if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d",
-				NL80211_IFTYPE_STATION, NULL, NULL)) {
+				      NL80211_IFTYPE_STATION, NULL, NULL)) {
 		rtnl_unlock();
 		dev_err(adapter->dev, "cannot create default station"
 				" interface\n");
@@ -781,7 +780,7 @@
 		if (priv && priv->netdev) {
 			if (!netif_queue_stopped(priv->netdev))
 				mwifiex_stop_net_dev_queue(priv->netdev,
-								adapter);
+							   adapter);
 			if (netif_carrier_ok(priv->netdev))
 				netif_carrier_off(priv->netdev);
 		}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 4c86217..35225e9 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -219,6 +219,7 @@
 	u8 wapi_key_on;
 	u8 wep_enabled;
 	u32 authentication_mode;
+	u8 is_authtype_auto;
 	u32 encryption_mode;
 };
 
@@ -243,7 +244,7 @@
 
 struct mwifiex_bssdescriptor {
 	u8 mac_address[ETH_ALEN];
-	struct mwifiex_802_11_ssid ssid;
+	struct cfg80211_ssid ssid;
 	u32 privacy;
 	s32 rssi;
 	u32 channel;
@@ -387,7 +388,7 @@
 	s16 bcn_rssi_avg;
 	s16 bcn_nf_avg;
 	struct mwifiex_bssdescriptor *attempted_bss_desc;
-	struct mwifiex_802_11_ssid prev_ssid;
+	struct cfg80211_ssid prev_ssid;
 	u8 prev_bssid[ETH_ALEN];
 	struct mwifiex_current_bss_params curr_bss_params;
 	u16 beacon_period;
@@ -461,9 +462,9 @@
 };
 
 enum mwifiex_ba_status {
-	BA_STREAM_NOT_SETUP = 0,
-	BA_STREAM_SETUP_INPROGRESS,
-	BA_STREAM_SETUP_COMPLETE
+	BA_SETUP_NONE = 0,
+	BA_SETUP_INPROGRESS,
+	BA_SETUP_COMPLETE
 };
 
 struct mwifiex_tx_ba_stream_tbl {
@@ -746,8 +747,7 @@
 			    struct cmd_ctrl_node *cmd_node);
 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
 			    struct host_cmd_ds_command *resp);
-s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
-		       struct mwifiex_802_11_ssid *ssid2);
+s32 mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2);
 int mwifiex_associate(struct mwifiex_private *priv,
 		      struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
@@ -759,25 +759,20 @@
 u8 mwifiex_band_to_radio_type(u8 band);
 int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
 int mwifiex_adhoc_start(struct mwifiex_private *priv,
-			struct mwifiex_802_11_ssid *adhoc_ssid);
+			struct cfg80211_ssid *adhoc_ssid);
 int mwifiex_adhoc_join(struct mwifiex_private *priv,
 		       struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
 				    struct host_cmd_ds_command *cmd,
-				    struct mwifiex_802_11_ssid *req_ssid);
+				    struct cfg80211_ssid *req_ssid);
 int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
 				   struct host_cmd_ds_command *cmd,
 				   struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
 			      struct host_cmd_ds_command *resp);
 int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);
-struct mwifiex_chan_freq_power *
-			mwifiex_get_cfp_by_band_and_channel_from_cfg80211(
-						struct mwifiex_private *priv,
-						u8 band, u16 channel);
-struct mwifiex_chan_freq_power *mwifiex_get_cfp_by_band_and_freq_from_cfg80211(
-						struct mwifiex_private *priv,
-						u8 band, u32 freq);
+struct mwifiex_chan_freq_power *mwifiex_get_cfp(struct mwifiex_private *priv,
+						u8 band, u16 channel, u32 freq);
 u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index,
 							u8 ht_info);
 u32 mwifiex_find_freq_from_band_chan(u8, u8);
@@ -846,8 +841,8 @@
 
 	for (i = 0; i < adapter->priv_num; i++) {
 		if (adapter->priv[i]) {
-			if ((adapter->priv[i]->bss_num == bss_num)
-			    && (adapter->priv[i]->bss_type == bss_type))
+			if ((adapter->priv[i]->bss_num == bss_num) &&
+			    (adapter->priv[i]->bss_type == bss_type))
 				break;
 		}
 	}
@@ -897,7 +892,7 @@
 			    struct net_device *dev);
 int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
 int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
-		      struct mwifiex_802_11_ssid *req_ssid);
+		      struct cfg80211_ssid *req_ssid);
 int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
 int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
 int mwifiex_disable_auto_ds(struct mwifiex_private *priv);
@@ -906,13 +901,12 @@
 int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
 			      struct mwifiex_rate_cfg *rate);
 int mwifiex_request_scan(struct mwifiex_private *priv,
-			 struct mwifiex_802_11_ssid *req_ssid);
+			 struct cfg80211_ssid *req_ssid);
 int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
 				struct mwifiex_user_scan_cfg *scan_req);
-int mwifiex_change_adhoc_chan(struct mwifiex_private *priv, int channel);
 int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
 
-int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel);
+int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel);
 
 int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
 		       int key_len, u8 key_index, int disable);
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 4053509..e1f45ec 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -83,7 +83,7 @@
 	struct pcie_service_card *card;
 
 	pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
-				pdev->vendor, pdev->device, pdev->revision);
+		 pdev->vendor, pdev->device, pdev->revision);
 
 	card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL);
 	if (!card) {
@@ -110,6 +110,7 @@
 {
 	struct pcie_service_card *card;
 	struct mwifiex_adapter *adapter;
+	struct mwifiex_private *priv;
 	int i;
 
 	card = pci_get_drvdata(pdev);
@@ -128,16 +129,15 @@
 
 		for (i = 0; i < adapter->priv_num; i++)
 			if ((GET_BSS_ROLE(adapter->priv[i]) ==
-						MWIFIEX_BSS_ROLE_STA) &&
-					adapter->priv[i]->media_connected)
+			     MWIFIEX_BSS_ROLE_STA) &&
+			    adapter->priv[i]->media_connected)
 				mwifiex_deauthenticate(adapter->priv[i], NULL);
 
-		mwifiex_disable_auto_ds(mwifiex_get_priv(adapter,
-						 MWIFIEX_BSS_ROLE_ANY));
+		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 
-		mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
-						MWIFIEX_BSS_ROLE_ANY),
-					 MWIFIEX_FUNC_SHUTDOWN);
+		mwifiex_disable_auto_ds(priv);
+
+		mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
 	}
 
 	mwifiex_remove_card(card->adapter, &add_remove_card_sem);
@@ -221,7 +221,7 @@
 			netif_carrier_on(adapter->priv[i]->netdev);
 
 	mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
-			      MWIFIEX_ASYNC_CMD);
+			  MWIFIEX_ASYNC_CMD);
 
 	return 0;
 }
@@ -288,7 +288,7 @@
 
 	while (mwifiex_pcie_ok_to_access_hw(adapter)) {
 		i++;
-		udelay(10);
+		usleep_range(10, 20);
 		/* 50ms max wait */
 		if (i == 50000)
 			break;
@@ -380,26 +380,26 @@
 	/* allocate shared memory for the BD ring and divide the same in to
 	   several descriptors */
 	card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
-				MWIFIEX_MAX_TXRX_BD;
+							MWIFIEX_MAX_TXRX_BD;
 	dev_dbg(adapter->dev, "info: txbd_ring: Allocating %d bytes\n",
-				card->txbd_ring_size);
+		card->txbd_ring_size);
 	card->txbd_ring_vbase = kzalloc(card->txbd_ring_size, GFP_KERNEL);
 	if (!card->txbd_ring_vbase) {
-		dev_err(adapter->dev, "Unable to allocate buffer for txbd ring.\n");
+		dev_err(adapter->dev, "Unable to alloc buffer for txbd ring\n");
 		return -ENOMEM;
 	}
 	card->txbd_ring_pbase = virt_to_phys(card->txbd_ring_vbase);
 
-	dev_dbg(adapter->dev, "info: txbd_ring - base: %p, pbase: %#x:%x,"
-			"len: %x\n", card->txbd_ring_vbase,
-			(u32)card->txbd_ring_pbase,
-			(u32)((u64)card->txbd_ring_pbase >> 32),
-			card->txbd_ring_size);
+	dev_dbg(adapter->dev,
+		"info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
+		card->txbd_ring_vbase, (u32)card->txbd_ring_pbase,
+		(u32)((u64)card->txbd_ring_pbase >> 32), card->txbd_ring_size);
 
 	for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
 		card->txbd_ring[i] = (struct mwifiex_pcie_buf_desc *)
-				(card->txbd_ring_vbase +
-				(sizeof(struct mwifiex_pcie_buf_desc) * i));
+				     (card->txbd_ring_vbase +
+				      (sizeof(struct mwifiex_pcie_buf_desc)
+				       * i));
 
 		/* Allocate buffer here so that firmware can DMA data from it */
 		skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE);
@@ -412,10 +412,9 @@
 
 		skb_put(skb, MWIFIEX_RX_DATA_BUF_SIZE);
 		dev_dbg(adapter->dev, "info: TX ring: add new skb base: %p, "
-				"buf_base: %p, buf_pbase: %#x:%x, "
-				"buf_len: %#x\n", skb, skb->data,
-				(u32)*buf_pa, (u32)(((u64)*buf_pa >> 32)),
-				skb->len);
+			"buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n",
+			skb, skb->data, (u32)*buf_pa,
+			(u32)(((u64)*buf_pa >> 32)), skb->len);
 
 		card->tx_buf_list[i] = skb;
 		card->txbd_ring[i]->paddr = *buf_pa;
@@ -469,9 +468,9 @@
 	card->rxbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND;
 
 	card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
-				MWIFIEX_MAX_TXRX_BD;
+							MWIFIEX_MAX_TXRX_BD;
 	dev_dbg(adapter->dev, "info: rxbd_ring: Allocating %d bytes\n",
-				card->rxbd_ring_size);
+		card->rxbd_ring_size);
 	card->rxbd_ring_vbase = kzalloc(card->rxbd_ring_size, GFP_KERNEL);
 	if (!card->rxbd_ring_vbase) {
 		dev_err(adapter->dev, "Unable to allocate buffer for "
@@ -480,21 +479,23 @@
 	}
 	card->rxbd_ring_pbase = virt_to_phys(card->rxbd_ring_vbase);
 
-	dev_dbg(adapter->dev, "info: rxbd_ring - base: %p, pbase: %#x:%x,"
-			"len: %#x\n", card->rxbd_ring_vbase,
-			(u32)card->rxbd_ring_pbase,
-			(u32)((u64)card->rxbd_ring_pbase >> 32),
-			card->rxbd_ring_size);
+	dev_dbg(adapter->dev,
+		"info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
+		card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
+		(u32)((u64)card->rxbd_ring_pbase >> 32),
+		card->rxbd_ring_size);
 
 	for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
 		card->rxbd_ring[i] = (struct mwifiex_pcie_buf_desc *)
-				(card->rxbd_ring_vbase +
-				(sizeof(struct mwifiex_pcie_buf_desc) * i));
+				     (card->rxbd_ring_vbase +
+				      (sizeof(struct mwifiex_pcie_buf_desc)
+				       * i));
 
 		/* Allocate skb here so that firmware can DMA data from it */
 		skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE);
 		if (!skb) {
-			dev_err(adapter->dev, "Unable to allocate skb for RX ring.\n");
+			dev_err(adapter->dev,
+				"Unable to allocate skb for RX ring.\n");
 			kfree(card->rxbd_ring_vbase);
 			return -ENOMEM;
 		}
@@ -502,10 +503,9 @@
 		skb_put(skb, MWIFIEX_RX_DATA_BUF_SIZE);
 
 		dev_dbg(adapter->dev, "info: RX ring: add new skb base: %p, "
-				"buf_base: %p, buf_pbase: %#x:%x, "
-				"buf_len: %#x\n", skb, skb->data,
-				(u32)*buf_pa, (u32)((u64)*buf_pa >> 32),
-				skb->len);
+			"buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n",
+			skb, skb->data, (u32)*buf_pa, (u32)((u64)*buf_pa >> 32),
+			skb->len);
 
 		card->rx_buf_list[i] = skb;
 		card->rxbd_ring[i]->paddr = *buf_pa;
@@ -562,32 +562,34 @@
 	card->evtbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND;
 
 	card->evtbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
-				MWIFIEX_MAX_EVT_BD;
+							MWIFIEX_MAX_EVT_BD;
 	dev_dbg(adapter->dev, "info: evtbd_ring: Allocating %d bytes\n",
-				card->evtbd_ring_size);
+		card->evtbd_ring_size);
 	card->evtbd_ring_vbase = kzalloc(card->evtbd_ring_size, GFP_KERNEL);
 	if (!card->evtbd_ring_vbase) {
-		dev_err(adapter->dev, "Unable to allocate buffer. "
-				"Terminating download\n");
+		dev_err(adapter->dev,
+			"Unable to allocate buffer. Terminating download\n");
 		return -ENOMEM;
 	}
 	card->evtbd_ring_pbase = virt_to_phys(card->evtbd_ring_vbase);
 
-	dev_dbg(adapter->dev, "info: CMDRSP/EVT bd_ring - base: %p, "
-		       "pbase: %#x:%x, len: %#x\n", card->evtbd_ring_vbase,
-		       (u32)card->evtbd_ring_pbase,
-		       (u32)((u64)card->evtbd_ring_pbase >> 32),
-		       card->evtbd_ring_size);
+	dev_dbg(adapter->dev,
+		"info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
+		card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
+		(u32)((u64)card->evtbd_ring_pbase >> 32),
+		card->evtbd_ring_size);
 
 	for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
 		card->evtbd_ring[i] = (struct mwifiex_pcie_buf_desc *)
-				(card->evtbd_ring_vbase +
-				(sizeof(struct mwifiex_pcie_buf_desc) * i));
+				      (card->evtbd_ring_vbase +
+				       (sizeof(struct mwifiex_pcie_buf_desc)
+					* i));
 
 		/* Allocate skb here so that firmware can DMA data from it */
 		skb = dev_alloc_skb(MAX_EVENT_SIZE);
 		if (!skb) {
-			dev_err(adapter->dev, "Unable to allocate skb for EVENT buf.\n");
+			dev_err(adapter->dev,
+				"Unable to allocate skb for EVENT buf.\n");
 			kfree(card->evtbd_ring_vbase);
 			return -ENOMEM;
 		}
@@ -595,10 +597,9 @@
 		skb_put(skb, MAX_EVENT_SIZE);
 
 		dev_dbg(adapter->dev, "info: Evt ring: add new skb. base: %p, "
-			       "buf_base: %p, buf_pbase: %#x:%x, "
-			       "buf_len: %#x\n", skb, skb->data,
-			       (u32)*buf_pa, (u32)((u64)*buf_pa >> 32),
-			       skb->len);
+			"buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n",
+			skb, skb->data, (u32)*buf_pa, (u32)((u64)*buf_pa >> 32),
+			skb->len);
 
 		card->evt_buf_list[i] = skb;
 		card->evtbd_ring[i]->paddr = *buf_pa;
@@ -647,8 +648,8 @@
 	/* Allocate memory for receiving command response data */
 	skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
 	if (!skb) {
-		dev_err(adapter->dev, "Unable to allocate skb for command "
-				      "response data.\n");
+		dev_err(adapter->dev,
+			"Unable to allocate skb for command response data.\n");
 		return -ENOMEM;
 	}
 	mwifiex_update_sk_buff_pa(skb);
@@ -659,8 +660,8 @@
 	/* Allocate memory for sending command to firmware */
 	skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER);
 	if (!skb) {
-		dev_err(adapter->dev, "Unable to allocate skb for command "
-				      "data.\n");
+		dev_err(adapter->dev,
+			"Unable to allocate skb for command data.\n");
 		return -ENOMEM;
 	}
 	mwifiex_update_sk_buff_pa(skb);
@@ -702,8 +703,8 @@
 	/* Allocate memory for sleep cookie */
 	skb = dev_alloc_skb(sizeof(u32));
 	if (!skb) {
-		dev_err(adapter->dev, "Unable to allocate skb for sleep "
-				      "cookie!\n");
+		dev_err(adapter->dev,
+			"Unable to allocate skb for sleep cookie!\n");
 		return -ENOMEM;
 	}
 	mwifiex_update_sk_buff_pa(skb);
@@ -713,7 +714,7 @@
 	*(u32 *)skb->data = FW_AWAKE_COOKIE;
 
 	dev_dbg(adapter->dev, "alloc_scook: sleep cookie=0x%x\n",
-				*((u32 *)skb->data));
+		*((u32 *)skb->data));
 
 	/* Save the sleep cookie */
 	card->sleep_cookie = skb;
@@ -757,15 +758,15 @@
 
 	/* Read the TX ring read pointer set by firmware */
 	if (mwifiex_read_reg(adapter, REG_TXBD_RDPTR, &rdptr)) {
-		dev_err(adapter->dev, "SEND DATA: failed to read "
-				      "REG_TXBD_RDPTR\n");
+		dev_err(adapter->dev,
+			"SEND DATA: failed to read REG_TXBD_RDPTR\n");
 		return -1;
 	}
 
 	wrindx = card->txbd_wrptr & MWIFIEX_TXBD_MASK;
 
 	dev_dbg(adapter->dev, "info: SEND DATA: <Rd: %#x, Wr: %#x>\n", rdptr,
-				card->txbd_wrptr);
+		card->txbd_wrptr);
 	if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) !=
 			(rdptr & MWIFIEX_TXBD_MASK)) ||
 	    ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) !=
@@ -797,32 +798,31 @@
 
 		/* Write the TX ring write pointer in to REG_TXBD_WRPTR */
 		if (mwifiex_write_reg(adapter, REG_TXBD_WRPTR,
-							card->txbd_wrptr)) {
-			dev_err(adapter->dev, "SEND DATA: failed to write "
-					      "REG_TXBD_WRPTR\n");
+				      card->txbd_wrptr)) {
+			dev_err(adapter->dev,
+				"SEND DATA: failed to write REG_TXBD_WRPTR\n");
 			return 0;
 		}
 
 		/* Send the TX ready interrupt */
 		if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
 				      CPU_INTR_DNLD_RDY)) {
-			dev_err(adapter->dev, "SEND DATA: failed to assert "
-					      "door-bell interrupt.\n");
+			dev_err(adapter->dev,
+				"SEND DATA: failed to assert door-bell intr\n");
 			return -1;
 		}
 		dev_dbg(adapter->dev, "info: SEND DATA: Updated <Rd: %#x, Wr: "
-				      "%#x> and sent packet to firmware "
-				      "successfully\n", rdptr,
-				      card->txbd_wrptr);
+			"%#x> and sent packet to firmware successfully\n",
+			rdptr, card->txbd_wrptr);
 	} else {
-		dev_dbg(adapter->dev, "info: TX Ring full, can't send anymore "
-				      "packets to firmware\n");
+		dev_dbg(adapter->dev,
+			"info: TX Ring full, can't send packets to fw\n");
 		adapter->data_sent = true;
 		/* Send the TX ready interrupt */
 		if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
 				      CPU_INTR_DNLD_RDY))
-			dev_err(adapter->dev, "SEND DATA: failed to assert "
-					      "door-bell interrupt\n");
+			dev_err(adapter->dev,
+				"SEND DATA: failed to assert door-bell intr\n");
 		return -EBUSY;
 	}
 
@@ -842,8 +842,8 @@
 
 	/* Read the RX ring Write pointer set by firmware */
 	if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) {
-		dev_err(adapter->dev, "RECV DATA: failed to read "
-				      "REG_TXBD_RDPTR\n");
+		dev_err(adapter->dev,
+			"RECV DATA: failed to read REG_TXBD_RDPTR\n");
 		ret = -1;
 		goto done;
 	}
@@ -861,12 +861,13 @@
 		/* Get data length from interface header -
 		   first byte is len, second byte is type */
 		rx_len = *((u16 *)skb_data->data);
-		dev_dbg(adapter->dev, "info: RECV DATA: Rd=%#x, Wr=%#x, "
-				"Len=%d\n", card->rxbd_rdptr, wrptr, rx_len);
+		dev_dbg(adapter->dev,
+			"info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
+			card->rxbd_rdptr, wrptr, rx_len);
 		skb_tmp = dev_alloc_skb(rx_len);
 		if (!skb_tmp) {
-			dev_dbg(adapter->dev, "info: Failed to alloc skb "
-					      "for RX\n");
+			dev_dbg(adapter->dev,
+				"info: Failed to alloc skb for RX\n");
 			ret = -EBUSY;
 			goto done;
 		}
@@ -881,26 +882,26 @@
 					    MWIFIEX_BD_FLAG_ROLLOVER_IND);
 		}
 		dev_dbg(adapter->dev, "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
-				card->rxbd_rdptr, wrptr);
+			card->rxbd_rdptr, wrptr);
 
 		/* Write the RX ring read pointer in to REG_RXBD_RDPTR */
 		if (mwifiex_write_reg(adapter, REG_RXBD_RDPTR,
 				      card->rxbd_rdptr)) {
-			dev_err(adapter->dev, "RECV DATA: failed to "
-					      "write REG_RXBD_RDPTR\n");
+			dev_err(adapter->dev,
+				"RECV DATA: failed to write REG_RXBD_RDPTR\n");
 			ret = -1;
 			goto done;
 		}
 
 		/* Read the RX ring Write pointer set by firmware */
 		if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) {
-			dev_err(adapter->dev, "RECV DATA: failed to read "
-					      "REG_TXBD_RDPTR\n");
+			dev_err(adapter->dev,
+				"RECV DATA: failed to read REG_TXBD_RDPTR\n");
 			ret = -1;
 			goto done;
 		}
-		dev_dbg(adapter->dev, "info: RECV DATA: Received packet from "
-				      "firmware successfully\n");
+		dev_dbg(adapter->dev,
+			"info: RECV DATA: Rcvd packet from fw successfully\n");
 		mwifiex_handle_rx_packet(adapter, skb_tmp);
 	}
 
@@ -919,17 +920,19 @@
 	phys_addr_t *buf_pa = MWIFIEX_SKB_PACB(skb);
 
 	if (!(skb->data && skb->len && *buf_pa)) {
-		dev_err(adapter->dev, "Invalid parameter in %s <%p, %#x:%x, "
-				"%x>\n", __func__, skb->data, skb->len,
-				(u32)*buf_pa, (u32)((u64)*buf_pa >> 32));
+		dev_err(adapter->dev,
+			"Invalid parameter in %s <%p, %#x:%x, %x>\n",
+			__func__, skb->data, skb->len,
+			(u32)*buf_pa, (u32)((u64)*buf_pa >> 32));
 		return -1;
 	}
 
 	/* Write the lower 32bits of the physical address to scratch
 	 * register 0 */
 	if (mwifiex_write_reg(adapter, PCIE_SCRATCH_0_REG, (u32)*buf_pa)) {
-		dev_err(adapter->dev, "%s: failed to write download command "
-				      "to boot code.\n", __func__);
+		dev_err(adapter->dev,
+			"%s: failed to write download command to boot code.\n",
+			__func__);
 		return -1;
 	}
 
@@ -937,23 +940,25 @@
 	 * register 1 */
 	if (mwifiex_write_reg(adapter, PCIE_SCRATCH_1_REG,
 			      (u32)((u64)*buf_pa >> 32))) {
-		dev_err(adapter->dev, "%s: failed to write download command "
-				      "to boot code.\n", __func__);
+		dev_err(adapter->dev,
+			"%s: failed to write download command to boot code.\n",
+			__func__);
 		return -1;
 	}
 
 	/* Write the command length to scratch register 2 */
 	if (mwifiex_write_reg(adapter, PCIE_SCRATCH_2_REG, skb->len)) {
-		dev_err(adapter->dev, "%s: failed to write command length to "
-				      "scratch register 2\n", __func__);
+		dev_err(adapter->dev,
+			"%s: failed to write command len to scratch reg 2\n",
+			__func__);
 		return -1;
 	}
 
 	/* Ring the door bell */
 	if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
 			      CPU_INTR_DOOR_BELL)) {
-		dev_err(adapter->dev, "%s: failed to assert door-bell "
-				      "interrupt.\n", __func__);
+		dev_err(adapter->dev,
+			"%s: failed to assert door-bell intr\n", __func__);
 		return -1;
 	}
 
@@ -973,14 +978,14 @@
 
 	if (!(skb->data && skb->len)) {
 		dev_err(adapter->dev, "Invalid parameter in %s <%p, %#x>\n",
-				      __func__, skb->data, skb->len);
+			__func__, skb->data, skb->len);
 		return -1;
 	}
 
 	/* Make sure a command response buffer is available */
 	if (!card->cmdrsp_buf) {
-		dev_err(adapter->dev, "No response buffer available, send "
-				      "command failed\n");
+		dev_err(adapter->dev,
+			"No response buffer available, send command failed\n");
 		return -EBUSY;
 	}
 
@@ -1011,17 +1016,18 @@
 		/* Write the lower 32bits of the cmdrsp buffer physical
 		   address */
 		if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO,
-					(u32)*cmdrsp_buf_pa)) {
-			dev_err(adapter->dev, "Failed to write download command to boot code.\n");
+				      (u32)*cmdrsp_buf_pa)) {
+			dev_err(adapter->dev,
+				"Failed to write download cmd to boot code.\n");
 			ret = -1;
 			goto done;
 		}
 		/* Write the upper 32bits of the cmdrsp buffer physical
 		   address */
 		if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI,
-					(u32)((u64)*cmdrsp_buf_pa >> 32))) {
-			dev_err(adapter->dev, "Failed to write download command"
-					      " to boot code.\n");
+				      (u32)((u64)*cmdrsp_buf_pa >> 32))) {
+			dev_err(adapter->dev,
+				"Failed to write download cmd to boot code.\n");
 			ret = -1;
 			goto done;
 		}
@@ -1029,27 +1035,25 @@
 
 	cmd_buf_pa = MWIFIEX_SKB_PACB(card->cmd_buf);
 	/* Write the lower 32bits of the physical address to REG_CMD_ADDR_LO */
-	if (mwifiex_write_reg(adapter, REG_CMD_ADDR_LO,
-				(u32)*cmd_buf_pa)) {
-		dev_err(adapter->dev, "Failed to write download command "
-				      "to boot code.\n");
+	if (mwifiex_write_reg(adapter, REG_CMD_ADDR_LO, (u32)*cmd_buf_pa)) {
+		dev_err(adapter->dev,
+			"Failed to write download cmd to boot code.\n");
 		ret = -1;
 		goto done;
 	}
 	/* Write the upper 32bits of the physical address to REG_CMD_ADDR_HI */
 	if (mwifiex_write_reg(adapter, REG_CMD_ADDR_HI,
-				(u32)((u64)*cmd_buf_pa >> 32))) {
-		dev_err(adapter->dev, "Failed to write download command "
-				      "to boot code.\n");
+			      (u32)((u64)*cmd_buf_pa >> 32))) {
+		dev_err(adapter->dev,
+			"Failed to write download cmd to boot code.\n");
 		ret = -1;
 		goto done;
 	}
 
 	/* Write the command length to REG_CMD_SIZE */
-	if (mwifiex_write_reg(adapter, REG_CMD_SIZE,
-				card->cmd_buf->len)) {
-		dev_err(adapter->dev, "Failed to write command length to "
-				      "REG_CMD_SIZE\n");
+	if (mwifiex_write_reg(adapter, REG_CMD_SIZE, card->cmd_buf->len)) {
+		dev_err(adapter->dev,
+			"Failed to write cmd len to REG_CMD_SIZE\n");
 		ret = -1;
 		goto done;
 	}
@@ -1057,8 +1061,8 @@
 	/* Ring the door bell */
 	if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
 			      CPU_INTR_DOOR_BELL)) {
-		dev_err(adapter->dev, "Failed to assert door-bell "
-				      "interrupt.\n");
+		dev_err(adapter->dev,
+			"Failed to assert door-bell intr\n");
 		ret = -1;
 		goto done;
 	}
@@ -1076,30 +1080,29 @@
 static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
 {
 	struct pcie_service_card *card = adapter->card;
+	struct sk_buff *skb = card->cmdrsp_buf;
 	int count = 0;
 
 	dev_dbg(adapter->dev, "info: Rx CMD Response\n");
 
 	if (!adapter->curr_cmd) {
-		skb_pull(card->cmdrsp_buf, INTF_HEADER_LEN);
+		skb_pull(skb, INTF_HEADER_LEN);
 		if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
-			mwifiex_process_sleep_confirm_resp(adapter,
-					card->cmdrsp_buf->data,
-					card->cmdrsp_buf->len);
+			mwifiex_process_sleep_confirm_resp(adapter, skb->data,
+							   skb->len);
 			while (mwifiex_pcie_ok_to_access_hw(adapter) &&
 							(count++ < 10))
-				udelay(50);
+				usleep_range(50, 60);
 		} else {
-			dev_err(adapter->dev, "There is no command but "
-					      "got cmdrsp\n");
+			dev_err(adapter->dev,
+				"There is no command but got cmdrsp\n");
 		}
-		memcpy(adapter->upld_buf, card->cmdrsp_buf->data,
-		       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER,
-			     card->cmdrsp_buf->len));
-		skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
+		memcpy(adapter->upld_buf, skb->data,
+		       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
+		skb_push(skb, INTF_HEADER_LEN);
 	} else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
-		skb_pull(card->cmdrsp_buf, INTF_HEADER_LEN);
-		adapter->curr_cmd->resp_skb = card->cmdrsp_buf;
+		skb_pull(skb, INTF_HEADER_LEN);
+		adapter->curr_cmd->resp_skb = skb;
 		adapter->cmd_resp_received = true;
 		/* Take the pointer and set it to CMD node and will
 		   return in the response complete callback */
@@ -1109,15 +1112,15 @@
 		   will prevent firmware from writing to the same response
 		   buffer again. */
 		if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO, 0)) {
-			dev_err(adapter->dev, "cmd_done: failed to clear "
-					      "cmd_rsp address.\n");
+			dev_err(adapter->dev,
+				"cmd_done: failed to clear cmd_rsp_addr_lo\n");
 			return -1;
 		}
 		/* Write the upper 32bits of the cmdrsp buffer physical
 		   address */
 		if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI, 0)) {
-			dev_err(adapter->dev, "cmd_done: failed to clear "
-					      "cmd_rsp address.\n");
+			dev_err(adapter->dev,
+				"cmd_done: failed to clear cmd_rsp_addr_hi\n");
 			return -1;
 		}
 	}
@@ -1151,8 +1154,8 @@
 	u32 wrptr, event;
 
 	if (adapter->event_received) {
-		dev_dbg(adapter->dev, "info: Event being processed, "\
-				"do not process this interrupt just yet\n");
+		dev_dbg(adapter->dev, "info: Event being processed, "
+			"do not process this interrupt just yet\n");
 		return 0;
 	}
 
@@ -1163,14 +1166,15 @@
 
 	/* Read the event ring write pointer set by firmware */
 	if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) {
-		dev_err(adapter->dev, "EventReady: failed to read REG_EVTBD_WRPTR\n");
+		dev_err(adapter->dev,
+			"EventReady: failed to read REG_EVTBD_WRPTR\n");
 		return -1;
 	}
 
 	dev_dbg(adapter->dev, "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
-			card->evtbd_rdptr, wrptr);
-	if (((wrptr & MWIFIEX_EVTBD_MASK) !=
-	     (card->evtbd_rdptr & MWIFIEX_EVTBD_MASK)) ||
+		card->evtbd_rdptr, wrptr);
+	if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
+					      & MWIFIEX_EVTBD_MASK)) ||
 	    ((wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) ==
 	     (card->evtbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) {
 		struct sk_buff *skb_cmd;
@@ -1230,13 +1234,14 @@
 
 	if (rdptr >= MWIFIEX_MAX_EVT_BD) {
 		dev_err(adapter->dev, "event_complete: Invalid rdptr 0x%x\n",
-					rdptr);
+			rdptr);
 		return -EINVAL;
 	}
 
 	/* Read the event ring write pointer set by firmware */
 	if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) {
-		dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_WRPTR\n");
+		dev_err(adapter->dev,
+			"event_complete: failed to read REG_EVTBD_WRPTR\n");
 		return -1;
 	}
 
@@ -1249,9 +1254,9 @@
 		card->evtbd_ring[rdptr]->flags = 0;
 		skb = NULL;
 	} else {
-		dev_dbg(adapter->dev, "info: ERROR: Buffer is still valid at "
-				      "index %d, <%p, %p>\n", rdptr,
-				      card->evt_buf_list[rdptr], skb);
+		dev_dbg(adapter->dev,
+			"info: ERROR: buf still valid at index %d, <%p, %p>\n",
+			rdptr, card->evt_buf_list[rdptr], skb);
 	}
 
 	if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
@@ -1261,11 +1266,12 @@
 	}
 
 	dev_dbg(adapter->dev, "info: Updated <Rd: 0x%x, Wr: 0x%x>",
-				card->evtbd_rdptr, wrptr);
+		card->evtbd_rdptr, wrptr);
 
 	/* Write the event ring read pointer in to REG_EVTBD_RDPTR */
 	if (mwifiex_write_reg(adapter, REG_EVTBD_RDPTR, card->evtbd_rdptr)) {
-		dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_RDPTR\n");
+		dev_err(adapter->dev,
+			"event_complete: failed to read REG_EVTBD_RDPTR\n");
 		return -1;
 	}
 
@@ -1299,17 +1305,17 @@
 	}
 
 	if (!firmware || !firmware_len) {
-		dev_err(adapter->dev, "No firmware image found! "
-				      "Terminating download\n");
+		dev_err(adapter->dev,
+			"No firmware image found! Terminating download\n");
 		return -1;
 	}
 
 	dev_dbg(adapter->dev, "info: Downloading FW image (%d bytes)\n",
-				firmware_len);
+		firmware_len);
 
 	if (mwifiex_pcie_disable_host_int(adapter)) {
-		dev_err(adapter->dev, "%s: Disabling interrupts"
-				      " failed.\n", __func__);
+		dev_err(adapter->dev,
+			"%s: Disabling interrupts failed.\n", __func__);
 		return -1;
 	}
 
@@ -1332,19 +1338,20 @@
 			ret = mwifiex_read_reg(adapter, PCIE_SCRATCH_2_REG,
 					       &len);
 			if (ret) {
-				dev_warn(adapter->dev, "Failed reading length from boot code\n");
+				dev_warn(adapter->dev,
+					 "Failed reading len from boot code\n");
 				goto done;
 			}
 			if (len)
 				break;
-			udelay(10);
+			usleep_range(10, 20);
 		}
 
 		if (!len) {
 			break;
 		} else if (len > MWIFIEX_UPLD_SIZE) {
 			pr_err("FW download failure @ %d, invalid length %d\n",
-				offset, len);
+			       offset, len);
 			ret = -1;
 			goto done;
 		}
@@ -1360,8 +1367,8 @@
 				goto done;
 			}
 			dev_err(adapter->dev, "FW CRC error indicated by the "
-					      "helper: len = 0x%04X, txlen = "
-					      "%d\n", len, txlen);
+				"helper: len = 0x%04X, txlen = %d\n",
+				len, txlen);
 			len &= ~BIT(0);
 			/* Setting this to 0 to resend from same offset */
 			txlen = 0;
@@ -1374,9 +1381,9 @@
 
 			dev_dbg(adapter->dev, ".");
 
-			tx_blocks =
-				(txlen + MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD - 1) /
-				MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD;
+			tx_blocks = (txlen +
+				     MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD - 1) /
+				     MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD;
 
 			/* Copy payload to buffer */
 			memmove(skb->data, &firmware[offset], txlen);
@@ -1387,7 +1394,8 @@
 
 		/* Send the boot command to device */
 		if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
-			dev_err(adapter->dev, "Failed to send firmware download command\n");
+			dev_err(adapter->dev,
+				"Failed to send firmware download command\n");
 			ret = -1;
 			goto done;
 		}
@@ -1396,8 +1404,8 @@
 			if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
 					     &ireg_intr)) {
 				dev_err(adapter->dev, "%s: Failed to read "
-						      "interrupt status during "
-						      "fw dnld.\n", __func__);
+					"interrupt status during fw dnld.\n",
+					__func__);
 				ret = -1;
 				goto done;
 			}
@@ -1407,7 +1415,7 @@
 	} while (true);
 
 	dev_dbg(adapter->dev, "info:\nFW download over, size %d bytes\n",
-				offset);
+		offset);
 
 	ret = 0;
 
@@ -1430,14 +1438,15 @@
 
 	/* Mask spurios interrupts */
 	if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
-				HOST_INTR_MASK)) {
+			      HOST_INTR_MASK)) {
 		dev_warn(adapter->dev, "Write register failed\n");
 		return -1;
 	}
 
 	dev_dbg(adapter->dev, "Setting driver ready signature\n");
 	if (mwifiex_write_reg(adapter, REG_DRV_READY, FIRMWARE_READY_PCIE)) {
-		dev_err(adapter->dev, "Failed to write driver ready signature\n");
+		dev_err(adapter->dev,
+			"Failed to write driver ready signature\n");
 		return -1;
 	}
 
@@ -1468,8 +1477,9 @@
 			adapter->winner = 1;
 			ret = -1;
 		} else {
-			dev_err(adapter->dev, "PCI-E is not the winner <%#x, %d>, exit download\n",
-					ret, adapter->winner);
+			dev_err(adapter->dev,
+				"PCI-E is not the winner <%#x,%d>, exit dnld\n",
+				ret, adapter->winner);
 			ret = 0;
 		}
 	}
@@ -1512,10 +1522,11 @@
 			    (adapter->ps_state == PS_STATE_SLEEP)) {
 				mwifiex_pcie_enable_host_int(adapter);
 				if (mwifiex_write_reg(adapter,
-						PCIE_CPU_INT_EVENT,
-						CPU_INTR_SLEEP_CFM_DONE)) {
-					dev_warn(adapter->dev, "Write register"
-							       " failed\n");
+						      PCIE_CPU_INT_EVENT,
+						      CPU_INTR_SLEEP_CFM_DONE)
+						      ) {
+					dev_warn(adapter->dev,
+						 "Write register failed\n");
 					return;
 
 				}
@@ -1551,7 +1562,7 @@
 	card = (struct pcie_service_card *) pci_get_drvdata(pdev);
 	if (!card || !card->adapter) {
 		pr_debug("info: %s: card=%p adapter=%p\n", __func__, card,
-						card ? card->adapter : NULL);
+			 card ? card->adapter : NULL);
 		goto exit;
 	}
 	adapter = card->adapter;
@@ -1594,7 +1605,7 @@
 		if (adapter->int_status & HOST_INTR_DNLD_DONE) {
 			adapter->int_status &= ~HOST_INTR_DNLD_DONE;
 			if (adapter->data_sent) {
-				dev_dbg(adapter->dev, "info: DATA sent Interrupt\n");
+				dev_dbg(adapter->dev, "info: DATA sent intr\n");
 				adapter->data_sent = false;
 			}
 		}
@@ -1616,7 +1627,8 @@
 		if (adapter->int_status & HOST_INTR_CMD_DONE) {
 			adapter->int_status &= ~HOST_INTR_CMD_DONE;
 			if (adapter->cmd_sent) {
-				dev_dbg(adapter->dev, "info: CMD sent Interrupt\n");
+				dev_dbg(adapter->dev,
+					"info: CMD sent Interrupt\n");
 				adapter->cmd_sent = false;
 			}
 			/* Handle command response */
@@ -1628,15 +1640,17 @@
 		if (mwifiex_pcie_ok_to_access_hw(adapter)) {
 			if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
 					     &pcie_ireg)) {
-				dev_warn(adapter->dev, "Read register failed\n");
+				dev_warn(adapter->dev,
+					 "Read register failed\n");
 				return -1;
 			}
 
 			if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
 				if (mwifiex_write_reg(adapter,
-					PCIE_HOST_INT_STATUS, ~pcie_ireg)) {
-					dev_warn(adapter->dev, "Write register"
-							       " failed\n");
+						      PCIE_HOST_INT_STATUS,
+						      ~pcie_ireg)) {
+					dev_warn(adapter->dev,
+						 "Write register failed\n");
 					return -1;
 				}
 				adapter->int_status |= pcie_ireg;
@@ -1646,7 +1660,7 @@
 		}
 	}
 	dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
-	       adapter->cmd_sent, adapter->data_sent);
+		adapter->cmd_sent, adapter->data_sent);
 	mwifiex_pcie_enable_host_int(adapter);
 
 	return 0;
@@ -1737,8 +1751,9 @@
 		goto err_iomap2;
 	}
 
-	dev_dbg(adapter->dev, "PCI memory map Virt0: %p PCI memory map Virt2: "
-			      "%p\n", card->pci_mmap, card->pci_mmap1);
+	dev_dbg(adapter->dev,
+		"PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
+		card->pci_mmap, card->pci_mmap1);
 
 	card->cmdrsp_buf = NULL;
 	ret = mwifiex_pcie_create_txbd_ring(adapter);
@@ -1808,7 +1823,8 @@
 	dev_dbg(adapter->dev, "Clearing driver ready signature\n");
 	if (user_rmmod) {
 		if (mwifiex_write_reg(adapter, REG_DRV_READY, 0x00000000))
-			dev_err(adapter->dev, "Failed to write driver not-ready signature\n");
+			dev_err(adapter->dev,
+				"Failed to write driver not-ready signature\n");
 	}
 
 	if (pdev) {
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 8f10038..aff9cd7 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -125,7 +125,7 @@
 					ieee_hdr.element_id == WLAN_EID_RSN))) {
 		iebody = (struct ie_body *)
 			 (((u8 *) bss_desc->bcn_rsn_ie->data) +
-			 RSN_GTK_OUI_OFFSET);
+			  RSN_GTK_OUI_OFFSET);
 		oui = &mwifiex_rsn_oui[cipher][0];
 		ret = mwifiex_search_oui_in_ie(iebody, oui);
 		if (ret)
@@ -148,8 +148,9 @@
 	struct ie_body *iebody;
 	u8 ret = MWIFIEX_OUI_NOT_PRESENT;
 
-	if (((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)).
-				      vend_hdr.element_id == WLAN_EID_WPA))) {
+	if (((bss_desc->bcn_wpa_ie) &&
+	     ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id ==
+	      WLAN_EID_WPA))) {
 		iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
 		oui = &mwifiex_wpa_oui[cipher][0];
 		ret = mwifiex_search_oui_in_ie(iebody, oui);
@@ -163,8 +164,7 @@
  * This function compares two SSIDs and checks if they match.
  */
 s32
-mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
-		 struct mwifiex_802_11_ssid *ssid2)
+mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
 {
 	if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
 		return -1;
@@ -176,8 +176,8 @@
  * compatible with it.
  */
 static bool
-mwifiex_is_network_compatible_for_wapi(struct mwifiex_private *priv,
-				       struct mwifiex_bssdescriptor *bss_desc)
+mwifiex_is_bss_wapi(struct mwifiex_private *priv,
+		    struct mwifiex_bssdescriptor *bss_desc)
 {
 	if (priv->sec_info.wapi_enabled &&
 	    (bss_desc->bcn_wapi_ie &&
@@ -193,18 +193,17 @@
  * scanned network is compatible with it.
  */
 static bool
-mwifiex_is_network_compatible_for_no_sec(struct mwifiex_private *priv,
-				       struct mwifiex_bssdescriptor *bss_desc)
+mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
+		      struct mwifiex_bssdescriptor *bss_desc)
 {
 	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 	    !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
 		((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
-	    WLAN_EID_WPA))
-	    && ((!bss_desc->bcn_rsn_ie) ||
+		 WLAN_EID_WPA)) &&
+	    ((!bss_desc->bcn_rsn_ie) ||
 		((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
-	    WLAN_EID_RSN))
-	    && !priv->sec_info.encryption_mode
-	    && !bss_desc->privacy) {
+		 WLAN_EID_RSN)) &&
+	    !priv->sec_info.encryption_mode && !bss_desc->privacy) {
 		return true;
 	}
 	return false;
@@ -215,8 +214,8 @@
  * is compatible with it.
  */
 static bool
-mwifiex_is_network_compatible_for_static_wep(struct mwifiex_private *priv,
-				       struct mwifiex_bssdescriptor *bss_desc)
+mwifiex_is_bss_static_wep(struct mwifiex_private *priv,
+			  struct mwifiex_bssdescriptor *bss_desc)
 {
 	if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 	    !priv->sec_info.wpa2_enabled && bss_desc->privacy) {
@@ -230,8 +229,8 @@
  * compatible with it.
  */
 static bool
-mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
-				      struct mwifiex_bssdescriptor *bss_desc)
+mwifiex_is_bss_wpa(struct mwifiex_private *priv,
+		   struct mwifiex_bssdescriptor *bss_desc)
 {
 	if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
 	    !priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) &&
@@ -265,17 +264,18 @@
  * compatible with it.
  */
 static bool
-mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv,
-				       struct mwifiex_bssdescriptor *bss_desc)
+mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
+		    struct mwifiex_bssdescriptor *bss_desc)
 {
-	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
-	    priv->sec_info.wpa2_enabled && ((bss_desc->bcn_rsn_ie) &&
-	    ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id == WLAN_EID_RSN))
-	   /*
-	    * Privacy bit may NOT be set in some APs like
-	    * LinkSys WRT54G && bss_desc->privacy
-	    */
-	 ) {
+	if (!priv->sec_info.wep_enabled &&
+	    !priv->sec_info.wpa_enabled &&
+	    priv->sec_info.wpa2_enabled &&
+	    ((bss_desc->bcn_rsn_ie) &&
+	     ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id == WLAN_EID_RSN))) {
+		/*
+		 * Privacy bit may NOT be set in some APs like
+		 * LinkSys WRT54G && bss_desc->privacy
+		 */
 		dev_dbg(priv->adapter->dev, "info: %s: WPA2: "
 			" wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
 			"EncMode=%#x privacy=%#x\n", __func__,
@@ -300,16 +300,16 @@
  * compatible with it.
  */
 static bool
-mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv,
-				       struct mwifiex_bssdescriptor *bss_desc)
+mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
+			 struct mwifiex_bssdescriptor *bss_desc)
 {
 	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
-	    !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
-	    ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA))
-	    && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.
-		   element_id != WLAN_EID_RSN))
-	    && !priv->sec_info.encryption_mode
-	    && bss_desc->privacy) {
+	    !priv->sec_info.wpa2_enabled &&
+	    ((!bss_desc->bcn_wpa_ie) ||
+	     ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) &&
+	    ((!bss_desc->bcn_rsn_ie) ||
+	     ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
+	    !priv->sec_info.encryption_mode && bss_desc->privacy) {
 		return true;
 	}
 	return false;
@@ -320,16 +320,16 @@
  * is compatible with it.
  */
 static bool
-mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
-				       struct mwifiex_bssdescriptor *bss_desc)
+mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
+			   struct mwifiex_bssdescriptor *bss_desc)
 {
 	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
-	    !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
-	    ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA))
-	    && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.
-		   element_id != WLAN_EID_RSN))
-	    && priv->sec_info.encryption_mode
-	    && bss_desc->privacy) {
+	    !priv->sec_info.wpa2_enabled &&
+	    ((!bss_desc->bcn_wpa_ie) ||
+	     ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) &&
+	    ((!bss_desc->bcn_rsn_ie) ||
+	     ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
+	    priv->sec_info.encryption_mode && bss_desc->privacy) {
 		dev_dbg(priv->adapter->dev, "info: %s: dynamic "
 			"WEP: wpa_ie=%#x wpa2_ie=%#x "
 			"EncMode=%#x privacy=%#x\n",
@@ -374,8 +374,9 @@
 	bss_desc->disable_11n = false;
 
 	/* Don't check for compatibility if roaming */
-	if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION)
-	    && (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
+	if (priv->media_connected &&
+	    (priv->bss_mode == NL80211_IFTYPE_STATION) &&
+	    (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
 		return 0;
 
 	if (priv->wps.session_enable) {
@@ -384,32 +385,30 @@
 		return 0;
 	}
 
-	if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) {
+	if (mwifiex_is_bss_wapi(priv, bss_desc)) {
 		dev_dbg(adapter->dev, "info: return success for WAPI AP\n");
 		return 0;
 	}
 
 	if (bss_desc->bss_mode == mode) {
-		if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) {
+		if (mwifiex_is_bss_no_sec(priv, bss_desc)) {
 			/* No security */
 			return 0;
-		} else if (mwifiex_is_network_compatible_for_static_wep(priv,
-								bss_desc)) {
+		} else if (mwifiex_is_bss_static_wep(priv, bss_desc)) {
 			/* Static WEP enabled */
 			dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n");
 			bss_desc->disable_11n = true;
 			return 0;
-		} else if (mwifiex_is_network_compatible_for_wpa(priv,
-								 bss_desc)) {
+		} else if (mwifiex_is_bss_wpa(priv, bss_desc)) {
 			/* WPA enabled */
-			if (((priv->adapter->config_bands & BAND_GN
-			      || priv->adapter->config_bands & BAND_AN)
-			      && bss_desc->bcn_ht_cap)
-			      && !mwifiex_is_wpa_oui_present(bss_desc,
-					CIPHER_SUITE_CCMP)) {
+			if (((priv->adapter->config_bands & BAND_GN ||
+			      priv->adapter->config_bands & BAND_AN) &&
+			     bss_desc->bcn_ht_cap) &&
+			    !mwifiex_is_wpa_oui_present(bss_desc,
+							 CIPHER_SUITE_CCMP)) {
 
-				if (mwifiex_is_wpa_oui_present(bss_desc,
-					    CIPHER_SUITE_TKIP)) {
+				if (mwifiex_is_wpa_oui_present
+						(bss_desc, CIPHER_SUITE_TKIP)) {
 					dev_dbg(adapter->dev,
 						"info: Disable 11n if AES "
 						"is not supported by AP\n");
@@ -419,17 +418,16 @@
 				}
 			}
 			return 0;
-		} else if (mwifiex_is_network_compatible_for_wpa2(priv,
-							bss_desc)) {
+		} else if (mwifiex_is_bss_wpa2(priv, bss_desc)) {
 			/* WPA2 enabled */
-			if (((priv->adapter->config_bands & BAND_GN
-			      || priv->adapter->config_bands & BAND_AN)
-			      && bss_desc->bcn_ht_cap)
-			      && !mwifiex_is_rsn_oui_present(bss_desc,
-					CIPHER_SUITE_CCMP)) {
+			if (((priv->adapter->config_bands & BAND_GN ||
+			      priv->adapter->config_bands & BAND_AN) &&
+			     bss_desc->bcn_ht_cap) &&
+			    !mwifiex_is_rsn_oui_present(bss_desc,
+							CIPHER_SUITE_CCMP)) {
 
-				if (mwifiex_is_rsn_oui_present(bss_desc,
-					    CIPHER_SUITE_TKIP)) {
+				if (mwifiex_is_rsn_oui_present
+						(bss_desc, CIPHER_SUITE_TKIP)) {
 					dev_dbg(adapter->dev,
 						"info: Disable 11n if AES "
 						"is not supported by AP\n");
@@ -439,31 +437,26 @@
 				}
 			}
 			return 0;
-		} else if (mwifiex_is_network_compatible_for_adhoc_aes(priv,
-								bss_desc)) {
+		} else if (mwifiex_is_bss_adhoc_aes(priv, bss_desc)) {
 			/* Ad-hoc AES enabled */
 			return 0;
-		} else if (mwifiex_is_network_compatible_for_dynamic_wep(priv,
-							bss_desc)) {
+		} else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) {
 			/* Dynamic WEP enabled */
 			return 0;
 		}
 
 		/* Security doesn't match */
-		dev_dbg(adapter->dev, "info: %s: failed: "
-		       "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode"
-		       "=%#x privacy=%#x\n",
-		       __func__,
-		       (bss_desc->bcn_wpa_ie) ?
-		       (*(bss_desc->bcn_wpa_ie)).vend_hdr.
-		       element_id : 0,
-		       (bss_desc->bcn_rsn_ie) ?
-		       (*(bss_desc->bcn_rsn_ie)).ieee_hdr.
-		       element_id : 0,
-		       (priv->sec_info.wep_enabled) ? "e" : "d",
-		       (priv->sec_info.wpa_enabled) ? "e" : "d",
-		       (priv->sec_info.wpa2_enabled) ? "e" : "d",
-		       priv->sec_info.encryption_mode, bss_desc->privacy);
+		dev_dbg(adapter->dev,
+			"info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s "
+			"WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n", __func__,
+			(bss_desc->bcn_wpa_ie) ?
+			(*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id : 0,
+			(bss_desc->bcn_rsn_ie) ?
+			(*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id : 0,
+			(priv->sec_info.wep_enabled) ? "e" : "d",
+			(priv->sec_info.wpa_enabled) ? "e" : "d",
+			(priv->sec_info.wpa2_enabled) ? "e" : "d",
+			priv->sec_info.encryption_mode, bss_desc->privacy);
 		return -1;
 	}
 
@@ -480,11 +473,11 @@
  */
 static void
 mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
-				const struct mwifiex_user_scan_cfg
-				*user_scan_in,
-				struct mwifiex_chan_scan_param_set
-				*scan_chan_list,
-				u8 filtered_scan)
+				 const struct mwifiex_user_scan_cfg
+							*user_scan_in,
+				 struct mwifiex_chan_scan_param_set
+							*scan_chan_list,
+				 u8 filtered_scan)
 {
 	enum ieee80211_band band;
 	struct ieee80211_supported_band *sband;
@@ -506,7 +499,7 @@
 			scan_chan_list[chan_idx].radio_type = band;
 
 			if (user_scan_in &&
-				user_scan_in->chan_list[0].scan_time)
+			    user_scan_in->chan_list[0].scan_time)
 				scan_chan_list[chan_idx].max_scan_time =
 					cpu_to_le16((u16) user_scan_in->
 					chan_list[0].scan_time);
@@ -595,19 +588,19 @@
 		 *   - done_early is set (controlling individual scanning of
 		 *     1,6,11)
 		 */
-		while (tlv_idx < max_chan_per_scan
-		       && tmp_chan_list->chan_number && !done_early) {
+		while (tlv_idx < max_chan_per_scan &&
+		       tmp_chan_list->chan_number && !done_early) {
 
 			dev_dbg(priv->adapter->dev,
 				"info: Scan: Chan(%3d), Radio(%d),"
 				" Mode(%d, %d), Dur(%d)\n",
-			       tmp_chan_list->chan_number,
-			       tmp_chan_list->radio_type,
-			       tmp_chan_list->chan_scan_mode_bitmap
-			       & MWIFIEX_PASSIVE_SCAN,
-			       (tmp_chan_list->chan_scan_mode_bitmap
-			       & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
-			       le16_to_cpu(tmp_chan_list->max_scan_time));
+				tmp_chan_list->chan_number,
+				tmp_chan_list->radio_type,
+				tmp_chan_list->chan_scan_mode_bitmap
+				& MWIFIEX_PASSIVE_SCAN,
+				(tmp_chan_list->chan_scan_mode_bitmap
+				 & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
+				le16_to_cpu(tmp_chan_list->max_scan_time));
 
 			/* Copy the current channel TLV to the command being
 			   prepared */
@@ -649,9 +642,10 @@
 			/* Stop the loop if the *current* channel is in the
 			   1,6,11 set and we are not filtering on a BSSID
 			   or SSID. */
-			if (!filtered_scan && (tmp_chan_list->chan_number == 1
-				|| tmp_chan_list->chan_number == 6
-				|| tmp_chan_list->chan_number == 11))
+			if (!filtered_scan &&
+			    (tmp_chan_list->chan_number == 1 ||
+			     tmp_chan_list->chan_number == 6 ||
+			     tmp_chan_list->chan_number == 11))
 				done_early = true;
 
 			/* Increment the tmp pointer to the next channel to
@@ -661,9 +655,10 @@
 			/* Stop the loop if the *next* channel is in the 1,6,11
 			   set.  This will cause it to be the only channel
 			   scanned on the next interation */
-			if (!filtered_scan && (tmp_chan_list->chan_number == 1
-				|| tmp_chan_list->chan_number == 6
-				|| tmp_chan_list->chan_number == 11))
+			if (!filtered_scan &&
+			    (tmp_chan_list->chan_number == 1 ||
+			     tmp_chan_list->chan_number == 6 ||
+			     tmp_chan_list->chan_number == 11))
 				done_early = true;
 		}
 
@@ -715,15 +710,13 @@
  * If the number of probes is not set, adapter default setting is used.
  */
 static void
-mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
-			       const struct mwifiex_user_scan_cfg *user_scan_in,
-			       struct mwifiex_scan_cmd_config *scan_cfg_out,
-			       struct mwifiex_ie_types_chan_list_param_set
-			       **chan_list_out,
-			       struct mwifiex_chan_scan_param_set
-			       *scan_chan_list,
-			       u8 *max_chan_per_scan, u8 *filtered_scan,
-			       u8 *scan_current_only)
+mwifiex_config_scan(struct mwifiex_private *priv,
+		    const struct mwifiex_user_scan_cfg *user_scan_in,
+		    struct mwifiex_scan_cmd_config *scan_cfg_out,
+		    struct mwifiex_ie_types_chan_list_param_set **chan_list_out,
+		    struct mwifiex_chan_scan_param_set *scan_chan_list,
+		    u8 *max_chan_per_scan, u8 *filtered_scan,
+		    u8 *scan_current_only)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
 	struct mwifiex_ie_types_num_probes *num_probes_tlv;
@@ -738,7 +731,7 @@
 	u16 scan_dur;
 	u8 channel;
 	u8 radio_type;
-	u32 ssid_idx;
+	int i;
 	u8 ssid_filter;
 	u8 rates[MWIFIEX_SUPPORTED_RATES];
 	u32 rates_size;
@@ -793,14 +786,8 @@
 		       user_scan_in->specific_bssid,
 		       sizeof(scan_cfg_out->specific_bssid));
 
-		for (ssid_idx = 0;
-		     ((ssid_idx < ARRAY_SIZE(user_scan_in->ssid_list))
-		      && (*user_scan_in->ssid_list[ssid_idx].ssid
-			  || user_scan_in->ssid_list[ssid_idx].max_len));
-		     ssid_idx++) {
-
-			ssid_len = strlen(user_scan_in->ssid_list[ssid_idx].
-					  ssid) + 1;
+		for (i = 0; i < user_scan_in->num_ssids; i++) {
+			ssid_len = user_scan_in->ssid_list[i].ssid_len;
 
 			wildcard_ssid_tlv =
 				(struct mwifiex_ie_types_wildcard_ssid_params *)
@@ -811,19 +798,26 @@
 				(u16) (ssid_len + sizeof(wildcard_ssid_tlv->
 							 max_ssid_length)));
 
-			/* max_ssid_length = 0 tells firmware to perform
-			   specific scan for the SSID filled */
-			wildcard_ssid_tlv->max_ssid_length = 0;
+			/*
+			 * max_ssid_length = 0 tells firmware to perform
+			 * specific scan for the SSID filled, whereas
+			 * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
+			 * wildcard scan.
+			 */
+			if (ssid_len)
+				wildcard_ssid_tlv->max_ssid_length = 0;
+			else
+				wildcard_ssid_tlv->max_ssid_length =
+							IEEE80211_MAX_SSID_LEN;
 
 			memcpy(wildcard_ssid_tlv->ssid,
-			       user_scan_in->ssid_list[ssid_idx].ssid,
-			       ssid_len);
+			       user_scan_in->ssid_list[i].ssid, ssid_len);
 
 			tlv_pos += (sizeof(wildcard_ssid_tlv->header)
 				+ le16_to_cpu(wildcard_ssid_tlv->header.len));
 
-			dev_dbg(adapter->dev, "info: scan: ssid_list[%d]: %s, %d\n",
-				ssid_idx, wildcard_ssid_tlv->ssid,
+			dev_dbg(adapter->dev, "info: scan: ssid[%d]: %s, %d\n",
+				i, wildcard_ssid_tlv->ssid,
 				wildcard_ssid_tlv->max_ssid_length);
 
 			/* Empty wildcard ssid with a maxlen will match many or
@@ -832,7 +826,6 @@
 			   filtered. */
 			if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
 				ssid_filter = false;
-
 		}
 
 		/*
@@ -841,9 +834,9 @@
 		 *  truncate scan results.  That is not an issue with an SSID
 		 *  or BSSID filter applied to the scan results in the firmware.
 		 */
-		if ((ssid_idx && ssid_filter)
-		    || memcmp(scan_cfg_out->specific_bssid, &zero_mac,
-			      sizeof(zero_mac)))
+		if ((i && ssid_filter) ||
+		    memcmp(scan_cfg_out->specific_bssid, &zero_mac,
+			   sizeof(zero_mac)))
 			*filtered_scan = true;
 	} else {
 		scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
@@ -864,7 +857,7 @@
 	if (num_probes) {
 
 		dev_dbg(adapter->dev, "info: scan: num_probes = %d\n",
-						num_probes);
+			num_probes);
 
 		num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
 		num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
@@ -890,9 +883,9 @@
 
 	dev_dbg(adapter->dev, "info: SCAN_CMD: Rates size = %d\n", rates_size);
 
-	if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info)
-	    && (priv->adapter->config_bands & BAND_GN
-		|| priv->adapter->config_bands & BAND_AN)) {
+	if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
+	    (priv->adapter->config_bands & BAND_GN ||
+	     priv->adapter->config_bands & BAND_AN)) {
 		ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
 		memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
 		ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
@@ -921,8 +914,8 @@
 		dev_dbg(adapter->dev, "info: Scan: Using supplied channel list\n");
 
 		for (chan_idx = 0;
-		     chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX
-		     && user_scan_in->chan_list[chan_idx].chan_number;
+		     chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
+		     user_scan_in->chan_list[chan_idx].chan_number;
 		     chan_idx++) {
 
 			channel = user_scan_in->chan_list[chan_idx].chan_number;
@@ -962,9 +955,9 @@
 		}
 
 		/* Check if we are only scanning the current channel */
-		if ((chan_idx == 1)
-		    && (user_scan_in->chan_list[0].chan_number
-			== priv->curr_bss_params.bss_descriptor.channel)) {
+		if ((chan_idx == 1) &&
+		    (user_scan_in->chan_list[0].chan_number ==
+		     priv->curr_bss_params.bss_descriptor.channel)) {
 			*scan_current_only = true;
 			dev_dbg(adapter->dev,
 				"info: Scan: Scanning current channel only\n");
@@ -972,7 +965,7 @@
 
 	} else {
 		dev_dbg(adapter->dev,
-				"info: Scan: Creating full region channel list\n");
+			"info: Scan: Creating full region channel list\n");
 		mwifiex_scan_create_channel_list(priv, user_scan_in,
 						 scan_chan_list,
 						 *filtered_scan);
@@ -1004,7 +997,7 @@
 	*tlv_data = NULL;
 
 	dev_dbg(adapter->dev, "info: SCAN_RESP: tlv_buf_size = %d\n",
-						tlv_buf_size);
+		tlv_buf_size);
 
 	while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
 
@@ -1101,8 +1094,9 @@
 			bss_entry->ssid.ssid_len = element_len;
 			memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
 			       element_len);
-			dev_dbg(adapter->dev, "info: InterpretIE: ssid: "
-					      "%-32s\n", bss_entry->ssid.ssid);
+			dev_dbg(adapter->dev,
+				"info: InterpretIE: ssid: %-32s\n",
+				bss_entry->ssid.ssid);
 			break;
 
 		case WLAN_EID_SUPP_RATES:
@@ -1190,13 +1184,13 @@
 				bss_entry->bcn_wpa_ie =
 					(struct ieee_types_vendor_specific *)
 					current_ptr;
-				bss_entry->wpa_offset = (u16) (current_ptr -
-							bss_entry->beacon_buf);
+				bss_entry->wpa_offset = (u16)
+					(current_ptr - bss_entry->beacon_buf);
 			} else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui,
 				    sizeof(wmm_oui))) {
 				if (total_ie_len ==
-				    sizeof(struct ieee_types_wmm_parameter)
-				    || total_ie_len ==
+				    sizeof(struct ieee_types_wmm_parameter) ||
+				    total_ie_len ==
 				    sizeof(struct ieee_types_wmm_info))
 					/*
 					 * Only accept and copy the WMM IE if
@@ -1317,14 +1311,14 @@
 	}
 
 	scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
-					GFP_KERNEL);
+								GFP_KERNEL);
 	if (!scan_cfg_out) {
 		dev_err(adapter->dev, "failed to alloc scan_cfg_out\n");
 		return -ENOMEM;
 	}
 
 	buf_size = sizeof(struct mwifiex_chan_scan_param_set) *
-			MWIFIEX_USER_SCAN_CHAN_MAX;
+						MWIFIEX_USER_SCAN_CHAN_MAX;
 	scan_chan_list = kzalloc(buf_size, GFP_KERNEL);
 	if (!scan_chan_list) {
 		dev_err(adapter->dev, "failed to alloc scan_chan_list\n");
@@ -1332,10 +1326,9 @@
 		return -ENOMEM;
 	}
 
-	mwifiex_scan_setup_scan_config(priv, user_scan_in,
-				       &scan_cfg_out->config, &chan_list_out,
-				       scan_chan_list, &max_chan_per_scan,
-				       &filtered_scan, &scan_current_chan_only);
+	mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
+			    &chan_list_out, scan_chan_list, &max_chan_per_scan,
+			    &filtered_scan, &scan_current_chan_only);
 
 	ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
 					&scan_cfg_out->config, chan_list_out,
@@ -1346,10 +1339,10 @@
 		spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
 		if (!list_empty(&adapter->scan_pending_q)) {
 			cmd_node = list_first_entry(&adapter->scan_pending_q,
-						struct cmd_ctrl_node, list);
+						    struct cmd_ctrl_node, list);
 			list_del(&cmd_node->list);
 			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-									flags);
+					       flags);
 			adapter->cmd_queued = cmd_node;
 			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
 							true);
@@ -1435,8 +1428,8 @@
 	if (!bss_desc)
 		return -1;
 
-	if ((mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
-			(u8) bss_desc->bss_band, (u16) bss_desc->channel))) {
+	if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
+			     (u16) bss_desc->channel, 0))) {
 		switch (priv->bss_mode) {
 		case NL80211_IFTYPE_STATION:
 		case NL80211_IFTYPE_ADHOC:
@@ -1515,7 +1508,7 @@
 
 	/* Make a copy of current BSSID descriptor */
 	memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
-		sizeof(priv->curr_bss_params.bss_descriptor));
+	       sizeof(priv->curr_bss_params.bss_descriptor));
 	mwifiex_save_curr_bcn(priv);
 	spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
 
@@ -1566,7 +1559,7 @@
 	struct cfg80211_bss *bss;
 
 	is_bgscan_resp = (le16_to_cpu(resp->command)
-		== HostCmd_CMD_802_11_BG_SCAN_QUERY);
+			  == HostCmd_CMD_802_11_BG_SCAN_QUERY);
 	if (is_bgscan_resp)
 		scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
 	else
@@ -1575,20 +1568,20 @@
 
 	if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
 		dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",
-		       scan_rsp->number_of_sets);
+			scan_rsp->number_of_sets);
 		ret = -1;
 		goto done;
 	}
 
 	bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
 	dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n",
-						bytes_left);
+		bytes_left);
 
 	scan_resp_size = le16_to_cpu(resp->size);
 
 	dev_dbg(adapter->dev,
 		"info: SCAN_RESP: returned %d APs before parsing\n",
-	       scan_rsp->number_of_sets);
+		scan_rsp->number_of_sets);
 
 	bss_info = scan_rsp->bss_desc_and_tlv_buffer;
 
@@ -1626,7 +1619,7 @@
 		s32 rssi;
 		const u8 *ie_buf;
 		size_t ie_len;
-		int channel = -1;
+		u16 channel = 0;
 		u64 network_tsf = 0;
 		u16 beacon_size = 0;
 		u32 curr_bcn_bytes;
@@ -1664,7 +1657,8 @@
 		 *   and capability information
 		 */
 		if (curr_bcn_bytes < sizeof(struct mwifiex_bcn_param)) {
-			dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
+			dev_err(adapter->dev,
+				"InterpretIE: not enough bytes left\n");
 			continue;
 		}
 		bcn_param = (struct mwifiex_bcn_param *)current_ptr;
@@ -1674,20 +1668,20 @@
 		memcpy(bssid, bcn_param->bssid, ETH_ALEN);
 
 		rssi = (s32) (bcn_param->rssi);
-		dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n",
-					rssi);
+		dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", rssi);
 
 		beacon_period = le16_to_cpu(bcn_param->beacon_period);
 
 		cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
 		dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
-				cap_info_bitmap);
+			cap_info_bitmap);
 
 		/* Rest of the current buffer are IE's */
 		ie_buf = current_ptr;
 		ie_len = curr_bcn_bytes;
-		dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP"
-				      " = %d\n", curr_bcn_bytes);
+		dev_dbg(adapter->dev,
+			"info: InterpretIE: IELength for this AP = %d\n",
+			curr_bcn_bytes);
 
 		while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
 			u8 element_id, element_len;
@@ -1696,8 +1690,8 @@
 			element_len = *(current_ptr + 1);
 			if (curr_bcn_bytes < element_len +
 					sizeof(struct ieee_types_header)) {
-				dev_err(priv->adapter->dev, "%s: in processing"
-					" IE, bytes left < IE length\n",
+				dev_err(priv->adapter->dev,
+					"%s: bytes left < IE length\n",
 					__func__);
 				goto done;
 			}
@@ -1721,10 +1715,10 @@
 		 */
 		if (tsf_tlv)
 			memcpy(&network_tsf,
-					&tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
-					sizeof(network_tsf));
+			       &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
+			       sizeof(network_tsf));
 
-		if (channel != -1) {
+		if (channel) {
 			struct ieee80211_channel *chan;
 			u8 band;
 
@@ -1737,8 +1731,7 @@
 						& (BIT(0) | BIT(1)));
 			}
 
-			cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(
-						priv, (u8)band, (u16)channel);
+			cfp = mwifiex_get_cfp(priv, band, channel, 0);
 
 			freq = cfp ? cfp->freq : 0;
 
@@ -1752,13 +1745,15 @@
 				*(u8 *)bss->priv = band;
 				cfg80211_put_bss(bss);
 
-				if (priv->media_connected && !memcmp(bssid,
-					priv->curr_bss_params.bss_descriptor
-						     .mac_address, ETH_ALEN))
-					mwifiex_update_curr_bss_params(priv,
-							bssid, rssi, ie_buf,
-							ie_len, beacon_period,
-							cap_info_bitmap, band);
+				if (priv->media_connected &&
+				    !memcmp(bssid,
+					    priv->curr_bss_params.bss_descriptor
+					    .mac_address, ETH_ALEN))
+					mwifiex_update_curr_bss_params
+							(priv, bssid, rssi,
+							 ie_buf, ie_len,
+							 beacon_period,
+							 cap_info_bitmap, band);
 			}
 		} else {
 			dev_dbg(adapter->dev, "missing BSS channel IE\n");
@@ -1785,8 +1780,8 @@
 		}
 
 		if (priv->user_scan_cfg) {
-			dev_dbg(priv->adapter->dev, "info: %s: sending scan "
-							"results\n", __func__);
+			dev_dbg(priv->adapter->dev,
+				"info: %s: sending scan results\n", __func__);
 			cfg80211_scan_done(priv->scan_request, 0);
 			priv->scan_request = NULL;
 			kfree(priv->user_scan_cfg);
@@ -1851,7 +1846,7 @@
  * firmware, filtered on a specific SSID.
  */
 static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
-				      struct mwifiex_802_11_ssid *req_ssid)
+				      struct cfg80211_ssid *req_ssid)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
 	int ret = 0;
@@ -1877,8 +1872,8 @@
 		return -ENOMEM;
 	}
 
-	memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid,
-	       req_ssid->ssid_len);
+	scan_cfg->ssid_list = req_ssid;
+	scan_cfg->num_ssids = 1;
 
 	ret = mwifiex_scan_networks(priv, scan_cfg);
 
@@ -1896,13 +1891,13 @@
  * scan, depending upon whether an SSID is provided or not.
  */
 int mwifiex_request_scan(struct mwifiex_private *priv,
-			 struct mwifiex_802_11_ssid *req_ssid)
+			 struct cfg80211_ssid *req_ssid)
 {
 	int ret;
 
 	if (down_interruptible(&priv->async_sem)) {
 		dev_err(priv->adapter->dev, "%s: acquire semaphore\n",
-						__func__);
+			__func__);
 		return -1;
 	}
 	priv->scan_pending_on_block = true;
@@ -1987,21 +1982,21 @@
 
 	/* allocate beacon buffer at 1st time; or if it's size has changed */
 	if (!priv->curr_bcn_buf ||
-			priv->curr_bcn_size != curr_bss->beacon_buf_size) {
+	    priv->curr_bcn_size != curr_bss->beacon_buf_size) {
 		priv->curr_bcn_size = curr_bss->beacon_buf_size;
 
 		kfree(priv->curr_bcn_buf);
 		priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
-						GFP_ATOMIC);
+					     GFP_ATOMIC);
 		if (!priv->curr_bcn_buf) {
 			dev_err(priv->adapter->dev,
-					"failed to alloc curr_bcn_buf\n");
+				"failed to alloc curr_bcn_buf\n");
 			return;
 		}
 	}
 
 	memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
-		curr_bss->beacon_buf_size);
+	       curr_bss->beacon_buf_size);
 	dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n",
 		priv->curr_bcn_size);
 
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index d39d845..3f597f4 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -67,7 +67,7 @@
 	struct sdio_mmc_card *card = NULL;
 
 	pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
-	       func->vendor, func->device, func->class, func->num);
+		 func->vendor, func->device, func->class, func->num);
 
 	card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
 	if (!card) {
@@ -112,6 +112,7 @@
 {
 	struct sdio_mmc_card *card;
 	struct mwifiex_adapter *adapter;
+	struct mwifiex_private *priv;
 	int i;
 
 	pr_debug("info: SDIO func num=%d\n", func->num);
@@ -131,15 +132,12 @@
 		for (i = 0; i < adapter->priv_num; i++)
 			if ((GET_BSS_ROLE(adapter->priv[i]) ==
 						MWIFIEX_BSS_ROLE_STA) &&
-					adapter->priv[i]->media_connected)
+			    adapter->priv[i]->media_connected)
 				mwifiex_deauthenticate(adapter->priv[i], NULL);
 
-		mwifiex_disable_auto_ds(mwifiex_get_priv(adapter,
-							 MWIFIEX_BSS_ROLE_ANY));
-
-		mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
-						MWIFIEX_BSS_ROLE_ANY),
-					 MWIFIEX_FUNC_SHUTDOWN);
+		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
+		mwifiex_disable_auto_ds(priv);
+		mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
 	}
 
 	mwifiex_remove_card(card->adapter, &add_remove_card_sem);
@@ -169,7 +167,7 @@
 	if (func) {
 		pm_flag = sdio_get_host_pm_caps(func);
 		pr_debug("cmd: %s: suspend: PM flag = 0x%x\n",
-		       sdio_func_id(func), pm_flag);
+			 sdio_func_id(func), pm_flag);
 		if (!(pm_flag & MMC_PM_KEEP_POWER)) {
 			pr_err("%s: cannot remain alive while host is"
 				" suspended\n", sdio_func_id(func));
@@ -363,12 +361,11 @@
 {
 	struct sdio_mmc_card *card = adapter->card;
 	int ret = -1;
-	u8 blk_mode =
-		(port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE;
+	u8 blk_mode = (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE
+		       : BLOCK_MODE;
 	u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1;
-	u32 blk_cnt =
-		(blk_mode ==
-		 BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE) : len;
+	u32 blk_cnt = (blk_mode == BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE)
+			: len;
 	u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK);
 
 	if (claim)
@@ -472,8 +469,7 @@
 			i++;
 			dev_err(adapter->dev, "host_to_card, write iomem"
 					" (%d) failed: %d\n", i, ret);
-			if (mwifiex_write_reg(adapter,
-					CONFIGURATION_REG, 0x04))
+			if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04))
 				dev_err(adapter->dev, "write CFG reg failed\n");
 
 			ret = -1;
@@ -507,11 +503,11 @@
 		card->mp_rd_bitmap &= (u16) (~CTRL_PORT_MASK);
 		*port = CTRL_PORT;
 		dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%04x\n",
-		       *port, card->mp_rd_bitmap);
+			*port, card->mp_rd_bitmap);
 	} else {
 		if (card->mp_rd_bitmap & (1 << card->curr_rd_port)) {
-			card->mp_rd_bitmap &=
-				(u16) (~(1 << card->curr_rd_port));
+			card->mp_rd_bitmap &= (u16)
+						(~(1 << card->curr_rd_port));
 			*port = card->curr_rd_port;
 
 			if (++card->curr_rd_port == MAX_PORT)
@@ -522,7 +518,7 @@
 
 		dev_dbg(adapter->dev,
 			"data: port=%d mp_rd_bitmap=0x%04x -> 0x%04x\n",
-		       *port, rd_bitmap, card->mp_rd_bitmap);
+			*port, rd_bitmap, card->mp_rd_bitmap);
 	}
 	return 0;
 }
@@ -556,14 +552,14 @@
 
 	if (*port == CTRL_PORT) {
 		dev_err(adapter->dev, "invalid data port=%d cur port=%d"
-				" mp_wr_bitmap=0x%04x -> 0x%04x\n",
-				*port, card->curr_wr_port, wr_bitmap,
-				card->mp_wr_bitmap);
+			" mp_wr_bitmap=0x%04x -> 0x%04x\n",
+			*port, card->curr_wr_port, wr_bitmap,
+			card->mp_wr_bitmap);
 		return -1;
 	}
 
 	dev_dbg(adapter->dev, "data: port=%d mp_wr_bitmap=0x%04x -> 0x%04x\n",
-	       *port, wr_bitmap, card->mp_wr_bitmap);
+		*port, wr_bitmap, card->mp_wr_bitmap);
 
 	return 0;
 }
@@ -583,11 +579,11 @@
 		else if ((cs & bits) == bits)
 			return 0;
 
-		udelay(10);
+		usleep_range(10, 20);
 	}
 
-	dev_err(adapter->dev, "poll card status failed, tries = %d\n",
-	       tries);
+	dev_err(adapter->dev, "poll card status failed, tries = %d\n", tries);
+
 	return -1;
 }
 
@@ -670,14 +666,14 @@
 
 	if (ret) {
 		dev_err(adapter->dev, "%s: read iomem failed: %d\n", __func__,
-				ret);
+			ret);
 		return -1;
 	}
 
 	nb = le16_to_cpu(*(__le16 *) (buffer));
 	if (nb > npayload) {
-		dev_err(adapter->dev, "%s: invalid packet, nb=%d, npayload=%d\n",
-				__func__, nb, npayload);
+		dev_err(adapter->dev, "%s: invalid packet, nb=%d npayload=%d\n",
+			__func__, nb, npayload);
 		return -1;
 	}
 
@@ -707,19 +703,19 @@
 	u32 i = 0;
 
 	if (!firmware_len) {
-		dev_err(adapter->dev, "firmware image not found!"
-				" Terminating download\n");
+		dev_err(adapter->dev,
+			"firmware image not found! Terminating download\n");
 		return -1;
 	}
 
 	dev_dbg(adapter->dev, "info: downloading FW image (%d bytes)\n",
-			firmware_len);
+		firmware_len);
 
 	/* Assume that the allocated buffer is 8-byte aligned */
 	fwbuf = kzalloc(MWIFIEX_UPLD_SIZE, GFP_KERNEL);
 	if (!fwbuf) {
-		dev_err(adapter->dev, "unable to alloc buffer for firmware."
-				" Terminating download\n");
+		dev_err(adapter->dev,
+			"unable to alloc buffer for FW. Terminating dnld\n");
 		return -ENOMEM;
 	}
 
@@ -731,7 +727,7 @@
 						    DN_LD_CARD_RDY);
 		if (ret) {
 			dev_err(adapter->dev, "FW download with helper:"
-					" poll status timeout @ %d\n", offset);
+				" poll status timeout @ %d\n", offset);
 			goto done;
 		}
 
@@ -743,17 +739,19 @@
 			ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_0,
 					       &base0);
 			if (ret) {
-				dev_err(adapter->dev, "dev BASE0 register read"
-					" failed: base0=0x%04X(%d). Terminating "
-				       "download\n", base0, base0);
+				dev_err(adapter->dev,
+					"dev BASE0 register read failed: "
+					"base0=%#04X(%d). Terminating dnld\n",
+					base0, base0);
 				goto done;
 			}
 			ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_1,
 					       &base1);
 			if (ret) {
-				dev_err(adapter->dev, "dev BASE1 register read"
-					" failed: base1=0x%04X(%d). Terminating "
-				       "download\n", base1, base1);
+				dev_err(adapter->dev,
+					"dev BASE1 register read failed: "
+					"base1=%#04X(%d). Terminating dnld\n",
+					base1, base1);
 				goto done;
 			}
 			len = (u16) (((base1 & 0xff) << 8) | (base0 & 0xff));
@@ -761,14 +759,15 @@
 			if (len)
 				break;
 
-			udelay(10);
+			usleep_range(10, 20);
 		}
 
 		if (!len) {
 			break;
 		} else if (len > MWIFIEX_UPLD_SIZE) {
-			dev_err(adapter->dev, "FW download failed @ %d,"
-				" invalid length %d\n", offset, len);
+			dev_err(adapter->dev,
+				"FW dnld failed @ %d, invalid length %d\n",
+				offset, len);
 			ret = -1;
 			goto done;
 		}
@@ -778,13 +777,14 @@
 		if (len & BIT(0)) {
 			i++;
 			if (i > MAX_WRITE_IOMEM_RETRY) {
-				dev_err(adapter->dev, "FW download failed @"
-					" %d, over max retry count\n", offset);
+				dev_err(adapter->dev,
+					"FW dnld failed @ %d, over max retry\n",
+					offset);
 				ret = -1;
 				goto done;
 			}
 			dev_err(adapter->dev, "CRC indicated by the helper:"
-			       " len = 0x%04X, txlen = %d\n", len, txlen);
+				" len = 0x%04X, txlen = %d\n", len, txlen);
 			len &= ~BIT(0);
 			/* Setting this to 0 to resend from same offset */
 			txlen = 0;
@@ -796,8 +796,8 @@
 			if (firmware_len - offset < txlen)
 				txlen = firmware_len - offset;
 
-			tx_blocks = (txlen + MWIFIEX_SDIO_BLOCK_SIZE -
-					1) / MWIFIEX_SDIO_BLOCK_SIZE;
+			tx_blocks = (txlen + MWIFIEX_SDIO_BLOCK_SIZE - 1)
+				    / MWIFIEX_SDIO_BLOCK_SIZE;
 
 			/* Copy payload to buffer */
 			memmove(fwbuf, &firmware[offset], txlen);
@@ -807,8 +807,9 @@
 					      MWIFIEX_SDIO_BLOCK_SIZE,
 					      adapter->ioport);
 		if (ret) {
-			dev_err(adapter->dev, "FW download, write iomem (%d)"
-					" failed @ %d\n", i, offset);
+			dev_err(adapter->dev,
+				"FW download, write iomem (%d) failed @ %d\n",
+				i, offset);
 			if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04))
 				dev_err(adapter->dev, "write CFG reg failed\n");
 
@@ -820,7 +821,7 @@
 	} while (true);
 
 	dev_dbg(adapter->dev, "info: FW download over, size %d bytes\n",
-						offset);
+		offset);
 
 	ret = 0;
 done:
@@ -912,7 +913,7 @@
 	card = sdio_get_drvdata(func);
 	if (!card || !card->adapter) {
 		pr_debug("int: func=%p card=%p adapter=%p\n",
-		       func, card, card ? card->adapter : NULL);
+			 func, card, card ? card->adapter : NULL);
 		return;
 	}
 	adapter = card->adapter;
@@ -955,10 +956,12 @@
 
 			if (adapter->ps_state == PS_STATE_SLEEP_CFM)
 				mwifiex_process_sleep_confirm_resp(adapter,
-							skb->data, skb->len);
+								   skb->data,
+								   skb->len);
 
-			memcpy(cmd_buf, skb->data, min_t(u32,
-				       MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
+			memcpy(cmd_buf, skb->data,
+			       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER,
+				     skb->len));
 
 			dev_kfree_skb_any(skb);
 		} else {
@@ -1016,7 +1019,7 @@
 	if (port == CTRL_PORT) {
 		/* Read the command Resp without aggr */
 		dev_dbg(adapter->dev, "info: %s: no aggregation for cmd "
-				"response\n", __func__);
+			"response\n", __func__);
 
 		f_do_rx_cur = 1;
 		goto rx_curr_single;
@@ -1024,7 +1027,7 @@
 
 	if (!card->mpa_rx.enabled) {
 		dev_dbg(adapter->dev, "info: %s: rx aggregation disabled\n",
-						__func__);
+			__func__);
 
 		f_do_rx_cur = 1;
 		goto rx_curr_single;
@@ -1071,7 +1074,7 @@
 		if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) ||
 		    MP_RX_AGGR_PORT_LIMIT_REACHED(card)) {
 			dev_dbg(adapter->dev, "info: %s: aggregated packet "
-					"limit reached\n", __func__);
+				"limit reached\n", __func__);
 			/* No more pkts allowed in Aggr buf, rx it */
 			f_do_rx_aggr = 1;
 		}
@@ -1080,7 +1083,7 @@
 	if (f_do_rx_aggr) {
 		/* do aggr RX now */
 		dev_dbg(adapter->dev, "info: do_rx_aggr: num of packets: %d\n",
-		       card->mpa_rx.pkt_cnt);
+			card->mpa_rx.pkt_cnt);
 
 		if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf,
 					   card->mpa_rx.buf_len,
@@ -1194,7 +1197,7 @@
 		card->mp_wr_bitmap = ((u16) card->mp_regs[WR_BITMAP_U]) << 8;
 		card->mp_wr_bitmap |= (u16) card->mp_regs[WR_BITMAP_L];
 		dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%04x\n",
-				card->mp_wr_bitmap);
+			card->mp_wr_bitmap);
 		if (adapter->data_sent &&
 		    (card->mp_wr_bitmap & card->mp_data_port_mask)) {
 			dev_dbg(adapter->dev,
@@ -1216,12 +1219,12 @@
 	}
 
 	dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
-	       adapter->cmd_sent, adapter->data_sent);
+		adapter->cmd_sent, adapter->data_sent);
 	if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
 		card->mp_rd_bitmap = ((u16) card->mp_regs[RD_BITMAP_U]) << 8;
 		card->mp_rd_bitmap |= (u16) card->mp_regs[RD_BITMAP_L];
 		dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%04x\n",
-				card->mp_rd_bitmap);
+			card->mp_rd_bitmap);
 
 		while (true) {
 			ret = mwifiex_get_rd_port(adapter, &port);
@@ -1235,15 +1238,15 @@
 			rx_len = ((u16) card->mp_regs[len_reg_u]) << 8;
 			rx_len |= (u16) card->mp_regs[len_reg_l];
 			dev_dbg(adapter->dev, "info: RX: port=%d rx_len=%u\n",
-					port, rx_len);
+				port, rx_len);
 			rx_blocks =
 				(rx_len + MWIFIEX_SDIO_BLOCK_SIZE -
 				 1) / MWIFIEX_SDIO_BLOCK_SIZE;
-			if (rx_len <= INTF_HEADER_LEN
-			    || (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
-			    MWIFIEX_RX_DATA_BUF_SIZE) {
+			if (rx_len <= INTF_HEADER_LEN ||
+			    (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
+			     MWIFIEX_RX_DATA_BUF_SIZE) {
 				dev_err(adapter->dev, "invalid rx_len=%d\n",
-						rx_len);
+					rx_len);
 				return -1;
 			}
 			rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE);
@@ -1252,42 +1255,42 @@
 
 			if (!skb) {
 				dev_err(adapter->dev, "%s: failed to alloc skb",
-								__func__);
+					__func__);
 				return -1;
 			}
 
 			skb_put(skb, rx_len);
 
 			dev_dbg(adapter->dev, "info: rx_len = %d skb->len = %d\n",
-					rx_len, skb->len);
+				rx_len, skb->len);
 
 			if (mwifiex_sdio_card_to_host_mp_aggr(adapter, skb,
 							      port)) {
 				u32 cr = 0;
 
 				dev_err(adapter->dev, "card_to_host_mpa failed:"
-						" int status=%#x\n", sdio_ireg);
+					" int status=%#x\n", sdio_ireg);
 				if (mwifiex_read_reg(adapter,
 						     CONFIGURATION_REG, &cr))
 					dev_err(adapter->dev,
-							"read CFG reg failed\n");
+						"read CFG reg failed\n");
 
 				dev_dbg(adapter->dev,
-						"info: CFG reg val = %d\n", cr);
+					"info: CFG reg val = %d\n", cr);
 				if (mwifiex_write_reg(adapter,
 						      CONFIGURATION_REG,
 						      (cr | 0x04)))
 					dev_err(adapter->dev,
-							"write CFG reg failed\n");
+						"write CFG reg failed\n");
 
 				dev_dbg(adapter->dev, "info: write success\n");
 				if (mwifiex_read_reg(adapter,
 						     CONFIGURATION_REG, &cr))
 					dev_err(adapter->dev,
-							"read CFG reg failed\n");
+						"read CFG reg failed\n");
 
 				dev_dbg(adapter->dev,
-						"info: CFG reg val =%x\n", cr);
+					"info: CFG reg val =%x\n", cr);
 				return -1;
 			}
 		}
@@ -1323,7 +1326,7 @@
 
 	if ((!card->mpa_tx.enabled) || (port == CTRL_PORT)) {
 		dev_dbg(adapter->dev, "info: %s: tx aggregation disabled\n",
-						__func__);
+			__func__);
 
 		f_send_cur_buf = 1;
 		goto tx_curr_single;
@@ -1332,7 +1335,7 @@
 	if (next_pkt_len) {
 		/* More pkt in TX queue */
 		dev_dbg(adapter->dev, "info: %s: more packets in queue.\n",
-						__func__);
+			__func__);
 
 		if (MP_TX_AGGR_IN_PROGRESS(card)) {
 			if (!MP_TX_AGGR_PORT_LIMIT_REACHED(card) &&
@@ -1340,9 +1343,9 @@
 				f_precopy_cur_buf = 1;
 
 				if (!(card->mp_wr_bitmap &
-						(1 << card->curr_wr_port))
-						|| !MP_TX_AGGR_BUF_HAS_ROOM(
-						card, pkt_len + next_pkt_len))
+				      (1 << card->curr_wr_port)) ||
+				    !MP_TX_AGGR_BUF_HAS_ROOM(
+					    card, pkt_len + next_pkt_len))
 					f_send_aggr_buf = 1;
 			} else {
 				/* No room in Aggr buf, send it */
@@ -1356,8 +1359,8 @@
 					f_postcopy_cur_buf = 1;
 			}
 		} else {
-			if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)
-			    && (card->mp_wr_bitmap & (1 << card->curr_wr_port)))
+			if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len) &&
+			    (card->mp_wr_bitmap & (1 << card->curr_wr_port)))
 				f_precopy_cur_buf = 1;
 			else
 				f_send_cur_buf = 1;
@@ -1365,7 +1368,7 @@
 	} else {
 		/* Last pkt in TX queue */
 		dev_dbg(adapter->dev, "info: %s: Last packet in Tx Queue.\n",
-						__func__);
+			__func__);
 
 		if (MP_TX_AGGR_IN_PROGRESS(card)) {
 			/* some packs in Aggr buf already */
@@ -1383,7 +1386,7 @@
 
 	if (f_precopy_cur_buf) {
 		dev_dbg(adapter->dev, "data: %s: precopy current buffer\n",
-						__func__);
+			__func__);
 		MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
 
 		if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) ||
@@ -1394,7 +1397,7 @@
 
 	if (f_send_aggr_buf) {
 		dev_dbg(adapter->dev, "data: %s: send aggr buffer: %d %d\n",
-				__func__,
+			__func__,
 				card->mpa_tx.start_port, card->mpa_tx.ports);
 		ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf,
 						 card->mpa_tx.buf_len,
@@ -1408,14 +1411,14 @@
 tx_curr_single:
 	if (f_send_cur_buf) {
 		dev_dbg(adapter->dev, "data: %s: send current buffer %d\n",
-						__func__, port);
+			__func__, port);
 		ret = mwifiex_write_data_to_card(adapter, payload, pkt_len,
 						 adapter->ioport + port);
 	}
 
 	if (f_postcopy_cur_buf) {
 		dev_dbg(adapter->dev, "data: %s: postcopy current buffer\n",
-						__func__);
+			__func__);
 		MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
 	}
 
@@ -1460,7 +1463,7 @@
 		ret = mwifiex_get_wr_port_data(adapter, &port);
 		if (ret) {
 			dev_err(adapter->dev, "%s: no wr_port available\n",
-						__func__);
+				__func__);
 			return ret;
 		}
 	} else {
@@ -1470,7 +1473,7 @@
 		if (pkt_len <= INTF_HEADER_LEN ||
 		    pkt_len > MWIFIEX_UPLD_SIZE)
 			dev_err(adapter->dev, "%s: payload=%p, nb=%d\n",
-					__func__, payload, pkt_len);
+				__func__, payload, pkt_len);
 	}
 
 	/* Transfer data to card */
@@ -1478,10 +1481,11 @@
 
 	if (tx_param)
 		ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len,
-				port, tx_param->next_pkt_len);
+						   port, tx_param->next_pkt_len
+						   );
 	else
 		ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len,
-				port, 0);
+						   port, 0);
 
 	if (ret) {
 		if (type == MWIFIEX_TYPE_CMD)
@@ -1734,7 +1738,7 @@
 	card->curr_wr_port = 1;
 
 	dev_dbg(adapter->dev, "cmd: mp_end_port %d, data port mask 0x%x\n",
-	       port, card->mp_data_port_mask);
+		port, card->mp_data_port_mask);
 }
 
 static struct mwifiex_if_ops sdio_ops = {
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 324c651..6c8e459 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -110,7 +110,7 @@
 	dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
 	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib)
-		- 1 + S_DS_GEN);
+				- 1 + S_DS_GEN);
 
 	snmp_mib->oid = cpu_to_le16((u16)cmd_oid);
 	if (cmd_action == HostCmd_ACT_GEN_GET) {
@@ -127,8 +127,8 @@
 	dev_dbg(priv->adapter->dev,
 		"cmd: SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x,"
 		" Value=0x%x\n",
-	       cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size),
-	       le16_to_cpu(*(__le16 *) snmp_mib->value));
+		cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size),
+		le16_to_cpu(*(__le16 *) snmp_mib->value));
 	return 0;
 }
 
@@ -174,8 +174,8 @@
 	rate_scope = (struct mwifiex_rate_scope *) ((u8 *) rate_cfg +
 		      sizeof(struct host_cmd_ds_tx_rate_cfg));
 	rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE);
-	rate_scope->length = cpu_to_le16(sizeof(struct mwifiex_rate_scope) -
-			sizeof(struct mwifiex_ie_types_header));
+	rate_scope->length = cpu_to_le16
+		(sizeof(*rate_scope) - sizeof(struct mwifiex_ie_types_header));
 	if (pbitmap_rates != NULL) {
 		rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]);
 		rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]);
@@ -197,7 +197,7 @@
 	}
 
 	rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope +
-			sizeof(struct mwifiex_rate_scope));
+					     sizeof(struct mwifiex_rate_scope));
 	rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL);
 	rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode));
 	rate_drop->rate_drop_mode = 0;
@@ -284,22 +284,22 @@
 	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
 
 	if (!hs_activate &&
-	    (hscfg_param->conditions
-	    != cpu_to_le32(HOST_SLEEP_CFG_CANCEL))
-	    && ((adapter->arp_filter_size > 0)
-		&& (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
+	    (hscfg_param->conditions != cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) &&
+	    ((adapter->arp_filter_size > 0) &&
+	     (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
 		dev_dbg(adapter->dev,
 			"cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
-		       adapter->arp_filter_size);
+			adapter->arp_filter_size);
 		memcpy(((u8 *) hs_cfg) +
 		       sizeof(struct host_cmd_ds_802_11_hs_cfg_enh),
 		       adapter->arp_filter, adapter->arp_filter_size);
-		cmd->size = cpu_to_le16(adapter->arp_filter_size +
-				    sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
-				    + S_DS_GEN);
+		cmd->size = cpu_to_le16
+				(adapter->arp_filter_size +
+				 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
+				+ S_DS_GEN);
 	} else {
 		cmd->size = cpu_to_le16(S_DS_GEN + sizeof(struct
-					   host_cmd_ds_802_11_hs_cfg_enh));
+						host_cmd_ds_802_11_hs_cfg_enh));
 	}
 	if (hs_activate) {
 		hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
@@ -467,7 +467,7 @@
 			key_param_set =
 				(struct mwifiex_ie_type_key_param_set *)
 						((u8 *)key_param_set +
-						cur_key_param_len);
+						 cur_key_param_len);
 		} else if (!priv->wep_key[i].key_length) {
 			continue;
 		} else {
@@ -527,13 +527,13 @@
 	if (enc_key->is_wapi_key) {
 		dev_dbg(priv->adapter->dev, "info: Set WAPI Key\n");
 		key_material->key_param_set.key_type_id =
-			cpu_to_le16(KEY_TYPE_ID_WAPI);
+						cpu_to_le16(KEY_TYPE_ID_WAPI);
 		if (cmd_oid == KEY_INFO_ENABLED)
 			key_material->key_param_set.key_info =
-				cpu_to_le16(KEY_ENABLED);
+						cpu_to_le16(KEY_ENABLED);
 		else
 			key_material->key_param_set.key_info =
-				cpu_to_le16(!KEY_ENABLED);
+						cpu_to_le16(!KEY_ENABLED);
 
 		key_material->key_param_set.key[0] = enc_key->key_index;
 		if (!priv->sec_info.wapi_key_on)
@@ -553,9 +553,9 @@
 		}
 
 		key_material->key_param_set.type =
-			cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
+					cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
 		key_material->key_param_set.key_len =
-			cpu_to_le16(WAPI_KEY_LEN);
+						cpu_to_le16(WAPI_KEY_LEN);
 		memcpy(&key_material->key_param_set.key[2],
 		       enc_key->key_material, enc_key->key_len);
 		memcpy(&key_material->key_param_set.key[2 + enc_key->key_len],
@@ -565,49 +565,49 @@
 
 		key_param_len = (WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN) +
 				 sizeof(struct mwifiex_ie_types_header);
-		cmd->size = cpu_to_le16(key_param_len +
-				sizeof(key_material->action) + S_DS_GEN);
+		cmd->size = cpu_to_le16(sizeof(key_material->action)
+					+ S_DS_GEN +  key_param_len);
 		return ret;
 	}
 	if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
 		dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n");
 		key_material->key_param_set.key_type_id =
-			cpu_to_le16(KEY_TYPE_ID_AES);
+						cpu_to_le16(KEY_TYPE_ID_AES);
 		if (cmd_oid == KEY_INFO_ENABLED)
 			key_material->key_param_set.key_info =
-				cpu_to_le16(KEY_ENABLED);
+						cpu_to_le16(KEY_ENABLED);
 		else
 			key_material->key_param_set.key_info =
-				cpu_to_le16(!KEY_ENABLED);
+						cpu_to_le16(!KEY_ENABLED);
 
 		if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
 				/* AES pairwise key: unicast */
 			key_material->key_param_set.key_info |=
-				cpu_to_le16(KEY_UNICAST);
+						cpu_to_le16(KEY_UNICAST);
 		else		/* AES group key: multicast */
 			key_material->key_param_set.key_info |=
-				cpu_to_le16(KEY_MCAST);
+							cpu_to_le16(KEY_MCAST);
 	} else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
 		dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n");
 		key_material->key_param_set.key_type_id =
-			cpu_to_le16(KEY_TYPE_ID_TKIP);
+						cpu_to_le16(KEY_TYPE_ID_TKIP);
 		key_material->key_param_set.key_info =
-			cpu_to_le16(KEY_ENABLED);
+						cpu_to_le16(KEY_ENABLED);
 
 		if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
 				/* TKIP pairwise key: unicast */
 			key_material->key_param_set.key_info |=
-				cpu_to_le16(KEY_UNICAST);
+						cpu_to_le16(KEY_UNICAST);
 		else		/* TKIP group key: multicast */
 			key_material->key_param_set.key_info |=
-				cpu_to_le16(KEY_MCAST);
+							cpu_to_le16(KEY_MCAST);
 	}
 
 	if (key_material->key_param_set.key_type_id) {
 		key_material->key_param_set.type =
-			cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
+					cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
 		key_material->key_param_set.key_len =
-			cpu_to_le16((u16) enc_key->key_len);
+					cpu_to_le16((u16) enc_key->key_len);
 		memcpy(key_material->key_param_set.key, enc_key->key_material,
 		       enc_key->key_len);
 		key_material->key_param_set.length =
@@ -615,10 +615,10 @@
 				    KEYPARAMSET_FIXED_LEN);
 
 		key_param_len = (u16) (enc_key->key_len + KEYPARAMSET_FIXED_LEN)
-				      + sizeof(struct mwifiex_ie_types_header);
+				+ sizeof(struct mwifiex_ie_types_header);
 
-		cmd->size = cpu_to_le16(key_param_len +
-				    sizeof(key_material->action) + S_DS_GEN);
+		cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN
+					+ key_param_len);
 	}
 
 	return ret;
@@ -655,21 +655,22 @@
 	/* Set domain info fields */
 	domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY);
 	memcpy(domain->country_code, adapter->domain_reg.country_code,
-			sizeof(domain->country_code));
+	       sizeof(domain->country_code));
 
-	domain->header.len = cpu_to_le16((no_of_triplet *
-				sizeof(struct ieee80211_country_ie_triplet)) +
-				sizeof(domain->country_code));
+	domain->header.len =
+		cpu_to_le16((no_of_triplet *
+			     sizeof(struct ieee80211_country_ie_triplet))
+			    + sizeof(domain->country_code));
 
 	if (no_of_triplet) {
 		memcpy(domain->triplet, adapter->domain_reg.triplet,
-				no_of_triplet *
-				sizeof(struct ieee80211_country_ie_triplet));
+		       no_of_triplet * sizeof(struct
+					      ieee80211_country_ie_triplet));
 
 		cmd->size = cpu_to_le16(sizeof(domain_info->action) +
-				le16_to_cpu(domain->header.len) +
-				sizeof(struct mwifiex_ie_types_header)
-				+ S_DS_GEN);
+					le16_to_cpu(domain->header.len) +
+					sizeof(struct mwifiex_ie_types_header)
+					+ S_DS_GEN);
 	} else {
 		cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN);
 	}
@@ -698,8 +699,8 @@
 				+ S_DS_GEN);
 
 	if (cmd_action == HostCmd_ACT_GEN_SET) {
-		if ((priv->adapter->adhoc_start_band & BAND_A)
-		    || (priv->adapter->adhoc_start_band & BAND_AN))
+		if ((priv->adapter->adhoc_start_band & BAND_A) ||
+		    (priv->adapter->adhoc_start_band & BAND_AN))
 			rf_chan->rf_type =
 				cpu_to_le16(HostCmd_SCAN_RADIO_TYPE_A);
 
@@ -777,7 +778,7 @@
 
 		cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN);
 		mac_reg = (struct host_cmd_ds_mac_reg_access *) &cmd->
-			params.mac_reg;
+								params.mac_reg;
 		mac_reg->action = cpu_to_le16(cmd_action);
 		mac_reg->offset =
 			cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
@@ -789,8 +790,8 @@
 		struct host_cmd_ds_bbp_reg_access *bbp_reg;
 
 		cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN);
-		bbp_reg = (struct host_cmd_ds_bbp_reg_access *) &cmd->
-			params.bbp_reg;
+		bbp_reg = (struct host_cmd_ds_bbp_reg_access *)
+							&cmd->params.bbp_reg;
 		bbp_reg->action = cpu_to_le16(cmd_action);
 		bbp_reg->offset =
 			cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
@@ -802,11 +803,10 @@
 		struct host_cmd_ds_rf_reg_access *rf_reg;
 
 		cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN);
-		rf_reg = (struct host_cmd_ds_rf_reg_access *) &cmd->
-			params.rf_reg;
+		rf_reg = (struct host_cmd_ds_rf_reg_access *)
+							&cmd->params.rf_reg;
 		rf_reg->action = cpu_to_le16(cmd_action);
-		rf_reg->offset =
-			cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
+		rf_reg->offset = cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
 		rf_reg->value = (u8) le32_to_cpu(reg_rw->value);
 		break;
 	}
@@ -819,7 +819,7 @@
 				params.pmic_reg;
 		pmic_reg->action = cpu_to_le16(cmd_action);
 		pmic_reg->offset =
-			cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
+				cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
 		pmic_reg->value = (u8) le32_to_cpu(reg_rw->value);
 		break;
 	}
@@ -828,11 +828,11 @@
 		struct host_cmd_ds_rf_reg_access *cau_reg;
 
 		cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN);
-		cau_reg = (struct host_cmd_ds_rf_reg_access *) &cmd->
-				params.rf_reg;
+		cau_reg = (struct host_cmd_ds_rf_reg_access *)
+							&cmd->params.rf_reg;
 		cau_reg->action = cpu_to_le16(cmd_action);
 		cau_reg->offset =
-			cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
+				cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
 		cau_reg->value = (u8) le32_to_cpu(reg_rw->value);
 		break;
 	}
@@ -868,7 +868,7 @@
  */
 static int
 mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv,
-				   struct host_cmd_ds_command *cmd, u16 action)
+			   struct host_cmd_ds_command *cmd, u16 action)
 {
 	struct host_cmd_ds_pcie_details *host_spec =
 					&cmd->params.pcie_host_spec;
@@ -882,29 +882,25 @@
 
 	memset(host_spec, 0, sizeof(struct host_cmd_ds_pcie_details));
 
-	if (action == HostCmd_ACT_GEN_SET) {
-		/* Send the ring base addresses and count to firmware */
-		host_spec->txbd_addr_lo = (u32)(card->txbd_ring_pbase);
-		host_spec->txbd_addr_hi =
-				(u32)(((u64)card->txbd_ring_pbase)>>32);
-		host_spec->txbd_count = MWIFIEX_MAX_TXRX_BD;
-		host_spec->rxbd_addr_lo = (u32)(card->rxbd_ring_pbase);
-		host_spec->rxbd_addr_hi =
-				(u32)(((u64)card->rxbd_ring_pbase)>>32);
-		host_spec->rxbd_count = MWIFIEX_MAX_TXRX_BD;
-		host_spec->evtbd_addr_lo =
-				(u32)(card->evtbd_ring_pbase);
-		host_spec->evtbd_addr_hi =
-				(u32)(((u64)card->evtbd_ring_pbase)>>32);
-		host_spec->evtbd_count = MWIFIEX_MAX_EVT_BD;
-		if (card->sleep_cookie) {
-			buf_pa = MWIFIEX_SKB_PACB(card->sleep_cookie);
-			host_spec->sleep_cookie_addr_lo = (u32) *buf_pa;
-			host_spec->sleep_cookie_addr_hi =
-						(u32) (((u64)*buf_pa) >> 32);
-			dev_dbg(priv->adapter->dev, "sleep_cook_lo phy addr: "
-				 "0x%x\n", host_spec->sleep_cookie_addr_lo);
-		}
+	if (action != HostCmd_ACT_GEN_SET)
+		return 0;
+
+	/* Send the ring base addresses and count to firmware */
+	host_spec->txbd_addr_lo = (u32)(card->txbd_ring_pbase);
+	host_spec->txbd_addr_hi = (u32)(((u64)card->txbd_ring_pbase)>>32);
+	host_spec->txbd_count = MWIFIEX_MAX_TXRX_BD;
+	host_spec->rxbd_addr_lo = (u32)(card->rxbd_ring_pbase);
+	host_spec->rxbd_addr_hi = (u32)(((u64)card->rxbd_ring_pbase)>>32);
+	host_spec->rxbd_count = MWIFIEX_MAX_TXRX_BD;
+	host_spec->evtbd_addr_lo = (u32)(card->evtbd_ring_pbase);
+	host_spec->evtbd_addr_hi = (u32)(((u64)card->evtbd_ring_pbase)>>32);
+	host_spec->evtbd_count = MWIFIEX_MAX_EVT_BD;
+	if (card->sleep_cookie) {
+		buf_pa = MWIFIEX_SKB_PACB(card->sleep_cookie);
+		host_spec->sleep_cookie_addr_lo = (u32) *buf_pa;
+		host_spec->sleep_cookie_addr_hi = (u32) (((u64)*buf_pa) >> 32);
+		dev_dbg(priv->adapter->dev, "sleep_cook_lo phy addr: 0x%x\n",
+			host_spec->sleep_cookie_addr_lo);
 	}
 
 	return 0;
@@ -1036,12 +1032,12 @@
 		break;
 	case HostCmd_CMD_802_11_KEY_MATERIAL:
 		ret = mwifiex_cmd_802_11_key_material(priv, cmd_ptr,
-						cmd_action, cmd_oid,
-						data_buf);
+						      cmd_action, cmd_oid,
+						      data_buf);
 		break;
 	case HostCmd_CMD_802_11D_DOMAIN_INFO:
 		ret = mwifiex_cmd_802_11d_domain_info(priv, cmd_ptr,
-						cmd_action);
+						      cmd_action);
 		break;
 	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
 		ret = mwifiex_cmd_recfg_tx_buf(priv, cmd_ptr, cmd_action,
@@ -1052,8 +1048,7 @@
 						  data_buf);
 		break;
 	case HostCmd_CMD_11N_CFG:
-		ret = mwifiex_cmd_11n_cfg(cmd_ptr, cmd_action,
-					  data_buf);
+		ret = mwifiex_cmd_11n_cfg(cmd_ptr, cmd_action, data_buf);
 		break;
 	case HostCmd_CMD_WMM_GET_STATUS:
 		dev_dbg(priv->adapter->dev,
@@ -1131,8 +1126,8 @@
 	if (first_sta) {
 		if (priv->adapter->iface_type == MWIFIEX_PCIE) {
 			ret = mwifiex_send_cmd_async(priv,
-					HostCmd_CMD_PCIE_DESC_DETAILS,
-					HostCmd_ACT_GEN_SET, 0, NULL);
+						HostCmd_CMD_PCIE_DESC_DETAILS,
+						HostCmd_ACT_GEN_SET, 0, NULL);
 			if (ret)
 				return -1;
 		}
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 0d8618a..4da19ed 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -49,7 +49,7 @@
 	unsigned long flags;
 
 	dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n",
-			resp->command, resp->result);
+		resp->command, resp->result);
 
 	if (adapter->curr_cmd->wait_q_enabled)
 		adapter->cmd_wait_q.status = -1;
@@ -57,13 +57,13 @@
 	switch (le16_to_cpu(resp->command)) {
 	case HostCmd_CMD_802_11_PS_MODE_ENH:
 		pm = &resp->params.psmode_enh;
-		dev_err(adapter->dev, "PS_MODE_ENH cmd failed: "
-					"result=0x%x action=0x%X\n",
-				resp->result, le16_to_cpu(pm->action));
+		dev_err(adapter->dev,
+			"PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n",
+			resp->result, le16_to_cpu(pm->action));
 		/* We do not re-try enter-ps command in ad-hoc mode. */
 		if (le16_to_cpu(pm->action) == EN_AUTO_PS &&
-			(le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) &&
-				priv->bss_mode == NL80211_IFTYPE_ADHOC)
+		    (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) &&
+		    priv->bss_mode == NL80211_IFTYPE_ADHOC)
 			adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
 
 		break;
@@ -123,7 +123,7 @@
 					struct mwifiex_ds_get_signal *signal)
 {
 	struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
-		&resp->params.rssi_info_rsp;
+						&resp->params.rssi_info_rsp;
 
 	priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
 	priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
@@ -191,8 +191,8 @@
 	u32 ul_temp;
 
 	dev_dbg(priv->adapter->dev, "info: SNMP_RESP: oid value = %#x,"
-			" query_type = %#x, buf size = %#x\n",
-			oid, query_type, le16_to_cpu(smib->buf_size));
+		" query_type = %#x, buf size = %#x\n",
+		oid, query_type, le16_to_cpu(smib->buf_size));
 	if (query_type == HostCmd_ACT_GEN_GET) {
 		ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
 		if (data_buf)
@@ -327,31 +327,26 @@
 					  HostCmd_CMD_802_11_TX_RATE_QUERY,
 					  HostCmd_ACT_GEN_GET, 0, NULL);
 
-	if (ds_rate) {
-		if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {
-			if (priv->is_data_rate_auto) {
-				ds_rate->is_rate_auto = 1;
-			} else {
-				ds_rate->rate = mwifiex_get_rate_index(priv->
-							       bitmap_rates,
-							       sizeof(priv->
-							       bitmap_rates));
-				if (ds_rate->rate >=
-				    MWIFIEX_RATE_BITMAP_OFDM0
-				    && ds_rate->rate <=
-				    MWIFIEX_RATE_BITMAP_OFDM7)
-					ds_rate->rate -=
-						(MWIFIEX_RATE_BITMAP_OFDM0 -
-						 MWIFIEX_RATE_INDEX_OFDM0);
-				if (ds_rate->rate >=
-				    MWIFIEX_RATE_BITMAP_MCS0
-				    && ds_rate->rate <=
-				    MWIFIEX_RATE_BITMAP_MCS127)
-					ds_rate->rate -=
-						(MWIFIEX_RATE_BITMAP_MCS0 -
-						 MWIFIEX_RATE_INDEX_MCS0);
-			}
-		}
+	if (!ds_rate)
+		return ret;
+
+	if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {
+		if (priv->is_data_rate_auto) {
+			ds_rate->is_rate_auto = 1;
+		return ret;
+	}
+	ds_rate->rate = mwifiex_get_rate_index(priv->bitmap_rates,
+					       sizeof(priv->bitmap_rates));
+
+	if (ds_rate->rate >= MWIFIEX_RATE_BITMAP_OFDM0 &&
+	    ds_rate->rate <= MWIFIEX_RATE_BITMAP_OFDM7)
+		ds_rate->rate -= (MWIFIEX_RATE_BITMAP_OFDM0 -
+				  MWIFIEX_RATE_INDEX_OFDM0);
+
+	if (ds_rate->rate >= MWIFIEX_RATE_BITMAP_MCS0 &&
+	    ds_rate->rate <= MWIFIEX_RATE_BITMAP_MCS127)
+		ds_rate->rate -= (MWIFIEX_RATE_BITMAP_MCS0 -
+				  MWIFIEX_RATE_INDEX_MCS0);
 	}
 
 	return ret;
@@ -369,34 +364,32 @@
 	struct mwifiex_types_power_group *pg_tlv_hdr;
 	struct mwifiex_power_group *pg;
 
-	if (data_buf) {
-		pg_tlv_hdr =
-			(struct mwifiex_types_power_group *) ((u8 *) data_buf
-					+ sizeof(struct host_cmd_ds_txpwr_cfg));
-		pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr +
-				sizeof(struct mwifiex_types_power_group));
-		length = pg_tlv_hdr->length;
-		if (length > 0) {
-			max_power = pg->power_max;
-			min_power = pg->power_min;
-			length -= sizeof(struct mwifiex_power_group);
-		}
-		while (length) {
-			pg++;
-			if (max_power < pg->power_max)
-				max_power = pg->power_max;
-
-			if (min_power > pg->power_min)
-				min_power = pg->power_min;
-
-			length -= sizeof(struct mwifiex_power_group);
-		}
-		if (pg_tlv_hdr->length > 0) {
-			priv->min_tx_power_level = (u8) min_power;
-			priv->max_tx_power_level = (u8) max_power;
-		}
-	} else {
+	if (!data_buf)
 		return -1;
+
+	pg_tlv_hdr = (struct mwifiex_types_power_group *)
+		((u8 *) data_buf + sizeof(struct host_cmd_ds_txpwr_cfg));
+	pg = (struct mwifiex_power_group *)
+		((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group));
+	length = pg_tlv_hdr->length;
+	if (length > 0) {
+		max_power = pg->power_max;
+		min_power = pg->power_min;
+		length -= sizeof(struct mwifiex_power_group);
+	}
+	while (length) {
+		pg++;
+		if (max_power < pg->power_max)
+			max_power = pg->power_max;
+
+		if (min_power > pg->power_min)
+			min_power = pg->power_min;
+
+		length -= sizeof(struct mwifiex_power_group);
+	}
+	if (pg_tlv_hdr->length > 0) {
+		priv->min_tx_power_level = (u8) min_power;
+		priv->max_tx_power_level = (u8) max_power;
 	}
 
 	return 0;
@@ -420,42 +413,38 @@
 
 	switch (action) {
 	case HostCmd_ACT_GEN_GET:
-		{
-			pg_tlv_hdr =
-				(struct mwifiex_types_power_group *) ((u8 *)
-						txp_cfg +
-						sizeof
-						(struct
-						 host_cmd_ds_txpwr_cfg));
-			pg = (struct mwifiex_power_group *) ((u8 *)
-						pg_tlv_hdr +
-						sizeof(struct
-						mwifiex_types_power_group));
-			if (adapter->hw_status ==
-			    MWIFIEX_HW_STATUS_INITIALIZING)
-				mwifiex_get_power_level(priv, txp_cfg);
-			priv->tx_power_level = (u16) pg->power_min;
-			break;
-		}
+		pg_tlv_hdr = (struct mwifiex_types_power_group *)
+			((u8 *) txp_cfg +
+			 sizeof(struct host_cmd_ds_txpwr_cfg));
+
+		pg = (struct mwifiex_power_group *)
+			((u8 *) pg_tlv_hdr +
+			 sizeof(struct mwifiex_types_power_group));
+
+		if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
+			mwifiex_get_power_level(priv, txp_cfg);
+
+		priv->tx_power_level = (u16) pg->power_min;
+		break;
+
 	case HostCmd_ACT_GEN_SET:
-		if (le32_to_cpu(txp_cfg->mode)) {
-			pg_tlv_hdr =
-				(struct mwifiex_types_power_group *) ((u8 *)
-						txp_cfg +
-						sizeof
-						(struct
-						 host_cmd_ds_txpwr_cfg));
-			pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr
-						+
-						sizeof(struct
-						mwifiex_types_power_group));
-			if (pg->power_max == pg->power_min)
-				priv->tx_power_level = (u16) pg->power_min;
-		}
+		if (!le32_to_cpu(txp_cfg->mode))
+			break;
+
+		pg_tlv_hdr = (struct mwifiex_types_power_group *)
+			((u8 *) txp_cfg +
+			 sizeof(struct host_cmd_ds_txpwr_cfg));
+
+		pg = (struct mwifiex_power_group *)
+			((u8 *) pg_tlv_hdr +
+			 sizeof(struct mwifiex_types_power_group));
+
+		if (pg->power_max == pg->power_min)
+			priv->tx_power_level = (u16) pg->power_min;
 		break;
 	default:
 		dev_err(adapter->dev, "CMD_RESP: unknown cmd action %d\n",
-				action);
+			action);
 		return 0;
 	}
 	dev_dbg(adapter->dev,
@@ -475,7 +464,7 @@
 					  struct host_cmd_ds_command *resp)
 {
 	struct host_cmd_ds_802_11_mac_address *cmd_mac_addr =
-		&resp->params.mac_addr;
+							&resp->params.mac_addr;
 
 	memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN);
 
@@ -560,7 +549,7 @@
 					   struct host_cmd_ds_command *resp)
 {
 	struct host_cmd_ds_802_11_key_material *key =
-		&resp->params.key_material;
+						&resp->params.key_material;
 
 	if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) {
 		if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
@@ -591,17 +580,18 @@
 	u16 action = le16_to_cpu(domain_info->action);
 	u8 no_of_triplet;
 
-	no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) -
-					IEEE80211_COUNTRY_STRING_LEN) /
-				sizeof(struct ieee80211_country_ie_triplet));
+	no_of_triplet = (u8) ((le16_to_cpu(domain->header.len)
+				- IEEE80211_COUNTRY_STRING_LEN)
+			      / sizeof(struct ieee80211_country_ie_triplet));
 
-	dev_dbg(priv->adapter->dev, "info: 11D Domain Info Resp:"
-			" no_of_triplet=%d\n", no_of_triplet);
+	dev_dbg(priv->adapter->dev,
+		"info: 11D Domain Info Resp: no_of_triplet=%d\n",
+		no_of_triplet);
 
 	if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) {
 		dev_warn(priv->adapter->dev,
-			"11D: invalid number of triplets %d "
-			"returned!!\n", no_of_triplet);
+			 "11D: invalid number of triplets %d returned\n",
+			 no_of_triplet);
 		return -1;
 	}
 
@@ -635,8 +625,8 @@
 
 	if (priv->curr_bss_params.bss_descriptor.channel != new_channel) {
 		dev_dbg(priv->adapter->dev, "cmd: Channel Switch: %d to %d\n",
-		       priv->curr_bss_params.bss_descriptor.channel,
-		       new_channel);
+			priv->curr_bss_params.bss_descriptor.channel,
+			new_channel);
 		/* Update the channel again */
 		priv->curr_bss_params.bss_descriptor.channel = new_channel;
 	}
@@ -679,90 +669,70 @@
 {
 	struct mwifiex_ds_reg_rw *reg_rw;
 	struct mwifiex_ds_read_eeprom *eeprom;
+	union reg {
+		struct host_cmd_ds_mac_reg_access *mac;
+		struct host_cmd_ds_bbp_reg_access *bbp;
+		struct host_cmd_ds_rf_reg_access *rf;
+		struct host_cmd_ds_pmic_reg_access *pmic;
+		struct host_cmd_ds_802_11_eeprom_access *eeprom;
+	} r;
 
-	if (data_buf) {
-		reg_rw = data_buf;
-		eeprom = data_buf;
-		switch (type) {
-		case HostCmd_CMD_MAC_REG_ACCESS:
-			{
-				struct host_cmd_ds_mac_reg_access *reg;
-				reg = (struct host_cmd_ds_mac_reg_access *)
-					&resp->params.mac_reg;
-				reg_rw->offset = cpu_to_le32(
-					(u32) le16_to_cpu(reg->offset));
-				reg_rw->value = reg->value;
-				break;
-			}
-		case HostCmd_CMD_BBP_REG_ACCESS:
-			{
-				struct host_cmd_ds_bbp_reg_access *reg;
-				reg = (struct host_cmd_ds_bbp_reg_access *)
-					&resp->params.bbp_reg;
-				reg_rw->offset = cpu_to_le32(
-					(u32) le16_to_cpu(reg->offset));
-				reg_rw->value = cpu_to_le32((u32) reg->value);
-				break;
-			}
+	if (!data_buf)
+		return 0;
 
-		case HostCmd_CMD_RF_REG_ACCESS:
-			{
-				struct host_cmd_ds_rf_reg_access *reg;
-				reg = (struct host_cmd_ds_rf_reg_access *)
-					&resp->params.rf_reg;
-				reg_rw->offset = cpu_to_le32(
-					(u32) le16_to_cpu(reg->offset));
-				reg_rw->value = cpu_to_le32((u32) reg->value);
-				break;
-			}
-		case HostCmd_CMD_PMIC_REG_ACCESS:
-			{
-				struct host_cmd_ds_pmic_reg_access *reg;
-				reg = (struct host_cmd_ds_pmic_reg_access *)
-					&resp->params.pmic_reg;
-				reg_rw->offset = cpu_to_le32(
-					(u32) le16_to_cpu(reg->offset));
-				reg_rw->value = cpu_to_le32((u32) reg->value);
-				break;
-			}
-		case HostCmd_CMD_CAU_REG_ACCESS:
-			{
-				struct host_cmd_ds_rf_reg_access *reg;
-				reg = (struct host_cmd_ds_rf_reg_access *)
-					&resp->params.rf_reg;
-				reg_rw->offset = cpu_to_le32(
-					(u32) le16_to_cpu(reg->offset));
-				reg_rw->value = cpu_to_le32((u32) reg->value);
-				break;
-			}
-		case HostCmd_CMD_802_11_EEPROM_ACCESS:
-			{
-				struct host_cmd_ds_802_11_eeprom_access
-					*cmd_eeprom =
-					(struct host_cmd_ds_802_11_eeprom_access
-					 *) &resp->params.eeprom;
-				pr_debug("info: EEPROM read len=%x\n",
-				       cmd_eeprom->byte_count);
-				if (le16_to_cpu(eeprom->byte_count) <
-						le16_to_cpu(
-						cmd_eeprom->byte_count)) {
-					eeprom->byte_count = cpu_to_le16(0);
-					pr_debug("info: EEPROM read "
-							"length is too big\n");
-					return -1;
-				}
-				eeprom->offset = cmd_eeprom->offset;
-				eeprom->byte_count = cmd_eeprom->byte_count;
-				if (le16_to_cpu(eeprom->byte_count) > 0)
-					memcpy(&eeprom->value,
-					       &cmd_eeprom->value,
-					       le16_to_cpu(eeprom->byte_count));
+	reg_rw = data_buf;
+	eeprom = data_buf;
+	switch (type) {
+	case HostCmd_CMD_MAC_REG_ACCESS:
+		r.mac = (struct host_cmd_ds_mac_reg_access *)
+			&resp->params.mac_reg;
+		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.mac->offset));
+		reg_rw->value = r.mac->value;
+		break;
+	case HostCmd_CMD_BBP_REG_ACCESS:
+		r.bbp = (struct host_cmd_ds_bbp_reg_access *)
+			&resp->params.bbp_reg;
+		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.bbp->offset));
+		reg_rw->value = cpu_to_le32((u32) r.bbp->value);
+		break;
 
-				break;
-			}
-		default:
+	case HostCmd_CMD_RF_REG_ACCESS:
+		r.rf = (struct host_cmd_ds_rf_reg_access *)
+		       &resp->params.rf_reg;
+		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
+		reg_rw->value = cpu_to_le32((u32) r.bbp->value);
+		break;
+	case HostCmd_CMD_PMIC_REG_ACCESS:
+		r.pmic = (struct host_cmd_ds_pmic_reg_access *)
+			 &resp->params.pmic_reg;
+		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.pmic->offset));
+		reg_rw->value = cpu_to_le32((u32) r.pmic->value);
+		break;
+	case HostCmd_CMD_CAU_REG_ACCESS:
+		r.rf = (struct host_cmd_ds_rf_reg_access *)
+		       &resp->params.rf_reg;
+		reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
+		reg_rw->value = cpu_to_le32((u32) r.rf->value);
+		break;
+	case HostCmd_CMD_802_11_EEPROM_ACCESS:
+		r.eeprom = (struct host_cmd_ds_802_11_eeprom_access *)
+			   &resp->params.eeprom;
+		pr_debug("info: EEPROM read len=%x\n", r.eeprom->byte_count);
+		if (le16_to_cpu(eeprom->byte_count) <
+		    le16_to_cpu(r.eeprom->byte_count)) {
+			eeprom->byte_count = cpu_to_le16(0);
+			pr_debug("info: EEPROM read length is too big\n");
 			return -1;
 		}
+		eeprom->offset = r.eeprom->offset;
+		eeprom->byte_count = r.eeprom->byte_count;
+		if (le16_to_cpu(eeprom->byte_count) > 0)
+			memcpy(&eeprom->value, &r.eeprom->value,
+			       le16_to_cpu(r.eeprom->byte_count));
+
+		break;
+	default:
+		return -1;
 	}
 	return 0;
 }
@@ -778,7 +748,7 @@
 					      struct host_cmd_ds_command *resp)
 {
 	struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp =
-		&(resp->params.ibss_coalescing);
+					&(resp->params.ibss_coalescing);
 	u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
 
 	if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET)
@@ -918,20 +888,17 @@
 	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
 		adapter->tx_buf_size = (u16) le16_to_cpu(resp->params.
 							     tx_buf.buff_size);
-		adapter->tx_buf_size = (adapter->tx_buf_size /
-						MWIFIEX_SDIO_BLOCK_SIZE) *
-						MWIFIEX_SDIO_BLOCK_SIZE;
+		adapter->tx_buf_size = (adapter->tx_buf_size
+					/ MWIFIEX_SDIO_BLOCK_SIZE)
+				       * MWIFIEX_SDIO_BLOCK_SIZE;
 		adapter->curr_tx_buf_size = adapter->tx_buf_size;
 		dev_dbg(adapter->dev,
 			"cmd: max_tx_buf_size=%d, tx_buf_size=%d\n",
-		       adapter->max_tx_buf_size, adapter->tx_buf_size);
+			adapter->max_tx_buf_size, adapter->tx_buf_size);
 
 		if (adapter->if_ops.update_mp_end_port)
 			adapter->if_ops.update_mp_end_port(adapter,
-					le16_to_cpu(resp->
-						params.
-						tx_buf.
-						mp_end_port));
+				le16_to_cpu(resp->params.tx_buf.mp_end_port));
 		break;
 	case HostCmd_CMD_AMSDU_AGGR_CTRL:
 		ret = mwifiex_ret_amsdu_aggr_ctrl(resp, data_buf);
@@ -959,7 +926,7 @@
 		break;
 	default:
 		dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
-		       resp->command);
+			resp->command);
 		break;
 	}
 
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index d7aa21d..cc531b5 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -93,15 +93,15 @@
 	 */
 
 	dev_dbg(adapter->dev, "info: previous SSID=%s, SSID len=%u\n",
-	       priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);
+		priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);
 
 	dev_dbg(adapter->dev, "info: current SSID=%s, SSID len=%u\n",
-	       priv->curr_bss_params.bss_descriptor.ssid.ssid,
-	       priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
+		priv->curr_bss_params.bss_descriptor.ssid.ssid,
+		priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
 
 	memcpy(&priv->prev_ssid,
 	       &priv->curr_bss_params.bss_descriptor.ssid,
-	       sizeof(struct mwifiex_802_11_ssid));
+	       sizeof(struct cfg80211_ssid));
 
 	memcpy(priv->prev_bssid,
 	       priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN);
@@ -115,9 +115,9 @@
 	if (adapter->num_cmd_timeout && adapter->curr_cmd)
 		return;
 	priv->media_connected = false;
-	dev_dbg(adapter->dev, "info: successfully disconnected from"
-			" %pM: reason code %d\n", priv->cfg_bssid,
-			WLAN_REASON_DEAUTH_LEAVING);
+	dev_dbg(adapter->dev,
+		"info: successfully disconnected from %pM: reason code %d\n",
+		priv->cfg_bssid, WLAN_REASON_DEAUTH_LEAVING);
 	if (priv->bss_mode == NL80211_IFTYPE_STATION) {
 		cfg80211_disconnected(priv->netdev, WLAN_REASON_DEAUTH_LEAVING,
 				      NULL, 0, GFP_KERNEL);
@@ -192,8 +192,8 @@
 
 	switch (eventcause) {
 	case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
-		dev_err(adapter->dev, "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL,"
-				" ignoring it\n");
+		dev_err(adapter->dev,
+			"invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n");
 		break;
 	case EVENT_LINK_SENSED:
 		dev_dbg(adapter->dev, "event: LINK_SENSED\n");
@@ -235,8 +235,7 @@
 	case EVENT_PS_AWAKE:
 		dev_dbg(adapter->dev, "info: EVENT: AWAKE\n");
 		if (!adapter->pps_uapsd_mode &&
-			priv->media_connected &&
-			adapter->sleep_period.period) {
+		    priv->media_connected && adapter->sleep_period.period) {
 				adapter->pps_uapsd_mode = true;
 				dev_dbg(adapter->dev,
 					"event: PPS/UAPSD mode activated\n");
@@ -244,15 +243,19 @@
 		adapter->tx_lock_flag = false;
 		if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
 			if (mwifiex_check_last_packet_indication(priv)) {
-				if (!adapter->data_sent) {
-					if (!mwifiex_send_null_packet(priv,
-					MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET
-					|
-					MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
+				if (adapter->data_sent) {
+					adapter->ps_state = PS_STATE_AWAKE;
+					adapter->pm_wakeup_card_req = false;
+					adapter->pm_wakeup_fw_try = false;
+					break;
+				}
+				if (!mwifiex_send_null_packet
+					(priv,
+					 MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
+					 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
 						adapter->ps_state =
 							PS_STATE_SLEEP;
 					return 0;
-				}
 			}
 		}
 		adapter->ps_state = PS_STATE_AWAKE;
@@ -371,12 +374,12 @@
 		break;
 	case EVENT_AMSDU_AGGR_CTRL:
 		dev_dbg(adapter->dev, "event:  AMSDU_AGGR_CTRL %d\n",
-		       *(u16 *) adapter->event_body);
+			*(u16 *) adapter->event_body);
 		adapter->tx_buf_size =
 			min(adapter->curr_tx_buf_size,
 			    le16_to_cpu(*(__le16 *) adapter->event_body));
 		dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
-				adapter->tx_buf_size);
+			adapter->tx_buf_size);
 		break;
 
 	case EVENT_WEP_ICV_ERR:
@@ -392,7 +395,7 @@
 		break;
 	default:
 		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
-						eventcause);
+			eventcause);
 		break;
 	}
 
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 866026e..d7b11de 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -71,7 +71,7 @@
 
 	/* Wait for completion */
 	wait_event_interruptible(adapter->cmd_wait_q.wait,
-					*(cmd_queued->condition));
+				 *(cmd_queued->condition));
 	if (!*(cmd_queued->condition))
 		cancel_flag = true;
 
@@ -192,7 +192,7 @@
  * first.
  */
 int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
-		      struct mwifiex_802_11_ssid *req_ssid)
+		      struct cfg80211_ssid *req_ssid)
 {
 	int ret;
 	struct mwifiex_adapter *adapter = priv->adapter;
@@ -249,15 +249,25 @@
 		 * application retrieval */
 		priv->assoc_rsp_size = 0;
 		ret = mwifiex_associate(priv, bss_desc);
+
+		/* If auth type is auto and association fails using open mode,
+		 * try to connect using shared mode */
+		if (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
+		    priv->sec_info.is_authtype_auto &&
+		    priv->sec_info.wep_enabled) {
+			priv->sec_info.authentication_mode =
+						NL80211_AUTHTYPE_SHARED_KEY;
+			ret = mwifiex_associate(priv, bss_desc);
+		}
+
 		if (bss)
 			cfg80211_put_bss(bss);
 	} else {
 		/* Adhoc mode */
 		/* If the requested SSID matches current SSID, return */
 		if (bss_desc && bss_desc->ssid.ssid_len &&
-		    (!mwifiex_ssid_cmp
-		     (&priv->curr_bss_params.bss_descriptor.ssid,
-		      &bss_desc->ssid))) {
+		    (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor.
+				       ssid, &bss_desc->ssid))) {
 			kfree(bss_desc);
 			kfree(beacon_ie);
 			return 0;
@@ -339,9 +349,8 @@
 				adapter->hs_cfg.gpio = (u8)hs_cfg->gpio;
 				if (hs_cfg->gap)
 					adapter->hs_cfg.gap = (u8)hs_cfg->gap;
-			} else if (adapter->hs_cfg.conditions ==
-						cpu_to_le32(
-						HOST_SLEEP_CFG_CANCEL)) {
+			} else if (adapter->hs_cfg.conditions
+				   == cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) {
 				/* Return failure if no parameters for HS
 				   enable */
 				status = -1;
@@ -363,7 +372,7 @@
 						cpu_to_le32(prev_cond);
 		} else {
 			adapter->hs_cfg.conditions =
-				cpu_to_le32(hs_cfg->conditions);
+						cpu_to_le32(hs_cfg->conditions);
 			adapter->hs_cfg.gpio = (u8)hs_cfg->gpio;
 			adapter->hs_cfg.gap = (u8)hs_cfg->gap;
 		}
@@ -416,11 +425,11 @@
 
 	adapter->hs_activate_wait_q_woken = false;
 
-	memset(&hscfg, 0, sizeof(struct mwifiex_hs_config_param));
+	memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
 	hscfg.is_invoke_hostcmd = true;
 
 	if (mwifiex_set_hs_params(mwifiex_get_priv(adapter,
-						       MWIFIEX_BSS_ROLE_STA),
+						   MWIFIEX_BSS_ROLE_STA),
 				  HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD,
 				  &hscfg)) {
 		dev_err(adapter->dev, "IOCTL request HS enable failed\n");
@@ -428,7 +437,7 @@
 	}
 
 	wait_event_interruptible(adapter->hs_activate_wait_q,
-			adapter->hs_activate_wait_q_woken);
+				 adapter->hs_activate_wait_q_woken);
 
 	return true;
 }
@@ -453,8 +462,7 @@
 
 	info->bss_mode = priv->bss_mode;
 
-	memcpy(&info->ssid, &bss_desc->ssid,
-	       sizeof(struct mwifiex_802_11_ssid));
+	memcpy(&info->ssid, &bss_desc->ssid, sizeof(struct cfg80211_ssid));
 
 	memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN);
 
@@ -519,30 +527,27 @@
 		adapter->adhoc_start_band = BAND_G | BAND_B;
 	if (chan->channel) {
 		if (chan->channel <= MAX_CHANNEL_BAND_BG)
-			cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211
-					(priv, 0, (u16) chan->channel);
+			cfp = mwifiex_get_cfp(priv, 0, (u16) chan->channel, 0);
 		if (!cfp) {
-			cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211
-					(priv, BAND_A, (u16) chan->channel);
+			cfp = mwifiex_get_cfp(priv, BAND_A,
+					      (u16) chan->channel, 0);
 			if (cfp) {
 				if (adapter->adhoc_11n_enabled)
 					adapter->adhoc_start_band = BAND_A
-						| BAND_AN;
+								    | BAND_AN;
 				else
 					adapter->adhoc_start_band = BAND_A;
 			}
 		}
 	} else {
 		if (chan->freq <= MAX_FREQUENCY_BAND_BG)
-			cfp = mwifiex_get_cfp_by_band_and_freq_from_cfg80211(
-							priv, 0, chan->freq);
+			cfp = mwifiex_get_cfp(priv, 0, 0, chan->freq);
 		if (!cfp) {
-			cfp = mwifiex_get_cfp_by_band_and_freq_from_cfg80211
-						  (priv, BAND_A, chan->freq);
+			cfp = mwifiex_get_cfp(priv, BAND_A, 0, chan->freq);
 			if (cfp) {
 				if (adapter->adhoc_11n_enabled)
 					adapter->adhoc_start_band = BAND_A
-						| BAND_AN;
+								    | BAND_AN;
 				else
 					adapter->adhoc_start_band = BAND_A;
 			}
@@ -578,7 +583,7 @@
 	}
 
 	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_RF_CHANNEL,
-				    action, 0, channel);
+				     action, 0, channel);
 }
 
 /*
@@ -599,7 +604,7 @@
  *          - Start/Join the IBSS
  */
 int
-mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
+mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel)
 {
 	int ret;
 	struct mwifiex_bss_info bss_info;
@@ -624,7 +629,7 @@
 		goto done;
 	}
 	dev_dbg(priv->adapter->dev, "cmd: updating channel from %d to %d\n",
-			curr_chan, channel);
+		curr_chan, channel);
 
 	if (!bss_info.media_connected) {
 		ret = 0;
@@ -636,7 +641,7 @@
 	ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid);
 
 	ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET,
-					     (u16 *) &channel);
+					     &channel);
 
 	/* Do specific SSID scanning */
 	if (mwifiex_request_scan(priv, &bss_info.ssid)) {
@@ -646,7 +651,8 @@
 
 	band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
 	chan = __ieee80211_get_channel(priv->wdev->wiphy,
-			ieee80211_channel_to_frequency(channel, band));
+				       ieee80211_channel_to_frequency(channel,
+								      band));
 
 	/* Find the BSS we want using available scan results */
 	bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid,
@@ -654,7 +660,7 @@
 			       WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
 	if (!bss)
 		wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n",
-			  bss_info.bssid);
+			   bss_info.bssid);
 
 	ret = mwifiex_bss_start(priv, bss, &bss_info.ssid);
 done:
@@ -783,7 +789,9 @@
 	if (!ret) {
 		if (rate->is_rate_auto)
 			rate->rate = mwifiex_index_to_data_rate(priv,
-					priv->tx_rate, priv->tx_htinfo);
+								priv->tx_rate,
+								priv->tx_htinfo
+								);
 		else
 			rate->rate = priv->data_rate;
 	} else {
@@ -820,16 +828,16 @@
 		if ((dbm < priv->min_tx_power_level) ||
 		    (dbm > priv->max_tx_power_level)) {
 			dev_err(priv->adapter->dev, "txpower value %d dBm"
-					" is out of range (%d dBm-%d dBm)\n",
-					dbm, priv->min_tx_power_level,
-					priv->max_tx_power_level);
+				" is out of range (%d dBm-%d dBm)\n",
+				dbm, priv->min_tx_power_level,
+				priv->max_tx_power_level);
 			return -1;
 		}
 	}
 	buf = kzalloc(MWIFIEX_SIZE_OF_CMD_BUFFER, GFP_KERNEL);
 	if (!buf) {
 		dev_err(priv->adapter->dev, "%s: failed to alloc cmd buffer\n",
-				__func__);
+			__func__);
 		return -ENOMEM;
 	}
 
@@ -837,13 +845,13 @@
 	txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
 	if (!power_cfg->is_power_auto) {
 		txp_cfg->mode = cpu_to_le32(1);
-		pg_tlv = (struct mwifiex_types_power_group *) (buf +
-				sizeof(struct host_cmd_ds_txpwr_cfg));
+		pg_tlv = (struct mwifiex_types_power_group *)
+			 (buf + sizeof(struct host_cmd_ds_txpwr_cfg));
 		pg_tlv->type = TLV_TYPE_POWER_GROUP;
 		pg_tlv->length = 4 * sizeof(struct mwifiex_power_group);
-		pg = (struct mwifiex_power_group *) (buf +
-				sizeof(struct host_cmd_ds_txpwr_cfg) +
-				sizeof(struct mwifiex_types_power_group));
+		pg = (struct mwifiex_power_group *)
+		     (buf + sizeof(struct host_cmd_ds_txpwr_cfg)
+		      + sizeof(struct mwifiex_types_power_group));
 		/* Power group for modulation class HR/DSSS */
 		pg->first_rate_code = 0x00;
 		pg->last_rate_code = 0x03;
@@ -906,8 +914,8 @@
 				    sub_cmd, BITMAP_STA_PS, NULL);
 	if ((!ret) && (sub_cmd == DIS_AUTO_PS))
 		ret = mwifiex_send_cmd_async(priv,
-				HostCmd_CMD_802_11_PS_MODE_ENH, GET_PS,
-				0, NULL);
+					     HostCmd_CMD_802_11_PS_MODE_ENH,
+					     GET_PS, 0, NULL);
 
 	return ret;
 }
@@ -931,7 +939,7 @@
 		memcpy(priv->wpa_ie, ie_data_ptr, ie_len);
 		priv->wpa_ie_len = (u8) ie_len;
 		dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n",
-				priv->wpa_ie_len, priv->wpa_ie[0]);
+			priv->wpa_ie_len, priv->wpa_ie[0]);
 
 		if (priv->wpa_ie[0] == WLAN_EID_WPA) {
 			priv->sec_info.wpa_enabled = true;
@@ -972,7 +980,7 @@
 		memcpy(priv->wapi_ie, ie_data_ptr, ie_len);
 		priv->wapi_ie_len = ie_len;
 		dev_dbg(priv->adapter->dev, "cmd: Set wapi_ie_len=%d IE=%#x\n",
-				priv->wapi_ie_len, priv->wapi_ie[0]);
+			priv->wapi_ie_len, priv->wapi_ie[0]);
 
 		if (priv->wapi_ie[0] == WLAN_EID_BSS_AC_ACCESS_DELAY)
 			priv->sec_info.wapi_enabled = true;
@@ -998,8 +1006,8 @@
 {
 
 	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-				    HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
-				    encrypt_key);
+				     HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
+				     encrypt_key);
 }
 
 /*
@@ -1093,9 +1101,9 @@
 		/* Send the key as PTK to firmware */
 		encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST;
 		ret = mwifiex_send_cmd_async(priv,
-					HostCmd_CMD_802_11_KEY_MATERIAL,
-					HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
-					encrypt_key);
+					     HostCmd_CMD_802_11_KEY_MATERIAL,
+					     HostCmd_ACT_GEN_SET,
+					     KEY_INFO_ENABLED, encrypt_key);
 		if (ret)
 			return ret;
 
@@ -1120,14 +1128,14 @@
 
 	if (remove_key)
 		ret = mwifiex_send_cmd_sync(priv,
-				       HostCmd_CMD_802_11_KEY_MATERIAL,
-				       HostCmd_ACT_GEN_SET, !(KEY_INFO_ENABLED),
-				       encrypt_key);
+					    HostCmd_CMD_802_11_KEY_MATERIAL,
+					    HostCmd_ACT_GEN_SET,
+					    !KEY_INFO_ENABLED, encrypt_key);
 	else
 		ret = mwifiex_send_cmd_sync(priv,
-					HostCmd_CMD_802_11_KEY_MATERIAL,
-					HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
-					encrypt_key);
+					    HostCmd_CMD_802_11_KEY_MATERIAL,
+					    HostCmd_ACT_GEN_SET,
+					    KEY_INFO_ENABLED, encrypt_key);
 
 	return ret;
 }
@@ -1246,7 +1254,7 @@
 
 	memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext));
 	if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_VERSION_EXT,
-				    HostCmd_ACT_GEN_GET, 0, &ver_ext))
+				  HostCmd_ACT_GEN_GET, 0, &ver_ext))
 		return -1;
 
 	return 0;
@@ -1263,7 +1271,7 @@
 		       struct mwifiex_ds_get_stats *log)
 {
 	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG,
-				    HostCmd_ACT_GEN_GET, 0, log);
+				     HostCmd_ACT_GEN_GET, 0, log);
 }
 
 /*
@@ -1403,9 +1411,9 @@
 	}
 	pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
 	/* Test to see if it is a WPA IE, if not, then it is a gen IE */
-	if (((pvendor_ie->element_id == WLAN_EID_WPA)
-	     && (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui))))
-			|| (pvendor_ie->element_id == WLAN_EID_RSN)) {
+	if (((pvendor_ie->element_id == WLAN_EID_WPA) &&
+	     (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
+	    (pvendor_ie->element_id == WLAN_EID_RSN)) {
 
 		/* IE is a WPA/WPA2 IE so call set_wpa function */
 		ret = mwifiex_set_wpa_ie_helper(priv, ie_data_ptr, ie_len);
@@ -1428,9 +1436,8 @@
 		 * wps session flag
 		 */
 		pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
-		if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC)
-				&& (!memcmp(pvendor_ie->oui, wps_oui,
-						sizeof(wps_oui)))) {
+		if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
+		    (!memcmp(pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) {
 			priv->wps.session_enable = true;
 			dev_dbg(priv->adapter->dev,
 				"info: WPS Session Enabled.\n");
@@ -1439,7 +1446,7 @@
 		/* Append the passed data to the end of the
 		   genIeBuffer */
 		memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len, ie_data_ptr,
-									ie_len);
+		       ie_len);
 		/* Increment the stored buffer length by the
 		   size passed */
 		priv->gen_ie_buf_len += ie_len;
@@ -1483,7 +1490,7 @@
 			return -1;
 		} else {
 			memcpy(adapter->arp_filter, gen_ie->ie_data,
-								gen_ie->len);
+			       gen_ie->len);
 			adapter->arp_filter_size = gen_ie->len;
 		}
 		break;
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index d7a5d76..750b695 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -43,8 +43,9 @@
 {
 	int ret;
 	struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
-	struct mwifiex_private *priv = mwifiex_get_priv_by_id(adapter,
-			rx_info->bss_num, rx_info->bss_type);
+	struct mwifiex_private *priv =
+			mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
+					       rx_info->bss_type);
 	struct rx_packet_hdr *rx_pkt_hdr;
 	struct rxpd *local_rx_pd;
 	int hdr_chop;
@@ -125,8 +126,9 @@
 	struct rx_packet_hdr *rx_pkt_hdr;
 	u8 ta[ETH_ALEN];
 	u16 rx_pkt_type;
-	struct mwifiex_private *priv = mwifiex_get_priv_by_id(adapter,
-			rx_info->bss_num, rx_info->bss_type);
+	struct mwifiex_private *priv =
+			mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
+					       rx_info->bss_type);
 
 	if (!priv)
 		return -1;
@@ -157,7 +159,7 @@
 		skb_trim(skb, local_rx_pd->rx_pkt_length);
 
 		ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
-				priv->wdev->iftype, 0, false);
+					 priv->wdev->iftype, 0, false);
 
 		while (!skb_queue_empty(&list)) {
 			rx_skb = __skb_dequeue(&list);
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index 94d31a9..7af534f 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -50,8 +50,7 @@
 	u8 pad;
 
 	if (!skb->len) {
-		dev_err(adapter->dev, "Tx: bad packet length: %d\n",
-		       skb->len);
+		dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len);
 		tx_info->status_code = -1;
 		return skb->data;
 	}
@@ -60,19 +59,20 @@
 	pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4;
 
 	BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN
-								+ pad));
+				    + pad));
 	skb_push(skb, sizeof(*local_tx_pd) + pad);
 
 	local_tx_pd = (struct txpd *) skb->data;
 	memset(local_tx_pd, 0, sizeof(struct txpd));
 	local_tx_pd->bss_num = priv->bss_num;
 	local_tx_pd->bss_type = priv->bss_type;
-	local_tx_pd->tx_pkt_length = cpu_to_le16((u16) (skb->len -
-						(sizeof(struct txpd) + pad)));
+	local_tx_pd->tx_pkt_length = cpu_to_le16((u16)(skb->len -
+						       (sizeof(struct txpd)
+							+ pad)));
 
 	local_tx_pd->priority = (u8) skb->priority;
 	local_tx_pd->pkt_delay_2ms =
-		mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
+				mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
 
 	if (local_tx_pd->priority <
 	    ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
@@ -82,7 +82,7 @@
 		 */
 		local_tx_pd->tx_control =
 			cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[local_tx_pd->
-							 priority]);
+								   priority]);
 
 	if (adapter->pps_uapsd_mode) {
 		if (mwifiex_check_last_packet_indication(priv)) {
@@ -160,13 +160,13 @@
 	case -1:
 		dev_kfree_skb_any(skb);
 		dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n",
-						__func__, ret);
+			__func__, ret);
 		adapter->dbg.num_tx_host_to_card_failure++;
 		break;
 	case 0:
 		dev_kfree_skb_any(skb);
 		dev_dbg(adapter->dev, "data: %s: host_to_card succeeded\n",
-						__func__);
+			__func__);
 		adapter->tx_lock_flag = true;
 		break;
 	case -EINPROGRESS:
@@ -192,8 +192,8 @@
 	if (mwifiex_wmm_lists_empty(adapter))
 			ret = true;
 
-	if (ret && !adapter->cmd_sent && !adapter->curr_cmd
-	    && !is_command_pending(adapter)) {
+	if (ret && !adapter->cmd_sent && !adapter->curr_cmd &&
+	    !is_command_pending(adapter)) {
 		adapter->delay_null_pkt = false;
 		ret = true;
 	} else {
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index 9a6eacc..d2af8cb 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -85,8 +85,7 @@
 	switch (ret) {
 	case -EBUSY:
 		if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-			(adapter->pps_uapsd_mode) &&
-			(adapter->tx_lock_flag)) {
+		    (adapter->pps_uapsd_mode) && (adapter->tx_lock_flag)) {
 				priv->adapter->tx_lock_flag = false;
 				if (local_tx_pd)
 					local_tx_pd->flags = 0;
@@ -96,7 +95,7 @@
 	case -1:
 		adapter->data_sent = false;
 		dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n",
-		       ret);
+			ret);
 		adapter->dbg.num_tx_host_to_card_failure++;
 		mwifiex_write_data_complete(adapter, skb, ret);
 		break;
@@ -132,7 +131,7 @@
 
 	tx_info = MWIFIEX_SKB_TXCB(skb);
 	priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
-			tx_info->bss_type);
+				      tx_info->bss_type);
 	if (!priv)
 		goto done;
 
@@ -151,11 +150,11 @@
 
 		tpriv = adapter->priv[i];
 
-		if ((GET_BSS_ROLE(tpriv) == MWIFIEX_BSS_ROLE_STA)
-				&& (tpriv->media_connected)) {
+		if ((GET_BSS_ROLE(tpriv) == MWIFIEX_BSS_ROLE_STA) &&
+		    (tpriv->media_connected)) {
 			if (netif_queue_stopped(tpriv->netdev))
 				mwifiex_wake_up_net_dev_queue(tpriv->netdev,
-								adapter);
+							      adapter);
 		}
 	}
 done:
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index 9c48f37..6b39997 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -93,10 +93,10 @@
 		       sizeof(priv->wmm.packets_out));
 		info->max_tx_buf_size = (u32) adapter->max_tx_buf_size;
 		info->tx_buf_size = (u32) adapter->tx_buf_size;
-		info->rx_tbl_num = mwifiex_get_rx_reorder_tbl(
-					priv, info->rx_tbl);
-		info->tx_tbl_num = mwifiex_get_tx_ba_stream_tbl(
-					priv, info->tx_tbl);
+		info->rx_tbl_num = mwifiex_get_rx_reorder_tbl(priv,
+							      info->rx_tbl);
+		info->tx_tbl_num = mwifiex_get_tx_ba_stream_tbl(priv,
+								info->tx_tbl);
 		info->ps_mode = adapter->ps_mode;
 		info->ps_state = adapter->ps_state;
 		info->is_deep_sleep = adapter->is_deep_sleep;
@@ -105,19 +105,19 @@
 		info->is_hs_configured = adapter->is_hs_configured;
 		info->hs_activated = adapter->hs_activated;
 		info->num_cmd_host_to_card_failure
-			= adapter->dbg.num_cmd_host_to_card_failure;
+				= adapter->dbg.num_cmd_host_to_card_failure;
 		info->num_cmd_sleep_cfm_host_to_card_failure
 			= adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure;
 		info->num_tx_host_to_card_failure
-			= adapter->dbg.num_tx_host_to_card_failure;
+				= adapter->dbg.num_tx_host_to_card_failure;
 		info->num_event_deauth = adapter->dbg.num_event_deauth;
 		info->num_event_disassoc = adapter->dbg.num_event_disassoc;
 		info->num_event_link_lost = adapter->dbg.num_event_link_lost;
 		info->num_cmd_deauth = adapter->dbg.num_cmd_deauth;
 		info->num_cmd_assoc_success =
-			adapter->dbg.num_cmd_assoc_success;
+					adapter->dbg.num_cmd_assoc_success;
 		info->num_cmd_assoc_failure =
-			adapter->dbg.num_cmd_assoc_failure;
+					adapter->dbg.num_cmd_assoc_failure;
 		info->num_tx_timeout = adapter->dbg.num_tx_timeout;
 		info->num_cmd_timeout = adapter->dbg.num_cmd_timeout;
 		info->timeout_cmd_id = adapter->dbg.timeout_cmd_id;
@@ -160,7 +160,7 @@
 
 	rx_info = MWIFIEX_SKB_RXCB(skb);
 	priv = mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
-			rx_info->bss_type);
+				      rx_info->bss_type);
 	if (!priv)
 		return -1;
 
@@ -191,7 +191,7 @@
 {
 	atomic_dec(&adapter->cmd_pending);
 	dev_dbg(adapter->dev, "cmd completed: status=%d\n",
-					adapter->cmd_wait_q.status);
+		adapter->cmd_wait_q.status);
 
 	*(cmd_node->condition) = true;
 
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 75f79ef..5a7316c 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -87,15 +87,15 @@
 	const char *ac_str[] = { "BK", "BE", "VI", "VO" };
 
 	pr_debug("info: WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, "
-	       "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
-	       ac_str[wmm_aci_to_qidx_map[(ac_param->aci_aifsn_bitmap
-	       & MWIFIEX_ACI) >> 5]],
-	       (ac_param->aci_aifsn_bitmap & MWIFIEX_ACI) >> 5,
-	       (ac_param->aci_aifsn_bitmap & MWIFIEX_ACM) >> 4,
-	       ac_param->aci_aifsn_bitmap & MWIFIEX_AIFSN,
-	       ac_param->ecw_bitmap & MWIFIEX_ECW_MIN,
-	       (ac_param->ecw_bitmap & MWIFIEX_ECW_MAX) >> 4,
-	       le16_to_cpu(ac_param->tx_op_limit));
+		 "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n",
+		 ac_str[wmm_aci_to_qidx_map[(ac_param->aci_aifsn_bitmap
+					     & MWIFIEX_ACI) >> 5]],
+		 (ac_param->aci_aifsn_bitmap & MWIFIEX_ACI) >> 5,
+		 (ac_param->aci_aifsn_bitmap & MWIFIEX_ACM) >> 4,
+		 ac_param->aci_aifsn_bitmap & MWIFIEX_AIFSN,
+		 ac_param->ecw_bitmap & MWIFIEX_ECW_MIN,
+		 (ac_param->ecw_bitmap & MWIFIEX_ECW_MAX) >> 4,
+		 le16_to_cpu(ac_param->tx_op_limit));
 }
 
 /*
@@ -112,7 +112,7 @@
 
 	if (!ra_list) {
 		dev_err(adapter->dev, "%s: failed to alloc ra_list\n",
-						__func__);
+			__func__);
 		return NULL;
 	}
 	INIT_LIST_HEAD(&ra_list->list);
@@ -154,7 +154,7 @@
 			ra_list, ra_list->is_11n_enabled);
 
 		list_add_tail(&ra_list->list,
-				&priv->wmm.tid_tbl_ptr[i].ra_list);
+			      &priv->wmm.tid_tbl_ptr[i].ra_list);
 
 		if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr)
 			priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list;
@@ -217,22 +217,19 @@
 		wmm_ie->reserved);
 
 	for (num_ac = 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) {
-		cw_min = (1 << (wmm_ie->ac_params[num_ac].ecw_bitmap &
-			MWIFIEX_ECW_MIN)) - 1;
-		avg_back_off = (cw_min >> 1) +
-			(wmm_ie->ac_params[num_ac].aci_aifsn_bitmap &
-			MWIFIEX_AIFSN);
+		u8 ecw = wmm_ie->ac_params[num_ac].ecw_bitmap;
+		u8 aci_aifsn = wmm_ie->ac_params[num_ac].aci_aifsn_bitmap;
+		cw_min = (1 << (ecw & MWIFIEX_ECW_MIN)) - 1;
+		avg_back_off = (cw_min >> 1) + (aci_aifsn & MWIFIEX_AIFSN);
 
-		ac_idx = wmm_aci_to_qidx_map[(wmm_ie->ac_params[num_ac].
-					     aci_aifsn_bitmap &
-					     MWIFIEX_ACI) >> 5];
+		ac_idx = wmm_aci_to_qidx_map[(aci_aifsn & MWIFIEX_ACI) >> 5];
 		priv->wmm.queue_priority[ac_idx] = ac_idx;
 		tmp[ac_idx] = avg_back_off;
 
-		dev_dbg(priv->adapter->dev, "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n",
-		       (1 << ((wmm_ie->ac_params[num_ac].ecw_bitmap &
-		       MWIFIEX_ECW_MAX) >> 4)) - 1,
-		       cw_min, avg_back_off);
+		dev_dbg(priv->adapter->dev,
+			"info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n",
+			(1 << ((ecw & MWIFIEX_ECW_MAX) >> 4)) - 1,
+			cw_min, avg_back_off);
 		mwifiex_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]);
 	}
 
@@ -312,13 +309,14 @@
 		/* WMM is not enabled, default priorities */
 		for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++)
 			priv->wmm.ac_down_graded_vals[ac_val] =
-				(enum mwifiex_wmm_ac_e) ac_val;
+						(enum mwifiex_wmm_ac_e) ac_val;
 	} else {
 		for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) {
 			priv->wmm.ac_down_graded_vals[ac_val]
 				= mwifiex_wmm_eval_downgrade_ac(priv,
 						(enum mwifiex_wmm_ac_e) ac_val);
-			dev_dbg(priv->adapter->dev, "info: WMM: AC PRIO %d maps to %d\n",
+			dev_dbg(priv->adapter->dev,
+				"info: WMM: AC PRIO %d maps to %d\n",
 				ac_val, priv->wmm.ac_down_graded_vals[ac_val]);
 		}
 	}
@@ -394,13 +392,13 @@
 		}
 
 		priv->aggr_prio_tbl[6].amsdu
-			= priv->aggr_prio_tbl[6].ampdu_ap
-			= priv->aggr_prio_tbl[6].ampdu_user
-			= BA_STREAM_NOT_ALLOWED;
+					= priv->aggr_prio_tbl[6].ampdu_ap
+					= priv->aggr_prio_tbl[6].ampdu_user
+					= BA_STREAM_NOT_ALLOWED;
 
 		priv->aggr_prio_tbl[7].amsdu = priv->aggr_prio_tbl[7].ampdu_ap
-			= priv->aggr_prio_tbl[7].ampdu_user
-			= BA_STREAM_NOT_ALLOWED;
+					= priv->aggr_prio_tbl[7].ampdu_user
+					= BA_STREAM_NOT_ALLOWED;
 
 		priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
 		priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE;
@@ -472,7 +470,7 @@
 
 	for (i = 0; i < MAX_NUM_TID; i++)
 		mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i].
-						     ra_list);
+								       ra_list);
 
 	atomic_set(&priv->wmm.tx_pkts_queued, 0);
 	atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
@@ -488,9 +486,10 @@
 
 	for (i = 0; i < MAX_NUM_TID; ++i) {
 		dev_dbg(priv->adapter->dev,
-				"info: ra_list: freeing buf for tid %d\n", i);
+			"info: ra_list: freeing buf for tid %d\n", i);
 		list_for_each_entry_safe(ra_list, tmp_node,
-				&priv->wmm.tid_tbl_ptr[i].ra_list, list) {
+					 &priv->wmm.tid_tbl_ptr[i].ra_list,
+					 list) {
 			list_del(&ra_list->list);
 			kfree(ra_list);
 		}
@@ -652,7 +651,7 @@
 	if (atomic_read(&priv->wmm.highest_queued_prio) <
 						tos_to_tid_inv[tid_down])
 		atomic_set(&priv->wmm.highest_queued_prio,
-						tos_to_tid_inv[tid_down]);
+			   tos_to_tid_inv[tid_down]);
 
 	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
 }
@@ -681,7 +680,7 @@
 	struct mwifiex_wmm_ac_status *ac_status;
 
 	dev_dbg(priv->adapter->dev, "info: WMM: WMM_GET_STATUS cmdresp received: %d\n",
-			resp_len);
+		resp_len);
 
 	while ((resp_len >= sizeof(tlv_hdr->header)) && valid) {
 		tlv_hdr = (struct mwifiex_ie_types_data *) curr;
@@ -695,15 +694,15 @@
 			dev_dbg(priv->adapter->dev,
 				"info: CMD_RESP: WMM_GET_STATUS:"
 				" QSTATUS TLV: %d, %d, %d\n",
-			       tlv_wmm_qstatus->queue_index,
-			       tlv_wmm_qstatus->flow_required,
-			       tlv_wmm_qstatus->disabled);
+				tlv_wmm_qstatus->queue_index,
+				tlv_wmm_qstatus->flow_required,
+				tlv_wmm_qstatus->disabled);
 
 			ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus->
 							 queue_index];
 			ac_status->disabled = tlv_wmm_qstatus->disabled;
 			ac_status->flow_required =
-				tlv_wmm_qstatus->flow_required;
+						tlv_wmm_qstatus->flow_required;
 			ac_status->flow_created = tlv_wmm_qstatus->flow_created;
 			break;
 
@@ -772,29 +771,27 @@
 	if (!wmm_ie)
 		return 0;
 
-	dev_dbg(priv->adapter->dev, "info: WMM: process assoc req:"
-			"bss->wmmIe=0x%x\n",
-			wmm_ie->vend_hdr.element_id);
+	dev_dbg(priv->adapter->dev,
+		"info: WMM: process assoc req: bss->wmm_ie=%#x\n",
+		wmm_ie->vend_hdr.element_id);
 
-	if ((priv->wmm_required
-	     || (ht_cap && (priv->adapter->config_bands & BAND_GN
-		     || priv->adapter->config_bands & BAND_AN))
-	    )
-	    && wmm_ie->vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) {
+	if ((priv->wmm_required ||
+	     (ht_cap && (priv->adapter->config_bands & BAND_GN ||
+	     priv->adapter->config_bands & BAND_AN))) &&
+	    wmm_ie->vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) {
 		wmm_tlv = (struct mwifiex_ie_types_wmm_param_set *) *assoc_buf;
 		wmm_tlv->header.type = cpu_to_le16((u16) wmm_info_ie[0]);
 		wmm_tlv->header.len = cpu_to_le16((u16) wmm_info_ie[1]);
 		memcpy(wmm_tlv->wmm_ie, &wmm_info_ie[2],
-			le16_to_cpu(wmm_tlv->header.len));
+		       le16_to_cpu(wmm_tlv->header.len));
 		if (wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD)
 			memcpy((u8 *) (wmm_tlv->wmm_ie
-					+ le16_to_cpu(wmm_tlv->header.len)
-					 - sizeof(priv->wmm_qosinfo)),
-					&priv->wmm_qosinfo,
-					sizeof(priv->wmm_qosinfo));
+				       + le16_to_cpu(wmm_tlv->header.len)
+				       - sizeof(priv->wmm_qosinfo)),
+			       &priv->wmm_qosinfo, sizeof(priv->wmm_qosinfo));
 
 		ret_len = sizeof(wmm_tlv->header)
-			+ le16_to_cpu(wmm_tlv->header.len);
+			  + le16_to_cpu(wmm_tlv->header.len);
 
 		*assoc_buf += ret_len;
 	}
@@ -813,7 +810,7 @@
  */
 u8
 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv,
-					const struct sk_buff *skb)
+				  const struct sk_buff *skb)
 {
 	u8 ret_val;
 	struct timeval out_tstamp, in_tstamp;
@@ -850,17 +847,18 @@
 	struct mwifiex_ra_list_tbl *ptr, *head;
 	struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head;
 	struct mwifiex_tid_tbl *tid_ptr;
+	atomic_t *hqp;
 	int is_list_empty;
 	unsigned long flags;
 	int i, j;
 
 	for (j = adapter->priv_num - 1; j >= 0; --j) {
 		spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock,
-				flags);
+				  flags);
 		is_list_empty = list_empty(&adapter->bss_prio_tbl[j]
-				.bss_prio_head);
+					   .bss_prio_head);
 		spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock,
-				flags);
+				       flags);
 		if (is_list_empty)
 			continue;
 
@@ -879,12 +877,8 @@
 		}
 
 		do {
-			atomic_t *hqp;
-			spinlock_t *lock;
-
 			priv_tmp = bssprio_node->priv;
 			hqp = &priv_tmp->wmm.highest_queued_prio;
-			lock = &priv_tmp->wmm.ra_list_spinlock;
 
 			for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) {
 
@@ -923,16 +917,10 @@
 				do {
 					is_list_empty =
 						skb_queue_empty(&ptr->skb_head);
-					if (!is_list_empty) {
-						spin_lock_irqsave(lock, flags);
-						if (atomic_read(hqp) > i)
-							atomic_set(hqp, i);
-						spin_unlock_irqrestore(lock,
-									flags);
-						*priv = priv_tmp;
-						*tid = tos_to_tid[i];
-						return ptr;
-					}
+
+					if (!is_list_empty)
+						goto found;
+
 					/* Get next ra */
 					ptr = list_first_entry(&ptr->list,
 						 struct mwifiex_ra_list_tbl,
@@ -969,6 +957,17 @@
 		} while (bssprio_node != bssprio_head);
 	}
 	return NULL;
+
+found:
+	spin_lock_irqsave(&priv_tmp->wmm.ra_list_spinlock, flags);
+	if (atomic_read(hqp) > i)
+		atomic_set(hqp, i);
+	spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags);
+
+	*priv = priv_tmp;
+	*tid = tos_to_tid[i];
+
+	return ptr;
 }
 
 /*
@@ -1208,25 +1207,24 @@
 		return 0;
 	}
 
-	if (!ptr->is_11n_enabled || mwifiex_is_ba_stream_setup(priv, ptr, tid)
-	    || ((priv->sec_info.wpa_enabled
-		  || priv->sec_info.wpa2_enabled) && !priv->wpa_is_gtk_set)
-		) {
+	if (!ptr->is_11n_enabled ||
+	    mwifiex_is_ba_stream_setup(priv, ptr, tid) ||
+	    ((priv->sec_info.wpa_enabled ||
+	      priv->sec_info.wpa2_enabled) &&
+	     !priv->wpa_is_gtk_set)) {
 		mwifiex_send_single_packet(priv, ptr, ptr_index, flags);
 		/* ra_list_spinlock has been freed in
 		   mwifiex_send_single_packet() */
 	} else {
 		if (mwifiex_is_ampdu_allowed(priv, tid)) {
 			if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
-				mwifiex_11n_create_tx_ba_stream_tbl(priv,
-						ptr->ra, tid,
-						BA_STREAM_SETUP_INPROGRESS);
+				mwifiex_create_ba_tbl(priv, ptr->ra, tid,
+						      BA_SETUP_INPROGRESS);
 				mwifiex_send_addba(priv, tid, ptr->ra);
 			} else if (mwifiex_find_stream_to_delete
 				   (priv, tid, &tid_del, ra)) {
-				mwifiex_11n_create_tx_ba_stream_tbl(priv,
-						ptr->ra, tid,
-						BA_STREAM_SETUP_INPROGRESS);
+				mwifiex_create_ba_tbl(priv, ptr->ra, tid,
+						      BA_SETUP_INPROGRESS);
 				mwifiex_send_delba(priv, tid_del, ra, 1);
 			}
 		}
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 40f4eb7..ee8af1f 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -227,6 +227,7 @@
 			     struct ieee80211_vif *vif)
 {
 	struct p54_common *priv = dev->priv;
+	int err;
 
 	vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
 
@@ -251,9 +252,9 @@
 	}
 
 	memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
-	p54_setup_mac(priv);
+	err = p54_setup_mac(priv);
 	mutex_unlock(&priv->conf_mutex);
-	return 0;
+	return err;
 }
 
 static void p54_remove_interface(struct ieee80211_hw *dev,
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index b1f51a2..45df728 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -624,36 +624,39 @@
 }
 
 #ifdef CONFIG_PM
-static int p54p_suspend(struct pci_dev *pdev, pm_message_t state)
+static int p54p_suspend(struct device *device)
 {
-	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-	struct p54p_priv *priv = dev->priv;
-
-	if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) {
-		ieee80211_stop_queues(dev);
-		p54p_stop(dev);
-	}
+	struct pci_dev *pdev = to_pci_dev(device);
 
 	pci_save_state(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	pci_set_power_state(pdev, PCI_D3hot);
+	pci_disable_device(pdev);
 	return 0;
 }
 
-static int p54p_resume(struct pci_dev *pdev)
+static int p54p_resume(struct device *device)
 {
-	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-	struct p54p_priv *priv = dev->priv;
+	struct pci_dev *pdev = to_pci_dev(device);
+	int err;
 
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-
-	if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) {
-		p54p_open(dev);
-		ieee80211_wake_queues(dev);
-	}
-
-	return 0;
+	err = pci_reenable_device(pdev);
+	if (err)
+		return err;
+	return pci_set_power_state(pdev, PCI_D0);
 }
+
+static const struct dev_pm_ops p54pci_pm_ops = {
+	.suspend = p54p_suspend,
+	.resume = p54p_resume,
+	.freeze = p54p_suspend,
+	.thaw = p54p_resume,
+	.poweroff = p54p_suspend,
+	.restore = p54p_resume,
+};
+
+#define P54P_PM_OPS (&p54pci_pm_ops)
+#else
+#define P54P_PM_OPS (NULL)
 #endif /* CONFIG_PM */
 
 static struct pci_driver p54p_driver = {
@@ -661,10 +664,7 @@
 	.id_table	= p54p_table,
 	.probe		= p54p_probe,
 	.remove		= __devexit_p(p54p_remove),
-#ifdef CONFIG_PM
-	.suspend	= p54p_suspend,
-	.resume		= p54p_resume,
-#endif /* CONFIG_PM */
+	.driver.pm	= P54P_PM_OPS,
 };
 
 static int __init p54p_init(void)
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index 7faed62..f792990 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -618,19 +618,19 @@
 	ret = spi_setup(spi);
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "spi_setup failed");
-		goto err_free_common;
+		goto err_free;
 	}
 
 	ret = gpio_request(p54spi_gpio_power, "p54spi power");
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret);
-		goto err_free_common;
+		goto err_free;
 	}
 
 	ret = gpio_request(p54spi_gpio_irq, "p54spi irq");
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret);
-		goto err_free_common;
+		goto err_free_gpio_power;
 	}
 
 	gpio_direction_output(p54spi_gpio_power, 0);
@@ -641,7 +641,7 @@
 			  priv->spi);
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "request_irq() failed");
-		goto err_free_common;
+		goto err_free_gpio_irq;
 	}
 
 	irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
@@ -673,6 +673,12 @@
 	return 0;
 
 err_free_common:
+	free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
+err_free_gpio_irq:
+	gpio_free(p54spi_gpio_irq);
+err_free_gpio_power:
+	gpio_free(p54spi_gpio_power);
+err_free:
 	p54_free_common(priv->hw);
 	return ret;
 }
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index a330c69..d66e298 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -518,7 +518,7 @@
 	__le32 current_command_oid;
 
 	/* encryption stuff */
-	int  encr_tx_key_index;
+	u8 encr_tx_key_index;
 	struct rndis_wlan_encr_key encr_keys[RNDIS_WLAN_NUM_KEYS];
 	int  wpa_version;
 
@@ -634,7 +634,7 @@
 	}
 }
 
-static bool is_wpa_key(struct rndis_wlan_private *priv, int idx)
+static bool is_wpa_key(struct rndis_wlan_private *priv, u8 idx)
 {
 	int cipher = priv->encr_keys[idx].cipher;
 
@@ -1350,7 +1350,7 @@
 }
 
 static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev,
-						     u16 *beacon_interval)
+						     u32 *beacon_period)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ieee80211_channel *channel;
@@ -1370,14 +1370,14 @@
 	if (!channel)
 		return NULL;
 
-	if (beacon_interval)
-		*beacon_interval = le16_to_cpu(config.beacon_period);
+	if (beacon_period)
+		*beacon_period = le32_to_cpu(config.beacon_period);
 	return channel;
 }
 
 /* index must be 0 - N, as per NDIS  */
 static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len,
-								int index)
+								u8 index)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_wep_key ndis_key;
@@ -1387,13 +1387,15 @@
 	netdev_dbg(usbdev->net, "%s(idx: %d, len: %d)\n",
 		   __func__, index, key_len);
 
-	if ((key_len != 5 && key_len != 13) || index < 0 || index > 3)
+	if (index >= RNDIS_WLAN_NUM_KEYS)
 		return -EINVAL;
 
 	if (key_len == 5)
 		cipher = WLAN_CIPHER_SUITE_WEP40;
-	else
+	else if (key_len == 13)
 		cipher = WLAN_CIPHER_SUITE_WEP104;
+	else
+		return -EINVAL;
 
 	memset(&ndis_key, 0, sizeof(ndis_key));
 
@@ -1428,7 +1430,7 @@
 }
 
 static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
-			int index, const u8 *addr, const u8 *rx_seq,
+			u8 index, const u8 *addr, const u8 *rx_seq,
 			int seq_len, u32 cipher, __le32 flags)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@@ -1436,7 +1438,7 @@
 	bool is_addr_ok;
 	int ret;
 
-	if (index < 0 || index >= 4) {
+	if (index >= RNDIS_WLAN_NUM_KEYS) {
 		netdev_dbg(usbdev->net, "%s(): index out of range (%i)\n",
 			   __func__, index);
 		return -EINVAL;
@@ -1524,7 +1526,7 @@
 	return 0;
 }
 
-static int restore_key(struct usbnet *usbdev, int key_idx)
+static int restore_key(struct usbnet *usbdev, u8 key_idx)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct rndis_wlan_encr_key key;
@@ -1550,13 +1552,13 @@
 		restore_key(usbdev, i);
 }
 
-static void clear_key(struct rndis_wlan_private *priv, int idx)
+static void clear_key(struct rndis_wlan_private *priv, u8 idx)
 {
 	memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx]));
 }
 
 /* remove_key is for both wep and wpa */
-static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid)
+static int remove_key(struct usbnet *usbdev, u8 index, const u8 *bssid)
 {
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_remove_key remove_key;
@@ -1790,9 +1792,9 @@
 						struct cfg80211_pmksa *pmksa,
 						int max_pmkids)
 {
-	int i, len, count, newlen, err;
+	int i, newlen, err;
+	unsigned int count;
 
-	len = le32_to_cpu(pmkids->length);
 	count = le32_to_cpu(pmkids->bssid_info_count);
 
 	if (count > max_pmkids)
@@ -1831,9 +1833,9 @@
 						struct cfg80211_pmksa *pmksa,
 						int max_pmkids)
 {
-	int i, err, len, count, newlen;
+	int i, err, newlen;
+	unsigned int count;
 
-	len = le32_to_cpu(pmkids->length);
 	count = le32_to_cpu(pmkids->bssid_info_count);
 
 	if (count > max_pmkids)
@@ -2683,7 +2685,7 @@
 	s32 signal;
 	u64 timestamp;
 	u16 capability;
-	u16 beacon_interval = 0;
+	u32 beacon_period = 0;
 	__le32 rssi;
 	u8 ie_buf[34];
 	int len, ret, ie_len;
@@ -2708,7 +2710,7 @@
 	}
 
 	/* Get channel and beacon interval */
-	channel = get_current_channel(usbdev, &beacon_interval);
+	channel = get_current_channel(usbdev, &beacon_period);
 	if (!channel) {
 		netdev_warn(usbdev->net, "%s(): could not get channel.\n",
 					__func__);
@@ -2738,11 +2740,11 @@
 	netdev_dbg(usbdev->net, "%s(): channel:%d(freq), bssid:[%pM], tsf:%d, "
 		"capa:%x, beacon int:%d, resp_ie(len:%d, essid:'%.32s'), "
 		"signal:%d\n", __func__, (channel ? channel->center_freq : -1),
-		bssid, (u32)timestamp, capability, beacon_interval, ie_len,
+		bssid, (u32)timestamp, capability, beacon_period, ie_len,
 		ssid.essid, signal);
 
 	bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid,
-		timestamp, capability, beacon_interval, ie_buf, ie_len,
+		timestamp, capability, beacon_period, ie_buf, ie_len,
 		signal, GFP_KERNEL);
 	cfg80211_put_bss(bss);
 }
@@ -2755,9 +2757,10 @@
 	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_assoc_info *info = NULL;
 	u8 bssid[ETH_ALEN];
-	int resp_ie_len, req_ie_len;
+	unsigned int resp_ie_len, req_ie_len;
+	unsigned int offset;
 	u8 *req_ie, *resp_ie;
-	int ret, offset;
+	int ret;
 	bool roamed = false;
 	bool match_bss;
 
@@ -2785,7 +2788,9 @@
 		ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE);
 		if (!ret) {
 			req_ie_len = le32_to_cpu(info->req_ie_length);
-			if (req_ie_len > 0) {
+			if (req_ie_len > CONTROL_BUFFER_SIZE)
+				req_ie_len = CONTROL_BUFFER_SIZE;
+			if (req_ie_len != 0) {
 				offset = le32_to_cpu(info->offset_req_ies);
 
 				if (offset > CONTROL_BUFFER_SIZE)
@@ -2799,7 +2804,9 @@
 			}
 
 			resp_ie_len = le32_to_cpu(info->resp_ie_length);
-			if (resp_ie_len > 0) {
+			if (resp_ie_len > CONTROL_BUFFER_SIZE)
+				resp_ie_len = CONTROL_BUFFER_SIZE;
+			if (resp_ie_len != 0) {
 				offset = le32_to_cpu(info->offset_resp_ies);
 
 				if (offset > CONTROL_BUFFER_SIZE)
@@ -3038,7 +3045,7 @@
 			struct rndis_indicate *msg, int buflen)
 {
 	struct ndis_80211_status_indication *indication;
-	int len, offset;
+	unsigned int len, offset;
 
 	offset = offsetof(struct rndis_indicate, status) +
 			le32_to_cpu(msg->offset);
@@ -3050,7 +3057,7 @@
 		return;
 	}
 
-	if (offset + len > buflen) {
+	if (len > buflen || offset > buflen || offset + len > buflen) {
 		netdev_info(usbdev->net, "media specific indication, too large to fit to buffer (%i > %i)\n",
 			    offset + len, buflen);
 		return;
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index e5c05d8..063bfa8 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2475,6 +2475,12 @@
 #define EIRP_MAX_TX_POWER_LIMIT	0x50
 
 /*
+ * Number of TBTT intervals after which we have to adjust
+ * the hw beacon timer.
+ */
+#define BCN_TBTT_OFFSET 64
+
+/*
  * RT2800 driver data structure
  */
 struct rt2800_drv_data {
@@ -2484,6 +2490,7 @@
 	u8 bbp26;
 	u8 txmixer_gain_24g;
 	u8 txmixer_gain_5g;
+	unsigned int tbtt_tick;
 };
 
 #endif /* RT2800_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 474b5b9..6c0a12e 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -4500,7 +4500,9 @@
 	    IEEE80211_HW_SIGNAL_DBM |
 	    IEEE80211_HW_SUPPORTS_PS |
 	    IEEE80211_HW_PS_NULLFUNC_STACK |
-	    IEEE80211_HW_AMPDU_AGGREGATION;
+	    IEEE80211_HW_AMPDU_AGGREGATION |
+	    IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+
 	/*
 	 * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices
 	 * unless we are capable of sending the buffered frames out after the
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 9375db4..0397bbf 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -809,7 +809,33 @@
 static void rt2800pci_tbtt_tasklet(unsigned long data)
 {
 	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+	u32 reg;
+
 	rt2x00lib_beacondone(rt2x00dev);
+
+	if (rt2x00dev->intf_ap_count) {
+		/*
+		 * The rt2800pci hardware tbtt timer is off by 1us per tbtt
+		 * causing beacon skew and as a result causing problems with
+		 * some powersaving clients over time. Shorten the beacon
+		 * interval every 64 beacons by 64us to mitigate this effect.
+		 */
+		if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
+			rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+			rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
+					   (rt2x00dev->beacon_int * 16) - 1);
+			rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+		} else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
+			rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+			rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
+					   (rt2x00dev->beacon_int * 16));
+			rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+		}
+		drv_data->tbtt_tick++;
+		drv_data->tbtt_tick %= BCN_TBTT_OFFSET;
+	}
+
 	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
 }
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 2c11137..cd490ab 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -114,45 +114,103 @@
 	return false;
 }
 
+static inline bool rt2800usb_entry_txstatus_timeout(struct queue_entry *entry)
+{
+	bool tout;
+
+	if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+		return false;
+
+	tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
+	if (unlikely(tout))
+		WARNING(entry->queue->rt2x00dev,
+			"TX status timeout for entry %d in queue %d\n",
+			entry->entry_idx, entry->queue->qid);
+	return tout;
+
+}
+
+static bool rt2800usb_txstatus_timeout(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+	struct queue_entry *entry;
+
+	tx_queue_for_each(rt2x00dev, queue) {
+		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+		if (rt2800usb_entry_txstatus_timeout(entry))
+			return true;
+	}
+	return false;
+}
+
 static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
 						 int urb_status, u32 tx_status)
 {
+	bool valid;
+
 	if (urb_status) {
-		WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status);
+		WARNING(rt2x00dev, "TX status read failed %d\n", urb_status);
+
+		goto stop_reading;
+	}
+
+	valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID);
+	if (valid) {
+		if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status))
+			WARNING(rt2x00dev, "TX status FIFO overrun\n");
+
+		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+
+		/* Reschedule urb to read TX status again instantly */
+		return true;
+	} else if (rt2800usb_txstatus_pending(rt2x00dev)) {
+		/* Read register after 250 us */
+		hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000),
+			      HRTIMER_MODE_REL);
 		return false;
 	}
 
-	/* try to read all TX_STA_FIFO entries before scheduling txdone_work */
-	if (rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID)) {
-		if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) {
-			WARNING(rt2x00dev, "TX status FIFO overrun, "
-				"drop tx status report.\n");
-			queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
-		} else
-			return true;
-	} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
-		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
-	} else if (rt2800usb_txstatus_pending(rt2x00dev)) {
-		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(2));
-	}
+stop_reading:
+	clear_bit(TX_STATUS_READING, &rt2x00dev->flags);
+	/*
+	 * There is small race window above, between txstatus pending check and
+	 * clear_bit someone could do rt2x00usb_interrupt_txdone, so recheck
+	 * here again if status reading is needed.
+	 */
+	if (rt2800usb_txstatus_pending(rt2x00dev) &&
+	    test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
+		return true;
+	else
+		return false;
+}
 
-	return false;
+static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev)
+{
+
+	if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
+		return;
+
+	/* Read TX_STA_FIFO register after 500 us */
+	hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 500000),
+		      HRTIMER_MODE_REL);
 }
 
 static void rt2800usb_tx_dma_done(struct queue_entry *entry)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 
-	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
-				      rt2800usb_tx_sta_fifo_read_completed);
+	rt2800usb_async_read_tx_status(rt2x00dev);
 }
 
-static void rt2800usb_tx_sta_fifo_timeout(unsigned long data)
+static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer)
 {
-	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	struct rt2x00_dev *rt2x00dev =
+	    container_of(timer, struct rt2x00_dev, txstatus_timer);
 
 	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
 				      rt2800usb_tx_sta_fifo_read_completed);
+
+	return HRTIMER_NORESTART;
 }
 
 /*
@@ -438,35 +496,26 @@
 /*
  * TX control handlers
  */
-static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
+static enum txdone_entry_desc_flags
+rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
 {
 	__le32 *txwi;
 	u32 word;
 	int wcid, ack, pid;
-	int tx_wcid, tx_ack, tx_pid;
-
-	if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
-	    !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) {
-		WARNING(entry->queue->rt2x00dev,
-			"Data pending for entry %u in queue %u\n",
-			entry->entry_idx, entry->queue->qid);
-		cond_resched();
-		return false;
-	}
-
-	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
-	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
-	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+	int tx_wcid, tx_ack, tx_pid, is_agg;
 
 	/*
 	 * This frames has returned with an IO error,
 	 * so the status report is not intended for this
 	 * frame.
 	 */
-	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
-		rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
-		return false;
-	}
+	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+		return TXDONE_FAILURE;
+
+	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
+	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+	is_agg	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_AGGRE);
 
 	/*
 	 * Validate if this TX status report is intended for
@@ -479,15 +528,14 @@
 	tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK);
 	tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID);
 
-	if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
+	if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) {
 		WARNING(entry->queue->rt2x00dev,
 			"TX status report missed for queue %d entry %d\n",
-		entry->queue->qid, entry->entry_idx);
-		rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
-		return false;
+			entry->queue->qid, entry->entry_idx);
+		return TXDONE_UNKNOWN;
 	}
 
-	return true;
+	return TXDONE_SUCCESS;
 }
 
 static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
@@ -496,47 +544,44 @@
 	struct queue_entry *entry;
 	u32 reg;
 	u8 qid;
+	enum txdone_entry_desc_flags done_status;
 
 	while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
-
-		/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
-		 * qid is guaranteed to be one of the TX QIDs
+		/*
+		 * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
+		 * guaranteed to be one of the TX QIDs .
 		 */
 		qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
 		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
-		if (unlikely(!queue)) {
-			WARNING(rt2x00dev, "Got TX status for an unavailable "
+
+		if (unlikely(rt2x00queue_empty(queue))) {
+			WARNING(rt2x00dev, "Got TX status for an empty "
 					   "queue %u, dropping\n", qid);
-			continue;
+			break;
 		}
 
-		/*
-		 * Inside each queue, we process each entry in a chronological
-		 * order. We first check that the queue is not empty.
-		 */
-		entry = NULL;
-		while (!rt2x00queue_empty(queue)) {
-			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-			if (rt2800usb_txdone_entry_check(entry, reg))
-				break;
-			entry = NULL;
+		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+
+		if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+			     !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
+			WARNING(rt2x00dev, "Data pending for entry %u "
+					   "in queue %u\n", entry->entry_idx, qid);
+			break;
 		}
 
-		if (entry)
-			rt2800_txdone_entry(entry, reg,
-					    rt2800usb_get_txwi(entry));
+		done_status = rt2800usb_txdone_entry_check(entry, reg);
+		if (likely(done_status == TXDONE_SUCCESS))
+			rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry));
+		else
+			rt2x00lib_txdone_noinfo(entry, done_status);
 	}
 }
 
-static void rt2800usb_work_txdone(struct work_struct *work)
+static void rt2800usb_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
 {
-	struct rt2x00_dev *rt2x00dev =
-	    container_of(work, struct rt2x00_dev, txdone_work);
 	struct data_queue *queue;
 	struct queue_entry *entry;
 
-	rt2800usb_txdone(rt2x00dev);
-
 	/*
 	 * Process any trailing TX status reports for IO failures,
 	 * we loop until we find the first non-IO error entry. This
@@ -554,20 +599,34 @@
 
 			if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
 				rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
-			else if (rt2x00queue_status_timeout(entry))
+			else if (rt2800usb_entry_txstatus_timeout(entry))
 				rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
 			else
 				break;
 		}
 	}
+}
 
-	/*
-	 * The hw may delay sending the packet after DMA complete
-	 * if the medium is busy, thus the TX_STA_FIFO entry is
-	 * also delayed -> use a timer to retrieve it.
-	 */
-	if (rt2800usb_txstatus_pending(rt2x00dev))
-		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(2));
+static void rt2800usb_work_txdone(struct work_struct *work)
+{
+	struct rt2x00_dev *rt2x00dev =
+	    container_of(work, struct rt2x00_dev, txdone_work);
+
+	while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
+	       rt2800usb_txstatus_timeout(rt2x00dev)) {
+
+		rt2800usb_txdone(rt2x00dev);
+
+		rt2800usb_txdone_nostatus(rt2x00dev);
+
+		/*
+		 * The hw may delay sending the packet after DMA complete
+		 * if the medium is busy, thus the TX_STA_FIFO entry is
+		 * also delayed -> use a timer to retrieve it.
+		 */
+		if (rt2800usb_txstatus_pending(rt2x00dev))
+			rt2800usb_async_read_tx_status(rt2x00dev);
+	}
 }
 
 /*
@@ -709,9 +768,7 @@
 	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
 	__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
 
-	setup_timer(&rt2x00dev->txstatus_timer,
-		    rt2800usb_tx_sta_fifo_timeout,
-		    (unsigned long) rt2x00dev);
+	rt2x00dev->txstatus_timer.function = rt2800usb_tx_sta_fifo_timeout,
 
 	/*
 	 * Set the rssi offset.
@@ -813,7 +870,7 @@
 };
 
 static const struct data_queue_desc rt2800usb_queue_tx = {
-	.entry_num		= 64,
+	.entry_num		= 16,
 	.data_size		= AGGREGATION_SIZE,
 	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 65275ef..471f87ca 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -38,7 +38,7 @@
 #include <linux/etherdevice.h>
 #include <linux/input-polldev.h>
 #include <linux/kfifo.h>
-#include <linux/timer.h>
+#include <linux/hrtimer.h>
 
 #include <net/mac80211.h>
 
@@ -692,6 +692,12 @@
 	 */
 	CONFIG_CHANNEL_HT40,
 	CONFIG_POWERSAVING,
+
+	/*
+	 * Mark we currently are sequentially reading TX_STA_FIFO register
+	 * FIXME: this is for only rt2800usb, should go to private data
+	 */
+	TX_STATUS_READING,
 };
 
 /*
@@ -974,7 +980,7 @@
 	/*
 	 * Timer to ensure tx status reports are read (rt2800usb).
 	 */
-	struct timer_list txstatus_timer;
+	struct hrtimer txstatus_timer;
 
 	/*
 	 * Tasklet for processing tx status reports (rt2800pci).
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index d7c0f86..293676b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -102,7 +102,7 @@
 
 	/* Update the AID, this is needed for dynamic PS support */
 	rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;
-	rt2x00dev->last_beacon = bss_conf->timestamp;
+	rt2x00dev->last_beacon = bss_conf->last_tsf;
 
 	/* Update global beacon interval time, this is needed for PS support */
 	rt2x00dev->beacon_int = bss_conf->beacon_int;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 49a51b4..cffcf2e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1232,7 +1232,7 @@
 	cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
 	cancel_work_sync(&rt2x00dev->sleep_work);
 	if (rt2x00_is_usb(rt2x00dev)) {
-		del_timer_sync(&rt2x00dev->txstatus_timer);
+		hrtimer_cancel(&rt2x00dev->txstatus_timer);
 		cancel_work_sync(&rt2x00dev->rxdone_work);
 		cancel_work_sync(&rt2x00dev->txdone_work);
 	}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 349008d..5f1392c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -636,18 +636,6 @@
 {
 	return rt2x00queue_available(queue) < queue->threshold;
 }
-
-/**
- * rt2x00queue_status_timeout - Check if a timeout occurred for STATUS reports
- * @entry: Queue entry to check.
- */
-static inline int rt2x00queue_status_timeout(struct queue_entry *entry)
-{
-	if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-		return false;
-	return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
-}
-
 /**
  * rt2x00queue_dma_timeout - Check if a timeout occurred for DMA transfers
  * @entry: Queue entry to check.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 2eea386..66094eb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -526,22 +526,6 @@
 	rt2x00queue_flush_queue(queue, true);
 }
 
-static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
-{
-	WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
-		" invoke forced tx handler\n", queue->qid);
-
-	queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work);
-}
-
-static int rt2x00usb_status_timeout(struct data_queue *queue)
-{
-	struct queue_entry *entry;
-
-	entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-	return rt2x00queue_status_timeout(entry);
-}
-
 static int rt2x00usb_dma_timeout(struct data_queue *queue)
 {
 	struct queue_entry *entry;
@@ -558,8 +542,6 @@
 		if (!rt2x00queue_empty(queue)) {
 			if (rt2x00usb_dma_timeout(queue))
 				rt2x00usb_watchdog_tx_dma(queue);
-			if (rt2x00usb_status_timeout(queue))
-				rt2x00usb_watchdog_tx_status(queue);
 		}
 	}
 }
@@ -829,7 +811,8 @@
 
 	INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
 	INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
-	init_timer(&rt2x00dev->txstatus_timer);
+	hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
 
 	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	if (retval)
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 638fbef..cf53ac9 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -8,7 +8,7 @@
  * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
  *
  * The driver was extended to the RTL8187B in 2008 by:
- * 	Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ *	Herton Ronaldo Krzesinski <herton@mandriva.com.br>
  *	Hin-Tak Leung <htl10@users.sourceforge.net>
  *	Larry Finger <Larry.Finger@lwfinger.net>
  *
@@ -232,6 +232,7 @@
 {
 	struct rtl8187_priv *priv = dev->priv;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *tx_hdr =	(struct ieee80211_hdr *)(skb->data);
 	unsigned int ep;
 	void *buf;
 	struct urb *urb;
@@ -249,7 +250,7 @@
 	flags |= RTL818X_TX_DESC_FLAG_NO_ENC;
 
 	flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24;
-	if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control))
+	if (ieee80211_has_morefrags(tx_hdr->frame_control))
 		flags |= RTL818X_TX_DESC_FLAG_MOREFRAG;
 	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
 		flags |= RTL818X_TX_DESC_FLAG_RTS;
@@ -261,6 +262,13 @@
 		flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
 	}
 
+	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+		if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+			priv->seqno += 0x10;
+		tx_hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+		tx_hdr->seq_ctrl |= cpu_to_le16(priv->seqno);
+	}
+
 	if (!priv->is_rtl8187b) {
 		struct rtl8187_tx_hdr *hdr =
 			(struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
@@ -274,8 +282,6 @@
 	} else {
 		/* fc needs to be calculated before skb_push() */
 		unsigned int epmap[4] = { 6, 7, 5, 4 };
-		struct ieee80211_hdr *tx_hdr =
-			(struct ieee80211_hdr *)(skb->data);
 		u16 fc = le16_to_cpu(tx_hdr->frame_control);
 
 		struct rtl8187b_tx_hdr *hdr =
@@ -1031,10 +1037,61 @@
 		cancel_delayed_work_sync(&priv->work);
 }
 
+static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	return rtl818x_ioread32(priv, &priv->map->TSFT[0]) |
+	       (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
+}
+
+
+static void rtl8187_beacon_work(struct work_struct *work)
+{
+	struct rtl8187_vif *vif_priv =
+		container_of(work, struct rtl8187_vif, beacon_work.work);
+	struct ieee80211_vif *vif =
+		container_of((void *)vif_priv, struct ieee80211_vif, drv_priv);
+	struct ieee80211_hw *dev = vif_priv->dev;
+	struct ieee80211_mgmt *mgmt;
+	struct sk_buff *skb;
+
+	/* don't overflow the tx ring */
+	if (ieee80211_queue_stopped(dev, 0))
+		goto resched;
+
+	/* grab a fresh beacon */
+	skb = ieee80211_beacon_get(dev, vif);
+	if (!skb)
+		goto resched;
+
+	/*
+	 * update beacon timestamp w/ TSF value
+	 * TODO: make hardware update beacon timestamp
+	 */
+	mgmt = (struct ieee80211_mgmt *)skb->data;
+	mgmt->u.beacon.timestamp = cpu_to_le64(rtl8187_get_tsf(dev, vif));
+
+	/* TODO: use actual beacon queue */
+	skb_set_queue_mapping(skb, 0);
+
+	rtl8187_tx(dev, skb);
+
+resched:
+	/*
+	 * schedule next beacon
+	 * TODO: use hardware support for beacon timing
+	 */
+	schedule_delayed_work(&vif_priv->beacon_work,
+			usecs_to_jiffies(1024 * vif->bss_conf.beacon_int));
+}
+
+
 static int rtl8187_add_interface(struct ieee80211_hw *dev,
 				 struct ieee80211_vif *vif)
 {
 	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_vif *vif_priv;
 	int i;
 	int ret = -EOPNOTSUPP;
 
@@ -1044,6 +1101,7 @@
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_ADHOC:
 		break;
 	default:
 		goto exit;
@@ -1052,6 +1110,13 @@
 	ret = 0;
 	priv->vif = vif;
 
+	/* Initialize driver private area */
+	vif_priv = (struct rtl8187_vif *)&vif->drv_priv;
+	vif_priv->dev = dev;
+	INIT_DELAYED_WORK(&vif_priv->beacon_work, rtl8187_beacon_work);
+	vif_priv->enable_beacon = false;
+
+
 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
 	for (i = 0; i < ETH_ALEN; i++)
 		rtl818x_iowrite8(priv, &priv->map->MAC[i],
@@ -1175,9 +1240,12 @@
 				     u32 changed)
 {
 	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_vif *vif_priv;
 	int i;
 	u8 reg;
 
+	vif_priv = (struct rtl8187_vif *)&vif->drv_priv;
+
 	if (changed & BSS_CHANGED_BSSID) {
 		mutex_lock(&priv->conf_mutex);
 		for (i = 0; i < ETH_ALEN; i++)
@@ -1189,8 +1257,12 @@
 		else
 			reg = 0;
 
-		if (is_valid_ether_addr(info->bssid))
-			reg |= RTL818X_MSR_INFRA;
+		if (is_valid_ether_addr(info->bssid)) {
+			if (vif->type == NL80211_IFTYPE_ADHOC)
+				reg |= RTL818X_MSR_ADHOC;
+			else
+				reg |= RTL818X_MSR_INFRA;
+		}
 		else
 			reg |= RTL818X_MSR_NO_LINK;
 
@@ -1202,6 +1274,16 @@
 	if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE))
 		rtl8187_conf_erp(priv, info->use_short_slot,
 				 info->use_short_preamble);
+
+	if (changed & BSS_CHANGED_BEACON_ENABLED)
+		vif_priv->enable_beacon = info->enable_beacon;
+
+	if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) {
+		cancel_delayed_work_sync(&vif_priv->beacon_work);
+		if (vif_priv->enable_beacon)
+			schedule_work(&vif_priv->beacon_work.work);
+	}
+
 }
 
 static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev,
@@ -1279,13 +1361,6 @@
 	return 0;
 }
 
-static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
-{
-	struct rtl8187_priv *priv = dev->priv;
-
-	return rtl818x_ioread32(priv, &priv->map->TSFT[0]) |
-	       (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
-}
 
 static const struct ieee80211_ops rtl8187_ops = {
 	.tx			= rtl8187_tx,
@@ -1514,12 +1589,9 @@
 		if (reg & 0xFF00)
 			priv->rfkill_mask = RFKILL_MASK_8198;
 	}
-
-	/*
-	 * XXX: Once this driver supports anything that requires
-	 *	beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ.
-	 */
-	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+	dev->vif_data_size = sizeof(struct rtl8187_vif);
+	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				      BIT(NL80211_IFTYPE_ADHOC) ;
 
 	if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
 		printk(KERN_INFO "rtl8187: inconsistency between id with OEM"
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
index f1cc907..e19a20a 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
@@ -89,6 +89,14 @@
 	DEVICE_RTL8187B
 };
 
+struct rtl8187_vif {
+	struct ieee80211_hw *dev;
+
+	/* beaconing */
+	struct delayed_work beacon_work;
+	bool enable_beacon;
+};
+
 struct rtl8187_priv {
 	/* common between rtl818x drivers */
 	struct rtl818x_csr *map;
@@ -141,6 +149,7 @@
 		__le32 bits32;
 	} *io_dmabuf;
 	bool rfkill_off;
+	u16 seqno;
 };
 
 void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index cb5535c..d8d73db 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -520,6 +520,10 @@
 		 dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
 		 dm_digtable.backoff_val);
 
+	dm_digtable.cur_igvalue += 2;
+	if (dm_digtable.cur_igvalue > 0x3f)
+		dm_digtable.cur_igvalue = 0x3f;
+
 	if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
 		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
 			      dm_digtable.cur_igvalue);
@@ -1201,13 +1205,18 @@
 				 "PreState = %d, CurState = %d\n",
 				 p_ra->pre_ratr_state, p_ra->ratr_state);
 
-			rcu_read_lock();
-			sta = ieee80211_find_sta(mac->vif, mac->bssid);
+			/* Only the PCI card uses sta in the update rate table
+			 * callback routine */
+			if (rtlhal->interface == INTF_PCI) {
+				rcu_read_lock();
+				sta = ieee80211_find_sta(mac->vif, mac->bssid);
+			}
 			rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
 					p_ra->ratr_state);
 
 			p_ra->pre_ratr_state = p_ra->ratr_state;
-			rcu_read_unlock();
+			if (rtlhal->interface == INTF_PCI)
+				rcu_read_unlock();
 		}
 	}
 }
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index ffcf89f..2e1e352 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -346,9 +346,14 @@
 			 pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize,
 			 pep_desc->bInterval);
 	}
-	if (rtlusb->in_ep_nums <  rtlpriv->cfg->usb_interface_cfg->in_ep_num)
-		return -EINVAL ;
-
+	if (rtlusb->in_ep_nums <  rtlpriv->cfg->usb_interface_cfg->in_ep_num) {
+		pr_err("Too few input end points found\n");
+		return -EINVAL;
+	}
+	if (rtlusb->out_ep_nums == 0) {
+		pr_err("No output end points found\n");
+		return -EINVAL;
+	}
 	/* usb endpoint mapping */
 	err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw);
 	rtlusb->usb_mq_to_hwq =  rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq;
@@ -357,7 +362,7 @@
 	return err;
 }
 
-static int _rtl_usb_init_sw(struct ieee80211_hw *hw)
+static void rtl_usb_init_sw(struct ieee80211_hw *hw)
 {
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -392,7 +397,6 @@
 	/* HIMR_EX - turn all on */
 	rtlusb->irq_mask[1] = 0xFFFFFFFF;
 	rtlusb->disableHWSM =  true;
-	return 0;
 }
 
 #define __RADIO_TAP_SIZE_RSV	32
@@ -976,7 +980,9 @@
 	}
 	rtlpriv->cfg->ops->init_sw_leds(hw);
 	err = _rtl_usb_init(hw);
-	err = _rtl_usb_init_sw(hw);
+	if (err)
+		goto error_out;
+	rtl_usb_init_sw(hw);
 	/* Init mac80211 sw */
 	err = rtl_init_core(hw);
 	if (err) {
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index b776d9d..3414fc1 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -459,23 +459,39 @@
 
 int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
 {
+	unsigned long flags;
 	u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS);
 	if (link >= WL12XX_MAX_LINKS)
 		return -EBUSY;
 
+	/* these bits are used by op_tx */
+	spin_lock_irqsave(&wl->wl_lock, flags);
 	__set_bit(link, wl->links_map);
 	__set_bit(link, wlvif->links_map);
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
 	*hlid = link;
 	return 0;
 }
 
 void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
 {
+	unsigned long flags;
+
 	if (*hlid == WL12XX_INVALID_LINK_ID)
 		return;
 
+	/* these bits are used by op_tx */
+	spin_lock_irqsave(&wl->wl_lock, flags);
 	__clear_bit(*hlid, wl->links_map);
 	__clear_bit(*hlid, wlvif->links_map);
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+	/*
+	 * At this point op_tx() will not add more packets to the queues. We
+	 * can purge them.
+	 */
+	wl1271_tx_reset_link_queues(wl, *hlid);
+
 	*hlid = WL12XX_INVALID_LINK_ID;
 }
 
@@ -515,7 +531,7 @@
 			goto out_free;
 	}
 	cmd->device.hlid = wlvif->dev_hlid;
-	cmd->device.session = wlvif->session_counter;
+	cmd->device.session = wl12xx_get_new_session_id(wl, wlvif);
 
 	wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d",
 		     cmd->role_id, cmd->device.hlid, cmd->device.session);
@@ -1802,6 +1818,14 @@
 		goto out;
 
 	__clear_bit(role_id, wl->roc_map);
+
+	/*
+	 * Rearm the tx watchdog when removing the last ROC. This prevents
+	 * recoveries due to just finished ROCs - when Tx hasn't yet had
+	 * a chance to get out.
+	 */
+	if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) >= WL12XX_MAX_ROLES)
+		wl12xx_rearm_tx_watchdog_locked(wl);
 out:
 	return ret;
 }
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index cc50faa..3e581e1 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -690,6 +690,9 @@
 	 */
 	u8 tmpl_short_retry_limit;
 	u8 tmpl_long_retry_limit;
+
+	/* Time in ms for Tx watchdog timer to expire */
+	u32 tx_watchdog_timeout;
 };
 
 enum {
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index adf9bbc..3900236 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -217,6 +217,7 @@
 		.basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
 		.tmpl_short_retry_limit      = 10,
 		.tmpl_long_retry_limit       = 10,
+		.tx_watchdog_timeout         = 5000,
 	},
 	.conn = {
 		.wake_up_event               = CONF_WAKE_UP_EVENT_DTIM,
@@ -246,7 +247,7 @@
 		.psm_entry_retries           = 8,
 		.psm_exit_retries            = 16,
 		.psm_entry_nullfunc_retries  = 3,
-		.dynamic_ps_timeout          = 100,
+		.dynamic_ps_timeout          = 200,
 		.forced_ps                   = false,
 		.keep_alive_interval         = 55000,
 		.max_listen_interval         = 20,
@@ -392,15 +393,15 @@
 static void wl1271_op_stop(struct ieee80211_hw *hw);
 static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif);
 
-static DEFINE_MUTEX(wl_list_mutex);
-static LIST_HEAD(wl_list);
-
-static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
-				  unsigned char operstate)
+static int wl12xx_set_authorized(struct wl1271 *wl,
+				 struct wl12xx_vif *wlvif)
 {
 	int ret;
 
-	if (operstate != IF_OPER_UP)
+	if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS))
+		return -EINVAL;
+
+	if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
 		return 0;
 
 	if (test_and_set_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags))
@@ -415,76 +416,6 @@
 	wl1271_info("Association completed.");
 	return 0;
 }
-static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
-			     void *arg)
-{
-	struct net_device *dev = arg;
-	struct wireless_dev *wdev;
-	struct wiphy *wiphy;
-	struct ieee80211_hw *hw;
-	struct wl1271 *wl;
-	struct wl1271 *wl_temp;
-	struct wl12xx_vif *wlvif;
-	int ret = 0;
-
-	/* Check that this notification is for us. */
-	if (what != NETDEV_CHANGE)
-		return NOTIFY_DONE;
-
-	wdev = dev->ieee80211_ptr;
-	if (wdev == NULL)
-		return NOTIFY_DONE;
-
-	wiphy = wdev->wiphy;
-	if (wiphy == NULL)
-		return NOTIFY_DONE;
-
-	hw = wiphy_priv(wiphy);
-	if (hw == NULL)
-		return NOTIFY_DONE;
-
-	wl_temp = hw->priv;
-	mutex_lock(&wl_list_mutex);
-	list_for_each_entry(wl, &wl_list, list) {
-		if (wl == wl_temp)
-			break;
-	}
-	mutex_unlock(&wl_list_mutex);
-	if (wl != wl_temp)
-		return NOTIFY_DONE;
-
-	mutex_lock(&wl->mutex);
-
-	if (wl->state == WL1271_STATE_OFF)
-		goto out;
-
-	if (dev->operstate != IF_OPER_UP)
-		goto out;
-	/*
-	 * The correct behavior should be just getting the appropriate wlvif
-	 * from the given dev, but currently we don't have a mac80211
-	 * interface for it.
-	 */
-	wl12xx_for_each_wlvif_sta(wl, wlvif) {
-		struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
-
-		if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
-			continue;
-
-		ret = wl1271_ps_elp_wakeup(wl);
-		if (ret < 0)
-			goto out;
-
-		wl1271_check_operstate(wl, wlvif,
-				       ieee80211_get_operstate(vif));
-
-		wl1271_ps_elp_sleep(wl);
-	}
-out:
-	mutex_unlock(&wl->mutex);
-
-	return NOTIFY_OK;
-}
 
 static int wl1271_reg_notify(struct wiphy *wiphy,
 			     struct regulatory_request *request)
@@ -623,6 +554,80 @@
 	ieee80211_queue_work(wl->hw, &wlvif->rx_streaming_disable_work);
 }
 
+/* wl->mutex must be taken */
+void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl)
+{
+	/* if the watchdog is not armed, don't do anything */
+	if (wl->tx_allocated_blocks == 0)
+		return;
+
+	cancel_delayed_work(&wl->tx_watchdog_work);
+	ieee80211_queue_delayed_work(wl->hw, &wl->tx_watchdog_work,
+		msecs_to_jiffies(wl->conf.tx.tx_watchdog_timeout));
+}
+
+static void wl12xx_tx_watchdog_work(struct work_struct *work)
+{
+	struct delayed_work *dwork;
+	struct wl1271 *wl;
+
+	dwork = container_of(work, struct delayed_work, work);
+	wl = container_of(dwork, struct wl1271, tx_watchdog_work);
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1271_STATE_OFF))
+		goto out;
+
+	/* Tx went out in the meantime - everything is ok */
+	if (unlikely(wl->tx_allocated_blocks == 0))
+		goto out;
+
+	/*
+	 * if a ROC is in progress, we might not have any Tx for a long
+	 * time (e.g. pending Tx on the non-ROC channels)
+	 */
+	if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES) {
+		wl1271_debug(DEBUG_TX, "No Tx (in FW) for %d ms due to ROC",
+			     wl->conf.tx.tx_watchdog_timeout);
+		wl12xx_rearm_tx_watchdog_locked(wl);
+		goto out;
+	}
+
+	/*
+	 * if a scan is in progress, we might not have any Tx for a long
+	 * time
+	 */
+	if (wl->scan.state != WL1271_SCAN_STATE_IDLE) {
+		wl1271_debug(DEBUG_TX, "No Tx (in FW) for %d ms due to scan",
+			     wl->conf.tx.tx_watchdog_timeout);
+		wl12xx_rearm_tx_watchdog_locked(wl);
+		goto out;
+	}
+
+	/*
+	* AP might cache a frame for a long time for a sleeping station,
+	* so rearm the timer if there's an AP interface with stations. If
+	* Tx is genuinely stuck we will most hopefully discover it when all
+	* stations are removed due to inactivity.
+	*/
+	if (wl->active_sta_count) {
+		wl1271_debug(DEBUG_TX, "No Tx (in FW) for %d ms. AP has "
+			     " %d stations",
+			      wl->conf.tx.tx_watchdog_timeout,
+			      wl->active_sta_count);
+		wl12xx_rearm_tx_watchdog_locked(wl);
+		goto out;
+	}
+
+	wl1271_error("Tx stuck (in FW) for %d ms. Starting recovery",
+		     wl->conf.tx.tx_watchdog_timeout);
+	wl12xx_queue_recovery_work(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+}
+
 static void wl1271_conf_init(struct wl1271 *wl)
 {
 
@@ -815,6 +820,18 @@
 
 	wl->tx_allocated_blocks -= freed_blocks;
 
+	/*
+	 * If the FW freed some blocks:
+	 * If we still have allocated blocks - re-arm the timer, Tx is
+	 * not stuck. Otherwise, cancel the timer (no Tx currently).
+	 */
+	if (freed_blocks) {
+		if (wl->tx_allocated_blocks)
+			wl12xx_rearm_tx_watchdog_locked(wl);
+		else
+			cancel_delayed_work(&wl->tx_watchdog_work);
+	}
+
 	avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks;
 
 	/*
@@ -1224,7 +1241,8 @@
 	wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
 		    wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
 
-	BUG_ON(bug_on_recovery);
+	BUG_ON(bug_on_recovery &&
+	       !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
 
 	/*
 	 * Advance security sequence number to overcome potential progress
@@ -1487,6 +1505,7 @@
 	cancel_work_sync(&wl->netstack_work);
 	cancel_work_sync(&wl->recovery_work);
 	cancel_delayed_work_sync(&wl->elp_work);
+	cancel_delayed_work_sync(&wl->tx_watchdog_work);
 
 	mutex_lock(&wl->mutex);
 	wl1271_power_off(wl);
@@ -1528,7 +1547,8 @@
 		goto out;
 	}
 
-	wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
+	wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d len %d",
+		     hlid, q, skb->len);
 	skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
 
 	wl->tx_queue_count[q]++;
@@ -1626,10 +1646,6 @@
 }
 
 
-static struct notifier_block wl1271_dev_notifier = {
-	.notifier_call = wl1271_dev_notify,
-};
-
 #ifdef CONFIG_PM
 static int wl1271_configure_suspend_sta(struct wl1271 *wl,
 					struct wl12xx_vif *wlvif)
@@ -1737,6 +1753,8 @@
 	wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
 	WARN_ON(!wow || !wow->any);
 
+	wl1271_tx_flush(wl);
+
 	wl->wow_enabled = true;
 	wl12xx_for_each_wlvif(wl, wlvif) {
 		ret = wl1271_configure_suspend(wl, wlvif);
@@ -1854,15 +1872,12 @@
 	wl->state = WL1271_STATE_OFF;
 	mutex_unlock(&wl->mutex);
 
-	mutex_lock(&wl_list_mutex);
-	list_del(&wl->list);
-	mutex_unlock(&wl_list_mutex);
-
 	wl1271_flush_deferred_work(wl);
 	cancel_delayed_work_sync(&wl->scan_complete_work);
 	cancel_work_sync(&wl->netstack_work);
 	cancel_work_sync(&wl->tx_work);
 	cancel_delayed_work_sync(&wl->elp_work);
+	cancel_delayed_work_sync(&wl->tx_watchdog_work);
 
 	/* let's notify MAC80211 about the remaining pending TX frames */
 	wl12xx_tx_reset(wl, true);
@@ -2209,6 +2224,7 @@
 
 	if (wl12xx_need_fw_change(wl, vif_count, true)) {
 		wl12xx_force_active_psm(wl);
+		set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags);
 		mutex_unlock(&wl->mutex);
 		wl1271_recovery_work(&wl->recovery_work);
 		return 0;
@@ -2268,11 +2284,6 @@
 out_unlock:
 	mutex_unlock(&wl->mutex);
 
-	mutex_lock(&wl_list_mutex);
-	if (!ret)
-		list_add(&wl->list, &wl_list);
-	mutex_unlock(&wl_list_mutex);
-
 	return ret;
 }
 
@@ -2296,6 +2307,12 @@
 
 	if (wl->scan.state != WL1271_SCAN_STATE_IDLE &&
 	    wl->scan_vif == vif) {
+		/*
+		 * Rearm the tx watchdog just before idling scan. This
+		 * prevents just-finished scans from triggering the watchdog
+		 */
+		wl12xx_rearm_tx_watchdog_locked(wl);
+
 		wl->scan.state = WL1271_SCAN_STATE_IDLE;
 		memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
 		wl->scan_vif = NULL;
@@ -2398,6 +2415,7 @@
 	WARN_ON(iter != wlvif);
 	if (wl12xx_need_fw_change(wl, vif_count, false)) {
 		wl12xx_force_active_psm(wl);
+		set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags);
 		wl12xx_queue_recovery_work(wl);
 		cancel_recovery = false;
 	}
@@ -2417,7 +2435,7 @@
 	set_bit(WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, &wl->flags);
 	wl1271_op_remove_interface(hw, vif);
 
-	vif->type = ieee80211_iftype_p2p(new_type, p2p);
+	vif->type = new_type;
 	vif->p2p = p2p;
 	ret = wl1271_op_add_interface(hw, vif);
 
@@ -2596,35 +2614,22 @@
 				wl1271_warning("rate policy for channel "
 					       "failed %d", ret);
 
-			if (test_bit(WLVIF_FLAG_STA_ASSOCIATED,
-				     &wlvif->flags)) {
-				if (wl12xx_dev_role_started(wlvif)) {
-					/* roaming */
-					ret = wl12xx_croc(wl,
-							  wlvif->dev_role_id);
-					if (ret < 0)
-						return ret;
-				}
-				ret = wl1271_join(wl, wlvif, false);
+			/*
+			 * change the ROC channel. do it only if we are
+			 * not idle. otherwise, CROC will be called
+			 * anyway.
+			 */
+			if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED,
+				      &wlvif->flags) &&
+			    wl12xx_dev_role_started(wlvif) &&
+			    !(conf->flags & IEEE80211_CONF_IDLE)) {
+				ret = wl12xx_stop_dev(wl, wlvif);
 				if (ret < 0)
-					wl1271_warning("cmd join on channel "
-						       "failed %d", ret);
-			} else {
-				/*
-				 * change the ROC channel. do it only if we are
-				 * not idle. otherwise, CROC will be called
-				 * anyway.
-				 */
-				if (wl12xx_dev_role_started(wlvif) &&
-				    !(conf->flags & IEEE80211_CONF_IDLE)) {
-					ret = wl12xx_stop_dev(wl, wlvif);
-					if (ret < 0)
-						return ret;
+					return ret;
 
-					ret = wl12xx_start_dev(wl, wlvif);
-					if (ret < 0)
-						return ret;
-				}
+				ret = wl12xx_start_dev(wl, wlvif);
+				if (ret < 0)
+					return ret;
 			}
 		}
 	}
@@ -3151,8 +3156,6 @@
 			     struct cfg80211_scan_request *req)
 {
 	struct wl1271 *wl = hw->priv;
-	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
-
 	int ret;
 	u8 *ssid = NULL;
 	size_t len = 0;
@@ -3180,8 +3183,8 @@
 	if (ret < 0)
 		goto out;
 
-	if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) &&
-	    test_bit(wlvif->role_id, wl->roc_map)) {
+	/* fail if there is any role in ROC */
+	if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES) {
 		/* don't allow scanning right now */
 		ret = -EBUSY;
 		goto out_sleep;
@@ -3221,6 +3224,13 @@
 		if (ret < 0)
 			goto out_sleep;
 	}
+
+	/*
+	 * Rearm the tx watchdog just before idling scan. This
+	 * prevents just-finished scans from triggering the watchdog
+	 */
+	wl12xx_rearm_tx_watchdog_locked(wl);
+
 	wl->scan.state = WL1271_SCAN_STATE_IDLE;
 	memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
 	wl->scan_vif = NULL;
@@ -3744,10 +3754,8 @@
 			ibss_joined = true;
 		} else {
 			if (test_and_clear_bit(WLVIF_FLAG_IBSS_JOINED,
-					       &wlvif->flags)) {
+					       &wlvif->flags))
 				wl1271_unjoin(wl, wlvif);
-				wl12xx_start_dev(wl, wlvif);
-			}
 		}
 	}
 
@@ -3765,7 +3773,7 @@
 		do_join = true;
 	}
 
-	if (changed & BSS_CHANGED_IDLE) {
+	if (changed & BSS_CHANGED_IDLE && !is_ibss) {
 		ret = wl1271_sta_handle_idle(wl, wlvif, bss_conf->idle);
 		if (ret < 0)
 			wl1271_warning("idle mode change failed %d", ret);
@@ -3821,6 +3829,7 @@
 			u32 rates;
 			int ieoffset;
 			wlvif->aid = bss_conf->aid;
+			wlvif->beacon_int = bss_conf->beacon_int;
 			set_assoc = true;
 
 			/*
@@ -3901,7 +3910,6 @@
 
 			/* restore the bssid filter and go to dummy bssid */
 			if (was_assoc) {
-				u32 conf_flags = wl->hw->conf.flags;
 				/*
 				 * we might have to disable roc, if there was
 				 * no IF_OPER_UP notification.
@@ -3924,7 +3932,7 @@
 				}
 
 				wl1271_unjoin(wl, wlvif);
-				if (!(conf_flags & IEEE80211_CONF_IDLE))
+				if (!bss_conf->idle)
 					wl12xx_start_dev(wl, wlvif);
 			}
 		}
@@ -3968,8 +3976,8 @@
 			if (ret < 0)
 				goto out;
 
-			wl1271_check_operstate(wl, wlvif,
-					       ieee80211_get_operstate(vif));
+			if (test_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags))
+				wl12xx_set_authorized(wl, wlvif);
 		}
 		/*
 		 * stop device role if started (we might already be in
@@ -4228,107 +4236,155 @@
 	clear_bit(hlid, wlvif->ap.sta_hlid_map);
 	memset(wl->links[hlid].addr, 0, ETH_ALEN);
 	wl->links[hlid].ba_bitmap = 0;
-	wl1271_tx_reset_link_queues(wl, hlid);
 	__clear_bit(hlid, &wl->ap_ps_map);
 	__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
 	wl12xx_free_link(wl, wlvif, &hlid);
 	wl->active_sta_count--;
+
+	/*
+	 * rearm the tx watchdog when the last STA is freed - give the FW a
+	 * chance to return STA-buffered packets before complaining.
+	 */
+	if (wl->active_sta_count == 0)
+		wl12xx_rearm_tx_watchdog_locked(wl);
 }
 
-static int wl1271_op_sta_add(struct ieee80211_hw *hw,
-			     struct ieee80211_vif *vif,
-			     struct ieee80211_sta *sta)
+static int wl12xx_sta_add(struct wl1271 *wl,
+			  struct wl12xx_vif *wlvif,
+			  struct ieee80211_sta *sta)
 {
-	struct wl1271 *wl = hw->priv;
-	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 	struct wl1271_station *wl_sta;
 	int ret = 0;
 	u8 hlid;
 
-	mutex_lock(&wl->mutex);
-
-	if (unlikely(wl->state == WL1271_STATE_OFF))
-		goto out;
-
-	if (wlvif->bss_type != BSS_TYPE_AP_BSS)
-		goto out;
-
 	wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid);
 
 	ret = wl1271_allocate_sta(wl, wlvif, sta);
 	if (ret < 0)
-		goto out;
+		return ret;
 
 	wl_sta = (struct wl1271_station *)sta->drv_priv;
 	hlid = wl_sta->hlid;
 
-	ret = wl1271_ps_elp_wakeup(wl);
-	if (ret < 0)
-		goto out_free_sta;
-
 	ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid);
 	if (ret < 0)
-		goto out_sleep;
-
-	ret = wl12xx_cmd_set_peer_state(wl, hlid);
-	if (ret < 0)
-		goto out_sleep;
-
-	ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, hlid);
-	if (ret < 0)
-		goto out_sleep;
-
-out_sleep:
-	wl1271_ps_elp_sleep(wl);
-
-out_free_sta:
-	if (ret < 0)
 		wl1271_free_sta(wl, wlvif, hlid);
 
-out:
-	mutex_unlock(&wl->mutex);
 	return ret;
 }
 
-static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
-				struct ieee80211_vif *vif,
-				struct ieee80211_sta *sta)
+static int wl12xx_sta_remove(struct wl1271 *wl,
+			     struct wl12xx_vif *wlvif,
+			     struct ieee80211_sta *sta)
 {
-	struct wl1271 *wl = hw->priv;
-	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 	struct wl1271_station *wl_sta;
 	int ret = 0, id;
 
-	mutex_lock(&wl->mutex);
-
-	if (unlikely(wl->state == WL1271_STATE_OFF))
-		goto out;
-
-	if (wlvif->bss_type != BSS_TYPE_AP_BSS)
-		goto out;
-
 	wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid);
 
 	wl_sta = (struct wl1271_station *)sta->drv_priv;
 	id = wl_sta->hlid;
 	if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map)))
+		return -EINVAL;
+
+	ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid);
+	if (ret < 0)
+		return ret;
+
+	wl1271_free_sta(wl, wlvif, wl_sta->hlid);
+	return ret;
+}
+
+static int wl12xx_update_sta_state(struct wl1271 *wl,
+				   struct wl12xx_vif *wlvif,
+				   struct ieee80211_sta *sta,
+				   enum ieee80211_sta_state old_state,
+				   enum ieee80211_sta_state new_state)
+{
+	struct wl1271_station *wl_sta;
+	u8 hlid;
+	bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS;
+	bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS;
+	int ret;
+
+	wl_sta = (struct wl1271_station *)sta->drv_priv;
+	hlid = wl_sta->hlid;
+
+	/* Add station (AP mode) */
+	if (is_ap &&
+	    old_state == IEEE80211_STA_NOTEXIST &&
+	    new_state == IEEE80211_STA_NONE)
+		return wl12xx_sta_add(wl, wlvif, sta);
+
+	/* Remove station (AP mode) */
+	if (is_ap &&
+	    old_state == IEEE80211_STA_NONE &&
+	    new_state == IEEE80211_STA_NOTEXIST) {
+		/* must not fail */
+		wl12xx_sta_remove(wl, wlvif, sta);
+		return 0;
+	}
+
+	/* Authorize station (AP mode) */
+	if (is_ap &&
+	    new_state == IEEE80211_STA_AUTHORIZED) {
+		ret = wl12xx_cmd_set_peer_state(wl, hlid);
+		if (ret < 0)
+			return ret;
+
+		ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true,
+						     hlid);
+		return ret;
+	}
+
+	/* Authorize station */
+	if (is_sta &&
+	    new_state == IEEE80211_STA_AUTHORIZED) {
+		set_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags);
+		return wl12xx_set_authorized(wl, wlvif);
+	}
+
+	if (is_sta &&
+	    old_state == IEEE80211_STA_AUTHORIZED &&
+	    new_state == IEEE80211_STA_ASSOC) {
+		clear_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags);
+		return 0;
+	}
+
+	return 0;
+}
+
+static int wl12xx_op_sta_state(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ieee80211_sta *sta,
+			       enum ieee80211_sta_state old_state,
+			       enum ieee80211_sta_state new_state)
+{
+	struct wl1271 *wl = hw->priv;
+	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+	int ret;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 sta %d state=%d->%d",
+		     sta->aid, old_state, new_state);
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1271_STATE_OFF)) {
+		ret = -EBUSY;
 		goto out;
+	}
 
 	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
-	ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid);
-	if (ret < 0)
-		goto out_sleep;
+	ret = wl12xx_update_sta_state(wl, wlvif, sta, old_state, new_state);
 
-	wl1271_free_sta(wl, wlvif, wl_sta->hlid);
-
-out_sleep:
 	wl1271_ps_elp_sleep(wl);
-
 out:
 	mutex_unlock(&wl->mutex);
+	if (new_state < old_state)
+		return 0;
 	return ret;
 }
 
@@ -4497,6 +4553,8 @@
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
 
+	wl1271_tx_flush(wl);
+
 	mutex_lock(&wl->mutex);
 
 	if (unlikely(wl->state == WL1271_STATE_OFF)) {
@@ -4795,8 +4853,7 @@
 	.conf_tx = wl1271_op_conf_tx,
 	.get_tsf = wl1271_op_get_tsf,
 	.get_survey = wl1271_op_get_survey,
-	.sta_add = wl1271_op_sta_add,
-	.sta_remove = wl1271_op_sta_remove,
+	.sta_state = wl12xx_op_sta_state,
 	.ampdu_action = wl1271_op_ampdu_action,
 	.tx_frames_pending = wl1271_tx_frames_pending,
 	.set_bitrate_mask = wl12xx_set_bitrate_mask,
@@ -5117,8 +5174,6 @@
 
 	wl1271_debugfs_init(wl);
 
-	register_netdevice_notifier(&wl1271_dev_notifier);
-
 	wl1271_notice("loaded");
 
 out:
@@ -5130,7 +5185,6 @@
 	if (wl->plt)
 		wl1271_plt_stop(wl);
 
-	unregister_netdevice_notifier(&wl1271_dev_notifier);
 	ieee80211_unregister_hw(wl->hw);
 	wl->mac80211_registered = false;
 
@@ -5251,7 +5305,6 @@
 	wl = hw->priv;
 	memset(wl, 0, sizeof(*wl));
 
-	INIT_LIST_HEAD(&wl->list);
 	INIT_LIST_HEAD(&wl->wlvif_list);
 
 	wl->hw = hw;
@@ -5268,6 +5321,7 @@
 	INIT_WORK(&wl->tx_work, wl1271_tx_work);
 	INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
 	INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
+	INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work);
 
 	wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
 	if (!wl->freezable_wq) {
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 23d6750..78f598b 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -69,8 +69,6 @@
 	mutex_unlock(&wl->mutex);
 }
 
-#define ELP_ENTRY_DELAY  5
-
 /* Routines to toggle sleep mode while in ELP */
 void wl1271_ps_elp_sleep(struct wl1271 *wl)
 {
@@ -90,7 +88,7 @@
 	}
 
 	ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
-				     msecs_to_jiffies(ELP_ENTRY_DELAY));
+		msecs_to_jiffies(wl->conf.conn.dynamic_ps_timeout));
 }
 
 int wl1271_ps_elp_wakeup(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index e43a6b2..fcba055 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -55,6 +55,12 @@
 	vif = wl->scan_vif;
 	wlvif = wl12xx_vif_to_data(vif);
 
+	/*
+	 * Rearm the tx watchdog just before idling scan. This
+	 * prevents just-finished scans from triggering the watchdog
+	 */
+	wl12xx_rearm_tx_watchdog_locked(wl);
+
 	wl->scan.state = WL1271_SCAN_STATE_IDLE;
 	memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
 	wl->scan.req = NULL;
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 6446e4d..43ae491 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -226,6 +226,10 @@
 		wl->tx_blocks_available -= total_blocks;
 		wl->tx_allocated_blocks += total_blocks;
 
+		/* If the FW was empty before, arm the Tx watchdog */
+		if (wl->tx_allocated_blocks == total_blocks)
+			wl12xx_rearm_tx_watchdog_locked(wl);
+
 		ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		wl->tx_allocated_pkts[ac]++;
 
@@ -527,6 +531,7 @@
 	if (skb) {
 		int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		spin_lock_irqsave(&wl->wl_lock, flags);
+		WARN_ON_ONCE(wl->tx_queue_count[q] <= 0);
 		wl->tx_queue_count[q]--;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
 	}
@@ -571,6 +576,7 @@
 	struct wl12xx_vif *wlvif = wl->last_wlvif;
 	struct sk_buff *skb = NULL;
 
+	/* continue from last wlvif (round robin) */
 	if (wlvif) {
 		wl12xx_for_each_wlvif_continue(wl, wlvif) {
 			skb = wl12xx_vif_skb_dequeue(wl, wlvif);
@@ -581,7 +587,11 @@
 		}
 	}
 
-	/* do another pass */
+	/* dequeue from the system HLID before the restarting wlvif list */
+	if (!skb)
+		skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]);
+
+	/* do a new pass over the wlvif list */
 	if (!skb) {
 		wl12xx_for_each_wlvif(wl, wlvif) {
 			skb = wl12xx_vif_skb_dequeue(wl, wlvif);
@@ -589,12 +599,16 @@
 				wl->last_wlvif = wlvif;
 				break;
 			}
+
+			/*
+			 * No need to continue after last_wlvif. The previous
+			 * pass should have found it.
+			 */
+			if (wlvif == wl->last_wlvif)
+				break;
 		}
 	}
 
-	if (!skb)
-		skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]);
-
 	if (!skb &&
 	    test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
 		int q;
@@ -602,6 +616,7 @@
 		skb = wl->dummy_packet;
 		q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		spin_lock_irqsave(&wl->wl_lock, flags);
+		WARN_ON_ONCE(wl->tx_queue_count[q] <= 0);
 		wl->tx_queue_count[q]--;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
 	}
@@ -959,7 +974,6 @@
 		else
 			wlvif->sta.ba_rx_bitmap = 0;
 
-		wl1271_tx_reset_link_queues(wl, i);
 		wl->links[i].allocated_pkts = 0;
 		wl->links[i].prev_freed_pkts = 0;
 	}
@@ -973,8 +987,14 @@
 	struct sk_buff *skb;
 	struct ieee80211_tx_info *info;
 
-	for (i = 0; i < NUM_TX_QUEUES; i++)
-		wl->tx_queue_count[i] = 0;
+	/* only reset the queues if something bad happened */
+	if (WARN_ON_ONCE(wl1271_tx_total_queue_count(wl) != 0)) {
+		for (i = 0; i < WL12XX_MAX_LINKS; i++)
+			wl1271_tx_reset_link_queues(wl, i);
+
+		for (i = 0; i < NUM_TX_QUEUES; i++)
+			wl->tx_queue_count[i] = 0;
+	}
 
 	wl->stopped_queues_map = 0;
 
@@ -1024,6 +1044,7 @@
 void wl1271_tx_flush(struct wl1271 *wl)
 {
 	unsigned long timeout;
+	int i;
 	timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT);
 
 	while (!time_after(jiffies, timeout)) {
@@ -1041,6 +1062,12 @@
 	}
 
 	wl1271_warning("Unable to flush all TX buffers, timed out.");
+
+	/* forcibly flush all Tx buffers on our queues */
+	mutex_lock(&wl->mutex);
+	for (i = 0; i < WL12XX_MAX_LINKS; i++)
+		wl1271_tx_reset_link_queues(wl, i);
+	mutex_unlock(&wl->mutex);
 }
 
 u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set)
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index e3977b5..5cf8c32 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -227,5 +227,6 @@
 
 /* from main.c */
 void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
+void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl);
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 9035241..749a15a 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -260,11 +260,13 @@
 	WL1271_FLAG_SOFT_GEMINI,
 	WL1271_FLAG_RECOVERY_IN_PROGRESS,
 	WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
+	WL1271_FLAG_INTENDED_FW_RECOVERY,
 };
 
 enum wl12xx_vif_flags {
 	WLVIF_FLAG_INITIALIZED,
 	WLVIF_FLAG_STA_ASSOCIATED,
+	WLVIF_FLAG_STA_AUTHORIZED,
 	WLVIF_FLAG_IBSS_JOINED,
 	WLVIF_FLAG_AP_STARTED,
 	WLVIF_FLAG_IN_PS,
@@ -452,8 +454,6 @@
 
 	bool enable_11a;
 
-	struct list_head list;
-
 	/* Most recently reported noise in dBm */
 	s8 noise;
 
@@ -495,6 +495,9 @@
 
 	/* last wlvif we transmitted from */
 	struct wl12xx_vif *last_wlvif;
+
+	/* work to fire when Tx is stuck */
+	struct delayed_work tx_watchdog_work;
 };
 
 struct wl1271_station {
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 1a1500b..cb6204f 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -736,6 +736,8 @@
 
 	nfc_tgt->sens_res = be16_to_cpu(tgt_type_a->sens_res);
 	nfc_tgt->sel_res = tgt_type_a->sel_res;
+	nfc_tgt->nfcid1_len = tgt_type_a->nfcid_len;
+	memcpy(nfc_tgt->nfcid1, tgt_type_a->nfcid_data, nfc_tgt->nfcid1_len);
 
 	return 0;
 }
@@ -781,6 +783,9 @@
 	else
 		nfc_tgt->supported_protocols = NFC_PROTO_FELICA_MASK;
 
+	memcpy(nfc_tgt->sensf_res, &tgt_felica->opcode, 9);
+	nfc_tgt->sensf_res_len = 9;
+
 	return 0;
 }
 
@@ -823,6 +828,8 @@
 
 	nfc_tgt->supported_protocols = NFC_PROTO_JEWEL_MASK;
 	nfc_tgt->sens_res = be16_to_cpu(tgt_jewel->sens_res);
+	nfc_tgt->nfcid1_len = 4;
+	memcpy(nfc_tgt->nfcid1, tgt_jewel->jewelid, nfc_tgt->nfcid1_len);
 
 	return 0;
 }
@@ -902,6 +909,8 @@
 	if (resp->tg != 1)
 		return -EPROTO;
 
+	memset(&nfc_tgt, 0, sizeof(struct nfc_target));
+
 	target_data_len = resp_len - sizeof(struct pn533_poll_response);
 
 	switch (dev->poll_mod_curr) {
@@ -1307,6 +1316,8 @@
 		nfc_dev_dbg(&dev->interface->dev, "Creating new target");
 
 		nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+		nfc_target.nfcid1_len = 10;
+		memcpy(nfc_target.nfcid1, resp->nfcid3t, nfc_target.nfcid1_len);
 		rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1);
 		if (rc)
 			return 0;
@@ -1329,21 +1340,15 @@
 }
 
 static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx,
-						u8 comm_mode, u8 rf_mode)
+			     u8 comm_mode, u8* gb, size_t gb_len)
 {
 	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
 	struct pn533_cmd_jump_dep *cmd;
-	u8 cmd_len, local_gt_len, *local_gt;
+	u8 cmd_len;
 	int rc;
 
 	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
-	if (rf_mode == NFC_RF_TARGET) {
-		nfc_dev_err(&dev->interface->dev, "Target mode not supported");
-		return -EOPNOTSUPP;
-	}
-
-
 	if (dev->poll_mod_count) {
 		nfc_dev_err(&dev->interface->dev,
 				"Cannot bring the DEP link up while polling");
@@ -1356,11 +1361,7 @@
 		return -EBUSY;
 	}
 
-	local_gt = nfc_get_local_general_bytes(dev->nfc_dev, &local_gt_len);
-	if (local_gt_len > NFC_MAX_GT_LEN)
-		return -EINVAL;
-
-	cmd_len = sizeof(struct pn533_cmd_jump_dep) + local_gt_len;
+	cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len;
 	cmd = kzalloc(cmd_len, GFP_KERNEL);
 	if (cmd == NULL)
 		return -ENOMEM;
@@ -1369,9 +1370,9 @@
 
 	cmd->active = !comm_mode;
 	cmd->baud = 0;
-	if (local_gt != NULL) {
+	if (gb != NULL && gb_len > 0) {
 		cmd->next = 4; /* We have some Gi */
-		memcpy(cmd->gt, local_gt, local_gt_len);
+		memcpy(cmd->gt, gb, gb_len);
 	} else {
 		cmd->next = 0;
 	}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index befa89e..ed41244 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -331,7 +331,6 @@
 {
 	int i;
 	u16 v;
-	s8 gain;
 	u16 loc[3];
 
 	if (out->revision == 3)			/* rev 3 moved MAC */
@@ -390,20 +389,12 @@
 		SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
 
 	/* Extract the antenna gain values. */
-	gain = r123_extract_antgain(out->revision, in,
-				    SSB_SPROM1_AGAIN_BG,
-				    SSB_SPROM1_AGAIN_BG_SHIFT);
-	out->antenna_gain.ghz24.a0 = gain;
-	out->antenna_gain.ghz24.a1 = gain;
-	out->antenna_gain.ghz24.a2 = gain;
-	out->antenna_gain.ghz24.a3 = gain;
-	gain = r123_extract_antgain(out->revision, in,
-				    SSB_SPROM1_AGAIN_A,
-				    SSB_SPROM1_AGAIN_A_SHIFT);
-	out->antenna_gain.ghz5.a0 = gain;
-	out->antenna_gain.ghz5.a1 = gain;
-	out->antenna_gain.ghz5.a2 = gain;
-	out->antenna_gain.ghz5.a3 = gain;
+	out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
+						    SSB_SPROM1_AGAIN_BG,
+						    SSB_SPROM1_AGAIN_BG_SHIFT);
+	out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
+						    SSB_SPROM1_AGAIN_A,
+						    SSB_SPROM1_AGAIN_A_SHIFT);
 }
 
 /* Revs 4 5 and 8 have partially shared layout */
@@ -504,16 +495,14 @@
 	}
 
 	/* Extract the antenna gain values. */
-	SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
+	SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
 	     SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
-	SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
+	SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
 	     SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
-	SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
+	SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
 	     SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
-	SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
+	SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
 	     SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
-	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
-	       sizeof(out->antenna_gain.ghz5));
 
 	sprom_extract_r458(out, in);
 
@@ -602,16 +591,14 @@
 	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
 
 	/* Extract the antenna gain values. */
-	SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
+	SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
 	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
-	SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
+	SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
 	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
-	SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
+	SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
 	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
-	SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
+	SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
 	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
-	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
-	       sizeof(out->antenna_gain.ghz5));
 
 	/* Extract cores power info info */
 	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index c821c6b..fbafed5 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -676,14 +676,10 @@
 	case SSB_PCMCIA_CIS_ANTGAIN:
 		GOTO_ERROR_ON(tuple->TupleDataLen != 2,
 			"antg tpl size");
-		sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1];
+		sprom->antenna_gain.a0 = tuple->TupleData[1];
+		sprom->antenna_gain.a1 = tuple->TupleData[1];
+		sprom->antenna_gain.a2 = tuple->TupleData[1];
+		sprom->antenna_gain.a3 = tuple->TupleData[1];
 		break;
 	case SSB_PCMCIA_CIS_BFLAGS:
 		GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c
index 63fd709..b2d36f7 100644
--- a/drivers/ssb/sdio.c
+++ b/drivers/ssb/sdio.c
@@ -551,14 +551,10 @@
 			case SSB_SDIO_CIS_ANTGAIN:
 				GOTO_ERROR_ON(tuple->size != 2,
 					      "antg tpl size");
-				sprom->antenna_gain.ghz24.a0 = tuple->data[1];
-				sprom->antenna_gain.ghz24.a1 = tuple->data[1];
-				sprom->antenna_gain.ghz24.a2 = tuple->data[1];
-				sprom->antenna_gain.ghz24.a3 = tuple->data[1];
-				sprom->antenna_gain.ghz5.a0 = tuple->data[1];
-				sprom->antenna_gain.ghz5.a1 = tuple->data[1];
-				sprom->antenna_gain.ghz5.a2 = tuple->data[1];
-				sprom->antenna_gain.ghz5.a3 = tuple->data[1];
+				sprom->antenna_gain.a0 = tuple->data[1];
+				sprom->antenna_gain.a1 = tuple->data[1];
+				sprom->antenna_gain.a2 = tuple->data[1];
+				sprom->antenna_gain.a3 = tuple->data[1];
 				break;
 			case SSB_SDIO_CIS_BFLAGS:
 				GOTO_ERROR_ON((tuple->size != 3) &&
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index b9f65fb..5af9a07 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -176,6 +176,12 @@
 
 extern void bcma_driver_unregister(struct bcma_driver *drv);
 
+/* Set a fallback SPROM.
+ * See kdoc at the function definition for complete documentation. */
+extern int bcma_arch_register_fallback_sprom(
+		int (*sprom_callback)(struct bcma_bus *bus,
+		struct ssb_sprom *out));
+
 struct bcma_bus {
 	/* The MMIO area. */
 	void __iomem *mmio;
@@ -284,6 +290,7 @@
 	bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
 }
 
+extern struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid);
 extern bool bcma_core_is_enabled(struct bcma_device *core);
 extern void bcma_core_disable(struct bcma_device *core, u32 flags);
 extern int bcma_core_enable(struct bcma_device *core, u32 flags);
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index e72938b..8bbfe31 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -56,6 +56,9 @@
 #define	 BCMA_CC_OTPS_HW_PROTECT	0x00000001
 #define	 BCMA_CC_OTPS_SW_PROTECT	0x00000002
 #define	 BCMA_CC_OTPS_CID_PROTECT	0x00000004
+#define  BCMA_CC_OTPS_GU_PROG_IND	0x00000F00	/* General Use programmed indication */
+#define  BCMA_CC_OTPS_GU_PROG_IND_SHIFT	8
+#define  BCMA_CC_OTPS_GU_PROG_HW	0x00000100	/* HW region programmed */
 #define BCMA_CC_OTPC			0x0014		/* OTP control */
 #define	 BCMA_CC_OTPC_RECWAIT		0xFF000000
 #define	 BCMA_CC_OTPC_PROGWAIT		0x00FFFF00
@@ -72,6 +75,8 @@
 #define	 BCMA_CC_OTPP_READ		0x40000000
 #define	 BCMA_CC_OTPP_START		0x80000000
 #define	 BCMA_CC_OTPP_BUSY		0x80000000
+#define BCMA_CC_OTPL			0x001C		/* OTP layout */
+#define  BCMA_CC_OTPL_GURGN_OFFSET	0x00000FFF	/* offset of general use region */
 #define BCMA_CC_IRQSTAT			0x0020
 #define BCMA_CC_IRQMASK			0x0024
 #define	 BCMA_CC_IRQ_GPIO		0x00000001	/* gpio intr */
@@ -79,6 +84,10 @@
 #define	 BCMA_CC_IRQ_WDRESET		0x80000000	/* watchdog reset occurred */
 #define BCMA_CC_CHIPCTL			0x0028		/* Rev >= 11 only */
 #define BCMA_CC_CHIPSTAT		0x002C		/* Rev >= 11 only */
+#define  BCMA_CC_CHIPST_4313_SPROM_PRESENT	1
+#define  BCMA_CC_CHIPST_4313_OTP_PRESENT	2
+#define  BCMA_CC_CHIPST_4331_SPROM_PRESENT	2
+#define  BCMA_CC_CHIPST_4331_OTP_PRESENT	4
 #define BCMA_CC_JCMD			0x0030		/* Rev >= 10 only */
 #define  BCMA_CC_JCMD_START		0x80000000
 #define  BCMA_CC_JCMD_BUSY		0x80000000
@@ -256,7 +265,6 @@
 #define BCMA_CC_PLLCTL_ADDR		0x0660
 #define BCMA_CC_PLLCTL_DATA		0x0664
 #define BCMA_CC_SPROM			0x0800 /* SPROM beginning */
-#define BCMA_CC_SPROM_PCIE6		0x0830 /* SPROM beginning on PCIe rev >= 6 */
 
 /* Divider allocation in 4716/47162/5356 */
 #define BCMA_CC_PMU5_MAINPLL_CPU	1
diff --git a/include/linux/nfc.h b/include/linux/nfc.h
index b4999ab..39c1fcf 100644
--- a/include/linux/nfc.h
+++ b/include/linux/nfc.h
@@ -107,6 +107,7 @@
 	NFC_ATTR_TARGET_SENSF_RES,
 	NFC_ATTR_COMM_MODE,
 	NFC_ATTR_RF_MODE,
+	NFC_ATTR_DEVICE_POWERED,
 /* private: internal use only */
 	__NFC_ATTR_AFTER_LAST
 };
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index be35a68..e474f6e 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -168,8 +168,8 @@
  *	%NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID,
  *	%NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE,
  *	%NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS,
- *	%NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY and
- *	%NL80211_ATTR_AUTH_TYPE.
+ *	%NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
+ *	%NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT.
  * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP
  * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface
  * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP
@@ -369,6 +369,11 @@
  *	%NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT,
  *	%NL80211_ATTR_CONTROL_PORT_ETHERTYPE and
  *	%NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT.
+ *	Background scan period can optionally be
+ *	specified in %NL80211_ATTR_BG_SCAN_PERIOD,
+ *	if not specified default background scan configuration
+ *	in driver is used and if period value is 0, bg scan will be disabled.
+ *	This attribute is ignored if driver does not support roam scan.
  *	It is also sent as an event, with the BSSID and response IEs when the
  *	connection is established or failed to be established. This can be
  *	determined by the STATUS_CODE attribute.
@@ -1197,6 +1202,19 @@
  * @NL80211_ATTR_NOACK_MAP: This u16 bitmap contains the No Ack Policy of
  *      up to 16 TIDs.
  *
+ * @NL80211_ATTR_INACTIVITY_TIMEOUT: timeout value in seconds, this can be
+ *	used by the drivers which has MLME in firmware and does not have support
+ *	to report per station tx/rx activity to free up the staion entry from
+ *	the list. This needs to be used when the driver advertises the
+ *	capability to timeout the stations.
+ *
+ * @NL80211_ATTR_RX_SIGNAL_DBM: signal strength in dBm (as a 32-bit int);
+ *	this attribute is (depending on the driver capabilities) added to
+ *	received frames indicated with %NL80211_CMD_FRAME.
+ *
+ * @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds
+ *      or 0 to disable background scan.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1442,6 +1460,12 @@
 
 	NL80211_ATTR_NOACK_MAP,
 
+	NL80211_ATTR_INACTIVITY_TIMEOUT,
+
+	NL80211_ATTR_RX_SIGNAL_DBM,
+
+	NL80211_ATTR_BG_SCAN_PERIOD,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2112,6 +2136,10 @@
  * @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding
  * or forwarding entity (default is TRUE - forwarding entity)
  *
+ * @NL80211_MESHCONF_RSSI_THRESHOLD: RSSI threshold in dBm. This specifies the
+ * threshold for average signal strength of candidate station to establish
+ * a peer link.
+ *
  * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
  *
  * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
@@ -2137,6 +2165,7 @@
 	NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
 	NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
 	NL80211_MESHCONF_FORWARDING,
+	NL80211_MESHCONF_RSSI_THRESHOLD,
 
 	/* keep last */
 	__NL80211_MESHCONF_ATTR_AFTER_LAST,
@@ -2804,10 +2833,13 @@
  *	TX status to the socket error queue when requested with the
  *	socket option.
  * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates.
+ * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up
+ *	the connected inactive stations in AP mode.
  */
 enum nl80211_feature_flags {
 	NL80211_FEATURE_SK_TX_STATUS	= 1 << 0,
 	NL80211_FEATURE_HT_IBSS		= 1 << 1,
+	NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
 };
 
 /**
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index bbc2612..d276831 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -19,7 +19,7 @@
 struct ssb_sprom_core_pwr_info {
 	u8 itssi_2g, itssi_5g;
 	u8 maxpwr_2g, maxpwr_5gl, maxpwr_5g, maxpwr_5gh;
-	u16 pa_2g[3], pa_5gl[3], pa_5g[3], pa_5gh[3];
+	u16 pa_2g[4], pa_5gl[4], pa_5g[4], pa_5gh[4];
 };
 
 struct ssb_sprom {
@@ -32,9 +32,12 @@
 	u8 et0mdcport;		/* MDIO for enet0 */
 	u8 et1mdcport;		/* MDIO for enet1 */
 	u16 board_rev;		/* Board revision number from SPROM. */
+	u16 board_num;		/* Board number from SPROM. */
+	u16 board_type;		/* Board type from SPROM. */
 	u8 country_code;	/* Country Code */
-	u16 leddc_on_time;	/* LED Powersave Duty Cycle On Count */
-	u16 leddc_off_time;	/* LED Powersave Duty Cycle Off Count */
+	char alpha2[2];		/* Country Code as two chars like EU or US */
+	u8 leddc_on_time;	/* LED Powersave Duty Cycle On Count */
+	u8 leddc_off_time;	/* LED Powersave Duty Cycle Off Count */
 	u8 ant_available_a;	/* 2GHz antenna available bits (up to 4) */
 	u8 ant_available_bg;	/* 5GHz antenna available bits (up to 4) */
 	u16 pa0b0;
@@ -53,10 +56,10 @@
 	u8 gpio1;		/* GPIO pin 1 */
 	u8 gpio2;		/* GPIO pin 2 */
 	u8 gpio3;		/* GPIO pin 3 */
-	u16 maxpwr_bg;		/* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
-	u16 maxpwr_al;		/* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
-	u16 maxpwr_a;		/* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
-	u16 maxpwr_ah;		/* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
+	u8 maxpwr_bg;		/* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
+	u8 maxpwr_al;		/* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
+	u8 maxpwr_a;		/* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
+	u8 maxpwr_ah;		/* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
 	u8 itssi_a;		/* Idle TSSI Target for A-PHY */
 	u8 itssi_bg;		/* Idle TSSI Target for B/G-PHY */
 	u8 tri2g;		/* 2.4GHz TX isolation */
@@ -67,8 +70,8 @@
 	u8 txpid5gl[4];		/* 4.9 - 5.1GHz TX power index */
 	u8 txpid5g[4];		/* 5.1 - 5.5GHz TX power index */
 	u8 txpid5gh[4];		/* 5.5 - ...GHz TX power index */
-	u8 rxpo2g;		/* 2GHz RX power offset */
-	u8 rxpo5g;		/* 5GHz RX power offset */
+	s8 rxpo2g;		/* 2GHz RX power offset */
+	s8 rxpo5g;		/* 5GHz RX power offset */
 	u8 rssisav2g;		/* 2GHz RSSI params */
 	u8 rssismc2g;
 	u8 rssismf2g;
@@ -94,12 +97,7 @@
 	 * on each band. Values in dBm/4 (Q5.2). Negative gain means the
 	 * loss in the connectors is bigger than the gain. */
 	struct {
-		struct {
-			s8 a0, a1, a2, a3;
-		} ghz24;	/* 2.4GHz band */
-		struct {
-			s8 a0, a1, a2, a3;
-		} ghz5;		/* 5GHz band */
+		s8 a0, a1, a2, a3;
 	} antenna_gain;
 
 	struct {
@@ -111,7 +109,79 @@
 		} ghz5;
 	} fem;
 
-	/* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
+	u16 mcs2gpo[8];
+	u16 mcs5gpo[8];
+	u16 mcs5glpo[8];
+	u16 mcs5ghpo[8];
+	u8 opo;
+
+	u8 rxgainerr2ga[3];
+	u8 rxgainerr5gla[3];
+	u8 rxgainerr5gma[3];
+	u8 rxgainerr5gha[3];
+	u8 rxgainerr5gua[3];
+
+	u8 noiselvl2ga[3];
+	u8 noiselvl5gla[3];
+	u8 noiselvl5gma[3];
+	u8 noiselvl5gha[3];
+	u8 noiselvl5gua[3];
+
+	u8 regrev;
+	u8 txchain;
+	u8 rxchain;
+	u8 antswitch;
+	u16 cddpo;
+	u16 stbcpo;
+	u16 bw40po;
+	u16 bwduppo;
+
+	u8 tempthresh;
+	u8 tempoffset;
+	u16 rawtempsense;
+	u8 measpower;
+	u8 tempsense_slope;
+	u8 tempcorrx;
+	u8 tempsense_option;
+	u8 freqoffset_corr;
+	u8 iqcal_swp_dis;
+	u8 hw_iqcal_en;
+	u8 elna2g;
+	u8 elna5g;
+	u8 phycal_tempdelta;
+	u8 temps_period;
+	u8 temps_hysteresis;
+	u8 measpower1;
+	u8 measpower2;
+	u8 pcieingress_war;
+
+	/* power per rate from sromrev 9 */
+	u16 cckbw202gpo;
+	u16 cckbw20ul2gpo;
+	u32 legofdmbw202gpo;
+	u32 legofdmbw20ul2gpo;
+	u32 legofdmbw205glpo;
+	u32 legofdmbw20ul5glpo;
+	u32 legofdmbw205gmpo;
+	u32 legofdmbw20ul5gmpo;
+	u32 legofdmbw205ghpo;
+	u32 legofdmbw20ul5ghpo;
+	u32 mcsbw202gpo;
+	u32 mcsbw20ul2gpo;
+	u32 mcsbw402gpo;
+	u32 mcsbw205glpo;
+	u32 mcsbw20ul5glpo;
+	u32 mcsbw405glpo;
+	u32 mcsbw205gmpo;
+	u32 mcsbw20ul5gmpo;
+	u32 mcsbw405gmpo;
+	u32 mcsbw205ghpo;
+	u32 mcsbw20ul5ghpo;
+	u32 mcsbw405ghpo;
+	u16 mcs32po;
+	u16 legofdm40duppo;
+	u8 sar2g;
+	u8 sar5g;
 };
 
 /* Information about the PCB the circuitry is soldered on. */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0178c74..69b7ad3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -413,6 +413,7 @@
  * @crypto: crypto settings
  * @privacy: the BSS uses privacy
  * @auth_type: Authentication type (algorithm)
+ * @inactivity_timeout: time in seconds to determine station's inactivity.
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_beacon_data beacon;
@@ -424,6 +425,7 @@
 	struct cfg80211_crypto_settings crypto;
 	bool privacy;
 	enum nl80211_auth_type auth_type;
+	int inactivity_timeout;
 };
 
 /**
@@ -809,6 +811,7 @@
 	 * Still keeping the same nomenclature to be in sync with the spec. */
 	bool  dot11MeshGateAnnouncementProtocol;
 	bool dot11MeshForwarding;
+	s32 rssi_threshold;
 };
 
 /**
@@ -1200,6 +1203,8 @@
  * @key_idx: index of WEP key for shared key authentication
  * @key: WEP key for shared key authentication
  * @flags:  See &enum cfg80211_assoc_req_flags
+ * @bg_scan_period:  Background scan period in seconds
+ *   or -1 to indicate that default value is to be used.
  * @ht_capa:  HT Capabilities over-rides.  Values set in ht_capa_mask
  *   will be used in ht_capa.  Un-supported values will be ignored.
  * @ht_capa_mask:  The bits of ht_capa which are to be used.
@@ -1217,6 +1222,7 @@
 	const u8 *key;
 	u8 key_len, key_idx;
 	u32 flags;
+	int bg_scan_period;
 	struct ieee80211_ht_cap ht_capa;
 	struct ieee80211_ht_cap ht_capa_mask;
 };
@@ -1356,12 +1362,10 @@
  *
  * @set_rekey_data: give the data necessary for GTK rekeying to the driver
  *
- * @add_beacon: Add a beacon with given parameters, @head, @interval
- *	and @dtim_period will be valid, @tail is optional.
- * @set_beacon: Change the beacon parameters for an access point mode
- *	interface. This should reject the call when no beacon has been
- *	configured.
- * @del_beacon: Remove beacon configuration and stop sending the beacon.
+ * @start_ap: Start acting in AP mode defined by the parameters.
+ * @change_beacon: Change the beacon parameters for an access point mode
+ *	interface. This should reject the call when AP mode wasn't started.
+ * @stop_ap: Stop being an AP, including stopping beaconing.
  *
  * @add_station: Add a new station.
  * @del_station: Remove a station; @mac may be NULL to remove all stations.
@@ -2693,7 +2697,7 @@
  * @wiphy: the wiphy reporting the BSS
  * @channel: The channel the frame was received on
  * @bssid: the BSSID of the BSS
- * @timestamp: the TSF timestamp sent by the peer
+ * @tsf: the TSF sent by the peer in the beacon/probe response (or 0)
  * @capability: the capability field sent by the peer
  * @beacon_interval: the beacon interval announced by the peer
  * @ie: additional IEs sent by the peer
@@ -2709,9 +2713,8 @@
 struct cfg80211_bss * __must_check
 cfg80211_inform_bss(struct wiphy *wiphy,
 		    struct ieee80211_channel *channel,
-		    const u8 *bssid,
-		    u64 timestamp, u16 capability, u16 beacon_interval,
-		    const u8 *ie, size_t ielen,
+		    const u8 *bssid, u64 tsf, u16 capability,
+		    u16 beacon_interval, const u8 *ie, size_t ielen,
 		    s32 signal, gfp_t gfp);
 
 struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
@@ -3188,6 +3191,7 @@
  * cfg80211_rx_mgmt - notification of received, unprocessed management frame
  * @dev: network device
  * @freq: Frequency on which the frame was received in MHz
+ * @sig_dbm: signal strength in mBm, or 0 if unknown
  * @buf: Management frame (header + body)
  * @len: length of the frame data
  * @gfp: context flags
@@ -3200,8 +3204,8 @@
  * This function is called whenever an Action frame is received for a station
  * mode interface, but is not processed in kernel.
  */
-bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
-		      size_t len, gfp_t gfp);
+bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm,
+		      const u8 *buf, size_t len, gfp_t gfp);
 
 /**
  * cfg80211_mgmt_tx_status - notification of TX status for management frame
@@ -3314,6 +3318,7 @@
  * @frame: the frame
  * @len: length of the frame
  * @freq: frequency the frame was received on
+ * @sig_dbm: signal strength in mBm, or 0 if unknown
  * @gfp: allocation flags
  *
  * Use this function to report to userspace when a beacon was
@@ -3322,7 +3327,7 @@
  */
 void cfg80211_report_obss_beacon(struct wiphy *wiphy,
 				 const u8 *frame, size_t len,
-				 int freq, gfp_t gfp);
+				 int freq, int sig_dbm, gfp_t gfp);
 
 /*
  * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used
@@ -3334,6 +3339,14 @@
 				 struct ieee80211_channel *chan,
 				 enum nl80211_channel_type channel_type);
 
+/*
+ * cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units)
+ * @rate: given rate_info to calculate bitrate from
+ *
+ * return 0 if MCS index >= 32
+ */
+u16 cfg80211_calculate_bitrate(struct rate_info *rate);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7477f02..9a012be6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -229,7 +229,8 @@
  *	valid in station mode only while @assoc is true and if also
  *	requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf
  *	@ps_dtim_period)
- * @timestamp: beacon timestamp
+ * @last_tsf: last beacon's/probe response's TSF timestamp (could be old
+ *	as it may have been received during scanning long ago)
  * @beacon_int: beacon interval
  * @assoc_capability: capabilities taken from assoc resp
  * @basic_rates: bitmap of basic rates, each bit stands for an
@@ -276,7 +277,7 @@
 	u8 dtim_period;
 	u16 beacon_int;
 	u16 assoc_capability;
-	u64 timestamp;
+	u64 last_tsf;
 	u32 basic_rates;
 	int mcast_rate[IEEE80211_NUM_BANDS];
 	u16 ht_operation_mode;
@@ -659,6 +660,8 @@
  * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
  * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
  * @RX_FLAG_SHORT_GI: Short guard interval was used
+ * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
+ *	Valid only for data frames (mainly A-MPDU)
  */
 enum mac80211_rx_flags {
 	RX_FLAG_MMIC_ERROR	= 1<<0,
@@ -672,6 +675,7 @@
 	RX_FLAG_HT		= 1<<9,
 	RX_FLAG_40MHZ		= 1<<10,
 	RX_FLAG_SHORT_GI	= 1<<11,
+	RX_FLAG_NO_SIGNAL_VAL	= 1<<12,
 };
 
 /**
@@ -1763,20 +1767,6 @@
 };
 
 /**
- * enum ieee80211_tx_sync_type - TX sync type
- * @IEEE80211_TX_SYNC_AUTH: sync TX for authentication
- *	(and possibly also before direct probe)
- * @IEEE80211_TX_SYNC_ASSOC: sync TX for association
- * @IEEE80211_TX_SYNC_ACTION: sync TX for action frame
- *	(not implemented yet)
- */
-enum ieee80211_tx_sync_type {
-	IEEE80211_TX_SYNC_AUTH,
-	IEEE80211_TX_SYNC_ASSOC,
-	IEEE80211_TX_SYNC_ACTION,
-};
-
-/**
  * enum ieee80211_frame_release_type - frame release reason
  * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll
  * @IEEE80211_FRAME_RELEASE_UAPSD: frame(s) released due to
@@ -1886,26 +1876,6 @@
  *	of the bss parameters has changed when a call is made. The callback
  *	can sleep.
  *
- * @tx_sync: Called before a frame is sent to an AP/GO. In the GO case, the
- *	driver should sync with the GO's powersaving so the device doesn't
- *	transmit the frame while the GO is asleep. In the regular AP case
- *	it may be used by drivers for devices implementing other restrictions
- *	on talking to APs, e.g. due to regulatory enforcement or just HW
- *	restrictions.
- *	This function is called for every authentication, association and
- *	action frame separately since applications might attempt to auth
- *	with multiple APs before chosing one to associate to. If it returns
- *	an error, the corresponding authentication, association or frame
- *	transmission is aborted and reported as having failed. It is always
- *	called after tuning to the correct channel.
- *	The callback might be called multiple times before @finish_tx_sync
- *	(but @finish_tx_sync will be called once for each) but in practice
- *	this is unlikely to happen. It can also refuse in that case if the
- *	driver cannot handle that situation.
- *	This callback can sleep.
- * @finish_tx_sync: Called as a counterpart to @tx_sync, unless that returned
- *	an error. This callback can sleep.
- *
  * @prepare_multicast: Prepare for multicast filter configuration.
  *	This callback is optional, and its return value is passed
  *	to configure_filter(). This callback must be atomic.
@@ -2177,13 +2147,6 @@
 				 struct ieee80211_bss_conf *info,
 				 u32 changed);
 
-	int (*tx_sync)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		       const u8 *bssid, enum ieee80211_tx_sync_type type);
-	void (*finish_tx_sync)(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       const u8 *bssid,
-			       enum ieee80211_tx_sync_type type);
-
 	u64 (*prepare_multicast)(struct ieee80211_hw *hw,
 				 struct netdev_hw_addr_list *mc_list);
 	void (*configure_filter)(struct ieee80211_hw *hw,
@@ -3565,6 +3528,8 @@
  * @hw: The hardware the algorithm is invoked for.
  * @sband: The band this frame is being transmitted on.
  * @bss_conf: the current BSS configuration
+ * @skb: the skb that will be transmitted, the control information in it needs
+ *	to be filled in
  * @reported_rate: The rate control algorithm can fill this in to indicate
  *	which rate should be reported to userspace as the current rate and
  *	used for rate calculations in the mesh network.
@@ -3572,12 +3537,11 @@
  *	RTS threshold
  * @short_preamble: whether mac80211 will request short-preamble transmission
  *	if the selected rate supports it
- * @max_rate_idx: user-requested maximum rate (not MCS for now)
+ * @max_rate_idx: user-requested maximum (legacy) rate
  *	(deprecated; this will be removed once drivers get updated to use
  *	rate_idx_mask)
- * @rate_idx_mask: user-requested rate mask (not MCS for now)
- * @skb: the skb that will be transmitted, the control information in it needs
- *	to be filled in
+ * @rate_idx_mask: user-requested (legacy) rate mask
+ * @rate_idx_mcs_mask: user-requested MCS rate mask
  * @bss: whether this frame is sent out in AP or IBSS mode
  */
 struct ieee80211_tx_rate_control {
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 86fee8b..feba740 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -141,17 +141,17 @@
 
 /* ----- NCI Devices ----- */
 struct nci_dev *nci_allocate_device(struct nci_ops *ops,
-				__u32 supported_protocols,
-				int tx_headroom,
-				int tx_tailroom);
+				    __u32 supported_protocols,
+				    int tx_headroom,
+				    int tx_tailroom);
 void nci_free_device(struct nci_dev *ndev);
 int nci_register_device(struct nci_dev *ndev);
 void nci_unregister_device(struct nci_dev *ndev);
 int nci_recv_frame(struct sk_buff *skb);
 
 static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
-						unsigned int len,
-						gfp_t how)
+					    unsigned int len,
+					    gfp_t how)
 {
 	struct sk_buff *skb;
 
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index d253278..bac070b 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -53,15 +53,15 @@
 	int (*dev_down)(struct nfc_dev *dev);
 	int (*start_poll)(struct nfc_dev *dev, u32 protocols);
 	void (*stop_poll)(struct nfc_dev *dev);
-	int (*dep_link_up)(struct nfc_dev *dev, int target_idx,
-				u8 comm_mode, u8 rf_mode);
+	int (*dep_link_up)(struct nfc_dev *dev, int target_idx, u8 comm_mode,
+			   u8 *gb, size_t gb_len);
 	int (*dep_link_down)(struct nfc_dev *dev);
 	int (*activate_target)(struct nfc_dev *dev, u32 target_idx,
-							u32 protocol);
+			       u32 protocol);
 	void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);
 	int (*data_exchange)(struct nfc_dev *dev, u32 target_idx,
-				struct sk_buff *skb, data_exchange_cb_t cb,
-							void *cb_context);
+			     struct sk_buff *skb, data_exchange_cb_t cb,
+			     void *cb_context);
 };
 
 #define NFC_TARGET_IDX_ANY -1
@@ -110,9 +110,9 @@
 extern struct class nfc_class;
 
 struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
-					u32 supported_protocols,
-					int tx_headroom,
-					int tx_tailroom);
+				    u32 supported_protocols,
+				    int tx_headroom,
+				    int tx_tailroom);
 
 /**
  * nfc_free_device - free nfc device
@@ -135,7 +135,7 @@
  * @dev: The parent device
  */
 static inline void nfc_set_parent_dev(struct nfc_dev *nfc_dev,
-					struct device *dev)
+				      struct device *dev)
 {
 	nfc_dev->dev.parent = dev;
 }
@@ -172,17 +172,15 @@
 }
 
 struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
-					unsigned int flags, unsigned int size,
-					unsigned int *err);
+				   unsigned int flags, unsigned int size,
+				   unsigned int *err);
 struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp);
 
 int nfc_set_remote_general_bytes(struct nfc_dev *dev,
-					u8 *gt, u8 gt_len);
+				 u8 *gt, u8 gt_len);
 
-u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len);
-
-int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
-							int ntargets);
+int nfc_targets_found(struct nfc_dev *dev,
+		      struct nfc_target *targets, int ntargets);
 
 int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
 		       u8 comm_mode, u8 rf_mode);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6a77d4c..677d659 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -336,6 +336,20 @@
 		rate->mcs = idx;
 }
 
+void sta_set_rate_info_tx(struct sta_info *sta,
+			  const struct ieee80211_tx_rate *rate,
+			  struct rate_info *rinfo)
+{
+	rinfo->flags = 0;
+	if (rate->flags & IEEE80211_TX_RC_MCS)
+		rinfo->flags |= RATE_INFO_FLAGS_MCS;
+	if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+		rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
+	rate_idx_to_bitrate(rinfo, sta, rate->idx);
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -378,14 +392,7 @@
 		sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
 	}
 
-	sinfo->txrate.flags = 0;
-	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
-		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
-	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
-	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
-		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
-	rate_idx_to_bitrate(&sinfo->txrate, sta, sta->last_tx_rate.idx);
+	sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
 
 	sinfo->rxrate.flags = 0;
 	if (sta->last_rx_rate_flag & RX_FLAG_HT)
@@ -1314,6 +1321,14 @@
 	}
 	if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask))
 		conf->dot11MeshForwarding = nconf->dot11MeshForwarding;
+	if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) {
+		/* our RSSI threshold implementation is supported only for
+		 * devices that report signal in dBm.
+		 */
+		if (!(sdata->local->hw.flags & IEEE80211_HW_SIGNAL_DBM))
+			return -ENOTSUPP;
+		conf->rssi_threshold = nconf->rssi_threshold;
+	}
 	return 0;
 }
 
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index d1f7abd..e00ce8c 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -3,6 +3,7 @@
  */
 
 #include <linux/nl80211.h>
+#include <net/cfg80211.h>
 #include "ieee80211_i.h"
 
 static enum ieee80211_chan_mode
@@ -134,3 +135,29 @@
 
 	return result;
 }
+
+/*
+ * ieee80211_get_tx_channel_type returns the channel type we should
+ * use for packet transmission, given the channel capability and
+ * whatever regulatory flags we have been given.
+ */
+enum nl80211_channel_type ieee80211_get_tx_channel_type(
+				struct ieee80211_local *local,
+				enum nl80211_channel_type channel_type)
+{
+	switch (channel_type) {
+	case NL80211_CHAN_HT40PLUS:
+		if (local->hw.conf.channel->flags &
+				IEEE80211_CHAN_NO_HT40PLUS)
+			return NL80211_CHAN_HT20;
+		break;
+	case NL80211_CHAN_HT40MINUS:
+		if (local->hw.conf.channel->flags &
+				IEEE80211_CHAN_NO_HT40MINUS)
+			return NL80211_CHAN_HT20;
+		break;
+	default:
+		break;
+	}
+	return channel_type;
+}
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 483e96e..cc5b7a6 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -97,85 +97,6 @@
 	.llseek = noop_llseek,
 };
 
-static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf,
-				 size_t count, loff_t *ppos)
-{
-	struct ieee80211_local *local = file->private_data;
-	return mac80211_format_buffer(user_buf, count, ppos, "0x%x\n",
-				      local->uapsd_queues);
-}
-
-static ssize_t uapsd_queues_write(struct file *file,
-				  const char __user *user_buf,
-				  size_t count, loff_t *ppos)
-{
-	struct ieee80211_local *local = file->private_data;
-	u8 val;
-	int ret;
-
-	ret = kstrtou8_from_user(user_buf, count, 0, &val);
-	if (ret)
-		return ret;
-
-	if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
-		return -ERANGE;
-
-	local->uapsd_queues = val;
-
-	return count;
-}
-
-static const struct file_operations uapsd_queues_ops = {
-	.read = uapsd_queues_read,
-	.write = uapsd_queues_write,
-	.open = mac80211_open_file_generic,
-	.llseek = default_llseek,
-};
-
-static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf,
-				     size_t count, loff_t *ppos)
-{
-	struct ieee80211_local *local = file->private_data;
-
-	return mac80211_format_buffer(user_buf, count, ppos, "0x%x\n",
-				      local->uapsd_max_sp_len);
-}
-
-static ssize_t uapsd_max_sp_len_write(struct file *file,
-				      const char __user *user_buf,
-				      size_t count, loff_t *ppos)
-{
-	struct ieee80211_local *local = file->private_data;
-	unsigned long val;
-	char buf[10];
-	size_t len;
-	int ret;
-
-	len = min(count, sizeof(buf) - 1);
-	if (copy_from_user(buf, user_buf, len))
-		return -EFAULT;
-	buf[len] = '\0';
-
-	ret = kstrtoul(buf, 0, &val);
-
-	if (ret)
-		return -EINVAL;
-
-	if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
-		return -ERANGE;
-
-	local->uapsd_max_sp_len = val;
-
-	return count;
-}
-
-static const struct file_operations uapsd_max_sp_len_ops = {
-	.read = uapsd_max_sp_len_read,
-	.write = uapsd_max_sp_len_write,
-	.open = mac80211_open_file_generic,
-	.llseek = default_llseek,
-};
-
 static ssize_t channel_type_read(struct file *file, char __user *user_buf,
 		       size_t count, loff_t *ppos)
 {
@@ -362,8 +283,6 @@
 	DEBUGFS_ADD(wep_iv);
 	DEBUGFS_ADD(queues);
 	DEBUGFS_ADD_MODE(reset, 0200);
-	DEBUGFS_ADD(uapsd_queues);
-	DEBUGFS_ADD(uapsd_max_sp_len);
 	DEBUGFS_ADD(channel_type);
 	DEBUGFS_ADD(hwflags);
 	DEBUGFS_ADD(user_power);
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 510ed1d..a32eeda 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -49,16 +49,15 @@
 	size_t count, loff_t *ppos,
 	ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int))
 {
-	u8 *buf;
+	char buf[64];
 	ssize_t ret;
 
-	buf = kmalloc(count, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
+	if (count >= sizeof(buf))
+		return -E2BIG;
 
-	ret = -EFAULT;
 	if (copy_from_user(buf, userbuf, count))
-		goto freebuf;
+		return -EFAULT;
+	buf[count] = '\0';
 
 	ret = -ENODEV;
 	rtnl_lock();
@@ -66,8 +65,6 @@
 		ret = (*write)(sdata, buf, count);
 	rtnl_unlock();
 
-freebuf:
-	kfree(buf);
 	return ret;
 }
 
@@ -340,6 +337,62 @@
 
 __IEEE80211_IF_FILE_W(tkip_mic_test);
 
+static ssize_t ieee80211_if_fmt_uapsd_queues(
+	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+	const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+	return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_queues);
+}
+
+static ssize_t ieee80211_if_parse_uapsd_queues(
+	struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
+{
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+	u8 val;
+	int ret;
+
+	ret = kstrtou8(buf, 0, &val);
+	if (ret)
+		return ret;
+
+	if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
+		return -ERANGE;
+
+	ifmgd->uapsd_queues = val;
+
+	return buflen;
+}
+__IEEE80211_IF_FILE_W(uapsd_queues);
+
+static ssize_t ieee80211_if_fmt_uapsd_max_sp_len(
+	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+	const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+	return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_max_sp_len);
+}
+
+static ssize_t ieee80211_if_parse_uapsd_max_sp_len(
+	struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
+{
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret)
+		return -EINVAL;
+
+	if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
+		return -ERANGE;
+
+	ifmgd->uapsd_max_sp_len = val;
+
+	return buflen;
+}
+__IEEE80211_IF_FILE_W(uapsd_max_sp_len);
+
 /* AP attributes */
 IEEE80211_IF_FILE(num_sta_authorized, u.ap.num_sta_authorized, ATOMIC);
 IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
@@ -443,6 +496,7 @@
 IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
 		u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
 IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
+IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
 #endif
 
 
@@ -471,6 +525,8 @@
 	DEBUGFS_ADD(ave_beacon);
 	DEBUGFS_ADD_MODE(smps, 0600);
 	DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
+	DEBUGFS_ADD_MODE(uapsd_queues, 0600);
+	DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600);
 }
 
 static void add_ap_files(struct ieee80211_sub_if_data *sdata)
@@ -537,11 +593,15 @@
 
 #ifdef CONFIG_MAC80211_MESH
 
+static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_ADD_MODE(tsf, 0600);
+}
+
 static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
 {
 	struct dentry *dir = debugfs_create_dir("mesh_stats",
 						sdata->debugfs.dir);
-
 #define MESHSTATS_ADD(name)\
 	debugfs_create_file(#name, 0400, dir, sdata, &name##_ops);
 
@@ -581,6 +641,7 @@
 	MESHPARAMS_ADD(dot11MeshHWMPRootMode);
 	MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
 	MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
+	MESHPARAMS_ADD(rssi_threshold);
 #undef MESHPARAMS_ADD
 }
 #endif
@@ -593,6 +654,7 @@
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_MESH_POINT:
 #ifdef CONFIG_MAC80211_MESH
+		add_mesh_files(sdata);
 		add_mesh_stats(sdata);
 		add_mesh_config(sdata);
 #endif
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 70dfb64..af4691f 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -168,41 +168,6 @@
 	trace_drv_return_void(local);
 }
 
-static inline int drv_tx_sync(struct ieee80211_local *local,
-			      struct ieee80211_sub_if_data *sdata,
-			      const u8 *bssid,
-			      enum ieee80211_tx_sync_type type)
-{
-	int ret = 0;
-
-	might_sleep();
-
-	check_sdata_in_driver(sdata);
-
-	trace_drv_tx_sync(local, sdata, bssid, type);
-	if (local->ops->tx_sync)
-		ret = local->ops->tx_sync(&local->hw, &sdata->vif,
-					  bssid, type);
-	trace_drv_return_int(local, ret);
-	return ret;
-}
-
-static inline void drv_finish_tx_sync(struct ieee80211_local *local,
-				      struct ieee80211_sub_if_data *sdata,
-				      const u8 *bssid,
-				      enum ieee80211_tx_sync_type type)
-{
-	might_sleep();
-
-	check_sdata_in_driver(sdata);
-
-	trace_drv_finish_tx_sync(local, sdata, bssid, type);
-	if (local->ops->finish_tx_sync)
-		local->ops->finish_tx_sync(&local->hw, &sdata->vif,
-					   bssid, type);
-	trace_drv_return_void(local);
-}
-
 static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
 					struct netdev_hw_addr_list *mc_list)
 {
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 384e2f0..21d6f52 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -296,7 +296,7 @@
 		__entry->dtimper = info->dtim_period;
 		__entry->bcnint = info->beacon_int;
 		__entry->assoc_cap = info->assoc_capability;
-		__entry->timestamp = info->timestamp;
+		__entry->timestamp = info->last_tsf;
 		__entry->basic_rates = info->basic_rates;
 		__entry->enable_beacon = info->enable_beacon;
 		__entry->ht_operation_mode = info->ht_operation_mode;
@@ -308,49 +308,6 @@
 	)
 );
 
-DECLARE_EVENT_CLASS(tx_sync_evt,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 const u8 *bssid,
-		 enum ieee80211_tx_sync_type type),
-	TP_ARGS(local, sdata, bssid, type),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		__array(char, bssid, ETH_ALEN)
-		__field(u32, sync_type)
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		memcpy(__entry->bssid, bssid, ETH_ALEN);
-		__entry->sync_type = type;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT  VIF_PR_FMT " bssid:%pM type:%d",
-		LOCAL_PR_ARG, VIF_PR_ARG, __entry->bssid, __entry->sync_type
-	)
-);
-
-DEFINE_EVENT(tx_sync_evt, drv_tx_sync,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 const u8 *bssid,
-		 enum ieee80211_tx_sync_type type),
-	TP_ARGS(local, sdata, bssid, type)
-);
-
-DEFINE_EVENT(tx_sync_evt, drv_finish_tx_sync,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 const u8 *bssid,
-		 enum ieee80211_tx_sync_type type),
-	TP_ARGS(local, sdata, bssid, type)
-);
-
 TRACE_EVENT(drv_prepare_multicast,
 	TP_PROTO(struct ieee80211_local *local, int mc_count),
 
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 7f9ac57..33fd8d9 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -66,7 +66,7 @@
 	skb_reset_tail_pointer(skb);
 	skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
 
-	if (memcmp(ifibss->bssid, bssid, ETH_ALEN))
+	if (compare_ether_addr(ifibss->bssid, bssid))
 		sta_info_flush(sdata->local, sdata);
 
 	/* if merging, indicate to driver that we leave the old IBSS */
@@ -403,7 +403,7 @@
 		return;
 
 	if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
-	    memcmp(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) {
+	    compare_ether_addr(mgmt->bssid, sdata->u.ibss.bssid) == 0) {
 
 		rcu_read_lock();
 		sta = sta_info_get(sdata, mgmt->sa);
@@ -508,7 +508,7 @@
 		goto put_bss;
 
 	/* same BSSID */
-	if (memcmp(cbss->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0)
+	if (compare_ether_addr(cbss->bssid, sdata->u.ibss.bssid) == 0)
 		goto put_bss;
 
 	if (rx_status->flag & RX_FLAG_MACTIME_MPDU) {
@@ -831,8 +831,8 @@
 	if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da))
 		return;
 
-	if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 &&
-	    memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
+	if (compare_ether_addr(mgmt->bssid, ifibss->bssid) != 0 &&
+	    !is_broadcast_ether_addr(mgmt->bssid))
 		return;
 
 	end = ((u8 *) mgmt) + len;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index cee0c74..d9798a3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -105,6 +105,44 @@
 	 */
 	bool has_erp_value;
 	u8 erp_value;
+
+	/* Keep track of the corruption of the last beacon/probe response. */
+	u8 corrupt_data;
+
+	/* Keep track of what bits of information we have valid info for. */
+	u8 valid_data;
+};
+
+/**
+ * enum ieee80211_corrupt_data_flags - BSS data corruption flags
+ * @IEEE80211_BSS_CORRUPT_BEACON: last beacon frame received was corrupted
+ * @IEEE80211_BSS_CORRUPT_PROBE_RESP: last probe response received was corrupted
+ *
+ * These are bss flags that are attached to a bss in the
+ * @corrupt_data field of &struct ieee80211_bss.
+ */
+enum ieee80211_bss_corrupt_data_flags {
+	IEEE80211_BSS_CORRUPT_BEACON		= BIT(0),
+	IEEE80211_BSS_CORRUPT_PROBE_RESP	= BIT(1)
+};
+
+/**
+ * enum ieee80211_valid_data_flags - BSS valid data flags
+ * @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE
+ * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE
+ * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE
+ * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE
+ *
+ * These are bss flags that are attached to a bss in the
+ * @valid_data field of &struct ieee80211_bss.  They show which parts
+ * of the data structure were recieved as a result of an un-corrupted
+ * beacon/probe response.
+ */
+enum ieee80211_bss_valid_data_flags {
+	IEEE80211_BSS_VALID_DTIM		= BIT(0),
+	IEEE80211_BSS_VALID_WMM			= BIT(1),
+	IEEE80211_BSS_VALID_RATES		= BIT(2),
+	IEEE80211_BSS_VALID_ERP			= BIT(3)
 };
 
 static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss)
@@ -350,7 +388,6 @@
 
 	u8 key[WLAN_KEY_LEN_WEP104];
 	u8 key_len, key_idx;
-	bool synced;
 	bool done;
 
 	size_t ie_len;
@@ -370,7 +407,7 @@
 	u8 ssid[IEEE80211_MAX_SSID_LEN];
 	u8 ssid_len;
 	u8 supp_rates_len;
-	bool wmm_used, uapsd_used;
+	bool wmm, uapsd;
 	bool have_beacon;
 	bool sent_assoc;
 	bool synced;
@@ -422,6 +459,20 @@
 		IEEE80211_MFP_REQUIRED
 	} mfp; /* management frame protection */
 
+	/*
+	 * Bitmask of enabled u-apsd queues,
+	 * IEEE80211_WMM_IE_STA_QOSINFO_AC_BE & co. Needs a new association
+	 * to take effect.
+	 */
+	unsigned int uapsd_queues;
+
+	/*
+	 * Maximum number of buffered frames AP can deliver during a
+	 * service period, IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL or similar.
+	 * Needs a new association to take effect.
+	 */
+	unsigned int uapsd_max_sp_len;
+
 	int wmm_last_param_set;
 
 	u8 use_4addr;
@@ -480,7 +531,7 @@
 
 	bool control_port;
 
-	u8 bssid[ETH_ALEN];
+	u8 bssid[ETH_ALEN] __aligned(2);
 	u8 ssid[IEEE80211_MAX_SSID_LEN];
 	u8 ssid_len, ie_len;
 	u8 *ie;
@@ -980,20 +1031,6 @@
 				*/
 	unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
 
-	/*
-	 * Bitmask of enabled u-apsd queues,
-	 * IEEE80211_WMM_IE_STA_QOSINFO_AC_BE & co. Needs a new association
-	 * to take effect.
-	 */
-	unsigned int uapsd_queues;
-
-	/*
-	 * Maximum number of buffered frames AP can deliver during a
-	 * service period, IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL or similar.
-	 * Needs a new association to take effect.
-	 */
-	unsigned int uapsd_max_sp_len;
-
 	bool pspolling;
 	bool offchannel_ps_enabled;
 	/*
@@ -1120,6 +1157,9 @@
 	u8 quiet_elem_len;
 	u8 num_of_quiet_elem;	/* can be more the one */
 	u8 timeout_int_len;
+
+	/* whether a parse error occurred while retrieving these elements */
+	bool parse_error;
 };
 
 static inline struct ieee80211_local *hw_to_local(
@@ -1348,7 +1388,8 @@
 void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
 				     struct ieee80211_hdr *hdr, const u8 *tsc,
 				     gfp_t gfp);
-void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata);
+void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
+			       bool bss_notify);
 void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
 
 void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
@@ -1461,6 +1502,9 @@
 				enum nl80211_channel_type chantype);
 enum nl80211_channel_type
 ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info);
+enum nl80211_channel_type ieee80211_get_tx_channel_type(
+					struct ieee80211_local *local,
+					enum nl80211_channel_type channel_type);
 
 #ifdef CONFIG_MAC80211_NOINLINE
 #define debug_noinline noinline
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 620ca8d..401c01f 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -304,7 +304,7 @@
 		 * need to initialise the hardware if the hardware
 		 * doesn't start up with sane defaults
 		 */
-		ieee80211_set_wmm_default(sdata);
+		ieee80211_set_wmm_default(sdata, true);
 	}
 
 	set_bit(SDATA_STATE_RUNNING, &sdata->state);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 36fa805..b581a24 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -595,8 +595,6 @@
 	local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
 	local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
 	local->user_power_level = -1;
-	local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
-	local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
 	wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
 
 	INIT_LIST_HEAD(&local->interfaces);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index c707c8b..e5fbb7c 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -204,7 +204,7 @@
 			kmem_cache_free(rm_cache, p);
 			--entries;
 		} else if ((seqnum == p->seqnum) &&
-			   (memcmp(sa, p->sa, ETH_ALEN) == 0))
+			   (compare_ether_addr(sa, p->sa) == 0))
 			return -1;
 	}
 
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index c7e5c49..8d53b71 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -85,6 +85,8 @@
  * @state_lock: mesh path state lock used to protect changes to the
  * mpath itself.  No need to take this lock when adding or removing
  * an mpath to a hash bucket on a path table.
+ * @rann_snd_addr: the RANN sender address
+ * @is_root: the destination station of this path is a root node
  * @is_gate: the destination station of this path is a mesh gate
  *
  *
@@ -109,6 +111,8 @@
 	u8 discovery_retries;
 	enum mesh_path_flags flags;
 	spinlock_t state_lock;
+	u8 rann_snd_addr[ETH_ALEN];
+	bool is_root;
 	bool is_gate;
 };
 
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 31bc762..1c6f3d0 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/etherdevice.h>
 #include <asm/unaligned.h>
 #include "wme.h"
 #include "mesh.h"
@@ -323,6 +324,7 @@
 				   struct sta_info *sta)
 {
 	struct ieee80211_supported_band *sband;
+	struct rate_info rinfo;
 	/* This should be adjusted for each device */
 	int device_constant = 1 << ARITH_SHIFT;
 	int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
@@ -336,7 +338,9 @@
 	if (sta->fail_avg >= 100)
 		return MAX_METRIC;
 
-	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+	sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo);
+	rate = cfg80211_calculate_bitrate(&rinfo);
+	if (WARN_ON(!rate))
 		return MAX_METRIC;
 
 	err = (sta->fail_avg << ARITH_SHIFT) / 100;
@@ -344,7 +348,6 @@
 	/* bitrate is in units of 100 Kbps, while we need rate in units of
 	 * 1Mbps. This will be corrected on tx_time computation.
 	 */
-	rate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
 	tx_time = (device_constant + 10 * test_frame_len / rate);
 	estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
 	result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
@@ -419,7 +422,7 @@
 		new_metric = MAX_METRIC;
 	exp_time = TU_TO_EXP_TIME(orig_lifetime);
 
-	if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) {
+	if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0) {
 		/* This MP is the originator, we are not interested in this
 		 * frame, except for updating transmitter's path info.
 		 */
@@ -469,7 +472,7 @@
 
 	/* Update and check transmitter routing info */
 	ta = mgmt->sa;
-	if (memcmp(orig_addr, ta, ETH_ALEN) == 0)
+	if (compare_ether_addr(orig_addr, ta) == 0)
 		fresh_info = false;
 	else {
 		fresh_info = true;
@@ -513,8 +516,9 @@
 				    u8 *preq_elem, u32 metric)
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-	struct mesh_path *mpath;
+	struct mesh_path *mpath = NULL;
 	u8 *target_addr, *orig_addr;
+	const u8 *da;
 	u8 target_flags, ttl;
 	u32 orig_sn, target_sn, lifetime;
 	bool reply = false;
@@ -529,7 +533,7 @@
 
 	mhwmp_dbg("received PREQ from %pM", orig_addr);
 
-	if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) {
+	if (compare_ether_addr(target_addr, sdata->vif.addr) == 0) {
 		mhwmp_dbg("PREQ is for us");
 		forward = false;
 		reply = true;
@@ -591,9 +595,11 @@
 		flags = PREQ_IE_FLAGS(preq_elem);
 		preq_id = PREQ_IE_PREQ_ID(preq_elem);
 		hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
+		da = (mpath && mpath->is_root) ?
+			mpath->rann_snd_addr : broadcast_addr;
 		mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
 				cpu_to_le32(orig_sn), target_flags, target_addr,
-				cpu_to_le32(target_sn), broadcast_addr,
+				cpu_to_le32(target_sn), da,
 				hopcount, ttl, cpu_to_le32(lifetime),
 				cpu_to_le32(metric), cpu_to_le32(preq_id),
 				sdata);
@@ -615,6 +621,7 @@
 				    struct ieee80211_mgmt *mgmt,
 				    u8 *prep_elem, u32 metric)
 {
+	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 	struct mesh_path *mpath;
 	u8 *target_addr, *orig_addr;
 	u8 ttl, hopcount, flags;
@@ -624,10 +631,13 @@
 	mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem));
 
 	orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
-	if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0)
+	if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0)
 		/* destination, no forwarding required */
 		return;
 
+	if (!ifmsh->mshcfg.dot11MeshForwarding)
+		return;
+
 	ttl = PREP_IE_TTL(prep_elem);
 	if (ttl <= 1) {
 		sdata->u.mesh.mshstats.dropped_frames_ttl++;
@@ -694,21 +704,26 @@
 	rcu_read_lock();
 	mpath = mesh_path_lookup(target_addr, sdata);
 	if (mpath) {
+		struct sta_info *sta;
+
 		spin_lock_bh(&mpath->state_lock);
+		sta = next_hop_deref_protected(mpath);
 		if (mpath->flags & MESH_PATH_ACTIVE &&
-		    memcmp(ta, next_hop_deref_protected(mpath)->sta.addr,
-							ETH_ALEN) == 0 &&
+		    compare_ether_addr(ta, sta->sta.addr) == 0 &&
 		    (!(mpath->flags & MESH_PATH_SN_VALID) ||
 		    SN_GT(target_sn, mpath->sn))) {
 			mpath->flags &= ~MESH_PATH_ACTIVE;
 			mpath->sn = target_sn;
 			spin_unlock_bh(&mpath->state_lock);
+			if (!ifmsh->mshcfg.dot11MeshForwarding)
+				goto endperr;
 			mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn),
 					   cpu_to_le16(target_rcode),
 					   broadcast_addr, sdata);
 		} else
 			spin_unlock_bh(&mpath->state_lock);
 	}
+endperr:
 	rcu_read_unlock();
 }
 
@@ -739,11 +754,11 @@
 	metric = rann->rann_metric;
 
 	/*  Ignore our own RANNs */
-	if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0)
+	if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0)
 		return;
 
-	mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr,
-			root_is_gate);
+	mhwmp_dbg("received RANN from %pM via neighbour %pM (is_gate=%d)",
+			orig_addr, mgmt->sa, root_is_gate);
 
 	rcu_read_lock();
 	mpath = mesh_path_lookup(orig_addr, sdata);
@@ -765,7 +780,7 @@
 		mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
 	}
 
-	if (mpath->sn < orig_sn) {
+	if (mpath->sn < orig_sn && ifmsh->mshcfg.dot11MeshForwarding) {
 		mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
 				       cpu_to_le32(orig_sn),
 				       0, NULL, 0, broadcast_addr,
@@ -774,6 +789,11 @@
 				       0, sdata);
 		mpath->sn = orig_sn;
 	}
+
+	/* Using individually addressed PREQ for root node */
+	memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN);
+	mpath->is_root = true;
+
 	if (root_is_gate)
 		mesh_path_add_gate(mpath);
 
@@ -909,6 +929,7 @@
 	struct mesh_preq_queue *preq_node;
 	struct mesh_path *mpath;
 	u8 ttl, target_flags;
+	const u8 *da;
 	u32 lifetime;
 
 	spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
@@ -971,9 +992,10 @@
 		target_flags = MP_F_RF;
 
 	spin_unlock_bh(&mpath->state_lock);
+	da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr;
 	mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr,
 			cpu_to_le32(ifmsh->sn), target_flags, mpath->dst,
-			cpu_to_le32(mpath->sn), broadcast_addr, 0,
+			cpu_to_le32(mpath->sn), da, 0,
 			ttl, cpu_to_le32(lifetime), 0,
 			cpu_to_le32(ifmsh->preq_id++), sdata);
 	mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
@@ -1064,7 +1086,7 @@
 	if (time_after(jiffies,
 		       mpath->exp_time -
 		       msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
-	    !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) &&
+	    !compare_ether_addr(sdata->vif.addr, hdr->addr4) &&
 	    !(mpath->flags & MESH_PATH_RESOLVING) &&
 	    !(mpath->flags & MESH_PATH_FIXED))
 		mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index dc51669..be1361b 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -348,7 +348,7 @@
 	hlist_for_each_entry_rcu(node, n, bucket, list) {
 		mpath = node->mpath;
 		if (mpath->sdata == sdata &&
-				memcmp(dst, mpath->dst, ETH_ALEN) == 0) {
+				compare_ether_addr(dst, mpath->dst) == 0) {
 			if (MPATH_EXPIRED(mpath)) {
 				spin_lock_bh(&mpath->state_lock);
 				mpath->flags &= ~MESH_PATH_ACTIVE;
@@ -523,7 +523,7 @@
 	int err = 0;
 	u32 hash_idx;
 
-	if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0)
+	if (compare_ether_addr(dst, sdata->vif.addr) == 0)
 		/* never add ourselves as neighbours */
 		return -ENOTSUPP;
 
@@ -559,12 +559,13 @@
 	hash_idx = mesh_table_hash(dst, sdata, tbl);
 	bucket = &tbl->hash_buckets[hash_idx];
 
-	spin_lock_bh(&tbl->hashwlock[hash_idx]);
+	spin_lock(&tbl->hashwlock[hash_idx]);
 
 	err = -EEXIST;
 	hlist_for_each_entry(node, n, bucket, list) {
 		mpath = node->mpath;
-		if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0)
+		if (mpath->sdata == sdata &&
+		    compare_ether_addr(dst, mpath->dst) == 0)
 			goto err_exists;
 	}
 
@@ -575,7 +576,7 @@
 
 	mesh_paths_generation++;
 
-	spin_unlock_bh(&tbl->hashwlock[hash_idx]);
+	spin_unlock(&tbl->hashwlock[hash_idx]);
 	read_unlock_bh(&pathtbl_resize_lock);
 	if (grow) {
 		set_bit(MESH_WORK_GROW_MPATH_TABLE,  &ifmsh->wrkq_flags);
@@ -584,7 +585,7 @@
 	return 0;
 
 err_exists:
-	spin_unlock_bh(&tbl->hashwlock[hash_idx]);
+	spin_unlock(&tbl->hashwlock[hash_idx]);
 	read_unlock_bh(&pathtbl_resize_lock);
 	kfree(new_node);
 err_node_alloc:
@@ -655,7 +656,7 @@
 	int err = 0;
 	u32 hash_idx;
 
-	if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0)
+	if (compare_ether_addr(dst, sdata->vif.addr) == 0)
 		/* never add ourselves as neighbours */
 		return -ENOTSUPP;
 
@@ -687,12 +688,13 @@
 	hash_idx = mesh_table_hash(dst, sdata, tbl);
 	bucket = &tbl->hash_buckets[hash_idx];
 
-	spin_lock_bh(&tbl->hashwlock[hash_idx]);
+	spin_lock(&tbl->hashwlock[hash_idx]);
 
 	err = -EEXIST;
 	hlist_for_each_entry(node, n, bucket, list) {
 		mpath = node->mpath;
-		if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0)
+		if (mpath->sdata == sdata &&
+		    compare_ether_addr(dst, mpath->dst) == 0)
 			goto err_exists;
 	}
 
@@ -701,7 +703,7 @@
 	    tbl->mean_chain_len * (tbl->hash_mask + 1))
 		grow = 1;
 
-	spin_unlock_bh(&tbl->hashwlock[hash_idx]);
+	spin_unlock(&tbl->hashwlock[hash_idx]);
 	read_unlock_bh(&pathtbl_resize_lock);
 	if (grow) {
 		set_bit(MESH_WORK_GROW_MPP_TABLE,  &ifmsh->wrkq_flags);
@@ -710,7 +712,7 @@
 	return 0;
 
 err_exists:
-	spin_unlock_bh(&tbl->hashwlock[hash_idx]);
+	spin_unlock(&tbl->hashwlock[hash_idx]);
 	read_unlock_bh(&pathtbl_resize_lock);
 	kfree(new_node);
 err_node_alloc:
@@ -809,9 +811,9 @@
 	for_each_mesh_entry(tbl, p, node, i) {
 		mpath = node->mpath;
 		if (rcu_dereference(mpath->next_hop) == sta) {
-			spin_lock_bh(&tbl->hashwlock[i]);
+			spin_lock(&tbl->hashwlock[i]);
 			__mesh_path_del(tbl, node);
-			spin_unlock_bh(&tbl->hashwlock[i]);
+			spin_unlock(&tbl->hashwlock[i]);
 		}
 	}
 	read_unlock_bh(&pathtbl_resize_lock);
@@ -882,11 +884,11 @@
 	hash_idx = mesh_table_hash(addr, sdata, tbl);
 	bucket = &tbl->hash_buckets[hash_idx];
 
-	spin_lock_bh(&tbl->hashwlock[hash_idx]);
+	spin_lock(&tbl->hashwlock[hash_idx]);
 	hlist_for_each_entry(node, n, bucket, list) {
 		mpath = node->mpath;
 		if (mpath->sdata == sdata &&
-		    memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
+		    compare_ether_addr(addr, mpath->dst) == 0) {
 			__mesh_path_del(tbl, node);
 			goto enddel;
 		}
@@ -895,7 +897,7 @@
 	err = -ENXIO;
 enddel:
 	mesh_paths_generation++;
-	spin_unlock_bh(&tbl->hashwlock[hash_idx]);
+	spin_unlock(&tbl->hashwlock[hash_idx]);
 	read_unlock_bh(&pathtbl_resize_lock);
 	return err;
 }
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 8806e5e..4e53c4c 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -31,6 +31,12 @@
 #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
 #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
 
+/* We only need a valid sta if user configured a minimum rssi_threshold. */
+#define rssi_threshold_check(sta, sdata) \
+		(sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\
+		(sta && (s8) -ewma_read(&sta->avg_signal) > \
+		sdata->u.mesh.mshcfg.rssi_threshold))
+
 enum plink_event {
 	PLINK_UNDEFINED,
 	OPN_ACPT,
@@ -301,7 +307,8 @@
 	if (mesh_peer_accepts_plinks(elems) &&
 			sta->plink_state == NL80211_PLINK_LISTEN &&
 			sdata->u.mesh.accepting_plinks &&
-			sdata->u.mesh.mshcfg.auto_open_plinks)
+			sdata->u.mesh.mshcfg.auto_open_plinks &&
+			rssi_threshold_check(sta, sdata))
 		mesh_plink_open(sta);
 
 	rcu_read_unlock();
@@ -531,6 +538,14 @@
 		return;
 	}
 
+	if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
+	    !rssi_threshold_check(sta, sdata)) {
+		mpl_dbg("Mesh plink: %pM does not meet rssi threshold\n",
+			mgmt->sa);
+		rcu_read_unlock();
+		return;
+	}
+
 	if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
 		mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
 		rcu_read_unlock();
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index caf97f5..576fb25 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -189,40 +189,35 @@
 	u16 ht_opmode;
 	bool enable_ht = true;
 	enum nl80211_channel_type prev_chantype;
-	enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
+	enum nl80211_channel_type rx_channel_type = NL80211_CHAN_NO_HT;
+	enum nl80211_channel_type tx_channel_type;
 
 	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
 	prev_chantype = sdata->vif.bss_conf.channel_type;
 
-	/* HT is not supported */
-	if (!sband->ht_cap.ht_supported)
-		enable_ht = false;
 
-	if (enable_ht) {
-		hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan,
-							   sband->band);
-		/* check that channel matches the right operating channel */
-		if (local->hw.conf.channel->center_freq != hti_cfreq) {
-			/* Some APs mess this up, evidently.
-			 * Netgear WNDR3700 sometimes reports 4 higher than
-			 * the actual channel, for instance.
-			 */
-			printk(KERN_DEBUG
-			       "%s: Wrong control channel in association"
-			       " response: configured center-freq: %d"
-			       " hti-cfreq: %d  hti->control_chan: %d"
-			       " band: %d.  Disabling HT.\n",
-			       sdata->name,
-			       local->hw.conf.channel->center_freq,
-			       hti_cfreq, hti->control_chan,
-			       sband->band);
-			enable_ht = false;
-		}
+	hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan,
+						   sband->band);
+	/* check that channel matches the right operating channel */
+	if (local->hw.conf.channel->center_freq != hti_cfreq) {
+		/* Some APs mess this up, evidently.
+		 * Netgear WNDR3700 sometimes reports 4 higher than
+		 * the actual channel, for instance.
+		 */
+		printk(KERN_DEBUG
+		       "%s: Wrong control channel in association"
+		       " response: configured center-freq: %d"
+		       " hti-cfreq: %d  hti->control_chan: %d"
+		       " band: %d.  Disabling HT.\n",
+		       sdata->name,
+		       local->hw.conf.channel->center_freq,
+		       hti_cfreq, hti->control_chan,
+		       sband->band);
+		enable_ht = false;
 	}
 
 	if (enable_ht) {
-		channel_type = NL80211_CHAN_HT20;
+		rx_channel_type = NL80211_CHAN_HT20;
 
 		if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
 		    !ieee80111_cfg_override_disables_ht40(sdata) &&
@@ -230,29 +225,28 @@
 		    (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
 			switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
 			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-				if (!(local->hw.conf.channel->flags &
-				    IEEE80211_CHAN_NO_HT40PLUS))
-					channel_type = NL80211_CHAN_HT40PLUS;
+				rx_channel_type = NL80211_CHAN_HT40PLUS;
 				break;
 			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-				if (!(local->hw.conf.channel->flags &
-				    IEEE80211_CHAN_NO_HT40MINUS))
-					channel_type = NL80211_CHAN_HT40MINUS;
+				rx_channel_type = NL80211_CHAN_HT40MINUS;
 				break;
 			}
 		}
 	}
 
-	if (local->tmp_channel)
-		local->tmp_channel_type = channel_type;
+	tx_channel_type = ieee80211_get_tx_channel_type(local, rx_channel_type);
 
-	if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
+	if (local->tmp_channel)
+		local->tmp_channel_type = rx_channel_type;
+
+	if (!ieee80211_set_channel_type(local, sdata, rx_channel_type)) {
 		/* can only fail due to HT40+/- mismatch */
-		channel_type = NL80211_CHAN_HT20;
-		WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type));
+		rx_channel_type = NL80211_CHAN_HT20;
+		WARN_ON(!ieee80211_set_channel_type(local, sdata,
+						    rx_channel_type));
 	}
 
-	if (beacon_htcap_ie && (prev_chantype != channel_type)) {
+	if (beacon_htcap_ie && (prev_chantype != rx_channel_type)) {
 		/*
 		 * Whenever the AP announces the HT mode change that can be
 		 * 40MHz intolerant or etc., it would be safer to stop tx
@@ -270,13 +264,13 @@
 	/* channel_type change automatically detected */
 	ieee80211_hw_config(local, 0);
 
-	if (prev_chantype != channel_type) {
+	if (prev_chantype != tx_channel_type) {
 		rcu_read_lock();
 		sta = sta_info_get(sdata, bssid);
 		if (sta)
 			rate_control_rate_update(local, sband, sta,
 						 IEEE80211_RC_HT_CHANGED,
-						 channel_type);
+						 tx_channel_type);
 		rcu_read_unlock();
 
 		if (beacon_htcap_ie)
@@ -289,7 +283,7 @@
 	/* if bss configuration changed store the new one */
 	if (sdata->ht_opmode_valid != enable_ht ||
 	    sdata->vif.bss_conf.ht_operation_mode != ht_opmode ||
-	    prev_chantype != channel_type) {
+	    prev_chantype != rx_channel_type) {
 		changed |= BSS_CHANGED_HT;
 		sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
 		sdata->ht_opmode_valid = enable_ht;
@@ -335,9 +329,6 @@
 
 	BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap));
 
-	if (!sband->ht_cap.ht_supported)
-		return;
-
 	if (!ht_info_ie)
 		return;
 
@@ -405,7 +396,6 @@
 	u16 capab;
 	struct ieee80211_supported_band *sband;
 	u32 rates = 0;
-	struct ieee80211_bss *bss = (void *)assoc_data->bss->priv;
 
 	lockdep_assert_held(&ifmgd->mtx);
 
@@ -566,8 +556,7 @@
 		offset = noffset;
 	}
 
-	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N) &&
-	    bss->wmm_used && local->hw.queues >= 4)
+	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
 		ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie,
 				    sband, local->oper_channel, ifmgd->ap_smps);
 
@@ -581,10 +570,10 @@
 		offset = noffset;
 	}
 
-	if (assoc_data->wmm_used && local->hw.queues >= 4) {
-		if (assoc_data->uapsd_used) {
-			qos_info = local->uapsd_queues;
-			qos_info |= (local->uapsd_max_sp_len <<
+	if (assoc_data->wmm) {
+		if (assoc_data->uapsd) {
+			qos_info = ifmgd->uapsd_queues;
+			qos_info |= (ifmgd->uapsd_max_sp_len <<
 				     IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT);
 		} else {
 			qos_info = 0;
@@ -1203,7 +1192,7 @@
 		return;
 
 	if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
-		uapsd_queues = local->uapsd_queues;
+		uapsd_queues = ifmgd->uapsd_queues;
 
 	count = wmm_param[6] & 0x0f;
 	if (count == ifmgd->wmm_last_param_set)
@@ -1277,7 +1266,6 @@
 
 	/* enable WMM or activate new settings */
 	sdata->vif.bss_conf.qos = true;
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
 }
 
 static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
@@ -1330,7 +1318,7 @@
 	bss_info_changed |= BSS_CHANGED_ASSOC;
 	/* set timing information */
 	bss_conf->beacon_int = cbss->beacon_interval;
-	bss_conf->timestamp = cbss->tsf;
+	bss_conf->last_tsf = cbss->tsf;
 
 	bss_info_changed |= BSS_CHANGED_BEACON_INT;
 	bss_info_changed |= ieee80211_handle_bss_capability(sdata,
@@ -1356,15 +1344,6 @@
 		bss_conf->dtim_period = 0;
 
 	bss_conf->assoc = 1;
-	/*
-	 * For now just always ask the driver to update the basic rateset
-	 * when we have associated, we aren't checking whether it actually
-	 * changed or not.
-	 */
-	bss_info_changed |= BSS_CHANGED_BASIC_RATES;
-
-	/* And the BSSID changed - we're associated now */
-	bss_info_changed |= BSS_CHANGED_BSSID;
 
 	/* Tell the driver to monitor connection quality (if supported) */
 	if (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI &&
@@ -1395,7 +1374,7 @@
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
-	u32 changed = 0, config_changed = 0;
+	u32 changed = 0;
 	u8 bssid[ETH_ALEN];
 
 	ASSERT_MGD_MTX(ifmgd);
@@ -1455,11 +1434,6 @@
 	changed |= BSS_CHANGED_ASSOC;
 	sdata->vif.bss_conf.assoc = false;
 
-	ieee80211_set_wmm_default(sdata);
-
-	/* channel(_type) changes are handled by ieee80211_hw_config */
-	WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
-
 	/* on the next assoc, re-program HT parameters */
 	sdata->ht_opmode_valid = false;
 	memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
@@ -1472,22 +1446,30 @@
 
 	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
 		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
-		config_changed |= IEEE80211_CONF_CHANGE_PS;
+		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 	}
 	local->ps_sdata = NULL;
 
-	ieee80211_hw_config(local, config_changed);
-
 	/* Disable ARP filtering */
 	if (sdata->vif.bss_conf.arp_filter_enabled) {
 		sdata->vif.bss_conf.arp_filter_enabled = false;
 		changed |= BSS_CHANGED_ARP_FILTER;
 	}
 
+	sdata->vif.bss_conf.qos = false;
+	changed |= BSS_CHANGED_QOS;
+
 	/* The BSSID (not really interesting) and HT changed */
 	changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
 	ieee80211_bss_info_change_notify(sdata, changed);
 
+	/* channel(_type) changes are handled by ieee80211_hw_config */
+	WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
+	ieee80211_hw_config(local, 0);
+
+	/* disassociated - set to defaults now */
+	ieee80211_set_wmm_default(sdata, false);
+
 	del_timer_sync(&sdata->u.mgd.conn_mon_timer);
 	del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
 	del_timer_sync(&sdata->u.mgd.timer);
@@ -1767,11 +1749,6 @@
 
 	lockdep_assert_held(&sdata->u.mgd.mtx);
 
-	if (auth_data->synced)
-		drv_finish_tx_sync(sdata->local, sdata,
-				   auth_data->bss->bssid,
-				   IEEE80211_TX_SYNC_AUTH);
-
 	if (!assoc) {
 		sta_info_destroy_addr(sdata, auth_data->bss->bssid);
 
@@ -1822,7 +1799,7 @@
 
 	memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);
 
-	if (memcmp(bssid, mgmt->bssid, ETH_ALEN))
+	if (compare_ether_addr(bssid, mgmt->bssid))
 		return RX_MGMT_NONE;
 
 	auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
@@ -1859,10 +1836,6 @@
 
 	printk(KERN_DEBUG "%s: authenticated\n", sdata->name);
  out:
-	if (ifmgd->auth_data->synced)
-		drv_finish_tx_sync(sdata->local, sdata, bssid,
-				   IEEE80211_TX_SYNC_AUTH);
-	ifmgd->auth_data->synced = false;
 	ifmgd->auth_data->done = true;
 	ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
 	run_again(ifmgd, ifmgd->auth_data->timeout);
@@ -1903,7 +1876,7 @@
 		return RX_MGMT_NONE;
 
 	if (!ifmgd->associated ||
-	    memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN))
+	    compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid))
 		return RX_MGMT_NONE;
 
 	bssid = ifmgd->associated->bssid;
@@ -1936,7 +1909,7 @@
 		return RX_MGMT_NONE;
 
 	if (!ifmgd->associated ||
-	    memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN))
+	    compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid))
 		return RX_MGMT_NONE;
 
 	reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
@@ -2002,11 +1975,6 @@
 
 	lockdep_assert_held(&sdata->u.mgd.mtx);
 
-	if (assoc_data->synced)
-		drv_finish_tx_sync(sdata->local, sdata,
-				   assoc_data->bss->bssid,
-				   IEEE80211_TX_SYNC_ASSOC);
-
 	if (!assoc) {
 		sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
 
@@ -2027,15 +1995,12 @@
 	struct ieee80211_supported_band *sband;
 	struct sta_info *sta;
 	u8 *pos;
-	u32 rates, basic_rates;
 	u16 capab_info, aid;
 	struct ieee802_11_elems elems;
 	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
 	u32 changed = 0;
 	int err;
-	bool have_higher_than_11mbit = false;
 	u16 ap_ht_cap_flags;
-	int min_rate = INT_MAX, min_rate_index = -1;
 
 	/* AssocResp and ReassocResp have identical structure */
 
@@ -2080,39 +2045,8 @@
 		return false;
 	}
 
-	rates = 0;
-	basic_rates = 0;
 	sband = local->hw.wiphy->bands[local->oper_channel->band];
 
-	ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len,
-			    &rates, &basic_rates, &have_higher_than_11mbit,
-			    &min_rate, &min_rate_index);
-
-	ieee80211_get_rates(sband, elems.ext_supp_rates,
-			    elems.ext_supp_rates_len, &rates, &basic_rates,
-			    &have_higher_than_11mbit,
-			    &min_rate, &min_rate_index);
-
-	/*
-	 * some buggy APs don't advertise basic_rates. use the lowest
-	 * supported rate instead.
-	 */
-	if (unlikely(!basic_rates) && min_rate_index >= 0) {
-		printk(KERN_DEBUG "%s: No basic rates in AssocResp. "
-		       "Using min supported rate instead.\n", sdata->name);
-		basic_rates = BIT(min_rate_index);
-	}
-
-	sta->sta.supp_rates[local->oper_channel->band] = rates;
-	sdata->vif.bss_conf.basic_rates = basic_rates;
-
-	/* cf. IEEE 802.11 9.2.12 */
-	if (local->oper_channel->band == IEEE80211_BAND_2GHZ &&
-	    have_higher_than_11mbit)
-		sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
-	else
-		sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
-
 	if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
 		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
 				elems.ht_cap_elem, &sta->sta.ht_cap);
@@ -2155,10 +2089,10 @@
 		ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
 					 elems.wmm_param_len);
 	else
-		ieee80211_set_wmm_default(sdata);
+		ieee80211_set_wmm_default(sdata, false);
+	changed |= BSS_CHANGED_QOS;
 
 	if (elems.ht_info_elem && elems.wmm_param &&
-	    (sdata->local->hw.queues >= 4) &&
 	    !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
 		changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
 					       cbss->bssid, ap_ht_cap_flags,
@@ -2203,7 +2137,7 @@
 
 	if (!assoc_data)
 		return RX_MGMT_NONE;
-	if (memcmp(assoc_data->bss->bssid, mgmt->bssid, ETH_ALEN))
+	if (compare_ether_addr(assoc_data->bss->bssid, mgmt->bssid))
 		return RX_MGMT_NONE;
 
 	/*
@@ -2251,14 +2185,6 @@
 	} else {
 		printk(KERN_DEBUG "%s: associated\n", sdata->name);
 
-		/* tell driver about sync done first */
-		if (assoc_data->synced) {
-			drv_finish_tx_sync(sdata->local, sdata,
-					   assoc_data->bss->bssid,
-					   IEEE80211_TX_SYNC_ASSOC);
-			assoc_data->synced = false;
-		}
-
 		if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
 			/* oops -- internal error -- send timeout for now */
 			ieee80211_destroy_assoc_data(sdata, true);
@@ -2291,8 +2217,8 @@
 	bool need_ps = false;
 
 	if (sdata->u.mgd.associated &&
-	    memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid,
-		   ETH_ALEN) == 0) {
+	    compare_ether_addr(mgmt->bssid, sdata->u.mgd.associated->bssid)
+	    == 0) {
 		bss = (void *)sdata->u.mgd.associated->priv;
 		/* not previously set so we may need to recalc */
 		need_ps = !bss->dtim_period;
@@ -2347,7 +2273,7 @@
 
 	ASSERT_MGD_MTX(ifmgd);
 
-	if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
+	if (compare_ether_addr(mgmt->da, sdata->vif.addr))
 		return; /* ignore ProbeResp to foreign address */
 
 	baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
@@ -2360,11 +2286,12 @@
 	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
 
 	if (ifmgd->associated &&
-	    memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0)
+	    compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid) == 0)
 		ieee80211_reset_ap_probe(sdata);
 
 	if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies &&
-	    memcmp(mgmt->bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN) == 0) {
+	    compare_ether_addr(mgmt->bssid, ifmgd->auth_data->bss->bssid)
+	    == 0) {
 		/* got probe response, continue with auth */
 		printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name);
 		ifmgd->auth_data->tries = 0;
@@ -2421,7 +2348,8 @@
 		return;
 
 	if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon &&
-	    memcmp(mgmt->bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN) == 0) {
+	    compare_ether_addr(mgmt->bssid, ifmgd->assoc_data->bss->bssid)
+	    == 0) {
 		ieee802_11_parse_elems(mgmt->u.beacon.variable,
 				       len - baselen, &elems);
 
@@ -2436,7 +2364,7 @@
 	}
 
 	if (!ifmgd->associated ||
-	    memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN))
+	    compare_ether_addr(mgmt->bssid, ifmgd->associated->bssid))
 		return;
 	bssid = ifmgd->associated->bssid;
 
@@ -2741,14 +2669,6 @@
 	if (WARN_ON_ONCE(!auth_data))
 		return -EINVAL;
 
-	if (!auth_data->synced) {
-		int ret = drv_tx_sync(local, sdata, auth_data->bss->bssid,
-				      IEEE80211_TX_SYNC_AUTH);
-		if (ret)
-			return ret;
-	}
-	auth_data->synced = true;
-
 	auth_data->tries++;
 
 	if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) {
@@ -2805,14 +2725,6 @@
 
 	lockdep_assert_held(&sdata->u.mgd.mtx);
 
-	if (!assoc_data->synced) {
-		int ret = drv_tx_sync(local, sdata, assoc_data->bss->bssid,
-				      IEEE80211_TX_SYNC_ASSOC);
-		if (ret)
-			return ret;
-	}
-	assoc_data->synced = true;
-
 	assoc_data->tries++;
 	if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) {
 		printk(KERN_DEBUG "%s: association with %pM timed out\n",
@@ -3101,6 +3013,8 @@
 
 	ifmgd->flags = 0;
 	ifmgd->powersave = sdata->wdev.ps;
+	ifmgd->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+	ifmgd->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
 
 	mutex_init(&ifmgd->mtx);
 
@@ -3137,6 +3051,101 @@
 	return 0;
 }
 
+static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
+				     struct cfg80211_bss *cbss, bool assoc)
+{
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+	struct ieee80211_bss *bss = (void *)cbss->priv;
+	struct sta_info *sta;
+	bool have_sta = false;
+	int err;
+
+	if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data))
+		return -EINVAL;
+
+	if (assoc) {
+		rcu_read_lock();
+		have_sta = sta_info_get(sdata, cbss->bssid);
+		rcu_read_unlock();
+	}
+
+	if (!have_sta) {
+		sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL);
+		if (!sta)
+			return -ENOMEM;
+	}
+
+	mutex_lock(&local->mtx);
+	ieee80211_recalc_idle(sdata->local);
+	mutex_unlock(&local->mtx);
+
+	/* switch to the right channel */
+	local->oper_channel = cbss->channel;
+	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+
+	if (!have_sta) {
+		struct ieee80211_supported_band *sband;
+		u32 rates = 0, basic_rates = 0;
+		bool have_higher_than_11mbit;
+		int min_rate = INT_MAX, min_rate_index = -1;
+
+		sband = sdata->local->hw.wiphy->bands[cbss->channel->band];
+
+		ieee80211_get_rates(sband, bss->supp_rates,
+				    bss->supp_rates_len,
+				    &rates, &basic_rates,
+				    &have_higher_than_11mbit,
+				    &min_rate, &min_rate_index);
+
+		/*
+		 * This used to be a workaround for basic rates missing
+		 * in the association response frame. Now that we no
+		 * longer use the basic rates from there, it probably
+		 * doesn't happen any more, but keep the workaround so
+		 * in case some *other* APs are buggy in different ways
+		 * we can connect -- with a warning.
+		 */
+		if (!basic_rates && min_rate_index >= 0) {
+			printk(KERN_DEBUG
+			       "%s: No basic rates, using min rate instead.\n",
+			       sdata->name);
+			basic_rates = BIT(min_rate_index);
+		}
+
+		sta->sta.supp_rates[cbss->channel->band] = rates;
+		sdata->vif.bss_conf.basic_rates = basic_rates;
+
+		/* cf. IEEE 802.11 9.2.12 */
+		if (local->oper_channel->band == IEEE80211_BAND_2GHZ &&
+		    have_higher_than_11mbit)
+			sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
+		else
+			sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
+
+		memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN);
+
+		/* tell driver about BSSID and basic rates */
+		ieee80211_bss_info_change_notify(sdata,
+			BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES);
+
+		if (assoc)
+			sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
+
+		err = sta_info_insert(sta);
+		sta = NULL;
+		if (err) {
+			printk(KERN_DEBUG
+			       "%s: failed to insert STA entry for the AP (error %d)\n",
+			       sdata->name, err);
+			return err;
+		}
+	} else
+		WARN_ON_ONCE(compare_ether_addr(ifmgd->bssid, cbss->bssid));
+
+	return 0;
+}
+
 /* config hooks */
 int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 		       struct cfg80211_auth_request *req)
@@ -3144,7 +3153,6 @@
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	struct ieee80211_mgd_auth_data *auth_data;
-	struct sta_info *sta;
 	u16 auth_alg;
 	int err;
 
@@ -3210,38 +3218,12 @@
 	printk(KERN_DEBUG "%s: authenticate with %pM\n",
 	       sdata->name, req->bss->bssid);
 
-	mutex_lock(&local->mtx);
-	ieee80211_recalc_idle(sdata->local);
-	mutex_unlock(&local->mtx);
-
-	/* switch to the right channel */
-	local->oper_channel = req->bss->channel;
-	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-
-	/* set BSSID */
-	memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN);
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
-
-	/* add station entry */
-	sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL);
-	if (!sta) {
-		err = -ENOMEM;
+	err = ieee80211_prep_connection(sdata, req->bss, false);
+	if (err)
 		goto err_clear;
-	}
-
-	err = sta_info_insert(sta);
-	if (err) {
-		printk(KERN_DEBUG
-		       "%s: failed to insert STA entry for the AP %pM (error %d)\n",
-		       sdata->name, req->bss->bssid, err);
-		goto err_clear;
-	}
 
 	err = ieee80211_probe_auth(sdata);
 	if (err) {
-		if (auth_data->synced)
-			drv_finish_tx_sync(local, sdata, req->bss->bssid,
-					   IEEE80211_TX_SYNC_AUTH);
 		sta_info_destroy_addr(sdata, req->bss->bssid);
 		goto err_clear;
 	}
@@ -3268,7 +3250,7 @@
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	struct ieee80211_bss *bss = (void *)req->bss->priv;
 	struct ieee80211_mgd_assoc_data *assoc_data;
-	struct sta_info *sta;
+	struct ieee80211_supported_band *sband;
 	const u8 *ssidie;
 	int i, err;
 
@@ -3299,7 +3281,7 @@
 		bool match;
 
 		/* keep sta info, bssid if matching */
-		match = memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN) == 0;
+		match = compare_ether_addr(ifmgd->bssid, req->bss->bssid) == 0;
 		ieee80211_destroy_auth_data(sdata, match);
 	}
 
@@ -3310,6 +3292,13 @@
 
 	ifmgd->beacon_crc_valid = false;
 
+	/*
+	 * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode.
+	 * We still associate in non-HT mode (11a/b/g) if any one of these
+	 * ciphers is configured as pairwise.
+	 * We can set this to true for non-11n hardware, that'll be checked
+	 * separately along with the peer capabilities.
+	 */
 	for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
 		if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
 		    req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
@@ -3319,6 +3308,12 @@
 	if (req->flags & ASSOC_REQ_DISABLE_HT)
 		ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
 
+	/* Also disable HT if we don't support it or the AP doesn't use WMM */
+	sband = local->hw.wiphy->bands[req->bss->channel->band];
+	if (!sband->ht_cap.ht_supported ||
+	    local->hw.queues < 4 || !bss->wmm_used)
+		ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+
 	memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
 	memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask,
 	       sizeof(ifmgd->ht_capa_mask));
@@ -3338,15 +3333,8 @@
 	} else
 		ifmgd->ap_smps = ifmgd->req_smps;
 
-	/*
-	 * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode.
-	 * We still associate in non-HT mode (11a/b/g) if any one of these
-	 * ciphers is configured as pairwise.
-	 * We can set this to true for non-11n hardware, that'll be checked
-	 * separately along with the peer capabilities.
-	 */
 	assoc_data->capability = req->bss->capability;
-	assoc_data->wmm_used = bss->wmm_used;
+	assoc_data->wmm = bss->wmm_used && (local->hw.queues >= 4);
 	assoc_data->supp_rates = bss->supp_rates;
 	assoc_data->supp_rates_len = bss->supp_rates_len;
 	assoc_data->ht_information_ie =
@@ -3354,10 +3342,10 @@
 
 	if (bss->wmm_used && bss->uapsd_supported &&
 	    (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
-		assoc_data->uapsd_used = true;
+		assoc_data->uapsd = true;
 		ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
 	} else {
-		assoc_data->uapsd_used = false;
+		assoc_data->uapsd = false;
 		ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
 	}
 
@@ -3387,41 +3375,9 @@
 
 	ifmgd->assoc_data = assoc_data;
 
-	mutex_lock(&local->mtx);
-	ieee80211_recalc_idle(sdata->local);
-	mutex_unlock(&local->mtx);
-
-	/* switch to the right channel */
-	local->oper_channel = req->bss->channel;
-	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-
-	rcu_read_lock();
-	sta = sta_info_get(sdata, req->bss->bssid);
-	rcu_read_unlock();
-
-	if (!sta) {
-		/* set BSSID */
-		memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN);
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
-
-		sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL);
-		if (!sta) {
-			err = -ENOMEM;
-			goto err_clear;
-		}
-
-		sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
-
-		err = sta_info_insert(sta);
-		sta = NULL;
-		if (err) {
-			printk(KERN_DEBUG
-			       "%s: failed to insert STA entry for the AP (error %d)\n",
-			       sdata->name, err);
-			goto err_clear;
-		}
-	} else
-		WARN_ON_ONCE(memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN));
+	err = ieee80211_prep_connection(sdata, req->bss, true);
+	if (err)
+		goto err_clear;
 
 	if (!bss->dtim_period &&
 	    sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
@@ -3440,6 +3396,20 @@
 	}
 	run_again(ifmgd, assoc_data->timeout);
 
+	if (bss->corrupt_data) {
+		char *corrupt_type = "data";
+		if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_BEACON) {
+			if (bss->corrupt_data &
+					IEEE80211_BSS_CORRUPT_PROBE_RESP)
+				corrupt_type = "beacon and probe response";
+			else
+				corrupt_type = "beacon";
+		} else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP)
+			corrupt_type = "probe response";
+		printk(KERN_DEBUG "%s: associating with AP with corrupt %s\n",
+		       sdata->name, corrupt_type);
+	}
+
 	err = 0;
 	goto out;
  err_clear:
@@ -3471,7 +3441,7 @@
 	       sdata->name, req->bssid, req->reason_code);
 
 	if (ifmgd->associated &&
-	    memcmp(ifmgd->associated->bssid, req->bssid, ETH_ALEN) == 0)
+	    compare_ether_addr(ifmgd->associated->bssid, req->bssid) == 0)
 		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
 				       req->reason_code, true, frame_buf);
 	else
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index ff5f7b8..16e0b27 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -568,6 +568,13 @@
 	minstrel_next_sample_idx(mi);
 
 	/*
+	 * Sampling might add some overhead (RTS, no aggregation)
+	 * to the frame. Hence, don't use sampling for the currently
+	 * used max TP rate.
+	 */
+	if (sample_idx == mi->max_tp_rate)
+		return -1;
+	/*
 	 * When not using MRR, do not sample if the probability is already
 	 * higher than 95% to avoid wasting airtime
 	 */
@@ -692,6 +699,7 @@
 	int ack_dur;
 	int stbc;
 	int i;
+	unsigned int smps;
 
 	/* fall back to the old minstrel for legacy stations */
 	if (!sta->ht_cap.ht_supported)
@@ -731,6 +739,9 @@
 	    oper_chan_type != NL80211_CHAN_HT40PLUS)
 		sta_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 
+	smps = (sta_cap & IEEE80211_HT_CAP_SM_PS) >>
+		IEEE80211_HT_CAP_SM_PS_SHIFT;
+
 	for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {
 		u16 req = 0;
 
@@ -748,6 +759,11 @@
 		if ((sta_cap & req) != req)
 			continue;
 
+		/* Mark MCS > 7 as unsupported if STA is in static SMPS mode */
+		if (smps == WLAN_HT_CAP_SM_PS_STATIC &&
+		    minstrel_mcs_groups[i].streams > 1)
+			continue;
+
 		mi->groups[i].supported =
 			mcs->rx_mask[minstrel_mcs_groups[i].streams - 1];
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 7a4ff02..bcfe8c7 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -177,7 +177,8 @@
 	pos += 2;
 
 	/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
-	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM &&
+	    !(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
 		*pos = status->signal;
 		rthdr->it_present |=
 			cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
@@ -227,7 +228,7 @@
 {
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
 	struct ieee80211_sub_if_data *sdata;
-	int needed_headroom = 0;
+	int needed_headroom;
 	struct sk_buff *skb, *skb2;
 	struct net_device *prev_dev = NULL;
 	int present_fcs_len = 0;
@@ -489,12 +490,12 @@
 			if (ieee80211_has_tods(hdr->frame_control) ||
 				!ieee80211_has_fromds(hdr->frame_control))
 				return RX_DROP_MONITOR;
-			if (memcmp(hdr->addr3, dev_addr, ETH_ALEN) == 0)
+			if (compare_ether_addr(hdr->addr3, dev_addr) == 0)
 				return RX_DROP_MONITOR;
 		} else {
 			if (!ieee80211_has_a4(hdr->frame_control))
 				return RX_DROP_MONITOR;
-			if (memcmp(hdr->addr4, dev_addr, ETH_ALEN) == 0)
+			if (compare_ether_addr(hdr->addr4, dev_addr) == 0)
 				return RX_DROP_MONITOR;
 		}
 	}
@@ -1062,20 +1063,9 @@
 		return RX_DROP_MONITOR;
 	}
 
-	if (skb_linearize(rx->skb))
-		return RX_DROP_UNUSABLE;
-	/* the hdr variable is invalid now! */
-
 	switch (rx->key->conf.cipher) {
 	case WLAN_CIPHER_SUITE_WEP40:
 	case WLAN_CIPHER_SUITE_WEP104:
-		/* Check for weak IVs if possible */
-		if (rx->sta && ieee80211_is_data(fc) &&
-		    (!(status->flag & RX_FLAG_IV_STRIPPED) ||
-		     !(status->flag & RX_FLAG_DECRYPTED)) &&
-		    ieee80211_wep_is_weak_iv(rx->skb, rx->key))
-			rx->sta->wep_weak_iv_count++;
-
 		result = ieee80211_crypto_wep_decrypt(rx);
 		break;
 	case WLAN_CIPHER_SUITE_TKIP:
@@ -1095,6 +1085,8 @@
 		return RX_DROP_UNUSABLE;
 	}
 
+	/* the hdr variable is invalid after the decrypt handlers */
+
 	/* either the frame has been decrypted or will be dropped */
 	status->flag |= RX_FLAG_DECRYPTED;
 
@@ -1309,8 +1301,10 @@
 
 	sta->rx_fragments++;
 	sta->rx_bytes += rx->skb->len;
-	sta->last_signal = status->signal;
-	ewma_add(&sta->avg_signal, -status->signal);
+	if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
+		sta->last_signal = status->signal;
+		ewma_add(&sta->avg_signal, -status->signal);
+	}
 
 	/*
 	 * Change STA power saving mode only at the end of a frame
@@ -1957,6 +1951,9 @@
 		return RX_DROP_MONITOR;
 	}
 
+	if (!ifmsh->mshcfg.dot11MeshForwarding)
+		goto out;
+
 	fwd_skb = skb_copy(skb, GFP_ATOMIC);
 	if (!fwd_skb) {
 		if (net_ratelimit())
@@ -2182,9 +2179,14 @@
 	if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
 	    ieee80211_is_beacon(mgmt->frame_control) &&
 	    !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
+		int sig = 0;
+
+		if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+			sig = status->signal;
+
 		cfg80211_report_obss_beacon(rx->local->hw.wiphy,
 					    rx->skb->data, rx->skb->len,
-					    status->freq, GFP_ATOMIC);
+					    status->freq, sig, GFP_ATOMIC);
 		rx->flags |= IEEE80211_RX_BEACON_REPORTED;
 	}
 
@@ -2267,9 +2269,11 @@
 
 			sband = rx->local->hw.wiphy->bands[status->band];
 
-			rate_control_rate_update(local, sband, rx->sta,
-						 IEEE80211_RC_SMPS_CHANGED,
-						 local->_oper_channel_type);
+			rate_control_rate_update(
+				local, sband, rx->sta,
+				IEEE80211_RC_SMPS_CHANGED,
+				ieee80211_get_tx_channel_type(
+					local, local->_oper_channel_type));
 			goto handled;
 		}
 		default:
@@ -2336,7 +2340,7 @@
 			if (sdata->vif.type != NL80211_IFTYPE_STATION)
 				break;
 
-			if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
+			if (compare_ether_addr(mgmt->bssid, sdata->u.mgd.bssid))
 				break;
 
 			goto queue;
@@ -2408,6 +2412,7 @@
 ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+	int sig = 0;
 
 	/* skip known-bad action frames and return them in the next handler */
 	if (status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM)
@@ -2420,7 +2425,10 @@
 	 * it transmitted were processed or returned.
 	 */
 
-	if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq,
+	if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+		sig = status->signal;
+
+	if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, sig,
 			     rx->skb->data, rx->skb->len,
 			     GFP_ATOMIC)) {
 		if (rx->sta)
@@ -2538,16 +2546,10 @@
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_local *local = rx->local;
-	struct ieee80211_rtap_hdr {
-		struct ieee80211_radiotap_header hdr;
-		u8 flags;
-		u8 rate_or_pad;
-		__le16 chan_freq;
-		__le16 chan_flags;
-	} __packed *rthdr;
 	struct sk_buff *skb = rx->skb, *skb2;
 	struct net_device *prev_dev = NULL;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+	int needed_headroom;
 
 	/*
 	 * If cooked monitor has been processed already, then
@@ -2561,30 +2563,15 @@
 	if (!local->cooked_mntrs)
 		goto out_free_skb;
 
-	if (skb_headroom(skb) < sizeof(*rthdr) &&
-	    pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))
+	/* room for the radiotap header based on driver features */
+	needed_headroom = ieee80211_rx_radiotap_len(local, status);
+
+	if (skb_headroom(skb) < needed_headroom &&
+	    pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC))
 		goto out_free_skb;
 
-	rthdr = (void *)skb_push(skb, sizeof(*rthdr));
-	memset(rthdr, 0, sizeof(*rthdr));
-	rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
-	rthdr->hdr.it_present =
-		cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
-			    (1 << IEEE80211_RADIOTAP_CHANNEL));
-
-	if (rate) {
-		rthdr->rate_or_pad = rate->bitrate / 5;
-		rthdr->hdr.it_present |=
-			cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
-	}
-	rthdr->chan_freq = cpu_to_le16(status->freq);
-
-	if (status->band == IEEE80211_BAND_5GHZ)
-		rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_OFDM |
-						IEEE80211_CHAN_5GHZ);
-	else
-		rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_DYN |
-						IEEE80211_CHAN_2GHZ);
+	/* prepend radiotap information */
+	ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom);
 
 	skb_set_mac_header(skb, 0);
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 9270771..33cd169 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/if_arp.h>
+#include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/pm_qos.h>
 #include <net/sch_generic.h>
@@ -103,16 +104,35 @@
 	cbss->free_priv = ieee80211_rx_bss_free;
 	bss = (void *)cbss->priv;
 
-	/* save the ERP value so that it is available at association time */
-	if (elems->erp_info && elems->erp_info_len >= 1) {
-		bss->erp_value = elems->erp_info[0];
-		bss->has_erp_value = true;
+	if (elems->parse_error) {
+		if (beacon)
+			bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
+		else
+			bss->corrupt_data |= IEEE80211_BSS_CORRUPT_PROBE_RESP;
+	} else {
+		if (beacon)
+			bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_BEACON;
+		else
+			bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_PROBE_RESP;
 	}
 
-	if (elems->tim) {
+	/* save the ERP value so that it is available at association time */
+	if (elems->erp_info && elems->erp_info_len >= 1 &&
+			(!elems->parse_error ||
+			 !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
+		bss->erp_value = elems->erp_info[0];
+		bss->has_erp_value = true;
+		if (!elems->parse_error)
+			bss->valid_data |= IEEE80211_BSS_VALID_ERP;
+	}
+
+	if (elems->tim && (!elems->parse_error ||
+			   !(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) {
 		struct ieee80211_tim_ie *tim_ie =
 			(struct ieee80211_tim_ie *)elems->tim;
 		bss->dtim_period = tim_ie->dtim_period;
+		if (!elems->parse_error)
+				bss->valid_data |= IEEE80211_BSS_VALID_DTIM;
 	}
 
 	/* If the beacon had no TIM IE, or it was invalid, use 1 */
@@ -120,26 +140,38 @@
 		bss->dtim_period = 1;
 
 	/* replace old supported rates if we get new values */
-	srlen = 0;
-	if (elems->supp_rates) {
-		clen = IEEE80211_MAX_SUPP_RATES;
-		if (clen > elems->supp_rates_len)
-			clen = elems->supp_rates_len;
-		memcpy(bss->supp_rates, elems->supp_rates, clen);
-		srlen += clen;
+	if (!elems->parse_error ||
+	    !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
+		srlen = 0;
+		if (elems->supp_rates) {
+			clen = IEEE80211_MAX_SUPP_RATES;
+			if (clen > elems->supp_rates_len)
+				clen = elems->supp_rates_len;
+			memcpy(bss->supp_rates, elems->supp_rates, clen);
+			srlen += clen;
+		}
+		if (elems->ext_supp_rates) {
+			clen = IEEE80211_MAX_SUPP_RATES - srlen;
+			if (clen > elems->ext_supp_rates_len)
+				clen = elems->ext_supp_rates_len;
+			memcpy(bss->supp_rates + srlen, elems->ext_supp_rates,
+			       clen);
+			srlen += clen;
+		}
+		if (srlen) {
+			bss->supp_rates_len = srlen;
+			if (!elems->parse_error)
+				bss->valid_data |= IEEE80211_BSS_VALID_RATES;
+		}
 	}
-	if (elems->ext_supp_rates) {
-		clen = IEEE80211_MAX_SUPP_RATES - srlen;
-		if (clen > elems->ext_supp_rates_len)
-			clen = elems->ext_supp_rates_len;
-		memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen);
-		srlen += clen;
-	}
-	if (srlen)
-		bss->supp_rates_len = srlen;
 
-	bss->wmm_used = elems->wmm_param || elems->wmm_info;
-	bss->uapsd_supported = is_uapsd_supported(elems);
+	if (!elems->parse_error ||
+	    !(bss->valid_data & IEEE80211_BSS_VALID_WMM)) {
+		bss->wmm_used = elems->wmm_param || elems->wmm_info;
+		bss->uapsd_supported = is_uapsd_supported(elems);
+		if (!elems->parse_error)
+			bss->valid_data |= IEEE80211_BSS_VALID_WMM;
+	}
 
 	if (!beacon)
 		bss->last_probe_resp = jiffies;
@@ -176,7 +208,7 @@
 	presp = ieee80211_is_probe_resp(fc);
 	if (presp) {
 		/* ignore ProbeResp to foreign address */
-		if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
+		if (compare_ether_addr(mgmt->da, sdata->vif.addr))
 			return RX_DROP_MONITOR;
 
 		presp = true;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index cd0f265..38137cb 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -9,6 +9,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/etherdevice.h>
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/slab.h>
@@ -101,7 +102,7 @@
 				    lockdep_is_held(&local->sta_mtx));
 	while (sta) {
 		if (sta->sdata == sdata &&
-		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
+		    compare_ether_addr(sta->sta.addr, addr) == 0)
 			break;
 		sta = rcu_dereference_check(sta->hnext,
 					    lockdep_is_held(&local->sta_mtx));
@@ -124,7 +125,7 @@
 	while (sta) {
 		if ((sta->sdata == sdata ||
 		     (sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
-		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
+		    compare_ether_addr(sta->sta.addr, addr) == 0)
 			break;
 		sta = rcu_dereference_check(sta->hnext,
 					    lockdep_is_held(&local->sta_mtx));
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 23a97c9..ab05768 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -14,6 +14,7 @@
 #include <linux/if_ether.h>
 #include <linux/workqueue.h>
 #include <linux/average.h>
+#include <linux/etherdevice.h>
 #include "key.h"
 
 /**
@@ -489,7 +490,7 @@
 		nxt = _sta ? rcu_dereference(_sta->hnext) : NULL	\
 	     )								\
 	/* compare address and run code only if it matches */		\
-	if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0)
+	if (compare_ether_addr(_sta->sta.addr, (_addr)) == 0)
 
 /*
  * Get STA info by index, BROKEN!
@@ -528,6 +529,9 @@
 void sta_info_stop(struct ieee80211_local *local);
 int sta_info_flush(struct ieee80211_local *local,
 		   struct ieee80211_sub_if_data *sdata);
+void sta_set_rate_info_tx(struct sta_info *sta,
+			  const struct ieee80211_tx_rate *rate,
+			  struct rate_info *rinfo);
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
 			  unsigned long exp_time);
 
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index c928e4a..5f8f89e 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/export.h>
+#include <linux/etherdevice.h>
 #include <net/mac80211.h>
 #include <asm/unaligned.h>
 #include "ieee80211_i.h"
@@ -377,7 +378,7 @@
 
 	for_each_sta_info(local, hdr->addr1, sta, tmp) {
 		/* skip wrong virtual interface */
-		if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
+		if (compare_ether_addr(hdr->addr2, sta->sdata->vif.addr))
 			continue;
 
 		if (info->flags & IEEE80211_TX_STATUS_EOSP)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 570737d..782a601 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -226,12 +226,12 @@
 	 * have correct qos tag for some reason, due the network or the
 	 * peer application.
 	 *
-	 * Note: local->uapsd_queues access is racy here. If the value is
+	 * Note: ifmgd->uapsd_queues access is racy here. If the value is
 	 * changed via debugfs, user needs to reassociate manually to have
 	 * everything in sync.
 	 */
 	if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
-	    && (local->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
+	    && (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
 	    && skb_get_queue_mapping(tx->skb) == 0)
 		return TX_CONTINUE;
 
@@ -1065,6 +1065,7 @@
 {
 	bool queued = false;
 	bool reset_agg_timer = false;
+	struct sk_buff *purge_skb = NULL;
 
 	if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
 		info->flags |= IEEE80211_TX_CTL_AMPDU;
@@ -1106,8 +1107,13 @@
 			info->control.vif = &tx->sdata->vif;
 			info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
 			__skb_queue_tail(&tid_tx->pending, skb);
+			if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
+				purge_skb = __skb_dequeue(&tid_tx->pending);
 		}
 		spin_unlock(&tx->sta->lock);
+
+		if (purge_skb)
+			dev_kfree_skb(purge_skb);
 	}
 
 	/* reset session timer */
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index f6e4cef..32f7a3b 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -572,24 +572,40 @@
 	size_t left = len;
 	u8 *pos = start;
 	bool calc_crc = filter != 0;
+	DECLARE_BITMAP(seen_elems, 256);
 
+	bitmap_zero(seen_elems, 256);
 	memset(elems, 0, sizeof(*elems));
 	elems->ie_start = start;
 	elems->total_len = len;
 
 	while (left >= 2) {
 		u8 id, elen;
+		bool elem_parse_failed;
 
 		id = *pos++;
 		elen = *pos++;
 		left -= 2;
 
-		if (elen > left)
+		if (elen > left) {
+			elems->parse_error = true;
 			break;
+		}
+
+		if (id != WLAN_EID_VENDOR_SPECIFIC &&
+		    id != WLAN_EID_QUIET &&
+		    test_bit(id, seen_elems)) {
+			elems->parse_error = true;
+			left -= elen;
+			pos += elen;
+			continue;
+		}
 
 		if (calc_crc && id < 64 && (filter & (1ULL << id)))
 			crc = crc32_be(crc, pos - 2, elen + 2);
 
+		elem_parse_failed = false;
+
 		switch (id) {
 		case WLAN_EID_SSID:
 			elems->ssid = pos;
@@ -615,7 +631,8 @@
 			if (elen >= sizeof(struct ieee80211_tim_ie)) {
 				elems->tim = (void *)pos;
 				elems->tim_len = elen;
-			}
+			} else
+				elem_parse_failed = true;
 			break;
 		case WLAN_EID_IBSS_PARAMS:
 			elems->ibss_params = pos;
@@ -664,10 +681,14 @@
 		case WLAN_EID_HT_CAPABILITY:
 			if (elen >= sizeof(struct ieee80211_ht_cap))
 				elems->ht_cap_elem = (void *)pos;
+			else
+				elem_parse_failed = true;
 			break;
 		case WLAN_EID_HT_INFORMATION:
 			if (elen >= sizeof(struct ieee80211_ht_info))
 				elems->ht_info_elem = (void *)pos;
+			else
+				elem_parse_failed = true;
 			break;
 		case WLAN_EID_MESH_ID:
 			elems->mesh_id = pos;
@@ -676,6 +697,8 @@
 		case WLAN_EID_MESH_CONFIG:
 			if (elen >= sizeof(struct ieee80211_meshconf_ie))
 				elems->mesh_config = (void *)pos;
+			else
+				elem_parse_failed = true;
 			break;
 		case WLAN_EID_PEER_MGMT:
 			elems->peering = pos;
@@ -696,6 +719,8 @@
 		case WLAN_EID_RANN:
 			if (elen >= sizeof(struct ieee80211_rann_ie))
 				elems->rann = (void *)pos;
+			else
+				elem_parse_failed = true;
 			break;
 		case WLAN_EID_CHANNEL_SWITCH:
 			elems->ch_switch_elem = pos;
@@ -724,10 +749,18 @@
 			break;
 		}
 
+		if (elem_parse_failed)
+			elems->parse_error = true;
+		else
+			set_bit(id, seen_elems);
+
 		left -= elen;
 		pos += elen;
 	}
 
+	if (left != 0)
+		elems->parse_error = true;
+
 	return crc;
 }
 
@@ -737,7 +770,8 @@
 	ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
 }
 
-void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
+void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
+			       bool bss_notify)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_tx_queue_params qparam;
@@ -807,7 +841,9 @@
 	if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
 		sdata->vif.bss_conf.qos =
 			sdata->vif.type != NL80211_IFTYPE_STATION;
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
+		if (bss_notify)
+			ieee80211_bss_info_change_notify(sdata,
+							 BSS_CHANGED_QOS);
 	}
 }
 
@@ -829,7 +865,7 @@
 	else
 		sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
 
-	ieee80211_set_wmm_default(sdata);
+	ieee80211_set_wmm_default(sdata, true);
 }
 
 u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index 68ad351..7aa31bb 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -263,16 +263,14 @@
 }
 
 
-bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key)
+static bool ieee80211_wep_is_weak_iv(struct sk_buff *skb,
+				     struct ieee80211_key *key)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	unsigned int hdrlen;
 	u8 *ivpos;
 	u32 iv;
 
-	if (!ieee80211_has_protected(hdr->frame_control))
-		return false;
-
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
 	ivpos = skb->data + hdrlen;
 	iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2];
@@ -286,18 +284,27 @@
 	struct sk_buff *skb = rx->skb;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	__le16 fc = hdr->frame_control;
 
-	if (!ieee80211_is_data(hdr->frame_control) &&
-	    !ieee80211_is_auth(hdr->frame_control))
+	if (!ieee80211_is_data(fc) && !ieee80211_is_auth(fc))
 		return RX_CONTINUE;
 
 	if (!(status->flag & RX_FLAG_DECRYPTED)) {
+		if (skb_linearize(rx->skb))
+			return RX_DROP_UNUSABLE;
+		if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
+			rx->sta->wep_weak_iv_count++;
 		if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key))
 			return RX_DROP_UNUSABLE;
 	} else if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
+		if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + WEP_IV_LEN))
+			return RX_DROP_UNUSABLE;
+		if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
+			rx->sta->wep_weak_iv_count++;
 		ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
 		/* remove ICV */
-		skb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN);
+		if (pskb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN))
+			return RX_DROP_UNUSABLE;
 	}
 
 	return RX_CONTINUE;
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h
index 01e5484..9615749 100644
--- a/net/mac80211/wep.h
+++ b/net/mac80211/wep.h
@@ -25,7 +25,6 @@
 			  const u8 *key, int keylen, int keyidx);
 int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
 			       size_t klen, u8 *data, size_t data_len);
-bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
 
 ieee80211_rx_result
 ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx);
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index b758350..0ae23c6 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -138,6 +138,10 @@
 	if (skb->len < hdrlen + MICHAEL_MIC_LEN)
 		return RX_DROP_UNUSABLE;
 
+	if (skb_linearize(rx->skb))
+		return RX_DROP_UNUSABLE;
+	hdr = (void *)skb->data;
+
 	data = skb->data + hdrlen;
 	data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
 	key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
@@ -253,6 +257,11 @@
 	if (!rx->sta || skb->len - hdrlen < 12)
 		return RX_DROP_UNUSABLE;
 
+	/* it may be possible to optimize this a bit more */
+	if (skb_linearize(rx->skb))
+		return RX_DROP_UNUSABLE;
+	hdr = (void *)skb->data;
+
 	/*
 	 * Let TKIP code verify IV, but skip decryption.
 	 * In the case where hardware checks the IV as well,
@@ -484,6 +493,14 @@
 	if (!rx->sta || data_len < 0)
 		return RX_DROP_UNUSABLE;
 
+	if (status->flag & RX_FLAG_DECRYPTED) {
+		if (!pskb_may_pull(rx->skb, hdrlen + CCMP_HDR_LEN))
+			return RX_DROP_UNUSABLE;
+	} else {
+		if (skb_linearize(rx->skb))
+			return RX_DROP_UNUSABLE;
+	}
+
 	ccmp_hdr2pn(pn, skb->data + hdrlen);
 
 	queue = rx->security_idx;
@@ -509,7 +526,8 @@
 	memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN);
 
 	/* Remove CCMP header and MIC */
-	skb_trim(skb, skb->len - CCMP_MIC_LEN);
+	if (pskb_trim(skb, skb->len - CCMP_MIC_LEN))
+		return RX_DROP_UNUSABLE;
 	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
 	skb_pull(skb, CCMP_HDR_LEN);
 
@@ -609,6 +627,8 @@
 	if (!ieee80211_is_mgmt(hdr->frame_control))
 		return RX_CONTINUE;
 
+	/* management frames are already linear */
+
 	if (skb->len < 24 + sizeof(*mmie))
 		return RX_DROP_UNUSABLE;
 
diff --git a/net/nfc/af_nfc.c b/net/nfc/af_nfc.c
index da67756..9d68441 100644
--- a/net/nfc/af_nfc.c
+++ b/net/nfc/af_nfc.c
@@ -30,7 +30,7 @@
 static const struct nfc_protocol *proto_tab[NFC_SOCKPROTO_MAX];
 
 static int nfc_sock_create(struct net *net, struct socket *sock, int proto,
-								int kern)
+			   int kern)
 {
 	int rc = -EPROTONOSUPPORT;
 
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 6089aca..295d129 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -181,13 +181,13 @@
 	return rc;
 }
 
-int nfc_dep_link_up(struct nfc_dev *dev, int target_index,
-					u8 comm_mode, u8 rf_mode)
+int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
 {
 	int rc = 0;
+	u8 *gb;
+	size_t gb_len;
 
-	pr_debug("dev_name=%s comm:%d rf:%d\n",
-			dev_name(&dev->dev), comm_mode, rf_mode);
+	pr_debug("dev_name=%s comm %d\n", dev_name(&dev->dev), comm_mode);
 
 	if (!dev->ops->dep_link_up)
 		return -EOPNOTSUPP;
@@ -204,7 +204,13 @@
 		goto error;
 	}
 
-	rc = dev->ops->dep_link_up(dev, target_index, comm_mode, rf_mode);
+	gb = nfc_llcp_general_bytes(dev, &gb_len);
+	if (gb_len > NFC_MAX_GT_LEN) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	rc = dev->ops->dep_link_up(dev, target_index, comm_mode, gb, gb_len);
 
 error:
 	device_unlock(&dev->dev);
@@ -250,7 +256,7 @@
 }
 
 int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
-					u8 comm_mode, u8 rf_mode)
+		       u8 comm_mode, u8 rf_mode)
 {
 	dev->dep_link_up = true;
 	dev->dep_rf_mode = rf_mode;
@@ -330,10 +336,8 @@
  *
  * The user must wait for the callback before calling this function again.
  */
-int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
-					struct sk_buff *skb,
-					data_exchange_cb_t cb,
-					void *cb_context)
+int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
+		      data_exchange_cb_t cb, void *cb_context)
 {
 	int rc;
 
@@ -357,8 +361,7 @@
 
 int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
 {
-	pr_debug("dev_name=%s gb_len=%d\n",
-			dev_name(&dev->dev), gb_len);
+	pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len);
 
 	if (gb_len > NFC_MAX_GT_LEN)
 		return -EINVAL;
@@ -367,12 +370,6 @@
 }
 EXPORT_SYMBOL(nfc_set_remote_general_bytes);
 
-u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len)
-{
-	return nfc_llcp_general_bytes(dev, gt_len);
-}
-EXPORT_SYMBOL(nfc_get_local_general_bytes);
-
 /**
  * nfc_alloc_send_skb - allocate a skb for data exchange responses
  *
@@ -380,8 +377,8 @@
  * @gfp: gfp flags
  */
 struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
-					unsigned int flags, unsigned int size,
-					unsigned int *err)
+				   unsigned int flags, unsigned int size,
+				   unsigned int *err)
 {
 	struct sk_buff *skb;
 	unsigned int total_size;
@@ -428,8 +425,8 @@
  * are found. After calling this function, the device driver must stop
  * polling for targets.
  */
-int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
-							int n_targets)
+int nfc_targets_found(struct nfc_dev *dev,
+		      struct nfc_target *targets, int n_targets)
 {
 	pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets);
 
@@ -441,7 +438,7 @@
 
 	kfree(dev->targets);
 	dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target),
-								GFP_ATOMIC);
+			       GFP_ATOMIC);
 
 	if (!dev->targets) {
 		dev->n_targets = 0;
@@ -501,15 +498,14 @@
  * @supported_protocols: NFC protocols supported by the device
  */
 struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
-					u32 supported_protocols,
-					int tx_headroom,
-					int tx_tailroom)
+				    u32 supported_protocols,
+				    int tx_headroom, int tx_tailroom)
 {
 	static atomic_t dev_no = ATOMIC_INIT(0);
 	struct nfc_dev *dev;
 
 	if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
-		!ops->deactivate_target || !ops->data_exchange)
+	    !ops->deactivate_target || !ops->data_exchange)
 		return NULL;
 
 	if (!supported_protocols)
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index 151f2ef..7b76eb7 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -118,7 +118,7 @@
 }
 
 int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
-			u8 *tlv_array, u16 tlv_array_len)
+		       u8 *tlv_array, u16 tlv_array_len)
 {
 	u8 *tlv = tlv_array, type, length, offset = 0;
 
@@ -152,6 +152,8 @@
 		case LLCP_TLV_RW:
 			local->remote_rw = llcp_tlv_rw(tlv);
 			break;
+		case LLCP_TLV_SN:
+			break;
 		default:
 			pr_err("Invalid gt tlv value 0x%x\n", type);
 			break;
@@ -162,15 +164,15 @@
 	}
 
 	pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n",
-		local->remote_version, local->remote_miu,
-		local->remote_lto, local->remote_opt,
-		local->remote_wks, local->remote_rw);
+		 local->remote_version, local->remote_miu,
+		 local->remote_lto, local->remote_opt,
+		 local->remote_wks, local->remote_rw);
 
 	return 0;
 }
 
 static struct sk_buff *llcp_add_header(struct sk_buff *pdu,
-					u8 dsap, u8 ssap, u8 ptype)
+				       u8 dsap, u8 ssap, u8 ptype)
 {
 	u8 header[2];
 
@@ -186,7 +188,8 @@
 	return pdu;
 }
 
-static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv, u8 tlv_length)
+static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv,
+				    u8 tlv_length)
 {
 	/* XXX Add an skb length check */
 
@@ -199,7 +202,7 @@
 }
 
 static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock,
-							u8 cmd, u16 size)
+					 u8 cmd, u16 size)
 {
 	struct sk_buff *skb;
 	int err;
@@ -208,7 +211,7 @@
 		return NULL;
 
 	skb = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
-					size + LLCP_HEADER_SIZE, &err);
+				 size + LLCP_HEADER_SIZE, &err);
 	if (skb == NULL) {
 		pr_err("Could not allocate PDU\n");
 		return NULL;
@@ -276,7 +279,7 @@
 	skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM);
 
 	return nfc_data_exchange(dev, local->target_idx, skb,
-					nfc_llcp_recv, local);
+				 nfc_llcp_recv, local);
 }
 
 int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
@@ -284,6 +287,9 @@
 	struct nfc_llcp_local *local;
 	struct sk_buff *skb;
 	u8 *service_name_tlv = NULL, service_name_tlv_length;
+	u8 *miux_tlv = NULL, miux_tlv_length;
+	u8 *rw_tlv = NULL, rw_tlv_length, rw;
+	__be16 miux;
 	int err;
 	u16 size = 0;
 
@@ -295,12 +301,21 @@
 
 	if (sock->service_name != NULL) {
 		service_name_tlv = nfc_llcp_build_tlv(LLCP_TLV_SN,
-					sock->service_name,
-					sock->service_name_len,
-					&service_name_tlv_length);
+						      sock->service_name,
+						      sock->service_name_len,
+						      &service_name_tlv_length);
 		size += service_name_tlv_length;
 	}
 
+	miux = cpu_to_be16(LLCP_MAX_MIUX);
+	miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
+				      &miux_tlv_length);
+	size += miux_tlv_length;
+
+	rw = LLCP_MAX_RW;
+	rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
+	size += rw_tlv_length;
+
 	pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len);
 
 	skb = llcp_allocate_pdu(sock, LLCP_PDU_CONNECT, size);
@@ -311,7 +326,10 @@
 
 	if (service_name_tlv != NULL)
 		skb = llcp_add_tlv(skb, service_name_tlv,
-					service_name_tlv_length);
+				   service_name_tlv_length);
+
+	skb = llcp_add_tlv(skb, miux_tlv, miux_tlv_length);
+	skb = llcp_add_tlv(skb, rw_tlv, rw_tlv_length);
 
 	skb_queue_tail(&local->tx_queue, skb);
 
@@ -321,6 +339,8 @@
 	pr_err("error %d\n", err);
 
 	kfree(service_name_tlv);
+	kfree(miux_tlv);
+	kfree(rw_tlv);
 
 	return err;
 }
@@ -329,6 +349,11 @@
 {
 	struct nfc_llcp_local *local;
 	struct sk_buff *skb;
+	u8 *miux_tlv = NULL, miux_tlv_length;
+	u8 *rw_tlv = NULL, rw_tlv_length, rw;
+	__be16 miux;
+	int err;
+	u16 size = 0;
 
 	pr_debug("Sending CC\n");
 
@@ -336,13 +361,35 @@
 	if (local == NULL)
 		return -ENODEV;
 
-	skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, 0);
-	if (skb == NULL)
-		return -ENOMEM;
+	miux = cpu_to_be16(LLCP_MAX_MIUX);
+	miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
+				      &miux_tlv_length);
+	size += miux_tlv_length;
+
+	rw = LLCP_MAX_RW;
+	rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
+	size += rw_tlv_length;
+
+	skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size);
+	if (skb == NULL) {
+		err = -ENOMEM;
+		goto error_tlv;
+	}
+
+	skb = llcp_add_tlv(skb, miux_tlv, miux_tlv_length);
+	skb = llcp_add_tlv(skb, rw_tlv, rw_tlv_length);
 
 	skb_queue_tail(&local->tx_queue, skb);
 
 	return 0;
+
+error_tlv:
+	pr_err("error %d\n", err);
+
+	kfree(miux_tlv);
+	kfree(rw_tlv);
+
+	return err;
 }
 
 int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason)
@@ -397,3 +444,87 @@
 
 	return 0;
 }
+
+int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
+			  struct msghdr *msg, size_t len)
+{
+	struct sk_buff *pdu;
+	struct sock *sk = &sock->sk;
+	struct nfc_llcp_local *local;
+	size_t frag_len = 0, remaining_len;
+	u8 *msg_data, *msg_ptr;
+
+	pr_debug("Send I frame len %zd\n", len);
+
+	local = sock->local;
+	if (local == NULL)
+		return -ENODEV;
+
+	msg_data = kzalloc(len, GFP_KERNEL);
+	if (msg_data == NULL)
+		return -ENOMEM;
+
+	if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
+		kfree(msg_data);
+		return -EFAULT;
+	}
+
+	remaining_len = len;
+	msg_ptr = msg_data;
+
+	while (remaining_len > 0) {
+
+		frag_len = min_t(u16, local->remote_miu, remaining_len);
+
+		pr_debug("Fragment %zd bytes remaining %zd",
+			 frag_len, remaining_len);
+
+		pdu = llcp_allocate_pdu(sock, LLCP_PDU_I,
+					frag_len + LLCP_SEQUENCE_SIZE);
+		if (pdu == NULL)
+			return -ENOMEM;
+
+		skb_put(pdu, LLCP_SEQUENCE_SIZE);
+
+		memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
+
+		skb_queue_head(&sock->tx_queue, pdu);
+
+		lock_sock(sk);
+
+		nfc_llcp_queue_i_frames(sock);
+
+		release_sock(sk);
+
+		remaining_len -= frag_len;
+		msg_ptr += len;
+	}
+
+	kfree(msg_data);
+
+	return 0;
+}
+
+int nfc_llcp_send_rr(struct nfc_llcp_sock *sock)
+{
+	struct sk_buff *skb;
+	struct nfc_llcp_local *local;
+
+	pr_debug("Send rr nr %d\n", sock->recv_n);
+
+	local = sock->local;
+	if (local == NULL)
+		return -ENODEV;
+
+	skb = llcp_allocate_pdu(sock, LLCP_PDU_RR, LLCP_SEQUENCE_SIZE);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	skb_put(skb, LLCP_SEQUENCE_SIZE);
+
+	skb->data[2] = sock->recv_n % 16;
+
+	skb_queue_head(&local->tx_queue, skb);
+
+	return 0;
+}
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 1d32680..17a578f 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -37,7 +37,6 @@
 	struct sock *sk, *parent_sk;
 	int i;
 
-
 	mutex_lock(&local->socket_lock);
 
 	for (i = 0; i < LLCP_MAX_SAP; i++) {
@@ -47,7 +46,7 @@
 
 		/* Release all child sockets */
 		list_for_each_entry_safe(s, n, &parent->list, list) {
-			list_del(&s->list);
+			list_del_init(&s->list);
 			sk = &s->sk;
 
 			lock_sock(sk);
@@ -56,9 +55,12 @@
 				nfc_put_device(s->dev);
 
 			sk->sk_state = LLCP_CLOSED;
-			sock_set_flag(sk, SOCK_DEAD);
 
 			release_sock(sk);
+
+			sock_orphan(sk);
+
+			s->local = NULL;
 		}
 
 		parent_sk = &parent->sk;
@@ -70,18 +72,19 @@
 			struct sock *accept_sk;
 
 			list_for_each_entry_safe(lsk, n, &parent->accept_queue,
-								accept_queue) {
+						 accept_queue) {
 				accept_sk = &lsk->sk;
 				lock_sock(accept_sk);
 
 				nfc_llcp_accept_unlink(accept_sk);
 
 				accept_sk->sk_state = LLCP_CLOSED;
-				sock_set_flag(accept_sk, SOCK_DEAD);
 
 				release_sock(accept_sk);
 
 				sock_orphan(accept_sk);
+
+				lsk->local = NULL;
 			}
 		}
 
@@ -89,18 +92,32 @@
 			nfc_put_device(parent->dev);
 
 		parent_sk->sk_state = LLCP_CLOSED;
-		sock_set_flag(parent_sk, SOCK_DEAD);
 
 		release_sock(parent_sk);
+
+		sock_orphan(parent_sk);
+
+		parent->local = NULL;
 	}
 
 	mutex_unlock(&local->socket_lock);
 }
 
+static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local)
+{
+	mutex_lock(&local->sdp_lock);
+
+	local->local_wks = 0;
+	local->local_sdp = 0;
+	local->local_sap = 0;
+
+	mutex_unlock(&local->sdp_lock);
+}
+
 static void nfc_llcp_timeout_work(struct work_struct *work)
 {
 	struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
-							timeout_work);
+						    timeout_work);
 
 	nfc_dep_link_down(local->dev);
 }
@@ -146,7 +163,7 @@
 
 	num_wks = ARRAY_SIZE(wks);
 
-	for (sap = 0 ; sap < num_wks; sap++) {
+	for (sap = 0; sap < num_wks; sap++) {
 		if (wks[sap] == NULL)
 			continue;
 
@@ -158,13 +175,13 @@
 }
 
 u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
-				struct nfc_llcp_sock *sock)
+			 struct nfc_llcp_sock *sock)
 {
 	mutex_lock(&local->sdp_lock);
 
 	if (sock->service_name != NULL && sock->service_name_len > 0) {
 		int ssap = nfc_llcp_wks_sap(sock->service_name,
-						sock->service_name_len);
+					    sock->service_name_len);
 
 		if (ssap > 0) {
 			pr_debug("WKS %d\n", ssap);
@@ -176,7 +193,7 @@
 				return LLCP_SAP_MAX;
 			}
 
-			set_bit(BIT(ssap), &local->local_wks);
+			set_bit(ssap, &local->local_wks);
 			mutex_unlock(&local->sdp_lock);
 
 			return ssap;
@@ -195,25 +212,25 @@
 
 		pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap);
 
-		set_bit(BIT(ssap), &local->local_sdp);
+		set_bit(ssap, &local->local_sdp);
 		mutex_unlock(&local->sdp_lock);
 
 		return LLCP_WKS_NUM_SAP + ssap;
 
 	} else if (sock->ssap != 0) {
 		if (sock->ssap < LLCP_WKS_NUM_SAP) {
-			if (!(local->local_wks & BIT(sock->ssap))) {
-				set_bit(BIT(sock->ssap), &local->local_wks);
+			if (!test_bit(sock->ssap, &local->local_wks)) {
+				set_bit(sock->ssap, &local->local_wks);
 				mutex_unlock(&local->sdp_lock);
 
 				return sock->ssap;
 			}
 
 		} else if (sock->ssap < LLCP_SDP_NUM_SAP) {
-			if (!(local->local_sdp &
-				BIT(sock->ssap - LLCP_WKS_NUM_SAP))) {
-				set_bit(BIT(sock->ssap - LLCP_WKS_NUM_SAP),
-							&local->local_sdp);
+			if (!test_bit(sock->ssap - LLCP_WKS_NUM_SAP,
+				      &local->local_sdp)) {
+				set_bit(sock->ssap - LLCP_WKS_NUM_SAP,
+					&local->local_sdp);
 				mutex_unlock(&local->sdp_lock);
 
 				return sock->ssap;
@@ -238,7 +255,7 @@
 		return LLCP_SAP_MAX;
 	}
 
-	set_bit(BIT(local_ssap), &local->local_sap);
+	set_bit(local_ssap, &local->local_sap);
 
 	mutex_unlock(&local->sdp_lock);
 
@@ -265,12 +282,12 @@
 
 	mutex_lock(&local->sdp_lock);
 
-	clear_bit(1 << local_ssap, sdp);
+	clear_bit(local_ssap, sdp);
 
 	mutex_unlock(&local->sdp_lock);
 }
 
-u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len)
+u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
 {
 	struct nfc_llcp_local *local;
 
@@ -294,7 +311,7 @@
 
 	version = LLCP_VERSION_11;
 	version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version,
-							1, &version_length);
+					 1, &version_length);
 	gb_len += version_length;
 
 	/* 1500 ms */
@@ -304,7 +321,7 @@
 
 	pr_debug("Local wks 0x%lx\n", local->local_wks);
 	wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&local->local_wks, 2,
-								&wks_length);
+				     &wks_length);
 	gb_len += wks_length;
 
 	gb_len += ARRAY_SIZE(llcp_magic);
@@ -349,8 +366,7 @@
 	memcpy(local->remote_gb, gb, gb_len);
 	local->remote_gb_len = gb_len;
 
-	if (local->remote_gb == NULL ||
-			local->remote_gb_len == 0)
+	if (local->remote_gb == NULL || local->remote_gb_len == 0)
 		return -ENODEV;
 
 	if (memcmp(local->remote_gb, llcp_magic, 3)) {
@@ -359,26 +375,27 @@
 	}
 
 	return nfc_llcp_parse_tlv(local,
-			&local->remote_gb[3], local->remote_gb_len - 3);
+				  &local->remote_gb[3],
+				  local->remote_gb_len - 3);
 }
 
 static void nfc_llcp_tx_work(struct work_struct *work)
 {
 	struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
-							tx_work);
+						    tx_work);
 	struct sk_buff *skb;
 
 	skb = skb_dequeue(&local->tx_queue);
 	if (skb != NULL) {
 		pr_debug("Sending pending skb\n");
 		nfc_data_exchange(local->dev, local->target_idx,
-					skb, nfc_llcp_recv, local);
+				  skb, nfc_llcp_recv, local);
 	} else {
 		nfc_llcp_send_symm(local->dev);
 	}
 
 	mod_timer(&local->link_timer,
-			jiffies + msecs_to_jiffies(local->remote_lto));
+		  jiffies + msecs_to_jiffies(local->remote_lto));
 }
 
 static u8 nfc_llcp_dsap(struct sk_buff *pdu)
@@ -408,13 +425,13 @@
 
 static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu)
 {
-	pdu->data[2] = (sock->send_n << 4) | ((sock->recv_n - 1) % 16);
+	pdu->data[2] = (sock->send_n << 4) | (sock->recv_n % 16);
 	sock->send_n = (sock->send_n + 1) % 16;
 	sock->recv_ack_n = (sock->recv_n - 1) % 16;
 }
 
 static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
-						u8 ssap, u8 dsap)
+					       u8 ssap, u8 dsap)
 {
 	struct nfc_llcp_sock *sock, *llcp_sock, *n;
 
@@ -438,7 +455,7 @@
 
 	list_for_each_entry_safe(llcp_sock, n, &sock->list, list) {
 		pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock,
-				&llcp_sock->sk, llcp_sock->dsap);
+			 &llcp_sock->sk, llcp_sock->dsap);
 		if (llcp_sock->dsap == dsap) {
 			sock_hold(&llcp_sock->sk);
 			mutex_unlock(&local->socket_lock);
@@ -482,7 +499,7 @@
 }
 
 static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
-				struct sk_buff *skb)
+				  struct sk_buff *skb)
 {
 	struct sock *new_sk, *parent;
 	struct nfc_llcp_sock *sock, *new_sock;
@@ -494,7 +511,7 @@
 	pr_debug("%d %d\n", dsap, ssap);
 
 	nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
-				skb->len - LLCP_HEADER_SIZE);
+			   skb->len - LLCP_HEADER_SIZE);
 
 	if (dsap != LLCP_SAP_SDP) {
 		bound_sap = dsap;
@@ -513,7 +530,7 @@
 		lock_sock(&sock->sk);
 
 		if (sock->dsap == LLCP_SAP_SDP &&
-				sock->sk.sk_state == LLCP_LISTEN)
+		    sock->sk.sk_state == LLCP_LISTEN)
 			goto enqueue;
 	} else {
 		u8 *sn;
@@ -529,23 +546,23 @@
 
 		mutex_lock(&local->socket_lock);
 		for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET;
-								bound_sap++) {
+		     bound_sap++) {
 			sock = local->sockets[bound_sap];
 			if (sock == NULL)
 				continue;
 
 			if (sock->service_name == NULL ||
-				sock->service_name_len == 0)
+			    sock->service_name_len == 0)
 					continue;
 
 			if (sock->service_name_len != sn_len)
 				continue;
 
 			if (sock->dsap == LLCP_SAP_SDP &&
-					sock->sk.sk_state == LLCP_LISTEN &&
-					!memcmp(sn, sock->service_name, sn_len)) {
+			    sock->sk.sk_state == LLCP_LISTEN &&
+			    !memcmp(sn, sock->service_name, sn_len)) {
 				pr_debug("Found service name at SAP %d\n",
-								bound_sap);
+					 bound_sap);
 				sock_hold(&sock->sk);
 				mutex_unlock(&local->socket_lock);
 
@@ -570,8 +587,7 @@
 		goto fail;
 	}
 
-	new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type,
-				     GFP_ATOMIC);
+	new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type, GFP_ATOMIC);
 	if (new_sk == NULL) {
 		reason = LLCP_DM_REJ;
 		release_sock(&sock->sk);
@@ -616,8 +632,39 @@
 
 }
 
+int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock)
+{
+	int nr_frames = 0;
+	struct nfc_llcp_local *local = sock->local;
+
+	pr_debug("Remote ready %d tx queue len %d remote rw %d",
+		 sock->remote_ready, skb_queue_len(&sock->tx_pending_queue),
+		 local->remote_rw);
+
+	/* Try to queue some I frames for transmission */
+	while (sock->remote_ready &&
+	       skb_queue_len(&sock->tx_pending_queue) < local->remote_rw) {
+		struct sk_buff *pdu, *pending_pdu;
+
+		pdu = skb_dequeue(&sock->tx_queue);
+		if (pdu == NULL)
+			break;
+
+		/* Update N(S)/N(R) */
+		nfc_llcp_set_nrns(sock, pdu);
+
+		pending_pdu = skb_clone(pdu, GFP_KERNEL);
+
+		skb_queue_tail(&local->tx_queue, pdu);
+		skb_queue_tail(&sock->tx_pending_queue, pending_pdu);
+		nr_frames++;
+	}
+
+	return nr_frames;
+}
+
 static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
-				struct sk_buff *skb)
+			       struct sk_buff *skb)
 {
 	struct nfc_llcp_sock *llcp_sock;
 	struct sock *sk;
@@ -644,15 +691,15 @@
 		nfc_llcp_sock_put(llcp_sock);
 	}
 
-	if (ns == llcp_sock->recv_n)
-		llcp_sock->recv_n = (llcp_sock->recv_n + 1) % 16;
-	else
-		pr_err("Received out of sequence I PDU\n");
-
 	/* Pass the payload upstream */
 	if (ptype == LLCP_PDU_I) {
 		pr_debug("I frame, queueing on %p\n", &llcp_sock->sk);
 
+		if (ns == llcp_sock->recv_n)
+			llcp_sock->recv_n = (llcp_sock->recv_n + 1) % 16;
+		else
+			pr_err("Received out of sequence I PDU\n");
+
 		skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE);
 		if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) {
 			pr_err("receive queue is full\n");
@@ -673,30 +720,20 @@
 			}
 	}
 
-	/* Queue some I frames for transmission */
-	while (llcp_sock->remote_ready &&
-		skb_queue_len(&llcp_sock->tx_pending_queue) <= local->remote_rw) {
-		struct sk_buff *pdu, *pending_pdu;
+	if (ptype == LLCP_PDU_RR)
+		llcp_sock->remote_ready = true;
+	else if (ptype == LLCP_PDU_RNR)
+		llcp_sock->remote_ready = false;
 
-		pdu = skb_dequeue(&llcp_sock->tx_queue);
-		if (pdu == NULL)
-			break;
-
-		/* Update N(S)/N(R) */
-		nfc_llcp_set_nrns(llcp_sock, pdu);
-
-		pending_pdu = skb_clone(pdu, GFP_KERNEL);
-
-		skb_queue_tail(&local->tx_queue, pdu);
-		skb_queue_tail(&llcp_sock->tx_pending_queue, pending_pdu);
-	}
+	if (nfc_llcp_queue_i_frames(llcp_sock) == 0)
+		nfc_llcp_send_rr(llcp_sock);
 
 	release_sock(sk);
 	nfc_llcp_sock_put(llcp_sock);
 }
 
 static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
-				struct sk_buff *skb)
+			       struct sk_buff *skb)
 {
 	struct nfc_llcp_sock *llcp_sock;
 	struct sock *sk;
@@ -718,7 +755,6 @@
 		nfc_llcp_sock_put(llcp_sock);
 	}
 
-
 	if (sk->sk_state == LLCP_CONNECTED) {
 		nfc_put_device(local->dev);
 		sk->sk_state = LLCP_CLOSED;
@@ -731,13 +767,11 @@
 	nfc_llcp_sock_put(llcp_sock);
 }
 
-static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
-				struct sk_buff *skb)
+static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
 {
 	struct nfc_llcp_sock *llcp_sock;
 	u8 dsap, ssap;
 
-
 	dsap = nfc_llcp_dsap(skb);
 	ssap = nfc_llcp_ssap(skb);
 
@@ -756,7 +790,7 @@
 	llcp_sock->dsap = ssap;
 
 	nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
-				skb->len - LLCP_HEADER_SIZE);
+			   skb->len - LLCP_HEADER_SIZE);
 
 	nfc_llcp_sock_put(llcp_sock);
 }
@@ -764,7 +798,7 @@
 static void nfc_llcp_rx_work(struct work_struct *work)
 {
 	struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
-								rx_work);
+						    rx_work);
 	u8 dsap, ssap, ptype;
 	struct sk_buff *skb;
 
@@ -802,6 +836,7 @@
 
 	case LLCP_PDU_I:
 	case LLCP_PDU_RR:
+	case LLCP_PDU_RNR:
 		pr_debug("I frame\n");
 		nfc_llcp_recv_hdlc(local, skb);
 		break;
@@ -821,7 +856,7 @@
 
 	pr_debug("Received an LLCP PDU\n");
 	if (err < 0) {
-		pr_err("err %d", err);
+		pr_err("err %d\n", err);
 		return;
 	}
 
@@ -840,6 +875,8 @@
 	if (local == NULL)
 		return;
 
+	nfc_llcp_clear_sdp(local);
+
 	/* Close and purge all existing sockets */
 	nfc_llcp_socket_release(local);
 }
@@ -865,7 +902,7 @@
 		queue_work(local->tx_wq, &local->tx_work);
 	} else {
 		mod_timer(&local->link_timer,
-			jiffies + msecs_to_jiffies(local->remote_lto));
+			  jiffies + msecs_to_jiffies(local->remote_lto));
 	}
 }
 
@@ -891,8 +928,10 @@
 	skb_queue_head_init(&local->tx_queue);
 	INIT_WORK(&local->tx_work, nfc_llcp_tx_work);
 	snprintf(name, sizeof(name), "%s_llcp_tx_wq", dev_name(dev));
-	local->tx_wq = alloc_workqueue(name,
-			WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+	local->tx_wq =
+		alloc_workqueue(name,
+				WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
+				1);
 	if (local->tx_wq == NULL) {
 		err = -ENOMEM;
 		goto err_local;
@@ -901,8 +940,10 @@
 	local->rx_pending = NULL;
 	INIT_WORK(&local->rx_work, nfc_llcp_rx_work);
 	snprintf(name, sizeof(name), "%s_llcp_rx_wq", dev_name(dev));
-	local->rx_wq = alloc_workqueue(name,
-			WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+	local->rx_wq =
+		alloc_workqueue(name,
+				WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
+				1);
 	if (local->rx_wq == NULL) {
 		err = -ENOMEM;
 		goto err_tx_wq;
@@ -910,8 +951,10 @@
 
 	INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work);
 	snprintf(name, sizeof(name), "%s_llcp_timeout_wq", dev_name(dev));
-	local->timeout_wq = alloc_workqueue(name,
-			WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+	local->timeout_wq =
+		alloc_workqueue(name,
+				WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
+				1);
 	if (local->timeout_wq == NULL) {
 		err = -ENOMEM;
 		goto err_rx_wq;
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 0ad2e33..50680ce 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -28,6 +28,10 @@
 #define LLCP_DEFAULT_RW  1
 #define LLCP_DEFAULT_MIU 128
 
+#define LLCP_MAX_LTO  0xff
+#define LLCP_MAX_RW   15
+#define LLCP_MAX_MIUX 0x7ff
+
 #define LLCP_WKS_NUM_SAP   16
 #define LLCP_SDP_NUM_SAP   16
 #define LLCP_LOCAL_NUM_SAP 32
@@ -162,9 +166,10 @@
 
 struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
 u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
-				struct nfc_llcp_sock *sock);
+			 struct nfc_llcp_sock *sock);
 u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local);
 void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap);
+int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock);
 
 /* Sock API */
 struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp);
@@ -175,7 +180,7 @@
 
 /* TLV API */
 int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
-			u8 *tlv_array, u16 tlv_array_len);
+		       u8 *tlv_array, u16 tlv_array_len);
 
 /* Commands API */
 void nfc_llcp_recv(void *data, struct sk_buff *skb, int err);
@@ -187,6 +192,9 @@
 int nfc_llcp_send_cc(struct nfc_llcp_sock *sock);
 int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason);
 int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock);
+int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
+			  struct msghdr *msg, size_t len);
+int nfc_llcp_send_rr(struct nfc_llcp_sock *sock);
 
 /* Socket API */
 int __init nfc_llcp_sock_init(void);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index f738ccd..c13e02e 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -78,9 +78,11 @@
 	llcp_sock->local = local;
 	llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
 	llcp_sock->service_name_len = min_t(unsigned int,
-			llcp_addr.service_name_len, NFC_LLCP_MAX_SERVICE_NAME);
+					    llcp_addr.service_name_len,
+					    NFC_LLCP_MAX_SERVICE_NAME);
 	llcp_sock->service_name = kmemdup(llcp_addr.service_name,
-				llcp_sock->service_name_len, GFP_KERNEL);
+					  llcp_sock->service_name_len,
+					  GFP_KERNEL);
 
 	llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock);
 	if (llcp_sock->ssap == LLCP_MAX_SAP)
@@ -110,7 +112,7 @@
 	lock_sock(sk);
 
 	if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
-			|| sk->sk_state != LLCP_BOUND) {
+	    || sk->sk_state != LLCP_BOUND) {
 		ret = -EBADFD;
 		goto error;
 	}
@@ -149,13 +151,13 @@
 	sock_hold(sk);
 
 	list_add_tail(&llcp_sock->accept_queue,
-			&llcp_sock_parent->accept_queue);
+		      &llcp_sock_parent->accept_queue);
 	llcp_sock->parent = parent;
 	sk_acceptq_added(parent);
 }
 
 struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
-					struct socket *newsock)
+				     struct socket *newsock)
 {
 	struct nfc_llcp_sock *lsk, *n, *llcp_parent;
 	struct sock *sk;
@@ -163,7 +165,7 @@
 	llcp_parent = nfc_llcp_sock(parent);
 
 	list_for_each_entry_safe(lsk, n, &llcp_parent->accept_queue,
-							accept_queue) {
+				 accept_queue) {
 		sk = &lsk->sk;
 		lock_sock(sk);
 
@@ -192,7 +194,7 @@
 }
 
 static int llcp_sock_accept(struct socket *sock, struct socket *newsock,
-								int flags)
+			    int flags)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct sock *sk = sock->sk, *new_sk;
@@ -248,7 +250,7 @@
 static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr,
 			     int *len, int peer)
 {
-	struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *) addr;
+	struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *)addr;
 	struct sock *sk = sock->sk;
 	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
 
@@ -262,7 +264,7 @@
 	llcp_addr->ssap = llcp_sock->ssap;
 	llcp_addr->service_name_len = llcp_sock->service_name_len;
 	memcpy(llcp_addr->service_name, llcp_sock->service_name,
-					llcp_addr->service_name_len);
+	       llcp_addr->service_name_len);
 
 	return 0;
 }
@@ -275,7 +277,7 @@
 	parent_sock = nfc_llcp_sock(parent);
 
 	list_for_each_entry_safe(llcp_sock, n, &parent_sock->accept_queue,
-								accept_queue) {
+				 accept_queue) {
 		sk = &llcp_sock->sk;
 
 		if (sk->sk_state == LLCP_CONNECTED)
@@ -286,7 +288,7 @@
 }
 
 static unsigned int llcp_sock_poll(struct file *file, struct socket *sock,
-							poll_table *wait)
+				   poll_table *wait)
 {
 	struct sock *sk = sock->sk;
 	unsigned int mask = 0;
@@ -315,6 +317,7 @@
 	struct sock *sk = sock->sk;
 	struct nfc_llcp_local *local;
 	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+	int err = 0;
 
 	if (!sk)
 		return 0;
@@ -322,25 +325,17 @@
 	pr_debug("%p\n", sk);
 
 	local = llcp_sock->local;
-	if (local == NULL)
-		return -ENODEV;
+	if (local == NULL) {
+		err = -ENODEV;
+		goto out;
+	}
 
 	mutex_lock(&local->socket_lock);
 
-	if (llcp_sock == local->sockets[llcp_sock->ssap]) {
+	if (llcp_sock == local->sockets[llcp_sock->ssap])
 		local->sockets[llcp_sock->ssap] = NULL;
-	} else {
-		struct nfc_llcp_sock *parent, *s, *n;
-
-		parent = local->sockets[llcp_sock->ssap];
-
-		list_for_each_entry_safe(s, n, &parent->list, list)
-			if (llcp_sock == s) {
-				list_del(&s->list);
-				break;
-			}
-
-	}
+	else
+		list_del_init(&llcp_sock->list);
 
 	mutex_unlock(&local->socket_lock);
 
@@ -355,7 +350,7 @@
 		struct sock *accept_sk;
 
 		list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue,
-								accept_queue) {
+					 accept_queue) {
 			accept_sk = &lsk->sk;
 			lock_sock(accept_sk);
 
@@ -364,31 +359,27 @@
 
 			release_sock(accept_sk);
 
-			sock_set_flag(sk, SOCK_DEAD);
 			sock_orphan(accept_sk);
-			sock_put(accept_sk);
 		}
 	}
 
 	/* Freeing the SAP */
 	if ((sk->sk_state == LLCP_CONNECTED
-			&& llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) ||
-	    sk->sk_state == LLCP_BOUND ||
-	    sk->sk_state == LLCP_LISTEN)
+	     && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) ||
+	    sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN)
 		nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);
 
-	sock_set_flag(sk, SOCK_DEAD);
-
 	release_sock(sk);
 
+out:
 	sock_orphan(sk);
 	sock_put(sk);
 
-	return 0;
+	return err;
 }
 
 static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
-							int len, int flags)
+			     int len, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
@@ -400,7 +391,7 @@
 	pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags);
 
 	if (!addr || len < sizeof(struct sockaddr_nfc) ||
-			addr->sa_family != AF_NFC) {
+	    addr->sa_family != AF_NFC) {
 		pr_err("Invalid socket\n");
 		return -EINVAL;
 	}
@@ -411,7 +402,7 @@
 	}
 
 	pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", addr->dev_idx,
-					addr->target_idx, addr->nfc_protocol);
+		 addr->target_idx, addr->nfc_protocol);
 
 	lock_sock(sk);
 
@@ -441,7 +432,7 @@
 	device_unlock(&dev->dev);
 
 	if (local->rf_mode == NFC_RF_INITIATOR &&
-			addr->target_idx != local->target_idx) {
+	    addr->target_idx != local->target_idx) {
 		ret = -ENOLINK;
 		goto put_dev;
 	}
@@ -459,9 +450,11 @@
 		llcp_sock->dsap = LLCP_SAP_SDP;
 	llcp_sock->nfc_protocol = addr->nfc_protocol;
 	llcp_sock->service_name_len = min_t(unsigned int,
-			addr->service_name_len, NFC_LLCP_MAX_SERVICE_NAME);
+					    addr->service_name_len,
+					    NFC_LLCP_MAX_SERVICE_NAME);
 	llcp_sock->service_name = kmemdup(addr->service_name,
-				 llcp_sock->service_name_len, GFP_KERNEL);
+					  llcp_sock->service_name_len,
+					  GFP_KERNEL);
 
 	local->sockets[llcp_sock->ssap] = llcp_sock;
 
@@ -482,6 +475,34 @@
 	return ret;
 }
 
+static int llcp_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
+			     struct msghdr *msg, size_t len)
+{
+	struct sock *sk = sock->sk;
+	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+	int ret;
+
+	pr_debug("sock %p sk %p", sock, sk);
+
+	ret = sock_error(sk);
+	if (ret)
+		return ret;
+
+	if (msg->msg_flags & MSG_OOB)
+		return -EOPNOTSUPP;
+
+	lock_sock(sk);
+
+	if (sk->sk_state != LLCP_CONNECTED) {
+		release_sock(sk);
+		return -ENOTCONN;
+	}
+
+	release_sock(sk);
+
+	return nfc_llcp_send_i_frame(llcp_sock, msg, len);
+}
+
 static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 			     struct msghdr *msg, size_t len, int flags)
 {
@@ -496,7 +517,7 @@
 	lock_sock(sk);
 
 	if (sk->sk_state == LLCP_CLOSED &&
-			skb_queue_empty(&sk->sk_receive_queue)) {
+	    skb_queue_empty(&sk->sk_receive_queue)) {
 		release_sock(sk);
 		return 0;
 	}
@@ -509,7 +530,7 @@
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb) {
 		pr_err("Recv datagram failed state %d %d %d",
-				sk->sk_state, err, sock_error(sk));
+		       sk->sk_state, err, sock_error(sk));
 
 		if (sk->sk_shutdown & RCV_SHUTDOWN)
 			return 0;
@@ -517,7 +538,7 @@
 		return err;
 	}
 
-	rlen   = skb->len;		/* real length of skb */
+	rlen = skb->len;		/* real length of skb */
 	copied = min_t(unsigned int, rlen, len);
 
 	cskb = skb;
@@ -567,7 +588,7 @@
 	.shutdown       = sock_no_shutdown,
 	.setsockopt     = sock_no_setsockopt,
 	.getsockopt     = sock_no_getsockopt,
-	.sendmsg        = sock_no_sendmsg,
+	.sendmsg        = llcp_sock_sendmsg,
 	.recvmsg        = llcp_sock_recvmsg,
 	.mmap           = sock_no_mmap,
 };
@@ -627,6 +648,8 @@
 
 void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
 {
+	struct nfc_llcp_local *local = sock->local;
+
 	kfree(sock->service_name);
 
 	skb_queue_purge(&sock->tx_queue);
@@ -635,11 +658,16 @@
 
 	list_del_init(&sock->accept_queue);
 
+	if (local != NULL && sock == local->sockets[sock->ssap])
+		local->sockets[sock->ssap] = NULL;
+	else
+		list_del_init(&sock->list);
+
 	sock->parent = NULL;
 }
 
 static int llcp_sock_create(struct net *net, struct socket *sock,
-				const struct nfc_protocol *nfc_proto)
+			    const struct nfc_protocol *nfc_proto)
 {
 	struct sock *sk;
 
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index a47e90c..9ec065b 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -66,9 +66,8 @@
 
 /* Execute request and wait for completion. */
 static int __nci_request(struct nci_dev *ndev,
-	void (*req)(struct nci_dev *ndev, unsigned long opt),
-	unsigned long opt,
-	__u32 timeout)
+			 void (*req)(struct nci_dev *ndev, unsigned long opt),
+			 unsigned long opt, __u32 timeout)
 {
 	int rc = 0;
 	long completion_rc;
@@ -77,9 +76,9 @@
 
 	init_completion(&ndev->req_completion);
 	req(ndev, opt);
-	completion_rc = wait_for_completion_interruptible_timeout(
-							&ndev->req_completion,
-							timeout);
+	completion_rc =
+		wait_for_completion_interruptible_timeout(&ndev->req_completion,
+							  timeout);
 
 	pr_debug("wait_for_completion return %ld\n", completion_rc);
 
@@ -110,8 +109,9 @@
 }
 
 static inline int nci_request(struct nci_dev *ndev,
-		void (*req)(struct nci_dev *ndev, unsigned long opt),
-		unsigned long opt, __u32 timeout)
+			      void (*req)(struct nci_dev *ndev,
+					  unsigned long opt),
+			      unsigned long opt, __u32 timeout)
 {
 	int rc;
 
@@ -152,14 +152,14 @@
 	/* by default mapping is set to NCI_RF_INTERFACE_FRAME */
 	for (i = 0; i < ndev->num_supported_rf_interfaces; i++) {
 		if (ndev->supported_rf_interfaces[i] ==
-			NCI_RF_INTERFACE_ISO_DEP) {
+		    NCI_RF_INTERFACE_ISO_DEP) {
 			cfg[*num].rf_protocol = NCI_RF_PROTOCOL_ISO_DEP;
 			cfg[*num].mode = NCI_DISC_MAP_MODE_POLL |
 				NCI_DISC_MAP_MODE_LISTEN;
 			cfg[*num].rf_interface = NCI_RF_INTERFACE_ISO_DEP;
 			(*num)++;
 		} else if (ndev->supported_rf_interfaces[i] ==
-			NCI_RF_INTERFACE_NFC_DEP) {
+			   NCI_RF_INTERFACE_NFC_DEP) {
 			cfg[*num].rf_protocol = NCI_RF_PROTOCOL_NFC_DEP;
 			cfg[*num].mode = NCI_DISC_MAP_MODE_POLL |
 				NCI_DISC_MAP_MODE_LISTEN;
@@ -172,8 +172,7 @@
 	}
 
 	nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_MAP_CMD,
-		(1 + ((*num)*sizeof(struct disc_map_config))),
-		&cmd);
+		     (1 + ((*num) * sizeof(struct disc_map_config))), &cmd);
 }
 
 static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
@@ -184,36 +183,36 @@
 	cmd.num_disc_configs = 0;
 
 	if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
-		(protocols & NFC_PROTO_JEWEL_MASK
-		|| protocols & NFC_PROTO_MIFARE_MASK
-		|| protocols & NFC_PROTO_ISO14443_MASK
-		|| protocols & NFC_PROTO_NFC_DEP_MASK)) {
+	    (protocols & NFC_PROTO_JEWEL_MASK
+	     || protocols & NFC_PROTO_MIFARE_MASK
+	     || protocols & NFC_PROTO_ISO14443_MASK
+	     || protocols & NFC_PROTO_NFC_DEP_MASK)) {
 		cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
-		NCI_NFC_A_PASSIVE_POLL_MODE;
+			NCI_NFC_A_PASSIVE_POLL_MODE;
 		cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
 		cmd.num_disc_configs++;
 	}
 
 	if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
-		(protocols & NFC_PROTO_ISO14443_MASK)) {
+	    (protocols & NFC_PROTO_ISO14443_MASK)) {
 		cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
-		NCI_NFC_B_PASSIVE_POLL_MODE;
+			NCI_NFC_B_PASSIVE_POLL_MODE;
 		cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
 		cmd.num_disc_configs++;
 	}
 
 	if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
-		(protocols & NFC_PROTO_FELICA_MASK
-		|| protocols & NFC_PROTO_NFC_DEP_MASK)) {
+	    (protocols & NFC_PROTO_FELICA_MASK
+	     || protocols & NFC_PROTO_NFC_DEP_MASK)) {
 		cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
-		NCI_NFC_F_PASSIVE_POLL_MODE;
+			NCI_NFC_F_PASSIVE_POLL_MODE;
 		cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
 		cmd.num_disc_configs++;
 	}
 
 	nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD,
-		(1 + (cmd.num_disc_configs*sizeof(struct disc_config))),
-		&cmd);
+		     (1 + (cmd.num_disc_configs * sizeof(struct disc_config))),
+		     &cmd);
 }
 
 struct nci_rf_discover_select_param {
@@ -224,7 +223,7 @@
 static void nci_rf_discover_select_req(struct nci_dev *ndev, unsigned long opt)
 {
 	struct nci_rf_discover_select_param *param =
-				(struct nci_rf_discover_select_param *)opt;
+		(struct nci_rf_discover_select_param *)opt;
 	struct nci_rf_discover_select_cmd cmd;
 
 	cmd.rf_discovery_id = param->rf_discovery_id;
@@ -245,8 +244,7 @@
 	}
 
 	nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_SELECT_CMD,
-			sizeof(struct nci_rf_discover_select_cmd),
-			&cmd);
+		     sizeof(struct nci_rf_discover_select_cmd), &cmd);
 }
 
 static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt)
@@ -256,8 +254,7 @@
 	cmd.type = NCI_DEACTIVATE_TYPE_IDLE_MODE;
 
 	nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD,
-			sizeof(struct nci_rf_deactivate_cmd),
-			&cmd);
+		     sizeof(struct nci_rf_deactivate_cmd), &cmd);
 }
 
 static int nci_open_device(struct nci_dev *ndev)
@@ -281,16 +278,16 @@
 	set_bit(NCI_INIT, &ndev->flags);
 
 	rc = __nci_request(ndev, nci_reset_req, 0,
-				msecs_to_jiffies(NCI_RESET_TIMEOUT));
+			   msecs_to_jiffies(NCI_RESET_TIMEOUT));
 
 	if (!rc) {
 		rc = __nci_request(ndev, nci_init_req, 0,
-				msecs_to_jiffies(NCI_INIT_TIMEOUT));
+				   msecs_to_jiffies(NCI_INIT_TIMEOUT));
 	}
 
 	if (!rc) {
 		rc = __nci_request(ndev, nci_init_complete_req, 0,
-				msecs_to_jiffies(NCI_INIT_TIMEOUT));
+				   msecs_to_jiffies(NCI_INIT_TIMEOUT));
 	}
 
 	clear_bit(NCI_INIT, &ndev->flags);
@@ -340,7 +337,7 @@
 
 	set_bit(NCI_INIT, &ndev->flags);
 	__nci_request(ndev, nci_reset_req, 0,
-				msecs_to_jiffies(NCI_RESET_TIMEOUT));
+		      msecs_to_jiffies(NCI_RESET_TIMEOUT));
 	clear_bit(NCI_INIT, &ndev->flags);
 
 	/* Flush cmd wq */
@@ -396,7 +393,7 @@
 	int rc;
 
 	if ((atomic_read(&ndev->state) == NCI_DISCOVERY) ||
-		(atomic_read(&ndev->state) == NCI_W4_ALL_DISCOVERIES)) {
+	    (atomic_read(&ndev->state) == NCI_W4_ALL_DISCOVERIES)) {
 		pr_err("unable to start poll, since poll is already active\n");
 		return -EBUSY;
 	}
@@ -407,17 +404,17 @@
 	}
 
 	if ((atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) ||
-		(atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) {
+	    (atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) {
 		pr_debug("target active or w4 select, implicitly deactivate\n");
 
 		rc = nci_request(ndev, nci_rf_deactivate_req, 0,
-			msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
+				 msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
 		if (rc)
 			return -EBUSY;
 	}
 
 	rc = nci_request(ndev, nci_rf_discover_req, protocols,
-		msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
+			 msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
 
 	if (!rc)
 		ndev->poll_prots = protocols;
@@ -430,17 +427,17 @@
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
 
 	if ((atomic_read(&ndev->state) != NCI_DISCOVERY) &&
-		(atomic_read(&ndev->state) != NCI_W4_ALL_DISCOVERIES)) {
+	    (atomic_read(&ndev->state) != NCI_W4_ALL_DISCOVERIES)) {
 		pr_err("unable to stop poll, since poll is not active\n");
 		return;
 	}
 
 	nci_request(ndev, nci_rf_deactivate_req, 0,
-		msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
+		    msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
 }
 
 static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx,
-				__u32 protocol)
+			       __u32 protocol)
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
 	struct nci_rf_discover_select_param param;
@@ -451,7 +448,7 @@
 	pr_debug("target_idx %d, protocol 0x%x\n", target_idx, protocol);
 
 	if ((atomic_read(&ndev->state) != NCI_W4_HOST_SELECT) &&
-		(atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
+	    (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
 		pr_err("there is no available target to activate\n");
 		return -EINVAL;
 	}
@@ -494,8 +491,8 @@
 			param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP;
 
 		rc = nci_request(ndev, nci_rf_discover_select_req,
-				(unsigned long)&param,
-				msecs_to_jiffies(NCI_RF_DISC_SELECT_TIMEOUT));
+				 (unsigned long)&param,
+				 msecs_to_jiffies(NCI_RF_DISC_SELECT_TIMEOUT));
 	}
 
 	if (!rc)
@@ -519,14 +516,13 @@
 
 	if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) {
 		nci_request(ndev, nci_rf_deactivate_req, 0,
-			msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
+			    msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
 	}
 }
 
 static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx,
-						struct sk_buff *skb,
-						data_exchange_cb_t cb,
-						void *cb_context)
+			     struct sk_buff *skb,
+			     data_exchange_cb_t cb, void *cb_context)
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
 	int rc;
@@ -571,9 +567,8 @@
  * @supported_protocols: NFC protocols supported by the device
  */
 struct nci_dev *nci_allocate_device(struct nci_ops *ops,
-					__u32 supported_protocols,
-					int tx_headroom,
-					int tx_tailroom)
+				    __u32 supported_protocols,
+				    int tx_headroom, int tx_tailroom)
 {
 	struct nci_dev *ndev;
 
@@ -594,9 +589,9 @@
 	ndev->tx_tailroom = tx_tailroom;
 
 	ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops,
-						supported_protocols,
-						tx_headroom + NCI_DATA_HDR_SIZE,
-						tx_tailroom);
+					    supported_protocols,
+					    tx_headroom + NCI_DATA_HDR_SIZE,
+					    tx_tailroom);
 	if (!ndev->nfc_dev)
 		goto free_exit;
 
@@ -668,9 +663,9 @@
 	skb_queue_head_init(&ndev->tx_q);
 
 	setup_timer(&ndev->cmd_timer, nci_cmd_timer,
-			(unsigned long) ndev);
+		    (unsigned long) ndev);
 	setup_timer(&ndev->data_timer, nci_data_timer,
-			(unsigned long) ndev);
+		    (unsigned long) ndev);
 
 	mutex_init(&ndev->req_lock);
 
@@ -719,7 +714,7 @@
 	pr_debug("len %d\n", skb->len);
 
 	if (!ndev || (!test_bit(NCI_UP, &ndev->flags)
-		&& !test_bit(NCI_INIT, &ndev->flags))) {
+		      && !test_bit(NCI_INIT, &ndev->flags))) {
 		kfree_skb(skb);
 		return -ENXIO;
 	}
@@ -799,7 +794,7 @@
 
 		/* Check if data flow control is used */
 		if (atomic_read(&ndev->credits_cnt) !=
-				NCI_DATA_FLOW_CONTROL_NOT_USED)
+		    NCI_DATA_FLOW_CONTROL_NOT_USED)
 			atomic_dec(&ndev->credits_cnt);
 
 		pr_debug("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d\n",
@@ -810,7 +805,7 @@
 		nci_send_frame(skb);
 
 		mod_timer(&ndev->data_timer,
-			jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT));
+			  jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT));
 	}
 }
 
@@ -879,6 +874,6 @@
 		nci_send_frame(skb);
 
 		mod_timer(&ndev->cmd_timer,
-			jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT));
+			  jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT));
 	}
 }
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
index 7880ae9..a0bc326 100644
--- a/net/nfc/nci/data.c
+++ b/net/nfc/nci/data.c
@@ -35,8 +35,7 @@
 #include <linux/nfc.h>
 
 /* Complete data exchange transaction and forward skb to nfc core */
-void nci_data_exchange_complete(struct nci_dev *ndev,
-				struct sk_buff *skb,
+void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
 				int err)
 {
 	data_exchange_cb_t cb = ndev->data_exchange_cb;
@@ -67,9 +66,9 @@
 /* ----------------- NCI TX Data ----------------- */
 
 static inline void nci_push_data_hdr(struct nci_dev *ndev,
-					__u8 conn_id,
-					struct sk_buff *skb,
-					__u8 pbf)
+				     __u8 conn_id,
+				     struct sk_buff *skb,
+				     __u8 pbf)
 {
 	struct nci_data_hdr *hdr;
 	int plen = skb->len;
@@ -86,8 +85,8 @@
 }
 
 static int nci_queue_tx_data_frags(struct nci_dev *ndev,
-					__u8 conn_id,
-					struct sk_buff *skb) {
+				   __u8 conn_id,
+				   struct sk_buff *skb) {
 	int total_len = skb->len;
 	unsigned char *data = skb->data;
 	unsigned long flags;
@@ -105,8 +104,8 @@
 			min_t(int, total_len, ndev->max_data_pkt_payload_size);
 
 		skb_frag = nci_skb_alloc(ndev,
-					(NCI_DATA_HDR_SIZE + frag_len),
-					GFP_KERNEL);
+					 (NCI_DATA_HDR_SIZE + frag_len),
+					 GFP_KERNEL);
 		if (skb_frag == NULL) {
 			rc = -ENOMEM;
 			goto free_exit;
@@ -118,7 +117,8 @@
 
 		/* second, set the header */
 		nci_push_data_hdr(ndev, conn_id, skb_frag,
-		((total_len == frag_len) ? (NCI_PBF_LAST) : (NCI_PBF_CONT)));
+				  ((total_len == frag_len) ?
+				   (NCI_PBF_LAST) : (NCI_PBF_CONT)));
 
 		__skb_queue_tail(&frags_q, skb_frag);
 
@@ -186,8 +186,8 @@
 /* ----------------- NCI RX Data ----------------- */
 
 static void nci_add_rx_data_frag(struct nci_dev *ndev,
-				struct sk_buff *skb,
-				__u8 pbf)
+				 struct sk_buff *skb,
+				 __u8 pbf)
 {
 	int reassembly_len;
 	int err = 0;
@@ -211,8 +211,8 @@
 
 		/* second, combine the two fragments */
 		memcpy(skb_push(skb, reassembly_len),
-				ndev->rx_data_reassembly->data,
-				reassembly_len);
+		       ndev->rx_data_reassembly->data,
+		       reassembly_len);
 
 		/* third, free old reassembly */
 		kfree_skb(ndev->rx_data_reassembly);
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 03e7b46..2e3dee4 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -40,7 +40,7 @@
 /* Handle NCI Notification packets */
 
 static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
-						struct sk_buff *skb)
+					     struct sk_buff *skb)
 {
 	struct nci_core_conn_credit_ntf *ntf = (void *) skb->data;
 	int i;
@@ -62,7 +62,7 @@
 		if (ntf->conn_entries[i].conn_id == NCI_STATIC_RF_CONN_ID) {
 			/* found static rf connection */
 			atomic_add(ntf->conn_entries[i].credits,
-				&ndev->credits_cnt);
+				   &ndev->credits_cnt);
 		}
 	}
 
@@ -72,7 +72,7 @@
 }
 
 static void nci_core_generic_error_ntf_packet(struct nci_dev *ndev,
-						struct sk_buff *skb)
+					      struct sk_buff *skb)
 {
 	__u8 status = skb->data[0];
 
@@ -80,7 +80,7 @@
 
 	if (atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) {
 		/* Activation failed, so complete the request
-		(the state remains the same) */
+		   (the state remains the same) */
 		nci_req_complete(ndev, status);
 	}
 }
@@ -101,7 +101,7 @@
 
 static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev,
 			struct rf_tech_specific_params_nfca_poll *nfca_poll,
-			__u8 *data)
+						     __u8 *data)
 {
 	nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data));
 	data += 2;
@@ -128,7 +128,7 @@
 
 static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev,
 			struct rf_tech_specific_params_nfcb_poll *nfcb_poll,
-			__u8 *data)
+						     __u8 *data)
 {
 	nfcb_poll->sensb_res_len = *data++;
 
@@ -142,13 +142,13 @@
 
 static __u8 *nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev,
 			struct rf_tech_specific_params_nfcf_poll *nfcf_poll,
-			__u8 *data)
+						     __u8 *data)
 {
 	nfcf_poll->bit_rate = *data++;
 	nfcf_poll->sensf_res_len = *data++;
 
 	pr_debug("bit_rate %d, sensf_res_len %d\n",
-		nfcf_poll->bit_rate, nfcf_poll->sensf_res_len);
+		 nfcf_poll->bit_rate, nfcf_poll->sensf_res_len);
 
 	memcpy(nfcf_poll->sensf_res, data, nfcf_poll->sensf_res_len);
 	data += nfcf_poll->sensf_res_len;
@@ -189,7 +189,7 @@
 		target->nfcid1_len = nfca_poll->nfcid1_len;
 		if (target->nfcid1_len > 0) {
 			memcpy(target->nfcid1, nfca_poll->nfcid1,
-				target->nfcid1_len);
+			       target->nfcid1_len);
 		}
 	} else if (rf_tech_and_mode == NCI_NFC_B_PASSIVE_POLL_MODE) {
 		nfcb_poll = (struct rf_tech_specific_params_nfcb_poll *)params;
@@ -197,7 +197,7 @@
 		target->sensb_res_len = nfcb_poll->sensb_res_len;
 		if (target->sensb_res_len > 0) {
 			memcpy(target->sensb_res, nfcb_poll->sensb_res,
-				target->sensb_res_len);
+			       target->sensb_res_len);
 		}
 	} else if (rf_tech_and_mode == NCI_NFC_F_PASSIVE_POLL_MODE) {
 		nfcf_poll = (struct rf_tech_specific_params_nfcf_poll *)params;
@@ -205,7 +205,7 @@
 		target->sensf_res_len = nfcf_poll->sensf_res_len;
 		if (target->sensf_res_len > 0) {
 			memcpy(target->sensf_res, nfcf_poll->sensf_res,
-				target->sensf_res_len);
+			       target->sensf_res_len);
 		}
 	} else {
 		pr_err("unsupported rf_tech_and_mode 0x%x\n", rf_tech_and_mode);
@@ -220,7 +220,7 @@
 }
 
 static void nci_add_new_target(struct nci_dev *ndev,
-				struct nci_rf_discover_ntf *ntf)
+			       struct nci_rf_discover_ntf *ntf)
 {
 	struct nfc_target *target;
 	int i, rc;
@@ -230,8 +230,8 @@
 		if (target->idx == ntf->rf_discovery_id) {
 			/* This target already exists, add the new protocol */
 			nci_add_new_protocol(ndev, target, ntf->rf_protocol,
-						ntf->rf_tech_and_mode,
-						&ntf->rf_tech_specific_params);
+					     ntf->rf_tech_and_mode,
+					     &ntf->rf_tech_specific_params);
 			return;
 		}
 	}
@@ -245,27 +245,27 @@
 	target = &ndev->targets[ndev->n_targets];
 
 	rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol,
-					ntf->rf_tech_and_mode,
-					&ntf->rf_tech_specific_params);
+				  ntf->rf_tech_and_mode,
+				  &ntf->rf_tech_specific_params);
 	if (!rc) {
 		target->idx = ntf->rf_discovery_id;
 		ndev->n_targets++;
 
 		pr_debug("target_idx %d, n_targets %d\n", target->idx,
-				ndev->n_targets);
+			 ndev->n_targets);
 	}
 }
 
 void nci_clear_target_list(struct nci_dev *ndev)
 {
 	memset(ndev->targets, 0,
-		(sizeof(struct nfc_target)*NCI_MAX_DISCOVERED_TARGETS));
+	       (sizeof(struct nfc_target)*NCI_MAX_DISCOVERED_TARGETS));
 
 	ndev->n_targets = 0;
 }
 
 static void nci_rf_discover_ntf_packet(struct nci_dev *ndev,
-					struct sk_buff *skb)
+				       struct sk_buff *skb)
 {
 	struct nci_rf_discover_ntf ntf;
 	__u8 *data = skb->data;
@@ -280,7 +280,7 @@
 	pr_debug("rf_protocol 0x%x\n", ntf.rf_protocol);
 	pr_debug("rf_tech_and_mode 0x%x\n", ntf.rf_tech_and_mode);
 	pr_debug("rf_tech_specific_params_len %d\n",
-			ntf.rf_tech_specific_params_len);
+		 ntf.rf_tech_specific_params_len);
 
 	if (ntf.rf_tech_specific_params_len > 0) {
 		switch (ntf.rf_tech_and_mode) {
@@ -318,7 +318,7 @@
 	} else {
 		atomic_set(&ndev->state, NCI_W4_HOST_SELECT);
 		nfc_targets_found(ndev->nfc_dev, ndev->targets,
-					ndev->n_targets);
+				  ndev->n_targets);
 	}
 }
 
@@ -335,20 +335,17 @@
 		pr_debug("rats_res_len %d\n", nfca_poll->rats_res_len);
 		if (nfca_poll->rats_res_len > 0) {
 			memcpy(nfca_poll->rats_res,
-				data,
-				nfca_poll->rats_res_len);
+			       data, nfca_poll->rats_res_len);
 		}
 		break;
 
 	case NCI_NFC_B_PASSIVE_POLL_MODE:
 		nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep;
 		nfcb_poll->attrib_res_len = *data++;
-		pr_debug("attrib_res_len %d\n",
-			nfcb_poll->attrib_res_len);
+		pr_debug("attrib_res_len %d\n", nfcb_poll->attrib_res_len);
 		if (nfcb_poll->attrib_res_len > 0) {
 			memcpy(nfcb_poll->attrib_res,
-				data,
-				nfcb_poll->attrib_res_len);
+			       data, nfcb_poll->attrib_res_len);
 		}
 		break;
 
@@ -362,7 +359,7 @@
 }
 
 static void nci_target_auto_activated(struct nci_dev *ndev,
-					struct nci_rf_intf_activated_ntf *ntf)
+				      struct nci_rf_intf_activated_ntf *ntf)
 {
 	struct nfc_target *target;
 	int rc;
@@ -370,8 +367,8 @@
 	target = &ndev->targets[ndev->n_targets];
 
 	rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol,
-					ntf->activation_rf_tech_and_mode,
-					&ntf->rf_tech_specific_params);
+				  ntf->activation_rf_tech_and_mode,
+				  &ntf->rf_tech_specific_params);
 	if (rc)
 		return;
 
@@ -384,7 +381,7 @@
 }
 
 static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
-						struct sk_buff *skb)
+					     struct sk_buff *skb)
 {
 	struct nci_rf_intf_activated_ntf ntf;
 	__u8 *data = skb->data;
@@ -405,7 +402,8 @@
 		 ntf.activation_rf_tech_and_mode);
 	pr_debug("max_data_pkt_payload_size 0x%x\n",
 		 ntf.max_data_pkt_payload_size);
-	pr_debug("initial_num_credits 0x%x\n", ntf.initial_num_credits);
+	pr_debug("initial_num_credits 0x%x\n",
+		 ntf.initial_num_credits);
 	pr_debug("rf_tech_specific_params_len %d\n",
 		 ntf.rf_tech_specific_params_len);
 
@@ -441,18 +439,15 @@
 
 	pr_debug("data_exch_rf_tech_and_mode 0x%x\n",
 		 ntf.data_exch_rf_tech_and_mode);
-	pr_debug("data_exch_tx_bit_rate 0x%x\n",
-		 ntf.data_exch_tx_bit_rate);
-	pr_debug("data_exch_rx_bit_rate 0x%x\n",
-		 ntf.data_exch_rx_bit_rate);
-	pr_debug("activation_params_len %d\n",
-		 ntf.activation_params_len);
+	pr_debug("data_exch_tx_bit_rate 0x%x\n", ntf.data_exch_tx_bit_rate);
+	pr_debug("data_exch_rx_bit_rate 0x%x\n", ntf.data_exch_rx_bit_rate);
+	pr_debug("activation_params_len %d\n", ntf.activation_params_len);
 
 	if (ntf.activation_params_len > 0) {
 		switch (ntf.rf_interface) {
 		case NCI_RF_INTERFACE_ISO_DEP:
 			err = nci_extract_activation_params_iso_dep(ndev,
-				&ntf, data);
+								    &ntf, data);
 			break;
 
 		case NCI_RF_INTERFACE_FRAME:
@@ -489,7 +484,7 @@
 }
 
 static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
-					struct sk_buff *skb)
+					 struct sk_buff *skb)
 {
 	struct nci_rf_deactivate_ntf *ntf = (void *) skb->data;
 
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index aa63b1e..3003c33 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -67,19 +67,18 @@
 	ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
 
 	if (ndev->num_supported_rf_interfaces >
-			NCI_MAX_SUPPORTED_RF_INTERFACES) {
+	    NCI_MAX_SUPPORTED_RF_INTERFACES) {
 		ndev->num_supported_rf_interfaces =
 			NCI_MAX_SUPPORTED_RF_INTERFACES;
 	}
 
 	memcpy(ndev->supported_rf_interfaces,
-		rsp_1->supported_rf_interfaces,
-		ndev->num_supported_rf_interfaces);
+	       rsp_1->supported_rf_interfaces,
+	       ndev->num_supported_rf_interfaces);
 
 	rsp_2 = (void *) (skb->data + 6 + rsp_1->num_supported_rf_interfaces);
 
-	ndev->max_logical_connections =
-		rsp_2->max_logical_connections;
+	ndev->max_logical_connections = rsp_2->max_logical_connections;
 	ndev->max_routing_table_size =
 		__le16_to_cpu(rsp_2->max_routing_table_size);
 	ndev->max_ctrl_pkt_payload_len =
@@ -121,7 +120,7 @@
 }
 
 static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev,
-					struct sk_buff *skb)
+				       struct sk_buff *skb)
 {
 	__u8 status = skb->data[0];
 
@@ -143,7 +142,7 @@
 }
 
 static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev,
-						struct sk_buff *skb)
+					  struct sk_buff *skb)
 {
 	__u8 status = skb->data[0];
 
@@ -155,7 +154,7 @@
 }
 
 static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev,
-					struct sk_buff *skb)
+					 struct sk_buff *skb)
 {
 	__u8 status = skb->data[0];
 
@@ -163,7 +162,7 @@
 
 	/* If target was active, complete the request only in deactivate_ntf */
 	if ((status != NCI_STATUS_OK) ||
-		(atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
+	    (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
 		nci_clear_target_list(ndev);
 		atomic_set(&ndev->state, NCI_IDLE);
 		nci_req_complete(ndev, status);
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 07f0348..6404052 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -48,34 +48,34 @@
 	[NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 },
 	[NFC_ATTR_COMM_MODE] = { .type = NLA_U8 },
 	[NFC_ATTR_RF_MODE] = { .type = NLA_U8 },
+	[NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 },
 };
 
 static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
-					struct netlink_callback *cb, int flags)
+				struct netlink_callback *cb, int flags)
 {
 	void *hdr;
 
 	hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
-				&nfc_genl_family, flags, NFC_CMD_GET_TARGET);
+			  &nfc_genl_family, flags, NFC_CMD_GET_TARGET);
 	if (!hdr)
 		return -EMSGSIZE;
 
 	genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
 
 	NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target->idx);
-	NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS,
-				target->supported_protocols);
+	NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, target->supported_protocols);
 	NLA_PUT_U16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res);
 	NLA_PUT_U8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res);
 	if (target->nfcid1_len > 0)
 		NLA_PUT(msg, NFC_ATTR_TARGET_NFCID1, target->nfcid1_len,
-				target->nfcid1);
+			target->nfcid1);
 	if (target->sensb_res_len > 0)
 		NLA_PUT(msg, NFC_ATTR_TARGET_SENSB_RES, target->sensb_res_len,
-				target->sensb_res);
+			target->sensb_res);
 	if (target->sensf_res_len > 0)
 		NLA_PUT(msg, NFC_ATTR_TARGET_SENSF_RES, target->sensf_res_len,
-				target->sensf_res);
+			target->sensf_res);
 
 	return genlmsg_end(msg, hdr);
 
@@ -91,9 +91,9 @@
 	u32 idx;
 
 	rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize,
-						nfc_genl_family.attrbuf,
-						nfc_genl_family.maxattr,
-						nfc_genl_policy);
+			 nfc_genl_family.attrbuf,
+			 nfc_genl_family.maxattr,
+			 nfc_genl_policy);
 	if (rc < 0)
 		return ERR_PTR(rc);
 
@@ -110,7 +110,7 @@
 }
 
 static int nfc_genl_dump_targets(struct sk_buff *skb,
-				struct netlink_callback *cb)
+				 struct netlink_callback *cb)
 {
 	int i = cb->args[0];
 	struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
@@ -130,7 +130,7 @@
 
 	while (i < dev->n_targets) {
 		rc = nfc_genl_send_target(skb, &dev->targets[i], cb,
-								NLM_F_MULTI);
+					  NLM_F_MULTI);
 		if (rc < 0)
 			break;
 
@@ -166,7 +166,7 @@
 		return -ENOMEM;
 
 	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
-				NFC_EVENT_TARGETS_FOUND);
+			  NFC_EVENT_TARGETS_FOUND);
 	if (!hdr)
 		goto free_msg;
 
@@ -193,13 +193,14 @@
 		return -ENOMEM;
 
 	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
-				NFC_EVENT_DEVICE_ADDED);
+			  NFC_EVENT_DEVICE_ADDED);
 	if (!hdr)
 		goto free_msg;
 
 	NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
 	NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
 	NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);
+	NLA_PUT_U8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up);
 
 	genlmsg_end(msg, hdr);
 
@@ -224,7 +225,7 @@
 		return -ENOMEM;
 
 	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
-				NFC_EVENT_DEVICE_REMOVED);
+			  NFC_EVENT_DEVICE_REMOVED);
 	if (!hdr)
 		goto free_msg;
 
@@ -244,14 +245,14 @@
 }
 
 static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
-						u32 pid, u32 seq,
-						struct netlink_callback *cb,
-						int flags)
+				u32 pid, u32 seq,
+				struct netlink_callback *cb,
+				int flags)
 {
 	void *hdr;
 
 	hdr = genlmsg_put(msg, pid, seq, &nfc_genl_family, flags,
-							NFC_CMD_GET_DEVICE);
+			  NFC_CMD_GET_DEVICE);
 	if (!hdr)
 		return -EMSGSIZE;
 
@@ -261,6 +262,7 @@
 	NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
 	NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
 	NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);
+	NLA_PUT_U8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up);
 
 	return genlmsg_end(msg, hdr);
 
@@ -270,7 +272,7 @@
 }
 
 static int nfc_genl_dump_devices(struct sk_buff *skb,
-				struct netlink_callback *cb)
+				 struct netlink_callback *cb)
 {
 	struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
 	struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
@@ -297,8 +299,7 @@
 		int rc;
 
 		rc = nfc_genl_send_device(skb, dev, NETLINK_CB(cb->skb).pid,
-							cb->nlh->nlmsg_seq,
-							cb, NLM_F_MULTI);
+					  cb->nlh->nlmsg_seq, cb, NLM_F_MULTI);
 		if (rc < 0)
 			break;
 
@@ -323,7 +324,7 @@
 }
 
 int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
-						u8 comm_mode, u8 rf_mode)
+			       u8 comm_mode, u8 rf_mode)
 {
 	struct sk_buff *msg;
 	void *hdr;
@@ -334,8 +335,7 @@
 	if (!msg)
 		return -ENOMEM;
 
-	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
-				NFC_CMD_DEP_LINK_UP);
+	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_CMD_DEP_LINK_UP);
 	if (!hdr)
 		goto free_msg;
 
@@ -372,7 +372,7 @@
 		return -ENOMEM;
 
 	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
-				NFC_CMD_DEP_LINK_DOWN);
+			  NFC_CMD_DEP_LINK_DOWN);
 	if (!hdr)
 		goto free_msg;
 
@@ -414,7 +414,7 @@
 	}
 
 	rc = nfc_genl_send_device(msg, dev, info->snd_pid, info->snd_seq,
-								NULL, 0);
+				  NULL, 0);
 	if (rc < 0)
 		goto out_free;
 
@@ -481,7 +481,7 @@
 	pr_debug("Poll start\n");
 
 	if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
-		!info->attrs[NFC_ATTR_PROTOCOLS])
+	    !info->attrs[NFC_ATTR_PROTOCOLS])
 		return -EINVAL;
 
 	idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
@@ -539,13 +539,12 @@
 	struct nfc_dev *dev;
 	int rc, tgt_idx;
 	u32 idx;
-	u8 comm, rf;
+	u8 comm;
 
 	pr_debug("DEP link up\n");
 
 	if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
-			!info->attrs[NFC_ATTR_COMM_MODE] ||
-			!info->attrs[NFC_ATTR_RF_MODE])
+	    !info->attrs[NFC_ATTR_COMM_MODE])
 		return -EINVAL;
 
 	idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
@@ -555,19 +554,15 @@
 		tgt_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]);
 
 	comm = nla_get_u8(info->attrs[NFC_ATTR_COMM_MODE]);
-	rf = nla_get_u8(info->attrs[NFC_ATTR_RF_MODE]);
 
 	if (comm != NFC_COMM_ACTIVE && comm != NFC_COMM_PASSIVE)
 		return -EINVAL;
 
-	if (rf != NFC_RF_INITIATOR && comm != NFC_RF_TARGET)
-		return -EINVAL;
-
 	dev = nfc_get_device(idx);
 	if (!dev)
 		return -ENODEV;
 
-	rc = nfc_dep_link_up(dev, tgt_idx, comm, rf);
+	rc = nfc_dep_link_up(dev, tgt_idx, comm);
 
 	nfc_put_device(dev);
 
@@ -642,7 +637,7 @@
 };
 
 static int nfc_genl_rcv_nl_event(struct notifier_block *this,
-						unsigned long event, void *ptr)
+				 unsigned long event, void *ptr)
 {
 	struct netlink_notify *n = ptr;
 	struct class_dev_iter iter;
@@ -695,7 +690,7 @@
 	int rc;
 
 	rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops,
-					ARRAY_SIZE(nfc_genl_ops));
+					   ARRAY_SIZE(nfc_genl_ops));
 	if (rc)
 		return rc;
 
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 6d28d75..ec8794c 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -32,7 +32,7 @@
 	struct proto *proto;
 	struct module *owner;
 	int (*create)(struct net *net, struct socket *sock,
-			const struct nfc_protocol *nfc_proto);
+		      const struct nfc_protocol *nfc_proto);
 };
 
 struct nfc_rawsock {
@@ -54,7 +54,7 @@
 int nfc_llcp_register_device(struct nfc_dev *dev);
 void nfc_llcp_unregister_device(struct nfc_dev *dev);
 int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len);
-u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len);
+u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len);
 int __init nfc_llcp_init(void);
 void nfc_llcp_exit(void);
 
@@ -65,7 +65,7 @@
 }
 
 static inline void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
-			u8 comm_mode, u8 rf_mode)
+				      u8 comm_mode, u8 rf_mode)
 {
 }
 
@@ -78,7 +78,8 @@
 {
 }
 
-static inline int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
+static inline int nfc_llcp_set_remote_gb(struct nfc_dev *dev,
+					 u8 *gb, u8 gb_len)
 {
 	return 0;
 }
@@ -160,8 +161,7 @@
 
 int nfc_stop_poll(struct nfc_dev *dev);
 
-int nfc_dep_link_up(struct nfc_dev *dev, int target_idx,
-				u8 comm_mode, u8 rf_mode);
+int nfc_dep_link_up(struct nfc_dev *dev, int target_idx, u8 comm_mode);
 
 int nfc_dep_link_down(struct nfc_dev *dev);
 
@@ -169,9 +169,7 @@
 
 int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);
 
-int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
-					struct sk_buff *skb,
-					data_exchange_cb_t cb,
-					void *cb_context);
+int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
+		      data_exchange_cb_t cb, void *cb_context);
 
 #endif /* __LOCAL_NFC_H */
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
index 5325439..5a839ce 100644
--- a/net/nfc/rawsock.c
+++ b/net/nfc/rawsock.c
@@ -63,7 +63,7 @@
 }
 
 static int rawsock_connect(struct socket *sock, struct sockaddr *_addr,
-							int len, int flags)
+			   int len, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_nfc *addr = (struct sockaddr_nfc *)_addr;
@@ -73,7 +73,7 @@
 	pr_debug("sock=%p sk=%p flags=%d\n", sock, sk, flags);
 
 	if (!addr || len < sizeof(struct sockaddr_nfc) ||
-		addr->sa_family != AF_NFC)
+	    addr->sa_family != AF_NFC)
 		return -EINVAL;
 
 	pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n",
@@ -120,7 +120,7 @@
 }
 
 static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb,
-								int err)
+					   int err)
 {
 	struct sock *sk = (struct sock *) context;
 
@@ -173,7 +173,7 @@
 
 	sock_hold(sk);
 	rc = nfc_data_exchange(dev, target_idx, skb,
-				rawsock_data_exchange_complete, sk);
+			       rawsock_data_exchange_complete, sk);
 	if (rc) {
 		rawsock_report_error(sk, rc);
 		sock_put(sk);
@@ -181,7 +181,7 @@
 }
 
 static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,
-					struct msghdr *msg, size_t len)
+			   struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
 	struct nfc_dev *dev = nfc_rawsock(sk)->dev;
@@ -218,7 +218,7 @@
 }
 
 static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,
-				struct msghdr *msg, size_t len, int flags)
+			   struct msghdr *msg, size_t len, int flags)
 {
 	int noblock = flags & MSG_DONTWAIT;
 	struct sock *sk = sock->sk;
@@ -274,7 +274,7 @@
 
 	if (sk->sk_state == TCP_ESTABLISHED) {
 		nfc_deactivate_target(nfc_rawsock(sk)->dev,
-					nfc_rawsock(sk)->target_idx);
+				      nfc_rawsock(sk)->target_idx);
 		nfc_put_device(nfc_rawsock(sk)->dev);
 	}
 
@@ -287,7 +287,7 @@
 }
 
 static int rawsock_create(struct net *net, struct socket *sock,
-				const struct nfc_protocol *nfc_proto)
+			  const struct nfc_protocol *nfc_proto)
 {
 	struct sock *sk;
 
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 9d3e3b6..ba21ab2 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -23,6 +23,8 @@
 #define MESH_PERR_MIN_INT	100
 #define MESH_DIAM_TRAVERSAL_TIME 50
 
+#define MESH_RSSI_THRESHOLD	0
+
 /*
  * A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds
  * before timing out.  This way it will remain ACTIVE and no data frames
@@ -56,6 +58,7 @@
 	.dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL,
 	.dot11MeshGateAnnouncementProtocol = false,
 	.dot11MeshForwarding = true,
+	.rssi_threshold = MESH_RSSI_THRESHOLD,
 };
 
 const struct mesh_setup default_mesh_setup = {
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index fb1e721..f5a7ac3 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -814,8 +814,8 @@
 				  cookie);
 }
 
-bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
-		      size_t len, gfp_t gfp)
+bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm,
+		      const u8 *buf, size_t len, gfp_t gfp)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct wiphy *wiphy = wdev->wiphy;
@@ -854,7 +854,8 @@
 		/* found match! */
 
 		/* Indicate the received Action frame to user space */
-		if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq,
+		if (nl80211_send_mgmt(rdev, dev, reg->nlpid,
+				      freq, sig_mbm,
 				      buf, len, gfp))
 			continue;
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 1998c36..4c1eb94 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -204,6 +204,8 @@
 		.len = NL80211_HT_CAPABILITY_LEN
 	},
 	[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
+	[NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
+	[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
 };
 
 /* policy for the key attributes */
@@ -2214,6 +2216,13 @@
 	if (err)
 		return err;
 
+	if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
+		if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER))
+			return -EOPNOTSUPP;
+		params.inactivity_timeout = nla_get_u16(
+			info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
+	}
+
 	err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
 	if (!err)
 		wdev->beacon_interval = params.beacon_interval;
@@ -3290,6 +3299,8 @@
 			cur_params.dot11MeshGateAnnouncementProtocol);
 	NLA_PUT_U8(msg, NL80211_MESHCONF_FORWARDING,
 			cur_params.dot11MeshForwarding);
+	NLA_PUT_U32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
+			cur_params.rssi_threshold);
 	nla_nest_end(msg, pinfoattr);
 	genlmsg_end(msg, hdr);
 	return genlmsg_reply(msg, info);
@@ -3322,6 +3333,7 @@
 	[NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
 	[NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
 	[NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
+	[NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32},
 };
 
 static const struct nla_policy
@@ -3413,6 +3425,8 @@
 			nla_get_u8);
 	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding,
 			mask, NL80211_MESHCONF_FORWARDING, nla_get_u8);
+	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold,
+			mask, NL80211_MESHCONF_RSSI_THRESHOLD, nla_get_u32);
 	if (mask_out)
 		*mask_out = mask;
 
@@ -5103,6 +5117,13 @@
 
 	wiphy = &rdev->wiphy;
 
+	connect.bg_scan_period = -1;
+	if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
+		(wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
+		connect.bg_scan_period =
+			nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
+	}
+
 	if (info->attrs[NL80211_ATTR_MAC])
 		connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
 	connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
@@ -7673,7 +7694,8 @@
 
 int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
 		      struct net_device *netdev, u32 nlpid,
-		      int freq, const u8 *buf, size_t len, gfp_t gfp)
+		      int freq, int sig_dbm,
+		      const u8 *buf, size_t len, gfp_t gfp)
 {
 	struct sk_buff *msg;
 	void *hdr;
@@ -7691,6 +7713,8 @@
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
+	if (sig_dbm)
+		NLA_PUT_U32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm);
 	NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf);
 
 	genlmsg_end(msg, hdr);
@@ -7952,7 +7976,7 @@
 
 void cfg80211_report_obss_beacon(struct wiphy *wiphy,
 				 const u8 *frame, size_t len,
-				 int freq, gfp_t gfp)
+				 int freq, int sig_dbm, gfp_t gfp)
 {
 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 	struct sk_buff *msg;
@@ -7975,6 +7999,8 @@
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
 	if (freq)
 		NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
+	if (sig_dbm)
+		NLA_PUT_U32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm);
 	NLA_PUT(msg, NL80211_ATTR_FRAME, len, frame);
 
 	genlmsg_end(msg, hdr);
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 12bf4d1..4ffe50d 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -92,7 +92,8 @@
 				gfp_t gfp);
 
 int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
-		      struct net_device *netdev, u32 nlpid, int freq,
+		      struct net_device *netdev, u32 nlpid,
+		      int freq, int sig_dbm,
 		      const u8 *buf, size_t len, gfp_t gfp);
 void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
 				 struct net_device *netdev, u64 cookie,
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index afde7e5..70faadf 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -734,9 +734,8 @@
 struct cfg80211_bss*
 cfg80211_inform_bss(struct wiphy *wiphy,
 		    struct ieee80211_channel *channel,
-		    const u8 *bssid,
-		    u64 timestamp, u16 capability, u16 beacon_interval,
-		    const u8 *ie, size_t ielen,
+		    const u8 *bssid, u64 tsf, u16 capability,
+		    u16 beacon_interval, const u8 *ie, size_t ielen,
 		    s32 signal, gfp_t gfp)
 {
 	struct cfg80211_internal_bss *res;
@@ -758,7 +757,7 @@
 	memcpy(res->pub.bssid, bssid, ETH_ALEN);
 	res->pub.channel = channel;
 	res->pub.signal = signal;
-	res->pub.tsf = timestamp;
+	res->pub.tsf = tsf;
 	res->pub.beacon_interval = beacon_interval;
 	res->pub.capability = capability;
 	/*
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 9aa9db6..1b7a08df 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -904,6 +904,7 @@
 	/* do NOT round down here */
 	return (bitrate + 50000) / 100000;
 }
+EXPORT_SYMBOL(cfg80211_calculate_bitrate);
 
 int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 				 u32 beacon_int)
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 326750b..7c01c2f 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -30,6 +30,9 @@
 	wdev->wext.connect.ie = wdev->wext.ie;
 	wdev->wext.connect.ie_len = wdev->wext.ie_len;
 
+	/* Use default background scan period */
+	wdev->wext.connect.bg_scan_period = -1;
+
 	if (wdev->wext.keys) {
 		wdev->wext.keys->def = wdev->wext.default_key;
 		wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;