rpms/kernel/FC-6 jwltest-bcm43xx-2_6_20.patch, NONE, 1.1.10.1 jwltest-bcm43xx-host_strip_iv_icv-undo.patch, NONE, 1.1.10.1 jwltest-bcm43xx-post-2_6_20.patch, NONE, 1.1.10.1 jwltest-bcm43xx-workqueue-undo.patch, NONE, 1.1.10.1 jwltest-iwlwifi-2_6_19-fixup.patch, NONE, 1.1.2.1 jwltest-iwlwifi.patch, NONE, 1.1.2.1 jwltest-mac80211-backport-2_6_19-fixup.patch, NONE, 1.1.2.1 jwltest-mac80211-backport.patch, NONE, 1.1.2.1 jwltest-prism54-wpa-fix.patch, NONE, 1.1.14.1 jwltest-softmac_wx_get_rate-running-check.patch, NONE, 1.1.18.1

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Wed Feb 28 00:43:28 UTC 2007


Author: linville

Update of /cvs/dist/rpms/kernel/FC-6
In directory cvs.devel.redhat.com:/tmp/cvs-serv21245

Added Files:
      Tag: private-linville-jwltest-fc6-23-branch
	jwltest-bcm43xx-2_6_20.patch 
	jwltest-bcm43xx-host_strip_iv_icv-undo.patch 
	jwltest-bcm43xx-post-2_6_20.patch 
	jwltest-bcm43xx-workqueue-undo.patch 
	jwltest-iwlwifi-2_6_19-fixup.patch jwltest-iwlwifi.patch 
	jwltest-mac80211-backport-2_6_19-fixup.patch 
	jwltest-mac80211-backport.patch jwltest-prism54-wpa-fix.patch 
	jwltest-softmac_wx_get_rate-running-check.patch 
Log Message:


jwltest-bcm43xx-2_6_20.patch:
 bcm43xx.h       |   34 ++++++++
 bcm43xx_main.c  |  228 ++++++++++++++++++++++++++++++++------------------------
 bcm43xx_power.c |   28 +++++-
 bcm43xx_wx.c    |    4 
 bcm43xx_xmit.c  |   18 ----
 5 files changed, 188 insertions(+), 124 deletions(-)

--- NEW FILE jwltest-bcm43xx-2_6_20.patch ---
--- linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx.h.orig	2007-02-08 14:17:14.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx.h	2007-02-08 14:34:46.000000000 -0500
@@ -159,6 +159,7 @@
 
 /* Chipcommon registers. */
 #define BCM43xx_CHIPCOMMON_CAPABILITIES 	0x04
+#define BCM43xx_CHIPCOMMON_CTL			0x28
 #define BCM43xx_CHIPCOMMON_PLLONDELAY		0xB0
 #define BCM43xx_CHIPCOMMON_FREFSELDELAY		0xB4
 #define BCM43xx_CHIPCOMMON_SLOWCLKCTL		0xB8
@@ -172,6 +173,33 @@
 /* SBTOPCI2 values. */
 #define BCM43xx_SBTOPCI2_PREFETCH	0x4
 #define BCM43xx_SBTOPCI2_BURST		0x8
+#define BCM43xx_SBTOPCI2_MEMREAD_MULTI	0x20
+
+/* PCI-E core registers. */
+#define BCM43xx_PCIECORE_REG_ADDR      0x0130
+#define BCM43xx_PCIECORE_REG_DATA      0x0134
+#define BCM43xx_PCIECORE_MDIO_CTL      0x0128
+#define BCM43xx_PCIECORE_MDIO_DATA     0x012C
+
+/* PCI-E registers. */
+#define BCM43xx_PCIE_TLP_WORKAROUND    0x0004
+#define BCM43xx_PCIE_DLLP_LINKCTL      0x0100
+
+/* PCI-E MDIO bits. */
+#define BCM43xx_PCIE_MDIO_ST   0x40000000
+#define BCM43xx_PCIE_MDIO_WT   0x10000000
+#define BCM43xx_PCIE_MDIO_DEV  22
+#define BCM43xx_PCIE_MDIO_REG  18
+#define BCM43xx_PCIE_MDIO_TA   0x00020000
+#define BCM43xx_PCIE_MDIO_TC   0x0100
+
+/* MDIO devices. */
+#define BCM43xx_MDIO_SERDES_RX	0x1F
+
+/* SERDES RX registers. */
+#define BCM43xx_SERDES_RXTIMER	0x2
+#define BCM43xx_SERDES_CDR	0x6
+#define BCM43xx_SERDES_CDR_BW	0x7
 
 /* Chipcommon capabilities. */
 #define BCM43xx_CAPABILITIES_PCTL		0x00040000
@@ -221,6 +249,7 @@
 #define BCM43xx_COREID_USB20_HOST       0x819
 #define BCM43xx_COREID_USB20_DEV        0x81a
 #define BCM43xx_COREID_SDIO_HOST        0x81b
+#define BCM43xx_COREID_PCIE		0x820
 
 /* Core Information Registers */
 #define BCM43xx_CIR_BASE		0xf00
@@ -365,6 +394,9 @@
 #define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT	7
 #define BCM43xx_DEFAULT_LONG_RETRY_LIMIT	4
 
+/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
+#define RX_RSSI_MAX				60
+
 /* Max size of a security key */
 #define BCM43xx_SEC_KEYSIZE			16
 /* Security algorithms. */
@@ -787,7 +819,7 @@ struct bcm43xx_private {
 	struct tasklet_struct isr_tasklet;
 
 	/* Periodic tasks */
-	struct work_struct periodic_work;
+	struct delayed_work periodic_work;
 	unsigned int periodic_state;
 
 	struct work_struct restart_work;
--- linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_wx.c.orig	2006-11-29 16:57:37.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_wx.c	2007-02-08 14:34:46.000000000 -0500
@@ -47,9 +47,6 @@
 #define BCM43xx_WX_VERSION	18
 
 #define MAX_WX_STRING		80
-/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
-#define RX_RSSI_MAX		60
-
 
 static int bcm43xx_wx_get_name(struct net_device *net_dev,
                                struct iw_request_info *info,
@@ -693,6 +690,7 @@ static int bcm43xx_wx_set_swencryption(s
 	bcm->ieee->host_encrypt = !!on;
 	bcm->ieee->host_decrypt = !!on;
 	bcm->ieee->host_build_iv = !on;
+	bcm->ieee->host_strip_iv_icv = !on;
 	spin_unlock_irqrestore(&bcm->irq_lock, flags);
 	mutex_unlock(&bcm->mutex);
 
--- linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_main.c.orig	2007-02-08 14:17:14.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_main.c	2007-02-08 14:34:46.000000000 -0500
@@ -130,6 +130,10 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for
 	{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4307 802.11b */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4311 802.11(a)/b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4312 802.11a/b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4318 802.11b/g */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4319 802.11a/b/g */
@@ -2600,8 +2604,9 @@ static int bcm43xx_probe_cores(struct bc
 	/* fetch sb_id_hi from core information registers */
 	sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
 
-	core_id = (sb_id_hi & 0xFFF0) >> 4;
-	core_rev = (sb_id_hi & 0xF);
+	core_id = (sb_id_hi & 0x8FF0) >> 4;
+	core_rev = (sb_id_hi & 0x7000) >> 8;
+	core_rev |= (sb_id_hi & 0xF);
 	core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
 
 	/* if present, chipcommon is always core 0; read the chipid from it */
@@ -2679,14 +2684,10 @@ static int bcm43xx_probe_cores(struct bc
 		bcm->chip_id, bcm->chip_rev);
 	dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
 	if (bcm->core_chipcommon.available) {
-		dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
-			core_id, core_rev, core_vendor,
-			bcm43xx_core_enabled(bcm) ? "enabled" : "disabled");
-	}
-
-	if (bcm->core_chipcommon.available)
+		dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x\n",
+			core_id, core_rev, core_vendor);
 		current_core = 1;
-	else
+	} else
 		current_core = 0;
 	for ( ; current_core < core_count; current_core++) {
 		struct bcm43xx_coreinfo *core;
@@ -2700,17 +2701,17 @@ static int bcm43xx_probe_cores(struct bc
 		sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
 
 		/* extract core_id, core_rev, core_vendor */
-		core_id = (sb_id_hi & 0xFFF0) >> 4;
-		core_rev = (sb_id_hi & 0xF);
+		core_id = (sb_id_hi & 0x8FF0) >> 4;
+		core_rev = ((sb_id_hi & 0xF) | ((sb_id_hi & 0x7000) >> 8));
 		core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
 
-		dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
-			current_core, core_id, core_rev, core_vendor,
-			bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" );
+		dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n",
+			current_core, core_id, core_rev, core_vendor);
 
 		core = NULL;
 		switch (core_id) {
 		case BCM43xx_COREID_PCI:
+		case BCM43xx_COREID_PCIE:
 			core = &bcm->core_pci;
 			if (core->available) {
 				printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
@@ -2749,12 +2750,12 @@ static int bcm43xx_probe_cores(struct bc
 			case 6:
 			case 7:
 			case 9:
+			case 10:
 				break;
 			default:
-				printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
+				printk(KERN_WARNING PFX
+				       "Unsupported 80211 core revision %u\n",
 				       core_rev);
-				err = -ENODEV;
-				goto out;
 			}
 			bcm->nr_80211_available++;
 			core->priv = ext_80211;
@@ -2868,16 +2869,14 @@ static int bcm43xx_wireless_core_init(st
 	u32 sbimconfiglow;
 	u8 limit;
 
-	if (bcm->chip_rev < 5) {
+	if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) {
 		sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
 		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
 		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
 		if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
 			sbimconfiglow |= 0x32;
-		else if (bcm->bustype == BCM43xx_BUSTYPE_SB)
-			sbimconfiglow |= 0x53;
 		else
-			assert(0);
+			sbimconfiglow |= 0x53;
 		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
 	}
 
@@ -3004,22 +3003,64 @@ static void bcm43xx_pcicore_broadcast_va
 
 static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
 {
-	int err;
-	struct bcm43xx_coreinfo *old_core;
+	int err = 0;
 
-	old_core = bcm->current_core;
-	err = bcm43xx_switch_core(bcm, &bcm->core_pci);
-	if (err)
-		goto out;
+	bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
 
-	bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+	if (bcm->core_chipcommon.available) {
+		err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+		if (err)
+			goto out;
+
+		bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+
+		/* this function is always called when a PCI core is mapped */
+		err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+		if (err)
+			goto out;
+	} else
+		bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+
+	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
 
-	bcm43xx_switch_core(bcm, old_core);
-	assert(err == 0);
 out:
 	return err;
 }
 
+static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address)
+{
+	bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
+	return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA);
+}
+
+static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address,
+				    u32 data)
+{
+	bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
+	bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data);
+}
+
+static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg,
+				    u16 data)
+{
+	int i;
+
+	bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082);
+	bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST |
+			BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) |
+			(reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA |
+			data);
+	udelay(10);
+
+	for (i = 0; i < 10; i++) {
+		if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) &
+		    BCM43xx_PCIE_MDIO_TC)
+			break;
+		msleep(1);
+	}
+	bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0);
+}
+
 /* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
  * To enable core 0, pass a core_mask of 1<<0
  */
@@ -3039,7 +3080,8 @@ static int bcm43xx_setup_backplane_pci_c
 	if (err)
 		goto out;
 
-	if (bcm->core_pci.rev < 6) {
+	if (bcm->current_core->rev < 6 &&
+		bcm->current_core->id == BCM43xx_COREID_PCI) {
 		value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
 		value |= (1 << backplane_flag_nr);
 		bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
@@ -3057,21 +3099,46 @@ static int bcm43xx_setup_backplane_pci_c
 		}
 	}
 
-	value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
-	value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
-	bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
-
-	if (bcm->core_pci.rev < 5) {
-		value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
-		value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
-			 & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
-		value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
-			 & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
-		err = bcm43xx_pcicore_commit_settings(bcm);
-		assert(err == 0);
+	if (bcm->current_core->id == BCM43xx_COREID_PCI) {
+		value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+		value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
+		bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+
+		if (bcm->current_core->rev < 5) {
+			value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+			value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
+				 & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+			value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
+				 & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+			bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
+			err = bcm43xx_pcicore_commit_settings(bcm);
+			assert(err == 0);
+		} else if (bcm->current_core->rev >= 11) {
+			value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+			value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI;
+			bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+		}
+	} else {
+		if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) {
+			value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND);
+			value |= 0x8;
+			bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND,
+					       value);
+		}
+		if (bcm->current_core->rev == 0) {
+			bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+						BCM43xx_SERDES_RXTIMER, 0x8128);
+			bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+						BCM43xx_SERDES_CDR, 0x0100);
+			bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+						BCM43xx_SERDES_CDR_BW, 0x1466);
+		} else if (bcm->current_core->rev == 1) {
+			value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL);
+			value |= 0x40;
+			bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL,
+					       value);
+		}
 	}
-
 out_switch_back:
 	err = bcm43xx_switch_core(bcm, old_core);
 out:
@@ -3140,55 +3207,28 @@ static void bcm43xx_periodic_every15sec(
 
 static void do_periodic_work(struct bcm43xx_private *bcm)
 {
-	unsigned int state;
-
-	state = bcm->periodic_state;
-	if (state % 8 == 0)
+	if (bcm->periodic_state % 8 == 0)
 		bcm43xx_periodic_every120sec(bcm);
-	if (state % 4 == 0)
+	if (bcm->periodic_state % 4 == 0)
 		bcm43xx_periodic_every60sec(bcm);
-	if (state % 2 == 0)
+	if (bcm->periodic_state % 2 == 0)
 		bcm43xx_periodic_every30sec(bcm);
-	if (state % 1 == 0)
-		bcm43xx_periodic_every15sec(bcm);
-	bcm->periodic_state = state + 1;
+	bcm43xx_periodic_every15sec(bcm);
 
 	schedule_delayed_work(&bcm->periodic_work, HZ * 15);
 }
 
-/* Estimate a "Badness" value based on the periodic work
- * state-machine state. "Badness" is worse (bigger), if the
- * periodic work will take longer.
- */
-static int estimate_periodic_work_badness(unsigned int state)
-{
-	int badness = 0;
-
-	if (state % 8 == 0) /* every 120 sec */
-		badness += 10;
-	if (state % 4 == 0) /* every 60 sec */
-		badness += 5;
-	if (state % 2 == 0) /* every 30 sec */
-		badness += 1;
-	if (state % 1 == 0) /* every 15 sec */
-		badness += 1;
-
-#define BADNESS_LIMIT	4
-	return badness;
-}
-
-static void bcm43xx_periodic_work_handler(void *d)
+static void bcm43xx_periodic_work_handler(struct work_struct *work)
 {
-	struct bcm43xx_private *bcm = d;
+	struct bcm43xx_private *bcm =
+		container_of(work, struct bcm43xx_private, periodic_work.work);
 	struct net_device *net_dev = bcm->net_dev;
 	unsigned long flags;
 	u32 savedirqs = 0;
-	int badness;
 	unsigned long orig_trans_start = 0;
 
 	mutex_lock(&bcm->mutex);
-	badness = estimate_periodic_work_badness(bcm->periodic_state);
-	if (badness > BADNESS_LIMIT) {
+	if (unlikely(bcm->periodic_state % 4 == 0)) {
 		/* Periodic work will take a long time, so we want it to
 		 * be preemtible.
 		 */
@@ -3220,7 +3260,7 @@ static void bcm43xx_periodic_work_handle
 
 	do_periodic_work(bcm);
 
-	if (badness > BADNESS_LIMIT) {
+	if (unlikely(bcm->periodic_state % 4 == 0)) {
 		spin_lock_irqsave(&bcm->irq_lock, flags);
 		tasklet_enable(&bcm->isr_tasklet);
 		bcm43xx_interrupt_enable(bcm, savedirqs);
@@ -3231,6 +3271,7 @@ static void bcm43xx_periodic_work_handle
 		net_dev->trans_start = orig_trans_start;
 	}
 	mmiowb();
+	bcm->periodic_state++;
 	spin_unlock_irqrestore(&bcm->irq_lock, flags);
 	mutex_unlock(&bcm->mutex);
 }
@@ -3242,11 +3283,11 @@ void bcm43xx_periodic_tasks_delete(struc
 
 void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
 {
-	struct work_struct *work = &(bcm->periodic_work);
+	struct delayed_work *work = &bcm->periodic_work;
 
 	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
-	INIT_WORK(work, bcm43xx_periodic_work_handler, bcm);
-	schedule_work(work);
+	INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler);
+	schedule_delayed_work(work, 0);
 }
 
 static void bcm43xx_security_init(struct bcm43xx_private *bcm)
@@ -3598,7 +3639,7 @@ static int bcm43xx_init_board(struct bcm
 	bcm43xx_periodic_tasks_setup(bcm);
 
 	/*FIXME: This should be handled by softmac instead. */
-	schedule_work(&bcm->softmac->associnfo.work);
+	schedule_delayed_work(&bcm->softmac->associnfo.work, 0);
 
 out:
 	mutex_unlock(&(bcm)->mutex);
@@ -3676,7 +3717,7 @@ static int bcm43xx_read_phyinfo(struct b
 		bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
 		break;
 	case BCM43xx_PHYTYPE_G:
-		if (phy_rev > 7)
+		if (phy_rev > 8)
 			phy_rev_ok = 0;
 		bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
 					IEEE80211_CCK_MODULATION;
@@ -3688,6 +3729,8 @@ static int bcm43xx_read_phyinfo(struct b
 		       phy_type);
 		return -ENODEV;
 	};
+	bcm->ieee->perfect_rssi = RX_RSSI_MAX;
+	bcm->ieee->worst_rssi = 0;
 	if (!phy_rev_ok) {
 		printk(KERN_WARNING PFX "Invalid PHY Revision %x\n",
 		       phy_rev);
@@ -3974,11 +4017,6 @@ static int bcm43xx_ieee80211_hard_start_
 	return NETDEV_TX_OK;
 }
 
-static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev)
-{
-	return &(bcm43xx_priv(net_dev)->ieee->stats);
-}
-
 static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
@@ -4092,7 +4130,6 @@ static int __devinit bcm43xx_init_one(st
 
 	net_dev->open = bcm43xx_net_open;
 	net_dev->stop = bcm43xx_net_stop;
-	net_dev->get_stats = bcm43xx_net_get_stats;
 	net_dev->tx_timeout = bcm43xx_net_tx_timeout;
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	net_dev->poll_controller = bcm43xx_net_poll_controller;
@@ -4149,9 +4186,10 @@ static void __devexit bcm43xx_remove_one
 /* Hard-reset the chip. Do not call this directly.
  * Use bcm43xx_controller_restart()
  */
-static void bcm43xx_chip_reset(void *_bcm)
+static void bcm43xx_chip_reset(struct work_struct *work)
 {
-	struct bcm43xx_private *bcm = _bcm;
+	struct bcm43xx_private *bcm =
+		container_of(work, struct bcm43xx_private, restart_work);
 	struct bcm43xx_phyinfo *phy;
 	int err = -ENODEV;
 
@@ -4178,7 +4216,7 @@ void bcm43xx_controller_restart(struct b
 	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
 		return;
 	printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
-	INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
+	INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset);
 	schedule_work(&bcm->restart_work);
 }
 
--- linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_power.c.orig	2007-02-08 14:17:14.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_power.c	2007-02-08 14:34:46.000000000 -0500
@@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
 	int err, maxfreq;
 	struct bcm43xx_coreinfo *old_core;
 
-	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
-		return 0;
 	old_core = bcm->current_core;
 	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
 	if (err == -ENODEV)
@@ -162,11 +160,27 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
 	if (err)
 		goto out;
 
-	maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
-	bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
-			(maxfreq * 150 + 999999) / 1000000);
-	bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
-			(maxfreq * 15 + 999999) / 1000000);
+	if (bcm->chip_id == 0x4321) {
+		if (bcm->chip_rev == 0)
+			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4);
+		if (bcm->chip_rev == 1)
+			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4);
+	}
+
+	if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) {
+		if (bcm->current_core->rev >= 10) {
+			/* Set Idle Power clock rate to 1Mhz */
+			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL,
+				       (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL)
+				       & 0x0000FFFF) | 0x40000);
+		} else {
+			maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
+				       (maxfreq * 150 + 999999) / 1000000);
+			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
+				       (maxfreq * 15 + 999999) / 1000000);
+		}
+	}
 
 	err = bcm43xx_switch_core(bcm, old_core);
 	assert(err == 0);
--- linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c.orig	2006-11-29 16:57:37.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c	2007-02-08 14:34:46.000000000 -0500
@@ -544,24 +544,6 @@ int bcm43xx_rx(struct bcm43xx_private *b
 	}
 
 	frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
-	if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
-		frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
-		wlhdr->frame_ctl = cpu_to_le16(frame_ctl);		
-		/* trim IV and ICV */
-		/* FIXME: this must be done only for WEP encrypted packets */
-		if (skb->len < 32) {
-			dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
-					      "set and length < 32)\n");
-			return -EINVAL;
-		} else {		
-			memmove(skb->data + 4, skb->data, 24);
-			skb_pull(skb, 4);
-			skb_trim(skb, skb->len - 4);
-			stats.len -= 8;
-		}
-		wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
-	}
-	
 	switch (WLAN_FC_GET_TYPE(frame_ctl)) {
 	case IEEE80211_FTYPE_MGMT:
 		ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);

jwltest-bcm43xx-host_strip_iv_icv-undo.patch:
 bcm43xx_wx.c   |    1 -
 bcm43xx_xmit.c |   18 ++++++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

