rpms/kernel/FC-5 jwltest-bcm43xx-wx-overflow.patch, NONE, 1.1.10.1 jwltest-ipw3945-1_0_5.patch, NONE, 1.1.4.1 jwltest-ipw3945-1_1_0.patch, NONE, 1.1.2.1 jwltest-ipw3945-ipw_bg_calibrated_work-lockdep.patch, NONE, 1.1.2.1 jwltest-sk98lin-neuter.patch, NONE, 1.1.26.1 kernel-2.6.spec, 1.2195, 1.2195.2.1

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Mon Oct 9 19:28:20 UTC 2006


Author: linville

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

Modified Files:
      Tag: private-linville-jwltest-fc5-17-branch
	kernel-2.6.spec 
Added Files:
      Tag: private-linville-jwltest-fc5-17-branch
	jwltest-bcm43xx-wx-overflow.patch jwltest-ipw3945-1_0_5.patch 
	jwltest-ipw3945-1_1_0.patch 
	jwltest-ipw3945-ipw_bg_calibrated_work-lockdep.patch 
	jwltest-sk98lin-neuter.patch 
Log Message:


jwltest-bcm43xx-wx-overflow.patch:
 bcm43xx_wx.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

--- NEW FILE jwltest-bcm43xx-wx-overflow.patch ---
--- linux-2.6.15.noarch/drivers/net/wireless/bcm43xx/bcm43xx_wx.c.orig	2006-03-06 16:59:32.000000000 -0500
+++ linux-2.6.15.noarch/drivers/net/wireless/bcm43xx/bcm43xx_wx.c	2006-03-06 16:59:38.000000000 -0500
@@ -858,12 +858,6 @@ static int bcm43xx_wx_sprom_write(struct
 	if (!capable(CAP_SYS_RAWIO))
 		goto out;
 
-	err = -ENOMEM;
-	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
-			GFP_KERNEL);
-	if (!sprom)
-		goto out;
-
 	len = data->data.length;
 	extra[len - 1] = '\0';
 	input = strchr(extra, ':');
@@ -872,6 +866,19 @@ static int bcm43xx_wx_sprom_write(struct
 		len -= input - extra;
 	} else
 		input = extra;
+
+	if (len > BCM43xx_SPROM_SIZE * sizeof(*sprom)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+			GFP_KERNEL);
+	if (!sprom) {
+		err = -ENOMEM;
+		goto out;
+	}
+
 	err = hex2sprom(sprom, input, len);
 	if (err)
 		goto out_kfree;

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

