Subject: pull request: wireless-2.6 'upstream' 2008-01-29

From: "John W. Linville" <[email-masked]>
Date: Tue, 29 Jan 2008 16:27:03 -0500

Dave,

Here are some stragglers for 2.6.25.  Most of them are fixes for the
new stuff anyway -- I don't think there is anything convroversial.

Please let me know if there are problems!

Thanks,

John

---

Individual patches are available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/upstream

---

The following changes since commit 85040bcb4643cba578839e953f25e2d1965d83d0:
  YOSHIFUJI Hideaki (1):
        [IPV6] ADDRLABEL: Fix double free on label deletion.

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

Adrian Bassett (1):
      rtl8180_dev.c: add support for 1799:700f

Bruno Randolf (1):
      ath5k: debug level improvements

Cyrill Gorcunov (1):
      wireless: iwlwifi3945/4965 - fix incorrect counting of memory

Eric Sandeen (1):
      iwlwifi: correct math in elapsed_jiffies

Gregory Greenman (1):
      iwlwifi: Fix uCode error on association

Holger Schurig (1):
      libertas: fix interrupt while removing driver

Ihar Hrachyshka (1):
      libertas: fix memory alignment problems on the blackfin

Iñaky Pérez-González (1):
      rfkill: add the WiMAX radio type

Johannes Berg (1):
      mac80211: fix alignment warning

John W. Linville (1):
      rt61pci: fix-up merge damage

Joonwoo Park (1):
      iwlwifi: do not schedule tasklet when rcv unused irq

Maarten Lankhorst (1):
      iwlwifi: Fix an invalid bitmask test in iwl3945 and iwl4965

Marcin Juszkiewicz (1):
      Add another Prism2 card to hostap

Michael Buesch (4):
      b43: Fix rfkill allocation leakage in error paths
      b43legacy: Fix rfkill allocation leakage in error paths
      b43: Fix suspend/resume
      b43: Drop packets that we are not able to encrypt

Michal Piotrowski (1):
      hostap_80211.h: remove duplicate prototype

Reinette Chatre (3):
      iwl4965: fix return code indicating one interface is supported
      iwlwifi: initialize geo/channel information during probe
      iwlwifi: cleanup usage of inline functions

Ron Rindjunsky (1):
      mac80211: fixing null qos data frames check for reordering buffer

Stefano Brivio (1):
      b43legacy: fix MAC control and microcode init

 drivers/net/wireless/ath5k/base.c           |   10 +-
 drivers/net/wireless/ath5k/debug.c          |  124 +++++++++++++++++++++----
 drivers/net/wireless/ath5k/debug.h          |   18 ++--
 drivers/net/wireless/b43/dma.c              |   30 +++++-
 drivers/net/wireless/b43/main.c             |   19 +++-
 drivers/net/wireless/b43/xmit.c             |   23 +++--
 drivers/net/wireless/b43/xmit.h             |   10 +-
 drivers/net/wireless/b43legacy/b43legacy.h  |   31 +++----
 drivers/net/wireless/b43legacy/main.c       |  133 ++++++++++++++++++---------
 drivers/net/wireless/b43legacy/phy.c        |   14 ++--
 drivers/net/wireless/b43legacy/pio.c        |    6 +-
 drivers/net/wireless/b43legacy/radio.c      |   16 ++--
 drivers/net/wireless/hostap/hostap_80211.h  |    5 -
 drivers/net/wireless/hostap/hostap_cs.c     |    3 +
 drivers/net/wireless/iwlwifi/iwl-3945-hw.h  |    2 +-
 drivers/net/wireless/iwlwifi/iwl-3945.c     |   14 ---
 drivers/net/wireless/iwlwifi/iwl-3945.h     |    2 -
 drivers/net/wireless/iwlwifi/iwl-4965-hw.h  |    2 +-
 drivers/net/wireless/iwlwifi/iwl-4965.c     |    7 --
 drivers/net/wireless/iwlwifi/iwl-4965.h     |    1 -
 drivers/net/wireless/iwlwifi/iwl-helpers.h  |    4 +-
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   86 +++++++++++++----
 drivers/net/wireless/iwlwifi/iwl4965-base.c |   84 ++++++++++++-----
 drivers/net/wireless/libertas/assoc.c       |    6 +-
 drivers/net/wireless/libertas/dev.h         |    2 +-
 drivers/net/wireless/libertas/if_cs.c       |    6 +-
 drivers/net/wireless/rt2x00/rt61pci.c       |    3 +-
 drivers/net/wireless/rtl8180_dev.c          |    1 +
 include/linux/input.h                       |    2 +
 include/linux/rfkill.h                      |    2 +
 net/mac80211/rx.c                           |   48 +++++++---
 net/rfkill/rfkill-input.c                   |    9 ++
 net/rfkill/rfkill.c                         |    3 +
 33 files changed, 490 insertions(+), 236 deletions(-)

diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 72bcf32..d6599d2 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -1980,7 +1980,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 	struct ath5k_buf *bf = sc->bbuf;
 	struct ath5k_hw *ah = sc->ah;
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "in beacon_send\n");
+	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
 
 	if (unlikely(bf->skb == NULL || sc->opmode == IEEE80211_IF_TYPE_STA ||
 			sc->opmode == IEEE80211_IF_TYPE_MNTR)) {
@@ -1996,10 +1996,10 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 	 */
 	if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) {
 		sc->bmisscount++;
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
+		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
 			"missed %u consecutive beacons\n", sc->bmisscount);
 		if (sc->bmisscount > 3) {		/* NB: 3 is a guess */
-			ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
+			ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
 				"stuck beacon time (%u missed)\n",
 				sc->bmisscount);
 			tasklet_schedule(&sc->restq);
@@ -2007,7 +2007,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 		return;
 	}
 	if (unlikely(sc->bmisscount != 0)) {
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
+		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
 			"resume beacon xmit after %u misses\n",
 			sc->bmisscount);
 		sc->bmisscount = 0;
@@ -2027,7 +2027,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 
 	ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr);
 	ath5k_hw_tx_start(ah, sc->bhalq);
-	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "TXDP[%u] = %llx (%p)\n",
+	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
 		sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
 
 	sc->bsent++;
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
index 4ba649e..bb581ef 100644
--- a/drivers/net/wireless/ath5k/debug.c
+++ b/drivers/net/wireless/ath5k/debug.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 Bruno Randolf <[email-masked]>
+ * Copyright (c) 2007-2008 Bruno Randolf <[email-masked]>
  *
  *  This file is free software: you may copy, redistribute and/or modify it
  *  under the terms of the GNU General Public License as published by the
@@ -200,7 +200,7 @@ static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
 {
 	struct ath5k_softc *sc = file->private_data;
 	char buf[100];
-	snprintf(buf, 100, "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah));
+	snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah));
 	return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
 }
 
