rpms/kernel/FC-6 jwltest-bcm43xx-2_6_20.patch, NONE, 1.1.4.1 jwltest-bcm43xx-host_strip_iv_icv-undo.patch, NONE, 1.1.4.1 jwltest-bcm43xx-post-2_6_20.patch, NONE, 1.1.4.1 jwltest-bcm43xx-workqueue-undo.patch, NONE, 1.1.4.1 jwltest-d80211-backport.patch, NONE, 1.1.18.1 jwltest-ipw3945-1_0_5.patch, NONE, 1.1.44.1 jwltest-ipw3945-1_1_0.patch, NONE, 1.1.36.1 jwltest-prism54-wpa-fix.patch, NONE, 1.1.8.1 jwltest-softmac_wx_get_rate-running-check.patch, NONE, 1.1.12.1 kernel-2.6.spec, 1.2895, 1.2895.8.1

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Wed Feb 14 23:03:16 UTC 2007


Author: linville

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

Modified Files:
      Tag: private-linville-jwltest-fc6-20-branch
	kernel-2.6.spec 
Added Files:
      Tag: private-linville-jwltest-fc6-20-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-d80211-backport.patch jwltest-ipw3945-1_0_5.patch 
	jwltest-ipw3945-1_1_0.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-d80211-backport.patch:
 CREDITS                                               |   33 
 MAINTAINERS                                           |   38 
 drivers/Kconfig                                       |    2 
 drivers/Makefile                                      |    1 
 drivers/net/wireless/Kconfig                          |    2 
 drivers/net/wireless/Makefile                         |    3 
 drivers/net/wireless/d80211/Kconfig                   |    5 
 drivers/net/wireless/d80211/Makefile                  |    5 
 drivers/net/wireless/d80211/README                    |    2 
 drivers/net/wireless/d80211/adm8211/Kconfig           |   24 
 drivers/net/wireless/d80211/adm8211/Makefile          |    1 
 drivers/net/wireless/d80211/adm8211/adm8211.c         | 2203 ++++++++
 drivers/net/wireless/d80211/adm8211/adm8211.h         |  621 ++
 drivers/net/wireless/d80211/bcm43xx/Kconfig           |   99 
 drivers/net/wireless/d80211/bcm43xx/Makefile          |   17 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx.h         |  889 +++
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c |  433 +
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.h |  110 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c     | 1296 ++++
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.h     |  361 +
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c    |  298 +
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.h    |   56 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_lo.c      | 1060 +++
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_lo.h      |   91 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c    | 3799 ++++++++++++++
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h    |  138 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pci.c     |  147 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pci.h     |   38 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pcmcia.c  |  155 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pcmcia.h  |   35 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c     | 4094 +++++++++++++++
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.h     |  304 +
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c     |  671 ++
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.h     |  170 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c   |   82 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.h   |   41 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c   |  232 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_sysfs.h   |    9 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_tables.c  |  376 +
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_tables.h  |   28 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_vstack.c  |  202 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_vstack.h  |   83 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c    |  654 ++
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h    |  215 
 drivers/net/wireless/d80211/p54/Kconfig               |    9 
 drivers/net/wireless/d80211/p54/Makefile              |    4 
 drivers/net/wireless/d80211/p54/net2280.h             |  452 +
 drivers/net/wireless/d80211/p54/prism54.h             |   76 
 drivers/net/wireless/d80211/p54/prism54common.c       |  812 +++
 drivers/net/wireless/d80211/p54/prism54common.h       |  304 +
 drivers/net/wireless/d80211/p54/prism54magic.h        |   77 
 drivers/net/wireless/d80211/p54/prism54pci.c          |  698 ++
 drivers/net/wireless/d80211/p54/prism54pci.h          |  106 
 drivers/net/wireless/d80211/p54/prism54usb.c          |  944 +++
 drivers/net/wireless/d80211/p54/prism54usb.h          |  133 
 drivers/net/wireless/d80211/rt2x00/Kconfig            |   83 
 drivers/net/wireless/d80211/rt2x00/Makefile           |    5 
 drivers/net/wireless/d80211/rt2x00/rt2400pci.c        | 2998 +++++++++++
 drivers/net/wireless/d80211/rt2x00/rt2400pci.h        |  967 +++
 drivers/net/wireless/d80211/rt2x00/rt2500pci.c        | 3308 ++++++++++++
 drivers/net/wireless/d80211/rt2x00/rt2500pci.h        | 1234 ++++
 drivers/net/wireless/d80211/rt2x00/rt2500usb.c        | 3142 +++++++++++
 drivers/net/wireless/d80211/rt2x00/rt2500usb.h        |  739 ++
 drivers/net/wireless/d80211/rt2x00/rt2x00.h           | 1262 ++++
 drivers/net/wireless/d80211/rt2x00/rt2x00pci.h        |   44 
 drivers/net/wireless/d80211/rt2x00/rt2x00usb.h        |   81 
 drivers/net/wireless/d80211/rt2x00/rt61pci.c          | 3848 ++++++++++++++
 drivers/net/wireless/d80211/rt2x00/rt61pci.h          | 1398 +++++
 drivers/net/wireless/d80211/rt2x00/rt73usb.c          | 3488 ++++++++++++
 drivers/net/wireless/d80211/rt2x00/rt73usb.h          |  980 +++
 drivers/net/wireless/d80211/zd1211rw/Kconfig          |   19 
 drivers/net/wireless/d80211/zd1211rw/Makefile         |   11 
 drivers/net/wireless/d80211/zd1211rw/zd_chip.c        | 1655 ++++++
 drivers/net/wireless/d80211/zd1211rw/zd_chip.h        |  846 +++
 drivers/net/wireless/d80211/zd1211rw/zd_def.h         |   55 
 drivers/net/wireless/d80211/zd1211rw/zd_ieee80211.h   |   68 
 drivers/net/wireless/d80211/zd1211rw/zd_mac.c         |  672 ++
 drivers/net/wireless/d80211/zd1211rw/zd_mac.h         |  249 
 drivers/net/wireless/d80211/zd1211rw/zd_rf.c          |  156 
 drivers/net/wireless/d80211/zd1211rw/zd_rf.h          |   83 
 drivers/net/wireless/d80211/zd1211rw/zd_rf_al2230.c   |  373 +
 drivers/net/wireless/d80211/zd1211rw/zd_rf_al7230b.c  |  274 +
 drivers/net/wireless/d80211/zd1211rw/zd_rf_rf2959.c   |  279 +
 drivers/net/wireless/d80211/zd1211rw/zd_types.h       |   71 
 drivers/net/wireless/d80211/zd1211rw/zd_usb.c         | 1429 +++++
 drivers/net/wireless/d80211/zd1211rw/zd_usb.h         |  243 
 drivers/net/wireless/d80211/zd1211rw/zd_util.c        |   82 
 drivers/net/wireless/d80211/zd1211rw/zd_util.h        |   29 
 drivers/ssb/Kconfig                                   |   93 
 drivers/ssb/Makefile                                  |   14 
 drivers/ssb/core.c                                    |  805 ++
 drivers/ssb/driver_chipcommon/chipcommon.c            |  403 +
 drivers/ssb/driver_mips/mips.c                        |  258 
 drivers/ssb/driver_pci/pcicore.c                      |  485 +
 drivers/ssb/pci.c                                     |  480 +
 drivers/ssb/pcmcia.c                                  |  256 
 drivers/ssb/scan.c                                    |  373 +
 drivers/ssb/ssb_private.h                             |  143 
 drivers/usb/host/Kconfig                              |   10 
 drivers/usb/host/ohci-hcd.c                           |    5 
 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                             |  315 +
 include/linux/netdevice.h                             |    8 
 include/linux/nl80211.h                               |  276 +
 include/linux/ssb/ssb.h                               |  358 +
 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                          |  293 +
 include/net/cfg80211.h                                |  205 
 include/net/d80211.h                                  | 1002 +++
 lib/Kconfig                                           |   16 
 lib/Makefile                                          |    3 
 lib/crc-itu-t.c                                       |   64 
 lib/eeprom_93cx6.c                                    |  343 +
 net/Kconfig                                           |   32 
 net/Makefile                                          |    2 
 net/core/Makefile                                     |    1 
 net/core/dev.c                                        |   40 
 net/core/net-sysfs.c                                  |    4 
 net/core/rtnetlink.c                                  |   42 
 net/core/wireless.c                                   | 2353 --------
 net/d80211/Kconfig                                    |   71 
 net/d80211/Makefile                                   |   26 
 net/d80211/aes_ccm.c                                  |  155 
 net/d80211/aes_ccm.h                                  |   26 
 net/d80211/fifo_qdisc.c                               |  102 
 net/d80211/hostapd_ioctl.h                            |  434 +
 net/d80211/ieee80211.c                                | 4842 ++++++++++++++++++
 net/d80211/ieee80211_common.h                         |   98 
 net/d80211/ieee80211_dev.c                            |  117 
 net/d80211/ieee80211_i.h                              |  728 ++
 net/d80211/ieee80211_iface.c                          |  372 +
 net/d80211/ieee80211_ioctl.c                          | 3267 ++++++++++++
 net/d80211/ieee80211_key.h                            |   89 
 net/d80211/ieee80211_led.c                            |   91 
 net/d80211/ieee80211_led.h                            |   32 
 net/d80211/ieee80211_rate.c                           |  140 
 net/d80211/ieee80211_rate.h                           |  161 
 net/d80211/ieee80211_scan.c                           |  342 +
 net/d80211/ieee80211_sta.c                            | 2894 ++++++++++
 net/d80211/ieee80211_sysfs.c                          |  785 ++
 net/d80211/ieee80211_sysfs_sta.c                      |  437 +
 net/d80211/michael.c                                  |  104 
 net/d80211/michael.h                                  |   20 
 net/d80211/rc80211_simple.c                           |  398 +
 net/d80211/sta_info.c                                 |  460 +
 net/d80211/sta_info.h                                 |  149 
 net/d80211/tkip.c                                     |  341 +
 net/d80211/tkip.h                                     |   36 
 net/d80211/wep.c                                      |  328 +
 net/d80211/wep.h                                      |   40 
 net/d80211/wme.c                                      |  678 ++
 net/d80211/wme.h                                      |   38 
 net/d80211/wpa.c                                      |  846 +++
 net/d80211/wpa.h                                      |   34 
 net/wireless/Makefile                                 |   16 
 net/wireless/core.c                                   |  245 
 net/wireless/core.h                                   |   78 
 net/wireless/nl80211.c                                | 1050 +++
 net/wireless/nl80211.h                                |    7 
 net/wireless/wext-common.c                            |  610 ++
 net/wireless/wext-compat.c                            | 1633 ++++++
 net/wireless/wext-old.c                               | 1730 ++++++
 net/wireless/wext.h                                   |   13 
 169 files changed, 84297 insertions(+), 2361 deletions(-)