--- NEW FILE jwltest-bcm43xx-host_strip_iv_icv-undo.patch ---
--- linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_wx.c.orig	2007-02-08 15:50:54.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_wx.c	2007-02-08 15:49:59.000000000 -0500
@@ -690,7 +690,6 @@ static int bcm43xx_wx_set_swencryption(s
 	bcm->ieee->host_encrypt = !!on;
 	bcm->ieee->host_decrypt = !!on;
 	bcm->ieee->host_build_iv = !on;
-	bcm->ieee->host_strip_iv_icv = !on;
 	spin_unlock_irqrestore(&bcm->irq_lock, flags);
 	mutex_unlock(&bcm->mutex);
 
--- linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c.orig	2007-02-08 15:48:53.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c	2007-02-08 15:49:59.000000000 -0500
@@ -544,6 +544,24 @@ int bcm43xx_rx(struct bcm43xx_private *b
 	}
 
 	frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
+	if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
+		frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
+		wlhdr->frame_ctl = cpu_to_le16(frame_ctl);		
+		/* trim IV and ICV */
+		/* FIXME: this must be done only for WEP encrypted packets */
+		if (skb->len < 32) {
+			dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
+					      "set and length < 32)\n");
+			return -EINVAL;
+		} else {		
+			memmove(skb->data + 4, skb->data, 24);
+			skb_pull(skb, 4);
+			skb_trim(skb, skb->len - 4);
+			stats.len -= 8;
+		}
+		wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
+	}
+	
 	switch (WLAN_FC_GET_TYPE(frame_ctl)) {
 	case IEEE80211_FTYPE_MGMT:
 		ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);

jwltest-bcm43xx-post-2_6_20.patch:
 bcm43xx.h       |    9 +-
 bcm43xx_dma.c   |  171 +++++++++++++++++++++++++++++++++++--------------
 bcm43xx_ilt.c   |   15 ++++
 bcm43xx_ilt.h   |    1 
 bcm43xx_main.c  |   45 ++++++------
 bcm43xx_phy.c   |  195 ++++++++++++++++++++++++--------------------------------
 bcm43xx_radio.c |   13 ++-
 bcm43xx_wx.c    |   28 ++++----
 bcm43xx_xmit.h  |   10 --
 9 files changed, 275 insertions(+), 212 deletions(-)

--- NEW FILE jwltest-bcm43xx-post-2_6_20.patch ---
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 8286678..6b1749b 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -21,7 +21,7 @@ #include "bcm43xx_leds.h"
 #define PFX				KBUILD_MODNAME ": "
 
 #define BCM43xx_SWITCH_CORE_MAX_RETRIES	50
-#define BCM43xx_IRQWAIT_MAX_RETRIES	50
+#define BCM43xx_IRQWAIT_MAX_RETRIES	100
 
 #define BCM43xx_IO_SIZE			8192
 
@@ -333,7 +333,7 @@ #define BCM43xx_SBF_PS1			0x02000000
 #define BCM43xx_SBF_PS2			0x04000000
 #define BCM43xx_SBF_NO_SSID_BCAST	0x08000000
 #define BCM43xx_SBF_TIME_UPDATE		0x10000000
-#define BCM43xx_SBF_80000000		0x80000000 /*FIXME: fix name*/
+#define BCM43xx_SBF_MODE_G		0x80000000
 
 /* Microcode */
 #define BCM43xx_UCODE_REVISION		0x0000
@@ -503,8 +503,6 @@ struct bcm43xx_sprominfo {
 	u8 et1macaddr[6];
 	u8 et0phyaddr:5;
 	u8 et1phyaddr:5;
-	u8 et0mdcport:1;
-	u8 et1mdcport:1;
 	u8 boardrev;
 	u8 locale:4;
 	u8 antennas_aphy:2;
@@ -538,7 +536,7 @@ #define BCM43xx_LO_COUNT	(14*4)
 
 struct bcm43xx_phyinfo {
 	/* Hardware Data */
-	u8 version;
+	u8 analog;
 	u8 type;
 	u8 rev;
 	u16 antenna_diversity;
@@ -766,6 +764,7 @@ struct bcm43xx_private {
 	 * This is currently always BCM43xx_BUSTYPE_PCI
 	 */
 	u8 bustype;
+	u64 dma_mask;
 
 	u16 board_vendor;
 	u16 board_type;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index 978ed09..6e0dc76 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -145,16 +145,14 @@ dma_addr_t map_descbuffer(struct bcm43xx
 			  int tx)
 {
 	dma_addr_t dmaaddr;
+	int direction = PCI_DMA_FROMDEVICE;
 
-	if (tx) {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
-					 buf, len,
-					 DMA_TO_DEVICE);
-	} else {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+	if (tx)
+		direction = PCI_DMA_TODEVICE;
+
+	dmaaddr = pci_map_single(ring->bcm->pci_dev,
 					 buf, len,
-					 DMA_FROM_DEVICE);
-	}
+					 direction);
 
 	return dmaaddr;
 }
@@ -166,13 +164,13 @@ void unmap_descbuffer(struct bcm43xx_dma
 		      int tx)
 {
 	if (tx) {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		pci_unmap_single(ring->bcm->pci_dev,
 				 addr, len,
-				 DMA_TO_DEVICE);
+				 PCI_DMA_TODEVICE);
 	} else {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		pci_unmap_single(ring->bcm->pci_dev,
 				 addr, len,
-				 DMA_FROM_DEVICE);
+				 PCI_DMA_FROMDEVICE);
 	}
 }
 
@@ -183,8 +181,8 @@ void sync_descbuffer_for_cpu(struct bcm4
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
-				addr, len, DMA_FROM_DEVICE);
+	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+				    addr, len, PCI_DMA_FROMDEVICE);
 }
 
 static inline
@@ -194,8 +192,8 @@ void sync_descbuffer_for_device(struct b
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
-				   addr, len, DMA_FROM_DEVICE);
+	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+				    addr, len, PCI_DMA_TODEVICE);
 }
 
 /* Unmap and free a descriptor buffer. */
@@ -214,17 +212,53 @@ void free_descriptor_buffer(struct bcm43
 
 static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
 {
-	struct device *dev = &(ring->bcm->pci_dev->dev);
-
-	ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
-					    &(ring->dmabase), GFP_KERNEL);
+	ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
+					    &(ring->dmabase));
 	if (!ring->descbase) {
-		printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
-		return -ENOMEM;
+		/* Allocation may have failed due to pci_alloc_consistent
+		   insisting on use of GFP_DMA, which is more restrictive
+		   than necessary...  */
+		struct dma_desc *rx_ring;
+		dma_addr_t rx_ring_dma;
+
+		rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
+		if (!rx_ring)
+			goto out_err;
+
+		rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
+					     BCM43xx_DMA_RINGMEMSIZE,
+					     PCI_DMA_BIDIRECTIONAL);
+
+		if (pci_dma_mapping_error(rx_ring_dma) ||
+		    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+			/* Sigh... */
+			if (!pci_dma_mapping_error(rx_ring_dma))
+				pci_unmap_single(ring->bcm->pci_dev,
+						 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+						 PCI_DMA_BIDIRECTIONAL);
+			rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
+						 rx_ring, BCM43xx_DMA_RINGMEMSIZE,
+						 PCI_DMA_BIDIRECTIONAL);
+			if (pci_dma_mapping_error(rx_ring_dma) ||
+			    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+				assert(0);
+				if (!pci_dma_mapping_error(rx_ring_dma))
+					pci_unmap_single(ring->bcm->pci_dev,
+							 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+							 PCI_DMA_BIDIRECTIONAL);
+				goto out_err;
+			}
+                }
+
+                ring->descbase = rx_ring;
+                ring->dmabase = rx_ring_dma;
 	}
 	memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
 
 	return 0;
+out_err:
+	printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+	return -ENOMEM;
 }
 
 static void free_ringmemory(struct bcm43xx_dmaring *ring)
@@ -407,6 +441,29 @@ static int setup_rx_descbuffer(struct bc
 	if (unlikely(!skb))
 		return -ENOMEM;
 	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+	/* This hardware bug work-around adapted from the b44 driver.
+	   The chip may be unable to do PCI DMA to/from anything above 1GB */
+	if (pci_dma_mapping_error(dmaaddr) ||
+	    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+		/* This one has 30-bit addressing... */
+		if (!pci_dma_mapping_error(dmaaddr))
+			pci_unmap_single(ring->bcm->pci_dev,
+					 dmaaddr, ring->rx_buffersize,
+					 PCI_DMA_FROMDEVICE);
+		dev_kfree_skb_any(skb);
+		skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
+		if (skb == NULL)
+			return -ENOMEM;
+		dmaaddr = pci_map_single(ring->bcm->pci_dev,
+					 skb->data, ring->rx_buffersize,
+					 PCI_DMA_FROMDEVICE);
+		if (pci_dma_mapping_error(dmaaddr) ||
+		    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+			assert(0);
+			dev_kfree_skb_any(skb);
+			return -ENOMEM;
+		}
+	}
 	meta->skb = skb;
 	meta->dmaaddr = dmaaddr;
 	skb->dev = ring->bcm->net_dev;
@@ -636,8 +693,10 @@ #endif
 	err = dmacontroller_setup(ring);
 	if (err)
 		goto err_free_ringmemory;
+	return ring;
 
 out:
+	printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
 	return ring;
 
 err_free_ringmemory:
@@ -705,30 +764,16 @@ int bcm43xx_dma_init(struct bcm43xx_priv
 	struct bcm43xx_dmaring *ring;
 	int err = -ENOMEM;
 	int dma64 = 0;
-	u64 mask = bcm43xx_get_supported_dma_mask(bcm);
-	int nobits;
 
-	if (mask == DMA_64BIT_MASK) {
+	bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
+	if (bcm->dma_mask == DMA_64BIT_MASK)
 		dma64 = 1;
-		nobits = 64;
-	} else if (mask == DMA_32BIT_MASK)
-		nobits = 32;
-	else
-		nobits = 30;
-	err = pci_set_dma_mask(bcm->pci_dev, mask);
-	err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
-	if (err) {
-#ifdef CONFIG_BCM43XX_PIO
-		printk(KERN_WARNING PFX "DMA not supported on this device."
-					" Falling back to PIO.\n");
-		bcm->__using_pio = 1;
-		return -ENOSYS;
-#else
-		printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
-				    "Please recompile the driver with PIO support.\n");
-		return -ENODEV;
-#endif /* CONFIG_BCM43XX_PIO */
-	}
+	err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
+	if (err)
+		goto no_dma;
+	err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
+	if (err)
+		goto no_dma;
 
 	/* setup TX DMA channels. */
 	ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
@@ -774,7 +819,9 @@ #endif /* CONFIG_BCM43XX_PIO */
 		dma->rx_ring3 = ring;
 	}
 
-	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
+	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
+		(bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
+		(bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
 	err = 0;
 out:
 	return err;
@@ -800,7 +847,17 @@ err_destroy_tx1:
 err_destroy_tx0:
 	bcm43xx_destroy_dmaring(dma->tx_ring0);
 	dma->tx_ring0 = NULL;
-	goto out;
+no_dma:
+#ifdef CONFIG_BCM43XX_PIO
+	printk(KERN_WARNING PFX "DMA not supported on this device."
+				" Falling back to PIO.\n");
+	bcm->__using_pio = 1;
+	return -ENOSYS;
+#else
+	printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+			    "Please recompile the driver with PIO support.\n");
+	return -ENODEV;
+#endif /* CONFIG_BCM43XX_PIO */
 }
 
 /* Generate a cookie for the TX header. */
@@ -905,6 +962,7 @@ static void dma_tx_fragment(struct bcm43
 	struct bcm43xx_dmadesc_generic *desc;
 	struct bcm43xx_dmadesc_meta *meta;
 	dma_addr_t dmaaddr;
+	struct sk_buff *bounce_skb;
 
 	assert(skb_shinfo(skb)->nr_frags == 0);
 
@@ -924,9 +982,28 @@ static void dma_tx_fragment(struct bcm43
 			       skb->len - sizeof(struct bcm43xx_txhdr),
 			       (cur_frag == 0),
 			       generate_cookie(ring, slot));
+	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+	if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+		/* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
+		if (!dma_mapping_error(dmaaddr))
+			unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
+		if (!bounce_skb)
+			return;
+		dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
+		if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+			if (!dma_mapping_error(dmaaddr))
+				unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+			dev_kfree_skb_any(bounce_skb);
+			assert(0);
+			return;
+		}
+		memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+		dev_kfree_skb_any(skb);
+		skb = bounce_skb;
+	}
 
 	meta->skb = skb;
-	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 	meta->dmaaddr = dmaaddr;
 
 	fill_descriptor(ring, desc, dmaaddr,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
index ad8e569..f2b8dba 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
@@ -325,6 +325,21 @@ void bcm43xx_ilt_write(struct bcm43xx_pr
 	}
 }
 
+void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val)
+{
+	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+		mmiowb();
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (val & 0xFFFF0000) >> 16);
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val & 0x0000FFFF);
+	} else {
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+		mmiowb();
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16);
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val & 0x0000FFFF);
+	}
+}
+
 u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset)
 {
 	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
index 464521a..d7eaf5f 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
@@ -27,6 +27,7 @@ extern const u16 bcm43xx_ilt_sigmasqr2[B
 
 
 void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val);
 u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset);
 
 #endif /* BCM43xx_ILT_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 91b752e..e5336fa 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -95,13 +95,9 @@ static int modparam_noleds;
 module_param_named(noleds, modparam_noleds, int, 0444);
 MODULE_PARM_DESC(noleds, "Turn off all LED activity");
 
-#ifdef CONFIG_BCM43XX_DEBUG
 static char modparam_fwpostfix[64];
 module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
-MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
-#else
-# define modparam_fwpostfix  ""
-#endif /* CONFIG_BCM43XX_DEBUG*/
+MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
 
 
 /* If you want to debug with just a single device, enable this,
@@ -855,8 +851,6 @@ #endif
 	value = sprom[BCM43xx_SPROM_ETHPHY];
 	bcm->sprom.et0phyaddr = (value & 0x001F);
 	bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
-	bcm->sprom.et0mdcport = (value & (1 << 14)) >> 14;
-	bcm->sprom.et1mdcport = (value & (1 << 15)) >> 15;
 
 	/* boardrev, antennas, locale */
 	value = sprom[BCM43xx_SPROM_BOARDREV];
@@ -1453,12 +1447,10 @@ static void handle_irq_transmit_status(s
 
 		bcm43xx_debugfs_log_txstat(bcm, &stat);
 
-		if (stat.flags & BCM43xx_TXSTAT_FLAG_IGNORE)
+		if (stat.flags & BCM43xx_TXSTAT_FLAG_AMPDU)
+			continue;
+		if (stat.flags & BCM43xx_TXSTAT_FLAG_INTER)
 			continue;
-		if (!(stat.flags & BCM43xx_TXSTAT_FLAG_ACK)) {
-			//TODO: packet was not acked (was lost)
-		}
-		//TODO: There are more (unknown) flags to test. see bcm43xx_main.h
 
 		if (bcm43xx_using_pio(bcm))
 			bcm43xx_pio_handle_xmitstatus(bcm, &stat);
@@ -2980,8 +2972,10 @@ static int bcm43xx_chipset_attach(struct
 	err = bcm43xx_pctl_set_crystal(bcm, 1);
 	if (err)
 		goto out;
-	bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
-	bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
+	err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
+	if (err)
+		goto out;
+	err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
 
 out:
 	return err;
@@ -3680,7 +3674,7 @@ static int bcm43xx_read_phyinfo(struct b
 {
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	u16 value;
-	u8 phy_version;
+	u8 phy_analog;
 	u8 phy_type;
 	u8 phy_rev;
 	int phy_rev_ok = 1;
@@ -3688,12 +3682,12 @@ static int bcm43xx_read_phyinfo(struct b
 
 	value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
 
-	phy_version = (value & 0xF000) >> 12;
+	phy_analog = (value & 0xF000) >> 12;
 	phy_type = (value & 0x0F00) >> 8;
 	phy_rev = (value & 0x000F);
 
-	dprintk(KERN_INFO PFX "Detected PHY: Version: %x, Type %x, Revision %x\n",
-		phy_version, phy_type, phy_rev);
+	dprintk(KERN_INFO PFX "Detected PHY: Analog: %x, Type %x, Revision %x\n",
+		phy_analog, phy_type, phy_rev);
 
 	switch (phy_type) {
 	case BCM43xx_PHYTYPE_A:
@@ -3736,7 +3730,7 @@ static int bcm43xx_read_phyinfo(struct b
 		       phy_rev);
 	}
 
-	phy->version = phy_version;
+	phy->analog = phy_analog;
 	phy->type = phy_type;
 	phy->rev = phy_rev;
 	if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
@@ -3778,12 +3772,18 @@ static int bcm43xx_attach_board(struct b
 	}
 	net_dev->base_addr = (unsigned long)bcm->mmio_addr;
 
-	bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
+	err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
 	                          &bcm->board_vendor);
-	bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
+	if (err)
+		goto err_iounmap;
+	err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
 	                          &bcm->board_type);
-	bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
+	if (err)
+		goto err_iounmap;
+	err = bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
 	                          &bcm->board_revision);
+	if (err)
+		goto err_iounmap;
 
 	err = bcm43xx_chipset_attach(bcm);
 	if (err)
@@ -3874,6 +3874,7 @@ err_pci_release:
 	pci_release_regions(pci_dev);
 err_pci_disable:
 	pci_disable_device(pci_dev);
+	printk(KERN_ERR PFX "Unable to attach board\n");
 	goto out;
 }
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index 52ce2a9..3a5c9c2 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -205,8 +205,8 @@ static void bcm43xx_phy_init_pctl(struct
 	    (bcm->board_type == 0x0416))
 		return;
 
-	bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
 	bcm43xx_phy_write(bcm, 0x0028, 0x8018);
+	bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
 
 	if (phy->type == BCM43xx_PHYTYPE_G) {
 		if (!phy->connected)
@@ -317,6 +317,13 @@ static void bcm43xx_phy_agcsetup(struct 
 	bcm43xx_ilt_write(bcm, offset + 0x0801, 7);
 	bcm43xx_ilt_write(bcm, offset + 0x0802, 16);
 	bcm43xx_ilt_write(bcm, offset + 0x0803, 28);
+
+	if (phy->rev >= 6) {
+		bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
+				  & 0xFFFC));
+		bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
+				  & 0xEFFF));
+	}
 }
 
 static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
@@ -337,7 +344,7 @@ static void bcm43xx_phy_setupg(struct bc
 		for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++)
 			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]);
 		for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