@@ -209,7 +209,12 @@ static ssize_t write_file_tsf(struct file *file,
 				 size_t count, loff_t *ppos)
 {
 	struct ath5k_softc *sc = file->private_data;
-	if (strncmp(userbuf, "reset", 5) == 0) {
+	char buf[20];
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
+
+	if (strncmp(buf, "reset", 5) == 0) {
 		ath5k_hw_reset_tsf(sc->ah);
 		printk(KERN_INFO "debugfs reset TSF\n");
 	}
@@ -231,8 +236,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
 {
 	struct ath5k_softc *sc = file->private_data;
 	struct ath5k_hw *ah = sc->ah;
-	char buf[1000];
-	int len = 0;
+	char buf[500];
+	unsigned int len = 0;
 	unsigned int v;
 	u64 tsf;
 
@@ -277,11 +282,15 @@ static ssize_t write_file_beacon(struct file *file,
 {
 	struct ath5k_softc *sc = file->private_data;
 	struct ath5k_hw *ah = sc->ah;
+	char buf[20];
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
 
-	if (strncmp(userbuf, "disable", 7) == 0) {
+	if (strncmp(buf, "disable", 7) == 0) {
 		AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
 		printk(KERN_INFO "debugfs disable beacons\n");
-	} else if (strncmp(userbuf, "enable", 6) == 0) {
+	} else if (strncmp(buf, "enable", 6) == 0) {
 		AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
 		printk(KERN_INFO "debugfs enable beacons\n");
 	}
@@ -314,6 +323,82 @@ static const struct file_operations fops_reset = {
 };

+/* debugfs: debug level */
+
+static struct {
+	enum ath5k_debug_level level;
+	const char *name;
+	const char *desc;
+} dbg_info[] = {
+	{ ATH5K_DEBUG_RESET,	"reset",	"reset and initialization" },
+	{ ATH5K_DEBUG_INTR,	"intr",		"interrupt handling" },
+	{ ATH5K_DEBUG_MODE,	"mode",		"mode init/setup" },
+	{ ATH5K_DEBUG_XMIT,	"xmit",		"basic xmit operation" },
+	{ ATH5K_DEBUG_BEACON,	"beacon",	"beacon handling" },
+	{ ATH5K_DEBUG_CALIBRATE, "calib",	"periodic calibration" },
+	{ ATH5K_DEBUG_TXPOWER,	"txpower",	"transmit power setting" },
+	{ ATH5K_DEBUG_LED,	"led",		"LED mamagement" },
+	{ ATH5K_DEBUG_DUMP_RX,	"dumprx",	"print received skb content" },
+	{ ATH5K_DEBUG_DUMP_TX,	"dumptx",	"print transmit skb content" },
+	{ ATH5K_DEBUG_DUMPMODES, "dumpmodes",	"dump modes" },
+	{ ATH5K_DEBUG_TRACE,	"trace",	"trace function calls" },
+	{ ATH5K_DEBUG_ANY,	"all",		"show all debug levels" },
+};
+
+static ssize_t read_file_debug(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	char buf[700];
+	unsigned int len = 0;
+	unsigned int i;
+
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);
+
+	for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
+		len += snprintf(buf+len, sizeof(buf)-len,
+			"%10s %c 0x%08x - %s\n", dbg_info[i].name,
+			sc->debug.level & dbg_info[i].level ? '+' : ' ',
+			dbg_info[i].level, dbg_info[i].desc);
+	}
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"%10s %c 0x%08x - %s\n", dbg_info[i].name,
+		sc->debug.level == dbg_info[i].level ? '+' : ' ',
+		dbg_info[i].level, dbg_info[i].desc);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_debug(struct file *file,
+				 const char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	unsigned int i;
+	char buf[20];
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
+
+	for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
+		if (strncmp(buf, dbg_info[i].name,
+					strlen(dbg_info[i].name)) == 0) {
+			sc->debug.level ^= dbg_info[i].level; /* toggle bit */
+			break;
+		}
+	}
+	return count;
+}
+
+static const struct file_operations fops_debug = {
+	.read = read_file_debug,
+	.write = write_file_debug,
+	.open = ath5k_debugfs_open,
+	.owner = THIS_MODULE,
+};
+
+
 /* init */
 
 void
@@ -326,26 +411,24 @@ void
 ath5k_debug_init_device(struct ath5k_softc *sc)
 {
 	sc->debug.level = ath5k_debug;
+
 	sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
-			ath5k_global_debugfs);
-	sc->debug.debugfs_debug = debugfs_create_u32("debug",
-			0666, sc->debug.debugfs_phydir, &sc->debug.level);
+				ath5k_global_debugfs);
+
+	sc->debug.debugfs_debug = debugfs_create_file("debug", 0666,
+				sc->debug.debugfs_phydir, sc, &fops_debug);
 
 	sc->debug.debugfs_registers = debugfs_create_file("registers", 0444,
-				sc->debug.debugfs_phydir,
-				sc, &fops_registers);
+				sc->debug.debugfs_phydir, sc, &fops_registers);
 
 	sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666,
-				sc->debug.debugfs_phydir,
-				sc, &fops_tsf);
+				sc->debug.debugfs_phydir, sc, &fops_tsf);
 
 	sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666,
-				sc->debug.debugfs_phydir,
-				sc, &fops_beacon);
+				sc->debug.debugfs_phydir, sc, &fops_beacon);
 
 	sc->debug.debugfs_reset = debugfs_create_file("reset", 0222,
-				sc->debug.debugfs_phydir,
-				sc, &fops_reset);
+				sc->debug.debugfs_phydir, sc, &fops_reset);
 }
 
 void
@@ -415,8 +498,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
 	struct ath5k_buf *bf;
 	int status;
 