--- NEW FILE jwltest-d80211-backport.patch ---
--- /dev/null	2006-11-15 09:57:50.578980680 -0500
+++ linux-2.6.19.noarch/include/net/d80211.h	2007-02-08 13:41:33.000000000 -0500
@@ -0,0 +1,1002 @@
+/*
+ * 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 D80211_H
+#define D80211_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>
+
+/* 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
+ * copying of the data.
+ */
+
+/* Interface version (used for compatibility verification) */
+#define IEEE80211_VERSION 2
+
+
+#define IEEE80211_CHAN_W_SCAN 0x00000001
+#define IEEE80211_CHAN_W_ACTIVE_SCAN 0x00000002
+#define IEEE80211_CHAN_W_IBSS 0x00000004
+
+/* Channel information structure. Low-level driver is expected to fill in chan,
+ * freq, and val fields. Other fields will be filled in by 80211.o based on
+ * hostapd information and low-level driver does not need to use them. The
+ * limits for each channel will be provided in 'struct ieee80211_conf' when
+ * configuring the low-level driver with hw->config callback. */
+struct ieee80211_channel {
+	short chan; /* channel number (IEEE 802.11) */
+	short freq; /* frequency in MHz */
+	int val; /* hw specific value for the channel */
+	int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
+        unsigned char power_level;
+        unsigned char antenna_max;
+};
+
+#define IEEE80211_RATE_ERP 0x00000001
+#define IEEE80211_RATE_BASIC 0x00000002
+#define IEEE80211_RATE_PREAMBLE2 0x00000004
+#define IEEE80211_RATE_SUPPORTED 0x00000010
+#define IEEE80211_RATE_OFDM 0x00000020
+#define IEEE80211_RATE_CCK 0x00000040
+#define IEEE80211_RATE_TURBO 0x00000080
+#define IEEE80211_RATE_MANDATORY 0x00000100
+
+#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2)
+#define IEEE80211_RATE_MODULATION(f) \
+(f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM))
+
+/* Low-level driver should set PREAMBLE2, OFDM, CCK, and TURBO flags.
+ * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
+ * configuration. */
+struct ieee80211_rate {
+	int rate; /* rate in 100 kbps */
+	int val; /* hw specific value for the rate */
+	int flags; /* IEEE80211_RATE_ flags */
+	int val2; /* hw specific value for the rate when using short preamble
+		   * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
+		   * 2, 5.5, and 11 Mbps) */
+	signed char min_rssi_ack;
+	unsigned char min_rssi_ack_delta;
+
+	/* following fields are set by 80211.o and need not be filled by the
+	 * low-level driver */
+	int rate_inv; /* inverse of the rate (LCM(all rates) / rate) for
+		       * optimizing channel utilization estimates */
+};
+
+/* 802.11g is backwards-compatible with 802.11b, so a wlan card can
+ * actually be both in 11b and 11g modes at the same time. */
+enum {
+	MODE_IEEE80211A = 0 /* IEEE 802.11a */,
+	MODE_IEEE80211B = 1 /* IEEE 802.11b only */,
+	MODE_ATHEROS_TURBO = 2 /* Atheros Turbo mode (2x.11a at 5 GHz) */,
+	MODE_IEEE80211G = 3 /* IEEE 802.11g (and 802.11b compatibility) */,
+	MODE_ATHEROS_TURBOG = 4 /* Atheros Turbo mode (2x.11g at 2.4 GHz) */,
+	NUM_IEEE80211_MODES = 5
+};
+
+struct ieee80211_hw_mode {
+	int mode; /* MODE_IEEE80211... */
+	int num_channels; /* Number of channels (below) */
+	struct ieee80211_channel *channels; /* Array of supported channels */
+	int num_rates; /* Number of rates (below) */
+        struct ieee80211_rate *rates; /* Array of supported rates */
+
+	struct list_head list; /* Internal, don't touch */
+};
+
+struct ieee80211_tx_queue_params {
+	int aifs; /* 0 .. 255; -1 = use default */
+	int cw_min; /* 2^n-1: 1, 3, 7, .. , 1023; 0 = use default */
+	int cw_max; /* 2^n-1: 1, 3, 7, .. , 1023; 0 = use default */
+	int burst_time; /* maximum burst time in 0.1 ms (i.e., 10 = 1 ms);
+			 * 0 = disabled */
+};
+
+#define NUM_TX_DATA_QUEUES 6
+
+struct ieee80211_tx_queue_stats_data {
+	unsigned int len; /* num packets in queue */
+	unsigned int limit; /* queue len (soft) limit */
+	unsigned int count; /* total num frames sent */
+};
+
+struct ieee80211_tx_queue_stats {
+	struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES];
+};
+
+#ifndef IEEE80211_TX_QUEUE_NUMS
+#define IEEE80211_TX_QUEUE_NUMS
+/* TODO: these need to be synchronized with hostapd_ioctl.h; make a shared
+ * header file that can be included into low-level drivers, 80211.o, and
+ * hostapd */
+enum {
+	IEEE80211_TX_QUEUE_DATA0 = 0,
+	IEEE80211_TX_QUEUE_DATA1 = 1,
+	IEEE80211_TX_QUEUE_DATA2 = 2,
+	IEEE80211_TX_QUEUE_DATA3 = 3,
+	IEEE80211_TX_QUEUE_DATA4 = 4,
+	IEEE80211_TX_QUEUE_SVP = 5,
+	IEEE80211_TX_QUEUE_AFTER_BEACON = 6,
+	IEEE80211_TX_QUEUE_BEACON = 7
+};
+#endif /* IEEE80211_TX_QUEUE_NUMS */
+
+
+struct ieee80211_low_level_stats {
+	unsigned int dot11ACKFailureCount;
+	unsigned int dot11RTSFailureCount;
+        unsigned int dot11FCSErrorCount;
+	unsigned int dot11RTSSuccessCount;
+};
+
+/* Transmit control fields. This data structure is passed to low-level driver
+ * with each TX frame. The low-level driver is responsible for configuring
+ * the hardware to use given values (depending on what is supported). */
+#define HW_KEY_IDX_INVALID -1
+
+struct ieee80211_tx_control {
+	int tx_rate; /* Transmit rate, given as the hw specific value for the
+		      * rate (from struct ieee80211_rate) */
+	int rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw
+			   * specific value for the rate (from
+			   * struct ieee80211_rate) */
+
+#define IEEE80211_TXCTL_REQ_TX_STATUS	(1<<0)/* request TX status callback for
+						* this frame */
+#define IEEE80211_TXCTL_DO_NOT_ENCRYPT	(1<<1) /* send this frame without
+						* encryption; e.g., for EAPOL
+						* frames */
+#define IEEE80211_TXCTL_USE_RTS_CTS	(1<<2) /* use RTS-CTS before sending
+						* frame */
+#define IEEE80211_TXCTL_USE_CTS_PROTECT	(1<<3) /* use CTS protection for the
+						* frame (e.g., for combined
+						* 802.11g / 802.11b networks) */
+#define IEEE80211_TXCTL_NO_ACK		(1<<4) /* tell the low level not to
+						* wait for an ack */
+#define IEEE80211_TXCTL_RATE_CTRL_PROBE	(1<<5)
+#define IEEE80211_TXCTL_CLEAR_DST_MASK	(1<<6)
+#define IEEE80211_TXCTL_REQUEUE		(1<<7)
+#define IEEE80211_TXCTL_FIRST_FRAGMENT	(1<<8) /* this is a first fragment of
+						* the frame */
+#define IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY (1<<9)
+	u32 flags;			       /* tx control flags defined
+						* above */
[...87027 lines suppressed...]
+		/* 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 = 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;
+	if (ifsta->bssid_set && ifsta->ssid_set &&
+	    ifsta->state != IEEE80211_AUTHENTICATE)
+		ieee80211_sta_new_auth(dev, ifsta);
+	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 = 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;
+}
--- linux-2.6.19.noarch/net/Kconfig.orig	2006-11-29 16:57:37.000000000 -0500
+++ linux-2.6.19.noarch/net/Kconfig	2007-02-08 13:42:03.000000000 -0500
@@ -245,6 +245,7 @@ endmenu
 source "net/ax25/Kconfig"
 source "net/irda/Kconfig"
 source "net/bluetooth/Kconfig"
+source "net/d80211/Kconfig"
 source "net/ieee80211/Kconfig"
 
 config WIRELESS_EXT
@@ -253,6 +254,37 @@ config WIRELESS_EXT
 config FIB_RULES
 	bool
 
+config CFG80211
+	tristate "Improved wireless configuration API"
+
+config CFG80211_WEXT_COMPAT
+	bool "cfg80211 Wireless Extensions compatibility"
+	depends CFG80211
+	default y
+	---help---
+	This option allows using devices whose drivers have been
+	converted to use the new cfg80211 with wireless extensions,
+	providing WE-20 compatibility. Note that cfg80211's "native"
+	interface is nl80211 using generic netlink. The wireless
+	extensions are being deprecated, but userspace tools may still
+	be using them.
+
+	If unsure, say Y.
+
+config CFG80211_WEXTNL_COMPAT
+	bool "cfg80211 WE-netlink compatibility"
+	depends CFG80211 && CFG80211_WEXT_COMPAT
+	---help---
+	This option allows using devices whose drivers have been
+	converted to use the new cfg80211 with wireless extensions
+	over rtnetlink, providing WE-20 compatibility. Note that
+	cfg80211's "native" interface is nl80211 using generic netlink.
+	The wireless extensions are being deprecated and the netlink
+	based API for WE was never configured by default, nor do any
+	userspace tools use this feature.
+
+	This option exists only to make Jean happy. Say N.
+
 endif   # if NET
 endmenu # Networking
 

jwltest-ipw3945-1_0_5.patch:
 Documentation/networking/README.ipw3945 |  984 +
 drivers/net/wireless/Kconfig            |  104 
 drivers/net/wireless/Makefile           |    2 
 drivers/net/wireless/ipw3945.c          |16651 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ipw3945.h          | 2555 ++++
 drivers/net/wireless/ipw3945_daemon.h   |  403 
 6 files changed, 20699 insertions(+)

--- NEW FILE jwltest-ipw3945-1_0_5.patch ---
--- linux-2.6.17.noarch/Documentation/networking/README.ipw3945.orig	2006-06-26 12:09:00.000000000 -0400
+++ linux-2.6.17.noarch/Documentation/networking/README.ipw3945	2006-06-26 12:09:05.000000000 -0400
@@ -0,0 +1,998 @@
+
+Intel(R) PRO/Wireless 3945ABG Network Connection driver for Linux* in 
+support of:
+
+Intel(R) PRO/Wireless 3945ABG Network Connection Adapter
+Intel(R) PRO/Wireless 3945BG Network Connection Adapter
+
+Note: The Intel(R) PRO/Wireless 3945ABG Network Connection driver for 
+Linux is a unified driver that works on both hardware adapters listed 
+above. In this document the Intel(R) PRO/Wireless 3945ABG Network Connection 
+driver for Linux will be used to reference the unified driver.
+
+Copyright (C) 2005 - 2006, Intel Corporation
+
+README.ipw3945
+
+Version: 1.0.5
+Date   : May 22, 2006
+
+
+Index
+-----------------------------------------------
+0.   IMPORTANT INFORMATION BEFORE USING THIS DRIVER
+1.   Introduction
+1.1. Overview of Features
+2.   Loading the Driver
+3.   Feature Details
+3.1. LEDs
+3.2. Association Details
+3.3. Roaming Details
+3.4. Scanning Details
+3.5. Antenna Selection and "Diversity"
+3.6. IEEE 802.11h Details 
+3.7. Tx Power 
+3.8. Security Details
+3.9. Power Management
+4.   Configuring the driver
+4.1. Command Line Parameters
+4.3. Sysfs Helper Files:
+5.   Wireless Tools Details
+5.1. iwlist
+5.2. iwpriv
+5.3. iwconfig
+6.   Support
+7.   License
+
+
+===============================================
+0.   IMPORTANT INFORMATION BEFORE USING THIS DRIVER
+===============================================
+
+Important Notice FOR ALL USERS OR DISTRIBUTORS!!!! 
+
+Intel wireless LAN adapters are engineered, manufactured, tested, and
+quality checked to ensure that they meet all necessary local and
+governmental regulatory agency requirements for the regions that they
+are designated and/or marked to ship into. Since wireless LANs are
+generally unlicensed devices that share spectrum with radars,
+satellites, and other licensed and unlicensed devices, it is sometimes
+necessary to dynamically detect, avoid, and limit usage to avoid
+interference with these devices. In many instances Intel is required to
+provide test data to prove regional and local compliance to regional and
+governmental regulations before certification or approval to use the
+product is granted. Intel's wireless LAN's EEPROM, firmware, and
+software driver are designed to carefully control parameters that affect
+radio operation and to ensure electromagnetic compliance (EMC). These
+parameters include, without limitation, RF power, spectrum usage,
+channel scanning, and human exposure. 
+
+For these reasons Intel cannot permit any manipulation by third parties
+of the software provided in binary format with the wireless WLAN
+adapters (e.g., the EEPROM and firmware). Furthermore, if you use any
+patches, utilities, or code with the Intel wireless LAN adapters that
+have been manipulated by an unauthorized party (i.e., patches,
+utilities, or code (including open source code modifications) which have
+not been validated by Intel), (i) you will be solely responsible for
+ensuring the regulatory compliance of the products, (ii) Intel will bear
+no liability, under any theory of liability for any issues associated
+with the modified products, including without limitation, claims under
+the warranty and/or issues arising from regulatory non-compliance, and
+(iii) Intel will not provide or be required to assist in providing
+support to any third parties for such modified products.  
+
+Note: Many regulatory agencies consider Wireless LAN adapters to be
+modules, and accordingly, condition system-level regulatory approval
+upon receipt and review of test data documenting that the antennas and
+system configuration do not cause the EMC and radio operation to be
+non-compliant.
+
+The drivers available for download from SourceForge are provided as a 
+part of a development project.  Conformance to local regulatory 
+requirements is the responsibility of the individual developer.  As 
+such, if you are interested in deploying or shipping a driver as part of 
+solution intended to be used for purposes other than development, please 
+obtain a tested driver from Intel Customer Support at:
+
+http://support.intel.com/support/notebook/sb/CS-006408.htm
+
+
+===============================================
+1.   Introduction
+===============================================
+The following sections attempt to provide a brief introduction to using 
+the Intel(R) PRO/Wireless 3945ABG driver for Linux.
+
+This document is not meant to be a comprehensive manual on 
+understanding or using wireless technologies, but should be sufficient 
+to get you moving without wires on Linux.
+
+For information on building and installing the driver, see the INSTALL
+file.
+
+
+1.1. Overview of Features
+-----------------------------------------------
+The current release (1.0.5) supports the following features:
+
++ BSS mode (Infrastructure, Managed)
++ IBSS mode (Ad-Hoc)
++ WEP (OPEN and SHARED KEY mode)
++ 802.1x EAP via wpa_supplicant and xsupplicant
++ 802.11i (WPA/WPA2)
++ Wireless Extension support 
++ Full B and G rate support
++ Full A rate support (ABG only)
++ Transmit power control
++ S state support (ACPI suspend/resume)
+
+The following features are currently enabled, but not officially
+supported:
+
++ QoS
++ Monitor mode (aka RFMon)
++ Associated RF promiscuous mode
++ Frame Rx simulation
+
+The distinction between officially supported and enabled is a reflection 
+of the amount of validation and interoperability testing that has been
+performed on a given feature. Note: in addition, the features may not have 
+all of the code in the driver to fully enable the feature.
+
+
+===============================================
+2. Loading the Driver
+===============================================
+
+See the INSTALL document for information on installing the driver.
+
+Once installed, a typical method for launching the driver and the 
+regulatory daemon is via the load script provided in the source package:
+
+	# ./load debug=0x43fff   <--- You need to be root for this
+
+NOTE:  You will not be able to rmmod the driver so long as the 
+ipw3945d daemon is running.  
+
+If you followed the steps of the INSTALL document to set up your
+modprobe.conf, you can load the module by simply running:
+
+	# modprobe ipw3945       <--- You need to be root for this
+
+If you did not configure your modprobe.conf to automatically launch the 
+regulatory daemon (see INSTALL), you must do so manually after loading 
+the module:
+
+	# /sbin/ipw3945d	<--- You need to be root for this
+
+If you want to unload the module (and kill the deamon as well), you can 
+simply use the unload script:
+
+	# ./unload               <--- You need to be root for this
+
+or likewise if you configured modprobe.conf:
+
+	# modprobe -r ipw3945       <--- You need to be root for this
+
+If you did not configure modprobe.conf to unload the regulatory daemon 
+and are not using the unload script, you need to kill the regulatory 
+daemon before you will be able to unload the module:
+
+	# /sbin/ipw3945d --kill	<--- You need to be root for this
+	# modprobe -r ipw3945
+
+
+===============================================
+3. Feature Details
+===============================================
+
+3.1. LEDs
+-----------------------------------------------
+
+The driver will attempt to control the wireless LED, if one is 
+configured in hardware.  There are typically two LEDs:
+
+	Activity -- used to indicate wireless activity
+	Link     -- used to indicate wireless link
[...20344 lines suppressed...]
+ * a command to appear. Currently set to 60s. */
+#define DAEMON_POLL_INTERVAL 60000
+
+#define DAEMON_BUF_SIZE 3000
+
+struct daemon_cmd_hdr {
+	u8 cmd;
+	u8 flags;
+	u8 token;
+	u8 reserved1;
+	u16 version;
+	u16 data_len;
+	u8 data[0];
+} __attribute__ ((packed));
+
+struct daemon_cmd {
+	struct daemon_cmd_hdr hdr;
+	u8 data[DAEMON_BUF_SIZE];
+} __attribute__ ((packed));
+
+/*  driver <- daemon error response */
+struct daemon_error {
+	u8 cmd_requested;
+	u8 reserved1;
+	u16 reserved2;
+	s32 return_code;
+} __attribute__ ((packed));
+
+/*  driver <- daemon synchronous command done */
+struct daemon_cmd_done {
+	u8 cmd_requested;
+	u8 reserved1;
+	u16 reserved2;
+	s32 return_code;
+} __attribute__ ((packed));
+
+/*  driver <- daemon regulatory information
+ *
+ * The following is sent from the daemon to the driver
+ * to inform the driver of current channel capabilities and
+ * restrictions.
+ *
+ * Immediately after INIT is provided from the driver the
+ * daemon will send the full channel map.
+ *
+ * After a channel has been selected via rx_config, the
+ * daemon will send periodic updates when the channel limits
+ * change for a specific channel.
+ *
+ * NOTE:  The txpower field represents the current configured
+ * power as directed by either the user (sent to the daemon
+ * through the DAEMON_SYNC::DAEMON_SYNC_TXPOWER_LIMIT command)
+ * or as specified through the currently associated access
+ * point.  The max_txpower is the highest the channel is
+ * allowed to transmit.
+ *
+ */
+enum {
+	DAEMON_A_BAND = (1 << 0),	/* 0 - 2.4Ghz, 1 - 5.2Ghz */
+	DAEMON_IBSS_ALLOWED = (1 << 1),
+	DAEMON_ACTIVE_ALLOWED = (1 << 2),
+	DAEMON_RADAR_DETECT = (1 << 3),
+};
+struct daemon_channel_info {
+	u8 channel;
+	u8 flags;
+	s8 txpower;
+	s8 max_txpower;
+};
+struct daemon_regulatory_info {
+	u16 count;		/* Number of channels provided */
+	struct daemon_channel_info channel_info[0];
+} __attribute__ ((packed));
+
+/* driver <- daemon information request */
+struct daemon_request_info {
+	u8 request;
+} __attribute__ ((packed));
+
+/* driver <- daemon set state */
+struct daemon_set_state {
+	u8 state;
+} __attribute__ ((packed));
+
+/* driver -> daemon scan request */
+#define DAEMON_MIN_24GHZ_CHANNEL 1
+#define DAEMON_MAX_24GHZ_CHANNEL 14
+#define DAEMON_MIN_52GHZ_CHANNEL 34
+#define DAEMON_MAX_52GHZ_CHANNEL 165
+
+#define DAEMON_SCAN_FLAG_24GHZ  (1<<0)
+#define DAEMON_SCAN_FLAG_52GHZ  (1<<1)
+#define DAEMON_SCAN_FLAG_ACTIVE (1<<2)
+#define DAEMON_SCAN_FLAG_DIRECT (1<<3)
+
+#define DAEMON_MAX_CMD_SIZE 1024
+
+enum {
+	DAEMON_TXRATE_1 = 0xa,
+	DAEMON_TXRATE_2 = 0x14,
+	DAEMON_TXRATE_5_5 = 0x37,
+	DAEMON_TXRATE_6 = 0xd,
+	DAEMON_TXRATE_9 = 0xf,
+	DAEMON_TXRATE_11 = 0x6e,
+	DAEMON_TXRATE_12 = 0x5,
+	DAEMON_TXRATE_18 = 0x7,
+	DAEMON_TXRATE_24 = 0x9,
+	DAEMON_TXRATE_36 = 0xb,
+	DAEMON_TXRATE_48 = 0x1,
+	DAEMON_TXRATE_54 = 0x3,
+};
+
+struct daemon_scan_channel {
+	u8 channel;
+	u8 request_active;
+	u16 active_dwell;
+	u16 passive_dwell;
+} __attribute__ ((packed));
+
+struct daemon_ssid_ie {
+	u8 id;
+	u8 len;
+	u8 ssid[32];
+} __attribute__ ((packed));
+
+struct daemon_rx_config {
+	u8 dev_type;
+	u16 channel;
+	u32 flags;
+	u32 filter_flags;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	u8 node_addr[6];
+	u8 bssid_addr[6];
+	u16 assoc_id;
+	u16 beacon_interval;
+} __attribute__ ((packed));
+
+#define DAEMON_MAX_SCAN_SIZE 1024
+struct daemon_scan_request {
+	u8 flags;		/* 0 - 2.4Ghz, 1 - 5.2Ghz */
+	u8 channel_count;
+	u16 probe_request_len;
+	u16 quiet_time;		/* dwell only this long on quiet chnl (active scan) */
+	u16 quiet_plcp_th;	/* quiet chnl is < this # pkts (typ. 1) */
+	u32 suspend_time;	/* pause scan this long when returning to svc chnl */
+	u32 max_out_time;	/* max msec to be out of associated (service) chnl */
+	u8 probe_request_rate;	/* rate to send probe request */
+	u32 filter_flags;
+	u32 rxon_flags;
+	struct daemon_ssid_ie direct_scan;
+	u8 data[0];
+	/*
+	   The channels start after the probe request payload and are of type:
+
+	   struct daemon_scan_channel channels[0];
+
+	   NOTE:  Only one band of channels can be scanned per pass.  You
+	   can not mix 2.4Ghz channels and 5.2Ghz channels and must
+	   request a scan multiple times (not concurrently)
+
+	 */
+} __attribute__ ((packed));
+
+/* driver -> daemon 11h frame */
+struct daemon_80211_frame {
+	u8 channel;
+	u8 reserved1;
+	u16 rssi;
+	u16 reserved2;
+	u64 tsf;
+	u32 beacon_time;
+	u16 frame_len;
+	u8 frame[0];
+} __attribute__ ((packed));
+
+struct daemon_sync_txpower_limit {
+	u8 channel;
+	s8 power;
+} __attribute__ ((packed));
+
+enum {
+	DAEMON_SYNC_UNINIT = 0,
+	DAEMON_SYNC_INIT,
+	DAEMON_SYNC_SCAN_COMPLETE,
+	DAEMON_SYNC_TXPOWER_LIMIT,
+	DAEMON_SYNC_MEASURE_REPORT,
+	DAEMON_SYNC_TX_STATUS,
+	DAEMON_SYNC_SUSPEND,
+	DAEMON_SYNC_RESUME,
+};
+
+/* driver  -> daemon */
+struct daemon_sync_cmd {
+	u16 state;
+	u16 len;
+	u8 data[0];
+} __attribute__ ((packed));
+
+#endif

jwltest-ipw3945-1_1_0.patch:
 Documentation/networking/README.ipw3945 |   40 -
 drivers/net/wireless/ipw3945.c          |  809 +++++++++++++++++---------------
 drivers/net/wireless/ipw3945.h          |   17 
 3 files changed, 472 insertions(+), 394 deletions(-)

--- NEW FILE jwltest-ipw3945-1_1_0.patch ---
--- linux-2.6.18.noarch/Documentation/networking/README.ipw3945.orig	2006-09-20 15:30:01.000000000 -0400
+++ linux-2.6.18.noarch/Documentation/networking/README.ipw3945	2006-09-20 15:30:07.000000000 -0400
@@ -14,8 +14,8 @@
 
 README.ipw3945
 
-Version: 1.0.5
-Date   : May 22, 2006
+Version: 1.1.0
+Date   : July 14, 2006
 
 
 Index
@@ -113,7 +113,7 @@
 
 1.1. Overview of Features
 -----------------------------------------------
-The current release (1.0.5) supports the following features:
+The current release (1.1.0) supports the following features:
 
 + BSS mode (Infrastructure, Managed)
 + IBSS mode (Ad-Hoc)
@@ -163,7 +163,11 @@
 regulatory daemon (see INSTALL), you must do so manually after loading 
 the module:
 
-	# /sbin/ipw3945d	<--- You need to be root for this
+	# /sbin/ipw3945d	<--- You need to be root for this*
+
+* See README.ipw3945d (provided in the regulatory daemon package) for 
+  information on how to configure the system to run the regulatory 
+  daemon as a non-root user.
 
 If you want to unload the module (and kill the deamon as well), you can 
 simply use the unload script:
@@ -272,20 +276,15 @@
 
   The STA will not perform measurements requested by other STAs.
 
-IBSS is not supported on channels marked as DFS or passive-only.  As 
-such, supporting IBSS DFS is not required.  The use of IBSS networks 
-(starting or joining) on channels marked as spectrum managed is not 
-supported (since we do not support the full IBSS DFS owner mode)
+IBSS is not supported on channels marked passive-only. 
+
+The use of IBSS networks (starting or joining) on channels marked as 
+radar spectrum is also not supported.
 
 The user can manually control the transmit power control via the 
 iwconfig txpower command (see below for details on behavior of the
 txpower command with this driver).
 
-Channels indicated to require radar detection are only allowed to be 
-used in association with access points that advertise support for IEEE 
-802.11h.  To determine which channels require this, see the 'channels' 
-entry in the section 'Device Level Sysfs Helper Files.'
-
 
 3.7. Tx Power 
 -----------------------------------------------
@@ -455,7 +454,7 @@
 	info is logged.  See the 'dvals' and 'load' script for more info on
 	how to use this. 
 
-	The dvals and load scripts are provided in the ipw3945-1.0.5.tgz
+	The dvals and load scripts are provided in the ipw3945-1.1.0.tgz
 	development snapshot releases available from the SourceForge 
 	project at http://ipw3945.sf.net)
 
@@ -642,13 +641,10 @@
 	  36: 17dBm: BSS, IBSS, active/passive.
 	...
 	  48: 17dBm: BSS, IBSS, active/passive.
-	  52: 17dBm: BSS (IEEE 802.11h required), passive only.
+	  52: 17dBm: BSS (radar spectrum), passive only.
 	...
-	  136: 17dBm: BSS (IEEE 802.11h required), passive only.
-	  140: 17dBm: BSS (IEEE 802.11h required), passive only.
-
-	Channels where IEEE 802.11h is required will only associate with 
-	APs that have the Spectrum Management bit enabled.  
+	  136: 17dBm: BSS (radar spectrum), passive only.
+	  140: 17dBm: BSS (radar spectrum), passive only.
 
 	For channels marked where ad-hoc is not supported (IBSS is not 
 	listed), you can neither join or create an IBSS (ad-hoc) network 
@@ -686,6 +682,10 @@
 5. Wireless Tools Details
 ===============================================
 
+Due to an issue in handling 64-bit integers in the v28 based versions of 
+the wireless tools, we recommend that only wireless tools based on v29 be 
+used on 64-bit platforms.
+
 5.1. iwlist
 -----------------------------------------------
 
--- linux-2.6.18.noarch/drivers/net/wireless/ipw3945.c.orig	2006-09-20 15:30:01.000000000 -0400
+++ linux-2.6.18.noarch/drivers/net/wireless/ipw3945.c	2006-09-20 15:30:07.000000000 -0400
@@ -65,8 +65,16 @@
 #include <net/ieee80211_radiotap.h>
 #include <asm/div64.h>
 
+/* This matches the current version in FC6/RHEL5... */
+#define IEEE80211_API_VERSION	2
+
 #include "ipw3945.h"
 
+#if IEEE80211_API_VERSION != 1 && \
+    IEEE80211_API_VERSION != 2
+#error Incompatible ieee80211 subsystem version.  Please upgrade ipw3945 driver sources.
+#endif
+
 #ifdef CONFIG_IPW3945_DEBUG
 #define VD "d"
 #else
@@ -97,7 +105,7 @@
 #define VQ
 #endif
 
-#define IPW3945_VERSION "1.0.5" VD VM VP VR VQ
+#define IPW3945_VERSION "1.1.0" VD VM VP VR VQ
 
 #define DRV_DESCRIPTION	"Intel(R) PRO/Wireless 3945 Network Connection driver for Linux"
 #define DRV_COPYRIGHT	"Copyright(c) 2003-2006 Intel Corporation"
@@ -210,8 +218,6 @@
 static void ipw_down(struct ipw_priv *);
 static void ipw_bg_down(void *);
 
-static int init_supported_rates(struct ipw_priv *priv,
-				struct ipw_supported_rates *prates);
 static int ipw_card_show_info(struct ipw_priv *priv);
 static int ipw_query_eeprom(struct ipw_priv *priv, u32 offset,
 			    u32 len, u8 * buf);
@@ -2085,7 +2091,7 @@
 			       geo->bg[i].max_power,
 			       geo->bg[i].
 			       flags & IEEE80211_CH_RADAR_DETECT ?
-			       " (IEEE 802.11h requried)" : "",
+			       " (radar spectrum)" : "",
 			       ((geo->bg[i].flags & IEEE80211_CH_NO_IBSS)
 				|| (geo->bg[i].
 				    flags &
@@ -2877,7 +2883,27 @@
 	return rc;
 }
 
-static int ipw_send_rxon_assoc(struct ipw_priv *priv)
+static int ipw_rxon_assoc_callback(struct ipw_priv *priv,
+				   struct ipw_cmd *cmd, struct sk_buff *skb)
+{
+	struct ipw_rx_packet *res = NULL;
+
+	if (!skb) {
+		IPW_ERROR("error: response NULL in REPLY_RX_ON_ASSOC.\n");
+		return 1;
+	}
+
+	res = (struct ipw_rx_packet *)skb->data;
+	if (res->hdr.flags & 0x40) {
+		IPW_ERROR("bad return from REPLY_RX_ON_ASSOC.\n");
+		return 1;
+	}
+
+	dev_kfree_skb_any(skb);
+	return 0;
+}
+
+static int ipw_send_rxon_assoc(struct ipw_priv *priv, u8 flags)
 {
 	int rc = 0;
 	struct ipw_rx_packet *res = NULL;
@@ -2885,10 +2911,13 @@
 	struct ipw_host_cmd cmd = {
 		.id = REPLY_RX_ON_ASSOC,
 		.len = sizeof(struct ipw_rxon_assoc_cmd),
-		.meta.flags = CMD_WANT_SKB,
+		.meta.flags = flags,
 		.data = &rxon_assoc,
 	};
 
+	if (flags & CMD_ASYNC)
+		cmd.meta.u.callback = ipw_rxon_assoc_callback;
+
 	rxon_assoc.flags = priv->rxon.flags;
 	rxon_assoc.filter_flags = priv->rxon.filter_flags;
 	rxon_assoc.ofdm_basic_rates = priv->rxon.ofdm_basic_rates;
@@ -2896,7 +2925,7 @@
 	rxon_assoc.reserved = 0;
 
 	rc = ipw_send_cmd(priv, &cmd);
-	if (rc)
+	if (rc || (flags & CMD_ASYNC))
 		return rc;
 
 	res = (struct ipw_rx_packet *)cmd.meta.u.skb->data;
@@ -2910,6 +2939,18 @@
 	return rc;
 }
 
+static int ipw_rxon_assoc_async(struct ipw_priv *priv)
+{
+	u8 flags = CMD_ASYNC | CMD_NO_LOCK;
+	return ipw_send_rxon_assoc(priv, flags);
+}
+
+static int ipw_rxon_assoc_sync(struct ipw_priv *priv)
+{
+	u8 flags = CMD_WANT_SKB;
+	return ipw_send_rxon_assoc(priv, flags);
+}
+
 static int ipw_add_sta_sync_callback(struct ipw_priv *priv,
 				     struct ipw_cmd *cmd, struct sk_buff *skb)
 {
@@ -3091,25 +3132,6 @@
 	return -1;
 }
 
-static int ipw_rate_ieee2index(u8 x)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(rate_table_info); i++) {
-		if (rate_table_info[i].rate_ieee == x)
-			return i;
-	}
-	return -1;
-}
-
-static u8 ipw_rate_index2ieee(int x)
-{
-
-	if (x < ARRAY_SIZE(rate_table_info))
-		return rate_table_info[x].rate_ieee;
-
-	return IPW_INVALID_RATE;
-}
-
 static int ipw_rate_index2rate_scale(int x)
 {
 
@@ -3307,7 +3329,7 @@
 	 * If we're not associated, we need to request the regulatory
 	 * daemon to tune and configure the radio via ipw_send_rxon. */
 	if (is_assoc)
-		rc = ipw_send_rxon_assoc(priv);
+		rc = ipw_rxon_assoc_sync(priv);
 	else
 		rc = ipw_send_rx_config(priv);
 
@@ -3553,28 +3575,110 @@
 	return rc;
 }
 