-			bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+			bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
 	} else {
 		/* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
 		bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654);
@@ -377,7 +384,7 @@ static void bcm43xx_phy_setupg(struct bc
 	
 	if (phy->rev == 1) {
 		for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
-			bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+			bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
 		for (i = 0; i < 4; i++) {
 			bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020);
 			bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020);
@@ -500,10 +507,10 @@ static void bcm43xx_phy_setupa(struct bc
 		for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++)
 			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]);
 		for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
-			bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+			bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
 		bcm43xx_phy_init_noisescaletbl(bcm);
 		for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
-			bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+			bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
 		break;
 	case 3:
 		for (i = 0; i < 64; i++)
@@ -729,19 +736,19 @@ static void bcm43xx_phy_initb5(struct bc
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
 	u16 offset;
+	u16 value;
+	u8 old_channel;
 
-	if (phy->version == 1 &&
-	    radio->version == 0x2050) {
+	if (phy->analog == 1)
 		bcm43xx_radio_write16(bcm, 0x007A,
 				      bcm43xx_radio_read16(bcm, 0x007A)
 				      | 0x0050);
-	}
 	if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) &&
 	    (bcm->board_type != 0x0416)) {
+		value = 0x2120;
 		for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
-			bcm43xx_phy_write(bcm, offset,
-					  (bcm43xx_phy_read(bcm, offset) + 0x2020)
-					  & 0x3F3F);
+			bcm43xx_phy_write(bcm, offset, value);
+			value += 0x0202;
 		}
 	}
 	bcm43xx_phy_write(bcm, 0x0035,
@@ -750,7 +757,7 @@ static void bcm43xx_phy_initb5(struct bc
 	if (radio->version == 0x2050)
 		bcm43xx_phy_write(bcm, 0x0038, 0x0667);
 
-	if (phy->connected) {
+	if (phy->type == BCM43xx_PHYTYPE_G) {
 		if (radio->version == 0x2050) {
 			bcm43xx_radio_write16(bcm, 0x007A,
 					      bcm43xx_radio_read16(bcm, 0x007A)
@@ -776,7 +783,7 @@ static void bcm43xx_phy_initb5(struct bc
 				  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
 	}
 
-	if (phy->version == 1 && radio->version == 0x2050) {
+	if (phy->analog == 1) {
 		bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
 		bcm43xx_phy_write(bcm, 0x0021, 0x3763);
 		bcm43xx_phy_write(bcm, 0x0022, 0x1BC3);
@@ -787,14 +794,15 @@ static void bcm43xx_phy_initb5(struct bc
 	bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
 	bcm43xx_write16(bcm, 0x03EC, 0x3F22);
 
-	if (phy->version == 1 && radio->version == 0x2050)
+	if (phy->analog == 1)
 		bcm43xx_phy_write(bcm, 0x0020, 0x3E1C);
 	else
 		bcm43xx_phy_write(bcm, 0x0020, 0x301C);
 
-	if (phy->version == 0)
+	if (phy->analog == 0)
 		bcm43xx_write16(bcm, 0x03E4, 0x3000);
 
+	old_channel = radio->channel;
 	/* Force to channel 7, even if not supported. */
 	bcm43xx_radio_selectchannel(bcm, 7, 0);
 
@@ -816,11 +824,11 @@ static void bcm43xx_phy_initb5(struct bc
 
 	bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007);
 
-	bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+	bcm43xx_radio_selectchannel(bcm, old_channel, 0);
 
 	bcm43xx_phy_write(bcm, 0x0014, 0x0080);
 	bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
-	bcm43xx_phy_write(bcm, 0x88A3, 0x002A);
+	bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
 
 	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
 
@@ -835,61 +843,24 @@ static void bcm43xx_phy_initb6(struct bc
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
 	u16 offset, val;
+	u8 old_channel;
 
 	bcm43xx_phy_write(bcm, 0x003E, 0x817A);
 	bcm43xx_radio_write16(bcm, 0x007A,
 	                      (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058));
-	if ((radio->manufact == 0x17F) &&
-	    (radio->version == 0x2050) &&
-	    (radio->revision == 3 ||
-	     radio->revision == 4 ||
-	     radio->revision == 5)) {
-		bcm43xx_radio_write16(bcm, 0x0051, 0x001F);
-		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
-		bcm43xx_radio_write16(bcm, 0x0053, 0x005B);
-		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+	if (radio->revision == 4 ||
+	     radio->revision == 5) {
+		bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
+		bcm43xx_radio_write16(bcm, 0x0052, 0x0070);
+		bcm43xx_radio_write16(bcm, 0x0053, 0x00B3);
+		bcm43xx_radio_write16(bcm, 0x0054, 0x009B);
 		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
 		bcm43xx_radio_write16(bcm, 0x005B, 0x0088);
 		bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
 		bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
 		bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
 	}
-	if ((radio->manufact == 0x17F) &&
-	    (radio->version == 0x2050) &&
-	    (radio->revision == 6)) {
-		bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
-		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
-		bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
-		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
-		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
-		bcm43xx_radio_write16(bcm, 0x005B, 0x008B);
-		bcm43xx_radio_write16(bcm, 0x005C, 0x00B5);
-		bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
-		bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
-		bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
-		bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
-		bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
-	}
-	if ((radio->manufact == 0x17F) &&
-	    (radio->version == 0x2050) &&
-	    (radio->revision == 7)) {
-		bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
-		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
-		bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
-		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
-		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
-		bcm43xx_radio_write16(bcm, 0x005B, 0x00A8);
-		bcm43xx_radio_write16(bcm, 0x005C, 0x0075);
-		bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
-		bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
-		bcm43xx_radio_write16(bcm, 0x007D, 0x00E8);
-		bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
-		bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
-		bcm43xx_radio_write16(bcm, 0x007B, 0x0000);
-	}
-	if ((radio->manufact == 0x17F) &&
-	    (radio->version == 0x2050) &&
-	    (radio->revision == 8)) {
+	if (radio->revision == 8) {
 		bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
 		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
 		bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
@@ -933,20 +904,26 @@ static void bcm43xx_phy_initb6(struct bc
 		                  bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
 		bcm43xx_phy_write(bcm, 0x042B,
 		                  bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+		bcm43xx_phy_write(bcm, 0x5B, 0x0000);
+		bcm43xx_phy_write(bcm, 0x5C, 0x0000);
 	}
 
-	/* Force to channel 7, even if not supported. */
-	bcm43xx_radio_selectchannel(bcm, 7, 0);
+	old_channel = radio->channel;
+	if (old_channel >= 8)
+		bcm43xx_radio_selectchannel(bcm, 1, 0);
+	else
+		bcm43xx_radio_selectchannel(bcm, 13, 0);
 
 	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
 	bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
 	udelay(40);
-	bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002));
-	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-	if (radio->manufact == 0x17F &&
-	    radio->version == 0x2050 &&
-	    radio->revision <= 2) {
+	if (radio->revision < 6 || radio-> revision == 8) {
+		bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C)
+				      | 0x0002));
 		bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+	}
+	if (radio->revision <= 2) {
+		bcm43xx_radio_write16(bcm, 0x007C, 0x0020);
 		bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
 		bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
 		bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
@@ -954,46 +931,41 @@ static void bcm43xx_phy_initb6(struct bc
 	bcm43xx_radio_write16(bcm, 0x007A,
 	                      (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007);
 
-	bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+	bcm43xx_radio_selectchannel(bcm, old_channel, 0);
 
 	bcm43xx_phy_write(bcm, 0x0014, 0x0200);
-	if (radio->version == 0x2050){
-		if (radio->revision == 3 ||
-		    radio->revision == 4 ||
-		    radio->revision == 5)
-			bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
-		else
-			bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
-	}
+	if (radio->revision >= 6)
+		bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+	else
+		bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
 	bcm43xx_phy_write(bcm, 0x0038, 0x0668);
 	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
-	if (radio->version == 0x2050) {
-		if (radio->revision == 3 ||
-		    radio->revision == 4 ||
-		    radio->revision == 5)
-			bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003);
-		else if (radio->revision <= 2)
-			bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
-	}
+	if (radio->revision <= 5)
+		bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003);
+	if (radio->revision <= 2)
+		bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
 	
-	if (phy->rev == 4)
-		bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
-	else
+	if (phy->analog == 4){
 		bcm43xx_write16(bcm, 0x03E4, 0x0009);
+		bcm43xx_phy_write(bcm, 0x61, bcm43xx_phy_read(bcm, 0x61) & 0xFFF);
+	} else {
+		bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
+	}
+	if (phy->type == BCM43xx_PHYTYPE_G)
+		bcm43xx_write16(bcm, 0x03E6, 0x0);
 	if (phy->type == BCM43xx_PHYTYPE_B) {
 		bcm43xx_write16(bcm, 0x03E6, 0x8140);
 		bcm43xx_phy_write(bcm, 0x0016, 0x0410);
 		bcm43xx_phy_write(bcm, 0x0017, 0x0820);
 		bcm43xx_phy_write(bcm, 0x0062, 0x0007);
 		(void) bcm43xx_radio_calibrationvalue(bcm);
-		bcm43xx_phy_lo_b_measure(bcm);
+		bcm43xx_phy_lo_g_measure(bcm);
 		if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
 			bcm43xx_calc_nrssi_slope(bcm);
 			bcm43xx_calc_nrssi_threshold(bcm);
 		}
 		bcm43xx_phy_init_pctl(bcm);
-	} else
-		bcm43xx_write16(bcm, 0x03E6, 0x0);
+	}
 }
 
 static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