-	if (likely(!(sc->debug.level &
-	    (ATH5K_DEBUG_RESET | ATH5K_DEBUG_FATAL))))
+	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
 		return;
 
 	printk(KERN_DEBUG "rx queue %x, link %p\n",
@@ -426,7 +508,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
 	list_for_each_entry(bf, &sc->rxbuf, list) {
 		ds = bf->desc;
 		status = ah->ah_proc_rx_desc(ah, ds);
-		if (!status || (sc->debug.level & ATH5K_DEBUG_FATAL))
+		if (!status)
 			ath5k_debug_printrxbuf(bf, status == 0);
 	}
 	spin_unlock_bh(&sc->rxbuflock);
diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h
index 2b491cb..c4fd8c4 100644
--- a/drivers/net/wireless/ath5k/debug.h
+++ b/drivers/net/wireless/ath5k/debug.h
@@ -91,7 +91,6 @@ struct ath5k_dbg_info {
  * @ATH5K_DEBUG_MODE: mode init/setup
  * @ATH5K_DEBUG_XMIT: basic xmit operation
  * @ATH5K_DEBUG_BEACON: beacon handling
- * @ATH5K_DEBUG_BEACON_PROC: beacon ISR proc
  * @ATH5K_DEBUG_CALIBRATE: periodic calibration
  * @ATH5K_DEBUG_TXPOWER: transmit power setting
  * @ATH5K_DEBUG_LED: led management
@@ -99,7 +98,6 @@ struct ath5k_dbg_info {
  * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
  * @ATH5K_DEBUG_DUMPMODES: dump modes
  * @ATH5K_DEBUG_TRACE: trace function calls
- * @ATH5K_DEBUG_FATAL: fatal errors
  * @ATH5K_DEBUG_ANY: show at any debug level
  *
  * The debug level is used to control the amount and type of debugging output
@@ -115,15 +113,13 @@ enum ath5k_debug_level {
 	ATH5K_DEBUG_MODE	= 0x00000004,
 	ATH5K_DEBUG_XMIT	= 0x00000008,
 	ATH5K_DEBUG_BEACON	= 0x00000010,
-	ATH5K_DEBUG_BEACON_PROC	= 0x00000020,
-	ATH5K_DEBUG_CALIBRATE	= 0x00000100,
-	ATH5K_DEBUG_TXPOWER	= 0x00000200,
-	ATH5K_DEBUG_LED		= 0x00000400,
-	ATH5K_DEBUG_DUMP_RX	= 0x00001000,
-	ATH5K_DEBUG_DUMP_TX	= 0x00002000,
-	ATH5K_DEBUG_DUMPMODES	= 0x00004000,
-	ATH5K_DEBUG_TRACE	= 0x00010000,
-	ATH5K_DEBUG_FATAL	= 0x80000000,
+	ATH5K_DEBUG_CALIBRATE	= 0x00000020,
+	ATH5K_DEBUG_TXPOWER	= 0x00000040,
+	ATH5K_DEBUG_LED		= 0x00000080,
+	ATH5K_DEBUG_DUMP_RX	= 0x00000100,
+	ATH5K_DEBUG_DUMP_TX	= 0x00000200,
+	ATH5K_DEBUG_DUMPMODES	= 0x00000400,
+	ATH5K_DEBUG_TRACE	= 0x00001000,
 	ATH5K_DEBUG_ANY		= 0xffffffff
 };
 
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 3e73d2a..8a708b7 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1114,7 +1114,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 {
 	const struct b43_dma_ops *ops = ring->ops;
 	u8 *header;
-	int slot;
+	int slot, old_top_slot, old_used_slots;
 	int err;
 	struct b43_dmadesc_generic *desc;
 	struct b43_dmadesc_meta *meta;
@@ -1126,6 +1126,9 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 #define SLOTS_PER_PACKET  2
 	B43_WARN_ON(skb_shinfo(skb)->nr_frags);
 
+	old_top_slot = ring->current_slot;
+	old_used_slots = ring->used_slots;
+
 	/* Get a slot for the header. */
 	slot = request_slot(ring);
 	desc = ops->idx2desc(ring, slot, &meta_hdr);
@@ -1133,13 +1136,21 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 
 	header = &(ring->txhdr_cache[slot * hdrsize]);
 	cookie = generate_cookie(ring, slot);
-	b43_generate_txhdr(ring->dev, header,
-			   skb->data, skb->len, ctl, cookie);
+	err = b43_generate_txhdr(ring->dev, header,
+				 skb->data, skb->len, ctl, cookie);
+	if (unlikely(err)) {
+		ring->current_slot = old_top_slot;
+		ring->used_slots = old_used_slots;
+		return err;
+	}
 
 	meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
 					   hdrsize, 1);
-	if (dma_mapping_error(meta_hdr->dmaaddr))
+	if (dma_mapping_error(meta_hdr->dmaaddr)) {
+		ring->current_slot = old_top_slot;
+		ring->used_slots = old_used_slots;
 		return -EIO;
+	}
 	ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr,
 			     hdrsize, 1, 0, 0);
 
@@ -1157,6 +1168,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 	if (dma_mapping_error(meta->dmaaddr)) {
 		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
 		if (!bounce_skb) {
+			ring->current_slot = old_top_slot;
+			ring->used_slots = old_used_slots;
 			err = -ENOMEM;
 			goto out_unmap_hdr;
 		}
@@ -1167,6 +1180,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 		meta->skb = skb;
 		meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 		if (dma_mapping_error(meta->dmaaddr)) {
+			ring->current_slot = old_top_slot;
+			ring->used_slots = old_used_slots;
 			err = -EIO;
 			goto out_free_bounce;
 		}
@@ -1252,6 +1267,13 @@ int b43_dma_tx(struct b43_wldev *dev,
 	B43_WARN_ON(ring->stopped);
 
 	err = dma_tx_fragment(ring, skb, ctl);
+	if (unlikely(err == -ENOKEY)) {
+		/* Drop this packet, as we don't have the encryption key
+		 * anymore and must not transmit it unencrypted. */
+		dev_kfree_skb_any(skb);
+		err = 0;
+		goto out_unlock;
+	}
 	if (unlikely(err)) {
 		b43err(dev->wl, "DMA tx mapping failure\n");
 		goto out_unlock;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 88d2c15..64c154d 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3532,8 +3532,6 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 	b43_bluetooth_coext_enable(dev);
 
 	ssb_bus_powerup(bus, 1);	/* Enable dynamic PCTL */
-	memset(wl->bssid, 0, ETH_ALEN);
-	memset(wl->mac_addr, 0, ETH_ALEN);
 	b43_upload_card_macaddress(dev);
 	b43_security_init(dev);
 	b43_rng_init(wl);
@@ -3630,6 +3628,15 @@ static int b43_op_start(struct ieee80211_hw *hw)
 	struct b43_wldev *dev = wl->current_dev;
 	int did_init = 0;
 	int err = 0;
+	bool do_rfkill_exit = 0;
+
+	/* Kill all old instance specific information to make sure
+	 * the card won't use it in the short timeframe between start
+	 * and mac80211 reconfiguring it. */
+	memset(wl->bssid, 0, ETH_ALEN);
+	memset(wl->mac_addr, 0, ETH_ALEN);
+	wl->filter_flags = 0;
+	wl->radiotap_enabled = 0;
 
 	/* First register RFkill.
 	 * LEDs that are registered later depend on it. */
@@ -3639,8 +3646,10 @@ static int b43_op_start(struct ieee80211_hw *hw)
 
 	if (b43_status(dev) < B43_STAT_INITIALIZED) {
 		err = b43_wireless_core_init(dev);
-		if (err)
+		if (err) {
+			do_rfkill_exit = 1;
 			goto out_mutex_unlock;
+		}
 		did_init = 1;
 	}
 
@@ -3649,6 +3658,7 @@ static int b43_op_start(struct ieee80211_hw *hw)
 		if (err) {
 			if (did_init)
 				b43_wireless_core_exit(dev);
+			do_rfkill_exit = 1;
 			goto out_mutex_unlock;
 		}
 	}
@@ -3656,6 +3666,9 @@ static int b43_op_start(struct ieee80211_hw *hw)
  out_mutex_unlock:
 	mutex_unlock(&wl->mutex);
 
+	if (do_rfkill_exit)
+		b43_rfkill_exit(dev);
+
 	return err;
 }
 
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 3fc53e8..7caa26e 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -178,12 +178,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate)
 }
 
 /* Generate a TX data header. */
-void b43_generate_txhdr(struct b43_wldev *dev,
-			u8 *_txhdr,
-			const unsigned char *fragment_data,
-			unsigned int fragment_len,
-			const struct ieee80211_tx_control *txctl,
-			u16 cookie)
+int b43_generate_txhdr(struct b43_wldev *dev,
+		       u8 *_txhdr,
+		       const unsigned char *fragment_data,
+		       unsigned int fragment_len,
+		       const struct ieee80211_tx_control *txctl,
+		       u16 cookie)
 {
 	struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
 	const struct b43_phy *phy = &dev->phy;
@@ -237,7 +237,15 @@ void b43_generate_txhdr(struct b43_wldev *dev,
 
 		B43_WARN_ON(key_idx >= dev->max_nr_keys);
 		key = &(dev->key[key_idx]);
-		B43_WARN_ON(!key->keyconf);
+
+		if (unlikely(!key->keyconf)) {
+			/* This key is invalid. This might only happen
+			 * in a short timeframe after machine resume before
+			 * we were able to reconfigure keys.
+			 * Drop this packet completely. Do not transmit it
+			 * unencrypted to avoid leaking information. */
+			return -ENOKEY;
+		}
 
 		/* Hardware appends ICV. */
 		plcp_fragment_len += txctl->icv_len;
@@ -408,6 +416,7 @@ void b43_generate_txhdr(struct b43_wldev *dev,
 	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
 	txhdr->extra_ft = extra_ft;
 
+	return 0;
 }
 
 static s8 b43_rssi_postprocess(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index ca2a2ab..4176503 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -174,11 +174,11 @@ size_t b43_txhdr_size(struct b43_wldev *dev)
 }

-void b43_generate_txhdr(struct b43_wldev *dev,
-			u8 * txhdr,
-			const unsigned char *fragment_data,
-			unsigned int fragment_len,
-			const struct ieee80211_tx_control *txctl, u16 cookie);
+int b43_generate_txhdr(struct b43_wldev *dev,
+		       u8 * txhdr,
+		       const unsigned char *fragment_data,
+		       unsigned int fragment_len,
+		       const struct ieee80211_tx_control *txctl, u16 cookie);
 
 /* Transmit Status */
 struct b43_txstatus {
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index 93419ad..c80edd2 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -23,7 +23,7 @@
 #include "phy.h"

-#define B43legacy_IRQWAIT_MAX_RETRIES	100
+#define B43legacy_IRQWAIT_MAX_RETRIES	20
 
 #define B43legacy_RX_MAX_SSI		60 /* best guess at max ssi */
 
@@ -40,9 +40,8 @@
 #define B43legacy_MMIO_DMA4_IRQ_MASK	0x44
 #define B43legacy_MMIO_DMA5_REASON	0x48
 #define B43legacy_MMIO_DMA5_IRQ_MASK	0x4C
-#define B43legacy_MMIO_MACCTL		0x120
-#define B43legacy_MMIO_STATUS_BITFIELD	0x120
-#define B43legacy_MMIO_STATUS2_BITFIELD	0x124
+#define B43legacy_MMIO_MACCTL		0x120	/* MAC control */
+#define B43legacy_MMIO_MACCMD		0x124	/* MAC command */
 #define B43legacy_MMIO_GEN_IRQ_REASON	0x128
 #define B43legacy_MMIO_GEN_IRQ_MASK	0x12C
 #define B43legacy_MMIO_RAM_CONTROL	0x130
@@ -177,31 +176,25 @@
 #define B43legacy_RADIOCTL_ID		0x01
 
 /* MAC Control bitfield */
+#define B43legacy_MACCTL_ENABLED	0x00000001 /* MAC Enabled */
+#define B43legacy_MACCTL_PSM_RUN	0x00000002 /* Run Microcode */
+#define B43legacy_MACCTL_PSM_JMP0	0x00000004 /* Microcode jump to 0 */
+#define B43legacy_MACCTL_SHM_ENABLED	0x00000100 /* SHM Enabled */
 #define B43legacy_MACCTL_IHR_ENABLED	0x00000400 /* IHR Region Enabled */
+#define B43legacy_MACCTL_BE		0x00010000 /* Big Endian mode */
 #define B43legacy_MACCTL_INFRA		0x00020000 /* Infrastructure mode */
 #define B43legacy_MACCTL_AP		0x00040000 /* AccessPoint mode */
+#define B43legacy_MACCTL_RADIOLOCK	0x00080000 /* Radio lock */
 #define B43legacy_MACCTL_BEACPROMISC	0x00100000 /* Beacon Promiscuous */
 #define B43legacy_MACCTL_KEEP_BADPLCP	0x00200000 /* Keep bad PLCP frames */
 #define B43legacy_MACCTL_KEEP_CTL	0x00400000 /* Keep control frames */
 #define B43legacy_MACCTL_KEEP_BAD	0x00800000 /* Keep bad frames (FCS) */
 #define B43legacy_MACCTL_PROMISC	0x01000000 /* Promiscuous mode */
+#define B43legacy_MACCTL_HWPS		0x02000000 /* Hardware Power Saving */
+#define B43legacy_MACCTL_AWAKE		0x04000000 /* Device is awake */
+#define B43legacy_MACCTL_TBTTHOLD	0x10000000 /* TBTT Hold */
 #define B43legacy_MACCTL_GMODE		0x80000000 /* G Mode */
 
-/* StatusBitField */
-#define B43legacy_SBF_MAC_ENABLED	0x00000001
-#define B43legacy_SBF_CORE_READY	0x00000004
-#define B43legacy_SBF_400		0x00000400 /*FIXME: fix name*/
-#define B43legacy_SBF_XFER_REG_BYTESWAP	0x00010000
-#define B43legacy_SBF_MODE_NOTADHOC	0x00020000
-#define B43legacy_SBF_MODE_AP		0x00040000
-#define B43legacy_SBF_RADIOREG_LOCK	0x00080000
-#define B43legacy_SBF_MODE_MONITOR	0x00400000
-#define B43legacy_SBF_MODE_PROMISC	0x01000000
-#define B43legacy_SBF_PS1		0x02000000
-#define B43legacy_SBF_PS2		0x04000000
-#define B43legacy_SBF_NO_SSID_BCAST	0x08000000
-#define B43legacy_SBF_TIME_UPDATE	0x10000000
-
 /* 802.11 core specific TM State Low flags */
 #define B43legacy_TMSLOW_GMODE		0x20000000 /* G Mode Enable */
 #define B43legacy_TMSLOW_PLLREFSEL	0x00200000 /* PLL Freq Ref Select */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 4ed4243..aa20d5d 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -225,8 +225,8 @@ static void b43legacy_ram_write(struct b43legacy_wldev *dev, u16 offset,
 
 	B43legacy_WARN_ON(offset % 4 != 0);
 
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	if (status & B43legacy_SBF_XFER_REG_BYTESWAP)
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	if (status & B43legacy_MACCTL_BE)
 		val = swab32(val);
 
 	b43legacy_write32(dev, B43legacy_MMIO_RAM_CONTROL, offset);
@@ -434,9 +434,9 @@ static void b43legacy_time_lock(struct b43legacy_wldev *dev)
 {
 	u32 status;
 
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	status |= B43legacy_SBF_TIME_UPDATE;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	status |= B43legacy_MACCTL_TBTTHOLD;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 	mmiowb();
 }
 
@@ -444,9 +444,9 @@ static void b43legacy_time_unlock(struct b43legacy_wldev *dev)
 {
 	u32 status;
 
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	status &= ~B43legacy_SBF_TIME_UPDATE;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	status &= ~B43legacy_MACCTL_TBTTHOLD;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 }
 
 static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf)
@@ -647,7 +647,7 @@ void b43legacy_dummy_transmission(struct b43legacy_wldev *dev)
 		b43legacy_ram_write(dev, i * 4, buffer[i]);
 
 	/* dummy read follows */
-	b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+	b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
 
 	b43legacy_write16(dev, 0x0568, 0x0000);
 	b43legacy_write16(dev, 0x07C0, 0x0000);
@@ -794,9 +794,9 @@ static void b43legacy_jssi_write(struct b43legacy_wldev *dev, u32 jssi)
 static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev)
 {
 	b43legacy_jssi_write(dev, 0x7F7F7F7F);
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+	b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 			  b43legacy_read32(dev,
-			  B43legacy_MMIO_STATUS2_BITFIELD)
+			  B43legacy_MMIO_MACCMD)
 			  | (1 << 4));
 	B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
 			    dev->phy.channel);