+#define IEEE80211_MAX_RATES (IEEE80211_NUM_OFDM_RATES + \
+                             IEEE80211_NUM_CCK_RATES)
+#define IEEE80211_CCK_RATE_1MB_INDEX		0
+#define IEEE80211_CCK_RATE_2MB_INDEX		1
+#define IEEE80211_CCK_RATE_5MB_INDEX		2
+#define IEEE80211_CCK_RATE_11MB_INDEX		3
+#define IEEE80211_OFDM_RATE_6MB_INDEX		4
+#define IEEE80211_OFDM_RATE_9MB_INDEX		5
+#define IEEE80211_OFDM_RATE_12MB_INDEX		6
+#define IEEE80211_OFDM_RATE_18MB_INDEX		7
+#define IEEE80211_OFDM_RATE_24MB_INDEX		8
+#define IEEE80211_OFDM_RATE_36MB_INDEX		9
+#define IEEE80211_OFDM_RATE_48MB_INDEX		10
+#define IEEE80211_OFDM_RATE_54MB_INDEX		11
+#define IEEE80211_RATE_ENTRY(mod, rate) \
+        [IEEE80211_## mod ##_RATE_## rate ##MB_INDEX] = \
+        IEEE80211_## mod ##_RATE_## rate ##MB
+
+static u8 ipw_index_to_rate(int i)
+{
+	u8 rates[IEEE80211_MAX_RATES] = {
+		IEEE80211_RATE_ENTRY(CCK, 1),
+		IEEE80211_RATE_ENTRY(CCK, 2),
+		IEEE80211_RATE_ENTRY(CCK, 5),
+		IEEE80211_RATE_ENTRY(CCK, 11),
+		IEEE80211_RATE_ENTRY(OFDM, 6),
+		IEEE80211_RATE_ENTRY(OFDM, 9),
+		IEEE80211_RATE_ENTRY(OFDM, 12),
+		IEEE80211_RATE_ENTRY(OFDM, 18),
+		IEEE80211_RATE_ENTRY(OFDM, 24),
+		IEEE80211_RATE_ENTRY(OFDM, 36),
+		IEEE80211_RATE_ENTRY(OFDM, 48),
+		IEEE80211_RATE_ENTRY(OFDM, 54),
+	};
+
+	if (i >= IPW_MAX_RATES)
+		return 0xff;
+
+	return rates[i];
+}
+
+static void ipw_fill_network_rates(struct ieee80211_network *network,
+				   u32 rates_mask)
+{
+	int i, in_ex = 0;
+
+	network->rates_len = 0;
+	network->rates_ex_len = 0;
+
+	for (i = 0; i < IPW_MAX_RATES; i++) {
+		if (!(rates_mask & (1 << i)))
+			continue;
+
+		if (!in_ex) {
+			network->rates[network->rates_len] =
+			    ipw_index_to_rate(i);
+
+			/* If the rates mask has this rate flagged
+			 * as a basic rate then set the basic rate
+			 * bit on the rate entry */
+			if (rates_mask & (1 << (i + 16)))
+				network->rates[network->rates_len] |=
+				    IEEE80211_BASIC_RATE_MASK;
+
+			network->rates_len++;
+
+			if (network->rates_len == MAX_RATES_LENGTH)
+				in_ex = 1;
+		} else {
+			network->rates_ex[network->rates_ex_len] =
+			    ipw_index_to_rate(i);
+			if (rates_mask & (1 << (i + 16)))
+				network->rates_ex[network->rates_ex_len] |=
+				    IEEE80211_BASIC_RATE_MASK;
+			network->rates_ex_len++;
+		}
+	}
+}
+
 /*
   fill in the supported rate in IE fiels
   return : set the bit for each supported rate insert in ie
 */
 static u16 ipw_supported_rate_to_ie(struct ieee80211_info_element *ie,
-				    u16 supported_rate,
-				    u16 basic_rate, int max_count)
+				    const u16 rates_mask,
+				    const u16 basic_rate, const int max_count)
 {
-	u16 ret_rates = 0, bit;
+	u16 ret_rates = 0, mask;
+	u8 *rates = ie->data;
 	int i;
-	u8 *rates;
 
-	rates = &ie->data[0];
+	ie->len = 0;
+
+	for (i = 0, mask = 1; i < IPW_MAX_RATES; i++, mask <<= 1) {
+		if (rates_mask & mask) {
+			ret_rates |= mask;
+			rates[ie->len++] = ipw_index_to_rate(i) |
+			    ((mask & basic_rate) ? 0x80 : 0x00);
 
-	for (bit = 1, i = 0; i < IPW_MAX_RATES; i++, bit <<= 1) {
-		if (bit & supported_rate) {
-			ret_rates |= bit;
-			rates[ie->len++] = ipw_rate_index2ieee(i) |
-			    ((bit & basic_rate) ? 0x80 : 0x00);
 			if (ie->len >= max_count)
 				break;
-			//todoG for IBSS return only cck rates only in the first ie
+
+			/* todoG for IBSS return only cck rates only in
+			 * the first ie */
 		}
 	}
 
@@ -3715,6 +3819,11 @@
 
 	frame->capability = priv->assoc_request.capability & capability;
 
+	if (priv->assoc_request.ieee_mode == IPW_G_MODE)
+		frame->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
+	if (priv->assoc_request.ieee_mode != IPW_A_MODE)
+		frame->capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+
 	if (priv->config & CFG_PREAMBLE_LONG)
 		frame->capability &= ~WLAN_CAPABILITY_SHORT_PREAMBLE;
 
@@ -3733,12 +3842,17 @@
 	/* fill in supported rate */
 	info_element->id = MFIE_TYPE_RATES;
 	info_element->len = 0;
+	IPW_DEBUG_INFO("ASSOC REQ: Rates: %08X %08X\n", priv->active_rate,
+		       priv->active_rate_basic);
 	ret_rates =
-	    ipw_supported_rate_to_ie(info_element, priv->active_rate,
+	    ipw_supported_rate_to_ie(info_element,
+				     priv->active_rate & priv->rates_mask,
 				     priv->active_rate_basic,
 				     IPW_SUPPORTED_RATES_IE_LEN);
 
 	ret_rates = ~ret_rates & priv->active_rate;
+	IPW_DEBUG_INFO("ASSOC REQ: Rates: %08X %08X\n", priv->active_rate,
+		       priv->active_rate_basic);
 
 	/* Account for the size we know... */
 	len = sizeof(struct ieee80211_assoc_request) +
@@ -4114,6 +4228,14 @@
 	rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
 	rxon->assoc_id = assoc_id;
 	rxon->beacon_interval = priv->assoc_request.beacon_interval;
+
+	if (priv->assoc_request.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+		rxon->flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+
+	if ((priv->assoc_request.ieee_mode == IPW_G_MODE) &&
+	    (priv->assoc_request.capability & WLAN_CAPABILITY_SHORT_SLOT_TIME))
+		rxon->flags |= RXON_FLG_SHORT_SLOT_MSK;
+
 /*	switch (priv->ieee->sec.level) {
 	case SEC_LEVEL_1:
 	rxon->flags |= */
@@ -4186,17 +4308,9 @@
 	memcpy(priv->ieee->bssid, priv->bssid, ETH_ALEN);
 	memcpy(rxon->bssid_addr, associate->bssid, ETH_ALEN);
 	rxon->channel = associate->channel;
-	rxon->flags =
-	    (RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_ANT_B_MSK);
 
 	rxon->filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;	// todoG is this needed
 
-	if (associate->ieee_mode == IPW_A_MODE)
-		rxon->flags |= RXON_FLG_SHORT_SLOT_MSK;
-	else
-		rxon->flags |=
-		    (RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK);
-
 	switch (priv->ieee->iw_mode) {
 	case IW_MODE_INFRA:
 		rxon->dev_type = RXON_DEV_TYPE_ESS;
@@ -4224,16 +4338,19 @@
 				       RXON_FILTER_CTL2HOST_MSK);
 #endif
 
+	rxon->flags =
+	    (RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_ANT_B_MSK);
+
 	if (associate->ieee_mode == IPW_A_MODE) {
-		priv->rxon.flags &=
+		rxon->flags &=
 		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
 		      | RXON_FLG_CCK_MSK);
-		priv->rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		rxon->flags |= RXON_FLG_SHORT_SLOT_MSK;
 	} else {
-		priv->rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-		priv->rxon.flags |= RXON_FLG_BAND_24G_MSK;
-		priv->rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
-		priv->rxon.flags &= ~RXON_FLG_CCK_MSK;
+		rxon->flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+		rxon->flags |= RXON_FLG_BAND_24G_MSK;
+		rxon->flags |= RXON_FLG_AUTO_DETECT_MSK;
+		rxon->flags &= ~RXON_FLG_CCK_MSK;
 	}
 
 	if ((associate->capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
@@ -4241,29 +4358,27 @@
 	else
 		priv->rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
-	if ((priv->rxon.flags & RXON_FLG_BAND_24G_MSK) &&
+	if ((rxon->flags & RXON_FLG_BAND_24G_MSK) &&
 	    (associate->ieee_mode == IPW_G_MODE)) {
 		if (associate->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
-			priv->rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+			rxon->flags |= RXON_FLG_SHORT_SLOT_MSK;
 		else
-			priv->rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+			rxon->flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
 		if (associate->erp_value & IEEE80211_ERP_USE_PROTECTION)
-			priv->rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
+			rxon->flags |= RXON_FLG_TGG_PROTECT_MSK;
 		else
-			priv->rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+			rxon->flags &= ~RXON_FLG_TGG_PROTECT_MSK;
 	}
 
-	priv->rxon.cck_basic_rates =
-	    ((priv->active_rate_basic & 0xF) | R_1M_MSK);
-	priv->rxon.ofdm_basic_rates =
-	    ((priv->active_rate_basic >> 4) | R_6M_MSK);
+	rxon->cck_basic_rates = ((priv->active_rate_basic & 0xF) | R_1M_MSK);
+	rxon->ofdm_basic_rates = ((priv->active_rate_basic >> 4) | R_6M_MSK);
 
 	if ((priv->active_rate_basic & 0xF) == 0)
-		priv->rxon.cck_basic_rates =
+		rxon->cck_basic_rates =
 		    R_1M_MSK | R_2M_MSK | R_5_5M_MSK | R_11M_MSK;
 	if (priv->active_rate_basic >> 4 == 0)
-		priv->rxon.ofdm_basic_rates = R_6M_MSK | R_12M_MSK | R_24M_MSK;
+		rxon->ofdm_basic_rates = R_6M_MSK | R_12M_MSK | R_24M_MSK;
 
 	rc = ipw_rxon_call(priv, 0);
 	if (rc)
@@ -4287,10 +4402,15 @@
 		} else {
 			unsigned long flags;
 			spin_lock_irqsave(&priv->lock, flags);
+#if IEEE80211_API_VERSION >= 2
 			rc = ieee80211_tx_frame(priv->ieee,
 						(struct ieee80211_hdr
-						 *)&frame, IEEE80211_3ADDR_LEN,
-						sizeof(frame), 0);
+						 *)&frame, 0, sizeof(frame), 0);
+#else
+			rc = ieee80211_tx_frame(priv->ieee,
+						(struct ieee80211_hdr
+						 *)&frame, sizeof(frame));
+#endif
 			spin_unlock_irqrestore(&priv->lock, flags);
 		}
 	}
@@ -4407,27 +4527,24 @@
 	return rc;
 }
 
-static void ipw_send_supported_rates(struct ipw_priv *priv, struct ipw_supported_rates
-				     *rates)
+static void ipw_set_supported_rates_mask(struct ipw_priv *priv, int rates_mask)
 {
-	int index, i;
-	u8 rate, basic;
+	priv->active_rate = rates_mask & 0xffff;
+	priv->active_rate_basic = (rates_mask >> 16) & 0xffff;
+}
 
-	priv->active_rate = 0;
-	priv->active_rate_basic = 0;
-	for (i = 0; i < rates->num_rates; i++) {
-		rate = rates->supported_rates[i];
-		if (rate & IEEE80211_BASIC_RATE_MASK)
-			basic = 1;
-		else
-			basic = 0;
-		rate &= ~IEEE80211_BASIC_RATE_MASK;
-		index = ipw_rate_ieee2index(rate);
-		if (index != -1) {
-			priv->active_rate |= (1 << index);
-			if (basic == 1)
-				priv->active_rate_basic |= (1 << index);
-		}
+static void ipw_init_rates_mask(struct ipw_priv *priv)
+{
+	priv->rates_mask = 0;
+
+	if (priv->ieee->modulation & IEEE80211_OFDM_MODULATION) {
+		priv->rates_mask |= IEEE80211_OFDM_DEFAULT_RATES_MASK;
+		priv->rates_mask |= IEEE80211_OFDM_BASIC_RATES_MASK << 16;
+	}
+
+	if (priv->ieee->modulation & IEEE80211_CCK_MODULATION) {
+		priv->rates_mask |= IEEE80211_CCK_DEFAULT_RATES_MASK;
+		priv->rates_mask |= IEEE80211_CCK_BASIC_RATES_MASK << 16;
 	}
 }
 
@@ -4476,8 +4593,8 @@
 		netif_carrier_off(priv->net_dev);
 	}
 
-	init_supported_rates(priv, &priv->rates);
-	ipw_send_supported_rates(priv, &priv->rates);
+	ipw_init_rates_mask(priv);
+	ipw_set_supported_rates_mask(priv, priv->rates_mask);
 
 #ifdef CONFIG_IPW3945_QOS
 	ipw_qos_activate(priv, NULL);
@@ -4761,10 +4878,15 @@
 			break;
 
 		case DAEMON_FRAME_TX:
+#if IEEE80211_API_VERSION >= 2
 			ieee80211_tx_frame(priv->ieee, (struct ieee80211_hdr *)
-					   daemon_cmd->cmd.data,
-					   IEEE80211_3ADDR_LEN,
+					   daemon_cmd->cmd.data, 0,
 					   daemon_cmd->cmd.data_len, 0);
+#else
+			ieee80211_tx_frame(priv->ieee, (struct ieee80211_hdr *)
+					   daemon_cmd->cmd.data,
+					   daemon_cmd->cmd.data_len);
+#endif
 			daemon_cmd->cmd.data_len = 0;
 			spin_lock_irqsave(&priv->daemon_lock, flags);
 			list_add_tail(&daemon_cmd->list,
@@ -7179,208 +7301,151 @@
 	return 0;
 }
 
-static int ipw_is_rate_in_mask(struct ipw_priv *priv, int ieee_mode, u8 rate)
+#define IEEE80211_RATE_INDEX_MASK (0xf)
+#define IEEE80211_RATE_MASKED (1 << 14)
+#define IEEE80211_RATE_INVALID (1 << 13)
+/* Given a modulation (OFDM or CCK), the rate (1,2,5,6,9,11,12,18,24,36,48,54)
+ * and a bit mask, verify that the rate is supported in that bitmask and return
+ * the rate with the IEEE80211_RATE_MASKED bit set or cleared as appropriate */
+#define IEEE80211_RATE_IN_MASK(mod, rate, mask) \
+        case IEEE80211_## mod ##_RATE_## rate ##MB: \
+             return (mask & IEEE80211_## mod ##_RATE_## rate ##MB_MASK) ? \
+                     IEEE80211_## mod ##_RATE_## rate ##MB_INDEX : \
+                     (IEEE80211_RATE_MASKED | \
+                     IEEE80211_## mod ##_RATE_## rate ##MB_INDEX)
+
+static u16 ipw_is_rate_in_mask(struct ipw_priv *priv, u8 rate, u16 mask)
 {
 	rate &= ~IEEE80211_BASIC_RATE_MASK;
-	if (ieee_mode == IEEE_A) {
-		switch (rate) {
-		case IEEE80211_OFDM_RATE_6MB:
-			return priv->
-			    rates_mask & IEEE80211_OFDM_RATE_6MB_MASK ? 1 : 0;
-		case IEEE80211_OFDM_RATE_9MB:
-			return priv->
-			    rates_mask & IEEE80211_OFDM_RATE_9MB_MASK ? 1 : 0;
-		case IEEE80211_OFDM_RATE_12MB:
-			return priv->
-			    rates_mask & IEEE80211_OFDM_RATE_12MB_MASK ? 1 : 0;
-		case IEEE80211_OFDM_RATE_18MB:
-			return priv->
-			    rates_mask & IEEE80211_OFDM_RATE_18MB_MASK ? 1 : 0;
-		case IEEE80211_OFDM_RATE_24MB:
-			return priv->
-			    rates_mask & IEEE80211_OFDM_RATE_24MB_MASK ? 1 : 0;
-		case IEEE80211_OFDM_RATE_36MB:
-			return priv->
-			    rates_mask & IEEE80211_OFDM_RATE_36MB_MASK ? 1 : 0;
-		case IEEE80211_OFDM_RATE_48MB:
-			return priv->
-			    rates_mask & IEEE80211_OFDM_RATE_48MB_MASK ? 1 : 0;
-		case IEEE80211_OFDM_RATE_54MB:
-			return priv->
-			    rates_mask & IEEE80211_OFDM_RATE_54MB_MASK ? 1 : 0;
-		default:
-			return 0;
-		}
-	}
 
-	/* B and G mixed */
 	switch (rate) {
-	case IEEE80211_CCK_RATE_1MB:
-		return priv->rates_mask & IEEE80211_CCK_RATE_1MB_MASK ? 1 : 0;
-	case IEEE80211_CCK_RATE_2MB:
-		return priv->rates_mask & IEEE80211_CCK_RATE_2MB_MASK ? 1 : 0;
-	case IEEE80211_CCK_RATE_5MB:
-		return priv->rates_mask & IEEE80211_CCK_RATE_5MB_MASK ? 1 : 0;
-	case IEEE80211_CCK_RATE_11MB:
-		return priv->rates_mask & IEEE80211_CCK_RATE_11MB_MASK ? 1 : 0;
-	}
-
-	/* If we are limited to B modulations, bail at this point */
-	if (ieee_mode == IEEE_B)
-		return 0;
-	/* G */
-	switch (rate) {
-	case IEEE80211_OFDM_RATE_6MB:
-		return priv->rates_mask & IEEE80211_OFDM_RATE_6MB_MASK ? 1 : 0;
-	case IEEE80211_OFDM_RATE_9MB:
-		return priv->rates_mask & IEEE80211_OFDM_RATE_9MB_MASK ? 1 : 0;
-	case IEEE80211_OFDM_RATE_12MB:
-		return priv->rates_mask & IEEE80211_OFDM_RATE_12MB_MASK ? 1 : 0;
-	case IEEE80211_OFDM_RATE_18MB:
-		return priv->rates_mask & IEEE80211_OFDM_RATE_18MB_MASK ? 1 : 0;
-	case IEEE80211_OFDM_RATE_24MB:
-		return priv->rates_mask & IEEE80211_OFDM_RATE_24MB_MASK ? 1 : 0;
-	case IEEE80211_OFDM_RATE_36MB:
-		return priv->rates_mask & IEEE80211_OFDM_RATE_36MB_MASK ? 1 : 0;
-	case IEEE80211_OFDM_RATE_48MB:
-		return priv->rates_mask & IEEE80211_OFDM_RATE_48MB_MASK ? 1 : 0;
-	case IEEE80211_OFDM_RATE_54MB:
-		return priv->rates_mask & IEEE80211_OFDM_RATE_54MB_MASK ? 1 : 0;
-	}
-
-	return 0;
-}
+		IEEE80211_RATE_IN_MASK(OFDM, 6, mask);
+		IEEE80211_RATE_IN_MASK(OFDM, 9, mask);
+		IEEE80211_RATE_IN_MASK(OFDM, 12, mask);
+		IEEE80211_RATE_IN_MASK(OFDM, 18, mask);
+		IEEE80211_RATE_IN_MASK(OFDM, 24, mask);
+		IEEE80211_RATE_IN_MASK(OFDM, 36, mask);
+		IEEE80211_RATE_IN_MASK(OFDM, 48, mask);
+		IEEE80211_RATE_IN_MASK(OFDM, 54, mask);
+		IEEE80211_RATE_IN_MASK(CCK, 1, mask);
+		IEEE80211_RATE_IN_MASK(CCK, 2, mask);
+		IEEE80211_RATE_IN_MASK(CCK, 5, mask);
+		IEEE80211_RATE_IN_MASK(CCK, 11, mask);
+	}
+
+	return IEEE80211_RATE_INVALID;
+}
+
+static u32 ipw_find_compatible_rates(struct ipw_priv *priv,
+				     const struct ieee80211_network *network,
+				     u16 rates_mask)
+{
+	int bit_index, i;
+	u32 rates = 0;
+
+	/* rates */
+	for (i = 0; i < network->rates_len; i++) {
+		bit_index = ipw_is_rate_in_mask(priv, network->rates[i],
+						rates_mask);
+		if (bit_index & IEEE80211_RATE_INVALID) {
+			IPW_DEBUG_RATE("Invalid rate requested: "
+				       "%02X\n", network->rates[i]);
+			continue;
+		}
 
-static int ipw_compatible_rates(struct ipw_priv *priv, const struct ieee80211_network
-				*network, struct ipw_supported_rates *rates)
-{
-	int num_rates, i;
-	memset(rates, 0, sizeof(*rates));
-	num_rates = min(network->rates_len, (u8) IPW_MAX_RATES);
-	rates->num_rates = 0;
-	for (i = 0; i < num_rates; i++) {
-		if (!ipw_is_rate_in_mask
-		    (priv, network->mode, network->rates[i])) {
+		if (bit_index & IEEE80211_RATE_MASKED) {
+			if (!(network->rates[i] & IEEE80211_BASIC_RATE_MASK)) {
+				IPW_DEBUG_RATE("Rate %02X masked : 0x%08X\n",
+					       network->rates[i], rates_mask);
 
-			if (network->rates[i] & IEEE80211_BASIC_RATE_MASK) {
-				IPW_DEBUG_SCAN
-				    ("Adding masked mandatory "
-				     "rate %02X\n", network->rates[i]);
-				rates->supported_rates[rates->
-						       num_rates++] =
-				    network->rates[i];
 				continue;
 			}
 
-			IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n",
-				       network->rates[i], priv->rates_mask);
-			continue;
+			/* Clear out any bits set in the mask that are not
+			 * specific rates (INVALID and MASKED bits) */
+			bit_index &= IEEE80211_RATE_INDEX_MASK;
+
+			IPW_DEBUG_RATE("Adding masked mandatory "
+				       "rate %02X\n", network->rates[i]);
 		}
 
-		rates->supported_rates[rates->num_rates++] = network->rates[i];
+		if (network->rates[i] & IEEE80211_BASIC_RATE_MASK)
+			rates |= (1 << (bit_index + 16));
+
+		rates |= (1 << bit_index);
 	}
 
-	num_rates = min(network->rates_ex_len,
-			(u8) (IPW_MAX_RATES - num_rates));
-	for (i = 0; i < num_rates; i++) {
-		if (!ipw_is_rate_in_mask
-		    (priv, network->mode, network->rates_ex[i])) {
-			if (network->rates_ex[i] & IEEE80211_BASIC_RATE_MASK) {
-				IPW_DEBUG_SCAN
-				    ("Adding masked mandatory "
-				     "rate %02X\n", network->rates_ex[i]);
-				rates->supported_rates[rates->
-						       num_rates++] =
-				    network->rates[i];
+	/* extended rates */
+	for (i = 0; i < network->rates_ex_len; i++) {
+		bit_index = ipw_is_rate_in_mask(priv, network->rates_ex[i],
+						rates_mask);
+		if (bit_index & IEEE80211_RATE_INVALID) {
+			IPW_DEBUG_RATE("Invalid rate requested: "
+				       "%02X\n", network->rates_ex[i]);
+			continue;
+		}
+
+		if (bit_index & IEEE80211_RATE_MASKED) {
+			if (!(network->rates_ex[i] & IEEE80211_BASIC_RATE_MASK)) {
+				IPW_DEBUG_RATE("Rate %02X masked : 0x%08X\n",
+					       network->rates_ex[i],
+					       rates_mask);
+
 				continue;
 			}
 
-			IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n",
-				       network->rates_ex[i], priv->rates_mask);
-			continue;
+			bit_index &= ~IEEE80211_RATE_INDEX_MASK;
+
+			IPW_DEBUG_RATE("Adding masked mandatory "
+				       "rate %02X\n", network->rates_ex[i]);
 		}
 
-		rates->supported_rates[rates->num_rates++] =
-		    network->rates_ex[i];
+		if (network->rates_ex[i] & IEEE80211_BASIC_RATE_MASK)
+			rates |= (1 << (bit_index + 16));
+
+		rates |= (1 << bit_index);
 	}
 
-	return 1;
+	return rates;
 }
 
-static inline void ipw_copy_rates(struct ipw_supported_rates *dest, const struct ipw_supported_rates
-				  *src)
+#if 0
+static int ipw_compatible_basic_rates(struct ipw_priv *priv,
+				      struct ieee80211_network *network,
+				      u32 rates_mask)
 {
-	u8 i;
-	for (i = 0; i < src->num_rates; i++)
-		dest->supported_rates[i] = src->supported_rates[i];
-	dest->num_rates = src->num_rates;
-}
-
-/* TODO: Look at sniffed packets in the air to determine if the basic rate
- * mask should ever be used -- right now all callers to add the scan rates are
- * set with the modulation = CCK, so BASIC_RATE_MASK is never set... */
-static void ipw_add_cck_scan_rates(struct ipw_supported_rates
-				   *rates, u8 modulation, u32 rate_mask)
-{
-	u8 basic_mask =
-	    (IEEE80211_OFDM_MODULATION ==
-	     modulation) ? IEEE80211_BASIC_RATE_MASK : 0;
-	if (rate_mask & IEEE80211_CCK_RATE_1MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
-	if (rate_mask & IEEE80211_CCK_RATE_2MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
-	if (rate_mask & IEEE80211_CCK_RATE_5MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    basic_mask | IEEE80211_CCK_RATE_5MB;
-	if (rate_mask & IEEE80211_CCK_RATE_11MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    basic_mask | IEEE80211_CCK_RATE_11MB;
-}
-
-static void ipw_add_ofdm_scan_rates(struct ipw_supported_rates
-				    *rates, u8 modulation, u32 rate_mask)
-{
-	u8 basic_mask =
-	    (IEEE80211_OFDM_MODULATION ==
-	     modulation) ? IEEE80211_BASIC_RATE_MASK : 0;
-	if (rate_mask & IEEE80211_OFDM_RATE_6MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    basic_mask | IEEE80211_OFDM_RATE_6MB;
-	if (rate_mask & IEEE80211_OFDM_RATE_9MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    IEEE80211_OFDM_RATE_9MB;
-	if (rate_mask & IEEE80211_OFDM_RATE_12MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    basic_mask | IEEE80211_OFDM_RATE_12MB;
-	if (rate_mask & IEEE80211_OFDM_RATE_18MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    IEEE80211_OFDM_RATE_18MB;
-	if (rate_mask & IEEE80211_OFDM_RATE_24MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    basic_mask | IEEE80211_OFDM_RATE_24MB;
-	if (rate_mask & IEEE80211_OFDM_RATE_36MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    IEEE80211_OFDM_RATE_36MB;
-	if (rate_mask & IEEE80211_OFDM_RATE_48MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    IEEE80211_OFDM_RATE_48MB;
-	if (rate_mask & IEEE80211_OFDM_RATE_54MB_MASK)
-		rates->supported_rates[rates->num_rates++] =
-		    IEEE80211_OFDM_RATE_54MB;
+	int i;
+
+	for (i = 0; i < network->rates_len; i++) {
+		if (!(network->rates[i] & IEEE80211_BASIC_RATE_MASK))
+			continue;
+		if (!ipw_is_rate_in_mask(priv, network->rates[i], rates_mask))
+			return 1;
+	}
+
+	for (i = 0; i < network->rates_ex_len; i++) {
+		if (!(network->rates_ex[i] & IEEE80211_BASIC_RATE_MASK))
+			continue;
+		if (!ipw_is_rate_in_mask(priv, network->rates_ex[i],
+					 rates_mask))
+			return 1;
+	}
+
+	return 0;
 }
+#endif
 
 struct ipw_network_match {
 	struct ieee80211_network *network;
-	struct ipw_supported_rates rates;
+	u32 rates_mask;
 };
+
 static int ipw_find_adhoc_network(struct ipw_priv *priv,
 				  struct ipw_network_match *match,
 				  struct ieee80211_network *network,
 				  int roaming)
 {
-	struct ipw_supported_rates rates;
+	u16 rates_mask;
 	/* Verify that this network's capability is compatible with the
 	 * current mode (AdHoc or Infrastructure) */
 	if ((priv->ieee->iw_mode == IW_MODE_ADHOC &&
@@ -7524,10 +7589,10 @@
 				MAC_ARG(network->bssid));
 		return 0;
 	}
-
+#if 0
 	/* Ensure that the rates supported by the driver are compatible with
 	 * this AP, including verification of basic rates (mandatory) */
-	if (!ipw_compatible_rates(priv, network, &rates)) {
+	if (!ipw_compatible_basic_rates(priv, network, priv->rates_mask)) {
 		IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
 				"because configured rate mask excludes "
 				"AP mandatory rate.\n",
@@ -7536,8 +7601,10 @@
 				MAC_ARG(network->bssid));
 		return 0;
 	}
+#endif
 
-	if (rates.num_rates == 0) {
+	rates_mask = ipw_find_compatible_rates(priv, network, priv->rates_mask);
+	if (!rates_mask) {
 		IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
 				"because of no compatible rates.\n",
 				escape_essid(network->ssid,
@@ -7551,7 +7618,7 @@
 	 * should occur within a generic IEEE 802.11 user space tool.  */
 
 	/* Set up 'new' AP to this network */
-	ipw_copy_rates(&match->rates, &rates);
+	match->rates_mask = rates_mask;
 	match->network = network;
 	IPW_DEBUG_MERGE("Network '%s (" MAC_FMT
 			")' is a viable match.\n",
@@ -7607,7 +7674,8 @@
 			    struct ipw_network_match *match,
 			    struct ieee80211_network *network, int roaming)
 {
-	struct ipw_supported_rates rates;
+	u32 rates_mask;
+
 	/* Verify that this network's capability is compatible with the
 	 * current mode (AdHoc or Infrastructure) */
 	if ((priv->ieee->iw_mode == IW_MODE_INFRA &&
@@ -7632,18 +7700,6 @@
 		return 0;
 	}
 
-	/* 802.11h Sanity Checks */
-	if ((ieee80211_get_channel_flags(priv->ieee, network->channel)
-	     & IEEE80211_CH_RADAR_DETECT)
-	    && !(network->capability & WLAN_CAPABILITY_SPECTRUM_MGMT)) {
-		IPW_DEBUG_SCAN("Network '%s (" MAC_FMT ")' "
-			       "is invalid - Spectrum Management mismatch.\n",
-			       escape_essid(network->ssid,
-					    network->ssid_len),
-			       MAC_ARG(network->bssid));
-		return 0;
-	}
-
 	if (network->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) {
 		if ((network->capability & WLAN_CAPABILITY_IBSS) &&
 		    !(network->flags & NETWORK_HAS_IBSS_DFS)) {
@@ -7822,10 +7878,10 @@
 				MAC_ARG(network->bssid));
 		return 0;
 	}
-
+#if 0
 	/* Ensure that the rates supported by the driver are compatible with
 	 * this AP, including verification of basic rates (mandatory) */
-	if (!ipw_compatible_rates(priv, network, &rates)) {
+	if (!ipw_compatible_basic_rates(priv, network, priv->rates_mask)) {
 		IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
 				"because configured rate mask excludes "
 				"AP mandatory rate.\n",
@@ -7834,8 +7890,10 @@
 				MAC_ARG(network->bssid));
 		return 0;
 	}
+#endif
 
-	if (rates.num_rates == 0) {
+	rates_mask = ipw_find_compatible_rates(priv, network, priv->rates_mask);
+	if (!rates_mask) {
 		IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
 				"because of no compatible rates.\n",
 				escape_essid(network->ssid,
@@ -7849,7 +7907,7 @@
 	 * should occur within a generic IEEE 802.11 user space tool.  */
 
 	/* Set up 'new' AP to this network */
-	ipw_copy_rates(&match->rates, &rates);
+	match->rates_mask = rates_mask;
 	match->network = network;
 	IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT
 			")' is a viable match.\n",
@@ -7964,12 +8022,8 @@
 		network->capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
 	if (priv->capability & CAP_PRIVACY_ON)
 		network->capability |= WLAN_CAPABILITY_PRIVACY;
-	network->rates_len = min(priv->rates.num_rates, MAX_RATES_LENGTH);
-	memcpy(network->rates, priv->rates.supported_rates, network->rates_len);
-	network->rates_ex_len = priv->rates.num_rates - network->rates_len;
-	memcpy(network->rates_ex,
-	       &priv->rates.supported_rates[network->rates_len],
-	       network->rates_ex_len);
+	ipw_fill_network_rates(network, priv->rates_mask);
+
 	network->last_scanned = 0;
 	network->flags = 0;
 	network->last_associate = 0;
@@ -9319,8 +9373,27 @@
 		if (auth->algorithm == WLAN_AUTH_SHARED_KEY &&
 		    *state <= CMAS_RX_AUTH_SEQ_4) {
 			if (auth->transaction == 2) {
-				struct sk_buff *skb_auth = NULL;
 				struct ieee80211_auth *auth2;
+#if IEEE80211_API_VERSION >= 2
+				BUG_ON(!priv->auth_frame);
+				auth2 = priv->auth_frame;
+				auth2->header.seq_ctl = 0;
+
+				memcpy(auth2->header.addr1, priv->bssid, 6);
+				memcpy(auth2->header.addr2, priv->mac_addr, 6);
+				memcpy(auth2->header.addr3,
+				       priv->ieee->bssid, 6);
+				auth2->algorithm = WLAN_AUTH_SHARED_KEY;
+				auth2->transaction = 3;
+				auth2->status = 0;
+
+				ieee80211_tx_frame(priv->ieee,
+						   (struct ieee80211_hdr *)
+						   priv->auth_frame,
+						   IEEE80211_3ADDR_LEN,
+						   sizeof(*auth2) + 130, 1);
+#else
+				struct sk_buff *skb_auth = NULL;
 				int tx_key =
 				    !(priv->ieee->sec.
 				      flags & SEC_ACTIVE_KEY) ? 0 : priv->ieee->
@@ -9377,13 +9450,14 @@
 
 				memcpy(priv->auth_frame,
 				       skb_auth->data, skb_auth->len);
+
 				ieee80211_tx_frame(priv->ieee,
 						   (struct ieee80211_hdr *)
 						   priv->auth_frame,
-						   IEEE80211_3ADDR_LEN,
-						   skb_auth->len, 0);
+						   skb_auth->len);
 				dev_kfree_skb_any(skb_auth);
 			      out_fail2:
+#endif
 				spin_unlock_irqrestore(&priv->lock, flags);
 				mutex_unlock(&priv->mutex);
 				return;
@@ -9426,8 +9500,12 @@
 		if (len) {
 			IPW_DEBUG_11H("Sending %d bytes.\n", len);
 			spin_lock_irqsave(&priv->lock, flags);
-			ieee80211_tx_frame(priv->ieee, &frame->u.frame,
-					   IEEE80211_3ADDR_LEN, len, 0);
+#if IEEE80211_API_VERSION >= 2
+			ieee80211_tx_frame(priv->ieee, &frame->u.frame, 0, len,
+					   0);
+#else
+			ieee80211_tx_frame(priv->ieee, &frame->u.frame, len);
+#endif
 			spin_unlock_irqrestore(&priv->lock, flags);
 		}
 
@@ -9496,9 +9574,11 @@
 		IPW_DEBUG_11H("Sending %d bytes.\n", len);
 		out_frame->u.frame.frame_ctl = IEEE80211_FTYPE_MGMT |
 		    IEEE80211_STYPE_PROBE_RESP;
-
-		ieee80211_tx_frame(priv->ieee, &out_frame->u.frame,
-				   IEEE80211_3ADDR_LEN, len, 0);
+#if IEEE80211_API_VERSION >= 2
+		ieee80211_tx_frame(priv->ieee, &out_frame->u.frame, 0, len, 0);
+#else
+		ieee80211_tx_frame(priv->ieee, &out_frame->u.frame, len);
+#endif
 	}
 
 	ipw_free_frame(priv, out_frame);
@@ -9571,8 +9651,7 @@
 	   priv->auth_state = CMAS_INIT;
 
 	   ieee80211_tx_frame(priv->ieee,
-	   		      (struct ieee80211_hdr *)&frame, 
-			      IEEE80211_3ADDR_LEN, sizeof(frame), 0);
+	   (struct ieee80211_hdr *)&frame, sizeof(frame));
 
 	   return 0;
 	 */
@@ -9736,6 +9815,7 @@
 	cancel_delayed_work(&priv->associate_timeout);
 
 	priv->assoc_request.assoc_id = resp->aid & 0x3fff;
+	priv->assoc_request.capability = network->capability;
 	queue_work(priv->workqueue, &priv->post_associate);
 #ifdef CONFIG_IPW3945_QOS
 	ipw_qos_association_resp(priv, network);
@@ -9771,7 +9851,7 @@
 
 static int ipw_associate_network(struct ipw_priv *priv,
 				 struct ieee80211_network *network,
-				 struct ipw_supported_rates *rates, int roaming)
+				 u32 rates_mask, int roaming)
 {
 	int err;
 	unsigned long flags;
@@ -9829,14 +9909,14 @@
 
 	IPW_DEBUG_ASSOC
 	    ("%sssociation attempt [%s]: '%s', channel %d, "
-	     "802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
+	     "802.11%c [%08X], %s[:%s], enc=%s%s%s%c%c\n",
 	     roaming ? "Rea" : "A",
 	     (priv->
 	      capability & WLAN_CAPABILITY_IBSS) ? "IBSS" : "BSS",
 	     escape_essid(priv->essid, priv->essid_len),
 	     network->channel,
 	     ipw_modes[priv->assoc_request.ieee_mode],
-	     rates->num_rates,
+	     rates_mask,
 	     (priv->assoc_request.preamble_length ==
 	      DCT_FLAG_LONG_PREAMBLE) ? "long" : "short",
 	     network->
@@ -9881,9 +9961,8 @@
 	}
 
 	priv->assoc_request.listen_interval = network->listen_interval;
-	rates->ieee_mode = priv->assoc_request.ieee_mode;
-	rates->purpose = IPW_RATE_CONNECT;
-	ipw_send_supported_rates(priv, rates);
+
+	ipw_set_supported_rates_mask(priv, rates_mask);
 
 	/*
 	 * If preemption is enabled, it is possible for the association
@@ -9977,8 +10056,8 @@
 	}
 
 	/* Second pass through ROAM process -- request association */
-	ipw_compatible_rates(priv, priv->assoc_network, &match.rates);
-	ipw_associate_network(priv, priv->assoc_network, &match.rates, 1);
+	ipw_find_compatible_rates(priv, priv->assoc_network, match.rates_mask);
+	ipw_associate_network(priv, priv->assoc_network, match.rates_mask, 1);
 	priv->status &= ~STATUS_ROAMING;
 }
 
@@ -10001,7 +10080,7 @@
 	struct ipw_network_match match = {
 		.network = NULL
 	};
-	struct ipw_supported_rates *rates;
+	u32 rates_mask;
 	struct list_head *element;
 	unsigned long flags;
 
@@ -10050,7 +10129,7 @@
 	list_for_each_entry(network, &priv->ieee->network_list, list)
 	    ipw_best_network(priv, &match, network, 0);
 	network = match.network;
-	rates = &match.rates;
+	rates_mask = match.rates_mask;
 	if (network == NULL &&
 	    priv->ieee->iw_mode == IW_MODE_ADHOC &&
 	    priv->config & CFG_ADHOC_CREATE &&
@@ -10060,7 +10139,7 @@
 		element = priv->ieee->network_free_list.next;
 		network = list_entry(element, struct ieee80211_network, list);
 		if (!ipw_adhoc_create(priv, network)) {
-			rates = &priv->rates;
+			rates_mask = priv->rates_mask;
 			list_del(element);
 			list_add_tail(&network->list,
 				      &priv->ieee->network_list);
@@ -10077,7 +10156,7 @@
 		return 0;
 	}
 
-	ipw_associate_network(priv, network, rates, 0);
+	ipw_associate_network(priv, network, rates_mask, 0);
 	return 1;
 }
 
@@ -11853,7 +11932,7 @@
 	struct ipw_priv *priv = ieee80211_priv(dev);
 	struct iw_range *range = (struct iw_range *)extra;
 	const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee);
-	int i = 0, j;
+	int i = 0, j, mask;
 
 	if (!ipw_is_ready(priv))
 		return -EAGAIN;
@@ -11873,10 +11952,16 @@
 	range->avg_qual.noise = 0;
 	range->avg_qual.updated = 7;	/* Updated all three */
 	mutex_lock(&priv->mutex);
-	range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES);
-	for (i = 0; i < range->num_bitrates; i++)
-		range->bitrate[i] =
-		    (priv->rates.supported_rates[i] & 0x7F) * 500000;
+
+	j = 0;
+	for (i = 0, mask = 1; i < IPW_MAX_RATES; i++, mask <<= 1) {
+		if (!(priv->active_rate & mask))
+			continue;
+		range->bitrate[i] = ipw_index_to_rate(i) * 500000;
+		j++;
+	}
+	range->num_bitrates = j;
+
 	range->max_rts = MAX_RTS_THRESHOLD;
 	range->min_frag = MIN_FRAG_THRESHOLD;
 	range->max_frag = MAX_FRAG_THRESHOLD;
@@ -12117,8 +12202,7 @@
 	struct ipw_priv *priv = ieee80211_priv(dev);
 	u32 target_rate = wrqu->bitrate.value;
 	u32 fixed, mask;
-	int ret = 0, rc = -1;
-	struct ipw_supported_rates rates;
+	int rc = -1;
 
 	if (!ipw_is_ready(priv))
 		return -EAGAIN;
@@ -12194,7 +12278,7 @@
 		priv->config &= ~CFG_FIXED_RATE;
 	else
 		priv->config |= CFG_FIXED_RATE;
-	if (priv->rates_mask == mask) {
+	if ((priv->rates_mask & 0xffff) == mask) {
 		IPW_DEBUG_WX("Mask set to current mask.\n");
 		mutex_unlock(&priv->mutex);
 		return 0;
@@ -12206,11 +12290,14 @@
 		unsigned long flags;
 
 		spin_lock_irqsave(&priv->ieee->lock, flags);
-		ret = ipw_compatible_rates(priv, priv->assoc_network, &rates);
+		mask =
+		    ipw_find_compatible_rates(priv, priv->assoc_network,
+					      priv->rates_mask);
 		spin_unlock_irqrestore(&priv->ieee->lock, flags);
 	}
-	if ((ret) && (rates.num_rates != 0)) {
-		ipw_send_supported_rates(priv, &rates);
+
+	if (mask) {
+		ipw_set_supported_rates_mask(priv, mask);
 		priv->rxon.cck_basic_rates =
 		    ((priv->active_rate_basic & 0xF) | R_1M_MSK);
 		priv->rxon.ofdm_basic_rates =
@@ -12224,8 +12311,8 @@
 			    R_6M_MSK | R_12M_MSK | R_24M_MSK;
 
 		rc = ipw_rxon_call(priv, 1);
-
 	}
+
 	if (rc) {
 		/* Network configuration changed -- force [re]association */
 		IPW_DEBUG_ASSOC
@@ -13113,13 +13200,18 @@
 	priv->ieee->mode = mode;
 	priv->ieee->freq_band = band;
 	priv->ieee->modulation = modulation;
-	init_supported_rates(priv, &priv->rates);
+
+	ipw_init_rates_mask(priv);
+	ipw_set_supported_rates_mask(priv, priv->rates_mask);
+
+	IPW_DEBUG_INFO("ASSOC REQ: Rates: %08X %08X %08X\n",
+		       priv->rates_mask,
+		       priv->active_rate, priv->active_rate_basic);
+
 	/* Network configuration changed -- force [re]association */
 	IPW_DEBUG_ASSOC("[re]association triggered due to mode change.\n");
-	if (!ipw_disassociate(priv)) {
-		ipw_send_supported_rates(priv, &priv->rates);
+	if (!ipw_disassociate(priv))
 		ipw_associate(priv);
-	}
 
 	IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n",
 		     mode & IEEE_A ? 'a' : '.',
@@ -15435,43 +15527,6 @@
 	mutex_unlock(&priv->mutex);
 }
 
-static int init_supported_rates(struct ipw_priv *priv,
-				struct ipw_supported_rates *rates)
-{
-	/* TODO: Mask out rates based on priv->rates_mask */
-
-	memset(rates, 0, sizeof(*rates));
-	/* configure supported rates */
-	switch (priv->ieee->freq_band) {
-	case IEEE80211_52GHZ_BAND:
-		rates->ieee_mode = IPW_A_MODE;
-		rates->purpose = IPW_RATE_CAPABILITIES;
-		ipw_add_ofdm_scan_rates(rates,
-					IEEE80211_OFDM_MODULATION,
-					IEEE80211_OFDM_DEFAULT_RATES_MASK);
-		break;
-	default:		/* Mixed or 2.4Ghz */
-		rates->ieee_mode = IPW_G_MODE;
-		rates->purpose = IPW_RATE_CAPABILITIES;
-		ipw_add_cck_scan_rates(rates,
-				       IEEE80211_CCK_MODULATION,
-				       IEEE80211_CCK_DEFAULT_RATES_MASK);
-		if (priv->ieee->modulation & IEEE80211_OFDM_MODULATION) {
-			u8 modulation = IEEE80211_CCK_MODULATION;
-
-			if (!
-			    (priv->ieee->modulation & IEEE80211_CCK_MODULATION))
-				modulation = IEEE80211_OFDM_MODULATION;
-
-			ipw_add_ofdm_scan_rates(rates, modulation,
-						IEEE80211_OFDM_DEFAULT_RATES_MASK);
-		}
-		break;
-	}
-
-	return 0;
-}
-
 /*
   Power management (not Tx power!) functions
 */
@@ -15646,11 +15701,14 @@
   call registered function about change in current network
   beacon
 */
-static int ipw_card_bss_active_changed_notify(struct ipw_priv *priv, struct ieee80211_network
-					      *network)
+static int ipw_card_bss_active_changed_notify(struct ipw_priv *priv,
+					      struct ieee80211_network *network)
 {
 	int rc = 0;
 	u8 period = 0;
+	struct daemon_rx_config rxon;
+
+	memcpy(&rxon, &priv->rxon, sizeof(rxon));
 
 	if (network != NULL)
 		period = network->tim.tim_period;
@@ -15663,6 +15721,29 @@
 		else
 			priv->power_data.active_index = IPW_POWER_RANGE_1;
 	}
+
+	if (network->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+		priv->rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		priv->rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+	if (priv->assoc_request.ieee_mode == IPW_G_MODE) {
+		if (network->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+			priv->rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		else
+			priv->rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+
+		if (network->erp_value & IEEE80211_ERP_USE_PROTECTION)
+			priv->rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
+		else
+			priv->rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+	}
+
+	if (memcmp(&rxon, &priv->rxon, sizeof(rxon))) {
+		IPW_DEBUG_INFO("rxon changed\n");
+		ipw_rxon_assoc_async(priv);
+	}
+
 	return rc;
 }
 
@@ -16265,7 +16346,9 @@
 		goto out_destroy_workqueue;
 	}
 
-	priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK;
+	priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK |
+	    (IEEE80211_OFDM_BASIC_RATES_MASK |
+	     IEEE80211_CCK_BASIC_RATES_MASK) << 16;
 	priv->missed_beacon_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT;
 	priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT;
 	priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
--- linux-2.6.18.noarch/drivers/net/wireless/ipw3945.h.orig	2006-09-20 15:30:01.000000000 -0400
+++ linux-2.6.18.noarch/drivers/net/wireless/ipw3945.h	2006-09-20 15:30:07.000000000 -0400
@@ -1751,14 +1751,6 @@
 	spinlock_t lock;
 };				/* Not transferred over network, so not  __attribute__ ((packed)) */
 
-#define IPW_SUPPORTED_RATES_IE_LEN         8
-#define IPW_MAX_RATES                     12
-
-struct ipw_rates {
-	u8 num_rates;
-	u8 rates[IPW_MAX_RATES];
-} __attribute__ ((packed));
-
 struct ipw_multicast_addr {
 	u8 num_of_multicast_addresses;
 	u8 reserved[3];
@@ -1800,6 +1792,9 @@
 	u8 erp_value;
 } __attribute__ ((packed));
 
+#define IPW_SUPPORTED_RATES_IE_LEN         8
+#define IPW_MAX_RATES                     12
+
 struct ipw_supported_rates {
 	u8 ieee_mode;
 	u8 num_rates;
@@ -2177,6 +2172,8 @@
 	struct ipw_activity_blink activity;
 	unsigned long led_packets;
 	int led_state;
+
+	u32 rates_mask;
 	u16 active_rate;
 	u16 active_rate_basic;
 
@@ -2214,15 +2211,13 @@
 	struct ipw_associate assoc_request;
 	struct ieee80211_network *assoc_network;
 
-	struct ipw_supported_rates rates;
-
 	struct ipw_notif_statistics statistics;
 
 	/* context information */
 	u8 essid[IW_ESSID_MAX_SIZE];
 	u8 essid_len;
 	u8 nick[IW_ESSID_MAX_SIZE];
-	u16 rates_mask;
+
 	u8 channel;
 	u32 power_mode;
 	u32 antenna;

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;


Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/FC-6/kernel-2.6.spec,v
retrieving revision 1.2895
retrieving revision 1.2895.8.1
diff -u -r1.2895 -r1.2895.8.1
--- kernel-2.6.spec	10 Jan 2007 23:18:29 -0000	1.2895
+++ kernel-2.6.spec	14 Feb 2007 23:03:10 -0000	1.2895.8.1
@@ -33,7 +33,7 @@
 %define sublevel 19
 %define kversion 2.6.%{sublevel}
 %define rpmversion 2.6.%{sublevel}
-%define release %(R="$Revision$"; RR="${R##: }"; echo ${RR%%?})%{?dist}
+%define release %(R="$Revision$"; RR="${R##: }"; echo ${RR%%?})%{?dist}.jwltest.19
 %define signmodules 0
 %define xen_hv_cset 11774
 %define make_target bzImage
@@ -410,6 +410,14 @@
 # core networking changes.
 
 # NIC driver fixes
+Patch1350: jwltest-ipw3945-1_0_5.patch
+Patch1351: jwltest-ipw3945-1_1_0.patch
+Patch1352: jwltest-bcm43xx-2_6_20.patch
+Patch1353: jwltest-bcm43xx-workqueue-undo.patch
+Patch1354: jwltest-bcm43xx-host_strip_iv_icv-undo.patch
+Patch1355: jwltest-bcm43xx-post-2_6_20.patch
+Patch1356: jwltest-softmac_wx_get_rate-running-check.patch
+Patch1357: jwltest-prism54-wpa-fix.patch
 
 # Filesystem stuff.
 # Squashfs
@@ -484,6 +492,11 @@
 Patch5060: linux-2.6-olpc-battery.patch
 
 #
+# d80211 backport
+#
+Patch6000: jwltest-d80211-backport.patch
+
+#
 # 10000 to 20000 is for stuff that has to come last due to the
 # amount of drivers they touch. But only these should go here.
 # Not patches you're too lazy for to put in the proper place.
@@ -965,6 +978,22 @@
 # core networking changes.
 
 # NIC driver fixes
+# ipw3945 1.0.5
+%patch1350 -p1
+# ipw3945 1.1.0
+%patch1351 -p1
+# bcm43xx: update to version from 2.6.20
+%patch1352 -p1
+# bcm43xx: revert workqueue-related changes
+%patch1353 -p1
+# bcm43xx: revert host_strip_iv_icv-related changes
+%patch1354 -p1
+# bcm43xx: update to version from 2007-02-08
+%patch1355 -p1
+# check mac->running to avoid assert in ieee80211softmac_wx_get_rate
+%patch1356 -p1
+# prism54: fix WPA support (dcbw)
+%patch1357 -p1
 
 # Filesystem patches.
 # Squashfs
@@ -1084,6 +1113,9 @@
 # final stuff
 #
 
+# d80211 stuff
+%patch6000 -p1
+
 #
 # misc small stuff to make things compile or otherwise improve performance
 #




More information about the fedora-cvs-commits mailing list