@@ -1063,7 +1035,7 @@ static void bcm43xx_calc_loopback_gain(s
 	bcm43xx_phy_write(bcm, 0x005A, 0x0780);
 	bcm43xx_phy_write(bcm, 0x0059, 0xC810);
 	bcm43xx_phy_write(bcm, 0x0058, 0x000D);
-	if (phy->version == 0) {
+	if (phy->analog == 0) {
 		bcm43xx_phy_write(bcm, 0x0003, 0x0122);
 	} else {
 		bcm43xx_phy_write(bcm, 0x000A,
@@ -1205,27 +1177,30 @@ static void bcm43xx_phy_initg(struct bcm
 	if (phy->rev >= 2) {
 		bcm43xx_phy_write(bcm, 0x0814, 0x0000);
 		bcm43xx_phy_write(bcm, 0x0815, 0x0000);
-		if (phy->rev == 2)
-			bcm43xx_phy_write(bcm, 0x0811, 0x0000);
-		else if (phy->rev >= 3)
-			bcm43xx_phy_write(bcm, 0x0811, 0x0400);
+	}
+	if (phy->rev == 2) {
+		bcm43xx_phy_write(bcm, 0x0811, 0x0000);
 		bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
-		if (phy->connected) {
-			tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
-			if (tmp < 6) {
-				bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
-				bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
-				if (tmp != 3) {
-					bcm43xx_phy_write(bcm, 0x04CC,
-							  (bcm43xx_phy_read(bcm, 0x04CC)
-							   & 0x00FF) | 0x1F00);
-				}
+	}
+	if (phy->rev >= 3) {
+		bcm43xx_phy_write(bcm, 0x0811, 0x0400);
+		bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
+	}
+	if (phy->connected) {
+		tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
+		if (tmp < 6) {
+			bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
+			bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
+			if (tmp != 3) {
+				bcm43xx_phy_write(bcm, 0x04CC,
+						  (bcm43xx_phy_read(bcm, 0x04CC)
+						   & 0x00FF) | 0x1F00);
 			}
 		}
 	}
 	if (phy->rev < 3 && phy->connected)
 		bcm43xx_phy_write(bcm, 0x047E, 0x0078);
-	if (phy->rev >= 6 && phy->rev <= 8) {
+	if (radio->revision == 8) {
 		bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
 		bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
 	}
@@ -1638,14 +1613,14 @@ void bcm43xx_phy_set_baseband_attenuatio
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	u16 value;
 
-	if (phy->version == 0) {
+	if (phy->analog == 0) {
 		value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0);
 		value |= (baseband_attenuation & 0x000F);
 		bcm43xx_write16(bcm, 0x03E6, value);
 		return;
 	}
 
-	if (phy->version > 1) {
+	if (phy->analog > 1) {
 		value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
 		value |= (baseband_attenuation << 2) & 0x003C;
 	} else {
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
index bb9c484..3fbb3c6 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
@@ -1393,11 +1393,12 @@ u16 bcm43xx_radio_init2050(struct bcm43x
 	backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
 
 	// Initialization
-	if (phy->version == 0) {
+	if (phy->analog == 0) {
 		bcm43xx_write16(bcm, 0x03E6, 0x0122);
 	} else {
-		if (phy->version >= 2)
-			bcm43xx_write16(bcm, 0x03E6, 0x0040);
+		if (phy->analog >= 2)
+			bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003)
+					& 0xFFBF) | 0x0040);
 		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
 		                (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000));
 	}
@@ -1405,7 +1406,7 @@ u16 bcm43xx_radio_init2050(struct bcm43x
 	ret = bcm43xx_radio_calibrationvalue(bcm);
 
 	if (phy->type == BCM43xx_PHYTYPE_B)
-		bcm43xx_radio_write16(bcm, 0x0078, 0x0003);
+		bcm43xx_radio_write16(bcm, 0x0078, 0x0026);
 
 	bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);
 	bcm43xx_phy_write(bcm, 0x002B, 0x1403);
@@ -1416,7 +1417,7 @@ u16 bcm43xx_radio_init2050(struct bcm43x
 	                      (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));
 	bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
 	bcm43xx_radio_write16(bcm, 0x0043,
-			      bcm43xx_radio_read16(bcm, 0x0043) | 0x0009);
+			      (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0) | 0x0009);
 	bcm43xx_phy_write(bcm, 0x0058, 0x0000);
 
 	for (i = 0; i < 16; i++) {
@@ -1488,7 +1489,7 @@ u16 bcm43xx_radio_init2050(struct bcm43x
 	bcm43xx_phy_write(bcm, 0x0059, backup[17]);
 	bcm43xx_phy_write(bcm, 0x0058, backup[18]);
 	bcm43xx_write16(bcm, 0x03E6, backup[11]);
-	if (phy->version != 0)
+	if (phy->analog != 0)
 		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);
 	bcm43xx_phy_write(bcm, 0x0035, backup[10]);
 	bcm43xx_radio_selectchannel(bcm, radio->channel, 1);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index a659442..6961be6 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -261,22 +261,22 @@ static int bcm43xx_wx_get_rangeparams(st
 	if (phy->type == BCM43xx_PHYTYPE_A ||
 	    phy->type == BCM43xx_PHYTYPE_G) {
 		range->num_bitrates = 8;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
-		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
 	}
 	if (phy->type == BCM43xx_PHYTYPE_B ||
 	    phy->type == BCM43xx_PHYTYPE_G) {
 		range->num_bitrates += 4;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
-		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
 	}
 
 	geo = ieee80211_get_geo(bcm->ieee);
@@ -286,7 +286,7 @@ static int bcm43xx_wx_get_rangeparams(st
 		if (j == IW_MAX_FREQUENCIES)
 			break;
 		range->freq[j].i = j + 1;
-		range->freq[j].m = geo->a[i].freq;//FIXME?
+		range->freq[j].m = geo->a[i].freq * 100000;
 		range->freq[j].e = 1;
 		j++;
 	}
@@ -294,7 +294,7 @@ static int bcm43xx_wx_get_rangeparams(st
 		if (j == IW_MAX_FREQUENCIES)
 			break;
 		range->freq[j].i = j + 1;
-		range->freq[j].m = geo->bg[i].freq;//FIXME?
+		range->freq[j].m = geo->bg[i].freq * 100000;
 		range->freq[j].e = 1;
 		j++;
 	}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
index 2aed19e..9ecf2bf 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
@@ -137,14 +137,8 @@ struct bcm43xx_xmitstatus {
 	u16 unknown; //FIXME
 };
 
-#define BCM43xx_TXSTAT_FLAG_ACK		0x01
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x02
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x04
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x08
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x10
-#define BCM43xx_TXSTAT_FLAG_IGNORE	0x20
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x40
-//TODO #define BCM43xx_TXSTAT_FLAG_???	0x80
+#define BCM43xx_TXSTAT_FLAG_AMPDU	0x10
+#define BCM43xx_TXSTAT_FLAG_INTER	0x20
 
 u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
 u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);

jwltest-bcm43xx-workqueue-undo.patch:
 bcm43xx.h      |    2 +-
 bcm43xx_main.c |   20 +++++++++-----------
 2 files changed, 10 insertions(+), 12 deletions(-)

--- NEW FILE jwltest-bcm43xx-workqueue-undo.patch ---
--- linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx.h.orig	2007-02-14 17:43:25.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx.h	2007-02-14 17:44:27.000000000 -0500
@@ -818,7 +818,7 @@ struct bcm43xx_private {
 	struct tasklet_struct isr_tasklet;
 
 	/* Periodic tasks */
-	struct delayed_work periodic_work;
+	struct work_struct periodic_work;
 	unsigned int periodic_state;
 
 	struct work_struct restart_work;
--- linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_main.c.orig	2007-02-14 17:43:25.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/bcm43xx/bcm43xx_main.c	2007-02-14 17:44:27.000000000 -0500
@@ -3212,10 +3212,9 @@ static void do_periodic_work(struct bcm4
 	schedule_delayed_work(&bcm->periodic_work, HZ * 15);
 }
 
-static void bcm43xx_periodic_work_handler(struct work_struct *work)
+static void bcm43xx_periodic_work_handler(void *d)
 {
-	struct bcm43xx_private *bcm =
-		container_of(work, struct bcm43xx_private, periodic_work.work);
+	struct bcm43xx_private *bcm = d;
 	struct net_device *net_dev = bcm->net_dev;
 	unsigned long flags;
 	u32 savedirqs = 0;
@@ -3277,11 +3276,11 @@ void bcm43xx_periodic_tasks_delete(struc
 
 void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
 {
-	struct delayed_work *work = &bcm->periodic_work;
+	struct work_struct *work = &(bcm->periodic_work);
 
 	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
-	INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler);
-	schedule_delayed_work(work, 0);
+	INIT_WORK(work, bcm43xx_periodic_work_handler, bcm);
+	schedule_work(work);
 }
 
 static void bcm43xx_security_init(struct bcm43xx_private *bcm)
@@ -3633,7 +3632,7 @@ static int bcm43xx_init_board(struct bcm
 	bcm43xx_periodic_tasks_setup(bcm);
 
 	/*FIXME: This should be handled by softmac instead. */
-	schedule_delayed_work(&bcm->softmac->associnfo.work, 0);
+	schedule_work(&bcm->softmac->associnfo.work);
 
 out:
 	mutex_unlock(&(bcm)->mutex);
@@ -4187,10 +4186,9 @@ static void __devexit bcm43xx_remove_one
 /* Hard-reset the chip. Do not call this directly.
  * Use bcm43xx_controller_restart()
  */
-static void bcm43xx_chip_reset(struct work_struct *work)
+static void bcm43xx_chip_reset(void *_bcm)
 {
-	struct bcm43xx_private *bcm =
-		container_of(work, struct bcm43xx_private, restart_work);
+	struct bcm43xx_private *bcm = _bcm;
 	struct bcm43xx_phyinfo *phy;
 	int err = -ENODEV;
 
@@ -4217,7 +4215,7 @@ void bcm43xx_controller_restart(struct b
 	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
 		return;
 	printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
-	INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset);
+	INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
 	schedule_work(&bcm->restart_work);
 }
 

jwltest-iwlwifi-2_6_19-fixup.patch:
 base.c    |  128 +++++++++++++++++++++++++++++++-------------------------------
 iwlwifi.h |   14 +++---
 2 files changed, 71 insertions(+), 71 deletions(-)

--- NEW FILE jwltest-iwlwifi-2_6_19-fixup.patch ---
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/iwlwifi/base.c.orig	2007-02-27 19:28:00.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/iwlwifi/base.c	2007-02-27 19:28:13.000000000 -0500
@@ -253,12 +253,12 @@ static void ipw_rx_queue_free(struct ipw
 static void ipw_rx_queue_replenish(struct ipw_priv *priv);
 
 static int ipw_up(struct ipw_priv *);
-static void ipw_bg_up(struct work_struct *work);
+static void ipw_bg_up(void *p);
 static void ipw_down(struct ipw_priv *);
-static void ipw_bg_down(struct work_struct *work);
+static void ipw_bg_down(void *p);
 
 static int ipw_card_show_info(struct ipw_priv *priv);
-static void ipw_bg_alive_start(struct work_struct *work);
+static void ipw_bg_alive_start(void *p);
 static int ipw_send_card_state(struct ipw_priv *priv, u32 flags, u8 meta_flag);
 
 static void ipw_link_down(struct ipw_priv *priv);
@@ -1409,9 +1409,9 @@ static void ipw_setup_activity_timer(str
 			   IPW_ACTIVITY_PERIOD);
 }
 
-static void ipw_bg_activity_timer(struct work_struct *work)
+static void ipw_bg_activity_timer(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, activity_timer.work);
+	struct ipw_priv *priv = p;
 
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
@@ -3219,9 +3219,9 @@ static void reg_txpower_periodic(struct 
 			   &priv->thermal_periodic, REG_RECALIB_PERIOD * HZ);
 }
 
-static void ipw_bg_reg_txpower_periodic(struct work_struct *work)
+static void ipw_bg_reg_txpower_periodic(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, thermal_periodic.work);
+	struct ipw_priv *priv = p;
 
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
@@ -3560,9 +3560,9 @@ static void ipw_connection_init_rx_confi
 
 #define IPW_SCAN_CHECK_WATCHDOG (7 * HZ)
 
-static void ipw_bg_scan_check(struct work_struct *work)
+static void ipw_bg_scan_check(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, scan_check.work);
+	struct ipw_priv *priv = p;
 
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
@@ -4589,9 +4589,9 @@ static void ipw_init_geos(struct ipw_pri
 
 static int ipw_commit_rxon(struct ipw_priv *priv);
 
-static void ipw_bg_post_associate(struct work_struct *work)
+static void ipw_bg_post_associate(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, post_associate);
+	struct ipw_priv *priv = p;
 	struct ieee80211_conf *conf = NULL;
 
 	if (priv->status & STATUS_EXIT_PENDING)
@@ -4877,9 +4877,9 @@ static void ipw_rx_queue_replenish(struc
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static void ipw_bg_rx_queue_replenish(struct work_struct *work)
+static void ipw_bg_rx_queue_replenish(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, rx_replenish);
+	struct ipw_priv *priv = p;
 
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
@@ -6192,9 +6192,9 @@ static u8 ipw_sync_station(struct ipw_pr
 	return IPW_INVALID_STATION;
 }
 
-static void ipw_bg_scan_completed(struct work_struct *work)
+static void ipw_bg_scan_completed(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, scan_completed);
+	struct ipw_priv *priv = p;
 
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
@@ -6483,9 +6483,9 @@ static void ipw_gather_stats(struct ipw_
 			   IPW_STATS_INTERVAL);
 }
 
-static void ipw_bg_gather_stats(struct work_struct *work)
+static void ipw_bg_gather_stats(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, gather_stats.work);
+	struct ipw_priv *priv = p;
 
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
@@ -6723,7 +6723,7 @@ static int ipw_get_channels_for_scan(str
 	return added;
 }
 
-static void ipw_bg_request_scan(struct work_struct *work)
+static void ipw_bg_request_scan(void *p)
 {
 
 	struct ipw_host_cmd cmd = {
@@ -6731,7 +6731,7 @@ static void ipw_bg_request_scan(struct w
 		.len = sizeof(struct ipw_scan_cmd),
 		.meta.flags = CMD_SIZE_HUGE,
 	};
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, request_scan.work);
+	struct ipw_priv *priv = p;
 	int rc = 0;
 	struct ipw_scan_cmd *scan;
 	struct ieee80211_hw_mode *hw_mode = NULL;
@@ -6921,9 +6921,9 @@ static void ipw_bg_request_scan(struct w
 	mutex_unlock(&priv->mutex);
 }
 
-static void ipw_bg_abort_scan(struct work_struct *work)
+static void ipw_bg_abort_scan(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, abort_scan);
+	struct ipw_priv *priv = p;
 
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
@@ -7058,18 +7058,18 @@ static void ipw_qos_activate(struct ipw_
 */	}
 }
 
-static void ipw_bg_qos_activate(struct work_struct *work)
+static void ipw_bg_qos_activate(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, qos_activate);
+	struct ipw_priv *priv = p;
 
 	mutex_lock(&priv->mutex);
 	ipw_qos_activate(priv, 0);
 	mutex_unlock(&priv->mutex);
 }
 
-static void ipw_bg_report_work(struct work_struct *work)
+static void ipw_bg_report_work(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, report_work);
+	struct ipw_priv *priv = p;
 
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
@@ -9302,9 +9302,9 @@ static irqreturn_t ipw_isr(int irq, void
 	return IRQ_NONE;
 }
 
-static void ipw_bg_rf_kill(struct work_struct *work)
+static void ipw_bg_rf_kill(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, rf_kill);
+	struct ipw_priv *priv = p;
 
 	wake_up_interruptible(&priv->wait_command_queue);
 
@@ -9369,9 +9369,9 @@ static void ipw_link_up(struct ipw_priv 
 		ipw_scan_initiate(priv, 1000);
 }
 
-static void ipw_bg_update_link_led(struct work_struct *work)
+static void ipw_bg_update_link_led(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, update_link_led);
+	struct ipw_priv *priv = p;
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
 
@@ -9379,9 +9379,9 @@ static void ipw_bg_update_link_led(struc
 	ipw_update_link_led(priv);
 	mutex_unlock(&priv->mutex);
 }
-static void ipw_bg_link_up(struct work_struct *work)
+static void ipw_bg_link_up(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, link_up);
+	struct ipw_priv *priv = p;
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
 
@@ -9408,9 +9408,9 @@ static void ipw_link_down(struct ipw_pri
 		return;
 
 }
-static void ipw_bg_link_down(struct work_struct *work)
+static void ipw_bg_link_down(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, link_down);
+	struct ipw_priv *priv = p;
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
 
@@ -9419,9 +9419,9 @@ static void ipw_bg_link_down(struct work
 	mutex_unlock(&priv->mutex);
 }
 
-static void ipw_bg_resume_work(struct work_struct *work)
+static void ipw_bg_resume_work(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, resume_work.work);
+	struct ipw_priv *priv = p;
 	unsigned long flags;
 
 	mutex_lock(&priv->mutex);
@@ -9473,9 +9473,9 @@ static void ipw_bg_resume_work(struct wo
 }
 
 #if 0
-static void ipw_associate_timeout(struct work_struct *work)
+static void ipw_associate_timeout(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, associate_timeout.work);
+	struct ipw_priv *priv = p;
 
 	mutex_lock(&priv->mutex);
 
@@ -9520,32 +9520,32 @@ static void ipw_setup_deferred_work(stru
 
 	init_waitqueue_head(&priv->wait_command_queue);
 
-	INIT_WORK(&priv->scan_completed, ipw_bg_scan_completed);
-	INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish);
-	INIT_WORK(&priv->rf_kill, ipw_bg_rf_kill);
-	INIT_WORK(&priv->up, ipw_bg_up);
-	INIT_WORK(&priv->down, ipw_bg_down);
-	INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan);
-	INIT_WORK(&priv->link_up, ipw_bg_link_up);
-	INIT_WORK(&priv->update_link_led, ipw_bg_update_link_led);
-	INIT_WORK(&priv->link_down, ipw_bg_link_down);
-//	INIT_WORK(&priv->associate_timeout, ipw_associate_timeout);
-
-	INIT_DELAYED_WORK(&priv->alive_start, ipw_bg_alive_start);
-	INIT_DELAYED_WORK(&priv->scan_check, ipw_bg_scan_check);
-	INIT_DELAYED_WORK(&priv->request_scan, ipw_bg_request_scan);
-	INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats);
-	INIT_DELAYED_WORK(&priv->activity_timer, ipw_bg_activity_timer);
-	INIT_DELAYED_WORK(&priv->thermal_periodic, ipw_bg_reg_txpower_periodic);
-	INIT_DELAYED_WORK(&priv->resume_work, ipw_bg_resume_work);
+	INIT_WORK(&priv->scan_completed, ipw_bg_scan_completed, priv);
+	INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish, priv);
+	INIT_WORK(&priv->rf_kill, ipw_bg_rf_kill, priv);
+	INIT_WORK(&priv->up, ipw_bg_up, priv);
+	INIT_WORK(&priv->down, ipw_bg_down, priv);
+	INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan, priv);
+	INIT_WORK(&priv->link_up, ipw_bg_link_up, priv);
+	INIT_WORK(&priv->update_link_led, ipw_bg_update_link_led, priv);
+	INIT_WORK(&priv->link_down, ipw_bg_link_down, priv);
+//	INIT_WORK(&priv->associate_timeout, ipw_associate_timeout, priv);
+
+	INIT_WORK(&priv->alive_start, ipw_bg_alive_start, priv);
+	INIT_WORK(&priv->scan_check, ipw_bg_scan_check, priv);
+	INIT_WORK(&priv->request_scan, ipw_bg_request_scan, priv);
+	INIT_WORK(&priv->gather_stats, ipw_bg_gather_stats, priv);
+	INIT_WORK(&priv->activity_timer, ipw_bg_activity_timer, priv);
+	INIT_WORK(&priv->thermal_periodic, ipw_bg_reg_txpower_periodic, priv);
+	INIT_WORK(&priv->resume_work, ipw_bg_resume_work, priv);
 
 	/* QoS */
-	INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate);
+	INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate, priv);
 
 	/* 802.11h */
-	INIT_WORK(&priv->report_work, ipw_bg_report_work);
+	INIT_WORK(&priv->report_work, ipw_bg_report_work, priv);
 
-	INIT_WORK(&priv->post_associate, ipw_bg_post_associate);
+	INIT_WORK(&priv->post_associate, ipw_bg_post_associate, priv);
 
 	init_timer(&priv->rate_scale_flush);
 	priv->rate_scale_flush.data = (unsigned long)priv;
@@ -9712,9 +9712,9 @@ static int ipw_card_remove_notify(struct
  * this function starts the calibration then start the process
  * of transferring the card to receiving state
  */
-static void ipw_bg_alive_start(struct work_struct *work)
+static void ipw_bg_alive_start(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, alive_start.work);
+	struct ipw_priv *priv = p;
 	int rc = 0;
 	int thermal_spin = 0;
 
@@ -9896,9 +9896,9 @@ static int ipw_up(struct ipw_priv *priv)
 	return -EIO;
 }
 
-static void ipw_bg_up(struct work_struct *work)
+static void ipw_bg_up(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, up);
+	struct ipw_priv *priv = p;
 
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
@@ -10005,9 +10005,9 @@ static void ipw_down(struct ipw_priv *pr
 
 }
 
-static void ipw_bg_down(struct work_struct *work)
+static void ipw_bg_down(void *p)
 {
-	struct ipw_priv *priv = container_of(work, struct ipw_priv, down);
+	struct ipw_priv *priv = p;
 
 	if (priv->status & STATUS_EXIT_PENDING)
 		return;
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/iwlwifi/iwlwifi.h.orig	2007-02-27 19:28:00.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/iwlwifi/iwlwifi.h	2007-02-27 19:28:13.000000000 -0500
@@ -1195,13 +1195,13 @@ struct ipw_priv {
 
 	struct tasklet_struct irq_tasklet;
 
-	struct delayed_work alive_start;
-	struct delayed_work activity_timer;
-	struct delayed_work request_scan;
-	struct delayed_work thermal_periodic;
-	struct delayed_work gather_stats;
-	struct delayed_work scan_check;
-	struct delayed_work resume_work;
+	struct work_struct alive_start;
+	struct work_struct activity_timer;
+	struct work_struct request_scan;
+	struct work_struct thermal_periodic;
+	struct work_struct gather_stats;
+	struct work_struct scan_check;
+	struct work_struct resume_work;
 
 #define IPW_DEFAULT_TX_POWER 0x0F
 	s8 user_txpower_limit;

jwltest-iwlwifi.patch:
 Kconfig              |    1 
 Makefile             |    1 
 iwlwifi/Kconfig      |    3 
 iwlwifi/Makefile     |    2 
 iwlwifi/base.c       |12985 +++++++++++++++++++++++++++++++++++++++++++++++++++
 iwlwifi/iwlwifi.h    | 1308 +++++
 iwlwifi/iwlwifi_hw.h | 1875 +++++++
 7 files changed, 16175 insertions(+)

--- NEW FILE jwltest-iwlwifi.patch ---
--- /dev/null	2006-11-15 09:57:50.578980680 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/iwlwifi/base.c	2007-02-27 18:11:56.000000000 -0500
@@ -0,0 +1,12985 @@
+/******************************************************************************
+
+  Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
+
+  Portions of this file are derived from the ipw3945 project, as well
+  as portions of the ieee80211 subsystem header files.
+
+  802.11 status code portion of this file from ethereal-0.10.6:
+    Copyright 2000, Axis Communications AB
+    Ethereal - Network traffic analyzer
+    By Gerald Combs <gerald at ethereal.com>
+    Copyright 1998 Gerald Combs
+
+  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.
+
+  Contact Information:
+  James P. Ketrenos <ipw2100-admin at linux.intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+
+/*
+ * Theory of operation:
+ *
+ * The primary NIC mode of operation is configured within the RXON command.
+ * As such, there are two instances of RXON data -- staging_rxon and
+ * active_rxon.  The former is used to configure the device, the later to
+ * reflect the actual currently active configuration.
+ *
+ * After configuring staging_rxon, it is activated by calling
+ * ipw_commit_rxon(). The ipw_commit_rxon() will ensure the correct sequence
+ * of commands are invoked on the hardware to result in Tx being possible
+ * (if the channel is appropriate for Tx)
+ *
+ * About the threading and lock model of the driver...
+ *
+ * There are three paths of execution through the driver.
+ *
+ * 1.  ioctl based (wireless extensions, netdev, etc.)
+ * 2.  interrupt based
+ * 3.  scheduled work queue items
+ *
+ * As soon as an interrupt comes in, it schedules a tasklet.  That tasklet,
+ * when run, does any HW checks, pulls any data from the read queue,
+ * and schedules other layers to do the actual work.
+ *
+ * NOTE: This driver is a work in progress.  It is currently structured
+ * in a way that we can add support for the next wireless adapter
+ * available from Intel.
+ *
+ * Our current focus is as follows:
+ * 1.  Get the driver working w/ mac80211 in STA(client) mode.
+ * 2.  Clean up the dual-driver code from function redirection to
+ *     if/else switches where the code detlas are minimal.
+ * 3.  Evaluate the amount of delta between the hardware versions and
+ *     possibly split iwlwifi into multiple drivers for each piece of
+ *     HW, sharing as much base code as possible (would result in
+ *     multiple driver files on disk vs. a single module that works
+ *     with multiple hardware types)
+ * 4.  Document the uCode regulatory enforcement
+ * 5.  Document the rate scaling capabilities of the 3945
+ * 6.  Provide an initial rate scaling algorithm tailored for the
+ *     statistic data exposed by the 3945.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <net/iw_handler.h>
+
+//#define BIT(x) (1 << (x))
+#include <net/mac80211.h>
+#include <net/ieee80211.h>
+
+//#include <net/mac80211_mgmt.h>
+//#include <net/mac80211_common.h>
+//#include <net/mac80211_shared.h>
+#include <../net/mac80211/ieee80211_rate.h>
+
+#include <linux/if_arp.h>
+#include <asm/div64.h>
+
+#include "iwlwifi.h"
+
+#define IWLWIFI_VERSION "0.0.9k"
+
+#define DRV_DESCRIPTION	"Intel(R) Wireless Link driver for Linux"
+#define DRV_COPYRIGHT	"Copyright(c) 2003-2006 Intel Corporation"
+#define DRV_VERSION     IWLWIFI_VERSION
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+/*MAC80211  move this to mac80211 files */
+#define IEEE80211_FC(type, stype) cpu_to_le16((type << 2) | (stype << 4))
+
+#define IEEE80211_CHAN_W_RADAR_DETECT 0x00000010
+
+#define IEEE80211_24GHZ_BAND     (1<<0)
+#define IEEE80211_52GHZ_BAND     (1<<1)
+
+#define IEEE80211_CCK_RATE_1MB                  0x02
+#define IEEE80211_CCK_RATE_2MB                  0x04
+#define IEEE80211_CCK_RATE_5MB                  0x0B
+#define IEEE80211_CCK_RATE_11MB                 0x16
+#define IEEE80211_OFDM_RATE_6MB                 0x0C
+#define IEEE80211_OFDM_RATE_9MB                 0x12
+#define IEEE80211_OFDM_RATE_12MB                0x18
+#define IEEE80211_OFDM_RATE_18MB                0x24
+#define IEEE80211_OFDM_RATE_24MB                0x30
+#define IEEE80211_OFDM_RATE_36MB                0x48
+#define IEEE80211_OFDM_RATE_48MB                0x60
+#define IEEE80211_OFDM_RATE_54MB                0x6C
+#define IEEE80211_BASIC_RATE_MASK               0x80
+
+#define IEEE80211_CCK_RATE_1MB_MASK             (1<<0)
+#define IEEE80211_CCK_RATE_2MB_MASK             (1<<1)
+#define IEEE80211_CCK_RATE_5MB_MASK             (1<<2)
+#define IEEE80211_CCK_RATE_11MB_MASK            (1<<3)
+#define IEEE80211_OFDM_RATE_6MB_MASK            (1<<4)
+#define IEEE80211_OFDM_RATE_9MB_MASK            (1<<5)
+#define IEEE80211_OFDM_RATE_12MB_MASK           (1<<6)
+#define IEEE80211_OFDM_RATE_18MB_MASK           (1<<7)
+#define IEEE80211_OFDM_RATE_24MB_MASK           (1<<8)
+#define IEEE80211_OFDM_RATE_36MB_MASK           (1<<9)
+#define IEEE80211_OFDM_RATE_48MB_MASK           (1<<10)
+#define IEEE80211_OFDM_RATE_54MB_MASK           (1<<11)
+
+#define IEEE80211_CCK_RATES_MASK                0x0000000F
+#define IEEE80211_CCK_BASIC_RATES_MASK  (IEEE80211_CCK_RATE_1MB_MASK | \
+        IEEE80211_CCK_RATE_2MB_MASK)
+#define IEEE80211_CCK_DEFAULT_RATES_MASK        (IEEE80211_CCK_BASIC_RATES_MASK | \
+        IEEE80211_CCK_RATE_5MB_MASK | \
+        IEEE80211_CCK_RATE_11MB_MASK)
+
+#define IEEE80211_OFDM_RATES_MASK               0x00000FF0
+#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \
+        IEEE80211_OFDM_RATE_12MB_MASK | \
+        IEEE80211_OFDM_RATE_24MB_MASK)
+#define IEEE80211_OFDM_DEFAULT_RATES_MASK       (IEEE80211_OFDM_BASIC_RATES_MASK | \
+        IEEE80211_OFDM_RATE_9MB_MASK  | \
+        IEEE80211_OFDM_RATE_18MB_MASK | \
+        IEEE80211_OFDM_RATE_36MB_MASK | \
+        IEEE80211_OFDM_RATE_48MB_MASK | \
+        IEEE80211_OFDM_RATE_54MB_MASK)
+#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
+                                IEEE80211_CCK_DEFAULT_RATES_MASK)
+
+#define IEEE80211_NUM_OFDM_RATES            8
+#define IEEE80211_NUM_CCK_RATES             4
+#define IEEE80211_OFDM_SHIFT_MASK_A         4
+
+/*MAC80211 end */
+
+static u32 ipw_debug_level;
+
+static int param_debug = 0;
+static int param_channel = 0;
+static int param_mode = 0;
+static int param_auto_create = 1;	/* def: create new adhoc network if needed */
+static int param_led = 1;	/* def: use LEDs */
+static int param_disable = 0;	/* def: enable radio */
+static int param_antenna = 0;	/* def: 0 = both antennas (use diversity) */
+static int param_hwcrypto = 0;	/* def: using software encryption */
+static int param_qos_enable = 1;
+
+static const char ipw_modes[] = {
+	'a', 'b', 'g', '?'
+};
+
+#define LD_TIME_LINK_ON 300
+
+static int ipw_power_init_handle(struct ipw_priv *priv);
[...15803 lines suppressed...]
+	u8 flags;
+	/* We have 15 LSB to use as we please (MSB indicates
+	 * a frame Rx'd from the HW).  We encode the following
+	 * information into the sequence field:
+	 *
+	 *  0:7    index in fifo
+	 *  8:13   fifo selection
+	 * 14:14   bit indicating if this packet references the 'extra'
+	 *         storage at the end of the memory queue
+	 * 15:15   (Rx indication)
+	 *
+	 */
+	u16 sequence;
+
+	/* command data follows immediately */
+	u8 data[0];
+} __attribute__ ((packed));
+
+// Used for passing to driver number of successes and failures per rate
+struct rate_histogram {
+	union {
+		u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+		u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+		u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+	} success;
+	union {
+		u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+		u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+		u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+	} failed;
+} __attribute__ ((packed));
+
+/* statistics command response */
+
+struct statistics_rx_phy {
+	u32 ina_cnt;
+	u32 fina_cnt;
+	u32 plcp_err;
+	u32 crc32_err;
+	u32 overrun_err;
+	u32 early_overrun_err;
+	u32 crc32_good;
+	u32 false_alarm_cnt;
+	u32 fina_sync_err_cnt;
+	u32 sfd_timeout;
+	u32 fina_timeout;
+	u32 unresponded_rts;
+	u32 rxe_frame_limit_overrun;
+	u32 sent_ack_cnt;
+	u32 sent_cts_cnt;
+} __attribute__ ((packed));
+
+struct statistics_rx {
+	struct statistics_rx_phy ofdm;
+	struct statistics_rx_phy cck;
+	u32 bogus_cts;
+	u32 bogus_ack;
+	u32 non_bssid_frames;
+	u32 filtered_frames;
+	u32 non_channel_beacons;
+} __attribute__ ((packed));
+
+struct statistics_tx {
+	u32 preamble_cnt;
+	u32 rx_detected_cnt;
+	u32 bt_prio_defer_cnt;
+	u32 bt_prio_kill_cnt;
+	u32 few_bytes_cnt;
+	u32 cts_timeout;
+	u32 ack_timeout;
+	u32 expected_ack_cnt;
+	u32 actual_ack_cnt;
+} __attribute__ ((packed));
+
+struct statistics_dbg {
+	u32 burst_check;
+	u32 burst_count;
+	u32 reserved[4];
+} __attribute__ ((packed));
+
+struct statistics_div {
+	u32 tx_on_a;
+	u32 tx_on_b;
+	u32 exec_time;
+	u32 probe_time;
+} __attribute__ ((packed));
+
+struct statistics_general {
+	u32 temperature;
+	struct statistics_dbg dbg;
+	u32 sleep_time;
+	u32 slots_out;
+	u32 slots_idle;
+	u32 ttl_timestamp;
+	struct statistics_div div;
+} __attribute__ ((packed));
+
+struct ipw_notif_statistics {
+	u32 flag;
+	struct statistics_rx rx;
+	struct statistics_tx tx;
+	struct statistics_general general;
+} __attribute__ ((packed));
+
+struct ipw_rx_packet {
+	u32 len;
+	struct ipw_cmd_header hdr;
+	union {
+		struct ipw_alive_resp alive_frame;
+		struct ipw_rx_frame rx_frame;
+		struct ipw_tx_resp tx_resp;
+		struct ipw_spectrum_notification spectrum_notif;
+		struct ipw_csa_notification csa_notif;
+		struct ipw_error_resp err_resp;
+		struct ipw_card_state_notif card_state_notif;
+		struct ipw_notif_statistics stats;
+		struct BeaconNtfSpecifics beacon_status;
+		struct ipw_add_sta_resp add_sta;
+		struct ipw_sleep_notification sleep_notif;
+		u32 status;
+		u8 raw[0];
+	} u;
+} __attribute__ ((packed));
+
+#define IPW_RX_FRAME_SIZE        (4 + sizeof(struct ipw_rx_frame))
+
+struct ipw_multicast_addr {
+	u8 num_of_multicast_addresses;
+	u8 reserved[3];
+	u8 mac1[6];
+	u8 mac2[6];
+	u8 mac3[6];
+	u8 mac4[6];
+} __attribute__ ((packed));
+
+struct ipw_tgi_tx_key {
+	u8 key_id;
+	u8 security_type;
+	u8 station_index;
+	u8 flags;
+	u8 key[16];
+	u32 tx_counter[2];
+} __attribute__ ((packed));
+
+struct ipw_associate {
+	u8 channel;
+	u8 auth_type:4, auth_key:4;
+	u8 assoc_type;
+	u8 reserved;
+	u16 policy_support;
+	u8 preamble_length;
+	u8 ieee_mode;
+	u8 bssid[ETH_ALEN];
+	u32 assoc_tsf_msw;
+	u32 assoc_tsf_lsw;
+	u16 capability;
+	u16 listen_interval;
+	u16 beacon_interval;
+	u8 dest[ETH_ALEN];
+	u16 atim_window;
+	u8 smr;
+	u8 reserved1;
+	u16 reserved2;
+	u16 assoc_id;
+	u8 erp_value;
+} __attribute__ ((packed));
+
+#define IPW_SUPPORTED_RATES_IE_LEN         8
+
+struct ipw_supported_rates {
+	u8 ieee_mode;
+	u8 num_rates;
+	u8 purpose;
+	u8 reserved;
+	u8 supported_rates[IPW_MAX_RATES];
+} __attribute__ ((packed));
+
+struct ipw_channel_tx_power {
+	u8 channel_number;
+	s8 tx_power;
+} __attribute__ ((packed));
+
+
+#define IPW_RX_BUF_SIZE 3000
+
+#endif				/* __iwlwifi_hw_h__ */
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/Makefile.orig	2007-02-27 17:55:19.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/Makefile	2007-02-27 18:11:56.000000000 -0500
@@ -4,3 +4,4 @@ obj-$(CONFIG_ADM8211)		+= adm8211/
 obj-$(CONFIG_P54_COMMON)	+= p54/
 obj-$(CONFIG_ZD1211RW_MAC80211)	+= zd1211rw/
 obj-$(CONFIG_RTL818X)		+= rtl818x/
+obj-$(CONFIG_IWLWIFI)		+= iwlwifi/
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/Kconfig.orig	2007-02-27 17:55:19.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/Kconfig	2007-02-27 18:11:56.000000000 -0500
@@ -4,3 +4,4 @@ source "drivers/net/wireless/mac80211/ad
 source "drivers/net/wireless/mac80211/p54/Kconfig"
 source "drivers/net/wireless/mac80211/zd1211rw/Kconfig"
 source "drivers/net/wireless/mac80211/rtl818x/Kconfig"