@@ -895,8 +895,8 @@ static void handle_irq_atim_end(struct b43legacy_wldev *dev)
 {
 	if (!dev->reg124_set_0x4) /*FIXME rename this variable*/
 		return;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
-			  b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD)
+	b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+			  b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
 			  | 0x4);
 }
 
@@ -1106,9 +1106,9 @@ static void b43legacy_update_templates(struct b43legacy_wldev *dev)
 	b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
 					    B43legacy_CCK_RATE_11MB);
 
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
 	status |= 0x03;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, status);
+	b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status);
 }
 
 static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,
@@ -1166,7 +1166,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
 		return;
 
 	dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
 
 	if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
 		/* ACK beacon IRQ. */
@@ -1182,14 +1182,14 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
 		b43legacy_write_beacon_template(dev, 0x68, 0x18,
 						B43legacy_CCK_RATE_1MB);
 		status |= 0x1;
-		b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+		b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 				  status);
 	}
 	if (!(status & 0x2)) {
 		b43legacy_write_beacon_template(dev, 0x468, 0x1A,
 						B43legacy_CCK_RATE_1MB);
 		status |= 0x2;
-		b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+		b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
 				  status);
 	}
 }
@@ -1548,9 +1548,20 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 	u16 fwpatch;
 	u16 fwdate;
 	u16 fwtime;
-	u32 tmp;
+	u32 tmp, macctl;
 	int err = 0;
 
+	/* Jump the microcode PSM to offset 0 */
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	B43legacy_WARN_ON(macctl & B43legacy_MACCTL_PSM_RUN);
+	macctl |= B43legacy_MACCTL_PSM_JMP0;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+	/* Zero out all microcode PSM registers and shared memory. */
+	for (i = 0; i < 64; i++)
+		b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, i, 0);
+	for (i = 0; i < 4096; i += 2)
+		b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, i, 0);
+
 	/* Upload Microcode. */
 	data = (__be32 *) (dev->fw.ucode->data + hdr_len);
 	len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32);
@@ -1581,7 +1592,12 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 
 	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
 			  B43legacy_IRQ_ALL);
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0x00020402);
+
+	/* Start the microcode PSM */
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	macctl &= ~B43legacy_MACCTL_PSM_JMP0;
+	macctl |= B43legacy_MACCTL_PSM_RUN;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
 
 	/* Wait for the microcode to load and respond */
 	i = 0;
@@ -1594,9 +1610,13 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 			b43legacyerr(dev->wl, "Microcode not responding\n");
 			b43legacy_print_fw_helptext(dev->wl);
 			err = -ENODEV;
-			goto out;
+			goto error;
+		}
+		msleep_interruptible(50);
+		if (signal_pending(current)) {
+			err = -EINTR;
+			goto error;
 		}
-		udelay(10);
 	}
 	/* dummy read follows */
 	b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
@@ -1617,9 +1637,8 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 			     " is supported. You must change your firmware"
 			     " files.\n");
 		b43legacy_print_fw_helptext(dev->wl);
-		b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0);
 		err = -EOPNOTSUPP;