--- NEW FILE jwltest-ipw3945-1_0_5.patch ---
--- linux-2.6.16.noarch/Documentation/networking/README.ipw3945.orig	2006-06-15 12:59:52.000000000 -0400
+++ linux-2.6.16.noarch/Documentation/networking/README.ipw3945	2006-06-15 12:59:58.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
[...20341 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          |  791 +++++++++++++++++---------------
 drivers/net/wireless/ipw3945.h          |   18 
 3 files changed, 466 insertions(+), 383 deletions(-)

--- NEW FILE jwltest-ipw3945-1_1_0.patch ---
--- linux-2.6.18.noarch/Documentation/networking/README.ipw3945.orig	2006-10-09 15:12:07.000000000 -0400
+++ linux-2.6.18.noarch/Documentation/networking/README.ipw3945	2006-10-09 15:13:27.000000000 -0400
@@ -14,8 +14,8 @@ Copyright (C) 2005 - 2006, Intel Corpora
 
 README.ipw3945
 
-Version: 1.0.5
-Date   : May 22, 2006
+Version: 1.1.0
+Date   : July 14, 2006
 
 
 Index
@@ -113,7 +113,7 @@ file.
 
 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 @@ If you did not configure your modprobe.c
 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 @@ result in the channel switching.
 
   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 @@ The general form is:
 	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 @@ For the device level files, see /sys/bus
 	  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 @@ For the device level files, see /sys/bus
 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-10-09 15:12:07.000000000 -0400
+++ linux-2.6.18.noarch/drivers/net/wireless/ipw3945.c	2006-10-09 15:22:39.000000000 -0400
@@ -65,8 +65,16 @@
 #include <net/ieee80211_radiotap.h>
 #include <asm/div64.h>
 
+/* This matches the current version in FC5/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_bg_up(void *);
 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 @@ static ssize_t show_channels(struct devi
 			       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 @@ static int ipw_send_rx_config(struct ipw
 	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 @@ static int ipw_send_rxon_assoc(struct ip
 	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 @@ static int ipw_send_rxon_assoc(struct ip
 	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 @@ static int ipw_send_rxon_assoc(struct ip
 	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 @@ static inline int ipw_rate_plcp2rate_sca
 	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 @@ static int ipw_rxon_call(struct ipw_priv
 	 * 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 @@ static int ipw_setup_rxon_timing(struct 
 	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 @@ static int ipw_fill_association_req(stru
 
 	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 @@ static int ipw_fill_association_req(stru
 	/* 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 @@ static int ipw_post_associate(struct ipw
 	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 @@ static int ipw_send_associate(struct ipw
 	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 @@ static int ipw_send_associate(struct ipw
 				       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 @@ static int ipw_send_associate(struct ipw
 	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,9 +4402,15 @@ static int ipw_send_associate(struct ipw
 		} 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, 0, sizeof(frame), 0);
+#else
 			rc = ieee80211_tx_frame(priv->ieee,
 						(struct ieee80211_hdr
 						 *)&frame, sizeof(frame));
+#endif
 			spin_unlock_irqrestore(&priv->lock, flags);
 		}
 	}
@@ -4406,27 +4527,24 @@ static int ipw_send_power_mode(struct ip
 	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;
 	}
 }
 
@@ -4475,8 +4593,8 @@ static void ipw_bg_calibrated_work(void 
 		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);
@@ -4760,9 +4878,15 @@ static void ipw_bg_daemon_cmd(void *data
 			break;
 
 		case DAEMON_FRAME_TX:
+#if IEEE80211_API_VERSION >= 2
+			ieee80211_tx_frame(priv->ieee, (struct ieee80211_hdr *)
+					   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,
@@ -7177,208 +7301,151 @@ static int ipw_queue_tx_hcmd(struct ipw_
 	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 &&
@@ -7522,10 +7589,10 @@ static int ipw_find_adhoc_network(struct
 				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",
@@ -7534,8 +7601,10 @@ static int ipw_find_adhoc_network(struct
 				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,
@@ -7549,7 +7618,7 @@ static int ipw_find_adhoc_network(struct
 	 * 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",
@@ -7605,7 +7674,8 @@ static int ipw_best_network(struct ipw_p
 			    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 &&
@@ -7630,18 +7700,6 @@ static int ipw_best_network(struct ipw_p
 		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)) {
@@ -7820,10 +7878,10 @@ static int ipw_best_network(struct ipw_p
 				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",
@@ -7832,8 +7890,10 @@ static int ipw_best_network(struct ipw_p
 				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,
@@ -7847,7 +7907,7 @@ static int ipw_best_network(struct ipw_p
 	 * 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",
@@ -7962,12 +8022,8 @@ static int ipw_adhoc_create(struct ipw_p
 		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;
@@ -9317,8 +9373,27 @@ static void ipw_auth_work(void *data)
 		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->
@@ -9375,12 +9450,14 @@ static void ipw_auth_work(void *data)
 
 				memcpy(priv->auth_frame,
 				       skb_auth->data, skb_auth->len);
+
 				ieee80211_tx_frame(priv->ieee,
 						   (struct ieee80211_hdr *)
 						   priv->auth_frame,
 						   skb_auth->len);
 				dev_kfree_skb_any(skb_auth);
 			      out_fail2:
+#endif
 				spin_unlock_irqrestore(&priv->lock, flags);
 				mutex_unlock(&priv->mutex);
 				return;
@@ -9423,7 +9500,12 @@ static void ipw_auth_work(void *data)
 		if (len) {
 			IPW_DEBUG_11H("Sending %d bytes.\n", len);
 			spin_lock_irqsave(&priv->lock, flags);
+#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);
 		}
 
@@ -9492,8 +9574,11 @@ static int ipw_handle_probe_request(stru
 		IPW_DEBUG_11H("Sending %d bytes.\n", len);
 		out_frame->u.frame.frame_ctl = IEEE80211_FTYPE_MGMT |
 		    IEEE80211_STYPE_PROBE_RESP;
-
+#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);
@@ -9730,6 +9815,7 @@ static int ipw_handle_assoc_response(str
 	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);
@@ -9765,7 +9851,7 @@ static int ipw_handle_disassoc(struct ne
 
 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;
@@ -9823,14 +9909,14 @@ static int ipw_associate_network(struct 
 
 	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->
@@ -9875,9 +9961,8 @@ static int ipw_associate_network(struct 
 	}
 
 	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
@@ -9971,8 +10056,8 @@ static void ipw_roam(void *data)
 	}
 
 	/* 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;
 }
 
@@ -9995,7 +10080,7 @@ static int ipw_associate(void *data)
 	struct ipw_network_match match = {
 		.network = NULL
 	};
-	struct ipw_supported_rates *rates;
+	u32 rates_mask;
 	struct list_head *element;
 	unsigned long flags;
 
@@ -10044,7 +10129,7 @@ static int ipw_associate(void *data)
 	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 &&
@@ -10054,7 +10139,7 @@ static int ipw_associate(void *data)
 		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);
@@ -10071,7 +10156,7 @@ static int ipw_associate(void *data)
 		return 0;
 	}
 
-	ipw_associate_network(priv, network, rates, 0);
+	ipw_associate_network(priv, network, rates_mask, 0);
 	return 1;
 }
 
@@ -11847,7 +11932,7 @@ static int ipw_wx_get_range(struct net_d
 	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;
@@ -11867,10 +11952,16 @@ static int ipw_wx_get_range(struct net_d
 	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;
@@ -12111,8 +12202,7 @@ static int ipw_wx_set_rate(struct net_de
 	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;
@@ -12188,7 +12278,7 @@ static int ipw_wx_set_rate(struct net_de
 		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;
@@ -12200,11 +12290,14 @@ static int ipw_wx_set_rate(struct net_de
 		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 =
@@ -12218,8 +12311,8 @@ static int ipw_wx_set_rate(struct net_de
 			    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
@@ -13107,13 +13200,18 @@ static int ipw_wx_set_wireless_mode(stru
 	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' : '.',
@@ -15429,43 +15527,6 @@ static void shim__set_security(struct ne
 	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
 */
@@ -15640,11 +15701,14 @@ static int ipw_card_remove_notify(struct
   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;
@@ -15657,6 +15721,29 @@ static int ipw_card_bss_active_changed_n
 		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;
 }
 
@@ -16259,7 +16346,9 @@ static int ipw_pci_probe(struct pci_dev 
 		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-10-09 15:12:07.000000000 -0400
+++ linux-2.6.18.noarch/drivers/net/wireless/ipw3945.h	2006-10-09 15:23:49.000000000 -0400
@@ -29,7 +29,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/config.h>
 #include <linux/init.h>
 
 #include <linux/version.h>
@@ -1752,14 +1751,6 @@ struct ipw_rx_queue {
 	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];
@@ -1801,6 +1792,9 @@ struct ipw_associate {
 	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;
@@ -2178,6 +2172,8 @@ struct ipw_priv {
 	struct ipw_activity_blink activity;
 	unsigned long led_packets;
 	int led_state;
+
+	u32 rates_mask;
 	u16 active_rate;
 	u16 active_rate_basic;
 
@@ -2215,15 +2211,13 @@ struct ipw_priv {
 	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-ipw3945-ipw_bg_calibrated_work-lockdep.patch:
 ipw3945.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

--- NEW FILE jwltest-ipw3945-ipw_bg_calibrated_work-lockdep.patch ---
--- linux-2.6.18.noarch/drivers/net/wireless/ipw3945.c.orig	2006-10-06 14:38:48.000000000 -0400
+++ linux-2.6.18.noarch/drivers/net/wireless/ipw3945.c	2006-10-06 14:55:44.000000000 -0400
@@ -4558,6 +4558,9 @@ static void ipw_bg_calibrated_work(void 
 	priv->status |= STATUS_CALIBRATE;
 
 	if (!priv->netdev_registered) {
+		/* unlock priv->mutex to avoid rtnl_mutex contention */
+		mutex_unlock(&priv->mutex);
+
 		rc = register_netdev(priv->net_dev);
 		if (rc) {
 			IPW_ERROR("Failed to register network "
@@ -4565,12 +4568,13 @@ static void ipw_bg_calibrated_work(void 
 				  "in 5 seconds.\n", rc);
 			queue_delayed_work(priv->workqueue,
 					   &priv->down, 5 * HZ);
-			mutex_unlock(&priv->mutex);
 			return;
 		}
 #ifdef CONFIG_IPW3945_PROMISCUOUS
 		if (rtap_iface) {
+			dev_hold(&priv->net_dev);
 			rc = ipw_prom_alloc(priv);
+			dev_put(&priv->net_dev);
 			if (rc) {
 				IPW_ERROR
 				    ("Failed to register promiscuous network "
@@ -4578,12 +4582,12 @@ static void ipw_bg_calibrated_work(void 
 				     "in 5 seconds.\n", rc);
 				queue_delayed_work(priv->workqueue,
 						   &priv->down, 5 * HZ);
-				mutex_unlock(&priv->mutex);
 				unregister_netdev(priv->net_dev);
 				return;
 			}
 		}
 #endif
+		mutex_lock(&priv->mutex);
 		priv->netdev_registered = 1;
 
 		/* For some reason, this card comes up with IFF_RUNNING set.

jwltest-sk98lin-neuter.patch:
 skge.c |    2 --
 1 files changed, 2 deletions(-)

--- NEW FILE jwltest-sk98lin-neuter.patch ---
--- linux-2.6.13/drivers/net/sk98lin/skge.c.orig	2005-10-20 15:19:17.000000000 -0400
+++ linux-2.6.13/drivers/net/sk98lin/skge.c	2005-10-20 15:19:25.000000000 -0400
@@ -5227,8 +5227,6 @@
 	{ 0 }
 };
 
-MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
-
 static struct pci_driver skge_driver = {
 	.name		= "sk98lin",
 	.id_table	= skge_pci_tbl,


Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/FC-5/kernel-2.6.spec,v
retrieving revision 1.2195
retrieving revision 1.2195.2.1
diff -u -r1.2195 -r1.2195.2.1
--- kernel-2.6.spec	2 Oct 2006 03:39:42 -0000	1.2195
+++ kernel-2.6.spec	9 Oct 2006 19:28:18 -0000	1.2195.2.1
@@ -23,7 +23,7 @@
 %define sublevel 18
 %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.17
 %define signmodules 0
 %define xen_hv_cset 11540
 %define make_target bzImage
@@ -341,6 +341,7 @@
 
 # NIC driver fixes
 Patch1350: linux-2.6-bcm43xx-periodic-work.patch
+Patch1351: jwltest-sk98lin-neuter.patch
 
 # Filesystem stuff.
 # Squashfs
@@ -428,6 +429,10 @@
 # Lockdep fixes.
 Patch2400: linux-2.6-lockdep-fixes.patch
 
+# IPW3945 wireless driver
+Patch5100: jwltest-ipw3945-1_0_5.patch
+Patch5101: jwltest-ipw3945-1_1_0.patch
+Patch5102: jwltest-ipw3945-ipw_bg_calibrated_work-lockdep.patch
 
 #
 # 10000 to 20000 is for stuff that has to come last due to the
@@ -863,6 +868,8 @@
 
 # NIC driver fixes
 %patch1350 -p1
+# neuter sk98lin (as far as userland is concerned)
+%patch1351 -p1
 
 # Filesystem patches.
 # Squashfs
@@ -985,6 +992,13 @@
 # be merged upstream
 #
 
+# add ipw3945 driver
+%patch5100 -p1
+# ipw3945: update to version 1.1.0
+%patch5101 -p1
+# ipw3945: avoid rtnl_mutex contention (and lockdep spewage)
+%patch5102 -p1
+
 #
 # final stuff
 #




More information about the fedora-cvs-commits mailing list