+source "drivers/net/wireless/mac80211/iwlwifi/Kconfig"

jwltest-mac80211-backport-2_6_19-fixup.patch:
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx.h      |    2 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_main.c |   20 +--
 drivers/net/wireless/mac80211/rt2x00/rt2400pci.c     |   65 ++++-------
 drivers/net/wireless/mac80211/rt2x00/rt2400pci.h     |    6 -
 drivers/net/wireless/mac80211/rt2x00/rt2500pci.c     |   65 ++++-------
 drivers/net/wireless/mac80211/rt2x00/rt2500pci.h     |    6 -
 drivers/net/wireless/mac80211/rt2x00/rt2500usb.c     |   65 ++++-------
 drivers/net/wireless/mac80211/rt2x00/rt2500usb.h     |    6 -
 drivers/net/wireless/mac80211/rt2x00/rt2x00.h        |    8 -
 drivers/net/wireless/mac80211/rt2x00/rt61pci.c       |   65 ++++-------
 drivers/net/wireless/mac80211/rt2x00/rt61pci.h       |    6 -
 drivers/net/wireless/mac80211/rt2x00/rt73usb.c       |   65 ++++-------
 drivers/net/wireless/mac80211/rt2x00/rt73usb.h       |    6 -
 drivers/net/wireless/mac80211/zd1211rw/zd_mac.c      |   14 +-
 drivers/net/wireless/mac80211/zd1211rw/zd_mac.h      |    2 
 net/mac80211/ieee80211.c                             |    7 -
 net/mac80211/ieee80211_i.h                           |    6 -
 net/mac80211/ieee80211_iface.c                       |    2 
 net/mac80211/ieee80211_sta.c                         |  100 +----------------
 net/mac80211/ieee80211_sysfs.c                       |  111 +++++++++----------
 net/mac80211/ieee80211_sysfs_sta.c                   |    2 
 net/mac80211/sta_info.c                              |    7 -
 net/mac80211/wep.c                                   |    1 
 net/mac80211/wme.c                                   |    5 
 net/wireless/nl80211.c                               |    3 
 25 files changed, 253 insertions(+), 392 deletions(-)

--- NEW FILE jwltest-mac80211-backport-2_6_19-fixup.patch ---
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/bcm43xx/bcm43xx.h.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/bcm43xx/bcm43xx.h	2007-02-27 17:26:17.000000000 -0500
@@ -742,7 +742,7 @@ struct bcm43xx_wldev {
 	struct tasklet_struct isr_tasklet;
 
 	/* Periodic tasks */
-	struct delayed_work periodic_work;
+	struct work_struct periodic_work;
 	unsigned int periodic_state;
 
 	struct work_struct restart_work;
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/bcm43xx/bcm43xx_main.c.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/bcm43xx/bcm43xx_main.c	2007-02-27 17:26:17.000000000 -0500
@@ -2284,10 +2284,9 @@ static int estimate_periodic_work_badnes
 	return badness;
 }
 
-static void bcm43xx_periodic_work_handler(struct work_struct *work)
+static void bcm43xx_periodic_work_handler(void *d)
 {
-	struct bcm43xx_wldev *dev =
-		container_of(work, struct bcm43xx_wldev, periodic_work.work);
+	struct bcm43xx_wldev *dev = d;
 	unsigned long flags;
 	u32 savedirqs = 0;
 	int badness;
@@ -2336,12 +2335,12 @@ static void bcm43xx_periodic_tasks_delet
 
 static void bcm43xx_periodic_tasks_setup(struct bcm43xx_wldev *dev)
 {
-	struct delayed_work *work = &dev->periodic_work;
+	struct work_struct *work = &(dev->periodic_work);
 
 	assert(bcm43xx_status(dev) == BCM43xx_STAT_INITIALIZED);
 	dev->periodic_state = 0;
-	INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler);
-	schedule_delayed_work(work, 0);
+	INIT_WORK(work, bcm43xx_periodic_work_handler, dev);
+	schedule_work(work);
 }
 
 /* Validate access to the chip (SHM) */
@@ -3425,12 +3424,11 @@ static const struct ieee80211_ops bcm43x
 /* Hard-reset the chip. Do not call this directly.
  * Use bcm43xx_controller_restart()
  */