-		goto out;
+		goto error;
 	}
 	b43legacydbg(dev->wl, "Loading firmware version 0x%X, patch level %u "
 	       "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch,
@@ -1629,7 +1648,14 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 	dev->fw.rev = fwrev;
 	dev->fw.patch = fwpatch;
 
-out:
+	return 0;
+
+error:
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	macctl &= ~B43legacy_MACCTL_PSM_RUN;
+	macctl |= B43legacy_MACCTL_PSM_JMP0;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
 	return err;
 }
 
@@ -1736,9 +1762,9 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
 	u32 mask;
 	u32 set;
 
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
 			  b43legacy_read32(dev,
-			  B43legacy_MMIO_STATUS_BITFIELD)
+			  B43legacy_MMIO_MACCTL)
 			  & 0xFFFF3FFF);
 
 	b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
@@ -1798,14 +1824,14 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)
 	B43legacy_WARN_ON(dev->mac_suspended < 0);
 	B43legacy_WARN_ON(irqs_disabled());
 	if (dev->mac_suspended == 0) {
-		b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+		b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
 				  b43legacy_read32(dev,
-				  B43legacy_MMIO_STATUS_BITFIELD)
-				  | B43legacy_SBF_MAC_ENABLED);
+				  B43legacy_MMIO_MACCTL)
+				  | B43legacy_MACCTL_ENABLED);
 		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
 				  B43legacy_IRQ_MAC_SUSPENDED);
 		/* the next two are dummy reads */
-		b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+		b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
 		b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
 		b43legacy_power_saving_ctl_bits(dev, -1, -1);
 
@@ -1836,10 +1862,10 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev)
 		dev->irq_savedstate = tmp;
 
 		b43legacy_power_saving_ctl_bits(dev, -1, 1);
-		b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+		b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
 				  b43legacy_read32(dev,
-				  B43legacy_MMIO_STATUS_BITFIELD)
-				  & ~B43legacy_SBF_MAC_ENABLED);
+				  B43legacy_MMIO_MACCTL)
+				  & ~B43legacy_MACCTL_ENABLED);
 		b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
 		for (i = 40; i; i--) {
 			tmp = b43legacy_read32(dev,
@@ -2007,12 +2033,15 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
 	struct b43legacy_phy *phy = &dev->phy;
 	int err;
 	int tmp;
-	u32 value32;
+	u32 value32, macctl;
 	u16 value16;
 
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
-			  B43legacy_SBF_CORE_READY
-			  | B43legacy_SBF_400);
+	/* Initialize the MAC control */
+	macctl = B43legacy_MACCTL_IHR_ENABLED | B43legacy_MACCTL_SHM_ENABLED;
+	if (dev->phy.gmode)
+		macctl |= B43legacy_MACCTL_GMODE;
+	macctl |= B43legacy_MACCTL_INFRA;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
 
 	err = b43legacy_request_firmware(dev);
 	if (err)
@@ -2052,12 +2081,12 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
 	if (dev->dev->id.revision < 5)
 		b43legacy_write32(dev, 0x010C, 0x01000000);
 
-	value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	value32 &= ~B43legacy_SBF_MODE_NOTADHOC;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
-	value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	value32 |= B43legacy_SBF_MODE_NOTADHOC;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
+	value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	value32 &= ~B43legacy_MACCTL_INFRA;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32);
+	value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	value32 |= B43legacy_MACCTL_INFRA;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32);
 
 	if (b43legacy_using_pio(dev)) {
 		b43legacy_write32(dev, 0x0210, 0x00000100);
@@ -2951,12 +2980,19 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
 {
 	struct b43legacy_wl *wl = dev->wl;
 	struct b43legacy_phy *phy = &dev->phy;
+	u32 macctl;
 
 	B43legacy_WARN_ON(b43legacy_status(dev) > B43legacy_STAT_INITIALIZED);
 	if (b43legacy_status(dev) != B43legacy_STAT_INITIALIZED)
 		return;
 	b43legacy_set_status(dev, B43legacy_STAT_UNINIT);
 
+	/* Stop the microcode PSM. */
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	macctl &= ~B43legacy_MACCTL_PSM_RUN;
+	macctl |= B43legacy_MACCTL_PSM_JMP0;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
 	mutex_unlock(&wl->mutex);
 	/* Must unlock as it would otherwise deadlock. No races here.
 	 * Cancel possibly pending workqueues. */
@@ -3221,6 +3257,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
 	struct b43legacy_wldev *dev = wl->current_dev;
 	int did_init = 0;
 	int err = 0;
+	bool do_rfkill_exit = 0;
 
 	/* First register RFkill.
 	 * LEDs that are registered later depend on it. */
@@ -3230,8 +3267,10 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
 
 	if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
 		err = b43legacy_wireless_core_init(dev);
-		if (err)
+		if (err) {
+			do_rfkill_exit = 1;
 			goto out_mutex_unlock;
+		}
 		did_init = 1;
 	}
 
@@ -3240,6 +3279,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
 		if (err) {
 			if (did_init)
 				b43legacy_wireless_core_exit(dev);
+			do_rfkill_exit = 1;
 			goto out_mutex_unlock;
 		}
 	}
@@ -3247,6 +3287,9 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
 out_mutex_unlock:
 	mutex_unlock(&wl->mutex);
 
+	if (do_rfkill_exit)
+		b43legacy_rfkill_exit(dev);
+
 	return err;
 }
 
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index c16febb..8e5c09b 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -140,7 +140,7 @@ void b43legacy_phy_calibrate(struct b43legacy_wldev *dev)
 {
 	struct b43legacy_phy *phy = &dev->phy;
 
-	b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); /* Dummy read. */
+	b43legacy_read32(dev, B43legacy_MMIO_MACCTL); /* Dummy read. */
 	if (phy->calibrated)
 		return;
 	if (phy->type == B43legacy_PHYTYPE_G && phy->rev == 1) {
@@ -2231,16 +2231,16 @@ bit26 = 1;
 		 *	or the latest PS-Poll packet sent was successful,
 		 *	set bit26  */
 	}
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
 	if (bit25)
-		status |= B43legacy_SBF_PS1;
+		status |= B43legacy_MACCTL_HWPS;
 	else
-		status &= ~B43legacy_SBF_PS1;
+		status &= ~B43legacy_MACCTL_HWPS;
 	if (bit26)
-		status |= B43legacy_SBF_PS2;
+		status |= B43legacy_MACCTL_AWAKE;
 	else
-		status &= ~B43legacy_SBF_PS2;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+		status &= ~B43legacy_MACCTL_AWAKE;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 	if (bit26 && dev->dev->id.revision >= 5) {
 		for (i = 0; i < 100; i++) {
 			if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index de843ac..e4f4c5c 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -334,9 +334,9 @@ struct b43legacy_pioqueue *b43legacy_setup_pioqueue(struct b43legacy_wldev *dev,
 	tasklet_init(&queue->txtask, tx_tasklet,
 		     (unsigned long)queue);
 
-	value = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	value &= ~B43legacy_SBF_XFER_REG_BYTESWAP;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value);
+	value = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	value &= ~B43legacy_MACCTL_BE;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value);
 
 	qsize = b43legacy_read16(dev, queue->mmio_base
 				 + B43legacy_PIO_TXQBUFSIZE);
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c
index 318a270..955832e 100644
--- a/drivers/net/wireless/b43legacy/radio.c
+++ b/drivers/net/wireless/b43legacy/radio.c
@@ -91,10 +91,10 @@ void b43legacy_radio_lock(struct b43legacy_wldev *dev)
 {
 	u32 status;
 
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	B43legacy_WARN_ON(status & B43legacy_SBF_RADIOREG_LOCK);
-	status |= B43legacy_SBF_RADIOREG_LOCK;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	B43legacy_WARN_ON(status & B43legacy_MACCTL_RADIOLOCK);
+	status |= B43legacy_MACCTL_RADIOLOCK;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 	mmiowb();
 	udelay(10);
 }
@@ -104,10 +104,10 @@ void b43legacy_radio_unlock(struct b43legacy_wldev *dev)
 	u32 status;
 
 	b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); /* dummy read */
-	status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-	B43legacy_WARN_ON(!(status & B43legacy_SBF_RADIOREG_LOCK));
-	status &= ~B43legacy_SBF_RADIOREG_LOCK;
-	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	B43legacy_WARN_ON(!(status & B43legacy_MACCTL_RADIOLOCK));
+	status &= ~B43legacy_MACCTL_RADIOLOCK;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 	mmiowb();
 }
 
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index d6b9362..3694b1e 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -71,11 +71,6 @@ struct hostap_80211_rx_status {
 	u16 rate; /* in 100 kbps */
 };
 
-
-void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
-		     struct hostap_80211_rx_status *rx_stats);
-
-
 /* prism2_rx_80211 'type' argument */
 enum {
 	PRISM2_RX_MONITOR, PRISM2_RX_MGMT, PRISM2_RX_NON_ASSOC,
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 0759380..437a9bc 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -891,6 +891,9 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
 	PCMCIA_DEVICE_PROD_ID123(
 		"The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P",
 		0xa5f472c2, 0x9c05598d, 0xc9049a39),
+	PCMCIA_DEVICE_PROD_ID123(
+		"Wireless LAN" , "11Mbps PC Card", "Version 01.02",
+		0x4b8870ff, 0x70e946d1, 0x4b74baa0),
 	PCMCIA_DEVICE_NULL
 };
 MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index 6e01873..571815d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -373,7 +373,7 @@ struct iwl3945_eeprom {
 #define CSR_INT_BIT_HW_ERR       (1 << 29) /* DMA hardware error FH_INT[31] */
 #define CSR_INT_BIT_DNLD         (1 << 28) /* uCode Download */
 #define CSR_INT_BIT_FH_TX        (1 << 27) /* Tx DMA FH_INT[1:0] */
-#define CSR_INT_BIT_MAC_CLK_ACTV (1 << 26) /* NIC controller's clock toggled on/off */
+#define CSR_INT_BIT_SCD          (1 << 26) /* TXQ pointer advanced */
 #define CSR_INT_BIT_SW_ERR       (1 << 25) /* uCode error */
 #define CSR_INT_BIT_RF_KILL      (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
 #define CSR_INT_BIT_CT_KILL      (1 << 6)  /* Critical temp (chip too hot) rfkill */
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 76c4ed1..4fdeb53 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2369,18 +2369,4 @@ struct pci_device_id iwl3945_hw_card_ids[] = {
 	{0}
 };
 
-/*
- * Clear the OWNER_MSK, to establish driver (instead of uCode running on
- * embedded controller) as EEPROM reader; each read is a series of pulses
- * to/from the EEPROM chip, not a single event, so even reads could conflict
- * if they weren't arbitrated by some ownership mechanism.  Here, the driver
- * simply claims ownership, which should be safe when this function is called
- * (i.e. before loading uCode!).
- */
-inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv)
-{
-	_iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
-	return 0;
-}
-
 MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 20b925f..1da14f9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -671,7 +671,6 @@ extern int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel);
 /*
  * Forward declare iwl-3945.c functions for iwl-base.c
  */
-extern int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv);
 extern __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv);
 extern int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv);
 extern void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv);
@@ -791,7 +790,6 @@ struct iwl3945_priv {
 	u16 active_rate_basic;
 
 	u8 call_post_assoc_from_beacon;
-	u8 assoc_station_added;
 	/* Rate scaling data */
 	s8 data_retry_limit;
 	u8 retry_rate;
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index ff71c09..ffe1e9d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -465,7 +465,7 @@ struct iwl4965_eeprom {
 #define CSR_INT_BIT_HW_ERR       (1 << 29) /* DMA hardware error FH_INT[31] */
 #define CSR_INT_BIT_DNLD         (1 << 28) /* uCode Download */
 #define CSR_INT_BIT_FH_TX        (1 << 27) /* Tx DMA FH_INT[1:0] */
-#define CSR_INT_BIT_MAC_CLK_ACTV (1 << 26) /* NIC controller's clock toggled on/off */
+#define CSR_INT_BIT_SCD          (1 << 26) /* TXQ pointer advanced */
 #define CSR_INT_BIT_SW_ERR       (1 << 25) /* uCode error */
 #define CSR_INT_BIT_RF_KILL      (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
 #define CSR_INT_BIT_CT_KILL      (1 << 6)  /* Critical temp (chip too hot) rfkill */
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 04db34b..569347f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -4961,11 +4961,4 @@ int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv)
 	return rc;
 }
 
-inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv)
-{
-	iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-}
-
-
 MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids);
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index 78bc148..9cb82be 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -750,7 +750,6 @@ struct iwl4965_priv;
  * Forward declare iwl-4965.c functions for iwl-base.c
  */
 extern int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv);
-extern void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv);
 
 extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
 					  struct iwl4965_tx_queue *txq,
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index cd2eb18..cb009f4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -246,10 +246,10 @@ static inline int iwl_check_bits(unsigned long field, unsigned long mask)
 static inline unsigned long elapsed_jiffies(unsigned long start,
 					    unsigned long end)
 {
-	if (end > start)
+	if (end >= start)
 		return end - start;
 
-	return end + (MAX_JIFFY_OFFSET - start);
+	return end + (MAX_JIFFY_OFFSET - start) + 1;
 }
 
 static inline u8 iwl_get_dma_hi_address(dma_addr_t addr)
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 748ac12..33239f1 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1557,6 +1557,20 @@ static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac)
 	memcpy(mac, priv->eeprom.mac_address, 6);
 }
 
+/*
+ * Clear the OWNER_MSK, to establish driver (instead of uCode running on
+ * embedded controller) as EEPROM reader; each read is a series of pulses
+ * to/from the EEPROM chip, not a single event, so even reads could conflict
+ * if they weren't arbitrated by some ownership mechanism.  Here, the driver
+ * simply claims ownership, which should be safe when this function is called
+ * (i.e. before loading uCode!).
+ */
+static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv)
+{
+	_iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
+	return 0;
+}
+
 /**
  * iwl3945_eeprom_init - read EEPROM contents
  *
@@ -2792,7 +2806,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
 #endif
 
 	/* drop all data frame if we are not associated */
-	if (!iwl3945_is_associated(priv) && !priv->assoc_id &&
+	if ((!iwl3945_is_associated(priv) || !priv->assoc_id) &&
 	    ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
 		IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
 		goto drop_unlock;
@@ -4745,8 +4759,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
 #ifdef CONFIG_IWL3945_DEBUG
 	if (iwl3945_debug_level & (IWL_DL_ISR)) {
 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
-		if (inta & CSR_INT_BIT_MAC_CLK_ACTV)
-			IWL_DEBUG_ISR("Microcode started or stopped.\n");
+		if (inta & CSR_INT_BIT_SCD)
+			IWL_DEBUG_ISR("Scheduler finished to transmit "
+				      "the frame/frames.\n");
 
 		/* Alive notification via Rx interrupt will do the real work */
 		if (inta & CSR_INT_BIT_ALIVE)
@@ -4754,7 +4769,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
 	}
 #endif
 	/* Safely ignore these bits for debug checks below */
-	inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE);
+	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
 
 	/* HW RF KILL switch toggled (4965 only) */
 	if (inta & CSR_INT_BIT_RF_KILL) {
@@ -4890,8 +4905,11 @@ static irqreturn_t iwl3945_isr(int irq, void *data)
 	IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
 		      inta, inta_mask, inta_fh);
 
+	inta &= ~CSR_INT_BIT_SCD;
+
 	/* iwl3945_irq_tasklet() will service interrupts and re-enable them */
-	tasklet_schedule(&priv->irq_tasklet);
+	if (likely(inta || inta_fh))
+		tasklet_schedule(&priv->irq_tasklet);
 unplugged:
 	spin_unlock(&priv->lock);
 
@@ -5146,6 +5164,15 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
 	return 0;
 }
 
+/*
+ * iwl3945_free_channel_map - undo allocations in iwl3945_init_channel_map
+ */
+static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
+{
+	kfree(priv->channel_info);
+	priv->channel_count = 0;
+}
+
 /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
  * sending probe req.  This should be set long enough to hear probe responses
  * from more than one AP.  */
@@ -5471,6 +5498,17 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv)
 	return 0;
 }
 