-static void bcm43xx_chip_reset(struct work_struct *work)
+static void bcm43xx_chip_reset(void *d)
 {
-	struct bcm43xx_wldev *dev =
-		container_of(work, struct bcm43xx_wldev, restart_work);
+	struct bcm43xx_wldev *dev = d;
 	struct bcm43xx_wl *wl = dev->wl;
-	int err;
+	int err = 0;
 	int was_started = 0;
 	int was_inited = 0;
 
@@ -3630,7 +3628,7 @@ static int bcm43xx_wireless_core_attach(
 	/* Now set some default "current_dev" */
 	if (!wl->current_dev)
 		wl->current_dev = dev;
-	INIT_WORK(&dev->restart_work, bcm43xx_chip_reset);
+	INIT_WORK(&dev->restart_work, bcm43xx_chip_reset, dev);
 
 	bcm43xx_radio_turn_off(dev);
 	bcm43xx_switch_analog(dev, 0);
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2500pci.h.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2500pci.h	2007-02-27 17:26:17.000000000 -0500
@@ -1226,9 +1226,9 @@ static void rt2500pci_disable_radio(stru
 /*
  * Interrupt functions.
  */
-static void rt2500pci_beacondone(struct work_struct *work);
-static void rt2500pci_rxdone(struct work_struct *work);
-static void rt2500pci_txdone(struct work_struct *work);
+static void rt2500pci_beacondone(void *data);
+static void rt2500pci_rxdone(void *data);
+static void rt2500pci_txdone(void *data);
 static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance);
 
 #endif /* RT2500PCI_H */
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c	2007-02-27 17:26:17.000000000 -0500
@@ -724,12 +724,9 @@ static void rt2500usb_config_mac_address
 /*
  * Link tuning
  */
-static void rt2500usb_link_tuner(struct work_struct *work)
+static void rt2500usb_link_tuner(void *data)
 {
-	struct link *link =
-		container_of(work, struct link, work.work);
-	struct rt2x00_dev *rt2x00dev =
-		container_of(link, struct rt2x00_dev, link);
+	struct rt2x00_dev *rt2x00dev = data;
 	u16 reg;
 	u32 rssi;
 	u8 reg_r17;
@@ -905,7 +902,7 @@ static int rt2500usb_set_state(struct rt
  * Initialization functions.
  */
 static int rt2500usb_alloc_dma_ring(struct rt2x00_dev *rt2x00dev,
-	enum ring_index ring_type, void (*handler)(struct work_struct *),
+	enum ring_index ring_type, void (*handler)(void *),
 	const u16 max_entries, const u16 data_size, const u16 desc_size)
 {
 	struct data_ring *ring = &rt2x00dev->ring[ring_type];
@@ -915,7 +912,7 @@ static int rt2500usb_alloc_dma_ring(stru
 	/*
 	 * Initialize work structure for deferred work.
 	 */
-	INIT_WORK(&ring->irq_work, handler);
+	INIT_WORK(&ring->irq_work, handler, ring);
 
 	ring->stats.limit = max_entries;
 	ring->data_size = data_size;
@@ -1620,10 +1617,9 @@ static void rt2500usb_write_tx_desc(stru
 /*
  * Interrupt functions.
  */
-static void rt2500usb_beacondone(struct work_struct *work)
+static void rt2500usb_beacondone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry = rt2x00_get_data_entry(ring);
 	struct sk_buff *skb;
@@ -1638,10 +1634,9 @@ static void rt2500usb_beacondone(struct 
 	dev_kfree_skb_any(skb);
 }
 
-static void rt2500usb_rxdone(struct work_struct *work)
+static void rt2500usb_rxdone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry;
 	struct sk_buff *skb;
@@ -1724,10 +1719,9 @@ static void rt2500usb_rxdone(struct work
 	rt2500usb_activity_led(rt2x00dev, 0);
 }
 
-static void rt2500usb_txdone(struct work_struct *work)
+static void rt2500usb_txdone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry;
 	struct data_desc *txd;
@@ -2145,13 +2139,11 @@ static void rt2500usb_set_multicast_list
 	}
 }
 
-static void rt2500usb_scan(struct work_struct *work)
+static void rt2500usb_scan(void *data)
 {
-	struct scanning *scan =
-		container_of(work, struct scanning, work);
-	struct rt2x00_dev *rt2x00dev = scan->rt2x00dev;
+	struct rt2x00_dev *rt2x00dev = data;
 
-	if (unlikely(!rt2x00dev))
+	if (unlikely(!rt2x00dev->scan))
 		return;
 
 	/*
@@ -2159,34 +2151,34 @@ static void rt2500usb_scan(struct work_s
 	 * we need to wait untill all TX rings are empty to
 	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00_wait_scan(scan))
+	if (rt2x00_wait_scan(rt2x00dev->scan))
 		goto exit;
 
 	/*
 	 * Switch channel and update active info for RX.
 	 */
-	if (scan->state == IEEE80211_SCAN_START) {
+	if (rt2x00dev->scan->state == IEEE80211_SCAN_START) {
 		rt2500usb_config_phymode(rt2x00dev,
-			scan->conf.scan_phymode);
+			rt2x00dev->scan->conf.scan_phymode);
 
 		rt2500usb_config_channel(rt2x00dev,
-			scan->conf.scan_channel_val,
-			scan->conf.scan_channel,
-			scan->conf.scan_freq,
-			scan->conf.scan_power_level);
+			rt2x00dev->scan->conf.scan_channel_val,
+			rt2x00dev->scan->conf.scan_channel,
+			rt2x00dev->scan->conf.scan_freq,
+			rt2x00dev->scan->conf.scan_power_level);
 	} else {
 		rt2500usb_config_phymode(rt2x00dev,
-			scan->conf.running_phymode);
+			rt2x00dev->scan->conf.running_phymode);
 
 		rt2500usb_config_channel(rt2x00dev,
-			scan->conf.running_channel_val,
-			scan->conf.running_channel,
-			scan->conf.running_freq,
-			scan->conf.scan_power_level);
+			rt2x00dev->scan->conf.running_channel_val,
+			rt2x00dev->scan->conf.running_channel,
+			rt2x00dev->scan->conf.running_freq,
+			rt2x00dev->scan->conf.scan_power_level);
 	}
 
 exit:
-	kfree(scan);
+	kfree(rt2x00dev->scan);
 	rt2x00dev->scan = NULL;
 }
 
@@ -2227,13 +2219,12 @@ static int rt2500usb_passive_scan(struct
 	/*
 	 * Initialize Scanning structure.
 	 */
-	rt2x00dev->scan->rt2x00dev = rt2x00dev;
 	rt2x00_start_scan(rt2x00dev->scan, conf, state);
 
 	/*
 	 * Queue work.
 	 */
-	INIT_WORK(&rt2x00dev->scan->work, rt2500usb_scan);
+	INIT_WORK(&rt2x00dev->scan->work, rt2500usb_scan, rt2x00dev);
 	if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
 		goto exit;
 
@@ -2863,7 +2854,7 @@ static int rt2500usb_alloc_dev(struct us
 	/*
 	 * Initialize configuration work.
 	 */
-	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2500usb_link_tuner);
+	INIT_WORK(&rt2x00dev->link.work, rt2500usb_link_tuner, rt2x00dev);
 
 	/*
 	 * Reset current working type.
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2x00.h.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2x00.h	2007-02-27 17:26:17.000000000 -0500
@@ -686,7 +686,7 @@ struct link {
 	/*
 	 * Work structure for scheduling periodic link tuning.
 	 */
-	struct delayed_work work;
+	struct work_struct work;
 };
 
 static inline void rt2x00_start_link_tune(struct link *link)
@@ -817,12 +817,6 @@ static inline void rt2x00_remove_interfa
  */
 struct scanning {
 	/*
-	 * Pointer to main rt2x00dev structure where this
-	 * scanning structure belongs to.
-	 */
-	struct rt2x00_dev *rt2x00dev;
-
-	/*
 	 * Completion structure if an packet needs to be send.
 	 */
 	struct completion completion;
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt61pci.h.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt61pci.h	2007-02-27 17:26:17.000000000 -0500
@@ -1390,9 +1390,9 @@ static void rt61pci_disable_radio(struct
 /*
  * Interrupt functions.
  */
-static void rt61pci_beacondone(struct work_struct *work);
-static void rt61pci_rxdone(struct work_struct *work);
-static void rt61pci_txdone(struct work_struct *work);
+static void rt61pci_beacondone(void *data);
+static void rt61pci_rxdone(void *data);
+static void rt61pci_txdone(void *data);
 static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance);
 
 #endif /* RT61PCI_H */
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2500pci.c.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2500pci.c	2007-02-27 17:26:17.000000000 -0500
@@ -692,12 +692,9 @@ static void rt2500pci_config_mac_address
 /*
  * Link tuning
  */
-static void rt2500pci_link_tuner(struct work_struct *work)
+static void rt2500pci_link_tuner(void *data)
 {
-	struct link *link =
-		container_of(work, struct link, work.work);
-	struct rt2x00_dev *rt2x00dev =
-		container_of(link, struct rt2x00_dev, link);
+	struct rt2x00_dev *rt2x00dev = data;
 	u32 reg;
 	u32 rssi;
 	u8 reg_r17;
@@ -851,7 +848,7 @@ static int rt2500pci_set_state(struct rt
  * Initialization functions.
  */
 static int rt2500pci_alloc_dma_ring(struct rt2x00_dev *rt2x00dev,
-	enum ring_index ring_type, void (*handler)(struct work_struct *),
+	enum ring_index ring_type, void (*handler)(void *),
 	const u16 max_entries, const u16 data_size, const u16 desc_size)
 {
 	struct data_ring *ring = &rt2x00dev->ring[ring_type];
@@ -860,7 +857,7 @@ static int rt2500pci_alloc_dma_ring(stru
 	/*
 	 * Initialize work structure for deferred work.
 	 */
-	INIT_WORK(&ring->irq_work, handler);
+	INIT_WORK(&ring->irq_work, handler, ring);
 
 	ring->stats.limit = max_entries;
 	ring->data_size = data_size;
@@ -1655,10 +1652,9 @@ static void rt2500pci_write_tx_desc(stru
 /*
  * Interrupt functions.
  */
-static void rt2500pci_beacondone(struct work_struct *work)
+static void rt2500pci_beacondone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry = rt2x00_get_data_entry(ring);
 	struct sk_buff *skb;
@@ -1673,10 +1669,9 @@ static void rt2500pci_beacondone(struct 
 	dev_kfree_skb_any(skb);
 }
 
-static void rt2500pci_rxdone(struct work_struct *work)
+static void rt2500pci_rxdone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry;
 	struct sk_buff *skb;
@@ -1741,10 +1736,9 @@ static void rt2500pci_rxdone(struct work
 	rt2500pci_activity_led(rt2x00dev, 0);
 }
 
-static void rt2500pci_txdone(struct work_struct *work)
+static void rt2500pci_txdone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry;
 	struct data_desc *txd;
@@ -2207,13 +2201,11 @@ static void rt2500pci_set_multicast_list
 			rt2x00dev->interface.promisc);
 }
 
-static void rt2500pci_scan(struct work_struct *work)
+static void rt2500pci_scan(void *data)
 {
-	struct scanning *scan =
-		container_of(work, struct scanning, work);
-	struct rt2x00_dev *rt2x00dev = scan->rt2x00dev;
+	struct rt2x00_dev *rt2x00dev = data;
 
-	if (unlikely(!rt2x00dev))
+	if (unlikely(!rt2x00dev->scan))
 		return;
 
 	/*
@@ -2221,34 +2213,34 @@ static void rt2500pci_scan(struct work_s
 	 * we need to wait untill all TX rings are empty to
 	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00_wait_scan(scan))
+	if (rt2x00_wait_scan(rt2x00dev->scan))
 		goto exit;
 
 	/*
 	 * Switch channel and update active info for RX.
 	 */
-	if (scan->state == IEEE80211_SCAN_START) {
+	if (rt2x00dev->scan->state == IEEE80211_SCAN_START) {
 		rt2500pci_config_phymode(rt2x00dev,
-			scan->conf.scan_phymode);
+			rt2x00dev->scan->conf.scan_phymode);
 
 		rt2500pci_config_channel(rt2x00dev,
-			scan->conf.scan_channel_val,
-			scan->conf.scan_channel,
-			scan->conf.scan_freq,
-			scan->conf.scan_power_level);
+			rt2x00dev->scan->conf.scan_channel_val,
+			rt2x00dev->scan->conf.scan_channel,
+			rt2x00dev->scan->conf.scan_freq,
+			rt2x00dev->scan->conf.scan_power_level);
 	} else {
 		rt2500pci_config_phymode(rt2x00dev,
-			scan->conf.running_phymode);
+			rt2x00dev->scan->conf.running_phymode);
 
 		rt2500pci_config_channel(rt2x00dev,
-			scan->conf.running_channel_val,
-			scan->conf.running_channel,
-			scan->conf.running_freq,
-			scan->conf.scan_power_level);
+			rt2x00dev->scan->conf.running_channel_val,
+			rt2x00dev->scan->conf.running_channel,
+			rt2x00dev->scan->conf.running_freq,
+			rt2x00dev->scan->conf.scan_power_level);
 	}
 
 exit:
-	kfree(scan);
+	kfree(rt2x00dev->scan);
 	rt2x00dev->scan = NULL;
 }
 
@@ -2289,13 +2281,12 @@ static int rt2500pci_passive_scan(struct
 	/*
 	 * Initialize Scanning structure.
 	 */
-	rt2x00dev->scan->rt2x00dev = rt2x00dev;
 	rt2x00_start_scan(rt2x00dev->scan, conf, state);
 
 	/*
 	 * Queue work.
 	 */
-	INIT_WORK(&rt2x00dev->scan->work, rt2500pci_scan);
+	INIT_WORK(&rt2x00dev->scan->work, rt2500pci_scan, rt2x00dev);
 	if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
 		goto exit;
 
@@ -3039,7 +3030,7 @@ static int rt2500pci_alloc_dev(struct pc
 	/*
 	 * Initialize configuration work.
 	 */
-	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2500pci_link_tuner);
+	INIT_WORK(&rt2x00dev->link.work, rt2500pci_link_tuner, rt2x00dev);
 
 	/*
 	 * Reset current working type.
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2500usb.h.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2500usb.h	2007-02-27 17:26:17.000000000 -0500
@@ -731,9 +731,9 @@ static void rt2500usb_disable_radio(stru
 /*
  * Interrupt functions.
  */
-static void rt2500usb_beacondone(struct work_struct *work);
-static void rt2500usb_rxdone(struct work_struct *work);
-static void rt2500usb_txdone(struct work_struct *work);
+static void rt2500usb_beacondone(void *data);
+static void rt2500usb_rxdone(void *data);
+static void rt2500usb_txdone(void *data);
 static void rt2500usb_interrupt(struct urb *urb);
 
 #endif /* RT2500USB_H */
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt61pci.c.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt61pci.c	2007-02-27 17:26:17.000000000 -0500
@@ -916,12 +916,9 @@ static void rt61pci_config_mac_address(s
 /*
  * Link tuning
  */
-static void rt61pci_link_tuner(struct work_struct *work)
+static void rt61pci_link_tuner(void *data)
 {
-	struct link *link =
-		container_of(work, struct link, work.work);
-	struct rt2x00_dev *rt2x00dev =
-		container_of(link, struct rt2x00_dev, link);
+	struct rt2x00_dev *rt2x00dev = data;
 	u32 reg;
 	u32 rssi;
 	u8 reg_r17;
@@ -1267,7 +1264,7 @@ static int rt61pci_init_firmware(struct 
 }
 
 static int rt61pci_alloc_dma_ring(struct rt2x00_dev *rt2x00dev,
-	enum ring_index ring_type, void (*handler)(struct work_struct *work),
+	enum ring_index ring_type, void (*handler)(void *),
 	const u16 max_entries, const u16 data_size, const u16 desc_size)
 {
 	struct data_ring *ring = &rt2x00dev->ring[ring_type];
@@ -1276,7 +1273,7 @@ static int rt61pci_alloc_dma_ring(struct
 	/*
 	 * Initialize work structure for deferred work.
 	 */
-	INIT_WORK(&ring->irq_work, handler);
+	INIT_WORK(&ring->irq_work, handler, ring);
 
 	ring->stats.limit = max_entries;
 	ring->data_size = data_size;
@@ -2115,10 +2112,9 @@ static void rt61pci_write_tx_desc(struct
 /*
  * Interrupt functions.
  */
-static void rt61pci_beacondone(struct work_struct *work)
+static void rt61pci_beacondone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry = rt2x00_get_data_entry(ring);
 	struct sk_buff *skb;
@@ -2133,10 +2129,9 @@ static void rt61pci_beacondone(struct wo
 	dev_kfree_skb_any(skb);
 }
 
-static void rt61pci_rxdone(struct work_struct *work)
+static void rt61pci_rxdone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry;
 	struct sk_buff *skb;
@@ -2261,10 +2256,9 @@ static void rt61pci_txdone_entry(struct 
 			entry->tx_status.control.queue);
 }
 
-static void rt61pci_txdone(struct work_struct *work)
+static void rt61pci_txdone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	int index;
 	int reg;
@@ -2691,13 +2685,11 @@ static void rt61pci_set_multicast_list(s
 			rt2x00dev->interface.promisc);
 }
 
-static void rt61pci_scan(struct work_struct *work)
+static void rt61pci_scan(void *data)
 {
-	struct scanning *scan =
-		container_of(work, struct scanning, work);
-	struct rt2x00_dev *rt2x00dev = scan->rt2x00dev;
+	struct rt2x00_dev *rt2x00dev = data;
 
-	if (unlikely(!rt2x00dev))
+	if (unlikely(!rt2x00dev->scan))
 		return;
 
 	/*
@@ -2705,34 +2697,34 @@ static void rt61pci_scan(struct work_str
 	 * we need to wait untill all TX rings are empty to
 	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00_wait_scan(scan))
+	if (rt2x00_wait_scan(rt2x00dev->scan))
 		goto exit;
 
 	/*
 	 * Switch channel and update active info for RX.
 	 */
-	if (scan->state == IEEE80211_SCAN_START) {
+	if (rt2x00dev->scan->state == IEEE80211_SCAN_START) {
 		rt61pci_config_phymode(rt2x00dev,
-			scan->conf.scan_phymode);
+			rt2x00dev->scan->conf.scan_phymode);
 
 		rt61pci_config_channel(rt2x00dev,
-			scan->conf.scan_channel_val,
-			scan->conf.scan_channel,
-			scan->conf.scan_freq,
-			scan->conf.scan_power_level);
+			rt2x00dev->scan->conf.scan_channel_val,
+			rt2x00dev->scan->conf.scan_channel,
+			rt2x00dev->scan->conf.scan_freq,
+			rt2x00dev->scan->conf.scan_power_level);
 	} else {
 		rt61pci_config_phymode(rt2x00dev,
-			scan->conf.running_phymode);
+			rt2x00dev->scan->conf.running_phymode);
 
 		rt61pci_config_channel(rt2x00dev,
-			scan->conf.running_channel_val,
-			scan->conf.running_channel,
-			scan->conf.running_freq,
-			scan->conf.scan_power_level);
+			rt2x00dev->scan->conf.running_channel_val,
+			rt2x00dev->scan->conf.running_channel,
+			rt2x00dev->scan->conf.running_freq,
+			rt2x00dev->scan->conf.scan_power_level);
 	}
 
 exit:
-	kfree(scan);
+	kfree(rt2x00dev->scan);
 	rt2x00dev->scan = NULL;
 }
 
@@ -2773,13 +2765,12 @@ static int rt61pci_passive_scan(struct i
 	/*
 	 * Initialize Scanning structure.
 	 */
-	rt2x00dev->scan->rt2x00dev = rt2x00dev;
 	rt2x00_start_scan(rt2x00dev->scan, conf, state);
 
 	/*
 	 * Queue work.
 	 */
-	INIT_WORK(&rt2x00dev->scan->work, rt61pci_scan);
+	INIT_WORK(&rt2x00dev->scan->work, rt61pci_scan, rt2x00dev);
 	if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
 		goto exit;
 
@@ -3558,7 +3549,7 @@ static int rt61pci_alloc_dev(struct pci_
 	/*
 	 * Initialize configuration work.
 	 */
-	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt61pci_link_tuner);
+	INIT_WORK(&rt2x00dev->link.work, rt61pci_link_tuner, rt2x00dev);
 
 	/*
 	 * Reset current working type.
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt73usb.h.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt73usb.h	2007-02-27 17:26:17.000000000 -0500
@@ -972,9 +972,9 @@ static void rt73usb_disable_radio(struct
 /*
  * Interrupt functions.
  */
-static void rt73usb_beacondone(struct work_struct *work);
-static void rt73usb_rxdone(struct work_struct *work);
-static void rt73usb_txdone(struct work_struct *work);
+static void rt73usb_beacondone(void *data);
+static void rt73usb_rxdone(void *data);
+static void rt73usb_txdone(void *data);
 static void rt73usb_interrupt(struct urb *urb);
 
 #endif /* RT73USB_H */
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2400pci.h.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2400pci.h	2007-02-27 17:26:17.000000000 -0500
@@ -959,9 +959,9 @@ static void rt2400pci_disable_radio(stru
 /*
  * Interrupt functions.
  */
-static void rt2400pci_beacondone(struct work_struct *work);
-static void rt2400pci_rxdone(struct work_struct *work);
-static void rt2400pci_txdone(struct work_struct *work);
+static void rt2400pci_beacondone(void *data);
+static void rt2400pci_rxdone(void *data);
+static void rt2400pci_txdone(void *data);
 static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance);
 
 #endif /* RT2400PCI_H */
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt73usb.c.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt73usb.c	2007-02-27 17:26:17.000000000 -0500
@@ -814,12 +814,9 @@ static void rt73usb_config_mac_address(s
 /*
  * Link tuning
  */
-static void rt73usb_link_tuner(struct work_struct *work)
+static void rt73usb_link_tuner(void *data)
 {
-	struct link *link =
-		container_of(work, struct link, work.work);
-	struct rt2x00_dev *rt2x00dev =
-		container_of(link, struct rt2x00_dev, link);
+	struct rt2x00_dev *rt2x00dev = data;
 	u32 reg;
 	u32 rssi;
 	u8 reg_r17;
@@ -1125,7 +1122,7 @@ static int rt73usb_init_firmware(struct 
 }
 
 static int rt73usb_alloc_dma_ring(struct rt2x00_dev *rt2x00dev,
-	enum ring_index ring_type, void (*handler)(struct work_struct *work),
+	enum ring_index ring_type, void (*handler)(void *),
 	const u16 max_entries, const u16 data_size, const u16 desc_size)
 {
 	struct data_ring *ring = &rt2x00dev->ring[ring_type];
@@ -1135,7 +1132,7 @@ static int rt73usb_alloc_dma_ring(struct
 	/*
 	 * Initialize work structure for deferred work.
 	 */
-	INIT_WORK(&ring->irq_work, handler);
+	INIT_WORK(&ring->irq_work, handler, ring);
 
 	ring->stats.limit = max_entries;
 	ring->data_size = data_size;
@@ -1889,10 +1886,9 @@ static void rt73usb_write_tx_desc(struct
 /*
  * Interrupt functions.
  */
-static void rt73usb_beacondone(struct work_struct *work)
+static void rt73usb_beacondone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry = rt2x00_get_data_entry(
 		&rt2x00dev->ring[RING_BEACON]);
@@ -1908,10 +1904,9 @@ static void rt73usb_beacondone(struct wo
 	dev_kfree_skb_any(skb);
 }
 
-static void rt73usb_rxdone(struct work_struct *work)
+static void rt73usb_rxdone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry;
 	struct sk_buff *skb;
@@ -1985,10 +1980,9 @@ static void rt73usb_rxdone(struct work_s
 	}
 }
 
-static void rt73usb_txdone(struct work_struct *work)
+static void rt73usb_txdone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry;
 	struct data_desc *txd;
@@ -2405,13 +2399,11 @@ static void rt73usb_set_multicast_list(s
 	}
 }
 
-static void rt73usb_scan(struct work_struct *work)
+static void rt73usb_scan(void *data)
 {
-	struct scanning *scan =
-		container_of(work, struct scanning, work);
-	struct rt2x00_dev *rt2x00dev = scan->rt2x00dev;
+	struct rt2x00_dev *rt2x00dev = data;
 
-	if (unlikely(!rt2x00dev))
+	if (unlikely(!rt2x00dev->scan))
 		return;
 
 	/*
@@ -2419,34 +2411,34 @@ static void rt73usb_scan(struct work_str
 	 * we need to wait untill all TX rings are empty to
 	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00_wait_scan(scan))
+	if (rt2x00_wait_scan(rt2x00dev->scan))
 		goto exit;
 
 	/*
 	 * Switch channel and update active info for RX.
 	 */
-	if (scan->state == IEEE80211_SCAN_START) {
+	if (rt2x00dev->scan->state == IEEE80211_SCAN_START) {
 		rt73usb_config_phymode(rt2x00dev,
-			scan->conf.scan_phymode);
+			rt2x00dev->scan->conf.scan_phymode);
 
 		rt73usb_config_channel(rt2x00dev,
-			scan->conf.scan_channel_val,
-			scan->conf.scan_channel,
-			scan->conf.scan_freq,
-			scan->conf.scan_power_level);
+			rt2x00dev->scan->conf.scan_channel_val,
+			rt2x00dev->scan->conf.scan_channel,
+			rt2x00dev->scan->conf.scan_freq,
+			rt2x00dev->scan->conf.scan_power_level);
 	} else {
 		rt73usb_config_phymode(rt2x00dev,
-			scan->conf.running_phymode);
+			rt2x00dev->scan->conf.running_phymode);
 
 		rt73usb_config_channel(rt2x00dev,
-			scan->conf.running_channel_val,
-			scan->conf.running_channel,
-			scan->conf.running_freq,
-			scan->conf.scan_power_level);
+			rt2x00dev->scan->conf.running_channel_val,
+			rt2x00dev->scan->conf.running_channel,
+			rt2x00dev->scan->conf.running_freq,
+			rt2x00dev->scan->conf.scan_power_level);
 	}
 
 exit:
-	kfree(scan);
+	kfree(rt2x00dev->scan);
 	rt2x00dev->scan = NULL;
 }
 
@@ -2487,13 +2479,12 @@ static int rt73usb_passive_scan(struct i
 	/*
 	 * Initialize Scanning structure.
 	 */
-	rt2x00dev->scan->rt2x00dev = rt2x00dev;
 	rt2x00_start_scan(rt2x00dev->scan, conf, state);
 
 	/*
 	 * Queue work.
 	 */
-	INIT_WORK(&rt2x00dev->scan->work, rt73usb_scan);
+	INIT_WORK(&rt2x00dev->scan->work, rt73usb_scan, rt2x00dev);
 	if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
 		goto exit;
 
@@ -3195,7 +3186,7 @@ static int rt73usb_alloc_dev(struct usb_
 	/*
 	 * Initialize configuration work.
 	 */
-	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt73usb_link_tuner);
+	INIT_WORK(&rt2x00dev->link.work, rt73usb_link_tuner, rt2x00dev);
 
 	/*
 	 * Reset current working type.
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2400pci.c.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/rt2x00/rt2400pci.c	2007-02-27 17:26:17.000000000 -0500
@@ -617,12 +617,9 @@ static void rt2400pci_config_mac_address
 /*
  * Link tuning
  */
-static void rt2400pci_link_tuner(struct work_struct *work)
+static void rt2400pci_link_tuner(void *data)
 {
-	struct link *link =
-		container_of(work, struct link, work.work);
-	struct rt2x00_dev *rt2x00dev =
-		container_of(link, struct rt2x00_dev, link);
+	struct rt2x00_dev *rt2x00dev = data;
 	u8 reg;
 	char false_cca_delta;
 
@@ -757,7 +754,7 @@ static int rt2400pci_set_state(struct rt
  * Initialization functions.
  */
 static int rt2400pci_alloc_dma_ring(struct rt2x00_dev *rt2x00dev,
-	enum ring_index ring_type, void (*handler)(struct work_struct *),
+	enum ring_index ring_type, void (*handler)(void *),
 	const u16 max_entries, const u16 data_size, const u16 desc_size)
 {
 	struct data_ring *ring = &rt2x00dev->ring[ring_type];
@@ -766,7 +763,7 @@ static int rt2400pci_alloc_dma_ring(stru
 	/*
 	 * Initialize work structure for deferred work.
 	 */
-	INIT_WORK(&ring->irq_work, handler);
+	INIT_WORK(&ring->irq_work, handler, ring);
 
 	ring->stats.limit = max_entries;
 	ring->data_size = data_size;
@@ -1496,10 +1493,9 @@ static void rt2400pci_write_tx_desc(stru
 /*
  * Interrupt functions.
  */
-static void rt2400pci_beacondone(struct work_struct *work)
+static void rt2400pci_beacondone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry = rt2x00_get_data_entry(ring);
 	struct sk_buff *skb;
@@ -1514,10 +1510,9 @@ static void rt2400pci_beacondone(struct 
 	dev_kfree_skb_any(skb);
 }
 
-static void rt2400pci_rxdone(struct work_struct *work)
+static void rt2400pci_rxdone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry;
 	struct sk_buff *skb;
@@ -1575,10 +1570,9 @@ static void rt2400pci_rxdone(struct work
 	rt2400pci_activity_led(rt2x00dev, 0);
 }
 
-static void rt2400pci_txdone(struct work_struct *work)
+static void rt2400pci_txdone(void *data)
 {
-	struct data_ring *ring =
-		container_of(work, struct data_ring, irq_work);
+	struct data_ring *ring = data;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_entry *entry;
 	struct data_desc *txd;
@@ -2040,13 +2034,11 @@ static void rt2400pci_set_multicast_list
 			rt2x00dev->interface.promisc);
 }
 
-static void rt2400pci_scan(struct work_struct *work)
+static void rt2400pci_scan(void *data)
 {
-	struct scanning *scan =
-		container_of(work, struct scanning, work);
-	struct rt2x00_dev *rt2x00dev = scan->rt2x00dev;
+	struct rt2x00_dev *rt2x00dev = data;
 
-	if (unlikely(!rt2x00dev))
+	if (unlikely(!rt2x00dev->scan))
 		return;
 
 	/*
@@ -2054,38 +2046,38 @@ static void rt2400pci_scan(struct work_s
 	 * we need to wait untill all TX rings are empty to
 	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00_wait_scan(scan))
+	if (rt2x00_wait_scan(rt2x00dev->scan))
 		goto exit;
 
 	/*
 	 * Switch channel and update active info for RX.
 	 */
-	if (scan->state == IEEE80211_SCAN_START) {
+	if (rt2x00dev->scan->state == IEEE80211_SCAN_START) {
 		rt2400pci_config_phymode(rt2x00dev,
-			scan->conf.scan_phymode);
+			rt2x00dev->scan->conf.scan_phymode);
 
 		rt2400pci_config_channel(rt2x00dev,
-			scan->conf.scan_channel_val,
-			scan->conf.scan_channel,
-			scan->conf.scan_freq);
+			rt2x00dev->scan->conf.scan_channel_val,
+			rt2x00dev->scan->conf.scan_channel,
+			rt2x00dev->scan->conf.scan_freq);
 
 		rt2400pci_config_txpower(rt2x00dev,
-			scan->conf.scan_power_level);
+			rt2x00dev->scan->conf.scan_power_level);
 	} else {
 		rt2400pci_config_phymode(rt2x00dev,
-			scan->conf.running_phymode);
+			rt2x00dev->scan->conf.running_phymode);
 
 		rt2400pci_config_channel(rt2x00dev,
-			scan->conf.running_channel_val,
-			scan->conf.running_channel,
-			scan->conf.running_freq);
+			rt2x00dev->scan->conf.running_channel_val,
+			rt2x00dev->scan->conf.running_channel,
+			rt2x00dev->scan->conf.running_freq);
 
 		rt2400pci_config_txpower(rt2x00dev,
-			scan->conf.running_power_level);
+			rt2x00dev->scan->conf.running_power_level);
 	}
 
 exit:
-	kfree(scan);
+	kfree(rt2x00dev->scan);
 	rt2x00dev->scan = NULL;
 }
 
@@ -2126,13 +2118,12 @@ static int rt2400pci_passive_scan(struct
 	/*
 	 * Initialize Scanning structure.
 	 */
-	rt2x00dev->scan->rt2x00dev = rt2x00dev;
 	rt2x00_start_scan(rt2x00dev->scan, conf, state);
 
 	/*
 	 * Queue work.
 	 */
-	INIT_WORK(&rt2x00dev->scan->work, rt2400pci_scan);
+	INIT_WORK(&rt2x00dev->scan->work, rt2400pci_scan, rt2x00dev);
 	if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
 		goto exit;
 
@@ -2727,7 +2718,7 @@ static int rt2400pci_alloc_dev(struct pc
 	/*
 	 * Initialize configuration work.
 	 */
-	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2400pci_link_tuner);
+	INIT_WORK(&rt2x00dev->link.work, rt2400pci_link_tuner, rt2x00dev);
 
 	/*
 	 * Reset current working type.
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/zd1211rw/zd_mac.c.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/zd1211rw/zd_mac.c	2007-02-27 17:26:17.000000000 -0500
@@ -552,10 +552,9 @@ static int zd_mac_config_interface(struc
 	return 0;
 }
 
-static void set_multicast_hash_handler(struct work_struct *work)
+static void set_multicast_hash_handler(void *_mac)
 {
-	struct zd_mac *mac =
-		container_of(work, struct zd_mac, set_multicast_hash_work);
+	struct zd_mac *mac = _mac;
 	struct zd_mc_hash hash;
 
 	spin_lock_irq(&mac->lock);
@@ -655,7 +654,7 @@ struct ieee80211_hw *zd_mac_alloc(struct
 	skb_queue_head_init(&mac->tx_queue);
 	zd_chip_init(&mac->chip, dev, intf);
 	housekeeping_init(mac);
-	INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
+	INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler, mac);
 
 	SET_IEEE80211_DEV(dev, &intf->dev);
 	return dev;
@@ -663,10 +662,9 @@ struct ieee80211_hw *zd_mac_alloc(struct
 
 #define LINK_LED_WORK_DELAY HZ
 
-static void link_led_handler(struct work_struct *work)
+static void link_led_handler(void *p)
 {
-	struct zd_mac *mac =
-		container_of(work, struct zd_mac, housekeeping.link_led_work.work);
+	struct zd_mac *mac = p;
 	struct zd_chip *chip = &mac->chip;
 	int is_associated;
 	int r;
@@ -686,7 +684,7 @@ static void link_led_handler(struct work
 
 static void housekeeping_init(struct zd_mac *mac)
 {
-	INIT_DELAYED_WORK(&mac->housekeeping.link_led_work, link_led_handler);
+	INIT_WORK(&mac->housekeeping.link_led_work, link_led_handler, mac);
 }
 
 static void housekeeping_enable(struct zd_mac *mac)
--- linux-2.6.19.noarch/drivers/net/wireless/mac80211/zd1211rw/zd_mac.h.orig	2007-02-27 17:18:50.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/mac80211/zd1211rw/zd_mac.h	2007-02-27 17:26:17.000000000 -0500
@@ -119,7 +119,7 @@ enum mac_flags {
 };
 
 struct housekeeping {
-	struct delayed_work link_led_work;
+	struct work_struct link_led_work;
 };
 
 #define ZD_MAC_STATS_BUFFER_SIZE 16
--- linux-2.6.19.noarch/net/wireless/nl80211.c.orig	2007-02-27 17:18:58.000000000 -0500
+++ linux-2.6.19.noarch/net/wireless/nl80211.c	2007-02-27 17:26:17.000000000 -0500
@@ -1001,7 +1001,8 @@ static struct genl_ops nl80211_ops[] = {
 void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, int flags, u8 cmd)
 {
 	/* since there is no private header just add the generic one */
-	return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
+	return genlmsg_put(skb, pid, seq, nl80211_fam.id, nl80211_fam.hdrsize,
+			   flags, cmd, nl80211_fam.version);
 }
 EXPORT_SYMBOL_GPL(nl80211hdr_put);
 
--- linux-2.6.19.noarch/net/mac80211/wme.c.orig	2007-02-27 17:18:58.000000000 -0500
+++ linux-2.6.19.noarch/net/mac80211/wme.c	2007-02-27 17:26:17.000000000 -0500
@@ -417,8 +417,7 @@ static int wme_qdiscop_init(struct Qdisc
 	/* create child queues */
 	for (i = 0; i < queues; i++) {
 		skb_queue_head_init(&q->requeued[i]);
-		q->queues[i] = qdisc_create_dflt(qd->dev, &CHILD_QDISC_OPS,
-						 qd->handle);
+		q->queues[i] = qdisc_create_dflt(qd->dev, &CHILD_QDISC_OPS);
 		if (q->queues[i] == 0) {
 			q->queues[i] = &noop_qdisc;
 			printk(KERN_ERR "%s child qdisc %i creation failed", dev->name, i);
@@ -644,7 +643,7 @@ void ieee80211_install_qdisc(struct net_
 {
 	struct Qdisc *qdisc;
 
-	qdisc = qdisc_create_dflt(dev, &wme_qdisc_ops, TC_H_ROOT);
+	qdisc = qdisc_create_dflt(dev, &wme_qdisc_ops);
 	if (!qdisc) {
 		printk(KERN_ERR "%s: qdisc installation failed\n", dev->name);
 		return;
--- linux-2.6.19.noarch/net/mac80211/ieee80211_i.h.orig	2007-02-27 17:18:58.000000000 -0500
+++ linux-2.6.19.noarch/net/mac80211/ieee80211_i.h	2007-02-27 17:26:17.000000000 -0500
@@ -443,8 +443,7 @@ struct ieee80211_local {
 	int scan_channel_idx;
 	enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
 	unsigned long last_scan_completed;
-	struct delayed_work scan_work;
-	struct net_device *scan_dev;
+	struct work_struct scan_work;
 	struct ieee80211_channel *oper_channel, *scan_channel;
 	struct ieee80211_hw_mode *oper_hw_mode, *scan_hw_mode;
 	u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
@@ -667,8 +666,7 @@ int ieee80211_init_client(struct net_dev
 int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq);
 /* ieee80211_sta.c */
 void ieee80211_sta_timer(unsigned long data);
-void ieee80211_sta_work(struct work_struct *work);
-void ieee80211_sta_scan_work(struct work_struct *work);
+void ieee80211_sta_work(void *ptr);
 void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
 			   struct ieee80211_rx_status *rx_status);
 int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len);
--- linux-2.6.19.noarch/net/mac80211/ieee80211_sysfs.c.orig	2007-02-27 17:18:58.000000000 -0500
+++ linux-2.6.19.noarch/net/mac80211/ieee80211_sysfs.c	2007-02-27 17:34:32.000000000 -0500
@@ -24,6 +24,9 @@ static inline struct ieee80211_local *to
 	return wiphy_priv(wiphy);
 }
 
+#define to_net_dev(class) \
+	container_of(class, struct net_device, class_dev)
+
 static inline int rtnl_lock_local(struct ieee80211_local *local)
 {
 	rtnl_lock();
@@ -364,12 +367,11 @@ static struct attribute_group ieee80211_
 
 /* attributes in /sys/class/net/X/ */
 
-static ssize_t ieee80211_if_show(struct device *d,
-			struct device_attribute *attr, char *buf,
+static ssize_t ieee80211_if_show(struct class_device *cd, char *buf,
 			ssize_t (*format)(const struct ieee80211_sub_if_data *,
 					  char *))
 {
-	struct net_device *dev = to_net_dev(d);
+	struct net_device *dev = to_net_dev(cd);
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	ssize_t ret = -EINVAL;
 
@@ -409,13 +411,12 @@ static ssize_t ieee80211_if_fmt_##name(c
 }
 
 #define __IEEE80211_IF_SHOW(name)					\
-static ssize_t ieee80211_if_show_##name(struct device *d,		\
-					struct device_attribute *attr,	\
+static ssize_t ieee80211_if_show_##name(struct class_device *cd,	\
 					char *buf)			\
 {									\
-	return ieee80211_if_show(d, attr, buf, ieee80211_if_fmt_##name);\
+	return ieee80211_if_show(cd, buf, ieee80211_if_fmt_##name);	\
 }									\
-static DEVICE_ATTR(name, S_IRUGO, ieee80211_if_show_##name, NULL);
+static CLASS_DEVICE_ATTR(name, S_IRUGO, ieee80211_if_show_##name, NULL);
 
 #define IEEE80211_IF_SHOW(name, field, format)				\
 		IEEE80211_IF_FMT_##format(name, field)			\
@@ -509,64 +510,64 @@ static ssize_t ieee80211_if_fmt_mode(con
 __IEEE80211_IF_SHOW(mode);
 
 static struct attribute *ieee80211_sta_attrs[] = {
-	&dev_attr_channel_use.attr,
-	&dev_attr_drop_unencrypted.attr,
-	&dev_attr_eapol.attr,
-	&dev_attr_ieee8021_x.attr,
-	&dev_attr_state.attr,
-	&dev_attr_bssid.attr,
-	&dev_attr_prev_bssid.attr,
-	&dev_attr_ssid_len.attr,
-	&dev_attr_aid.attr,
-	&dev_attr_ap_capab.attr,
-	&dev_attr_capab.attr,
-	&dev_attr_extra_ie_len.attr,
-	&dev_attr_auth_tries.attr,
-	&dev_attr_assoc_tries.attr,
-	&dev_attr_auth_algs.attr,
-	&dev_attr_auth_alg.attr,
-	&dev_attr_auth_transaction.attr,
-	&dev_attr_flags.attr,
+	&class_device_attr_channel_use.attr,
+	&class_device_attr_drop_unencrypted.attr,
+	&class_device_attr_eapol.attr,
+	&class_device_attr_ieee8021_x.attr,
+	&class_device_attr_state.attr,
+	&class_device_attr_bssid.attr,
+	&class_device_attr_prev_bssid.attr,
+	&class_device_attr_ssid_len.attr,
+	&class_device_attr_aid.attr,
+	&class_device_attr_ap_capab.attr,
+	&class_device_attr_capab.attr,
+	&class_device_attr_extra_ie_len.attr,
+	&class_device_attr_auth_tries.attr,
+	&class_device_attr_assoc_tries.attr,
+	&class_device_attr_auth_algs.attr,
+	&class_device_attr_auth_alg.attr,
+	&class_device_attr_auth_transaction.attr,
+	&class_device_attr_flags.attr,
 	NULL
 };
 
 static struct attribute *ieee80211_ap_attrs[] = {
-	&dev_attr_channel_use.attr,
-	&dev_attr_drop_unencrypted.attr,
-	&dev_attr_eapol.attr,
-	&dev_attr_ieee8021_x.attr,
-	&dev_attr_num_sta_ps.attr,
-	&dev_attr_dtim_period.attr,
-	&dev_attr_dtim_count.attr,
-	&dev_attr_num_beacons.attr,
-	&dev_attr_force_unicast_rateidx.attr,
-	&dev_attr_max_ratectrl_rateidx.attr,
-	&dev_attr_num_buffered_multicast.attr,
-	&dev_attr_beacon_head_len.attr,
-	&dev_attr_beacon_tail_len.attr,
+	&class_device_attr_channel_use.attr,
+	&class_device_attr_drop_unencrypted.attr,
+	&class_device_attr_eapol.attr,
+	&class_device_attr_ieee8021_x.attr,
+	&class_device_attr_num_sta_ps.attr,
+	&class_device_attr_dtim_period.attr,
+	&class_device_attr_dtim_count.attr,
+	&class_device_attr_num_beacons.attr,
+	&class_device_attr_force_unicast_rateidx.attr,
+	&class_device_attr_max_ratectrl_rateidx.attr,
+	&class_device_attr_num_buffered_multicast.attr,
+	&class_device_attr_beacon_head_len.attr,
+	&class_device_attr_beacon_tail_len.attr,
 	NULL
 };
 
 static struct attribute *ieee80211_wds_attrs[] = {
-	&dev_attr_channel_use.attr,
-	&dev_attr_drop_unencrypted.attr,
-	&dev_attr_eapol.attr,
-	&dev_attr_ieee8021_x.attr,
-	&dev_attr_peer.attr,
+	&class_device_attr_channel_use.attr,
+	&class_device_attr_drop_unencrypted.attr,
+	&class_device_attr_eapol.attr,
+	&class_device_attr_ieee8021_x.attr,
+	&class_device_attr_peer.attr,
 	NULL
 };
 
 static struct attribute *ieee80211_vlan_attrs[] = {
-	&dev_attr_channel_use.attr,
-	&dev_attr_drop_unencrypted.attr,
-	&dev_attr_eapol.attr,
-	&dev_attr_ieee8021_x.attr,
-	&dev_attr_vlan_id.attr,
+	&class_device_attr_channel_use.attr,
+	&class_device_attr_drop_unencrypted.attr,
+	&class_device_attr_eapol.attr,
+	&class_device_attr_ieee8021_x.attr,
+	&class_device_attr_vlan_id.attr,
 	NULL
 };
 
 static struct attribute *ieee80211_monitor_attrs[] = {
-	&dev_attr_mode.attr,
+	&class_device_attr_mode.attr,
 	NULL
 };
 
@@ -694,7 +695,7 @@ out:
 
 int ieee80211_sysfs_change_if_type(struct net_device *dev)
 {
-	return ieee80211_add_if_group(&dev->dev.kobj, dev);
+	return ieee80211_add_if_group(&dev->class_dev.kobj, dev);
 }
 
 int ieee80211_sysfs_add_netdevice(struct net_device *dev)
@@ -702,19 +703,19 @@ int ieee80211_sysfs_add_netdevice(struct
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	int res;
 
-	res = sysfs_create_link(&dev->dev.kobj,
+	res = sysfs_create_link(&dev->class_dev.kobj,
 				&local->hw.wiphy->dev.kobj,
 				"wiphy");
 	if (res)
 		goto err_out;
-	res = ieee80211_add_if_group(&dev->dev.kobj, dev);
+	res = ieee80211_add_if_group(&dev->class_dev.kobj, dev);
 	if (res)
 		goto err_link;
 	res = ieee80211_key_kset_sysfs_register(IEEE80211_DEV_TO_SUB_IF(dev));
 	return res;
 
 err_link:
-	sysfs_remove_link(&dev->dev.kobj, "wiphy");
+	sysfs_remove_link(&dev->class_dev.kobj, "wiphy");
 err_out:
 	return res;
 }
@@ -722,6 +723,6 @@ err_out:
 void ieee80211_sysfs_remove_netdevice(struct net_device *dev)
 {
 	ieee80211_key_kset_sysfs_unregister(IEEE80211_DEV_TO_SUB_IF(dev));
-	ieee80211_remove_if_group(&dev->dev.kobj, dev);
-	sysfs_remove_link(&dev->dev.kobj, "wiphy");
+	ieee80211_remove_if_group(&dev->class_dev.kobj, dev);
+	sysfs_remove_link(&dev->class_dev.kobj, "wiphy");
 }
--- linux-2.6.19.noarch/net/mac80211/ieee80211_iface.c.orig	2007-02-27 17:18:58.000000000 -0500
+++ linux-2.6.19.noarch/net/mac80211/ieee80211_iface.c	2007-02-27 17:26:17.000000000 -0500
@@ -181,7 +181,7 @@ void ieee80211_if_set_type(struct net_de
 		struct ieee80211_if_sta *ifsta;
 
 		ifsta = &sdata->u.sta;
-		INIT_WORK(&ifsta->work, ieee80211_sta_work);
+		INIT_WORK(&ifsta->work, ieee80211_sta_work, dev);
 		setup_timer(&ifsta->timer, ieee80211_sta_timer,
 			    (unsigned long) ifsta);
 		skb_queue_head_init(&ifsta->skb_queue);
--- linux-2.6.19.noarch/net/mac80211/ieee80211_sysfs_sta.c.orig	2007-02-27 17:18:58.000000000 -0500
+++ linux-2.6.19.noarch/net/mac80211/ieee80211_sysfs_sta.c	2007-02-27 17:26:17.000000000 -0500
@@ -387,7 +387,7 @@ int ieee80211_key_kset_sysfs_register(st
 	res = kobject_set_name(&sdata->key_kset.kobj, "keys");
 	if (res)
 		return res;
-	sdata->key_kset.kobj.parent = &sdata->dev->dev.kobj;
+	sdata->key_kset.kobj.parent = &sdata->dev->class_dev.kobj;
 	sdata->key_kset.ktype = &key_ktype;
 	return kset_register(&sdata->key_kset);
 }
--- linux-2.6.19.noarch/net/mac80211/sta_info.c.orig	2007-02-27 17:18:58.000000000 -0500
+++ linux-2.6.19.noarch/net/mac80211/sta_info.c	2007-02-27 17:26:17.000000000 -0500
@@ -342,10 +342,9 @@ static void sta_info_cleanup(unsigned lo
 }
 
 
-static void sta_info_proc_add_task(struct work_struct *work)
+static void sta_info_proc_add_task(void *data)
 {
-	struct ieee80211_local *local =
-		container_of(work, struct ieee80211_local, sta_proc_add);
+	struct ieee80211_local *local = data;
 	struct sta_info *sta, *tmp;
 
 	while (1) {
@@ -396,7 +395,7 @@ void sta_info_init(struct ieee80211_loca
 	local->sta_cleanup.data = (unsigned long) local;
 	local->sta_cleanup.function = sta_info_cleanup;
 
-	INIT_WORK(&local->sta_proc_add, sta_info_proc_add_task);
+	INIT_WORK(&local->sta_proc_add, sta_info_proc_add_task, local);
 }
 
 int sta_info_start(struct ieee80211_local *local)
--- linux-2.6.19.noarch/net/mac80211/wep.c.orig	2007-02-27 17:18:58.000000000 -0500
+++ linux-2.6.19.noarch/net/mac80211/wep.c	2007-02-27 17:26:17.000000000 -0500
@@ -15,7 +15,6 @@
 #include <linux/crc32.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
-#include <linux/mm.h>
 #include <asm/scatterlist.h>
 
 #include <net/mac80211.h>
--- linux-2.6.19.noarch/net/mac80211/ieee80211.c.orig	2007-02-27 17:18:58.000000000 -0500
+++ linux-2.6.19.noarch/net/mac80211/ieee80211.c	2007-02-27 17:26:17.000000000 -0500
@@ -2199,13 +2199,13 @@ void ieee80211_if_shutdown(struct net_de
 		flush_scheduled_work();
 		skb_queue_purge(&sdata->u.sta.skb_queue);
 		if (!local->ops->hw_scan &&
-		    local->scan_dev == sdata->dev) {
+		    local->scan_work.data == sdata->dev) {
 			local->sta_scanning = 0;
 			cancel_delayed_work(&local->scan_work);
 			flush_scheduled_work();
 			/* see comment in ieee80211_unregister_hw to
 			 * understand why this works */
-			local->scan_dev = NULL;
+			local->scan_work.data = NULL;
 		} else
 			flush_scheduled_work();
 		break;
@@ -4584,7 +4584,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(
 	spin_lock_init(&local->sub_if_lock);
 	INIT_LIST_HEAD(&local->sub_if_list);
 
-	INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
 	init_timer(&local->stat_timer);
 	local->stat_timer.function = ieee80211_stat_refresh;
 	local->stat_timer.data = (unsigned long) local;
@@ -4776,7 +4775,7 @@ void ieee80211_unregister_hw(struct ieee
 
 	if (local->stat_time)
 		del_timer_sync(&local->stat_timer);
-	if (!local->ops->hw_scan && local->scan_dev) {
+	if (!local->ops->hw_scan && local->scan_work.data) {
 		local->sta_scanning = 0;
 		cancel_delayed_work(&local->scan_work);
 		flush_scheduled_work();
--- linux-2.6.19.noarch/net/mac80211/ieee80211_sta.c.orig	2007-02-27 17:18:58.000000000 -0500
+++ linux-2.6.19.noarch/net/mac80211/ieee80211_sta.c	2007-02-27 17:30:00.000000000 -0500
@@ -1898,11 +1898,10 @@ void ieee80211_sta_timer(unsigned long d
 }
 
 
-void ieee80211_sta_work(struct work_struct *work)
+void ieee80211_sta_work(void *ptr)
 {
-	struct ieee80211_sub_if_data *sdata =
-		container_of(work, struct ieee80211_sub_if_data, u.sta.work);
-	struct net_device *dev = sdata->dev;
+	struct net_device *dev = ptr;
+	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	struct ieee80211_if_sta *ifsta;
 	struct sk_buff *skb;
@@ -1910,10 +1909,10 @@ void ieee80211_sta_work(struct work_stru
 	if (!netif_running(dev))
 		return;
 
-	/* TODO: scan_dev check should be removed once scan_completed wakes
+	/* TODO: scan_work.data check should be removed once scan_completed wakes
 	 * every STA interface */
 	if (local->sta_scanning &&
-	    local->scan_dev == dev)
+	    local->scan_work.data == dev)
 		return;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -2513,7 +2512,7 @@ int ieee80211_sta_set_bssid(struct net_d
 void ieee80211_scan_completed(struct ieee80211_hw *hw)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
-	struct net_device *dev = local->scan_dev;
+	struct net_device *dev = local->scan_work.data;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	union iwreq_data wrqu;
 
@@ -2541,85 +2540,6 @@ void ieee80211_scan_completed(struct iee
 }
 EXPORT_SYMBOL(ieee80211_scan_completed);
 
-void ieee80211_sta_scan_work(struct work_struct *work)
-{
-	struct ieee80211_local *local =
-		container_of(work, struct ieee80211_local, scan_work.work);
-	struct net_device *dev = local->scan_dev;
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	struct ieee80211_hw_mode *mode;
-	struct ieee80211_channel *chan;
-	int skip;
-	unsigned long next_delay = 0;
-
-	if (!local->sta_scanning)
-		return;
-
-	switch (local->scan_state) {
-	case SCAN_SET_CHANNEL:
-		mode = local->scan_hw_mode;
-		if (local->scan_hw_mode->list.next == &local->modes_list &&
-		    local->scan_channel_idx >= mode->num_channels) {
-			ieee80211_scan_completed(local_to_hw(local));
-			return;
-		}
-		skip = !(local->enabled_modes & (1 << mode->mode));
-		chan = &mode->channels[local->scan_channel_idx];
-		if (!(chan->flag & IEEE80211_CHAN_W_SCAN) ||
-		    (sdata->type == IEEE80211_IF_TYPE_IBSS &&
-		     !(chan->flag & IEEE80211_CHAN_W_IBSS)) ||
-		    (local->hw_modes & local->enabled_modes &
-		     (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
-			skip = 1;
-
-		if (!skip) {
-#if 0
-			printk(KERN_DEBUG "%s: scan channel %d (%d MHz)\n",
-			       dev->name, chan->chan, chan->freq);
-#endif
-
-			local->scan_channel = chan;
-			if (ieee80211_hw_config(local)) {
-				printk(KERN_DEBUG "%s: failed to set channel "
-				       "%d (%d MHz) for scan\n", dev->name,
-				       chan->chan, chan->freq);
-				skip = 1;
-			}
-		}
-
-		local->scan_channel_idx++;
-		if (local->scan_channel_idx >= local->scan_hw_mode->num_channels) {
-			if (local->scan_hw_mode->list.next != &local->modes_list) {
-				local->scan_hw_mode = list_entry(local->scan_hw_mode->list.next,
-								 struct ieee80211_hw_mode,
-								 list);
-				local->scan_channel_idx = 0;
-			}
-		}
-
-		if (skip)
-			break;
-
-		next_delay = IEEE80211_PROBE_DELAY +
-			     usecs_to_jiffies(local->hw.channel_change_time);
-		local->scan_state = SCAN_SEND_PROBE;
-		break;
-	case SCAN_SEND_PROBE:
-		if (local->scan_channel->flag & IEEE80211_CHAN_W_ACTIVE_SCAN) {
-			ieee80211_send_probe_req(dev, NULL, local->scan_ssid,
-						 local->scan_ssid_len);
-			next_delay = IEEE80211_CHANNEL_TIME;
-		} else
-			next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
-		local->scan_state = SCAN_SET_CHANNEL;
-		break;
-	}
-
-	if (local->sta_scanning)
-		schedule_delayed_work(&local->scan_work, next_delay);
-}
-
-
 static int ieee80211_sta_start_scan(struct net_device *dev,
 				    u8 *ssid, size_t ssid_len)
 {
@@ -2649,7 +2569,7 @@ static int ieee80211_sta_start_scan(stru
 	 * scan */
 
 	if (local->sta_scanning) {
-		if (local->scan_dev == dev)
+		if (local->scan_work.data == dev)
 			return 0;
 		return -EBUSY;
 	}
@@ -2661,7 +2581,7 @@ static int ieee80211_sta_start_scan(stru
 					    ssid, ssid_len);
 		if (!rc) {
 			local->sta_scanning = 1;
-			local->scan_dev = dev;
+			local->scan_work.data = dev;
 		}
 		return rc;
 	}
@@ -2679,7 +2599,7 @@ static int ieee80211_sta_start_scan(stru
 					 struct ieee80211_hw_mode,
 					 list);
 	local->scan_channel_idx = 0;
-	local->scan_dev = dev;
+	local->scan_work.data = dev;
 	schedule_delayed_work(&local->scan_work, 0);
 
 	return 0;
@@ -2696,7 +2616,7 @@ int ieee80211_sta_req_scan(struct net_de
 		return ieee80211_sta_start_scan(dev, ssid, ssid_len);
 
 	if (local->sta_scanning) {
-		if (local->scan_dev == dev)
+		if (local->scan_work.data == dev)
 			return 0;
 		return -EBUSY;
 	}

jwltest-mac80211-backport.patch:
 CREDITS                                                 |   33 
 MAINTAINERS                                             |   56 
 drivers/Kconfig                                         |    2 
 drivers/Makefile                                        |    1 
 drivers/net/wireless/Kconfig                            |    2 
 drivers/net/wireless/Makefile                           |    3 
 drivers/net/wireless/mac80211/Kconfig                   |    6 
 drivers/net/wireless/mac80211/Makefile                  |    6 
 drivers/net/wireless/mac80211/README                    |    2 
 drivers/net/wireless/mac80211/adm8211/Kconfig           |   24 
 drivers/net/wireless/mac80211/adm8211/Makefile          |    1 
 drivers/net/wireless/mac80211/adm8211/adm8211.c         | 2188 +++++++
 drivers/net/wireless/mac80211/adm8211/adm8211.h         |  622 ++
 drivers/net/wireless/mac80211/bcm43xx/Kconfig           |   99 
 drivers/net/wireless/mac80211/bcm43xx/Makefile          |   17 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx.h         |  870 ++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_debugfs.c |  433 +
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_debugfs.h |  110 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_dma.c     | 1297 ++++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_dma.h     |  361 +
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_leds.c    |  300 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_leds.h    |   56 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_lo.c      | 1051 +++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_lo.h      |   89 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_main.c    | 3962 ++++++++++++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_main.h    |  156 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_pci.c     |   61 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_pci.h     |   22 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_pcmcia.c  |  163 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_pcmcia.h  |   22 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_phy.c     | 4234 +++++++++++++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_phy.h     |  307 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_pio.c     |  671 ++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_pio.h     |  170 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_power.c   |   82 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_power.h   |   41 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_sysfs.c   |  232 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_sysfs.h   |    9 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_tables.c  |  376 +
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_tables.h  |   28 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_vstack.c  |  202 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_vstack.h  |   83 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_xmit.c    |  615 +
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_xmit.h    |  215 
 drivers/net/wireless/mac80211/p54/Kconfig               |    9 
 drivers/net/wireless/mac80211/p54/Makefile              |    4 
 drivers/net/wireless/mac80211/p54/net2280.h             |  452 +
 drivers/net/wireless/mac80211/p54/prism54.h             |   77 
 drivers/net/wireless/mac80211/p54/prism54common.c       |  807 ++
 drivers/net/wireless/mac80211/p54/prism54common.h       |  304 
 drivers/net/wireless/mac80211/p54/prism54magic.h        |   77 
 drivers/net/wireless/mac80211/p54/prism54pci.c          |  698 ++
 drivers/net/wireless/mac80211/p54/prism54pci.h          |  106 
 drivers/net/wireless/mac80211/p54/prism54usb.c          |  946 +++
 drivers/net/wireless/mac80211/p54/prism54usb.h          |  133 
 drivers/net/wireless/mac80211/rt2x00/Kconfig            |   83 
 drivers/net/wireless/mac80211/rt2x00/Makefile           |    5 
 drivers/net/wireless/mac80211/rt2x00/rt2400pci.c        | 2985 +++++++++
 drivers/net/wireless/mac80211/rt2x00/rt2400pci.h        |  967 +++
 drivers/net/wireless/mac80211/rt2x00/rt2500pci.c        | 3297 ++++++++++
 drivers/net/wireless/mac80211/rt2x00/rt2500pci.h        | 1234 +++
 drivers/net/wireless/mac80211/rt2x00/rt2500usb.c        | 3131 ++++++++++
 drivers/net/wireless/mac80211/rt2x00/rt2500usb.h        |  739 ++
 drivers/net/wireless/mac80211/rt2x00/rt2x00.h           | 1268 ++++
 drivers/net/wireless/mac80211/rt2x00/rt2x00pci.h        |   44 
 drivers/net/wireless/mac80211/rt2x00/rt2x00usb.h        |   81 
 drivers/net/wireless/mac80211/rt2x00/rt61pci.c          | 3827 ++++++++++++
 drivers/net/wireless/mac80211/rt2x00/rt61pci.h          | 1398 ++++
 drivers/net/wireless/mac80211/rt2x00/rt73usb.c          | 3467 +++++++++++
 drivers/net/wireless/mac80211/rt2x00/rt73usb.h          |  980 +++
 drivers/net/wireless/mac80211/rtl818x/Kconfig           |    8 
 drivers/net/wireless/mac80211/rtl818x/Makefile          |    2 
 drivers/net/wireless/mac80211/rtl818x/rtl8187.h         |  126 
 drivers/net/wireless/mac80211/rtl818x/rtl8187_dev.c     |  712 ++
 drivers/net/wireless/mac80211/rtl818x/rtl8187_rtl8225.c |  738 ++
 drivers/net/wireless/mac80211/rtl818x/rtl8187_rtl8225.h |   28 
 drivers/net/wireless/mac80211/rtl818x/rtl818x.h         |  175 
 drivers/net/wireless/mac80211/zd1211rw/Kconfig          |   19 
 drivers/net/wireless/mac80211/zd1211rw/Makefile         |   11 
 drivers/net/wireless/mac80211/zd1211rw/zd_chip.c        | 1674 +++++
 drivers/net/wireless/mac80211/zd1211rw/zd_chip.h        |  909 ++
 drivers/net/wireless/mac80211/zd1211rw/zd_def.h         |   57 
 drivers/net/wireless/mac80211/zd1211rw/zd_ieee80211.h   |   67 
 drivers/net/wireless/mac80211/zd1211rw/zd_mac.c         |  705 ++
 drivers/net/wireless/mac80211/zd1211rw/zd_mac.h         |  250 
 drivers/net/wireless/mac80211/zd1211rw/zd_rf.c          |  156 
 drivers/net/wireless/mac80211/zd1211rw/zd_rf.h          |   81 
 drivers/net/wireless/mac80211/zd1211rw/zd_rf_al2230.c   |  373 +
 drivers/net/wireless/mac80211/zd1211rw/zd_rf_al7230b.c  |  274 
 drivers/net/wireless/mac80211/zd1211rw/zd_rf_rf2959.c   |  279 
 drivers/net/wireless/mac80211/zd1211rw/zd_usb.c         | 1324 ++++
 drivers/net/wireless/mac80211/zd1211rw/zd_usb.h         |  241 
 drivers/net/wireless/mac80211/zd1211rw/zd_util.c        |   82 
 drivers/net/wireless/mac80211/zd1211rw/zd_util.h        |   29 
 drivers/ssb/Kconfig                                     |   93 
 drivers/ssb/Makefile                                    |   14 
 drivers/ssb/core.c                                      |  956 +++
 drivers/ssb/driver_chipcommon/chipcommon.c              |  402 +
 drivers/ssb/driver_mips/mips.c                          |  258 
 drivers/ssb/driver_pci/pcicore.c                        |  556 +
 drivers/ssb/pci.c                                       |  667 ++
 drivers/ssb/pcihost_wrapper.c                           |  104 
 drivers/ssb/pcmcia.c                                    |  256 
 drivers/ssb/scan.c                                      |  427 +
 drivers/ssb/ssb_private.h                               |  152 
 drivers/usb/host/Kconfig                                |   10 
 drivers/usb/host/ohci-hcd.c                             |    4 
 drivers/usb/host/ohci-ssb.c                             |  193 
 include/linux/Kbuild                                    |    2 
 include/linux/crc-itu-t.h                               |   27 
 include/linux/eeprom_93cx6.h                            |   77 
 include/linux/ieee80211.h                               |  330 +
 include/linux/netdevice.h                               |    6 
 include/linux/nl80211.h                                 |  275 
 include/linux/ssb/ssb.h                                 |  388 +
 include/linux/ssb/ssb_driver_chipcommon.h               |  387 +
 include/linux/ssb/ssb_driver_extif.h                    |  163 
 include/linux/ssb/ssb_driver_mips.h                     |   47 
 include/linux/ssb/ssb_driver_pci.h                      |  108 
 include/linux/ssb/ssb_regs.h                            |  294 
 include/net/cfg80211.h                                  |  176 
 include/net/iw_handler.h                                |    3 
 include/net/mac80211.h                                  | 1079 +++
 include/net/wireless.h                                  |  150 
 lib/Kconfig                                             |   16 
 lib/Makefile                                            |    3 
 lib/crc-itu-t.c                                         |   64 
 lib/eeprom_93cx6.c                                      |  344 +
 net/Kconfig                                             |    3 
 net/Makefile                                            |    2 
 net/core/Makefile                                       |    1 
 net/core/dev.c                                          |   33 
 net/core/wireless.c                                     | 2353 -------
 net/mac80211/Kconfig                                    |   73 
 net/mac80211/Makefile                                   |   26 
 net/mac80211/aes_ccm.c                                  |  155 
 net/mac80211/aes_ccm.h                                  |   26 
 net/mac80211/fifo_qdisc.c                               |  102 
 net/mac80211/hostapd_ioctl.h                            |  434 +
 net/mac80211/ieee80211.c                                | 4940 ++++++++++++++++
 net/mac80211/ieee80211_cfg.c                            |  108 
 net/mac80211/ieee80211_cfg.h                            |    9 
 net/mac80211/ieee80211_common.h                         |   98 
 net/mac80211/ieee80211_i.h                              |  720 ++
 net/mac80211/ieee80211_iface.c                          |  372 +
 net/mac80211/ieee80211_ioctl.c                          | 3304 ++++++++++
 net/mac80211/ieee80211_key.h                            |   89 
 net/mac80211/ieee80211_led.c                            |   91 
 net/mac80211/ieee80211_led.h                            |   32 
 net/mac80211/ieee80211_rate.c                           |  140 
 net/mac80211/ieee80211_rate.h                           |  161 
 net/mac80211/ieee80211_scan.c                           |  344 +
 net/mac80211/ieee80211_sta.c                            | 3013 +++++++++
 net/mac80211/ieee80211_sysfs.c                          |  727 ++
 net/mac80211/ieee80211_sysfs.h                          |   12 
 net/mac80211/ieee80211_sysfs_sta.c                      |  438 +
 net/mac80211/michael.c                                  |  104 
 net/mac80211/michael.h                                  |   20 
 net/mac80211/rc80211_simple.c                           |  399 +
 net/mac80211/sta_info.c                                 |  461 +
 net/mac80211/sta_info.h                                 |  150 
 net/mac80211/tkip.c                                     |  341 +
 net/mac80211/tkip.h                                     |   36 
 net/mac80211/wep.c                                      |  328 +
 net/mac80211/wep.h                                      |   40 
 net/mac80211/wme.c                                      |  679 ++
 net/mac80211/wme.h                                      |   38 
 net/mac80211/wpa.c                                      |  846 ++
 net/mac80211/wpa.h                                      |   34 
 net/wireless/Kconfig                                    |   31 
 net/wireless/Makefile                                   |   17 
 net/wireless/core.c                                     |  276 
 net/wireless/core.h                                     |   73 
 net/wireless/nl80211.c                                  | 1050 +++
 net/wireless/nl80211.h                                  |   17 
 net/wireless/sysfs.c                                    |  125 
 net/wireless/sysfs.h                                    |    9 
 net/wireless/wext-common.c                              |  663 ++
 net/wireless/wext-compat.c                              |  819 ++
 net/wireless/wext-export.c                              |   29 
 net/wireless/wext-mod.c                                 |   20 
 net/wireless/wext-old.c                                 | 1461 ++++
 net/wireless/wext.h                                     |   51 
 183 files changed, 86282 insertions(+), 2391 deletions(-)

--- NEW FILE jwltest-mac80211-backport.patch ---
--- linux-2.6.19.noarch/include/net/wireless.h.orig	2007-02-27 17:17:53.000000000 -0500
+++ linux-2.6.19.noarch/include/net/wireless.h	2007-02-27 17:18:50.000000000 -0500
@@ -0,0 +1,150 @@
+#ifndef __NET_WIRELESS_H
+#define __NET_WIRELESS_H
+
+/*
+ * 802.11 device management
+ *
+ * Copyright 2007	Johannes Berg <johannes at sipsolutions.net>
+ */
+
+#include <linux/netdevice.h>
+#include <linux/debugfs.h>
+#include <net/cfg80211.h>
+
+/**
+ * struct wiphy - wireless hardware description
+ * @idx: the wiphy index assigned to this item
+ * @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name>
+ */
+struct wiphy {
+	/* assign these fields before you register the wiphy */
+
+	/* permanent MAC address */
+	u8 perm_addr[ETH_ALEN];
+
+	/* fields below are read-only, assigned by cfg80211 */
+
+	/* the item in /sys/class/ieee80211/ points to this,
+	 * you need use set_wiphy_dev() (see below) */
+	struct device dev;
+
+	/* dir in debugfs: ieee80211/<wiphyname> */
+	struct dentry *debugfsdir;
+
+	char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
+};
+
+/** struct wireless_dev - wireless per-netdev state
+ *
+ * This structure must be allocated by the driver/stack
+ * that uses the ieee80211_ptr field in struct net_device
+ * (this is intentional so it can be allocated along with
+ * the netdev.)
+ *
+ * @wiphy: pointer to hardware description
+ */
+struct wireless_dev {
+	struct wiphy *wiphy;
+
+	/* private to the generic wireless code */
+	struct cfg80211_config pending_config;
+};
+
+/**
+ * wiphy_priv - return priv from wiphy
+ */
+static inline void *wiphy_priv(struct wiphy *wiphy)
+{
+	BUG_ON(!wiphy);
+	return &wiphy->priv;
+}
+
+/**
+ * set_wiphy_dev - set device pointer for wiphy
+ */
+static inline void set_wiphy_dev(struct wiphy *wiphy, struct device *dev)
+{
+	wiphy->dev.parent = dev;
+}
+
+/**
+ * wiphy_dev - get wiphy dev pointer
+ */
+static inline struct device *wiphy_dev(struct wiphy *wiphy)
+{
+	return wiphy->dev.parent;
+}
+
+/**
+ * wiphy_name - get wiphy name
+ */
+static inline char *wiphy_name(struct wiphy *wiphy)
+{
+	return wiphy->dev.bus_id;
+}
+
+/**
+ * wdev_priv - return wiphy priv from wireless_dev
+ */
+static inline void *wdev_priv(struct wireless_dev *wdev)
+{
+	BUG_ON(!wdev);
+	return wiphy_priv(wdev->wiphy);
+}
+
+/**
+ * wiphy_new - create a new wiphy for use with cfg80211
+ *
+ * create a new wiphy and associate the given operations with it.
+ * @sizeof_priv bytes are allocated for private use.
+ *
+ * the returned pointer must be assigned to each netdev's
+ * ieee80211_ptr for proper operation.
+ */
+struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv);
+
+/**
+ * wiphy_register - register a wiphy with cfg80211
+ *
+ * register the given wiphy
+ *
+ * Returns a non-negative wiphy index or a negative error code.
+ */
+extern int wiphy_register(struct wiphy *wiphy);
+
+/**
+ * wiphy_unregister - deregister a wiphy from cfg80211
+ *
+ * unregister a device with the given priv pointer.
+ * After this call, no more requests can be made with this priv
+ * pointer, but the call may sleep to wait for an outstanding
+ * request that is being handled.
+ */
+extern void wiphy_unregister(struct wiphy *wiphy);
+
+/**
+ * wiphy_free - free wiphy
+ */
+extern void wiphy_free(struct wiphy *wiphy);
+
+
+/*
+ * internal definitions for wireless
+ */
+
+#if defined(CONFIG_CFG80211_WEXT_COMPAT) || defined(CONFIG_WIRELESS_EXT)
+int wext_ioctl(unsigned int cmd, struct ifreq *ifreq, void __user *arg);
+int wireless_proc_init(void);
+#else
+static inline
+int wext_ioctl(unsigned int cmd, struct ifreq *ifreq, void __user *arg)
+{
+	return -EINVAL;
+}
+static inline int wireless_proc_init(void)
+{
+	return 0;
+}
+#endif
+
+#endif /* __NET_WIRELESS_H */
--- /dev/null	2006-11-15 09:57:50.578980680 -0500
+++ linux-2.6.19.noarch/include/net/mac80211.h	2007-02-27 17:18:50.000000000 -0500
@@ -0,0 +1,1079 @@
+/*
+ * Low-level hardware driver -- IEEE 802.11 driver (80211.o) interface
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MAC80211_H
+#define MAC80211_H
+
+#include <linux/kernel.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/wireless.h>
+#include <linux/device.h>
+#include <linux/ieee80211.h>
+#include <net/wireless.h>
+#include <net/cfg80211.h>
+
+/* Note! Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be
+ * called in hardware interrupt context. The low-level driver must not call any
+ * other functions in hardware interrupt context. If there is a need for such
+ * call, the low-level driver should first ACK the interrupt and perform the
+ * IEEE 802.11 code call after this, e.g., from a scheduled tasklet (in
+ * software interrupt context).
+ */
+
+/*
+ * Frame format used when passing frame between low-level hardware drivers
+ * and IEEE 802.11 driver the same as used in the wireless media, i.e.,
+ * buffers start with IEEE 802.11 header and include the same octets that
+ * are sent over air.
+ *
+ * If hardware uses IEEE 802.3 headers (and perform 802.3 <-> 802.11
+ * conversion in firmware), upper layer 802.11 code needs to be changed to
+ * support this.
+ *
+ * If the receive frame format is not the same as the real frame sent
+ * on the wireless media (e.g., due to padding etc.), upper layer 802.11 code
+ * could be updated to provide support for such format assuming this would
+ * optimize the performance, e.g., by removing need to re-allocation and
[...89103 lines suppressed...]
+			iwe.u.data.length = strlen(buf);
+			current_ev = iwe_stream_add_point(current_ev, end_buf,
+							  &iwe, buf);
+			kfree(buf);
+		}
+	}
+
+	do {
+		char *buf, *p;
+		int i;
+
+		if (!(local->scan_flags & IEEE80211_SCAN_EXTRA_INFO))
+			break;
+
+		buf = kmalloc(100, GFP_ATOMIC);
+		if (!buf)
+			break;
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVCUSTOM;
+		sprintf(buf, "bcn_int=%d", bss->beacon_int);
+		iwe.u.data.length = strlen(buf);
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  buf);
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVCUSTOM;
+		sprintf(buf, "rssi=%d", bss->rssi);
+		iwe.u.data.length = strlen(buf);
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  buf);
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVCUSTOM;
+		sprintf(buf, "capab=0x%04x", bss->capability);
+		iwe.u.data.length = strlen(buf);
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  buf);
+
+		/* dispaly all support rates in readable format */
+		p = current_ev + IW_EV_LCP_LEN;
+		iwe.cmd = SIOCGIWRATE;
+		/* Those two flags are ignored... */
+		iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
+		for (i = 0; i < bss->supp_rates_len; i++) {
+			iwe.u.bitrate.value = ((bss->supp_rates[i] &
+							0x7f) * 500000);
+			p = iwe_stream_add_value(current_ev, p,
+					end_buf, &iwe, IW_EV_PARAM_LEN);
+		}
+		/* Check if we added any rate */
+		if((p - current_ev) > IW_EV_LCP_LEN)
+			current_ev = p;
+
+		kfree(buf);
+		break;
+	} while (0);
+
+	return current_ev;
+}
+
+
+int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	char *current_ev = buf;
+	char *end_buf = buf + len;
+	struct ieee80211_sta_bss *bss;
+
+	spin_lock_bh(&local->sta_bss_lock);
+	list_for_each_entry(bss, &local->sta_bss_list, list) {
+		if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
+			spin_unlock_bh(&local->sta_bss_lock);
+			return -E2BIG;
+		}
+		current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
+						       end_buf);
+	}
+	spin_unlock_bh(&local->sta_bss_lock);
+	return current_ev - buf;
+}
+
+
+int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+	kfree(ifsta->extra_ie);
+	if (len == 0) {
+		ifsta->extra_ie = NULL;
+		ifsta->extra_ie_len = 0;
+		return 0;
+	}
+	ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
+	if (!ifsta->extra_ie) {
+		ifsta->extra_ie_len = 0;
+		return -ENOMEM;
+	}
+	memcpy(ifsta->extra_ie, ie, len);
+	ifsta->extra_ie_len = len;
+	return 0;
+}
+
+
+struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
+					 struct sk_buff *skb, u8 *bssid,
+					 u8 *addr)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sta_info *sta;
+	struct ieee80211_sub_if_data *sdata = NULL;
+	struct net_device *sta_dev = NULL;
+
+	/* TODO: Could consider removing the least recently used entry and
+	 * allow new one to be added. */
+	if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: No room for a new IBSS STA "
+			       "entry " MAC_FMT "\n", dev->name, MAC_ARG(addr));
+		}
+		return NULL;
+	}
+
+	spin_lock_bh(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list)
+		if (sdata->type == IEEE80211_IF_TYPE_IBSS &&
+		    memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
+			sta_dev = sdata->dev;
+			break;
+		}
+	spin_unlock_bh(&local->sub_if_lock);
+
+	if (!sta_dev)
+		return NULL;
+
+	printk(KERN_DEBUG "%s: Adding new IBSS station " MAC_FMT " (dev=%s)\n",
+	       dev->name, MAC_ARG(addr), sta_dev->name);
+
+	sta = sta_info_add(local, dev, addr, GFP_ATOMIC);
+	if (!sta)
+		return NULL;
+
+	sta->dev = sta_dev;
+	sta->supp_rates = sdata->u.sta.supp_rates_bits;
+
+	rate_control_rate_init(sta, local);
+
+	return sta; /* caller will call sta_info_put() */
+}
+
+
+int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
+	printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
+	       dev->name, reason);
+
+	if (sdata->type != IEEE80211_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS)
+		return -EINVAL;
+
+	ieee80211_send_deauth(dev, ifsta, reason);
+	ieee80211_set_disassoc(dev, ifsta, 1);
+	return 0;
+}
+
+
+int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
+	printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
+	       dev->name, reason);
+
+	if (sdata->type != IEEE80211_IF_TYPE_STA)
+		return -EINVAL;
+
+	if (!ifsta->associated)
+		return -1;
+
+	ieee80211_send_disassoc(dev, ifsta, reason);
+	ieee80211_set_disassoc(dev, ifsta, 0);
+	return 0;
+}
--- /dev/null	2006-11-15 09:57:50.578980680 -0500
+++ linux-2.6.19.noarch/net/mac80211/ieee80211_cfg.h	2007-02-27 17:18:58.000000000 -0500
@@ -0,0 +1,9 @@
+/*
+ * mac80211 configuration hooks for cfg80211
+ */
+#ifndef __IEEE80211_CFG_H
+#define __IEEE80211_CFG_H
+
+extern struct cfg80211_ops mac80211_config_ops;
+
+#endif /* __IEEE80211_CFG_H */

jwltest-prism54-wpa-fix.patch:
 isl_ioctl.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletion(-)

--- NEW FILE jwltest-prism54-wpa-fix.patch ---
--- linux-2.6.19.noarch/drivers/net/wireless/prism54/isl_ioctl.c.orig	2007-02-05 10:33:42.000000000 -0500
+++ linux-2.6.19.noarch/drivers/net/wireless/prism54/isl_ioctl.c	2007-02-05 10:34:23.000000000 -0500
@@ -1395,11 +1395,17 @@ static int prism54_set_auth(struct net_d
 		break;
 
 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-		dot1x = param->value ? 1 : 0;
+		/* Don't allow turning on dot1x in WEP or unencrypted mode;
+		 * it appears to make all associations fail.
+		 */
+		if (!wpa && param->value)
+			break;
+		dot1x = param->value ? 0x01 : 0;
 		break;
 
 	case IW_AUTH_PRIVACY_INVOKED:
 		privinvoked = param->value ? 1 : 0;
+		break;
 
 	case IW_AUTH_DROP_UNENCRYPTED:
 		exunencrypt = param->value ? 1 : 0;
@@ -1589,6 +1595,7 @@ static int prism54_set_encodeext(struct 
 			}
 			key.type = DOT11_PRIV_TKIP;
 			key.length = KEY_SIZE_TKIP;
+			break;
 		default:
 			return -EINVAL;
 		}

jwltest-softmac_wx_get_rate-running-check.patch:
 ieee80211softmac_wx.c |    6 ++++++
 1 files changed, 6 insertions(+)

--- NEW FILE jwltest-softmac_wx_get_rate-running-check.patch ---
--- linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_wx.c.orig	2006-12-12 13:16:33.000000000 -0500
+++ linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_wx.c	2006-12-12 13:22:05.000000000 -0500
@@ -265,6 +265,12 @@ ieee80211softmac_wx_get_rate(struct net_
 	int err = -EINVAL;
 
 	spin_lock_irqsave(&mac->lock, flags);
+
+	if (unlikely(!mac->running)) {
+		err = -ENODEV;
+		goto out_unlock;
+	}
+
 	switch (mac->txrates.default_rate) {
 	case IEEE80211_CCK_RATE_1MB:
 		data->bitrate.value = 1000000;




More information about the fedora-cvs-commits mailing list