+/*
+ * iwl3945_free_geos - undo allocations in iwl3945_init_geos
+ */
+static void iwl3945_free_geos(struct iwl3945_priv *priv)
+{
+	kfree(priv->modes);
+	kfree(priv->ieee_channels);
+	kfree(priv->ieee_rates);
+	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+}
+
 /******************************************************************************
  *
  * uCode download functions
@@ -6130,15 +6168,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
 	/* Clear out the uCode error bit if it is set */
 	clear_bit(STATUS_FW_ERROR, &priv->status);
 
-	rc = iwl3945_init_channel_map(priv);
-	if (rc) {
-		IWL_ERROR("initializing regulatory failed: %d\n", rc);
-		return;
-	}
-
-	iwl3945_init_geos(priv);
-	iwl3945_reset_channel_flag(priv);
-
 	if (iwl3945_is_rfkill(priv))
 		return;
 
@@ -6599,7 +6628,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 	 * that based on the direct_mask added to each channel entry */
 	scan->tx_cmd.len = cpu_to_le16(
 		iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
-			IWL_MAX_SCAN_SIZE - sizeof(scan), 0));
+			IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
 	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
 	scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
 	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
@@ -7120,7 +7149,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
 {
 	int rc = 0;
 
-	if (priv->status & STATUS_EXIT_PENDING)
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	/* The following should be done only at AP bring up */
@@ -8614,11 +8643,24 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 	IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
 	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
+	err = iwl3945_init_channel_map(priv);
+	if (err) {
+		IWL_ERROR("initializing regulatory failed: %d\n", err);
+		goto out_remove_sysfs;
+	}
+
+	err = iwl3945_init_geos(priv);
+	if (err) {
+		IWL_ERROR("initializing geos failed: %d\n", err);
+		goto out_free_channel_map;
+	}
+	iwl3945_reset_channel_flag(priv);
+
 	iwl3945_rate_control_register(priv->hw);
 	err = ieee80211_register_hw(priv->hw);
 	if (err) {
 		IWL_ERROR("Failed to register network device (error %d)\n", err);
-		goto out_remove_sysfs;
+		goto out_free_geos;
 	}
 
 	priv->hw->conf.beacon_int = 100;
@@ -8628,6 +8670,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
 	return 0;
 
+ out_free_geos:
+	iwl3945_free_geos(priv);
+ out_free_channel_map:
+	iwl3945_free_channel_map(priv);
  out_remove_sysfs:
 	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
@@ -8702,10 +8748,8 @@ static void iwl3945_pci_remove(struct pci_dev *pdev)
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 
-	kfree(priv->channel_info);
-
-	kfree(priv->ieee_channels);
-	kfree(priv->ieee_rates);
+	iwl3945_free_channel_map(priv);
+	iwl3945_free_geos(priv);
 
 	if (priv->ibss_beacon)
 		dev_kfree_skb(priv->ibss_beacon);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index c86da5c..bf3a60c 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1639,6 +1639,12 @@ static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac)
 	memcpy(mac, priv->eeprom.mac_address, 6);
 }
 
+static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv)
+{
+	iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+}
+
 /**
  * iwl4965_eeprom_init - read EEPROM contents
  *
@@ -2927,8 +2933,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
 #endif
 
 	/* drop all data frame if we are not associated */
-	if (!iwl4965_is_associated(priv) && !priv->assoc_id &&
-	    ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
+	if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+	   (!iwl4965_is_associated(priv) ||
+	    !priv->assoc_id ||
+	    !priv->assoc_station_added)) {
 		IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n");
 		goto drop_unlock;
 	}
@@ -5131,8 +5139,9 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
 #ifdef CONFIG_IWL4965_DEBUG
 	if (iwl4965_debug_level & (IWL_DL_ISR)) {
 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
-		if (inta & CSR_INT_BIT_MAC_CLK_ACTV)
-			IWL_DEBUG_ISR("Microcode started or stopped.\n");
+		if (inta & CSR_INT_BIT_SCD)
+			IWL_DEBUG_ISR("Scheduler finished to transmit "
+				      "the frame/frames.\n");
 
 		/* Alive notification via Rx interrupt will do the real work */
 		if (inta & CSR_INT_BIT_ALIVE)
@@ -5140,7 +5149,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
 	}
 #endif
 	/* Safely ignore these bits for debug checks below */
-	inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE);
+	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
 
 	/* HW RF KILL switch toggled */
 	if (inta & CSR_INT_BIT_RF_KILL) {
@@ -5269,8 +5278,11 @@ static irqreturn_t iwl4965_isr(int irq, void *data)
 	IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
 		      inta, inta_mask, inta_fh);
 
+	inta &= ~CSR_INT_BIT_SCD;
+
 	/* iwl4965_irq_tasklet() will service interrupts and re-enable them */
-	tasklet_schedule(&priv->irq_tasklet);
+	if (likely(inta || inta_fh))
+		tasklet_schedule(&priv->irq_tasklet);
 
  unplugged:
 	spin_unlock(&priv->lock);
@@ -5576,6 +5588,15 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv)
 	return 0;
 }
 
+/*
+ * iwl4965_free_channel_map - undo allocations in iwl4965_init_channel_map
+ */
+static void iwl4965_free_channel_map(struct iwl4965_priv *priv)
+{
+	kfree(priv->channel_info);
+	priv->channel_count = 0;
+}
+
 /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
  * sending probe req.  This should be set long enough to hear probe responses
  * from more than one AP.  */
@@ -5909,6 +5930,17 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv)
 	return 0;
 }
 
+/*
+ * iwl4965_free_geos - undo allocations in iwl4965_init_geos
+ */
+static void iwl4965_free_geos(struct iwl4965_priv *priv)
+{
+	kfree(priv->modes);
+	kfree(priv->ieee_channels);
+	kfree(priv->ieee_rates);
+	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+}
+
 /******************************************************************************
  *
  * uCode download functions
@@ -6560,15 +6592,6 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
 	/* Clear out the uCode error bit if it is set */
 	clear_bit(STATUS_FW_ERROR, &priv->status);
 
-	rc = iwl4965_init_channel_map(priv);
-	if (rc) {
-		IWL_ERROR("initializing regulatory failed: %d\n", rc);
-		return;
-	}
-
-	iwl4965_init_geos(priv);
-	iwl4965_reset_channel_flag(priv);
-
 	if (iwl4965_is_rfkill(priv))
 		return;
 
@@ -7023,7 +7046,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
 	 * that based on the direct_mask added to each channel entry */
 	scan->tx_cmd.len = cpu_to_le16(
 		iwl4965_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
-			IWL_MAX_SCAN_SIZE - sizeof(scan), 0));
+			IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
 	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
 	scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
 	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
@@ -7448,7 +7471,7 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
 
 	if (priv->vif) {
 		IWL_DEBUG_MAC80211("leave - vif != NULL\n");
-		return 0;
+		return -EOPNOTSUPP;
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -7580,7 +7603,7 @@ static void iwl4965_config_ap(struct iwl4965_priv *priv)
 {
 	int rc = 0;
 
-	if (priv->status & STATUS_EXIT_PENDING)
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
 	/* The following should be done only at AP bring up */
@@ -9198,11 +9221,24 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 	IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
 	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 
+	err = iwl4965_init_channel_map(priv);
+	if (err) {
+		IWL_ERROR("initializing regulatory failed: %d\n", err);
+		goto out_remove_sysfs;
+	}
+
+	err = iwl4965_init_geos(priv);
+	if (err) {
+		IWL_ERROR("initializing geos failed: %d\n", err);
+		goto out_free_channel_map;
+	}
+	iwl4965_reset_channel_flag(priv);
+
 	iwl4965_rate_control_register(priv->hw);
 	err = ieee80211_register_hw(priv->hw);
 	if (err) {
 		IWL_ERROR("Failed to register network device (error %d)\n", err);
-		goto out_remove_sysfs;
+		goto out_free_geos;
 	}
 
 	priv->hw->conf.beacon_int = 100;
@@ -9212,6 +9248,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
 	return 0;
 
+ out_free_geos:
+	iwl4965_free_geos(priv);
+ out_free_channel_map:
+	iwl4965_free_channel_map(priv);
  out_remove_sysfs:
 	sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
 
@@ -9286,10 +9326,8 @@ static void iwl4965_pci_remove(struct pci_dev *pdev)
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 
-	kfree(priv->channel_info);
-
-	kfree(priv->ieee_channels);
-	kfree(priv->ieee_rates);
+	iwl4965_free_channel_map(priv);
+	iwl4965_free_geos(priv);
 
 	if (priv->ibss_beacon)
 		dev_kfree_skb(priv->ibss_beacon);
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index c622e9b..87e145f 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -12,8 +12,10 @@
 #include "cmd.h"

-static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const u8 bssid_any[ETH_ALEN]  __attribute__ ((aligned (2))) =
+	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+static const u8 bssid_off[ETH_ALEN]  __attribute__ ((aligned (2))) =
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

 static int assoc_helper_essid(struct lbs_private *priv,
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 58d7ef6..5a69f2b 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -349,7 +349,7 @@ struct assoc_request {
 	u8 channel;
 	u8 band;
 	u8 mode;
-	u8 bssid[ETH_ALEN];
+	u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
 
 	/** WEP keys */
 	struct enc_key wep_keys[4];
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 4b5ab9a..5a9cadb 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -249,14 +249,14 @@ static irqreturn_t if_cs_interrupt(int irq, void *data)
 	lbs_deb_enter(LBS_DEB_CS);
 
 	int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
-	if(int_cause == 0x0) {
+	if (int_cause == 0x0) {
 		/* Not for us */
 		return IRQ_NONE;
 
 	} else if (int_cause == 0xffff) {
 		/* Read in junk, the card has probably been removed */
 		card->priv->surpriseremoved = 1;
-
+		return IRQ_HANDLED;
 	} else {
 		if (int_cause & IF_CS_H_IC_TX_OVER)
 			lbs_host_to_card_done(card->priv);
@@ -717,8 +717,8 @@ static void if_cs_release(struct pcmcia_device *p_dev)
 
 	lbs_deb_enter(LBS_DEB_CS);
 
-	pcmcia_disable_device(p_dev);
 	free_irq(p_dev->irq.AssignedIRQ, card);
+	pcmcia_disable_device(p_dev);
 	if (card->iobase)
 		ioport_unmap(card->iobase);
 
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index ab52f22..b31f0c2 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1736,7 +1736,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
 			WARNING(rt2x00dev,
 				"TX status report missed for entry %p\n",
 				entry_done);
-			rt2x00lib_txdone(entry_done, TX_FAIL_OTHER, 0);
+			rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER,
+					 0);
 			entry_done = rt2x00_get_data_entry_done(ring);
 		}
 
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
index 07f37b0..27ebd68 100644
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -36,6 +36,7 @@ MODULE_LICENSE("GPL");
 static struct pci_device_id rtl8180_table[] __devinitdata = {
 	/* rtl8185 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x701f) },
 
 	/* rtl8180 */
diff --git a/include/linux/input.h b/include/linux/input.h
index 2075d6d..056a17a 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -371,6 +371,8 @@ struct input_absinfo {
 #define KEY_BRIGHTNESS_ZERO	244	/* brightness off, use ambient */
 #define KEY_DISPLAY_OFF		245	/* display device to off state */
 
+#define KEY_WIMAX		246
+
 #define BTN_MISC		0x100
 #define BTN_0			0x100
 #define BTN_1			0x101
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index 0ce5e0b..e3ab21d 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -33,11 +33,13 @@
  * RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device.
  * RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device.
  * RFKILL_TYPE_UWB: switch is on a ultra wideband device.
+ * RFKILL_TYPE_WIMAX: switch is on a WiMAX device.
  */
 enum rfkill_type {
 	RFKILL_TYPE_WLAN ,
 	RFKILL_TYPE_BLUETOOTH,
 	RFKILL_TYPE_UWB,
+	RFKILL_TYPE_WIMAX,
 	RFKILL_TYPE_MAX,
 };
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 89e1e30..d44c872 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -340,9 +340,42 @@ static u32 ieee80211_rx_load_stats(struct ieee80211_local *local,
 	return load;
 }
 
+static ieee80211_txrx_result
+ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx)
+{
+	int hdrlen;
+
+	/*
+	 * Drivers are required to align the payload data in a way that
+	 * guarantees that the contained IP header is aligned to a four-
+	 * byte boundary. In the case of regular frames, this simply means
+	 * aligning the payload to a four-byte boundary (because either
+	 * the IP header is directly contained, or IV/RFC1042 headers that
+	 * have a length divisible by four are in front of it.
+	 *
+	 * With A-MSDU frames, however, the payload data address must
+	 * yield two modulo four because there are 14-byte 802.3 headers
+	 * within the A-MSDU frames that push the IP header further back
+	 * to a multiple of four again. Thankfully, the specs were sane
+	 * enough this time around to require padding each A-MSDU subframe
+	 * to a length that is a multiple of four.
+	 *
+	 * Padding like atheros hardware adds which is inbetween the 802.11
+	 * header and the payload is not supported, the driver is required
+	 * to move the 802.11 header further back in that case.
+	 */
+	hdrlen = ieee80211_get_hdrlen(rx->fc);
+	if (rx->flags & IEEE80211_TXRXD_RX_AMSDU)
+		hdrlen += ETH_HLEN;
+	WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3);
+
+	return TXRX_CONTINUE;
+}
+
 ieee80211_rx_handler ieee80211_rx_pre_handlers[] =
 {
 	ieee80211_rx_h_parse_qos,
+	ieee80211_rx_h_verify_ip_alignment,
 	NULL
 };
 
@@ -1679,7 +1712,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 	struct ieee80211_sub_if_data *prev = NULL;
 	struct sk_buff *skb_new;
 	u8 *bssid;
-	int hdrlen;
 
 	hdr = (struct ieee80211_hdr *) skb->data;
 	memset(&rx, 0, sizeof(rx));
@@ -1691,18 +1723,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 	rx.fc = le16_to_cpu(hdr->frame_control);
 	type = rx.fc & IEEE80211_FCTL_FTYPE;
 
-	/*
-	 * Drivers are required to align the payload data to a four-byte
-	 * boundary, so the last two bits of the address where it starts
-	 * may not be set. The header is required to be directly before
-	 * the payload data, padding like atheros hardware adds which is
-	 * inbetween the 802.11 header and the payload is not supported,
-	 * the driver is required to move the 802.11 header further back
-	 * in that case.
-	 */
-	hdrlen = ieee80211_get_hdrlen(rx.fc);
-	WARN_ON_ONCE(((unsigned long)(skb->data + hdrlen)) & 3);
-
 	if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT)
 		local->dot11ReceivedFragmentCount++;
 
@@ -1952,7 +1972,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
 		goto end_reorder;
 
 	/* null data frames are excluded */
-	if (unlikely(fc & IEEE80211_STYPE_QOS_NULLFUNC))
+	if (unlikely(fc & IEEE80211_STYPE_NULLFUNC))
 		goto end_reorder;
 
 	/* new un-ordered ampdu frame - process it */
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index d1e9d68..e4b051d 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -84,6 +84,7 @@ static void rfkill_schedule_toggle(struct rfkill_task *task)
 static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN);
 static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH);
 static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB);
+static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX);
 
 static void rfkill_event(struct input_handle *handle, unsigned int type,
 			unsigned int code, int down)
@@ -99,6 +100,9 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,
 		case KEY_UWB:
 			rfkill_schedule_toggle(&rfkill_uwb);
 			break;
+		case KEY_WIMAX:
+			rfkill_schedule_toggle(&rfkill_wimax);
+			break;
 		default:
 			break;
 		}
@@ -159,6 +163,11 @@ static const struct input_device_id rfkill_ids[] = {
 		.evbit = { BIT_MASK(EV_KEY) },
 		.keybit = { [BIT_WORD(KEY_UWB)] = BIT_MASK(KEY_UWB) },
 	},
+	{
+		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
+		.evbit = { BIT_MASK(EV_KEY) },
+		.keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) },
+	},
 	{ }
 };
 
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index d06d338..6562f86 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -126,6 +126,9 @@ static ssize_t rfkill_type_show(struct device *dev,
 	case RFKILL_TYPE_UWB:
 		type = "ultrawideband";
 		break;
+	case RFKILL_TYPE_WIMAX:
+		type = "wimax";
+		break;
 	default:
 		BUG();
 	}
-- 
John W. Linville
[email-masked]