[kernel] r9456 - in dists/trunk/linux-2.6/debian/patches: features/all series

Maximilian Attems maks at alioth.debian.org
Tue Sep 4 18:52:04 UTC 2007


Author: maks
Date: Tue Sep  4 18:52:03 2007
New Revision: 9456

Log:
update iwlifi driver
newer version posted on linux-wireless on the 04. sept, see
Message-Id: <1188875058.13078.428.camel at debian.sh.intel.com>


Added:
   dists/trunk/linux-2.6/debian/patches/features/all/v6-Add-iwlwifi-wireless-drivers.patch
      - copied, changed from r9454, /dists/trunk/linux-2.6/debian/patches/features/all/v5-Add-iwlwifi-wireless-drivers.patch
Removed:
   dists/trunk/linux-2.6/debian/patches/features/all/v5-Add-iwlwifi-wireless-drivers.patch
Modified:
   dists/trunk/linux-2.6/debian/patches/series/1~experimental.1

Copied: dists/trunk/linux-2.6/debian/patches/features/all/v6-Add-iwlwifi-wireless-drivers.patch (from r9454, /dists/trunk/linux-2.6/debian/patches/features/all/v5-Add-iwlwifi-wireless-drivers.patch)
==============================================================================
--- /dists/trunk/linux-2.6/debian/patches/features/all/v5-Add-iwlwifi-wireless-drivers.patch	(original)
+++ dists/trunk/linux-2.6/debian/patches/features/all/v6-Add-iwlwifi-wireless-drivers.patch	Tue Sep  4 18:52:03 2007
@@ -1,8 +1,8 @@
 diff --git a/MAINTAINERS b/MAINTAINERS
-index d3a0684..547e8b3 100644
+index 48ca8b4..8a4ace8 100644
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
-@@ -2051,6 +2051,16 @@ L:	http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
+@@ -2057,6 +2057,16 @@ L:	http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
  W:	http://ipw2200.sourceforge.net
  S:	Supported
  
@@ -160,19 +160,15 @@
  source "drivers/net/wireless/bcm43xx/Kconfig"
  source "drivers/net/wireless/zd1211rw/Kconfig"
 diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
-index ef35bc6..1245b5c 100644
+index ef35bc6..59740e2 100644
 --- a/drivers/net/wireless/Makefile
 +++ b/drivers/net/wireless/Makefile
-@@ -47,3 +47,32 @@ obj-$(CONFIG_LIBERTAS_USB)     += libertas/
+@@ -47,3 +47,28 @@ obj-$(CONFIG_LIBERTAS_USB)     += libertas/
  
  rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o
  obj-$(CONFIG_RTL8187)	+= rtl8187.o
 +
-+# NOTE:  We use common code from iwl-base.c to build driver
-+# specific binaries based on the #define IWL -- the target
-+# setup below creates a specific driver target from iwl-base.c
-+#
-+# NOTE2: iwl-base-XXXX.o has -D"KBUILD_MODNAME=KBUILD_STR(...)" in order to
++# NOTE: iwl-base-XXXX.o has -D"KBUILD_MODNAME=KBUILD_STR(...)" in order to
 +# prevent the following kbuild error:
 +# 	include/linux/pci.h:603: error: `KBUILD_MODNAME' undeclared (first \
 +#		use in this function)
@@ -184,7 +180,7 @@
 +CFLAGS_iwl-3945.o	= -DIWL=3945
 +CFLAGS_iwl-3945-rs.o	= -DIWL=3945
 +CFLAGS_iwl-base-3945.o	= -DIWL=3945 -D"KBUILD_MODNAME=KBUILD_STR(iwl3945)"
-+$(obj)/iwl-base-3945.o: $(src)/iwl-base.c FORCE
++$(obj)/iwl-base-3945.o: $(src)/iwl3945-base.c FORCE
 +	$(call cmd,force_checksrc)
 +	$(call if_changed_rule,cc_o_c)
 +
@@ -193,12 +189,12 @@
 +CFLAGS_iwl-4965.o	= -DIWL=4965
 +CFLAGS_iwl-4965-rs.o	= -DIWL=4965
 +CFLAGS_iwl-base-4965.o	= -DIWL=4965 -D"KBUILD_MODNAME=KBUILD_STR(iwl4965)"
-+$(obj)/iwl-base-4965.o: $(src)/iwl-base.c FORCE
++$(obj)/iwl-base-4965.o: $(src)/iwl4965-base.c FORCE
 +	$(call cmd,force_checksrc)
 +	$(call if_changed_rule,cc_o_c)
 diff --git a/drivers/net/wireless/iwl-3945-hw.h b/drivers/net/wireless/iwl-3945-hw.h
 new file mode 100644
-index 0000000..1b5e72f
+index 0000000..fb5f064
 --- /dev/null
 +++ b/drivers/net/wireless/iwl-3945-hw.h
 @@ -0,0 +1,118 @@
@@ -283,8 +279,8 @@
 +
 +static inline int iwl_hw_valid_rtc_data_addr(u32 addr)
 +{
-+	return ((addr >= RTC_DATA_LOWER_BOUND)
-+		&& (addr < ALM_RTC_DATA_UPPER_BOUND));
++	return (addr >= RTC_DATA_LOWER_BOUND) &&
++	       (addr < ALM_RTC_DATA_UPPER_BOUND);
 +}
 +
 +/* Base physical address of iwl_shared is provided to FH_TSSR_CBB_BASE
@@ -322,10 +318,10 @@
 +#endif
 diff --git a/drivers/net/wireless/iwl-3945-rs.c b/drivers/net/wireless/iwl-3945-rs.c
 new file mode 100644
-index 0000000..2eee6c5
+index 0000000..f394fd4
 --- /dev/null
 +++ b/drivers/net/wireless/iwl-3945-rs.c
-@@ -0,0 +1,984 @@
+@@ -0,0 +1,968 @@
 +/******************************************************************************
 + *
 + * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
@@ -370,9 +366,7 @@
 +
 +#include "../net/mac80211/ieee80211_rate.h"
 +
-+#include "iwl-3945-rs.h"
 +#include "iwlwifi.h"
-+#include "iwl-helpers.h"
 +
 +#define RS_NAME "iwl-3945-rs"
 +
@@ -623,8 +617,7 @@
 +	unsigned long flags;
 +
 +	if (!retries) {
-+		IWL_DEBUG_RATE("leave: retries == 0 -- should be at "
-+			       "least 1\n");
++		IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n");
 +		return;
 +	}
 +
@@ -687,17 +680,9 @@
 +
 +static void *rs_alloc(struct ieee80211_local *local)
 +{
-+	IWL_DEBUG_RATE("enter\n");
-+	IWL_DEBUG_RATE("leave\n");
 +	return local->hw.priv;
 +}
 +
-+static void rs_free(void *data)
-+{
-+	IWL_DEBUG_RATE("enter\n");
-+	IWL_DEBUG_RATE("leave\n");
-+}
-+
 +static void *rs_alloc_sta(void *priv, gfp_t gfp)
 +{
 +	struct iwl_rate_scale_priv *rs_priv;
@@ -746,11 +731,6 @@
 +	IWL_DEBUG_RATE("leave\n");
 +}
 +
-+static void rs_clear(void *priv)
-+{
-+	IWL_DEBUG_RATE("NOP\n");
-+}
-+
 +/**
 + * rs_tx_status - Update rate control values based on Tx results
 + *
@@ -1148,9 +1128,9 @@
 +	.tx_status = rs_tx_status,
 +	.get_rate = rs_get_rate,
 +	.rate_init = rs_rate_init,
-+	.clear = rs_clear,
++	.clear = NULL,
 +	.alloc = rs_alloc,
-+	.free = rs_free,
++	.free = NULL,
 +	.alloc_sta = rs_alloc_sta,
 +	.free_sta = rs_free_sta,
 +};
@@ -1312,10 +1292,10 @@
 +
 diff --git a/drivers/net/wireless/iwl-3945-rs.h b/drivers/net/wireless/iwl-3945-rs.h
 new file mode 100644
-index 0000000..70dcec4
+index 0000000..b926738
 --- /dev/null
 +++ b/drivers/net/wireless/iwl-3945-rs.h
-@@ -0,0 +1,221 @@
+@@ -0,0 +1,191 @@
 +/******************************************************************************
 + *
 + * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
@@ -1460,37 +1440,15 @@
 +
 +extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
 +
-+static inline int iwl_rate_index_from_plcp(int plcp)
-+{
-+	int i = 0;
-+	for (i = 0; i < IWL_RATE_COUNT; i++)
-+		if (iwl_rates[i].plcp == plcp)
-+			return i;
-+	return -1;
-+}
-+
-+static inline u8 iwl_rate_get_lowest_plcp(int rate_mask)
-+{
-+	u8 i;
-+
-+	for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
-+	     i = iwl_rates[i].next_ieee) {
-+		if (rate_mask & (1 << i))
-+			return iwl_rates[i].plcp;
-+	}
-+
-+	return IWL_RATE_INVALID;
-+}
-+
 +static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
 +{
 +	u8 rate = iwl_rates[rate_index].prev_ieee;
++
 +	if (rate == IWL_RATE_INVALID)
 +		rate = rate_index;
 +	return rate;
 +}
 +
-+#if IWL == 3945
 +/**
 + * iwl_fill_rs_info - Fill an output text buffer with the rate representation
 + *
@@ -1527,22 +1485,14 @@
 + * the driver is unloaded.
 + */
 +extern void iwl_rate_control_unregister(struct ieee80211_hw *hw);
-+#else
-+static inline int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf,
-+				   u8 sta_id)
-+{ return -ENOTSUPP; }
-+static inline void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) {}
-+static inline void iwl_rate_control_register(struct ieee80211_hw *hw) {}
-+static inline void iwl_rate_control_unregister(struct ieee80211_hw *hw) {}
-+#endif /* IWL == 3945 */
 +
 +#endif
 diff --git a/drivers/net/wireless/iwl-3945.c b/drivers/net/wireless/iwl-3945.c
 new file mode 100644
-index 0000000..bb75836
+index 0000000..2ed217c
 --- /dev/null
 +++ b/drivers/net/wireless/iwl-3945.c
-@@ -0,0 +1,2286 @@
+@@ -0,0 +1,2287 @@
 +/******************************************************************************
 + *
 + * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
@@ -2265,9 +2215,9 @@
 +		rc = pci_read_config_dword(priv->pci_dev,
 +				PCI_POWER_SOURCE, &val);
 +		if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) {
-+			iwl_set_bits_mask_restricted_reg(priv, ALM_APMG_PS_CTL,
-+					APMG_PS_CTRL_REG_VAL_POWER_SRC_VAUX,
-+					~APMG_PS_CTRL_REG_MSK_POWER_SRC);
++			iwl_set_bits_mask_restricted_reg(priv, APMG_PS_CTRL_REG,
++					APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
++					~APMG_PS_CTRL_MSK_PWR_SRC);
 +			iwl_release_restricted_access(priv);
 +
 +			iwl_poll_bit(priv, CSR_GPIO_IN,
@@ -2276,9 +2226,9 @@
 +		} else
 +			iwl_release_restricted_access(priv);
 +	} else {
-+		iwl_set_bits_mask_restricted_reg(priv, ALM_APMG_PS_CTL,
-+				APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN,
-+				~APMG_PS_CTRL_REG_MSK_POWER_SRC);
++		iwl_set_bits_mask_restricted_reg(priv, APMG_PS_CTRL_REG,
++				APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
++				~APMG_PS_CTRL_MSK_PWR_SRC);
 +
 +		iwl_release_restricted_access(priv);
 +		iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
@@ -2434,12 +2384,12 @@
 +		spin_unlock_irqrestore(&priv->lock, flags);
 +		return rc;
 +	}
-+	iwl_write_restricted_reg(priv, ALM_APMG_CLK_EN,
-+				 APMG_CLK_REG_VAL_DMA_CLK_RQT |
-+				 APMG_CLK_REG_VAL_BSM_CLK_RQT);
++	iwl_write_restricted_reg(priv, APMG_CLK_EN_REG,
++				 APMG_CLK_VAL_DMA_CLK_RQT |
++				 APMG_CLK_VAL_BSM_CLK_RQT);
 +	udelay(20);
-+	iwl_set_bits_restricted_reg(priv, ALM_APMG_PCIDEV_STT,
-+				    APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE);
++	iwl_set_bits_restricted_reg(priv, APMG_PCIDEV_STT_REG,
++				    APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 +	iwl_release_restricted_access(priv);
 +	spin_unlock_irqrestore(&priv->lock, flags);
 +
@@ -2644,27 +2594,28 @@
 +	rc = iwl_grab_restricted_access(priv);
 +	if (!rc) {
 +		iwl_write_restricted_reg(priv, APMG_CLK_CTRL_REG,
-+					 APMG_CLK_REG_VAL_BSM_CLK_RQT);
++					 APMG_CLK_VAL_BSM_CLK_RQT);
 +
 +		udelay(10);
 +
 +		iwl_set_bit(priv, CSR_GP_CNTRL,
 +			    CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
 +
-+		iwl_write_restricted_reg(priv, ALM_APMG_LARC_INT_MSK, 0x0);
-+		iwl_write_restricted_reg(priv, ALM_APMG_LARC_INT, 0xFFFFFFFF);
++		iwl_write_restricted_reg(priv, APMG_RTC_INT_MSK_REG, 0x0);
++		iwl_write_restricted_reg(priv, APMG_RTC_INT_STT_REG,
++					0xFFFFFFFF);
 +
 +		/* enable DMA */
-+		iwl_write_restricted_reg(priv, ALM_APMG_CLK_EN,
-+					 APMG_CLK_REG_VAL_DMA_CLK_RQT |
-+					 APMG_CLK_REG_VAL_BSM_CLK_RQT);
++		iwl_write_restricted_reg(priv, APMG_CLK_EN_REG,
++					 APMG_CLK_VAL_DMA_CLK_RQT |
++					 APMG_CLK_VAL_BSM_CLK_RQT);
 +		udelay(10);
 +
-+		iwl_set_bits_restricted_reg(priv, ALM_APMG_PS_CTL,
-+				APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ);
++		iwl_set_bits_restricted_reg(priv, APMG_PS_CTRL_REG,
++				APMG_PS_CTRL_VAL_RESET_REQ);
 +		udelay(5);
-+		iwl_clear_bits_restricted_reg(priv, ALM_APMG_PS_CTL,
-+				APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ);
++		iwl_clear_bits_restricted_reg(priv, APMG_PS_CTRL_REG,
++				APMG_PS_CTRL_VAL_RESET_REQ);
 +		iwl_release_restricted_access(priv);
 +	}
 +
@@ -3831,10 +3782,10 @@
 +MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
 diff --git a/drivers/net/wireless/iwl-3945.h b/drivers/net/wireless/iwl-3945.h
 new file mode 100644
-index 0000000..0f4db4c
+index 0000000..813902e
 --- /dev/null
 +++ b/drivers/net/wireless/iwl-3945.h
-@@ -0,0 +1,60 @@
+@@ -0,0 +1,41 @@
 +/******************************************************************************
 + *
 + * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
@@ -3864,23 +3815,6 @@
 +#ifndef __iwl_3945_h__
 +#define __iwl_3945_h__
 +
-+#if IWL != 3945
-+/*
-+ * In non IWL == 3945 builds, these must build to nothing in order to allow
-+ * the common code to not have several #if IWL == XXXX / #endif blocks
-+ */
-+static inline __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
-+{ return 0; }
-+static inline int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
-+{ return 0; }
-+static inline void iwl3945_reg_txpower_periodic(struct iwl_priv *priv) {}
-+static inline void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
-+{}
-+static inline int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
-+{ return 0; }
-+static inline u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
-+		 u16 tx_rate, u8 flags) { return 0; }
-+#else				/* IWL == 3945 */
 +/*
 + * Forward declare iwl-3945.c functions for iwl-base.c
 + */
@@ -3892,15 +3826,13 @@
 +extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
 +extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
 +		 u16 tx_rate, u8 flags);
-+#endif				/* IWL == 3945 */
-+
 +#endif
 diff --git a/drivers/net/wireless/iwl-4965-hw.h b/drivers/net/wireless/iwl-4965-hw.h
 new file mode 100644
-index 0000000..858ec55
+index 0000000..810e969
 --- /dev/null
 +++ b/drivers/net/wireless/iwl-4965-hw.h
-@@ -0,0 +1,835 @@
+@@ -0,0 +1,581 @@
 +/******************************************************************************
 + *
 + * This file is provided under a dual BSD/GPLv2 license.  When using or
@@ -3979,8 +3911,8 @@
 +
 +static inline int iwl_hw_valid_rtc_data_addr(u32 addr)
 +{
-+	return ((addr >= RTC_DATA_LOWER_BOUND)
-+		&& (addr < KDR_RTC_DATA_UPPER_BOUND));
++	return (addr >= RTC_DATA_LOWER_BOUND) &&
++	       (addr < KDR_RTC_DATA_UPPER_BOUND);
 +}
 +
 +/********************* START TXPOWER *****************************************/
@@ -4110,10 +4042,8 @@
 +/********************* END TXPOWER *****************************************/
 +
 +/* HT flags */
-+#define RXON_FLG_CONTROL_CHANNEL_LOCATION_POS	(22)
-+#define RXON_FLG_CONTROL_CHANNEL_LOCATION_MSK	__constant_cpu_to_le32(0x1<<22)
-+#define RXON_FLG_CONTROL_CHANNEL_LOC_LOW_MSK	__constant_cpu_to_le32(0x0<<22)
-+#define RXON_FLG_CONTROL_CHANNEL_LOC_HIGH_MSK	__constant_cpu_to_le32(0x1<<22)
++#define RXON_FLG_CTRL_CHANNEL_LOC_POS		(22)
++#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK	__constant_cpu_to_le32(0x1<<22)
 +
 +#define RXON_FLG_HT_OPERATING_MODE_POS		(23)
 +
@@ -4122,7 +4052,6 @@
 +
 +#define RXON_FLG_CHANNEL_MODE_POS		(25)
 +#define RXON_FLG_CHANNEL_MODE_MSK		__constant_cpu_to_le32(0x3<<25)
-+#define RXON_FLG_CHANNEL_MODE_LEGACY_MSK	__constant_cpu_to_le32(0x0<<25)
 +#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK	__constant_cpu_to_le32(0x1<<25)
 +#define RXON_FLG_CHANNEL_MODE_MIXED_MSK		__constant_cpu_to_le32(0x2<<25)
 +
@@ -4177,61 +4106,7 @@
 +#define IWL_FH_REGS_LOWER_BOUND		     (0x1000)
 +#define IWL_FH_REGS_UPPER_BOUND		     (0x2000)
 +
-+/* TFDB  Area - TFDs buffer table */
-+#define FH_MEM_TFDB_LOWER_BOUND              (FH_MEM_LOWER_BOUND + 0x000)
-+#define FH_MEM_TFDB_UPPER_BOUND              (FH_MEM_LOWER_BOUND + 0x900)
-+/* channels 0 - 8 */
-+#define FH_MEM_TFDB_CHNL_BUF0(x) (FH_MEM_TFDB_LOWER_BOUND + (x) * 0x100)
-+#define FH_MEM_TFDB_CHNL_BUF1(x) (FH_MEM_TFDB_LOWER_BOUND + 0x80 + (x) * 0x100)
-+
-+/* TFDIB Area - TFD Immediate Buffer */
-+#define FH_MEM_TFDIB_LOWER_BOUND	     (FH_MEM_LOWER_BOUND + 0x900)
-+#define FH_MEM_TFDIB_UPPER_BOUND	     (FH_MEM_LOWER_BOUND + 0x958)
-+/* channels 0 - 10 */
-+#define FH_MEM_TFDIB_CHNL(x)     (FH_MEM_TFDIB_LOWER_BOUND + (x) * 0x8)
-+
-+/* TFDIB registers used in Service Mode */
-+#define FH_MEM_TFDIB_CHNL9_REG0		     (FH_MEM_TFDIB_CHNL(9))
-+#define FH_MEM_TFDIB_CHNL9_REG1		     (FH_MEM_TFDIB_CHNL(9) + 4)
-+#define FH_MEM_TFDIB_CHNL10_REG0	     (FH_MEM_TFDIB_CHNL(10))
-+#define FH_MEM_TFDIB_CHNL10_REG1	     (FH_MEM_TFDIB_CHNL(10) + 4)
-+
-+/* Tx service channels */
-+#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MASK	     (0xFFFFFFFF)
-+#define FH_MEM_TFDIB_DRAM_ADDR_MSB_MASK	     (0xF00000000)
-+#define FH_MEM_TFDIB_TB_LENGTH_MASK	     (0x0001FFFF)	/* bits 16:0 */
-+
-+#define FH_MEM_TFDIB_DRAM_ADDR_LSB_BITSHIFT  (0)
-+#define FH_MEM_TFDIB_DRAM_ADDR_MSB_BITSHIFT  (32)
-+#define FH_MEM_TFDIB_TB_LENGTH_BITSHIFT	     (0)
-+
-+#define FH_MEM_TFDIB_REG0_ADDR_MASK	     (0xFFFFFFFF)
-+#define FH_MEM_TFDIB_REG1_ADDR_MASK	     (0xF0000000)
-+#define FH_MEM_TFDIB_REG1_LENGTH_MASK	     (0x0001FFFF)
-+
-+#define FH_MEM_TFDIB_REG0_ADDR_BITSHIFT	     (0)
-+#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT	     (28)
-+#define FH_MEM_TFDIB_REG1_LENGTH_BITSHIFT    (0)
-+
-+/* TRB Area - Transmit Request Buffers */
-+#define FH_MEM_TRB_LOWER_BOUND		     (FH_MEM_LOWER_BOUND + 0x0958)
-+#define FH_MEM_TRB_UPPER_BOUND		     (FH_MEM_LOWER_BOUND + 0x0980)
-+/* channels 0 - 8 */
-+#define FH_MEM_TRB_CHNL(x)	   (FH_MEM_TRB_LOWER_BOUND + (x) * 0x4)
-+
 +#define IWL_FH_KW_MEM_ADDR_REG		     (FH_MEM_LOWER_BOUND + 0x97C)
-+/* STAGB Area - Scheduler TAG Buffer */
-+#define FH_MEM_STAGB_LOWER_BOUND	     (FH_MEM_LOWER_BOUND + 0x980)
-+#define FH_MEM_STAGB_UPPER_BOUND	     (FH_MEM_LOWER_BOUND + 0x9D0)
-+/* channels 0 - 8 */
-+#define FH_MEM_STAGB_0(x)     (FH_MEM_STAGB_LOWER_BOUND + (x) * 0x8)
-+#define FH_MEM_STAGB_1(x)     (FH_MEM_STAGB_LOWER_BOUND + 0x4 + (x) * 0x8)
-+
-+/* Tx service channels */
-+#define FH_MEM_SRAM_ADDR_9	     (FH_MEM_STAGB_LOWER_BOUND + 0x048)
-+#define FH_MEM_SRAM_ADDR_10	     (FH_MEM_STAGB_LOWER_BOUND + 0x04C)
-+
-+#define FH_MEM_STAGB_SRAM_ADDR_MASK	     (0x00FFFFFF)
 +
 +/* CBBC Area - Circular buffers base address cache pointers table */
 +#define FH_MEM_CBBC_LOWER_BOUND              (FH_MEM_LOWER_BOUND + 0x9D0)
@@ -4239,64 +4114,21 @@
 +/* queues 0 - 15 */
 +#define FH_MEM_CBBC_QUEUE(x)  (FH_MEM_CBBC_LOWER_BOUND + (x) * 0x4)
 +
-+/* TAGR Area - TAG reconstruct table */
-+#define FH_MEM_TAGR_LOWER_BOUND              (FH_MEM_LOWER_BOUND + 0xA10)
-+#define FH_MEM_TAGR_UPPER_BOUND              (FH_MEM_LOWER_BOUND + 0xA70)
-+
-+/* TDBGR Area - Tx Debug Registers */
-+#define FH_MEM_TDBGR_LOWER_BOUND             (FH_MEM_LOWER_BOUND + 0x0A70)
-+#define FH_MEM_TDBGR_UPPER_BOUND             (FH_MEM_LOWER_BOUND + 0x0B20)
-+/* channels 0 - 10 */
-+#define FH_MEM_TDBGR_CHNL(x)      (FH_MEM_TDBGR_LOWER_BOUND + (x) * 0x10)
-+
-+#define FH_MEM_TDBGR_CHNL_REG_0(x)	     (FH_MEM_TDBGR_CHNL(x))
-+#define FH_MEM_TDBGR_CHNL_REG_1(x)	     (FH_MEM_TDBGR_CHNL_REG_0(x) + 0x4)
-+
-+#define FH_MEM_TDBGR_CHNL_BYTES_TO_FIFO_MASK		(0x000FFFFF)
-+#define FH_MEM_TDBGR_CHNL_BYTES_TO_FIFO_BITSHIFT	(0)
-+
-+/* RDBUF Area */
-+#define FH_MEM_RDBUF_LOWER_BOUND             (FH_MEM_LOWER_BOUND + 0xB80)
-+#define FH_MEM_RDBUF_UPPER_BOUND             (FH_MEM_LOWER_BOUND + 0xBC0)
-+#define FH_MEM_RDBUF_CHNL0		     (FH_MEM_RDBUF_LOWER_BOUND)
-+
 +/* RSCSR Area */
 +#define FH_MEM_RSCSR_LOWER_BOUND	(FH_MEM_LOWER_BOUND + 0xBC0)
 +#define FH_MEM_RSCSR_UPPER_BOUND	(FH_MEM_LOWER_BOUND + 0xC00)
 +#define FH_MEM_RSCSR_CHNL0		(FH_MEM_RSCSR_LOWER_BOUND)
-+#define FH_MEM_RSCSR_CHNL1		(FH_MEM_RSCSR_LOWER_BOUND + 0x020)
 +
-+/* RSCSR registers used in Normal mode*/
 +#define FH_RSCSR_CHNL0_STTS_WPTR_REG		(FH_MEM_RSCSR_CHNL0)
 +#define FH_RSCSR_CHNL0_RBDCB_BASE_REG		(FH_MEM_RSCSR_CHNL0 + 0x004)
 +#define FH_RSCSR_CHNL0_RBDCB_WPTR_REG		(FH_MEM_RSCSR_CHNL0 + 0x008)
-+#define FH_RSCSR_CHNL0_RBDCB_RPTR_REG		(FH_MEM_RSCSR_CHNL0 + 0x00c)
-+
-+#define FH_RSCSR_FRAME_SIZE_MASK	(0x00003FFF)	/* bits 0-13 */
-+/* RSCSR registers used in Service mode*/
-+#define FH_RSCSR_CHNL1_RB_WPTR_REG		(FH_MEM_RSCSR_CHNL1)
-+#define FH_RSCSR_CHNL1_RB_WPTR_OFFSET_REG	(FH_MEM_RSCSR_CHNL1 + 0x004)
-+#define FH_RSCSR_CHNL1_RB_CHUNK_NUM_REG		(FH_MEM_RSCSR_CHNL1 + 0x008)
-+#define FH_RSCSR_CHNL1_SRAM_ADDR_REG		(FH_MEM_RSCSR_CHNL1 + 0x00C)
 +
 +/* RCSR Area - Registers address map */
 +#define FH_MEM_RCSR_LOWER_BOUND      (FH_MEM_LOWER_BOUND + 0xC00)
 +#define FH_MEM_RCSR_UPPER_BOUND      (FH_MEM_LOWER_BOUND + 0xCC0)
 +#define FH_MEM_RCSR_CHNL0            (FH_MEM_RCSR_LOWER_BOUND)
-+#define FH_MEM_RCSR_CHNL1            (FH_MEM_RCSR_LOWER_BOUND + 0x020)
 +
 +#define FH_MEM_RCSR_CHNL0_CONFIG_REG	(FH_MEM_RCSR_CHNL0)
-+#define FH_MEM_RCSR_CHNL0_CREDIT_REG	(FH_MEM_RCSR_CHNL0 + 0x004)
-+#define FH_MEM_RCSR_CHNL0_RBD_STTS_REG	(FH_MEM_RCSR_CHNL0 + 0x008)
-+#define FH_MEM_RCSR_CHNL0_RB_STTS_REG	(FH_MEM_RCSR_CHNL0 + 0x00C)
-+#define FH_MEM_RCSR_CHNL0_RXPD_STTS_REG	(FH_MEM_RCSR_CHNL0 + 0x010)
-+
-+#define FH_MEM_RCSR_CHNL0_RBD_STTS_FRAME_RB_CNT_MASK (0x7FFFFFF0) /* bits4:30 */
-+
-+/* RCSR registers used in Service mode*/
-+#define FH_MEM_RCSR_CHNL1_CONFIG_REG		(FH_MEM_RCSR_CHNL1)
-+#define FH_MEM_RCSR_CHNL1_RB_STTS_REG         	(FH_MEM_RCSR_CHNL1 + 0x00C)
-+#define FH_MEM_RCSR_CHNL1_RX_PD_STTS_REG       	(FH_MEM_RCSR_CHNL1 + 0x010)
 +
 +/* RSSR Area - Rx shared ctrl & status registers */
 +#define FH_MEM_RSSR_LOWER_BOUND                	(FH_MEM_LOWER_BOUND + 0xC40)
@@ -4312,10 +4144,6 @@
 +#define IWL_FH_TCSR_CHNL_NUM                            (7)
 +#define IWL_FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
 +	(IWL_FH_TCSR_LOWER_BOUND + 0x20 * _chnl)
-+#define IWL_FH_TCSR_CHNL_TX_CREDIT_REG(_chnl) \
-+	  (IWL_FH_TCSR_LOWER_BOUND + 0x20 * _chnl + 0x4)
-+#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl) \
-+	 (IWL_FH_TCSR_LOWER_BOUND + 0x20 * _chnl + 0x8)
 +
 +/* TSSR Area - Tx shared status registers */
 +/* TSSR */
@@ -4348,61 +4176,6 @@
 +	(IWL_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) | \
 +	IWL_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl))
 +
-+/* SRVC */
-+#define IWL_FH_SRVC_LOWER_BOUND          (IWL_FH_REGS_LOWER_BOUND + 0x9C8)
-+#define IWL_FH_SRVC_UPPER_BOUND          (IWL_FH_REGS_LOWER_BOUND + 0x9D0)
-+
-+#define IWL_FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \
-+	  (IWL_FH_SRVC_LOWER_BOUND + (_chnl - 9) * 0x4)
-+
-+/* TFDIB */
-+#define IWL_FH_TFDIB_LOWER_BOUND         (IWL_FH_REGS_LOWER_BOUND + 0x900)
-+#define IWL_FH_TFDIB_UPPER_BOUND         (IWL_FH_REGS_LOWER_BOUND + 0x958)
-+
-+#define IWL_FH_TFDIB_CTRL0_REG(_chnl)    \
-+	(IWL_FH_TFDIB_LOWER_BOUND + 0x8 * _chnl)
-+#define IWL_FH_TFDIB_CTRL1_REG(_chnl)    \
-+	(IWL_FH_TFDIB_LOWER_BOUND + 0x8 * _chnl + 0x4)
-+
-+#define IWL_FH_SRVC_CHNL                                (9)
-+#define IWL_FH_TFDIB_CTRL1_REG_POS_MSB                  (28)
-+
-+/* Debug Monitor Area */
-+#define FH_MEM_DM_LOWER_BOUND            (FH_MEM_LOWER_BOUND + 0xEE0)
-+#define FH_MEM_DM_UPPER_BOUND            (FH_MEM_LOWER_BOUND + 0xEF0)
-+#define FH_MEM_DM_CONTROL_MASK_REG       (FH_MEM_DM_LOWER_BOUND)
-+#define FH_MEM_DM_CONTROL_START_REG      (FH_MEM_DM_LOWER_BOUND + 0x004)
-+#define FH_MEM_DM_CONTROL_STATUS_REG     (FH_MEM_DM_LOWER_BOUND + 0x008)
-+#define FH_MEM_DM_MONITOR_REG            (FH_MEM_DM_LOWER_BOUND + 0x00C)
-+
-+#define FH_TB1_ADDR_LOW_MASK	(0xFFFFFFFF)	/* bits 31:0 */
-+#define FH_TB1_ADDR_HIGH_MASK	(0xF00000000)	/* bits 35:32 */
-+#define FH_TB2_ADDR_LOW_MASK	(0x0000FFFF)	/* bits 15:0 */
-+#define FH_TB2_ADDR_HIGH_MASK	(0xFFFFF0000)	/* bits 35:16 */
-+
-+#define FH_TB1_ADDR_LOW_BITSHIFT	(0)
-+#define FH_TB1_ADDR_HIGH_BITSHIFT	(32)
-+#define FH_TB2_ADDR_LOW_BITSHIFT	(0)
-+#define FH_TB2_ADDR_HIGH_BITSHIFT	(16)
-+
-+#define FH_TB1_LENGTH_MASK         (0x00000FFF)	/* bits 11:0 */
-+#define FH_TB2_LENGTH_MASK         (0x00000FFF)	/* bits 11:0 */
-+
-+/* number of FH channels including 2 service mode */
-+#define NUM_OF_FH_CHANNELS (10)
-+
-+/* ctrl field bitology */
-+#define FH_TFD_CTRL_PADDING_MASK     (0xC0000000)	/* bits 31:30 */
-+#define FH_TFD_CTRL_NUMTB_MASK       (0x1F000000)	/* bits 28:24 */
-+
-+#define FH_TFD_CTRL_PADDING_BITSHIFT                (30)
-+#define FH_TFD_CTRL_NUMTB_BITSHIFT                  (24)
-+
-+#define FH_TFD_GET_NUM_TBS(ctrl) \
-+	((ctrl & FH_TFD_CTRL_NUMTB_MASK) >> FH_TFD_CTRL_NUMTB_BITSHIFT)
-+#define FH_TFD_GET_PADDING(ctrl) \
-+	((ctrl & FH_TFD_CTRL_PADDING_MASK) >> FH_TFD_CTRL_PADDING_BITSHIFT)
-+
 +/* TCSR: tx_config register values */
 +#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF              (0x00000000)
 +#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER           (0x00000001)
@@ -4432,10 +4205,6 @@
 +#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM              (20)
 +#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX              (12)
 +
-+/* CBB table */
-+#define FH_CBB_ADDR_MASK	0x0FFFFFFF	/* bits 27:0 */
-+#define FH_CBB_ADDR_BIT_SHIFT		(8)
-+
 +/* RCSR:  channel 0 rx_config register defines */
 +#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MASK  (0xC0000000) /* bits 30-31 */
 +#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MASK   (0x00F00000) /* bits 20-23 */
@@ -4447,22 +4216,10 @@
 +#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT       (20)
 +#define FH_RCSR_RX_CONFIG_RB_SIZE_BITSHIFT			(16)
 +
-+#define FH_RCSR_GET_RDBC_SIZE(reg) \
-+	 ((reg & FH_RCSR_RX_CONFIG_RDBC_SIZE_MASK) >> \
-+	  FH_RCSR_RX_CONFIG_RDBC_SIZE_BITSHIFT)
-+
-+/* RCSR:  channel 1 rx_config register defines */
-+#define FH_RCSR_CHNL1_RX_CONFIG_DMA_CHNL_EN_MASK  (0xC0000000) /* bits 30-31 */
-+#define FH_RCSR_CHNL1_RX_CONFIG_IRQ_DEST_MASK	  (0x00003000) /* bits 12-13 */
-+
 +/* RCSR: rx_config register values */
 +#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL         (0x00000000)
 +#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL     (0x40000000)
 +#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL        (0x80000000)
-+#define FH_RCSR_RX_CONFIG_SINGLE_FRAME_MODE	    (0x00008000)
-+
-+#define FH_RCSR_RX_CONFIG_RDRBD_DISABLE_VAL         (0x00000000)
-+#define FH_RCSR_RX_CONFIG_RDRBD_ENABLE_VAL          (0x20000000)
 +
 +#define IWL_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K    (0x00000000)
 +
@@ -4470,38 +4227,9 @@
 +#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL       (0x00000000)
 +#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL     (0x00001000)
 +
-+/* RCSR channel 1 config register values */
-+#define FH_RCSR_CHNL1_RX_CONFIG_IRQ_DEST_NO_INT_VAL       (0x00000000)
-+#define FH_RCSR_CHNL1_RX_CONFIG_IRQ_DEST_INT_HOST_VAL     (0x00001000)
-+#define FH_RCSR_CHNL1_RX_CONFIG_IRQ_DEST_INT_RTC_VAL      (0x00002000)
-+#define FH_RCSR_CHNL1_RX_CONFIG_IRQ_DEST_INT_HOST_RTC_VAL (0x00003000)
-+
-+/* RCSR: rb status register defines */
-+#define FH_RCSR_RB_BYTE_TO_SEND_MASK		(0x0001FFFF)	/* bits 0-16 */
-+
 +/* RSCSR: defs used in normal mode */
 +#define FH_RSCSR_CHNL0_RBDCB_WPTR_MASK		(0x00000FFF)	/* bits 0-11 */
 +
-+/* RSCSR: defs used in service mode */
-+#define FH_RSCSR_CHNL1_SRAM_ADDR_MASK		(0x00FFFFFF)	/* bits 0-23 */
-+#define FH_RSCSR_CHNL1_RB_WPTR_MASK		(0x0FFFFFFF)	/* bits 0-27 */
-+#define FH_RSCSR_CHNL1_RB_WPTR_OFFSET_MASK	(0x000000FF)	/* bits 0-7 */
-+
-+/* RSSR: RX Enable Error IRQ to Driver register defines */
-+#define FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV_NO_RBD (0x00400000)	/* bit 22 */
-+
-+#define FH_DRAM2SRAM_DRAM_ADDR_HIGH_MASK	(0xFFFFFFF00)	/* bits 8-35 */
-+#define FH_DRAM2SRAM_DRAM_ADDR_LOW_MASK		(0x000000FF)	/* bits 0-7 */
-+
-+#define FH_DRAM2SRAM_DRAM_ADDR_HIGH_BITSHIFT	(8)	/* bits 8-35 */
-+
-+/* RX DRAM status regs definitions  */
-+#define FH_RX_RB_NUM_MASK			(0x00000FFF)	/* bits 0-11 */
-+#define FH_RX_FRAME_NUM_MASK			(0x0FFF0000) /* bits 16-27 */
-+
-+#define FH_RX_RB_NUM_BITSHIFT			(0)
-+#define FH_RX_FRAME_NUM_BITSHIFT		(16)
-+
 +#define SCD_WIN_SIZE				64
 +#define SCD_FRAME_LIMIT				10
 +
@@ -4575,46 +4303,6 @@
 +#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI		(0x00000100)
 +#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI	(0x00000200)
 +
-+
-+ /*IWL4965-END */
-+
-+#define IWL4965_BROADCAST_ID    (31)
-+
-+#define RX_RES_PHY_CNT 14
-+
-+#define STATISTICS_FLG_CLEAR                      (0x1)
-+#define STATISTICS_FLG_DISABLE_NOTIFICATION       (0x2)
-+
-+#define STATISTICS_REPLY_FLG_CLEAR                __constant_cpu_to_le32(0x1)
-+#define STATISTICS_REPLY_FLG_BAND_24G_MSK         __constant_cpu_to_le32(0x2)
-+#define STATISTICS_REPLY_FLG_TGJ_NARROW_BAND_MSK  __constant_cpu_to_le32(0x4)
-+#define STATISTICS_REPLY_FLG_FAT_MODE_MSK         __constant_cpu_to_le32(0x8)
-+#define RX_PHY_FLAGS_ANTENNAE_OFFSET		(4)
-+#define RX_PHY_FLAGS_ANTENNAE_MASK		(0x70)
-+
-+
-+
-+struct iwl4965_rx_phy_res {
-+	u8 non_cfg_phy_cnt;     /* non configurable DSP phy data byte count */
-+	u8 cfg_phy_cnt;		/* configurable DSP phy data byte count */
-+	u8 stat_id;		/* configurable DSP phy data set ID */
-+	u8 reserved1;
-+	__le64 timestamp;	/* TSF at on air rise */
-+	__le32 beacon_time_stamp; /* beacon at on-air rise */
-+	__le16 phy_flags;	/* general phy flags: band, modulation, ... */
-+	__le16 channel;		/* channel number */
-+	__le16 non_cfg_phy[RX_RES_PHY_CNT];	/* upto 14 phy entries */
-+	__le32 reserved2;
-+	__le32 rate_n_flags;
-+	__le16 byte_count;		/* frame's byte-count */
-+	__le16 reserved3;
-+} __attribute__ ((packed));
-+
-+struct iwl4965_rx_mpdu_res_start {
-+	__le16 byte_count;
-+	__le16 reserved;
-+} __attribute__ ((packed));
-+
 +static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
 +{
 +	return le32_to_cpu(rate_n_flags) & 0xFF;
@@ -4628,16 +4316,6 @@
 +	return cpu_to_le32(flags|(u16)rate);
 +}
 +
-+#define IWL_AGC_DB_MASK 	(0x3f80)	/* MASK(7,13) */
-+#define IWL_AGC_DB_POS		(7)
-+/* Fixed (non-configurable) rx data from phy */
-+struct iwl4965_rx_non_cfg_phy {
-+	__le16 ant_selection;	/* ant A bit 4, ant B bit 5, ant C bit 6 */
-+	__le16 agc_info;	/* agc code 0:6, agc dB 7:13, reserved 14:15 */
-+	u8 rssi_info[6];	/* we use even entries, 0/2/4 for A/B/C rssi */
-+	u8 pad[0];
-+} __attribute__ ((packed));
-+
 +struct iwl_tfd_frame_data {
 +	__le32 tb1_addr;
 +
@@ -4738,10 +4416,10 @@
 +#endif /* __iwl_4965_hw_h__ */
 diff --git a/drivers/net/wireless/iwl-4965-rs.c b/drivers/net/wireless/iwl-4965-rs.c
 new file mode 100644
-index 0000000..a97914f
+index 0000000..9e0ba5f
 --- /dev/null
 +++ b/drivers/net/wireless/iwl-4965-rs.c
-@@ -0,0 +1,2141 @@
+@@ -0,0 +1,2115 @@
 +/******************************************************************************
 + *
 + * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
@@ -4786,7 +4464,6 @@
 +#include "../net/mac80211/ieee80211_rate.h"
 +
 +#include "iwlwifi.h"
-+#include "iwl-4965-rs.h"
 +#include "iwl-helpers.h"
 +
 +#define RS_NAME "iwl-4965-rs"
@@ -4962,7 +4639,9 @@
 +
 +	if (flags & CMD_ASYNC)
 +		cmd.meta.u.callback = iwl_lq_sync_callback;
-+	if (iwl_is_associated(priv) && priv->lq_mngr.lq_ready)
++
++	if (iwl_is_associated(priv) && priv->assoc_station_added &&
++	    priv->lq_mngr.lq_ready)
 +		rc = iwl_send_cmd(priv, &cmd);
 +
 +	return rc;
@@ -5360,8 +5039,7 @@
 +	u16 fc = le16_to_cpu(hdr->frame_control);
 +	s32 tpt = 0;
 +
-+	IWL_DEBUG_RATE("getting frame ack response, update rate "
-+		       "scale window\n");
++	IWL_DEBUG_RATE("get frame ack response, update rate scale window\n");
 +
 +	if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
 +		return;
@@ -5528,23 +5206,6 @@
 +	return 0;
 +}
 +
-+#define IWL_LEGACY_SWITCH_ANTENNA	0
-+#define IWL_LECACY_SWITCH_SISO		1
-+#define IWL_LEGACY_SWITCH_MIMO	        2
-+
-+#define IWL_RS_GOOD_RATIO		12800
-+
-+#define IWL_ACTION_LIMIT		3
-+#define IWL_LEGACY_FAILURE_LIMIT	160
-+#define IWL_LEGACY_SUCCESS_LIMIT	480
-+#define IWL_LEGACY_TABLE_COUNT		160
-+
-+#define IWL_NONE_LEGACY_FAILURE_LIMIT	400
-+#define IWL_NONE_LEGACY_SUCCESS_LIMIT	4500
-+#define IWL_NONE_LEGACY_TABLE_COUNT	1500
-+
-+#define IWL_RATE_SCALE_SWITCH		(10880)
-+
 +static void rs_set_stay_in_table(u8 is_legacy,
 +				 struct iwl_rate_scale_priv *lq_data)
 +{
@@ -5857,10 +5518,6 @@
 +
 +}
 +
-+#define IWL_SISO_SWITCH_ANTENNA  0
-+#define IWL_SISO_SWITCH_MIMO     1
-+#define IWL_SISO_SWITCH_GI       2
-+
 +static int rs_move_siso_to_other(struct iwl_priv *priv,
 +				 struct iwl_rate_scale_priv *lq_data,
 +				 int index)
@@ -5952,10 +5609,6 @@
 +	return 0;
 +}
 +
-+#define IWL_MIMO_SWITCH_ANTENNA_A	0
-+#define IWL_MIMO_SWITCH_ANTENNA_B	1
-+#define IWL_MIMO_SWITCH_GI		2
-+
 +static int rs_move_mimo_to_other(struct iwl_priv *priv,
 +				 struct iwl_rate_scale_priv *lq_data,
 +				 int index)
@@ -6391,6 +6044,8 @@
 +	 */
 +	if (lq_data->phymode == (u8) MODE_IEEE80211A)
 +		sta->txrate = i - IWL_FIRST_OFDM_RATE;
++	else
++		sta->txrate = i;
 +
 +	sta->antenna_sel_tx = tbl->lq_type;
 +
@@ -6594,7 +6249,8 @@
 +			crl->lq.sta_id = sta_id;
 +			crl->lq.rs_table[0].rate_n_flags = 0;
 +		}
-+		priv->lq_mngr.lq_ready = 1;
++		/* FIXME: this is w/a remove it later */
++		priv->assoc_station_added = 1;
 +	}
 +
 +	for (i = 0; i < mode->num_rates; i++) {
@@ -6631,8 +6287,10 @@
 +		     crl->active_mimo_rate);
 +#endif /*CONFIG_IWLWIFI_HT*/
 +
-+	if (priv)
-+		rs_initialize_lq(priv, sta);
++	if (priv->assoc_station_added)
++		priv->lq_mngr.lq_ready = 1;
++
++	rs_initialize_lq(priv, sta);
 +}
 +
 +static int rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
@@ -6729,22 +6387,14 @@
 +
 +static void *rs_alloc(struct ieee80211_local *local)
 +{
-+	IWL_DEBUG_RATE("enter\n");
-+	IWL_DEBUG_RATE("leave\n");
 +	return local->hw.priv;
 +}
 +
-+static void rs_free(void *data)
-+{
-+	IWL_DEBUG_RATE("enter\n");
-+	IWL_DEBUG_RATE("leave\n");
-+}
-+
 +static void rs_clear(void *priv_rate)
 +{
 +	struct iwl_priv *priv = (struct iwl_priv *) priv_rate;
 +
-+	IWL_DEBUG_RATE("NOP\n");
++	IWL_DEBUG_RATE("enter\n");
 +
 +	priv->lq_mngr.lq_ready = 0;
 +#ifdef CONFIG_IWLWIFI_HT
@@ -6753,6 +6403,8 @@
 +		iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);
 +#endif /*CONFIG_IWLWIFI_HT_AGG */
 +#endif /* CONFIG_IWLWIFI_HT */
++
++	IWL_DEBUG_RATE("leave\n");
 +}
 +
 +static void rs_free_sta(void *priv, void *priv_sta)
@@ -6773,7 +6425,7 @@
 +	.rate_init = rs_rate_init,
 +	.clear = rs_clear,
 +	.alloc = rs_alloc,
-+	.free = rs_free,
++	.free = NULL,
 +	.alloc_sta = rs_alloc_sta,
 +	.free_sta = rs_free_sta,
 +};
@@ -6845,24 +6497,24 @@
 +			break;
 +		i = j;
 +	}
-+	sta_info_put(sta);
 +
 +	/* Display the average rate of all samples taken.
 +	 *
 +	 * NOTE:  We multiple # of samples by 2 since the IEEE measurement
 +	 * added from iwl_rates is actually 2X the rate */
 +	if (samples)
-+		count += sprintf(
-+			 &buf[count],
++		count += sprintf(&buf[count],
 +			 "\nAverage rate is %3d.%02dMbs over last %4dms\n"
 +			 "%3d%% success (%d good packets over %d tries)\n",
 +			 success / (2 * samples), (success * 5 / samples) % 10,
 +			 max_time, good * 100 / samples, good, samples);
 +	else
 +		count += sprintf(&buf[count], "\nAverage rate: 0Mbs\n");
-+	count += sprintf(&buf[count], "\nrate scale type %d anntena %d \n",
-+			 lq_type, antenna);
++	count += sprintf(&buf[count], "\nrate scale type %d anntena %d "
++			 "active_search %d rate index %d\n", lq_type, antenna,
++			 rs_priv->search_better_tbl, sta->last_txrate);
 +
++	sta_info_put(sta);
 +	return count;
 +}
 +
@@ -6885,10 +6537,10 @@
 +
 diff --git a/drivers/net/wireless/iwl-4965-rs.h b/drivers/net/wireless/iwl-4965-rs.h
 new file mode 100644
-index 0000000..aa9aae5
+index 0000000..35d2044
 --- /dev/null
 +++ b/drivers/net/wireless/iwl-4965-rs.h
-@@ -0,0 +1,286 @@
+@@ -0,0 +1,266 @@
 +/******************************************************************************
 + *
 + * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
@@ -6918,7 +6570,6 @@
 +#ifndef __iwl_4965_rs_h__
 +#define __iwl_4965_rs_h__
 +
-+#include "iwl-hw.h"
 +#include "iwl-4965.h"
 +
 +struct iwl_rate_info {
@@ -7062,10 +6713,35 @@
 +#define IWL_MIN_RSSI_VAL                 -100
 +#define IWL_MAX_RSSI_VAL                    0
 +
-+extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
++#define IWL_LEGACY_SWITCH_ANTENNA	0
++#define IWL_LECACY_SWITCH_SISO		1
++#define IWL_LEGACY_SWITCH_MIMO	        2
++
++#define IWL_RS_GOOD_RATIO		12800
++
++#define IWL_ACTION_LIMIT		3
++#define IWL_LEGACY_FAILURE_LIMIT	160
++#define IWL_LEGACY_SUCCESS_LIMIT	480
++#define IWL_LEGACY_TABLE_COUNT		160
++
++#define IWL_NONE_LEGACY_FAILURE_LIMIT	400
++#define IWL_NONE_LEGACY_SUCCESS_LIMIT	4500
++#define IWL_NONE_LEGACY_TABLE_COUNT	1500
++
++#define IWL_RATE_SCALE_SWITCH		(10880)
++
++#define IWL_SISO_SWITCH_ANTENNA		0
++#define IWL_SISO_SWITCH_MIMO		1
++#define IWL_SISO_SWITCH_GI		2
++
++#define IWL_MIMO_SWITCH_ANTENNA_A	0
++#define IWL_MIMO_SWITCH_ANTENNA_B	1
++#define IWL_MIMO_SWITCH_GI		2
 +
 +#define LQ_SIZE		2
 +
++extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
++
 +enum iwl_table_type {
 +	LQ_NONE,
 +	LQ_G,
@@ -7082,53 +6758,17 @@
 +	ANT_BOTH,
 +};
 +
-+static inline int iwl_rate_index_from_plcp(int plcp)
-+{
-+	int i = 0;
-+
-+	if (plcp & RATE_MCS_HT_MSK) {
-+		i = (plcp & 0xff);
-+
-+		if (i >= IWL_RATE_MIMO_6M_PLCP)
-+			i = i - IWL_RATE_MIMO_6M_PLCP;
-+
-+		i += IWL_FIRST_OFDM_RATE;
-+		/* skip 9M not supported in ht*/
-+		if (i >= IWL_RATE_9M_INDEX)
-+			i += 1;
-+		if ((i >= IWL_FIRST_OFDM_RATE) &&
-+		    (i <= IWL_LAST_OFDM_RATE))
-+			return i;
-+	} else {
-+		for (i = 0; i < ARRAY_SIZE(iwl_rates); i++)
-+			if (iwl_rates[i].plcp == (plcp &0xFF))
-+				return i;
-+	}
-+	return -1;
-+}
-+
-+static inline u8 iwl_rate_get_lowest_plcp(int rate_mask)
-+{
-+	u8 i;
-+
-+	for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
-+	     i = iwl_rates[i].next_ieee) {
-+		if (rate_mask & (1 << i))
-+			return iwl_rates[i].plcp;
-+	}
-+
-+	return IWL_RATE_INVALID;
-+}
-+
 +static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
 +{
 +	u8 rate = iwl_rates[rate_index].prev_ieee;
++
 +	if (rate == IWL_RATE_INVALID)
 +		rate = rate_index;
 +	return rate;
 +}
 +
-+#if IWL == 4965
++extern int iwl_rate_index_from_plcp(int plcp);
++
 +/**
 + * iwl_fill_rs_info - Fill an output text buffer with the rate representation
 + *
@@ -7165,22 +6805,14 @@
 + * the driver is unloaded.
 + */
 +extern void iwl_rate_control_unregister(struct ieee80211_hw *hw);
-+#else
-+static inline int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf,
-+				   u8 sta_id)
-+{ return -ENOTSUPP; }
-+static inline void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) {}
-+static inline void iwl_rate_control_register(struct ieee80211_hw *hw) {}
-+static inline void iwl_rate_control_unregister(struct ieee80211_hw *hw) {}
-+#endif /* IWL == 4965 */
 +
 +#endif
 diff --git a/drivers/net/wireless/iwl-4965.c b/drivers/net/wireless/iwl-4965.c
 new file mode 100644
-index 0000000..a78cc8c
+index 0000000..68b6d52
 --- /dev/null
 +++ b/drivers/net/wireless/iwl-4965.c
-@@ -0,0 +1,4763 @@
+@@ -0,0 +1,4731 @@
 +/******************************************************************************
 + *
 + * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
@@ -7392,14 +7024,14 @@
 +
 +		if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT)
 +			iwl_set_bits_mask_restricted_reg(
-+				priv, ALM_APMG_PS_CTL,
-+				APMG_PS_CTRL_REG_VAL_POWER_SRC_VAUX,
-+				~APMG_PS_CTRL_REG_MSK_POWER_SRC);
++				priv, APMG_PS_CTRL_REG,
++				APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
++				~APMG_PS_CTRL_MSK_PWR_SRC);
 +	} else
 +		iwl_set_bits_mask_restricted_reg(
-+			priv, ALM_APMG_PS_CTL,
-+			APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN,
-+			~APMG_PS_CTRL_REG_MSK_POWER_SRC);
++			priv, APMG_PS_CTRL_REG,
++			APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
++			~APMG_PS_CTRL_MSK_PWR_SRC);
 +
 +	iwl_release_restricted_access(priv);
 +	spin_unlock_irqrestore(&priv->lock, flags);
@@ -7634,14 +7266,14 @@
 +	iwl_read_restricted_reg(priv, APMG_CLK_CTRL_REG);
 +
 +	iwl_write_restricted_reg(priv, APMG_CLK_CTRL_REG,
-+				 APMG_CLK_REG_VAL_DMA_CLK_RQT |
-+				 APMG_CLK_REG_VAL_BSM_CLK_RQT);
++				 APMG_CLK_VAL_DMA_CLK_RQT |
++				 APMG_CLK_VAL_BSM_CLK_RQT);
 +	iwl_read_restricted_reg(priv, APMG_CLK_CTRL_REG);
 +
 +	udelay(20);
 +
-+	iwl_set_bits_restricted_reg(priv, ALM_APMG_PCIDEV_STT,
-+				    APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE);
++	iwl_set_bits_restricted_reg(priv, APMG_PCIDEV_STT_REG,
++				    APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 +
 +	iwl_release_restricted_access(priv);
 +	iwl_write32(priv, CSR_INT_COALESCING, 512 / 32);
@@ -7696,12 +7328,12 @@
 +		return rc;
 +	}
 +
-+	iwl_read_restricted_reg(priv, ALM_APMG_PS_CTL);
-+	iwl_set_bits_restricted_reg(priv, ALM_APMG_PS_CTL,
-+				    APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ);
++	iwl_read_restricted_reg(priv, APMG_PS_CTRL_REG);
++	iwl_set_bits_restricted_reg(priv, APMG_PS_CTRL_REG,
++				    APMG_PS_CTRL_VAL_RESET_REQ);
 +	udelay(5);
-+	iwl_clear_bits_restricted_reg(priv, ALM_APMG_PS_CTL,
-+				      APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ);
++	iwl_clear_bits_restricted_reg(priv, APMG_PS_CTRL_REG,
++				      APMG_PS_CTRL_VAL_RESET_REQ);
 +
 +	iwl_release_restricted_access(priv);
 +	spin_unlock_irqrestore(&priv->lock, flags);
@@ -7827,14 +7459,14 @@
 +
 +	rc = iwl_grab_restricted_access(priv);
 +	if (!rc) {
-+		iwl_write_restricted_reg(priv, ALM_APMG_CLK_EN,
-+					 APMG_CLK_REG_VAL_DMA_CLK_RQT |
-+					 APMG_CLK_REG_VAL_BSM_CLK_RQT);
++		iwl_write_restricted_reg(priv, APMG_CLK_EN_REG,
++					 APMG_CLK_VAL_DMA_CLK_RQT |
++					 APMG_CLK_VAL_BSM_CLK_RQT);
 +
 +		udelay(10);
 +
-+		iwl_set_bits_restricted_reg(priv, ALM_APMG_PCIDEV_STT,
-+				APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE);
++		iwl_set_bits_restricted_reg(priv, APMG_PCIDEV_STT_REG,
++				APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 +
 +		iwl_release_restricted_access(priv);
 +	}
@@ -8992,20 +8624,6 @@
 +	return -EINVAL;
 +}
 +
-+#define TX_POWER_IWL_ILLEGAL_VDET    -100000
-+#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
-+#define TX_POWER_IWL_CLOSED_LOOP_MIN_POWER 18
-+#define TX_POWER_IWL_CLOSED_LOOP_MAX_POWER 34
-+#define TX_POWER_IWL_VDET_SLOPE_BELOW_NOMINAL 17
-+#define TX_POWER_IWL_VDET_SLOPE_ABOVE_NOMINAL 20
-+#define TX_POWER_IWL_NOMINAL_POWER            26
-+#define TX_POWER_IWL_CLOSED_LOOP_ITERATION_LIMIT 1
-+#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V       7
-+#define TX_POWER_IWL_DEGREES_PER_VDET_CODE       11
-+#define IWL_TX_POWER_MAX_NUM_PA_MEASUREMENTS 1
-+#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
-+#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
-+
 +static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res)
 +{
 +	s32 sign = 1;
@@ -9703,7 +9321,7 @@
 + */
 +int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
 +{
-+	struct iwl_tx_power_table_cmd cmd = { 0 };
++	struct iwl_txpowertable_cmd cmd = { 0 };
 +	int rc = 0;
 +	u8 band = 0;
 +	u8 is_fat = 0;
@@ -9723,12 +9341,11 @@
 +	is_fat =  is_fat_channel(priv->active_rxon.flags);
 +
 +	if (is_fat &&
-+	    (priv->active_rxon.flags & RXON_FLG_CONTROL_CHANNEL_LOC_HIGH_MSK))
++	    (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
 +		ctrl_chan_high = 1;
 +
 +	cmd.band = band;
 +	cmd.channel = priv->active_rxon.channel;
-+	cmd.channel_normal_width = 0;
 +
 +	rc = iwl4965_fill_txpower_tbl(priv, band,
 +				le16_to_cpu(priv->active_rxon.channel),
@@ -9757,7 +9374,7 @@
 +	is_fat = is_fat_channel(priv->staging_rxon.flags);
 +
 +	if (is_fat &&
-+	    (priv->active_rxon.flags & RXON_FLG_CONTROL_CHANNEL_LOC_HIGH_MSK))
++	    (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
 +		ctrl_chan_high = 1;
 +
 +	cmd.band = band;
@@ -9981,23 +9598,6 @@
 +	return 0;
 +}
 +
-+#define IWL4965_LEGACY_SWITCH_ANTENNA	0
-+#define IWL4965_LECACY_SWITCH_SISO		1
-+#define IWL4965_LEGACY_SWITCH_MIMO	        2
-+
-+#define IWL4965_GOOD_RATIO			12800
-+
-+#define IWL_ACTION_LIMIT		3
-+#define IWL4965_LEGACY_FAILURE_LIMIT	160
-+#define IWL4965_LEGACY_SUCCESS_LIMIT	480
-+#define IWL4965_LEGACY_TABLE_COUNT		160
-+
-+#define IWL4965_NONE_LEGACY_FAILURE_LIMIT	400
-+#define IWL4965_NONE_LEGACY_SUCCESS_LIMIT	4500
-+#define IWL4965_NONE_LEGACY_TABLE_COUNT	1500
-+
-+#define IWL4965_RATE_SCALE_SWITCH  (10880)
-+
 +/* Set up Rx receiver/antenna/chain usage in "staging" RXON image.
 + * This should not be used for scan command ... it puts data in wrong place.  */
 +void iwl4965_set_rxon_chain(struct iwl_priv *priv)
@@ -11296,7 +10896,7 @@
 +		ack = bitmap0 & (1 << i);
 +		IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
 +			ack? "ACK":"NACK", i, idx, agg->start_idx + i);
-+		iwl4965_set_tx_status(priv, agg->txq_id, idx, ack, 1,
++		iwl4965_set_tx_status(priv, agg->txq_id, idx, ack, 0,
 +			agg->rate_n_flags);
 +
 +	}
@@ -11359,10 +10959,6 @@
 +}
 +
 +
-+#define STA_MODIFY_ADDBA_TID_MSK	0x08
-+#define STA_MODIFY_DELBA_TID_MSK	0x10
-+#define BUILD_RAxTID(sta_id, tid)	(((sta_id) << 4) + (tid))
-+
 +static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)
 +{
 +	iwl_write_restricted_reg(priv,
@@ -11372,7 +10968,7 @@
 +}
 +
 +static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
-+						u16 txq_id)
++					u16 txq_id)
 +{
 +	u32 tbl_dw_addr;
 +	u32 tbl_dw;
@@ -11384,7 +10980,11 @@
 +			SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
 +
 +	tbl_dw = iwl_read_restricted_mem(priv, tbl_dw_addr);
-+	((u16 *)&tbl_dw)[txq_id & 0x1] = scd_q2ratid;
++
++	if (txq_id & 0x1)
++		tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
++	else
++		tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
 +
 +	iwl_write_restricted_mem(priv, tbl_dw_addr, tbl_dw);
 +
@@ -11608,7 +11208,8 @@
 +	if (iwl_is_fat_tx_allowed(priv, ht_info))
 +		rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK;
 +	else
-+		rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY_MSK;
++		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
++				 RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
 +
 +	if (le16_to_cpu(rxon->channel) != ht_info->control_channel) {
 +		IWL_DEBUG_ASSOC("control diff than current %d %d\n",
@@ -11618,14 +11219,13 @@
 +		return;
 +	}
 +
-+	rxon->flags &= ~RXON_FLG_CONTROL_CHANNEL_LOCATION_MSK;
-+
++	/* Note: control channel is oposit to extension channel */
 +	switch (ht_info->extension_chan_offset) {
 +	case IWL_EXT_CHANNEL_OFFSET_ABOVE:
-+		rxon->flags |= RXON_FLG_CONTROL_CHANNEL_LOC_LOW_MSK;
++		rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
 +		break;
 +	case IWL_EXT_CHANNEL_OFFSET_BELOW:
-+		rxon->flags |= RXON_FLG_CONTROL_CHANNEL_LOC_HIGH_MSK;
++		rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
 +		break;
 +	case IWL_EXT_CHANNEL_OFFSET_AUTO:
 +		rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
@@ -11946,10 +11546,10 @@
 +MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
 diff --git a/drivers/net/wireless/iwl-4965.h b/drivers/net/wireless/iwl-4965.h
 new file mode 100644
-index 0000000..af5215f
+index 0000000..4c63b3b
 --- /dev/null
 +++ b/drivers/net/wireless/iwl-4965.h
-@@ -0,0 +1,367 @@
+@@ -0,0 +1,358 @@
 +/******************************************************************************
 + *
 + * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
@@ -11981,45 +11581,6 @@
 +struct iwl_priv;
 +struct sta_ht_info;
 +
-+#if IWL != 4965
-+/*
-+ * In non IWL == 4965 builds, these must build to nothing in order to allow
-+ * the common code to not have several #if IWL == XXXX / #endif blocks
-+ */
-+static inline void iwl_eeprom_release_semaphore(struct iwl_priv *priv) {}
-+
-+static inline void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr,
-+				       int is_ap) {}
-+static inline void iwl4965_set_rxon_ht(struct iwl_priv *priv,
-+				       struct sta_ht_info *ht_info) {}
-+
-+static inline void iwl4965_set_rxon_chain(struct iwl_priv *priv) {}
-+static inline int iwl4965_tx_cmd(struct iwl_priv *priv,
-+				 struct iwl_cmd *out_cmd,
-+				 u8 sta_id, dma_addr_t txcmd_phys,
-+				 struct ieee80211_hdr *hdr, u8 hdr_len,
-+				 struct ieee80211_tx_control *ctrl,
-+				 void *sta_in) { return 0; }
-+static inline int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv,
-+						 struct iwl_tx_queue *txq,
-+						 u16 len) { return 0; }
-+static inline int iwl4965_init_hw_rates(struct iwl_priv *priv,
-+					struct ieee80211_rate *rates)
-+{ return 0; }
-+static inline int iwl4965_alive_notify(struct iwl_priv *priv) { return 0; }
-+static inline void iwl4965_update_rate_scaling(struct iwl_priv *priv,
-+					       u8 mode) {}
-+static inline void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index)
-+{}
-+static inline void iwl4965_chain_noise_reset(struct iwl_priv *priv) {}
-+static inline void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags,
-+					    u8 force) {}
-+static inline int iwl4965_set_fat_chan_info(struct iwl_priv *priv, int phymode,
-+				u16 channel,
-+				const struct iwl_eeprom_channel *eeprom_ch,
-+				u8 fat_extension_channel) { return 0; }
-+static inline void iwl4965_rf_kill_ct_config(struct iwl_priv *priv) {}
-+#else				/* IWL == 4965 */
 +/*
 + * Forward declare iwl-4965.c functions for iwl-base.c
 + */
@@ -12111,11 +11672,42 @@
 +#define NRG_NUM_PREV_STAT_L     20
 +#define NUM_RX_CHAINS           (3)
 +
-+struct iwl_traffic_load {
-+	unsigned long time_stamp;
-+	u32 packet_count[TID_QUEUE_MAX_SIZE];
-+	u8 queue_count;
-+	u8 head;
++#define TX_POWER_IWL_ILLEGAL_VDET    -100000
++#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
++#define TX_POWER_IWL_CLOSED_LOOP_MIN_POWER 18
++#define TX_POWER_IWL_CLOSED_LOOP_MAX_POWER 34
++#define TX_POWER_IWL_VDET_SLOPE_BELOW_NOMINAL 17
++#define TX_POWER_IWL_VDET_SLOPE_ABOVE_NOMINAL 20
++#define TX_POWER_IWL_NOMINAL_POWER            26
++#define TX_POWER_IWL_CLOSED_LOOP_ITERATION_LIMIT 1
++#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V       7
++#define TX_POWER_IWL_DEGREES_PER_VDET_CODE       11
++#define IWL_TX_POWER_MAX_NUM_PA_MEASUREMENTS 1
++#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
++#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
++
++#define IWL4965_LEGACY_SWITCH_ANTENNA	0
++#define IWL4965_LECACY_SWITCH_SISO		1
++#define IWL4965_LEGACY_SWITCH_MIMO	        2
++
++#define IWL4965_GOOD_RATIO			12800
++
++#define IWL_ACTION_LIMIT		3
++#define IWL4965_LEGACY_FAILURE_LIMIT	160
++#define IWL4965_LEGACY_SUCCESS_LIMIT	480
++#define IWL4965_LEGACY_TABLE_COUNT		160
++
++#define IWL4965_NONE_LEGACY_FAILURE_LIMIT	400
++#define IWL4965_NONE_LEGACY_SUCCESS_LIMIT	4500
++#define IWL4965_NONE_LEGACY_TABLE_COUNT	1500
++
++#define IWL4965_RATE_SCALE_SWITCH  (10880)
++
++struct iwl_traffic_load {
++	unsigned long time_stamp;
++	u32 packet_count[TID_QUEUE_MAX_SIZE];
++	u8 queue_count;
++	u8 head;
 +	u32 total;
 +};
 +
@@ -12315,20 +11907,16 @@
 +#define	EEPROM_SEM_TIMEOUT 10
 +#define EEPROM_SEM_RETRY_LIMIT 1000
 +
-+#endif				/* IWL == 4965 */
 +#endif				/* __iwl_4965_h__ */
-diff --git a/drivers/net/wireless/iwl-base.c b/drivers/net/wireless/iwl-base.c
+diff --git a/drivers/net/wireless/iwl-channel.h b/drivers/net/wireless/iwl-channel.h
 new file mode 100644
-index 0000000..4b80728
+index 0000000..023c3f2
 --- /dev/null
-+++ b/drivers/net/wireless/iwl-base.c
-@@ -0,0 +1,9643 @@
++++ b/drivers/net/wireless/iwl-channel.h
+@@ -0,0 +1,161 @@
 +/******************************************************************************
 + *
-+ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ipw3945 project, as well
-+ * as portions of the ieee80211 subsystem header files.
++ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of version 2 of the GNU General Public License as
@@ -12351,13890 +11939,22449 @@
 + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 + *
 + *****************************************************************************/
++#ifndef __iwl_channel_h__
++#define __iwl_channel_h__
 +
-+/*
-+ * NOTE:  This file (iwl-base.c) is used to build to multiple hardware targets
-+ * by defining IWL to either 3945 or 4965.  The Makefile used when building
-+ * the base targets will create base-3945.o and base-4965.o
-+ *
-+ * The eventual goal is to move as many of the #if IWL / #endif blocks out of
-+ * this file and into the hardware specific implementation files (iwl-XXXX.c)
-+ * and leave only the common (non #ifdef sprinkled) code in this file
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/delay.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/wireless.h>
-+#include <linux/firmware.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/if_arp.h>
-+
-+#include <net/ieee80211_radiotap.h>
-+#include <net/mac80211.h>
++#define IWL_NUM_SCAN_RATES         (2)
 +
-+#include <asm/div64.h>
++struct iwl_channel_tgd_info {
++	u8 type;
++	s8 max_power;
++};
 +
-+#include "iwlwifi.h"
-+#include "iwl-helpers.h"
++struct iwl_channel_tgh_info {
++	s64 last_radar_time;
++};
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+u32 iwl_debug_level;
-+#endif
++/* current Tx power values to use, one for each rate for each channel.
++ * requested power is limited by:
++ * -- regulatory EEPROM limits for this channel
++ * -- hardware capabilities (clip-powers)
++ * -- spectrum management
++ * -- user preference (e.g. iwconfig)
++ * when requested power is set, base power index must also be set. */
++struct iwl_channel_power_info {
++	struct iwl_tx_power tpc;	/* actual radio and DSP gain settings */
++	s8 power_table_index;	/* actual (compenst'd) index into gain table */
++	s8 base_power_index;	/* gain index for power at factory temp. */
++	s8 requested_power;	/* power (dBm) requested for this chnl/rate */
++};
 +
-+/******************************************************************************
-+ *
-+ * module boiler plate
-+ *
-+ ******************************************************************************/
++/* current scan Tx power values to use, one for each scan rate for each
++ * channel. */
++struct iwl_scan_power_info {
++	struct iwl_tx_power tpc;	/* actual radio and DSP gain settings */
++	s8 power_table_index;	/* actual (compenst'd) index into gain table */
++	s8 requested_power;	/* scan pwr (dBm) requested for chnl/rate */
++};
 +
-+/* module parameters */
-+int iwl_param_disable_hw_scan;
-+int iwl_param_debug;
-+int iwl_param_disable;      /* def: enable radio */
-+int iwl_param_antenna;      /* def: 0 = both antennas (use diversity) */
-+int iwl_param_hwcrypto;     /* def: using software encryption */
-+int iwl_param_qos_enable = 1;
-+int iwl_param_queues_num = IWL_MAX_NUM_QUEUES;
++/* Channel unlock period is 15 seconds. If no beacon or probe response
++ * has been received within 15 seconds on a locked channel then the channel
++ * remains locked. */
++#define TX_UNLOCK_PERIOD 15
 +
++/* CSA lock period is 15 seconds.  If a CSA has been received on a channel in
++ * the last 15 seconds, the channel is locked */
++#define CSA_LOCK_PERIOD 15
 +/*
-+ * module name, copyright, version, etc.
-+ * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk
++ * One for each channel, holds all channel setup data
++ * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
++ *     with one another!
 + */
++#define IWL4965_MAX_RATE (33)
 +
-+#if IWL == 3945
-+#define DRV_DESCRIPTION	\
-+"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
-+#elif IWL == 4965
-+#define DRV_DESCRIPTION	\
-+"Intel(R) Wireless WiFi Link 4965AGN driver for Linux"
-+#else
-+BUILD_BUG()
-+#endif
++struct iwl_channel_info {
++	struct iwl_channel_tgd_info tgd;
++	struct iwl_channel_tgh_info tgh;
++	struct iwl_eeprom_channel eeprom;	/* EEPROM regulatory limit */
++	struct iwl_eeprom_channel fat_eeprom;	/* EEPROM regulatory limit for
++						 * FAT channel */
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+#define VD "d"
-+#else
-+#define VD
-+#endif
++	u8 channel;	  /* channel number */
++	u8 flags;	  /* flags copied from EEPROM */
++	s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
++	s8 curr_txpow;	  /* (dBm) regulatory/spectrum/user (not h/w) */
++	s8 min_power;	  /* always 0 */
++	s8 scan_power;	  /* (dBm) regul. eeprom, direct scans, any rate */
 +
-+#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
-+#define VS "s"
-+#else
-+#define VS
-+#endif
++	u8 group_index;	  /* 0-4, maps channel to group1/2/3/4/5 */
++	u8 band_index;	  /* 0-4, maps channel to band1/2/3/4/5 */
++	u8 phymode;	  /* MODE_IEEE80211{A,B,G} */
 +
-+#define IWLWIFI_VERSION "0.1.11k" VD VS
-+#define DRV_COPYRIGHT	"Copyright(c) 2003-2007 Intel Corporation"
-+#define DRV_VERSION     IWLWIFI_VERSION
++	/* Radio/DSP gain settings for each "normal" data Tx rate.
++	 * These include, in addition to RF and DSP gain, a few fields for
++	 *   remembering/modifying gain settings (indexes). */
++	struct iwl_channel_power_info power_info[IWL4965_MAX_RATE];
 +
-+/* Change firmware file name, using "-" and incrementing number,
-+ *   *only* when uCode interface or architecture changes so that it
-+ *   is not compatible with earlier drivers.
-+ * This number will also appear in << 8 position of 1st dword of uCode file */
-+#define IWL3945_UCODE_API "-1"
-+#define IWL4965_UCODE_API "-1"
++#if IWL == 4965
++	/* FAT channel info */
++	s8 fat_max_power_avg;	/* (dBm) regul. eeprom, normal Tx, any rate */
++	s8 fat_curr_txpow;	/* (dBm) regulatory/spectrum/user (not h/w) */
++	s8 fat_min_power;	/* always 0 */
++	s8 fat_scan_power;	/* (dBm) eeprom, direct scans, any rate */
++	u8 fat_flags;		/* flags copied from EEPROM */
++	u8 fat_extension_channel;
++#endif
 +
-+MODULE_DESCRIPTION(DRV_DESCRIPTION);
-+MODULE_VERSION(DRV_VERSION);
-+MODULE_AUTHOR(DRV_COPYRIGHT);
-+MODULE_LICENSE("GPL");
++	/* Radio/DSP gain settings for each scan rate, for directed scans. */
++	struct iwl_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
++};
 +
-+__le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
-+{
-+	u16 fc = le16_to_cpu(hdr->frame_control);
-+	int hdr_len = ieee80211_get_hdrlen(fc);
++struct iwl_clip_group {
++	/* maximum power level to prevent clipping for each rate, derived by
++	 *   us from this band's saturation power in EEPROM */
++	const s8 clip_powers[IWL_MAX_RATES];
++};
 +
-+	if ((fc & 0x00cc) == (IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA))
-+		return (__le16 *) ((u8 *) hdr + hdr_len - QOS_CONTROL_LEN);
-+	return NULL;
++static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
++{
++	if (ch_info == NULL)
++		return 0;
++	return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
 +}
 +
-+static const struct ieee80211_hw_mode *iwl_get_hw_mode(
-+		struct iwl_priv *priv, int mode)
++static inline int is_channel_narrow(const struct iwl_channel_info *ch_info)
 +{
-+	int i;
-+
-+	for (i = 0; i < 3; i++)
-+		if (priv->modes[i].mode == mode)
-+			return &priv->modes[i];
++	return (ch_info->flags & EEPROM_CHANNEL_NARROW) ? 1 : 0;
++}
 +
-+	return NULL;
++static inline int is_channel_radar(const struct iwl_channel_info *ch_info)
++{
++	return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
 +}
 +
-+static int iwl_is_empty_essid(const char *essid, int essid_len)
++static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info)
 +{
-+	/* Single white space is for Linksys APs */
-+	if (essid_len == 1 && essid[0] == ' ')
-+		return 1;
++	return ch_info->phymode == MODE_IEEE80211A;
++}
 +
-+	/* Otherwise, if the entire essid is 0, we assume it is hidden */
-+	while (essid_len) {
-+		essid_len--;
-+		if (essid[essid_len] != '\0')
-+			return 0;
-+	}
++static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info)
++{
++	return ((ch_info->phymode == MODE_IEEE80211B) ||
++		(ch_info->phymode == MODE_IEEE80211G));
++}
 +
-+	return 1;
++static inline int is_channel_passive(const struct iwl_channel_info *ch)
++{
++	return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
 +}
 +
-+static const char *iwl_escape_essid(const char *essid, u8 essid_len)
++static inline int is_channel_ibss(const struct iwl_channel_info *ch)
 +{
-+	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-+	const char *s = essid;
-+	char *d = escaped;
++	return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
++}
 +
-+	if (iwl_is_empty_essid(essid, essid_len)) {
-+		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
-+		return escaped;
-+	}
-+
-+	essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
-+	while (essid_len--) {
-+		if (*s == '\0') {
-+			*d++ = '\\';
-+			*d++ = '0';
-+			s++;
-+		} else
-+			*d++ = *s++;
-+	}
-+	*d = '\0';
-+	return escaped;
-+}
-+
-+static void iwl_print_hex_dump(int level, void *p, u32 len)
-+{
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	if (!(iwl_debug_level & level))
-+		return;
++extern const struct iwl_channel_info *iwl_get_channel_info(
++	const struct iwl_priv *priv, int phymode, u16 channel);
 +
-+	print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
-+			p, len, 1);
 +#endif
-+}
-+
-+/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
-+ * DMA services
+diff --git a/drivers/net/wireless/iwl-commands.h b/drivers/net/wireless/iwl-commands.h
+new file mode 100644
+index 0000000..b686d16
+--- /dev/null
++++ b/drivers/net/wireless/iwl-commands.h
+@@ -0,0 +1,1737 @@
++/******************************************************************************
 + *
-+ * Theory of operation
++ * This file is provided under a dual BSD/GPLv2 license.  When using or
++ * redistributing this file, you may do so under either license.
 + *
-+ * A queue is a circular buffers with 'Read' and 'Write' pointers.
-+ * 2 empty entries always kept in the buffer to protect from overflow.
++ * GPL LICENSE SUMMARY
 + *
-+ * For Tx queue, there are low mark and high mark limits. If, after queuing
-+ * the packet for Tx, free space become < low mark, Tx queue stopped. When
-+ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
-+ * Tx queue resumed.
++ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
 + *
-+ * The IPW operates with six queues, one receive queue in the device's
-+ * sram, one transmit queue for sending commands to the device firmware,
-+ * and four transmit queues for data.
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU Geeral Public License as
++ * published by the Free Software Foundation.
 + *
-+ * The four transmit queues allow for performing quality of service (qos)
-+ * transmissions as per the 802.11 protocol.  Currently Linux does not
-+ * provide a mechanism to the user for utilizing prioritized queues, so
-+ * we only utilize the first data transmit queue (queue1).
-+ ***************************************************/
-+
-+static int iwl_queue_space(const struct iwl_queue *q)
-+{
-+	int s = q->last_used - q->first_empty;
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ *  * Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ *  * Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *  * Neither the name Intel Corporation nor the names of its
++ *    contributors may be used to endorse or promote products derived
++ *    from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ *****************************************************************************/
 +
-+	if (q->last_used > q->first_empty)
-+		s -= q->n_bd;
++#ifndef __iwl_commands_h__
++#define __iwl_commands_h__
 +
-+	if (s <= 0)
-+		s += q->n_window;
-+	/* keep some reserve to not confuse empty and full situations */
-+	s -= 2;
-+	if (s < 0)
-+		s = 0;
-+	return s;
-+}
++enum {
++	REPLY_ALIVE = 0x1,
++	REPLY_ERROR = 0x2,
 +
-+/* XXX: n_bd must be power-of-two size */
-+static inline int iwl_queue_inc_wrap(int index, int n_bd)
-+{
-+	return ++index & (n_bd - 1);
-+}
++	/* RXON and QOS commands */
++	REPLY_RXON = 0x10,
++	REPLY_RXON_ASSOC = 0x11,
++	REPLY_QOS_PARAM = 0x13,
++	REPLY_RXON_TIMING = 0x14,
 +
-+/* XXX: n_bd must be power-of-two size */
-+static inline int iwl_queue_dec_wrap(int index, int n_bd)
-+{
-+	return --index & (n_bd - 1);
-+}
++	/* Multi-Station support */
++	REPLY_ADD_STA = 0x18,
++	REPLY_REMOVE_STA = 0x19,	/* not used */
++	REPLY_REMOVE_ALL_STA = 0x1a,	/* not used */
 +
-+static inline int x2_queue_used(const struct iwl_queue *q, int i)
-+{
-+	return q->first_empty > q->last_used ?
-+		(i >= q->last_used && i < q->first_empty) :
-+		!(i < q->last_used && i >= q->first_empty);
-+}
++	/* RX, TX, LEDs */
++#if IWL == 3945
++	REPLY_3945_RX = 0x1b,		/* 3945 only */
++#endif
++	REPLY_TX = 0x1c,
++	REPLY_RATE_SCALE = 0x47,	/* 3945 only */
++	REPLY_LEDS_CMD = 0x48,
++	REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */
 +
-+static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
-+{
-+	if (is_huge)
-+		return q->n_window;
++	/* 802.11h related */
++	RADAR_NOTIFICATION = 0x70,	/* not used */
++	REPLY_QUIET_CMD = 0x71,		/* not used */
++	REPLY_CHANNEL_SWITCH = 0x72,
++	CHANNEL_SWITCH_NOTIFICATION = 0x73,
++	REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74,
++	SPECTRUM_MEASURE_NOTIFICATION = 0x75,
 +
-+	return index & (q->n_window - 1);
-+}
++	/* Power Management */
++	POWER_TABLE_CMD = 0x77,
++	PM_SLEEP_NOTIFICATION = 0x7A,
++	PM_DEBUG_STATISTIC_NOTIFIC = 0x7B,
 +
-+static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
-+			  int count, int slots_num, u32 id)
-+{
-+	q->n_bd = count;
-+	q->n_window = slots_num;
-+	q->id = id;
++	/* Scan commands and notifications */
++	REPLY_SCAN_CMD = 0x80,
++	REPLY_SCAN_ABORT_CMD = 0x81,
++	SCAN_START_NOTIFICATION = 0x82,
++	SCAN_RESULTS_NOTIFICATION = 0x83,
++	SCAN_COMPLETE_NOTIFICATION = 0x84,
 +
-+	/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
-+	 * and iwl_queue_dec_wrap are broken. */
-+	BUG_ON(!is_power_of_2(count));
++	/* IBSS/AP commands */
++	BEACON_NOTIFICATION = 0x90,
++	REPLY_TX_BEACON = 0x91,
++	WHO_IS_AWAKE_NOTIFICATION = 0x94,	/* not used */
 +
-+	/* slots_num must be power-of-two size, otherwise
-+	 * get_cmd_index is broken. */
-+	BUG_ON(!is_power_of_2(slots_num));
++	/* Miscellaneous commands */
++	QUIET_NOTIFICATION = 0x96,		/* not used */
++	REPLY_TX_PWR_TABLE_CMD = 0x97,
++	MEASURE_ABORT_NOTIFICATION = 0x99,	/* not used */
 +
-+	q->low_mark = q->n_window / 4;
-+	if (q->low_mark < 4)
-+		q->low_mark = 4;
++	/* BT config command */
++	REPLY_BT_CONFIG = 0x9b,
 +
-+	q->high_mark = q->n_window / 8;
-+	if (q->high_mark < 2)
-+		q->high_mark = 2;
++	/* 4965 Statistics */
++	REPLY_STATISTICS_CMD = 0x9c,
++	STATISTICS_NOTIFICATION = 0x9d,
 +
-+	q->first_empty = q->last_used = 0;
++	/* RF-KILL commands and notifications */
++	REPLY_CARD_STATE_CMD = 0xa0,
++	CARD_STATE_NOTIFICATION = 0xa1,
 +
-+	return 0;
-+}
++	/* Missed beacons notification */
++	MISSED_BEACONS_NOTIFICATION = 0xa2,
 +
-+static int iwl_tx_queue_alloc(struct iwl_priv *priv,
-+			      struct iwl_tx_queue *txq, u32 id)
-+{
-+	struct pci_dev *dev = priv->pci_dev;
++#if IWL == 4965
++	REPLY_CT_KILL_CONFIG_CMD = 0xa4,
++	SENSITIVITY_CMD = 0xa8,
++	REPLY_PHY_CALIBRATION_CMD = 0xb0,
++	REPLY_RX_PHY_CMD = 0xc0,
++	REPLY_RX_MPDU_CMD = 0xc1,
++	REPLY_4965_RX = 0xc3,
++	REPLY_COMPRESSED_BA = 0xc5,
++#endif
++	REPLY_MAX = 0xff
++};
 +
-+	if (id != IWL_CMD_QUEUE_NUM) {
-+		txq->txb = kmalloc(sizeof(txq->txb[0]) *
-+				   TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
-+		if (!txq->txb) {
-+			IWL_ERROR("kmalloc for auxilary BD "
-+				  "structures failed\n");
-+			goto error;
-+		}
-+	} else
-+		txq->txb = NULL;
++/******************************************************************************
++ * (0)
++ * Header
++ *
++ *****************************************************************************/
 +
-+	txq->bd = pci_alloc_consistent(dev,
-+			sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
-+			&txq->q.dma_addr);
++#define IWL_CMD_FAILED_MSK 0x40
 +
-+	if (!txq->bd) {
-+		IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
-+			  sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
-+		goto error;
-+	}
-+	txq->q.id = id;
-+
-+	return 0;
-+
-+ error:
-+	if (txq->txb) {
-+		kfree(txq->txb);
-+		txq->txb = NULL;
-+	}
++struct iwl_cmd_header {
++	u8 cmd;
++	u8 flags;
++	/* We have 15 LSB to use as we please (MSB indicates
++	 * a frame Rx'd from the HW).  We encode the following
++	 * information into the sequence field:
++	 *
++	 *  0:7    index in fifo
++	 *  8:13   fifo selection
++	 * 14:14   bit indicating if this packet references the 'extra'
++	 *         storage at the end of the memory queue
++	 * 15:15   (Rx indication)
++	 *
++	 */
++	__le16 sequence;
 +
-+	return -ENOMEM;
-+}
++	/* command data follows immediately */
++	u8 data[0];
++} __attribute__ ((packed));
 +
-+int iwl_tx_queue_init(struct iwl_priv *priv,
-+		      struct iwl_tx_queue *txq, int slots_num, u32 txq_id)
-+{
-+	struct pci_dev *dev = priv->pci_dev;
-+	int len;
-+	int rc = 0;
++/******************************************************************************
++ * (0a)
++ * Alive and Error Commands & Responses:
++ *
++ *****************************************************************************/
 +
-+	/* alocate command space + one big command for scan since scan
-+	 * command is very huge the system will not have two scan at the
-+	 * same time */
-+	len = sizeof(struct iwl_cmd) * slots_num;
-+	if (txq_id == IWL_CMD_QUEUE_NUM);
-+		len +=  IWL_MAX_SCAN_SIZE;
-+	txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
-+	if (!txq->cmd)
-+		return -ENOMEM;
++#define UCODE_VALID_OK	__constant_cpu_to_le32(0x1)
++#define INITIALIZE_SUBTYPE    (9)
 +
-+	rc = iwl_tx_queue_alloc(priv, txq, txq_id);
-+	if (rc) {
-+		pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
++/*
++ * REPLY_ALIVE = 0x1 (response only, not a command)
++ */
++struct iwl_alive_resp {
++	u8 ucode_minor;
++	u8 ucode_major;
++	__le16 reserved1;
++	u8 sw_rev[8];
++	u8 ver_type;
++	u8 ver_subtype;
++	__le16 reserved2;
++	__le32 log_event_table_ptr;
++	__le32 error_event_table_ptr;
++	__le32 timestamp;
++	__le32 is_valid;
++} __attribute__ ((packed));
 +
-+		return -ENOMEM;
-+	}
-+	txq->need_update = 0;
++struct iwl_init_alive_resp {
++	u8 ucode_minor;
++	u8 ucode_major;
++	__le16 reserved1;
++	u8 sw_rev[8];
++	u8 ver_type;
++	u8 ver_subtype;
++	__le16 reserved2;
++	__le32 log_event_table_ptr;
++	__le32 error_event_table_ptr;
++	__le32 timestamp;
++	__le32 is_valid;
 +
-+	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
-+	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
-+	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
-+	iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
++#if IWL == 4965
++	/* calibration values from "initialize" uCode */
++	__le32 voltage;		/* signed */
++	__le32 therm_r1[2];	/* signed 1st for normal, 2nd for FAT channel */
++	__le32 therm_r2[2];	/* signed */
++	__le32 therm_r3[2];	/* signed */
++	__le32 therm_r4[2];	/* signed */
++	__le32 tx_atten[5][2];	/* signed MIMO gain comp, 5 freq groups,
++				 * 2 Tx chains */
++#endif
++} __attribute__ ((packed));
 +
-+	iwl_hw_tx_queue_init(priv, txq);
++union tsf {
++	u8 byte[8];
++	__le16 word[4];
++	__le32 dw[2];
++};
 +
-+	return 0;
-+}
++/*
++ * REPLY_ERROR = 0x2 (response only, not a command)
++ */
++struct iwl_error_resp {
++	__le32 error_type;
++	u8 cmd_id;
++	u8 reserved1;
++	__le16 bad_cmd_seq_num;
++#if IWL == 3945
++	__le16 reserved2;
++#endif
++	__le32 error_info;
++	union tsf timestamp;
++} __attribute__ ((packed));
 +
-+/**
-+ * iwl_tx_queue_free - Deallocate DMA queue.
-+ * @txq: Transmit queue to deallocate.
-+ *
-+ * Empty queue by removing and destroying all BD's.
-+ * Free all buffers.  txq itself is not freed.
++/******************************************************************************
++ * (1)
++ * RXON Commands & Responses:
 + *
++ *****************************************************************************/
++
++/*
++ * Rx config defines & structure
 + */
-+void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-+{
-+	struct iwl_queue *q = &txq->q;
-+	struct pci_dev *dev = priv->pci_dev;
-+	int len;
++/* rx_config device types  */
++enum {
++	RXON_DEV_TYPE_AP = 1,
++	RXON_DEV_TYPE_ESS = 3,
++	RXON_DEV_TYPE_IBSS = 4,
++	RXON_DEV_TYPE_SNIFFER = 6,
++};
 +
-+	if (q->n_bd == 0)
-+		return;
++/* rx_config flags */
++/* band & modulation selection */
++#define RXON_FLG_BAND_24G_MSK           __constant_cpu_to_le32(1 << 0)
++#define RXON_FLG_CCK_MSK                __constant_cpu_to_le32(1 << 1)
++/* auto detection enable */
++#define RXON_FLG_AUTO_DETECT_MSK        __constant_cpu_to_le32(1 << 2)
++/* TGg protection when tx */
++#define RXON_FLG_TGG_PROTECT_MSK        __constant_cpu_to_le32(1 << 3)
++/* cck short slot & preamble */
++#define RXON_FLG_SHORT_SLOT_MSK          __constant_cpu_to_le32(1 << 4)
++#define RXON_FLG_SHORT_PREAMBLE_MSK     __constant_cpu_to_le32(1 << 5)
++/* antenna selection */
++#define RXON_FLG_DIS_DIV_MSK            __constant_cpu_to_le32(1 << 7)
++#define RXON_FLG_ANT_SEL_MSK            __constant_cpu_to_le32(0x0f00)
++#define RXON_FLG_ANT_A_MSK              __constant_cpu_to_le32(1 << 8)
++#define RXON_FLG_ANT_B_MSK              __constant_cpu_to_le32(1 << 9)
++/* radar detection enable */
++#define RXON_FLG_RADAR_DETECT_MSK       __constant_cpu_to_le32(1 << 12)
++#define RXON_FLG_TGJ_NARROW_BAND_MSK    __constant_cpu_to_le32(1 << 13)
++/* rx response to host with 8-byte TSF
++* (according to ON_AIR deassertion) */
++#define RXON_FLG_TSF2HOST_MSK           __constant_cpu_to_le32(1 << 15)
 +
-+	/* first, empty all BD's */
-+	for (; q->first_empty != q->last_used;
-+	     q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd))
-+		iwl_hw_txq_free_tfd(priv, txq);
++/* rx_config filter flags */
++/* accept all data frames */
++#define RXON_FILTER_PROMISC_MSK         __constant_cpu_to_le32(1 << 0)
++/* pass control & management to host */
++#define RXON_FILTER_CTL2HOST_MSK        __constant_cpu_to_le32(1 << 1)
++/* accept multi-cast */
++#define RXON_FILTER_ACCEPT_GRP_MSK      __constant_cpu_to_le32(1 << 2)
++/* don't decrypt uni-cast frames */
++#define RXON_FILTER_DIS_DECRYPT_MSK     __constant_cpu_to_le32(1 << 3)
++/* don't decrypt multi-cast frames */
++#define RXON_FILTER_DIS_GRP_DECRYPT_MSK __constant_cpu_to_le32(1 << 4)
++/* STA is associated */
++#define RXON_FILTER_ASSOC_MSK           __constant_cpu_to_le32(1 << 5)
++/* transfer to host non bssid beacons in associated state */
++#define RXON_FILTER_BCON_AWARE_MSK      __constant_cpu_to_le32(1 << 6)
 +
-+	len = sizeof(struct iwl_cmd) * q->n_window;
-+	if (q->id == IWL_CMD_QUEUE_NUM);
-+		len += IWL_MAX_SCAN_SIZE;
++/*
++ * REPLY_RXON = 0x10 (command, has simple generic response)
++ */
++struct iwl_rxon_cmd {
++	u8 node_addr[6];
++	__le16 reserved1;
++	u8 bssid_addr[6];
++	__le16 reserved2;
++	u8 wlap_bssid_addr[6];
++	__le16 reserved3;
++	u8 dev_type;
++	u8 air_propagation;
++#if IWL == 3945
++	__le16 reserved4;
++#elif IWL == 4965
++	__le16 rx_chain;
++#endif
++	u8 ofdm_basic_rates;
++	u8 cck_basic_rates;
++	__le16 assoc_id;
++	__le32 flags;
++	__le32 filter_flags;
++	__le16 channel;
++#if IWL == 3945
++	__le16 reserved5;
++#elif IWL == 4965
++	u8 ofdm_ht_single_stream_basic_rates;
++	u8 ofdm_ht_dual_stream_basic_rates;
++#endif
++} __attribute__ ((packed));
 +
-+	pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
++/*
++ * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
++ */
++struct iwl_rxon_assoc_cmd {
++	__le32 flags;
++	__le32 filter_flags;
++	u8 ofdm_basic_rates;
++	u8 cck_basic_rates;
++#if IWL == 4965
++	u8 ofdm_ht_single_stream_basic_rates;
++	u8 ofdm_ht_dual_stream_basic_rates;
++	__le16 rx_chain_select_flags;
++#endif
++	__le16 reserved;
++} __attribute__ ((packed));
 +
-+	/* free buffers belonging to queue itself */
-+	if (txq->q.n_bd)
-+		pci_free_consistent(dev, sizeof(struct iwl_tfd_frame) *
-+				    txq->q.n_bd, txq->bd, txq->q.dma_addr);
++/*
++ * REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
++ */
++struct iwl_rxon_time_cmd {
++	union tsf timestamp;
++	__le16 beacon_interval;
++	__le16 atim_window;
++	__le32 beacon_init_val;
++	__le16 listen_interval;
++	__le16 reserved;
++} __attribute__ ((packed));
 +
-+	if (txq->txb) {
-+		kfree(txq->txb);
-+		txq->txb = NULL;
-+	}
-+
-+	/* 0 fill whole structure */
-+	memset(txq, 0, sizeof(*txq));
-+}
-+
-+const u8 BROADCAST_ADDR[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-+
-+/*************** STATION TABLE MANAGEMENT ****
-+ *
-+ * NOTE:  This needs to be overhauled to better synchronize between
-+ * how the iwl-4965.c is using iwl_hw_find_station vs. iwl-3945.c
-+ *
-+ * mac80211 should also be examined to determine if sta_info is duplicating
-+ * the functionality provided here
-+ */
++struct iwl_tx_power {
++	u8 tx_gain;		/* gain for analog radio */
++	u8 dsp_atten;		/* gain for DSP */
++} __attribute__ ((packed));
 +
-+/**************************************************************/
++#if IWL == 3945
++struct iwl_power_per_rate {
++	u8 rate;		/* plcp */
++	struct iwl_tx_power tpc;
++	u8 reserved;
++} __attribute__ ((packed));
 +
-+static u8 iwl_remove_station(struct iwl_priv *priv, const u8 *bssid, int is_ap)
-+{
-+	int index = IWL_INVALID_STATION;
-+	int i;
-+	unsigned long flags;
++#elif IWL == 4965
++#define POWER_TABLE_NUM_ENTRIES			33
++#define POWER_TABLE_NUM_HT_OFDM_ENTRIES		32
++#define POWER_TABLE_CCK_ENTRY			32
++struct tx_power_dual_stream {
++	__le32 dw;
++} __attribute__ ((packed));
 +
-+	spin_lock_irqsave(&priv->sta_lock, flags);
++struct iwl_tx_power_db {
++	struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES];
++} __attribute__ ((packed));
++#endif
 +
-+	if (is_ap) {
-+		index = IWL_AP_ID;
-+		if ((priv->stations[index].used))
-+			priv->stations[index].used = 0;
-+	} else if (is_broadcast_ether_addr(bssid)) {
-+		index = IWL_BROADCAST_ID;
-+		if ((priv->stations[index].used))
-+			priv->stations[index].used = 0;
-+	} else {
-+		for (i = IWL_STA_ID; i < priv->num_stations + IWL_STA_ID; i++) {
-+			if (priv->stations[i].used &&
-+			    !compare_ether_addr(priv->stations[i].sta.sta.addr,
-+						bssid)) {
-+				index = i;
-+				priv->stations[index].used = 0;
-+				break;
-+			}
-+		}
-+	}
-+	if (index != IWL_INVALID_STATION) {
-+		if (priv->num_stations > 0)
-+			priv->num_stations--;
-+	}
++/*
++ * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
++ */
++struct iwl_channel_switch_cmd {
++	u8 band;
++	u8 expect_beacon;
++	__le16 channel;
++	__le32 rxon_flags;
++	__le32 rxon_filter_flags;
++	__le32 switch_time;
++#if IWL == 3945
++	struct iwl_power_per_rate power[IWL_MAX_RATES];
++#elif IWL == 4965
++	struct iwl_tx_power_db tx_power;
++#endif
++} __attribute__ ((packed));
 +
-+	spin_unlock_irqrestore(&priv->sta_lock, flags);
-+	return 0;
-+}
++/*
++ * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
++ */
++struct iwl_csa_notification {
++	__le16 band;
++	__le16 channel;
++	__le32 status;		/* 0 - OK, 1 - fail */
++} __attribute__ ((packed));
 +
-+static void iwl_clear_stations_table(struct iwl_priv *priv)
-+{
-+	unsigned long flags;
++/******************************************************************************
++ * (2)
++ * Quality-of-Service (QOS) Commands & Responses:
++ *
++ *****************************************************************************/
++struct iwl_ac_qos {
++	__le16 cw_min;
++	__le16 cw_max;
++	u8 aifsn;
++	u8 reserved1;
++	__le16 edca_txop;
++} __attribute__ ((packed));
 +
-+	spin_lock_irqsave(&priv->sta_lock, flags);
++/* QoS flags defines */
++#define QOS_PARAM_FLG_UPDATE_EDCA_MSK	__constant_cpu_to_le32(0x01)
++#define QOS_PARAM_FLG_TGN_MSK		__constant_cpu_to_le32(0x02)
++#define QOS_PARAM_FLG_TXOP_TYPE_MSK	__constant_cpu_to_le32(0x10)
 +
-+	priv->num_stations = 0;
-+	memset(priv->stations, 0, sizeof(priv->stations));
++/*
++ *  TXFIFO Queue number defines
++ */
++/* number of Access categories (AC) (EDCA), queues 0..3 */
++#define AC_NUM                4
 +
-+	spin_unlock_irqrestore(&priv->sta_lock, flags);
-+}
++/*
++ * REPLY_QOS_PARAM = 0x13 (command, has simple generic response)
++ */
++struct iwl_qosparam_cmd {
++	__le32 qos_flags;
++	struct iwl_ac_qos ac[AC_NUM];
++} __attribute__ ((packed));
 +
-+u8 iwl_add_station(struct iwl_priv *priv, const u8 *bssid, int is_ap, u8 flags)
-+{
-+	int i = IWL_STATION_COUNT;
-+	int index = IWL_INVALID_STATION;
-+	struct iwl_station_entry *station;
-+	unsigned long flags_spin;
++/******************************************************************************
++ * (3)
++ * Add/Modify Stations Commands & Responses:
++ *
++ *****************************************************************************/
++/*
++ * Multi station support
++ */
 +#if IWL == 3945
-+	u8 rate;
++enum {
++	IWL_AP_ID = 0,
++	IWL_MULTICAST_ID,
++	IWL_STA_ID,
++	IWL_BROADCAST_ID = 24,
++	IWL_STATION_COUNT = 25,
++	IWL_INVALID_STATION
++};
++#elif IWL == 4965
++enum {
++	IWL_AP_ID = 0,
++	IWL_MULTICAST_ID,
++	IWL_STA_ID,
++	IWL_BROADCAST_ID = 31,
++	IWL_STATION_COUNT = 32,
++	IWL_INVALID_STATION
++};
 +#endif
-+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
-+	if (is_ap) {
-+		index = IWL_AP_ID;
-+		if (priv->stations[index].used &&
-+		    !compare_ether_addr(priv->stations[index].sta.sta.addr,
-+					bssid))
-+			goto done;
-+	} else if (is_broadcast_ether_addr(bssid)) {
-+		index = IWL_BROADCAST_ID;
-+		if (priv->stations[index].used &&
-+		    !compare_ether_addr(priv->stations[index].sta.sta.addr,
-+					bssid))
-+			goto done;
-+	} else {
-+		for (i = IWL_STA_ID; i < priv->num_stations + IWL_STA_ID; i++) {
-+			if (priv->stations[i].used &&
-+			    !compare_ether_addr(priv->stations[i].sta.sta.addr,
-+						bssid))
-+				goto done;
 +
-+			if (!priv->stations[i].used &&
-+			    index == IWL_INVALID_STATION)
-+				index = i;
-+		}
-+	}
++#if IWL == 3945
++#define STA_FLG_TX_RATE_MSK		__constant_cpu_to_le32(1<<2);
++#endif
++#define STA_FLG_PWR_SAVE_MSK		__constant_cpu_to_le32(1<<8);
 +
-+	if (index != IWL_INVALID_STATION)
-+		i = index;
++#define STA_CONTROL_MODIFY_MSK		0x01
 +
-+	if (i == IWL_STATION_COUNT) {
-+		index = IWL_INVALID_STATION;
-+		goto done;
-+	}
++/* key flags __le16*/
++#define STA_KEY_FLG_ENCRYPT_MSK	__constant_cpu_to_le16(0x7)
++#define STA_KEY_FLG_NO_ENC	__constant_cpu_to_le16(0x0)
++#define STA_KEY_FLG_WEP		__constant_cpu_to_le16(0x1)
++#define STA_KEY_FLG_CCMP	__constant_cpu_to_le16(0x2)
++#define STA_KEY_FLG_TKIP	__constant_cpu_to_le16(0x3)
 +
-+	IWL_DEBUG_ASSOC("Adding STA ID %d: " MAC_FMT "\n", i, MAC_ARG(bssid));
-+	station = &priv->stations[i];
++#define STA_KEY_FLG_KEYID_POS	8
++#define STA_KEY_FLG_INVALID 	__constant_cpu_to_le16(0x0800)
 +
-+	station->used = 1;
-+	memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
-+	memcpy(station->sta.sta.addr, bssid, ETH_ALEN);
-+	station->sta.mode = 0;
-+	station->sta.sta.sta_id = i;
-+	station->sta.station_flags = 0;
-+#if IWL == 3945
-+	rate = (priv->phymode == MODE_IEEE80211A) ? IWL_RATE_6M_PLCP :
-+			IWL_RATE_1M_PLCP | priv->hw_setting.cck_flag;
++/* modify flags  */
++#define	STA_MODIFY_KEY_MASK		0x01
++#define	STA_MODIFY_TID_DISABLE_TX	0x02
++#define	STA_MODIFY_TX_RATE_MSK		0x04
++#define STA_MODIFY_ADDBA_TID_MSK	0x08
++#define STA_MODIFY_DELBA_TID_MSK	0x10
++#define BUILD_RAxTID(sta_id, tid)	(((sta_id) << 4) + (tid))
 +
-+	/* Turn on both antennas for the station... */
-+	station->sta.rate_n_flags =
-+			iwl_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK);
++/*
++ * Antenna masks:
++ * bit14:15 01 B inactive, A active
++ *          10 B active, A inactive
++ *          11 Both active
++ */
++#define RATE_MCS_ANT_A_POS	14
++#define RATE_MCS_ANT_B_POS	15
++#define RATE_MCS_ANT_A_MSK	0x4000
++#define RATE_MCS_ANT_B_MSK	0x8000
++#define RATE_MCS_ANT_AB_MSK	0xc000
 +
-+	station->sta.station_flags |= STA_FLG_TX_RATE_MSK;
++struct iwl_keyinfo {
++	__le16 key_flags;
++	u8 tkip_rx_tsc_byte2;	/* TSC[2] for key mix ph1 detection */
++	u8 reserved1;
++	__le16 tkip_rx_ttak[5];	/* 10-byte unicast TKIP TTAK */
++	__le16 reserved2;
++	u8 key[16];		/* 16-byte unicast decryption key */
++} __attribute__ ((packed));
 +
-+	station->current_rate.rate_n_flags =
-+		le16_to_cpu(station->sta.rate_n_flags);
-+#endif
++struct sta_id_modify {
++	u8 addr[ETH_ALEN];
++	__le16 reserved1;
++	u8 sta_id;
++	u8 modify_mask;
++	__le16 reserved2;
++} __attribute__ ((packed));
 +
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+	if (is_ap) {
-+		iwl4965_set_ht_add_station(priv, i);
-+		iwl4965_set_rxon_chain(priv);
-+	}
-+#endif /*CONFIG_IWLWIFI_HT*/
++/*
++ * REPLY_ADD_STA = 0x18 (command)
++ */
++struct iwl_addsta_cmd {
++	u8 mode;
++	u8 reserved[3];
++	struct sta_id_modify sta;
++	struct iwl_keyinfo key;
++	__le32 station_flags;
++	__le32 station_flags_msk;
++	__le16 tid_disable_tx;
++#if IWL == 3945
++	__le16 rate_n_flags;
++#else
++	__le16	reserved1;
++#endif
++	u8 add_immediate_ba_tid;
++	u8 remove_immediate_ba_tid;
++	__le16 add_immediate_ba_ssn;
++#if IWL == 4965
++	__le32 reserved2;
 +#endif
++} __attribute__ ((packed));
 +
-+	priv->num_stations++;
-+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-+	iwl_send_add_station(priv, &station->sta, flags);
-+	return i;
++/*
++ * REPLY_ADD_STA = 0x18 (response)
++ */
++struct iwl_add_sta_resp {
++	u8 status;
++} __attribute__ ((packed));
 +
-+ done:
-+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-+	return index;
-+}
++#define ADD_STA_SUCCESS_MSK              0x1
 +
-+/*************** DRIVER STATUS FUNCTIONS   *****/
++/******************************************************************************
++ * (4)
++ * Rx Responses:
++ *
++ *****************************************************************************/
 +
-+static inline int iwl_is_ready(struct iwl_priv *priv)
-+{
-+	/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
-+	 * set but EXIT_PENDING is not */
-+	return test_bit(STATUS_READY, &priv->status) &&
-+	       test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
-+	       !test_bit(STATUS_EXIT_PENDING, &priv->status);
-+}
++struct iwl_rx_frame_stats {
++	u8 phy_count;
++	u8 id;
++	u8 rssi;
++	u8 agc;
++	__le16 sig_avg;
++	__le16 noise_diff;
++	u8 payload[0];
++} __attribute__ ((packed));
 +
-+static inline int iwl_is_alive(struct iwl_priv *priv)
-+{
-+	return test_bit(STATUS_ALIVE, &priv->status);
-+}
++struct iwl_rx_frame_hdr {
++	__le16 channel;
++	__le16 phy_flags;
++	u8 reserved1;
++	u8 rate;
++	__le16 len;
++	u8 payload[0];
++} __attribute__ ((packed));
 +
-+static inline int iwl_is_init(struct iwl_priv *priv)
-+{
-+	return test_bit(STATUS_INIT, &priv->status);
-+}
++#define	RX_RES_STATUS_NO_CRC32_ERROR	__constant_cpu_to_le32(1 << 0)
++#define	RX_RES_STATUS_NO_RXE_OVERFLOW	__constant_cpu_to_le32(1 << 1)
 +
-+static inline int iwl_is_rfkill(struct iwl_priv *priv)
-+{
-+	return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
-+	       test_bit(STATUS_RF_KILL_SW, &priv->status);
-+}
++#define	RX_RES_PHY_FLAGS_BAND_24_MSK	__constant_cpu_to_le16(1 << 0)
++#define	RX_RES_PHY_FLAGS_MOD_CCK_MSK		__constant_cpu_to_le16(1 << 1)
++#define	RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK	__constant_cpu_to_le16(1 << 2)
++#define	RX_RES_PHY_FLAGS_NARROW_BAND_MSK	__constant_cpu_to_le16(1 << 3)
++#define	RX_RES_PHY_FLAGS_ANTENNA_MSK		__constant_cpu_to_le16(0xf0)
 +
-+static inline int iwl_is_ready_rf(struct iwl_priv *priv)
-+{
++#define	RX_RES_STATUS_SEC_TYPE_MSK	(0x7 << 8)
++#define	RX_RES_STATUS_SEC_TYPE_NONE	(0x0 << 8)
++#define	RX_RES_STATUS_SEC_TYPE_WEP	(0x1 << 8)
++#define	RX_RES_STATUS_SEC_TYPE_CCMP	(0x2 << 8)
++#define	RX_RES_STATUS_SEC_TYPE_TKIP	(0x3 << 8)
 +
-+	if (iwl_is_rfkill(priv))
-+		return 0;
++#define	RX_RES_STATUS_DECRYPT_TYPE_MSK	(0x3 << 11)
++#define	RX_RES_STATUS_NOT_DECRYPT	(0x0 << 11)
++#define	RX_RES_STATUS_DECRYPT_OK	(0x3 << 11)
++#define	RX_RES_STATUS_BAD_ICV_MIC	(0x1 << 11)
++#define	RX_RES_STATUS_BAD_KEY_TTAK	(0x2 << 11)
 +
-+	return iwl_is_ready(priv);
-+}
++struct iwl_rx_frame_end {
++	__le32 status;
++	__le64 timestamp;
++	__le32 beacon_timestamp;
++} __attribute__ ((packed));
 +
-+/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
++/*
++ * REPLY_3945_RX = 0x1b (response only, not a command)
++ *
++ * NOTE:  DO NOT dereference from casts to this structure
++ * It is provided only for calculating minimum data set size.
++ * The actual offsets of the hdr and end are dynamic based on
++ * stats.phy_count
++ */
++struct iwl_rx_frame {
++	struct iwl_rx_frame_stats stats;
++	struct iwl_rx_frame_hdr hdr;
++	struct iwl_rx_frame_end end;
++} __attribute__ ((packed));
 +
-+#define IWL_CMD(x) case x : return #x
++/* Fixed (non-configurable) rx data from phy */
++#define RX_PHY_FLAGS_ANTENNAE_OFFSET		(4)
++#define RX_PHY_FLAGS_ANTENNAE_MASK		(0x70)
++#define IWL_AGC_DB_MASK 	(0x3f80)	/* MASK(7,13) */
++#define IWL_AGC_DB_POS		(7)
++struct iwl4965_rx_non_cfg_phy {
++	__le16 ant_selection;	/* ant A bit 4, ant B bit 5, ant C bit 6 */
++	__le16 agc_info;	/* agc code 0:6, agc dB 7:13, reserved 14:15 */
++	u8 rssi_info[6];	/* we use even entries, 0/2/4 for A/B/C rssi */
++	u8 pad[0];
++} __attribute__ ((packed));
 +
-+static const char *get_cmd_string(u8 cmd)
-+{
-+	switch (cmd) {
-+		IWL_CMD(REPLY_ALIVE);
-+		IWL_CMD(REPLY_ERROR);
-+		IWL_CMD(REPLY_RXON);
-+		IWL_CMD(REPLY_RXON_ASSOC);
-+		IWL_CMD(REPLY_QOS_PARAM);
-+		IWL_CMD(REPLY_RXON_TIMING);
-+		IWL_CMD(REPLY_ADD_STA);
-+		IWL_CMD(REPLY_REMOVE_STA);
-+		IWL_CMD(REPLY_REMOVE_ALL_STA);
-+#if IWL == 3945
-+		IWL_CMD(REPLY_3945_RX);
-+#endif
-+		IWL_CMD(REPLY_TX);
-+		IWL_CMD(REPLY_RATE_SCALE);
-+		IWL_CMD(REPLY_LEDS_CMD);
-+		IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
-+		IWL_CMD(RADAR_NOTIFICATION);
-+		IWL_CMD(REPLY_QUIET_CMD);
-+		IWL_CMD(REPLY_CHANNEL_SWITCH);
-+		IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
-+		IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
-+		IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
-+		IWL_CMD(POWER_TABLE_CMD);
-+		IWL_CMD(PM_SLEEP_NOTIFICATION);
-+		IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
-+		IWL_CMD(REPLY_SCAN_CMD);
-+		IWL_CMD(REPLY_SCAN_ABORT_CMD);
-+		IWL_CMD(SCAN_START_NOTIFICATION);
-+		IWL_CMD(SCAN_RESULTS_NOTIFICATION);
-+		IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
-+		IWL_CMD(BEACON_NOTIFICATION);
-+		IWL_CMD(REPLY_TX_BEACON);
-+		IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
-+		IWL_CMD(QUIET_NOTIFICATION);
-+		IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
-+		IWL_CMD(MEASURE_ABORT_NOTIFICATION);
-+		IWL_CMD(REPLY_BT_CONFIG);
-+		IWL_CMD(REPLY_STATISTICS_CMD);
-+		IWL_CMD(STATISTICS_NOTIFICATION);
-+		IWL_CMD(REPLY_CARD_STATE_CMD);
-+		IWL_CMD(CARD_STATE_NOTIFICATION);
-+		IWL_CMD(MISSED_BEACONS_NOTIFICATION);
-+#if IWL == 4965
-+		IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
-+		IWL_CMD(SENSITIVITY_CMD);
-+		IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
-+		IWL_CMD(REPLY_RX_PHY_CMD);
-+		IWL_CMD(REPLY_RX_MPDU_CMD);
-+		IWL_CMD(REPLY_4965_RX);
-+		IWL_CMD(REPLY_COMPRESSED_BA);
-+#endif
-+	default:
-+		return "UNKNOWN";
++/*
++ * REPLY_4965_RX = 0xc3 (response only, not a command)
++ * Used only for legacy (non 11n) frames.
++ */
++#define RX_RES_PHY_CNT 14
++struct iwl4965_rx_phy_res {
++	u8 non_cfg_phy_cnt;     /* non configurable DSP phy data byte count */
++	u8 cfg_phy_cnt;		/* configurable DSP phy data byte count */
++	u8 stat_id;		/* configurable DSP phy data set ID */
++	u8 reserved1;
++	__le64 timestamp;	/* TSF at on air rise */
++	__le32 beacon_time_stamp; /* beacon at on-air rise */
++	__le16 phy_flags;	/* general phy flags: band, modulation, ... */
++	__le16 channel;		/* channel number */
++	__le16 non_cfg_phy[RX_RES_PHY_CNT];	/* upto 14 phy entries */
++	__le32 reserved2;
++	__le32 rate_n_flags;
++	__le16 byte_count;		/* frame's byte-count */
++	__le16 reserved3;
++} __attribute__ ((packed));
 +
-+	}
-+}
++struct iwl4965_rx_mpdu_res_start {
++	__le16 byte_count;
++	__le16 reserved;
++} __attribute__ ((packed));
 +
-+#define HOST_COMPLETE_TIMEOUT (HZ / 2)
 +
-+/**
-+ * iwl_enqueue_hcmd - enqueue a uCode command
-+ * @priv: device private data point
-+ * @cmd: a point to the ucode command structure
++/******************************************************************************
++ * (5)
++ * Tx Commands & Responses:
 + *
-+ * The function returns < 0 values to indicate the operation is
-+ * failed. On success, it turns the index (> 0) of command in the
-+ * command queue.
-+ */
-+static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-+{
-+	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
-+	struct iwl_queue *q = &txq->q;
-+	struct iwl_tfd_frame *tfd;
-+	u32 *control_flags;
-+	struct iwl_cmd *out_cmd;
-+	u32 idx;
-+	u16 fix_size = (u16)(cmd->meta.len + sizeof(out_cmd->hdr));
-+	dma_addr_t phys_addr;
-+#if IWL == 3945
-+	int pad;
-+	u16 count;
-+#endif
-+	int rc = 0;
-+	unsigned long flags;
-+
-+	/* If any of the command structures end up being larger than
-+	 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
-+	 * we will need to increase the size of the TFD entries */
-+	BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
-+	       !(cmd->meta.flags & CMD_SIZE_HUGE));
++ *****************************************************************************/
 +
-+	if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
-+		IWL_ERROR("No space for Tx\n");
-+		return -ENOSPC;
-+	}
++/* Tx flags */
++#define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1)
++#define TX_CMD_FLG_CTS_MSK __constant_cpu_to_le32(1 << 2)
++#define TX_CMD_FLG_ACK_MSK __constant_cpu_to_le32(1 << 3)
++#define TX_CMD_FLG_STA_RATE_MSK __constant_cpu_to_le32(1 << 4)
++#define TX_CMD_FLG_IMM_BA_RSP_MASK  __constant_cpu_to_le32(1 << 6)
++#define TX_CMD_FLG_FULL_TXOP_PROT_MSK __constant_cpu_to_le32(1 << 7)
++#define TX_CMD_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0xf00)
++#define TX_CMD_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8)
++#define TX_CMD_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9)
 +
-+	spin_lock_irqsave(&priv->hcmd_lock, flags);
++/* ucode ignores BT priority for this frame */
++#define TX_CMD_FLG_BT_DIS_MSK __constant_cpu_to_le32(1 << 12)
 +
-+	tfd = &txq->bd[q->first_empty];
-+	memset(tfd, 0, sizeof(*tfd));
++/* ucode overrides sequence control */
++#define TX_CMD_FLG_SEQ_CTL_MSK __constant_cpu_to_le32(1 << 13)
 +
-+	control_flags = (u32 *) tfd;
++/* signal that this frame is non-last MPDU */
++#define TX_CMD_FLG_MORE_FRAG_MSK __constant_cpu_to_le32(1 << 14)
 +
-+	idx = get_cmd_index(q, q->first_empty, cmd->meta.flags & CMD_SIZE_HUGE);
-+	out_cmd = &txq->cmd[idx];
++/* calculate TSF in outgoing frame */
++#define TX_CMD_FLG_TSF_MSK __constant_cpu_to_le32(1 << 16)
 +
-+	out_cmd->hdr.cmd = cmd->id;
-+	memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta));
-+	memcpy(&out_cmd->cmd.payload, cmd->data, cmd->meta.len);
++/* activate TX calibration. */
++#define TX_CMD_FLG_CALIB_MSK __constant_cpu_to_le32(1 << 17)
 +
-+	/* At this point, the out_cmd now has all of the incoming cmd
-+	 * information */
++/* signals that 2 bytes pad was inserted
++   after the MAC header */
++#define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20)
 +
-+	out_cmd->hdr.flags = 0;
-+	out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
-+			INDEX_TO_SEQ(q->first_empty));
-+	if (out_cmd->meta.flags & CMD_SIZE_HUGE)
-+		out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
++/* HCCA-AP - disable duration overwriting. */
++#define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25)
 +
-+	phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
-+			offsetof(struct iwl_cmd, hdr);
-+	iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
++/*
++ * TX command security control
++ */
++#define TX_CMD_SEC_CCM  	0x2
++#define TX_CMD_SEC_TKIP		0x3
 +
-+#if IWL == 3945
-+	pad = U32_PAD(out_cmd->meta.len);
-+	count = TFD_CTL_COUNT_GET(*control_flags);
-+	*control_flags = TFD_CTL_COUNT_SET(count) | TFD_CTL_PAD_SET(pad);
-+#endif
++/*
++ * TX command Frame life time
++ */
 +
-+	IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
-+		     "%d bytes at %d[%d]:%d\n",
-+		     get_cmd_string(out_cmd->hdr.cmd),
-+		     out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
-+		     fix_size, q->first_empty, idx, IWL_CMD_QUEUE_NUM);
++struct iwl_dram_scratch {
++	u8 try_cnt;
++	u8 bt_kill_cnt;
++	__le16 reserved;
++} __attribute__ ((packed));
 +
-+	txq->need_update = 1;
++/*
++ * REPLY_TX = 0x1c (command)
++ */
++struct iwl_tx_cmd {
++	__le16 len;
++	__le16 next_frame_len;
++	__le32 tx_flags;
++#if IWL == 3945
++	u8 rate;
++	u8 sta_id;
++	u8 tid_tspec;
++#elif IWL == 4965
++	struct iwl_dram_scratch scratch;
++	__le32 rate_n_flags;
++	u8 sta_id;
++#endif
++	u8 sec_ctl;
 +#if IWL == 4965
-+	rc = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0);
-+	q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
-+	iwl_tx_queue_update_write_ptr(priv, txq);
-+#elif IWL == 3945
-+	q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
-+	rc = iwl_tx_queue_update_write_ptr(priv, txq);
++	u8 initial_rate_index;
++	u8 reserved;
++#endif
++	u8 key[16];
++#if IWL == 3945
++	union {
++		u8 byte[8];
++		__le16 word[4];
++		__le32 dw[2];
++	} tkip_mic;
++	__le32 next_frame_info;
++#elif IWL == 4965
++	__le16 next_frame_flags;
++	__le16 reserved2;
++#endif
++	union {
++		__le32 life_time;
++		__le32 attempt;
++	} stop_time;
++#if IWL == 3945
++	u8 supp_rates[2];
++#elif IWL == 4965
++	__le32 dram_lsb_ptr;
++	u8 dram_msb_ptr;
++#endif
++	u8 rts_retry_limit;	/*byte 50 */
++	u8 data_retry_limit;	/*byte 51 */
++#if IWL == 4965
++	u8 tid_tspec;
 +#endif
++	union {
++		__le16 pm_frame_timeout;
++		__le16 attempt_duration;
++	} timeout;
++	__le16 driver_txop;
++	u8 payload[0];
++	struct ieee80211_hdr hdr[0];
++} __attribute__ ((packed));
 +
-+	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-+	return rc ? rc : idx;
-+}
++/* TX command response is sent after *all* transmission attempts.
++ *
++ * NOTES:
++ *
++ * TX_STATUS_FAIL_NEXT_FRAG
++ *
++ * If the fragment flag in the MAC header for the frame being transmitted
++ * is set and there is insufficient time to transmit the next frame, the
++ * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'.
++ *
++ * TX_STATUS_FIFO_UNDERRUN
++ *
++ * Indicates the host did not provide bytes to the FIFO fast enough while
++ * a TX was in progress.
++ *
++ * TX_STATUS_FAIL_MGMNT_ABORT
++ *
++ * This status is only possible if the ABORT ON MGMT RX parameter was
++ * set to true with the TX command.
++ *
++ * If the MSB of the status parameter is set then an abort sequence is
++ * required.  This sequence consists of the host activating the TX Abort
++ * control line, and then waiting for the TX Abort command response.  This
++ * indicates that a the device is no longer in a transmit state, and that the
++ * command FIFO has been cleared.  The host must then deactivate the TX Abort
++ * control line.  Receiving is still allowed in this case.
++ */
++enum {
++	TX_STATUS_SUCCESS = 0x01,
++	TX_STATUS_DIRECT_DONE = 0x02,
++	TX_STATUS_FAIL_SHORT_LIMIT = 0x82,
++	TX_STATUS_FAIL_LONG_LIMIT = 0x83,
++	TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84,
++	TX_STATUS_FAIL_MGMNT_ABORT = 0x85,
++	TX_STATUS_FAIL_NEXT_FRAG = 0x86,
++	TX_STATUS_FAIL_LIFE_EXPIRE = 0x87,
++	TX_STATUS_FAIL_DEST_PS = 0x88,
++	TX_STATUS_FAIL_ABORTED = 0x89,
++	TX_STATUS_FAIL_BT_RETRY = 0x8a,
++	TX_STATUS_FAIL_STA_INVALID = 0x8b,
++	TX_STATUS_FAIL_FRAG_DROPPED = 0x8c,
++	TX_STATUS_FAIL_TID_DISABLE = 0x8d,
++	TX_STATUS_FAIL_FRAME_FLUSHED = 0x8e,
++	TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f,
++	TX_STATUS_FAIL_TX_LOCKED = 0x90,
++	TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91,
++};
 +
-+static int __iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-+{
-+	int rc;
++#define	TX_PACKET_MODE_REGULAR		0x0000
++#define	TX_PACKET_MODE_BURST_SEQ	0x0100
++#define	TX_PACKET_MODE_BURST_FIRST	0x0200
 +
-+	cmd->meta.len = cmd->len;
++enum {
++	TX_POWER_PA_NOT_ACTIVE = 0x0,
++};
 +
-+	rc = iwl_enqueue_hcmd(priv, cmd);
-+	if (rc < 0) {
-+		IWL_ERROR("Error sending %s: iwl_enqueue_hcmd failed: %d\n",
-+			  get_cmd_string(cmd->id), rc);
-+		return -ENOSPC;
-+	}
-+	return rc;
-+}
++enum {
++	TX_STATUS_MSK = 0x000000ff,	/* bits 0:7 */
++	TX_STATUS_DELAY_MSK = 0x00000040,
++	TX_STATUS_ABORT_MSK = 0x00000080,
++	TX_PACKET_MODE_MSK = 0x0000ff00,	/* bits 8:15 */
++	TX_FIFO_NUMBER_MSK = 0x00070000,	/* bits 16:18 */
++	TX_RESERVED = 0x00780000,	/* bits 19:22 */
++	TX_POWER_PA_DETECT_MSK = 0x7f800000,	/* bits 23:30 */
++	TX_ABORT_REQUIRED_MSK = 0x80000000,	/* bits 31:31 */
++};
 +
-+int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-+{
-+	int ret;
++/* *******************************
++ * TX aggregation state
++ ******************************* */
 +
-+	BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
++enum {
++	AGG_TX_STATE_TRANSMITTED = 0x00,
++	AGG_TX_STATE_UNDERRUN_MSK = 0x01,
++	AGG_TX_STATE_BT_PRIO_MSK = 0x02,
++	AGG_TX_STATE_FEW_BYTES_MSK = 0x04,
++	AGG_TX_STATE_ABORT_MSK = 0x08,
++	AGG_TX_STATE_LAST_SENT_TTL_MSK = 0x10,
++	AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK = 0x20,
++	AGG_TX_STATE_LAST_SENT_BT_KILL_MSK = 0x40,
++	AGG_TX_STATE_SCD_QUERY_MSK = 0x80,
++	AGG_TX_STATE_TEST_BAD_CRC32_MSK = 0x100,
++	AGG_TX_STATE_RESPONSE_MSK = 0x1ff,
++	AGG_TX_STATE_DUMP_TX_MSK = 0x200,
++	AGG_TX_STATE_DELAY_TX_MSK = 0x400
++};
 +
-+	/* An asynchronous command can not expect an SKB to be set. */
-+	BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
++#define AGG_TX_STATE_LAST_SENT_MSK \
++(AGG_TX_STATE_LAST_SENT_TTL_MSK | \
++ AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \
++ AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
 +
-+	/* An asynchronous command MUST have a callback. */
-+	BUG_ON(!cmd->meta.u.callback);
++#define AGG_TX_STATE_TRY_CNT_POS 12
++#define AGG_TX_STATE_TRY_CNT_MSK 0xf000
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+		return -EBUSY;
++#define AGG_TX_STATE_SEQ_NUM_POS 16
++#define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000
 +
-+	ret = __iwl_send_cmd(priv, cmd);
-+	if (ret < 0)
-+		return ret;
++/*
++ * REPLY_TX = 0x1c (response)
++ */
++#if IWL == 4965
++struct iwl_tx_resp {
++	u8 frame_count;		/* 1 no aggregation, >1 aggregation */
++	u8 bt_kill_count;
++	u8 failure_rts;
++	u8 failure_frame;
++	__le32 rate_n_flags;
++	__le16 wireless_media_time;
++	__le16 reserved;
++	__le32 pa_power1;
++	__le32 pa_power2;
++	__le32 status;	/* TX status (for aggregation status of 1st frame) */
++} __attribute__ ((packed));
 +
-+	return 0;
-+}
-+
-+int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-+{
-+	int cmd_idx;
-+	int ret;
-+	static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
++#elif IWL == 3945
++struct iwl_tx_resp {
++	u8 failure_rts;
++	u8 failure_frame;
++	u8 bt_kill_count;
++	u8 rate;
++	__le32 wireless_media_time;
++	__le32 status;	/* TX status (for aggregation status of 1st frame) */
++} __attribute__ ((packed));
++#endif
 +
-+	BUG_ON(cmd->meta.flags & CMD_ASYNC);
++/*
++ * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
++ */
++struct iwl_compressed_ba_resp {
++	__le32 sta_addr_lo32;
++	__le16 sta_addr_hi16;
++	__le16 reserved;
++	u8 sta_id;
++	u8 tid;
++	__le16 ba_seq_ctl;
++	__le32 ba_bitmap0;
++	__le32 ba_bitmap1;
++	__le16 scd_flow;
++	__le16 scd_ssn;
++} __attribute__ ((packed));
 +
-+	 /* A synchronous command can not have a callback set. */
-+	BUG_ON(cmd->meta.u.callback != NULL);
++/*
++ * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response)
++ */
++struct iwl_txpowertable_cmd {
++	u8 band;		/* 0: 5 GHz, 1: 2.4 GHz */
++	u8 reserved;
++	__le16 channel;
++#if IWL == 3945
++	struct iwl_power_per_rate power[IWL_MAX_RATES];
++#elif IWL == 4965
++	struct iwl_tx_power_db tx_power;
++#endif
++} __attribute__ ((packed));
 +
-+	if (atomic_xchg(&entry, 1)) {
-+		IWL_ERROR("Error sending %s: Already sending a host command\n",
-+			  get_cmd_string(cmd->id));
-+		return -EBUSY;
-+	}
++#if IWL == 3945
++struct iwl_rate_scaling_info {
++	__le16 rate_n_flags;
++	u8 try_cnt;
++	u8 next_rate_index;
++} __attribute__ ((packed));
 +
-+	set_bit(STATUS_HCMD_ACTIVE, &priv->status);
++/**
++ * struct iwl_rate_scaling_cmd - Rate Scaling Command & Response
++ *
++ * REPLY_RATE_SCALE = 0x47 (command, has simple generic response)
++ *
++ * NOTE: The table of rates passed to the uCode via the
++ * RATE_SCALE command sets up the corresponding order of
++ * rates used for all related commands, including rate
++ * masks, etc.
++ *
++ * For example, if you set 9MB (PLCP 0x0f) as the first
++ * rate in the rate table, the bit mask for that rate
++ * when passed through ofdm_basic_rates on the REPLY_RXON
++ * command would be bit 0 (1<<0)
++ */
++struct iwl_rate_scaling_cmd {
++	u8 table_id;
++	u8 reserved[3];
++	struct iwl_rate_scaling_info table[IWL_MAX_RATES];
++} __attribute__ ((packed));
 +
-+	if (cmd->meta.flags & CMD_WANT_SKB)
-+		cmd->meta.source = &cmd->meta;
++#elif IWL == 4965
 +
-+	ret = __iwl_send_cmd(priv, cmd);
-+	if (ret < 0)
-+		goto out;
++/*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */
++#define  LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK	(1<<0)
 +
-+	cmd_idx = ret;
++#define  LINK_QUAL_AC_NUM AC_NUM
++#define  LINK_QUAL_MAX_RETRY_NUM 16
 +
-+	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-+			!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
-+			HOST_COMPLETE_TIMEOUT);
-+	if (!ret) {
-+		if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
-+			IWL_ERROR("Error sending %s: time out after %dms.\n",
-+				  get_cmd_string(cmd->id),
-+				  jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
++#define  LINK_QUAL_ANT_A_MSK (1<<0)
++#define  LINK_QUAL_ANT_B_MSK (1<<1)
++#define  LINK_QUAL_ANT_MSK   (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK)
 +
-+			clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-+			ret = -ETIMEDOUT;
-+			goto cancel;
-+		}
-+	}
++struct iwl_link_qual_general_params {
++	u8 flags;
++	u8 mimo_delimiter;
++	u8 single_stream_ant_msk;
++	u8 dual_stream_ant_msk;
++	u8 start_rate_index[LINK_QUAL_AC_NUM];
++} __attribute__ ((packed));
 +
-+	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-+		IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
-+			       get_cmd_string(cmd->id));
-+		ret = -ECANCELED;
-+		goto fail;
-+	}
-+	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
-+		IWL_DEBUG_INFO("Command %s failed: FW Error\n",
-+			       get_cmd_string(cmd->id));
-+		ret = -EIO;
-+		goto fail;
-+	}
-+	if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
-+		IWL_ERROR("Error: Response NULL in '%s'\n",
-+			  get_cmd_string(cmd->id));
-+		ret = -EIO;
-+		goto out;
-+	}
++struct iwl_link_qual_agg_params {
++	__le16 agg_time_limit;
++	u8 agg_dis_start_th;
++	u8 agg_frame_cnt_limit;
++	__le32 reserved;
++} __attribute__ ((packed));
 +
-+	ret = 0;
-+	goto out;
++/*
++ * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
++ */
++struct iwl_link_quality_cmd {
++	u8 sta_id;
++	u8 reserved1;
++	__le16 control;
++	struct iwl_link_qual_general_params general_params;
++	struct iwl_link_qual_agg_params agg_params;
++	struct {
++		__le32 rate_n_flags;
++	} rs_table[LINK_QUAL_MAX_RETRY_NUM];
++	__le32 reserved2;
++} __attribute__ ((packed));
++#endif
 +
-+cancel:
-+	if (cmd->meta.flags & CMD_WANT_SKB) {
-+		struct iwl_cmd *qcmd;
++/*
++ * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
++ */
++struct iwl_bt_cmd {
++	u8 flags;
++	u8 lead_time;
++	u8 max_kill;
++	u8 reserved;
++	__le32 kill_ack_mask;
++	__le32 kill_cts_mask;
++} __attribute__ ((packed));
 +
-+		/* Cancel the CMD_WANT_SKB flag for the cmd in the
-+		 * TX cmd queue. Otherwise in case the cmd comes
-+		 * in later, it will possibly set an invalid
-+		 * address (cmd->meta.source). */
-+		qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
-+		qcmd->meta.flags &= ~CMD_WANT_SKB;
-+	}
-+fail:
-+	if (cmd->meta.u.skb) {
-+		dev_kfree_skb_any(cmd->meta.u.skb);
-+		cmd->meta.u.skb = NULL;
-+	}
-+out:
-+	atomic_set(&entry, 0);
-+	return ret;
-+}
++/******************************************************************************
++ * (6)
++ * Spectrum Management (802.11h) Commands, Responses, Notifications:
++ *
++ *****************************************************************************/
 +
-+int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-+{
-+	/* A command can not be asynchronous AND expect an SKB to be set. */
-+	BUG_ON((cmd->meta.flags & CMD_ASYNC) &&
-+	       (cmd->meta.flags & CMD_WANT_SKB));
++/*
++ * Spectrum Management
++ */
++#define MEASUREMENT_FILTER_FLAG (RXON_FILTER_PROMISC_MSK         | \
++				 RXON_FILTER_CTL2HOST_MSK        | \
++				 RXON_FILTER_ACCEPT_GRP_MSK      | \
++				 RXON_FILTER_DIS_DECRYPT_MSK     | \
++				 RXON_FILTER_DIS_GRP_DECRYPT_MSK | \
++				 RXON_FILTER_ASSOC_MSK           | \
++				 RXON_FILTER_BCON_AWARE_MSK)
 +
-+	if (cmd->meta.flags & CMD_ASYNC)
-+		return iwl_send_cmd_async(priv, cmd);
++struct iwl_measure_channel {
++	__le32 duration;	/* measurement duration in extended beacon
++				 * format */
++	u8 channel;		/* channel to measure */
++	u8 type;		/* see enum iwl_measure_type */
++	__le16 reserved;
++} __attribute__ ((packed));
 +
-+	return iwl_send_cmd_sync(priv, cmd);
-+}
++/*
++ * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command)
++ */
++struct iwl_spectrum_cmd {
++	__le16 len;		/* number of bytes starting from token */
++	u8 token;		/* token id */
++	u8 id;			/* measurement id -- 0 or 1 */
++	u8 origin;		/* 0 = TGh, 1 = other, 2 = TGk */
++	u8 periodic;		/* 1 = periodic */
++	__le16 path_loss_timeout;
++	__le32 start_time;	/* start time in extended beacon format */
++	__le32 reserved2;
++	__le32 flags;		/* rxon flags */
++	__le32 filter_flags;	/* rxon filter flags */
++	__le16 channel_count;	/* minimum 1, maximum 10 */
++	__le16 reserved3;
++	struct iwl_measure_channel channels[10];
++} __attribute__ ((packed));
 +
-+int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
-+{
-+	struct iwl_host_cmd cmd = {
-+		.id = id,
-+		.len = len,
-+		.data = data,
-+	};
++/*
++ * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response)
++ */
++struct iwl_spectrum_resp {
++	u8 token;
++	u8 id;			/* id of the prior command replaced, or 0xff */
++	__le16 status;		/* 0 - command will be handled
++				 * 1 - cannot handle (conflicts with another
++				 *     measurement) */
++} __attribute__ ((packed));
 +
-+	return iwl_send_cmd_sync(priv, &cmd);
-+}
++enum iwl_measurement_state {
++	IWL_MEASUREMENT_START = 0,
++	IWL_MEASUREMENT_STOP = 1,
++};
 +
-+static int __must_check iwl_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val)
-+{
-+	struct iwl_host_cmd cmd = {
-+		.id = id,
-+		.len = sizeof(val),
-+		.data = &val,
-+	};
-+
-+	return iwl_send_cmd_sync(priv, &cmd);
-+}
++enum iwl_measurement_status {
++	IWL_MEASUREMENT_OK = 0,
++	IWL_MEASUREMENT_CONCURRENT = 1,
++	IWL_MEASUREMENT_CSA_CONFLICT = 2,
++	IWL_MEASUREMENT_TGH_CONFLICT = 3,
++	/* 4-5 reserved */
++	IWL_MEASUREMENT_STOPPED = 6,
++	IWL_MEASUREMENT_TIMEOUT = 7,
++	IWL_MEASUREMENT_PERIODIC_FAILED = 8,
++};
 +
-+int iwl_send_statistics_request(struct iwl_priv *priv)
-+{
-+	return iwl_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
-+}
++#define NUM_ELEMENTS_IN_HISTOGRAM 8
 +
-+/**
-+ * iwl_rxon_add_station - add station into station table.
-+ *
-+ * there is only one AP station with id= IWL_AP_ID
-+ * NOTE: mutex must be held before calling the this fnction
-+*/
-+static int iwl_rxon_add_station(struct iwl_priv *priv,
-+				const u8 *addr, int is_ap)
-+{
-+	u8 rc;
++struct iwl_measurement_histogram {
++	__le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM];	/* in 0.8usec counts */
++	__le32 cck[NUM_ELEMENTS_IN_HISTOGRAM];	/* in 1usec counts */
++} __attribute__ ((packed));
 +
-+	/* Remove this station if it happens to already exist */
-+	iwl_remove_station(priv, addr, is_ap);
++/* clear channel availability counters */
++struct iwl_measurement_cca_counters {
++	__le32 ofdm;
++	__le32 cck;
++} __attribute__ ((packed));
 +
-+	rc = iwl_add_station(priv, addr, is_ap, 0);
++enum iwl_measure_type {
++	IWL_MEASURE_BASIC = (1 << 0),
++	IWL_MEASURE_CHANNEL_LOAD = (1 << 1),
++	IWL_MEASURE_HISTOGRAM_RPI = (1 << 2),
++	IWL_MEASURE_HISTOGRAM_NOISE = (1 << 3),
++	IWL_MEASURE_FRAME = (1 << 4),
++	/* bits 5:6 are reserved */
++	IWL_MEASURE_IDLE = (1 << 7),
++};
 +
-+	iwl4965_add_station(priv, addr, is_ap);
++/*
++ * SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command)
++ */
++struct iwl_spectrum_notification {
++	u8 id;			/* measurement id -- 0 or 1 */
++	u8 token;
++	u8 channel_index;	/* index in measurement channel list */
++	u8 state;		/* 0 - start, 1 - stop */
++	__le32 start_time;	/* lower 32-bits of TSF */
++	u8 band;		/* 0 - 5.2GHz, 1 - 2.4GHz */
++	u8 channel;
++	u8 type;		/* see enum iwl_measurement_type */
++	u8 reserved1;
++	/* NOTE:  cca_ofdm, cca_cck, basic_type, and histogram are only only
++	 * valid if applicable for measurement type requested. */
++	__le32 cca_ofdm;	/* cca fraction time in 40Mhz clock periods */
++	__le32 cca_cck;		/* cca fraction time in 44Mhz clock periods */
++	__le32 cca_time;	/* channel load time in usecs */
++	u8 basic_type;		/* 0 - bss, 1 - ofdm preamble, 2 -
++				 * unidentified */
++	u8 reserved2[3];
++	struct iwl_measurement_histogram histogram;
++	__le32 stop_time;	/* lower 32-bits of TSF */
++	__le32 status;		/* see iwl_measurement_status */
++} __attribute__ ((packed));
 +
-+	return rc;
-+}
++/******************************************************************************
++ * (7)
++ * Power Management Commands, Responses, Notifications:
++ *
++ *****************************************************************************/
 +
 +/**
-+ * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
-+ * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
-+ * @channel: Any channel valid for the requested phymode
-+
-+ * In addition to setting the staging RXON, priv->phymode is also set.
++ * struct iwl_powertable_cmd - Power Table Command
++ * @flags: See below:
 + *
-+ * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
-+ * in the staging RXON flag structure based on the phymode
++ * POWER_TABLE_CMD = 0x77 (command, has simple generic response)
++ *
++ * PM allow:
++ *   bit 0 - '0' Driver not allow power management
++ *           '1' Driver allow PM (use rest of parameters)
++ * uCode send sleep notifications:
++ *   bit 1 - '0' Don't send sleep notification
++ *           '1' send sleep notification (SEND_PM_NOTIFICATION)
++ * Sleep over DTIM
++ *   bit 2 - '0' PM have to walk up every DTIM
++ *           '1' PM could sleep over DTIM till listen Interval.
++ * PCI power managed
++ *   bit 3 - '0' (PCI_LINK_CTRL & 0x1)
++ *           '1' !(PCI_LINK_CTRL & 0x1)
++ * Force sleep Modes
++ *   bit 31/30- '00' use both mac/xtal sleeps
++ *              '01' force Mac sleep
++ *              '10' force xtal sleep
++ *              '11' Illegal set
++ *
++ * NOTE: if sleep_interval[SLEEP_INTRVL_TABLE_SIZE-1] > DTIM period then
++ * ucode assume sleep over DTIM is allowed and we don't need to wakeup
++ * for every DTIM.
 + */
-+static int iwl_set_rxon_channel(struct iwl_priv *priv, u8 phymode, u16 channel)
-+{
-+	if (!iwl_get_channel_info(priv, phymode, channel)) {
-+		IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
-+			       channel, phymode);
-+		return -EINVAL;
-+	}
++#define IWL_POWER_VEC_SIZE 5
 +
-+	if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
-+	    (priv->phymode == phymode))
-+		return 0;
 +
-+	priv->staging_rxon.channel = cpu_to_le16(channel);
-+	if (phymode == MODE_IEEE80211A)
-+		priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
-+	else
-+		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
++#if IWL == 3945
 +
-+	priv->phymode = phymode;
++#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK	__constant_cpu_to_le32(1<<0)
++#define IWL_POWER_SLEEP_OVER_DTIM_MSK		__constant_cpu_to_le32(1<<2)
++#define IWL_POWER_PCI_PM_MSK			__constant_cpu_to_le32(1<<3)
++struct iwl_powertable_cmd {
++	__le32 flags;
++	__le32 rx_data_timeout;
++	__le32 tx_data_timeout;
++	__le32 sleep_interval[IWL_POWER_VEC_SIZE];
++} __attribute__((packed));
 +
-+	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
++#elif IWL == 4965
 +
-+	return 0;
-+}
++#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK	__constant_cpu_to_le16(1<<0)
++#define IWL_POWER_SLEEP_OVER_DTIM_MSK		__constant_cpu_to_le16(1<<2)
++#define IWL_POWER_PCI_PM_MSK			__constant_cpu_to_le16(1<<3)
 +
-+/**
-+ * iwl_check_rxon_cmd - validate RXON structure is valid
-+ *
-+ * NOTE:  This is really only useful during development and can eventually
-+ * be #ifdef'd out once the driver is stable and folks aren't actively
-+ * making changes
-+ */
-+static int iwl_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
-+{
-+	int error = 0;
-+	int counter = 1;
++struct iwl_powertable_cmd {
++	__le16 flags;
++	u8 keep_alive_seconds;
++	u8 debug_flags;
++	__le32 rx_data_timeout;
++	__le32 tx_data_timeout;
++	__le32 sleep_interval[IWL_POWER_VEC_SIZE];
++	__le32 keep_alive_beacons;
++} __attribute__ ((packed));
++#endif
 +
-+	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
-+		error |= le32_to_cpu(rxon->flags &
-+				(RXON_FLG_TGJ_NARROW_BAND_MSK |
-+				 RXON_FLG_RADAR_DETECT_MSK));
-+		if (error)
-+			IWL_WARNING("check 24G fields %d | %d\n",
-+				    counter++, error);
-+	} else {
-+		error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
-+				0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
-+		if (error)
-+			IWL_WARNING("check 52 fields %d | %d\n",
-+				    counter++, error);
-+		error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
-+		if (error)
-+			IWL_WARNING("check 52 CCK %d | %d\n",
-+				    counter++, error);
-+	}
-+	error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
-+	if (error)
-+		IWL_WARNING("check mac addr %d | %d\n", counter++, error);
++/*
++ * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
++ * 3945 and 4965 identical.
++ */
++struct iwl_sleep_notification {
++	u8 pm_sleep_mode;
++	u8 pm_wakeup_src;
++	__le16 reserved;
++	__le32 sleep_time;
++	__le32 tsf_low;
++	__le32 bcon_timer;
++} __attribute__ ((packed));
 +
-+	/* make sure basic rates 6Mbps and 1Mbps are supported */
-+	error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
-+		  ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
-+	if (error)
-+		IWL_WARNING("check basic rate %d | %d\n", counter++, error);
++/* Sleep states.  3945 and 4965 identical. */
++enum {
++	IWL_PM_NO_SLEEP = 0,
++	IWL_PM_SLP_MAC = 1,
++	IWL_PM_SLP_FULL_MAC_UNASSOCIATE = 2,
++	IWL_PM_SLP_FULL_MAC_CARD_STATE = 3,
++	IWL_PM_SLP_PHY = 4,
++	IWL_PM_SLP_REPENT = 5,
++	IWL_PM_WAKEUP_BY_TIMER = 6,
++	IWL_PM_WAKEUP_BY_DRIVER = 7,
++	IWL_PM_WAKEUP_BY_RFKILL = 8,
++	/* 3 reserved */
++	IWL_PM_NUM_OF_MODES = 12,
++};
 +
-+	error |= (le16_to_cpu(rxon->assoc_id) > 2007);
-+	if (error)
-+		IWL_WARNING("check assoc id %d | %d\n", counter++, error);
++/*
++ * REPLY_CARD_STATE_CMD = 0xa0 (command, has simple generic response)
++ */
++#define CARD_STATE_CMD_DISABLE 0x00	/* Put card to sleep */
++#define CARD_STATE_CMD_ENABLE  0x01	/* Wake up card */
++#define CARD_STATE_CMD_HALT    0x02	/* Power down permanently */
++struct iwl_card_state_cmd {
++	__le32 status;		/* CARD_STATE_CMD_* request new power state */
++} __attribute__ ((packed));
 +
-+	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
-+			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
-+	if (error)
-+		IWL_WARNING("check CCK and short slot %d | %d\n",
-+			    counter++, error);
++/*
++ * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command)
++ */
++struct iwl_card_state_notif {
++	__le32 flags;
++} __attribute__ ((packed));
 +
-+	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
-+			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
-+	if (error)
-+		IWL_WARNING("check CCK & auto detect %d | %d\n",
-+			    counter++, error);
++#define HW_CARD_DISABLED   0x01
++#define SW_CARD_DISABLED   0x02
++#define RF_CARD_DISABLED   0x04
++#define RXON_CARD_DISABLED 0x10
 +
-+	error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
-+			RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
-+	if (error)
-+		IWL_WARNING("check TGG and auto detect %d | %d\n",
-+			    counter++, error);
-+
-+#if IWL == 3945
-+	if ((rxon->flags & RXON_FLG_DIS_DIV_MSK))
-+		error |= ((rxon->flags & (RXON_FLG_ANT_B_MSK |
-+				RXON_FLG_ANT_A_MSK)) == 0);
-+	if (error)
-+		IWL_WARNING("check antenna %d %d\n", counter++, error);
-+#endif
-+	if (error)
-+		IWL_WARNING("Tuning to channel %d\n",
-+			    le16_to_cpu(rxon->channel));
-+
-+	if (error) {
-+		IWL_ERROR("Not a valid iwl_rxon_assoc_cmd field values\n");
-+		return -1;
-+	}
-+	return 0;
-+}
++struct iwl_ct_kill_config {
++	__le32   reserved;
++	__le32   critical_temperature_M;
++	__le32   critical_temperature_R;
++}  __attribute__ ((packed));
 +
-+/**
-+ * iwl_full_rxon_required - determine if RXON_ASSOC can be used in RXON commit
-+ * @priv: staging_rxon is comapred to active_rxon
++/******************************************************************************
++ * (8)
++ * Scan Commands, Responses, Notifications:
 + *
-+ * If the RXON structure is changing sufficient to require a new
-+ * tune or to clear and reset the RXON_FILTER_ASSOC_MSK then return 1
-+ * to indicate a new tune is required.
-+ */
-+static int iwl_full_rxon_required(struct iwl_priv *priv)
-+{
-+
-+	/* These items are only settable from the full RXON command */
-+	if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ||
-+	    compare_ether_addr(priv->staging_rxon.bssid_addr,
-+			       priv->active_rxon.bssid_addr) ||
-+	    compare_ether_addr(priv->staging_rxon.node_addr,
-+			       priv->active_rxon.node_addr) ||
-+	    compare_ether_addr(priv->staging_rxon.wlap_bssid_addr,
-+			       priv->active_rxon.wlap_bssid_addr) ||
-+	    (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) ||
-+	    (priv->staging_rxon.channel != priv->active_rxon.channel) ||
-+	    (priv->staging_rxon.air_propagation !=
-+	     priv->active_rxon.air_propagation) ||
-+#if IWL == 4965
-+	    (priv->staging_rxon.ofdm_ht_single_stream_basic_rates !=
-+	     priv->active_rxon.ofdm_ht_single_stream_basic_rates) ||
-+	    (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates !=
-+	     priv->active_rxon.ofdm_ht_dual_stream_basic_rates) ||
-+	    (priv->staging_rxon.rx_chain != priv->active_rxon.rx_chain) ||
-+#endif
-+	    (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
-+		return 1;
++ *****************************************************************************/
 +
-+	/* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can
-+	 * be updated with the RXON_ASSOC command -- however only some
-+	 * flag transitions are allowed using RXON_ASSOC */
++struct iwl_scan_channel {
++	/* type is defined as:
++	 * 0:0 active (0 - passive)
++	 * 1:4 SSID direct
++	 *     If 1 is set then corresponding SSID IE is transmitted in probe
++	 * 5:7 reserved
++	 */
++	u8 type;
++	u8 channel;
++	struct iwl_tx_power tpc;
++	__le16 active_dwell;
++	__le16 passive_dwell;
++} __attribute__ ((packed));
 +
-+	/* Check if we are not switching bands */
-+	if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) !=
-+	    (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK))
-+		return 1;
++struct iwl_ssid_ie {
++	u8 id;
++	u8 len;
++	u8 ssid[32];
++} __attribute__ ((packed));
 +
-+	/* Check if we are switching association toggle */
-+	if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) !=
-+		(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK))
-+		return 1;
++#define PROBE_OPTION_MAX        0x4
++#define TX_CMD_LIFE_TIME_INFINITE	__constant_cpu_to_le32(0xFFFFFFFF)
++#define IWL_GOOD_CRC_TH		__constant_cpu_to_le16(1)
++#define IWL_MAX_SCAN_SIZE 1024
 +
-+	return 0;
-+}
++/*
++ * REPLY_SCAN_CMD = 0x80 (command)
++ */
++struct iwl_scan_cmd {
++	__le16 len;
++	u8 reserved0;
++	u8 channel_count;
++	__le16 quiet_time;     /* dwell only this long on quiet chnl
++				* (active scan) */
++	__le16 quiet_plcp_th;  /* quiet chnl is < this # pkts (typ. 1) */
++	__le16 good_CRC_th;    /* passive -> active promotion threshold */
++#if IWL == 3945
++	__le16 reserved1;
++#elif IWL == 4965
++	__le16 rx_chain;
++#endif
++	__le32 max_out_time;   /* max usec to be out of associated (service)
++				* chnl */
++	__le32 suspend_time;   /* pause scan this long when returning to svc
++				* chnl.
++				* 3945 -- 31:24 # beacons, 19:0 additional usec,
++				* 4965 -- 31:22 # beacons, 21:0 additional usec.
++				*/
++	__le32 flags;
++	__le32 filter_flags;
 +
-+static int iwl_send_rxon_assoc(struct iwl_priv *priv)
-+{
-+	int rc = 0;
-+	struct iwl_rx_packet *res = NULL;
-+	struct iwl_rxon_assoc_cmd rxon_assoc;
-+	struct iwl_host_cmd cmd = {
-+		.id = REPLY_RXON_ASSOC,
-+		.len = sizeof(rxon_assoc),
-+		.meta.flags = CMD_WANT_SKB,
-+		.data = &rxon_assoc,
-+	};
-+	const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
-+	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
++	struct iwl_tx_cmd tx_cmd;
++	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
 +
-+	if ((rxon1->flags == rxon2->flags) &&
-+	    (rxon1->filter_flags == rxon2->filter_flags) &&
-+	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
-+#if IWL == 4965
-+	    (rxon1->ofdm_ht_single_stream_basic_rates ==
-+	     rxon2->ofdm_ht_single_stream_basic_rates) &&
-+	    (rxon1->ofdm_ht_dual_stream_basic_rates ==
-+	     rxon2->ofdm_ht_dual_stream_basic_rates) &&
-+	    (rxon1->rx_chain == rxon2->rx_chain) &&
-+#endif
-+	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
-+		IWL_DEBUG_INFO("Using current RXON_ASSOC.  Not resending.\n");
-+		return 0;
-+	}
++	u8 data[0];
++	/*
++	 * The channels start after the probe request payload and are of type:
++	 *
++	 * struct iwl_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));
 +
-+	rxon_assoc.flags = priv->staging_rxon.flags;
-+	rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-+	rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-+	rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
-+	rxon_assoc.reserved = 0;
-+#if IWL == 4965
-+	rxon_assoc.ofdm_ht_single_stream_basic_rates =
-+	    priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
-+	rxon_assoc.ofdm_ht_dual_stream_basic_rates =
-+	    priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
-+	rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
-+#endif
++/* Can abort will notify by complete notification with abort status. */
++#define CAN_ABORT_STATUS	__constant_cpu_to_le32(0x1)
++/* complete notification statuses */
++#define ABORT_STATUS            0x2
 +
-+	rc = iwl_send_cmd_sync(priv, &cmd);
-+	if (rc)
-+		return rc;
++/*
++ * REPLY_SCAN_CMD = 0x80 (response)
++ */
++struct iwl_scanreq_notification {
++	__le32 status;		/* 1: okay, 2: cannot fulfill request */
++} __attribute__ ((packed));
 +
-+	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
-+	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-+		IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n");
-+		rc = -EIO;
-+	}
++/*
++ * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command)
++ */
++struct iwl_scanstart_notification {
++	__le32 tsf_low;
++	__le32 tsf_high;
++	__le32 beacon_timer;
++	u8 channel;
++	u8 band;
++	u8 reserved[2];
++	__le32 status;
++} __attribute__ ((packed));
 +
-+	priv->alloc_rxb_skb--;
-+	dev_kfree_skb_any(cmd.meta.u.skb);
++#define  SCAN_OWNER_STATUS 0x1;
++#define  MEASURE_OWNER_STATUS 0x2;
 +
-+	return rc;
-+}
++#define NUMBER_OF_STATISTICS 1	/* first __le32 is good CRC */
++/*
++ * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command)
++ */
++struct iwl_scanresults_notification {
++	u8 channel;
++	u8 band;
++	u8 reserved[2];
++	__le32 tsf_low;
++	__le32 tsf_high;
++	__le32 statistics[NUMBER_OF_STATISTICS];
++} __attribute__ ((packed));
 +
-+/**
-+ * iwl_commit_rxon - commit staging_rxon to hardware
-+ *
-+ * The RXON command in staging_rxon is commited to the hardware and
-+ * the active_rxon structure is updated with the new data.  This
-+ * function correctly transitions out of the RXON_ASSOC_MSK state if
-+ * a HW tune is required based on the RXON structure changes.
++/*
++ * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command)
 + */
-+static int iwl_commit_rxon(struct iwl_priv *priv)
-+{
-+	/* cast away the const for active_rxon in this function */
-+	struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
-+	int rc = 0;
++struct iwl_scancomplete_notification {
++	u8 scanned_channels;
++	u8 status;
++	u8 reserved;
++	u8 last_channel;
++	__le32 tsf_low;
++	__le32 tsf_high;
++} __attribute__ ((packed));
 +
-+	if (!iwl_is_alive(priv))
-+		return -1;
 +
-+	/* always get timestamp with Rx frame */
-+	priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
++/******************************************************************************
++ * (9)
++ * IBSS/AP Commands and Notifications:
++ *
++ *****************************************************************************/
 +
-+#if IWL == 3945
-+	/* select antenna */
-+	priv->staging_rxon.flags &=
-+	    ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
-+	priv->staging_rxon.flags |= iwl3945_get_antenna_flags(priv);
-+#endif
-+
-+	rc = iwl_check_rxon_cmd(&priv->staging_rxon);
-+	if (rc) {
-+		IWL_ERROR("Invalid RXON configuration.  Not committing.\n");
-+		return -EINVAL;
-+	}
++/*
++ * BEACON_NOTIFICATION = 0x90 (notification only, not a command)
++ */
++struct iwl_beacon_notif {
++	struct iwl_tx_resp beacon_notify_hdr;
++	__le32 low_tsf;
++	__le32 high_tsf;
++	__le32 ibss_mgr_status;
++} __attribute__ ((packed));
 +
-+	/* If we don't need to send a full RXON, we can use
-+	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
-+	 * and other flags for the current radio configuration. */
-+	if (!iwl_full_rxon_required(priv)) {
-+		rc = iwl_send_rxon_assoc(priv);
-+		if (rc) {
-+			IWL_ERROR("Error setting RXON_ASSOC "
-+				  "configuration (%d).\n", rc);
-+			return rc;
-+		}
++/*
++ * REPLY_TX_BEACON = 0x91 (command, has simple generic response)
++ */
++struct iwl_tx_beacon_cmd {
++	struct iwl_tx_cmd tx;
++	__le16 tim_idx;
++	u8 tim_size;
++	u8 reserved1;
++	struct ieee80211_hdr frame[0];	/* beacon frame */
++} __attribute__ ((packed));
 +
-+		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
++/******************************************************************************
++ * (10)
++ * Statistics Commands and Notifications:
++ *
++ *****************************************************************************/
 +
-+		return 0;
-+	}
++#define IWL_TEMP_CONVERT 260
 +
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_SENSITIVITY
-+	priv->sensitivity_data.state = IWL_SENS_CALIB_NEED_REINIT;
-+	if (!priv->error_recovering)
-+		priv->start_calib = 0;
++#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
++#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
++#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
 +
-+	iwl4965_init_sensitivity(priv, CMD_ASYNC, 1);
-+#endif /* CONFIG_IWLWIFI_SENSITIVITY */
-+#endif /* IWL == 4965 */
++/* Used for passing to driver number of successes and failures per rate */
++struct rate_histogram {
++	union {
++		__le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
++		__le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
++		__le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
++	} success;
++	union {
++		__le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
++		__le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
++		__le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
++	} failed;
++} __attribute__ ((packed));
 +
-+	/* If we are currently associated and the new config requires
-+	 * an RXON_ASSOC and the new config wants the associated mask enabled,
-+	 * we must clear the associated from the active configuration
-+	 * before we apply the new config */
-+	if (iwl_is_associated(priv) &&
-+	    (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
-+		IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
-+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++/* statistics command response */
 +
-+		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
-+				      sizeof(struct iwl_rxon_cmd),
-+				      &priv->active_rxon);
++struct statistics_rx_phy {
++	__le32 ina_cnt;
++	__le32 fina_cnt;
++	__le32 plcp_err;
++	__le32 crc32_err;
++	__le32 overrun_err;
++	__le32 early_overrun_err;
++	__le32 crc32_good;
++	__le32 false_alarm_cnt;
++	__le32 fina_sync_err_cnt;
++	__le32 sfd_timeout;
++	__le32 fina_timeout;
++	__le32 unresponded_rts;
++	__le32 rxe_frame_limit_overrun;
++	__le32 sent_ack_cnt;
++	__le32 sent_cts_cnt;
++#if IWL == 4965
++	__le32 sent_ba_rsp_cnt;
++	__le32 dsp_self_kill;
++	__le32 mh_format_err;
++	__le32 re_acq_main_rssi_sum;
++	__le32 reserved3;
++#endif
++} __attribute__ ((packed));
 +
-+		/* If the mask clearing failed then we set
-+		 * active_rxon back to what it was previously */
-+		if (rc) {
-+			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-+			IWL_ERROR("Error clearing ASSOC_MSK on current "
-+				  "configuration (%d).\n", rc);
-+			return rc;
-+		}
++#if IWL == 4965
++struct statistics_rx_ht_phy {
++	__le32 plcp_err;
++	__le32 overrun_err;
++	__le32 early_overrun_err;
++	__le32 crc32_good;
++	__le32 crc32_err;
++	__le32 mh_format_err;
++	__le32 agg_crc32_good;
++	__le32 agg_mpdu_cnt;
++	__le32 agg_cnt;
++	__le32 reserved2;
++} __attribute__ ((packed));
++#endif
 +
-+		/* The RXON bit toggling will have cleared out the
-+		 * station table in the uCode, so blank it in the driver
-+		 * as well */
-+		iwl_clear_stations_table(priv);
-+	} else if (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) {
-+		/* When switching from non-associated to associated, the
-+		 * uCode clears out the station table; so clear it in the
-+		 * driver as well */
-+		iwl_clear_stations_table(priv);
-+	}
++struct statistics_rx_non_phy {
++	__le32 bogus_cts;	/* CTS received when not expecting CTS */
++	__le32 bogus_ack;	/* ACK received when not expecting ACK */
++	__le32 non_bssid_frames;	/* number of frames with BSSID that
++					 * doesn't belong to the STA BSSID */
++	__le32 filtered_frames;	/* count frames that were dumped in the
++				 * filtering process */
++	__le32 non_channel_beacons;	/* beacons with our bss id but not on
++					 * our serving channel */
++#if IWL == 4965
++	__le32 channel_beacons;	/* beacons with our bss id and in our
++				 * serving channel */
++	__le32 num_missed_bcon;	/* number of missed beacons */
++	__le32 adc_rx_saturation_time;	/* count in 0.8us units the time the
++					 * ADC was in saturation */
++	__le32 ina_detection_search_time;/* total time (in 0.8us) searched
++					  * for INA */
++	__le32 beacon_silence_rssi_a;	/* RSSI silence after beacon frame */
++	__le32 beacon_silence_rssi_b;	/* RSSI silence after beacon frame */
++	__le32 beacon_silence_rssi_c;	/* RSSI silence after beacon frame */
++	__le32 interference_data_flag;	/* flag for interference data
++					 * availability. 1 when data is
++					 * available. */
++	__le32 channel_load;	/* counts RX Enable time */
++	__le32 dsp_false_alarms;	/* DSP false alarm (both OFDM
++					 * and CCK) counter */
++	__le32 beacon_rssi_a;
++	__le32 beacon_rssi_b;
++	__le32 beacon_rssi_c;
++	__le32 beacon_energy_a;
++	__le32 beacon_energy_b;
++	__le32 beacon_energy_c;
++#endif
++} __attribute__ ((packed));
 +
-+	IWL_DEBUG_INFO("Sending RXON\n"
-+		       "* with%s RXON_FILTER_ASSOC_MSK\n"
-+		       "* channel = %d\n"
-+		       "* bssid = " MAC_FMT "\n",
-+		       ((priv->staging_rxon.filter_flags &
-+			 RXON_FILTER_ASSOC_MSK) ? "" : "out"),
-+		       le16_to_cpu(priv->staging_rxon.channel),
-+		       MAC_ARG(priv->staging_rxon.bssid_addr));
++struct statistics_rx {
++	struct statistics_rx_phy ofdm;
++	struct statistics_rx_phy cck;
++	struct statistics_rx_non_phy general;
++#if IWL == 4965
++	struct statistics_rx_ht_phy ofdm_ht;
++#endif
++} __attribute__ ((packed));
 +
-+	/* Apply the new configuration */
-+	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
-+			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
-+	if (rc) {
-+		IWL_ERROR("Error setting new configuration (%d).\n", rc);
-+		return rc;
-+	}
++#if IWL == 4965
++struct statistics_tx_non_phy_agg {
++	__le32 ba_timeout;
++	__le32 ba_reschedule_frames;
++	__le32 scd_query_agg_frame_cnt;
++	__le32 scd_query_no_agg;
++	__le32 scd_query_agg;
++	__le32 scd_query_mismatch;
++	__le32 frame_not_ready;
++	__le32 underrun;
++	__le32 bt_prio_kill;
++	__le32 rx_ba_rsp_cnt;
++	__le32 reserved2;
++	__le32 reserved3;
++} __attribute__ ((packed));
++#endif
 +
++struct statistics_tx {
++	__le32 preamble_cnt;
++	__le32 rx_detected_cnt;
++	__le32 bt_prio_defer_cnt;
++	__le32 bt_prio_kill_cnt;
++	__le32 few_bytes_cnt;
++	__le32 cts_timeout;
++	__le32 ack_timeout;
++	__le32 expected_ack_cnt;
++	__le32 actual_ack_cnt;
 +#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_SENSITIVITY
-+	if (!priv->error_recovering)
-+		priv->start_calib = 0;
++	__le32 dump_msdu_cnt;
++	__le32 burst_abort_next_frame_mismatch_cnt;
++	__le32 burst_abort_missing_next_frame_cnt;
++	__le32 cts_timeout_collision;
++	__le32 ack_or_ba_timeout_collision;
++	struct statistics_tx_non_phy_agg agg;
++#endif
++} __attribute__ ((packed));
 +
-+	priv->sensitivity_data.state = IWL_SENS_CALIB_NEED_REINIT;
-+	iwl4965_init_sensitivity(priv, CMD_ASYNC, 1);
-+#endif /* CONFIG_IWLWIFI_SENSITIVITY */
-+#endif /* IWL == 4965 */
++struct statistics_dbg {
++	__le32 burst_check;
++	__le32 burst_count;
++	__le32 reserved[4];
++} __attribute__ ((packed));
 +
-+	memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
++struct statistics_div {
++	__le32 tx_on_a;
++	__le32 tx_on_b;
++	__le32 exec_time;
++	__le32 probe_time;
++#if IWL == 4965
++	__le32 reserved1;
++	__le32 reserved2;
++#endif
++} __attribute__ ((packed));
 +
-+	/* If we issue a new RXON command which required a tune then we must
-+	 * send a new TXPOWER command or we won't be able to Tx any frames */
-+	rc = iwl_hw_reg_send_txpower(priv);
-+	if (rc) {
-+		IWL_ERROR("Error setting Tx power (%d).\n", rc);
-+		return rc;
-+	}
-+
-+	/* Add the broadcast address so we can send broadcast frames */
-+	if (iwl_rxon_add_station(priv, BROADCAST_ADDR, 0) ==
-+	    IWL_INVALID_STATION) {
-+		IWL_ERROR("Error adding BROADCAST address for transmit.\n");
-+		return -EIO;
-+	}
-+
-+	/* If we have set the ASSOC_MSK and we are in BSS mode then
-+	 * add the IWL_AP_ID to the station rate table */
-+	if (iwl_is_associated(priv) &&
-+	    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
-+		if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
-+		    == IWL_INVALID_STATION) {
-+			IWL_ERROR("Error adding AP address for transmit.\n");
-+			return -EIO;
-+		}
-+	}
-+
-+	/* Init the hardware's rate fallback order based on the
-+	 * phymode */
-+	rc = iwl3945_init_hw_rate_table(priv);
-+	if (rc) {
-+		IWL_ERROR("Error setting HW rate table: %02X\n", rc);
-+		return -EIO;
-+	}
++struct statistics_general {
++	__le32 temperature;
++#if IWL == 4965
++	__le32 temperature_m;
++#endif
++	struct statistics_dbg dbg;
++	__le32 sleep_time;
++	__le32 slots_out;
++	__le32 slots_idle;
++	__le32 ttl_timestamp;
++	struct statistics_div div;
++#if IWL == 4965
++	__le32 rx_enable_counter;
++	__le32 reserved1;
++	__le32 reserved2;
++	__le32 reserved3;
++#endif
++} __attribute__ ((packed));
 +
-+	return 0;
-+}
++/*
++ * REPLY_STATISTICS_CMD = 0x9c,
++ * 3945 and 4965 identical.
++ *
++ * This command triggers an immediate response containing uCode statistics.
++ * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below.
++ *
++ * If the CLEAR_STATS configuration flag is set, uCode will clear its
++ * internal copy of the statistics (counters) after issuing the response.
++ * This flag does not affect STATISTICS_NOTIFICATIONs after beacons (see below).
++ *
++ * If the DISABLE_NOTIF configuration flag is set, uCode will not issue
++ * STATISTICS_NOTIFICATIONs after received beacons (see below).  This flag
++ * does not affect the response to the REPLY_STATISTICS_CMD 0x9c itself.
++ */
++#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1)	/* see above */
++#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */
++struct iwl_statistics_cmd {
++	__le32 configuration_flags;	/* IWL_STATS_CONF_* */
++} __attribute__ ((packed));
 +
-+static int iwl_send_bt_config(struct iwl_priv *priv)
-+{
-+	struct iwl_bt_cmd bt_cmd = {
-+		.flags = 3,
-+		.lead_time = 0xAA,
-+		.max_kill = 1,
-+		.kill_ack_mask = 0,
-+		.kill_cts_mask = 0,
-+	};
++/*
++ * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)
++ *
++ * By default, uCode issues this notification after receiving a beacon
++ * while associated.  To disable this behavior, set DISABLE_NOTIF flag in the
++ * REPLY_STATISTICS_CMD 0x9c, above.
++ *
++ * Statistics counters continue to increment beacon after beacon, but are
++ * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD
++ * 0x9c with CLEAR_STATS bit set (see above).
++ *
++ * uCode also issues this notification during scans.  uCode clears statistics
++ * appropriately so that each notification contains statistics for only the
++ * one channel that has just been scanned.
++ */
++#define STATISTICS_REPLY_FLG_BAND_24G_MSK         __constant_cpu_to_le32(0x2)
++#define STATISTICS_REPLY_FLG_FAT_MODE_MSK         __constant_cpu_to_le32(0x8)
++struct iwl_notif_statistics {
++	__le32 flag;
++	struct statistics_rx rx;
++	struct statistics_tx tx;
++	struct statistics_general general;
++} __attribute__ ((packed));
 +
-+	return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
-+				sizeof(struct iwl_bt_cmd), &bt_cmd);
-+}
 +
-+static int iwl_send_scan_abort(struct iwl_priv *priv)
-+{
-+	int rc = 0;
-+	struct iwl_rx_packet *res;
-+	struct iwl_host_cmd cmd = {
-+		.id = REPLY_SCAN_ABORT_CMD,
-+		.meta.flags = CMD_WANT_SKB,
-+	};
++/*
++ * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command)
++ */
++/* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row,
++ * then this notification will be sent. */
++#define CONSECUTIVE_MISSED_BCONS_TH 20
 +
-+	/* If there isn't a scan actively going on in the hardware
-+	 * then we are in between scan bands and not actually
-+	 * actively scanning, so don't send the abort command */
-+	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
-+		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-+		return 0;
-+	}
++struct iwl_missed_beacon_notif {
++	__le32 consequtive_missed_beacons;
++	__le32 total_missed_becons;
++	__le32 num_expected_beacons;
++	__le32 num_recvd_beacons;
++} __attribute__ ((packed));
 +
-+	rc = iwl_send_cmd_sync(priv, &cmd);
-+	if (rc) {
-+		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-+		return rc;
-+	}
++/******************************************************************************
++ * (11)
++ * Rx Calibration Commands:
++ *
++ *****************************************************************************/
 +
-+	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
-+	if (res->u.status != CAN_ABORT_STATUS) {
-+		/* The scan abort will return 1 for success or
-+		 * 2 for "failure".  A failure condition can be
-+		 * due to simply not being in an active scan which
-+		 * can occur if we send the scan abort before we
-+		 * the microcode has notified us that a scan is
-+		 * completed. */
-+		IWL_DEBUG_INFO("SCAN_ABORT returned %d.\n", res->u.status);
-+		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-+		clear_bit(STATUS_SCAN_HW, &priv->status);
-+	}
++#define PHY_CALIBRATE_DIFF_GAIN_CMD (7)
++#define HD_TABLE_SIZE  (11)
 +
-+	dev_kfree_skb_any(cmd.meta.u.skb);
++struct iwl_sensitivity_cmd {
++	__le16 control;
++	__le16 table[HD_TABLE_SIZE];
++} __attribute__ ((packed));
 +
-+	return rc;
-+}
++struct iwl_calibration_cmd {
++	u8 opCode;
++	u8 flags;
++	__le16 reserved;
++	s8 diff_gain_a;
++	s8 diff_gain_b;
++	s8 diff_gain_c;
++	u8 reserved1;
++} __attribute__ ((packed));
 +
-+static int iwl_card_state_sync_callback(struct iwl_priv *priv,
-+					struct iwl_cmd *cmd,
-+					struct sk_buff *skb)
-+{
-+	return 1;
-+}
++/******************************************************************************
++ * (12)
++ * Miscellaneous Commands:
++ *
++ *****************************************************************************/
 +
 +/*
-+ * CARD_STATE_CMD
-+ *
-+ * Use: Sets the internal card state to enable, disable, or halt
++ * LEDs Command & Response
++ * REPLY_LEDS_CMD = 0x48 (command, has simple generic response)
 + *
-+ * When in the 'enable' state the card operates as normal.
-+ * When in the 'disable' state, the card enters into a low power mode.
-+ * When in the 'halt' state, the card is shut down and must be fully
-+ * restarted to come back on.
++ * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field),
++ * this command turns it on or off, or sets up a periodic blinking cycle.
 + */
-+static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
-+{
-+	struct iwl_host_cmd cmd = {
-+		.id = REPLY_CARD_STATE_CMD,
-+		.len = sizeof(u32),
-+		.data = &flags,
-+		.meta.flags = meta_flag,
-+	};
-+
-+	if (meta_flag & CMD_ASYNC)
-+		cmd.meta.u.callback = iwl_card_state_sync_callback;
++struct iwl_led_cmd {
++	__le32 interval;	/* "interval" in uSec */
++	u8 id;			/* 1: Activity, 2: Link, 3: Tech */
++	u8 off;			/* # intervals off while blinking;
++				 * "0", with >0 "on" value, turns LED on */
++	u8 on;			/* # intervals on while blinking;
++				 * "0", regardless of "off", turns LED off */
++	u8 reserved;
++} __attribute__ ((packed));
 +
-+	return iwl_send_cmd(priv, &cmd);
-+}
++/******************************************************************************
++ * (13)
++ * Union of all expected notifications/responses:
++ *
++ *****************************************************************************/
 +
-+static int iwl_add_sta_sync_callback(struct iwl_priv *priv,
-+				     struct iwl_cmd *cmd, struct sk_buff *skb)
-+{
-+	struct iwl_rx_packet *res = NULL;
++struct iwl_rx_packet {
++	__le32 len;
++	struct iwl_cmd_header hdr;
++	union {
++		struct iwl_alive_resp alive_frame;
++		struct iwl_rx_frame rx_frame;
++		struct iwl_tx_resp tx_resp;
++		struct iwl_spectrum_notification spectrum_notif;
++		struct iwl_csa_notification csa_notif;
++		struct iwl_error_resp err_resp;
++		struct iwl_card_state_notif card_state_notif;
++		struct iwl_beacon_notif beacon_status;
++		struct iwl_add_sta_resp add_sta;
++		struct iwl_sleep_notification sleep_notif;
++		struct iwl_spectrum_resp spectrum;
++		struct iwl_notif_statistics stats;
++#if IWL == 4965
++		struct iwl_compressed_ba_resp compressed_ba;
++		struct iwl_missed_beacon_notif missed_beacon;
++#endif
++		__le32 status;
++		u8 raw[0];
++	} u;
++} __attribute__ ((packed));
 +
-+	if (!skb) {
-+		IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
-+		return 1;
-+	}
++#define IWL_RX_FRAME_SIZE        (4 + sizeof(struct iwl_rx_frame))
 +
-+	res = (struct iwl_rx_packet *)skb->data;
-+	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-+		IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
-+			  res->hdr.flags);
-+		return 1;
-+	}
++#endif				/* __iwl_commands_h__ */
+diff --git a/drivers/net/wireless/iwl-debug.h b/drivers/net/wireless/iwl-debug.h
+new file mode 100644
+index 0000000..0ebc4f7
+--- /dev/null
++++ b/drivers/net/wireless/iwl-debug.h
+@@ -0,0 +1,149 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
 +
-+	switch (res->u.add_sta.status) {
-+	case ADD_STA_SUCCESS_MSK:
-+		break;
-+	default:
-+		break;
-+	}
++#ifndef __iwl_debug_h__
++#define __iwl_debug_h__
 +
-+	/* We didn't cache the SKB; let the caller free it */
-+	return 1;
-+}
++#ifdef CONFIG_IWLWIFI_DEBUG
++extern u32 iwl_debug_level;
++#define IWL_DEBUG(level, fmt, args...) \
++do { if (iwl_debug_level & (level)) \
++  printk(KERN_ERR DRV_NAME": %c %s " fmt, \
++	 in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
 +
-+int iwl_send_add_station(struct iwl_priv *priv,
-+			 struct iwl_addsta_cmd *sta, u8 flags)
++#define IWL_DEBUG_LIMIT(level, fmt, args...) \
++do { if ((iwl_debug_level & (level)) && net_ratelimit()) \
++  printk(KERN_ERR DRV_NAME": %c %s " fmt, \
++	 in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
++#else
++static inline void IWL_DEBUG(int level, const char *fmt, ...)
 +{
-+	struct iwl_rx_packet *res = NULL;
-+	int rc = 0;
-+	struct iwl_host_cmd cmd = {
-+		.id = REPLY_ADD_STA,
-+		.len = sizeof(struct iwl_addsta_cmd),
-+		.meta.flags = flags,
-+		.data = sta,
-+	};
-+
-+	if (flags & CMD_ASYNC)
-+		cmd.meta.u.callback = iwl_add_sta_sync_callback;
-+	else
-+		cmd.meta.flags |= CMD_WANT_SKB;
-+
-+	rc = iwl_send_cmd(priv, &cmd);
-+
-+	if (rc || (flags & CMD_ASYNC))
-+		return rc;
-+
-+	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
-+	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-+		IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
-+			  res->hdr.flags);
-+		rc = -EIO;
-+	}
-+
-+	if (rc == 0) {
-+		switch (res->u.add_sta.status) {
-+		case ADD_STA_SUCCESS_MSK:
-+			IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n");
-+			break;
-+		default:
-+			rc = -EIO;
-+			IWL_WARNING("REPLY_ADD_STA failed\n");
-+			break;
-+		}
-+	}
-+
-+	priv->alloc_rxb_skb--;
-+	dev_kfree_skb_any(cmd.meta.u.skb);
-+
-+	return rc;
 +}
-+
-+static int iwl_update_sta_key_info(struct iwl_priv *priv,
-+				   struct ieee80211_key_conf *keyconf,
-+				   u8 sta_id)
++static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
 +{
-+	unsigned long flags;
-+	__le16 key_flags = 0;
-+
-+	switch (keyconf->alg) {
-+	case ALG_CCMP:
-+		key_flags |= STA_KEY_FLG_CCMP;
-+		key_flags |= cpu_to_le16(
-+				keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-+		key_flags &= ~STA_KEY_FLG_INVALID;
-+		break;
-+	case ALG_TKIP:
-+	case ALG_WEP:
-+		return -EINVAL;
-+	default:
-+		return -EINVAL;
-+	}
-+	spin_lock_irqsave(&priv->sta_lock, flags);
-+	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
-+	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-+	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
-+	       keyconf->keylen);
-+
-+	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
-+	       keyconf->keylen);
-+	priv->stations[sta_id].sta.key.key_flags = key_flags;
-+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-+
-+	spin_unlock_irqrestore(&priv->sta_lock, flags);
-+
-+	IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
-+	iwl_send_add_station(priv, &priv->stations[sta_id].sta, 0);
-+	return 0;
 +}
++#endif				/* CONFIG_IWLWIFI_DEBUG */
 +
-+static void iwl_clear_free_frames(struct iwl_priv *priv)
-+{
-+	struct list_head *element;
-+
-+	IWL_DEBUG_INFO("%d frames on pre-allocated heap on clear.\n",
-+		       priv->frames_count);
++/*
++ * To use the debug system;
++ *
++ * If you are defining a new debug classification, simply add it to the #define
++ * list here in the form of:
++ *
++ * #define IWL_DL_xxxx VALUE
++ *
++ * shifting value to the left one bit from the previous entry.  xxxx should be
++ * the name of the classification (for example, WEP)
++ *
++ * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
++ * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
++ * to send output to that classification.
++ *
++ * To add your debug level to the list of levels seen when you perform
++ *
++ * % cat /proc/net/ipw/debug_level
++ *
++ * you simply need to add your entry to the iwl_debug_levels array.
++ *
++ * If you do not see debug_level in /proc/net/ipw then you do not have
++ * CONFIG_IWLWIFI_DEBUG defined in your kernel configuration
++ *
++ */
 +
-+	while (!list_empty(&priv->free_frames)) {
-+		element = priv->free_frames.next;
-+		list_del(element);
-+		kfree(list_entry(element, struct iwl_frame, list));
-+		priv->frames_count--;
-+	}
++#define IWL_DL_INFO          (1<<0)
++#define IWL_DL_MAC80211      (1<<1)
++#define IWL_DL_HOST_COMMAND  (1<<2)
++#define IWL_DL_STATE         (1<<3)
 +
-+	if (priv->frames_count) {
-+		IWL_WARNING("%d frames still in use.  Did we lose one?\n",
-+			    priv->frames_count);
-+		priv->frames_count = 0;
-+	}
-+}
++#define IWL_DL_RADIO         (1<<7)
++#define IWL_DL_POWER         (1<<8)
++#define IWL_DL_TEMP          (1<<9)
 +
-+static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
-+{
-+	struct iwl_frame *frame;
-+	struct list_head *element;
-+	if (list_empty(&priv->free_frames)) {
-+		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
-+		if (!frame) {
-+			IWL_ERROR("Could not allocate frame!\n");
-+			return NULL;
-+		}
++#define IWL_DL_NOTIF         (1<<10)
++#define IWL_DL_SCAN          (1<<11)
++#define IWL_DL_ASSOC         (1<<12)
++#define IWL_DL_DROP          (1<<13)
 +
-+		priv->frames_count++;
-+		return frame;
-+	}
++#define IWL_DL_TXPOWER       (1<<14)
 +
-+	element = priv->free_frames.next;
-+	list_del(element);
-+	return list_entry(element, struct iwl_frame, list);
-+}
++#define IWL_DL_AP            (1<<15)
 +
-+static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
-+{
-+	memset(frame, 0, sizeof(*frame));
-+	list_add(&frame->list, &priv->free_frames);
-+}
++#define IWL_DL_FW            (1<<16)
++#define IWL_DL_RF_KILL       (1<<17)
++#define IWL_DL_FW_ERRORS     (1<<18)
 +
-+unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
-+				struct ieee80211_hdr *hdr,
-+				const u8 *dest, int left)
-+{
++#define IWL_DL_LED           (1<<19)
 +
-+	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
-+	    ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
-+	     (priv->iw_mode != IEEE80211_IF_TYPE_AP)))
-+		return 0;
++#define IWL_DL_RATE          (1<<20)
 +
-+	if (priv->ibss_beacon->len > left)
-+		return 0;
++#define IWL_DL_CALIB         (1<<21)
++#define IWL_DL_WEP           (1<<22)
++#define IWL_DL_TX            (1<<23)
++#define IWL_DL_RX            (1<<24)
++#define IWL_DL_ISR           (1<<25)
++#define IWL_DL_HT            (1<<26)
++#define IWL_DL_IO            (1<<27)
++#define IWL_DL_11H           (1<<28)
 +
-+	memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
++#define IWL_DL_STATS         (1<<29)
++#define IWL_DL_TX_REPLY      (1<<30)
++#define IWL_DL_QOS           (1<<31)
 +
-+	return priv->ibss_beacon->len;
-+}
++#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
++#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
++#define IWL_DEBUG_INFO(f, a...)    IWL_DEBUG(IWL_DL_INFO, f, ## a)
 +
-+static int iwl_send_beacon_cmd(struct iwl_priv *priv)
-+{
-+	struct iwl_frame *frame;
-+	unsigned int frame_size;
-+	int rc;
-+	u8 rate;
-+
-+	frame = iwl_get_free_frame(priv);
-+
-+	if (!frame) {
-+		IWL_ERROR("Could not obtain free frame buffer for beacon "
-+			  "command.\n");
-+		return -ENOMEM;
-+	}
-+
-+	if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) {
-+		rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic &
-+						0xFF0);
-+		if (rate == IWL_INVALID_RATE)
-+			rate = IWL_RATE_6M_PLCP;
-+	} else {
-+		rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic & 0xF);
-+		if (rate == IWL_INVALID_RATE)
-+			rate = IWL_RATE_1M_PLCP;
-+	}
-+
-+	frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate);
-+
-+	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
-+			      &frame->u.cmd[0]);
-+
-+	iwl_free_frame(priv, frame);
-+
-+	return rc;
-+}
++#define IWL_DEBUG_MAC80211(f, a...)     IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
++#define IWL_DEBUG_TEMP(f, a...)   IWL_DEBUG(IWL_DL_TEMP, f, ## a)
++#define IWL_DEBUG_SCAN(f, a...)   IWL_DEBUG(IWL_DL_SCAN, f, ## a)
++#define IWL_DEBUG_RX(f, a...)     IWL_DEBUG(IWL_DL_RX, f, ## a)
++#define IWL_DEBUG_TX(f, a...)     IWL_DEBUG(IWL_DL_TX, f, ## a)
++#define IWL_DEBUG_ISR(f, a...)    IWL_DEBUG(IWL_DL_ISR, f, ## a)
++#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
++#define IWL_DEBUG_WEP(f, a...)    IWL_DEBUG(IWL_DL_WEP, f, ## a)
++#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
++#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
++#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
++#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
++#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
++#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
++#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
++#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
++#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
++#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
++#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
++#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
++#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
++#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
++#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
++#define IWL_DEBUG_QOS(f, a...)   IWL_DEBUG(IWL_DL_QOS, f, ## a)
++#define IWL_DEBUG_RADIO(f, a...)  IWL_DEBUG(IWL_DL_RADIO, f, ## a)
++#define IWL_DEBUG_POWER(f, a...)  IWL_DEBUG(IWL_DL_POWER, f, ## a)
++#define IWL_DEBUG_11H(f, a...)  IWL_DEBUG(IWL_DL_11H, f, ## a)
 +
++#endif
+diff --git a/drivers/net/wireless/iwl-eeprom.h b/drivers/net/wireless/iwl-eeprom.h
+new file mode 100644
+index 0000000..e473c97
+--- /dev/null
++++ b/drivers/net/wireless/iwl-eeprom.h
+@@ -0,0 +1,336 @@
 +/******************************************************************************
 + *
-+ * EEPROM related functions
++ * This file is provided under a dual BSD/GPLv2 license.  When using or
++ * redistributing this file, you may do so under either license.
 + *
-+ ******************************************************************************/
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU Geeral Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ *  * Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ *  * Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *  * Neither the name Intel Corporation nor the names of its
++ *    contributors may be used to endorse or promote products derived
++ *    from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ *****************************************************************************/
 +
-+static void get_eeprom_mac(struct iwl_priv *priv, u8 *mac)
-+{
-+	memcpy(mac, priv->eeprom.mac_address, 6);
-+}
++#ifndef __iwl_eeprom_h__
++#define __iwl_eeprom_h__
 +
-+/**
-+ * iwl_eeprom_init - read EEPROM contents
-+ *
-+ * Load the EEPROM from adapter into priv->eeprom
++/*
++ * This file defines EEPROM related constants, enums, and inline functions.
 + *
-+ * NOTE:  This routine uses the non-debug IO access functions.
 + */
-+int iwl_eeprom_init(struct iwl_priv *priv)
-+{
-+	u16 *e = (u16 *)&priv->eeprom;
-+	u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
-+	u32 r;
-+	int sz = sizeof(priv->eeprom);
-+	int rc;
-+	int i;
-+	u16 addr;
 +
-+	/* The EEPROM structure has several padding buffers within it
-+	 * and when adding new EEPROM maps is subject to programmer errors
-+	 * which may be very difficult to identify without explicitly
-+	 * checking the resulting size of the eeprom map. */
-+	BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
++#define IWL_EEPROM_ACCESS_TIMEOUT	5000 /* uSec */
++#define IWL_EEPROM_ACCESS_DELAY		10   /* uSec */
++/* EEPROM field values */
++#define ANTENNA_SWITCH_NORMAL     0
++#define ANTENNA_SWITCH_INVERSE    1
 +
-+	if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
-+		IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
-+		return -ENOENT;
-+	}
++enum {
++	EEPROM_CHANNEL_VALID = (1 << 0),	/* usable for this SKU/geo */
++	EEPROM_CHANNEL_IBSS = (1 << 1),	/* usable as an IBSS channel */
++	/* Bit 2 Reserved */
++	EEPROM_CHANNEL_ACTIVE = (1 << 3),	/* active scanning allowed */
++	EEPROM_CHANNEL_RADAR = (1 << 4),	/* radar detection required */
++	EEPROM_CHANNEL_WIDE = (1 << 5),
++	EEPROM_CHANNEL_NARROW = (1 << 6),
++	EEPROM_CHANNEL_DFS = (1 << 7),	/* dynamic freq selection candidate */
++};
 +
-+	rc = iwl_eeprom_aqcuire_semaphore(priv);
-+	if (rc < 0) {
-+		IWL_ERROR("Failed to aqcuire EEPROM semaphore.\n");
-+		return -ENOENT;
-+	}
++/* EEPROM field lengths */
++#define EEPROM_BOARD_PBA_NUMBER_LENGTH                  11
 +
-+	/* eeprom is an array of 16bit values */
-+	for (addr = 0; addr < sz; addr += sizeof(u16)) {
-+		_iwl_write32(priv, CSR_EEPROM_REG, addr << 1);
-+		_iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
++/* EEPROM field lengths */
++#define EEPROM_BOARD_PBA_NUMBER_LENGTH                  11
++#define EEPROM_REGULATORY_SKU_ID_LENGTH                 4
++#define EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH         14
++#define EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH         13
++#define EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH         12
++#define EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH         11
++#define EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH         6
 +
-+		for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
-+					i += IWL_EEPROM_ACCESS_DELAY) {
-+			r = _iwl_read_restricted(priv, CSR_EEPROM_REG);
-+			if (r & CSR_EEPROM_REG_READ_VALID_MSK)
-+				break;
-+			udelay(IWL_EEPROM_ACCESS_DELAY);
-+		}
++#if IWL == 3945
++#define EEPROM_REGULATORY_CHANNELS_LENGTH ( \
++	EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH + \
++	EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH + \
++	EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH + \
++	EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH + \
++	EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH)
++#elif IWL == 4965
++#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS_LENGTH 7
++#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS_LENGTH 11
++#define EEPROM_REGULATORY_CHANNELS_LENGTH ( \
++	EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH + \
++	EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH + \
++	EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH + \
++	EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH + \
++	EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH + \
++	EEPROM_REGULATORY_BAND_24_FAT_CHANNELS_LENGTH + \
++	EEPROM_REGULATORY_BAND_52_FAT_CHANNELS_LENGTH)
++#endif
 +
-+		if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
-+			IWL_ERROR("Time out reading EEPROM[%d]", addr);
-+			rc = -ETIMEDOUT;
-+			goto done;
-+		}
-+		e[addr / 2] = le16_to_cpu(r >> 16);
-+	}
-+	rc = 0;
++#define EEPROM_REGULATORY_NUMBER_OF_BANDS               5
 +
-+done:
-+	iwl_eeprom_release_semaphore(priv);
-+	return rc;
-+}
++/* SKU Capabilities */
++#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE                (1 << 0)
++#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
++#define EEPROM_SKU_CAP_OP_MODE_MRC                      (1 << 7)
 +
-+/******************************************************************************
-+ *
-+ * Misc. internal state and helper functions
-+ *
-+ ******************************************************************************/
-+#ifdef CONFIG_IWLWIFI_DEBUG
++/* *regulatory* channel data from eeprom, one for each channel */
++struct iwl_eeprom_channel {
++	u8 flags;		/* flags copied from EEPROM */
++	s8 max_power_avg;	/* max power (dBm) on this chnl, limit 31 */
++} __attribute__ ((packed));
 +
-+/**
-+ * iwl_report_frame - dump frame to syslog during debug sessions
-+ *
-+ * hack this function to show different aspects of received frames,
-+ * including selective frame dumps.
-+ * group100 parameter selects whether to show 1 out of 100 good frames.
-+ *
-+ * TODO:  ieee80211_hdr stuff is common to 3945 and 4965, so frame type
-+ *        info output is okay, but some of this stuff (e.g. iwl_rx_frame_stats)
-+ *        is 3945-specific and gives bad output for 4965.  Need to split the
-+ *        functionality, keep common stuff here.
++/*
++ * Mapping of a Tx power level, at factory calibration temperature,
++ *   to a radio/DSP gain table index.
++ * One for each of 5 "sample" power levels in each band.
++ * v_det is measured at the factory, using the 3945's built-in power amplifier
++ *   (PA) output voltage detector.  This same detector is used during Tx of
++ *   long packets in normal operation to provide feedback as to proper output
++ *   level.
++ * Data copied from EEPROM.
 + */
-+void iwl_report_frame(struct iwl_priv *priv,
-+		      struct iwl_rx_packet *pkt,
-+		      struct ieee80211_hdr *header, int group100)
++struct iwl_eeprom_txpower_sample {
++	u8 gain_index;		/* index into power (gain) setup table ... */
++	s8 power;		/* ... for this pwr level for this chnl group */
++	u16 v_det;		/* PA output voltage */
++} __attribute__ ((packed));
++
++/*
++ * Mappings of Tx power levels -> nominal radio/DSP gain table indexes.
++ * One for each channel group (a.k.a. "band") (1 for BG, 4 for A).
++ * Tx power setup code interpolates between the 5 "sample" power levels
++ *    to determine the nominal setup for a requested power level.
++ * Data copied from EEPROM.
++ * DO NOT ALTER THIS STRUCTURE!!!
++ */
++struct iwl_eeprom_txpower_group {
++	struct iwl_eeprom_txpower_sample samples[5];	/* 5 power levels */
++	s32 a, b, c, d, e;	/* coefficients for voltage->power
++				 * formula (signed) */
++	s32 Fa, Fb, Fc, Fd, Fe;	/* these modify coeffs based on
++					 * frequency (signed) */
++	s8 saturation_power;	/* highest power possible by h/w in this
++				 * band */
++	u8 group_channel;	/* "representative" channel # in this band */
++	s16 temperature;	/* h/w temperature at factory calib this band
++				 * (signed) */
++} __attribute__ ((packed));
++
++/*
++ * Temperature-based Tx-power compensation data, not band-specific.
++ * These coefficients are use to modify a/b/c/d/e coeffs based on
++ *   difference between current temperature and factory calib temperature.
++ * Data copied from EEPROM.
++ */
++struct iwl_eeprom_temperature_corr {
++	u32 Ta;
++	u32 Tb;
++	u32 Tc;
++	u32 Td;
++	u32 Te;
++} __attribute__ ((packed));
++
++#if IWL == 4965
++#define EEPROM_TX_POWER_TX_CHAINS      (2)
++#define EEPROM_TX_POWER_BANDS          (8)
++#define EEPROM_TX_POWER_MEASUREMENTS   (3)
++#define EEPROM_TX_POWER_VERSION        (2)
++#define EEPROM_TX_POWER_VERSION_NEW    (5)
++
++struct iwl_eeprom_calib_measure {
++	u8 temperature;
++	u8 gain_idx;
++	u8 actual_pow;
++	s8 pa_det;
++} __attribute__ ((packed));
++
++struct iwl_eeprom_calib_ch_info {
++	u8 ch_num;
++	struct iwl_eeprom_calib_measure measurements[EEPROM_TX_POWER_TX_CHAINS]
++		[EEPROM_TX_POWER_MEASUREMENTS];
++} __attribute__ ((packed));
++
++struct iwl_eeprom_calib_subband_info {
++	u8 ch_from;
++	u8 ch_to;
++	struct iwl_eeprom_calib_ch_info ch1;
++	struct iwl_eeprom_calib_ch_info ch2;
++} __attribute__ ((packed));
++
++struct iwl_eeprom_calib_info {
++	u8 saturation_power24;
++	u8 saturation_power52;
++	s16 voltage;		/* signed */
++	struct iwl_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS];
++} __attribute__ ((packed));
++
++#endif
++
++struct iwl_eeprom {
++	u8 reserved0[16];
++#define EEPROM_DEVICE_ID                    (2*0x08)	/* 2 bytes */
++	u16 device_id;	/* abs.ofs: 16 */
++	u8 reserved1[2];
++#define EEPROM_PMC                          (2*0x0A)	/* 2 bytes */
++	u16 pmc;		/* abs.ofs: 20 */
++	u8 reserved2[20];
++#define EEPROM_MAC_ADDRESS                  (2*0x15)	/* 6  bytes */
++	u8 mac_address[6];	/* abs.ofs: 42 */
++	u8 reserved3[58];
++#define EEPROM_BOARD_REVISION               (2*0x35)	/* 2  bytes */
++	u16 board_revision;	/* abs.ofs: 106 */
++	u8 reserved4[11];
++#define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1)	/* 9  bytes */
++	u8 board_pba_number[9];	/* abs.ofs: 119 */
++	u8 reserved5[8];
++#define EEPROM_VERSION                      (2*0x44)	/* 2  bytes */
++	u16 version;		/* abs.ofs: 136 */
++#define EEPROM_SKU_CAP                      (2*0x45)	/* 1  bytes */
++	u8 sku_cap;		/* abs.ofs: 138 */
++#define EEPROM_LEDS_MODE                    (2*0x45+1)	/* 1  bytes */
++	u8 leds_mode;		/* abs.ofs: 139 */
++#define EEPROM_OEM_MODE                     (2*0x46)	/* 2  bytes */
++	u16 oem_mode;
++#define EEPROM_WOWLAN_MODE                  (2*0x47)	/* 2  bytes */
++	u16 wowlan_mode;	/* abs.ofs: 142 */
++#define EEPROM_LEDS_TIME_INTERVAL           (2*0x48)	/* 2  bytes */
++	u16 leds_time_interval;	/* abs.ofs: 144 */
++#define EEPROM_LEDS_OFF_TIME                (2*0x49)	/* 1  bytes */
++	u8 leds_off_time;	/* abs.ofs: 146 */
++#define EEPROM_LEDS_ON_TIME                 (2*0x49+1)	/* 1  bytes */
++	u8 leds_on_time;	/* abs.ofs: 147 */
++#define EEPROM_ALMGOR_M_VERSION             (2*0x4A)	/* 1  bytes */
++	u8 almgor_m_version;	/* abs.ofs: 148 */
++#define EEPROM_ANTENNA_SWITCH_TYPE          (2*0x4A+1)	/* 1  bytes */
++	u8 antenna_switch_type;	/* abs.ofs: 149 */
++#if IWL == 3945
++	u8 reserved6[42];
++#else
++	u8 reserved6[8];
++#define EEPROM_4965_BOARD_REVISION          (2*0x4F)	/* 2 bytes */
++	u16 board_revision_4965;	/* abs.ofs: 158 */
++	u8 reserved7[13];
++#define EEPROM_4965_BOARD_PBA               (2*0x56+1)	/* 9 bytes */
++	u8 board_pba_number_4965[9];	/* abs.ofs: 173 */
++	u8 reserved8[10];
++#endif
++#define EEPROM_REGULATORY_SKU_ID            (2*0x60)	/* 4  bytes */
++	u8 sku_id[4];		/* abs.ofs: 192 */
++#define EEPROM_REGULATORY_BAND_1            (2*0x62)	/* 2  bytes */
++	u16 band_1_count;	/* abs.ofs: 196 */
++#define EEPROM_REGULATORY_BAND_1_CHANNELS   (2*0x63)	/* 28 bytes */
++	struct iwl_eeprom_channel band_1_channels[14];	/* abs.ofs: 196 */
++#define EEPROM_REGULATORY_BAND_2            (2*0x71)	/* 2  bytes */
++	u16 band_2_count;	/* abs.ofs: 226 */
++#define EEPROM_REGULATORY_BAND_2_CHANNELS   (2*0x72)	/* 26 bytes */
++	struct iwl_eeprom_channel band_2_channels[13];	/* abs.ofs: 228 */
++#define EEPROM_REGULATORY_BAND_3            (2*0x7F)	/* 2  bytes */
++	u16 band_3_count;	/* abs.ofs: 254 */
++#define EEPROM_REGULATORY_BAND_3_CHANNELS   (2*0x80)	/* 24 bytes */
++	struct iwl_eeprom_channel band_3_channels[12];	/* abs.ofs: 256 */
++#define EEPROM_REGULATORY_BAND_4            (2*0x8C)	/* 2  bytes */
++	u16 band_4_count;	/* abs.ofs: 280 */
++#define EEPROM_REGULATORY_BAND_4_CHANNELS   (2*0x8D)	/* 22 bytes */
++	struct iwl_eeprom_channel band_4_channels[11];	/* abs.ofs: 282 */
++#define EEPROM_REGULATORY_BAND_5            (2*0x98)	/* 2  bytes */
++	u16 band_5_count;	/* abs.ofs: 304 */
++#define EEPROM_REGULATORY_BAND_5_CHANNELS   (2*0x99)	/* 12 bytes */
++	struct iwl_eeprom_channel band_5_channels[6];	/* abs.ofs: 306 */
++
++/* From here on out the EEPROM diverges between the 4965 and the 3945 */
++#if IWL == 3945
++
++	u8 reserved9[194];
++
++#define EEPROM_TXPOWER_CALIB_GROUP0 0x200
++#define EEPROM_TXPOWER_CALIB_GROUP1 0x240
++#define EEPROM_TXPOWER_CALIB_GROUP2 0x280
++#define EEPROM_TXPOWER_CALIB_GROUP3 0x2c0
++#define EEPROM_TXPOWER_CALIB_GROUP4 0x300
++#define IWL_NUM_TX_CALIB_GROUPS 5
++	struct iwl_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
++/* abs.ofs: 512 */
++#define EEPROM_CALIB_TEMPERATURE_CORRECT 0x340
++	struct iwl_eeprom_temperature_corr corrections;	/* abs.ofs: 832 */
++	u8 reserved16[172];	/* fill out to full 1024 byte block */
++
++/* 4965AGN adds fat channel support */
++#elif IWL == 4965
++
++	u8 reserved10[2];
++#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0)	/* 14 bytes */
++	struct iwl_eeprom_channel band_24_channels[7];	/* abs.ofs: 320 */
++	u8 reserved11[2];
++#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8)	/* 22 bytes */
++	struct iwl_eeprom_channel band_52_channels[11];	/* abs.ofs: 336 */
++	u8 reserved12[6];
++#define EEPROM_CALIB_VERSION_OFFSET            (2*0xB6)	/* 2 bytes */
++	u16 calib_version;	/* abs.ofs: 364 */
++	u8 reserved13[2];
++#define EEPROM_SATURATION_POWER_OFFSET         (2*0xB8)	/* 2 bytes */
++	u16 satruation_power;	/* abs.ofs: 368 */
++	u8 reserved14[94];
++#define EEPROM_IWL_CALIB_TXPOWER_OFFSET        (2*0xE8)	/* 48  bytes */
++	struct iwl_eeprom_calib_info calib_info;	/* abs.ofs: 464 */
++
++	u8 reserved16[140];	/* fill out to full 1024 byte block */
++
++#endif
++
++} __attribute__ ((packed));
++
++#define IWL_EEPROM_IMAGE_SIZE 1024
++
++#endif
+diff --git a/drivers/net/wireless/iwl-helpers.h b/drivers/net/wireless/iwl-helpers.h
+new file mode 100644
+index 0000000..e2a8d95
+--- /dev/null
++++ b/drivers/net/wireless/iwl-helpers.h
+@@ -0,0 +1,255 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project, as well
++ * as portions of the ieee80211 subsystem header files.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef __iwl_helpers_h__
++#define __iwl_helpers_h__
++
++#include <linux/ctype.h>
++
++/*
++ * The structures defined by the hardware/uCode interface
++ * have bit-wise operations.  For each bit-field there is
++ * a data symbol in the structure, the start bit position
++ * and the length of the bit-field.
++ *
++ * iwl_get_bits and iwl_set_bits will return or set the
++ * appropriate bits on a 32-bit value.
++ *
++ * IWL_GET_BITS and IWL_SET_BITS use symbol expansion to
++ * expand out to the appropriate call to iwl_get_bits
++ * and iwl_set_bits without having to reference all of the
++ * numerical constants and defines provided in the hardware
++ * definition
++ */
++
++/**
++ * iwl_get_bits - Extract a hardware bit-field value
++ * @src: source hardware value (__le32)
++ * @pos: bit-position (0-based) of first bit of value
++ * @len: length of bit-field
++ *
++ * iwl_get_bits will return the bit-field in cpu endian ordering.
++ *
++ * NOTE:  If used from IWL_GET_BITS then pos and len are compile-constants and
++ *        will collapse to minimal code by the compiler.
++ */
++static inline u32 iwl_get_bits(__le32 src, u8 pos, u8 len)
++{
++	u32 tmp = le32_to_cpu(src);
++
++	tmp >>= pos;
++	tmp &= (1UL << len) - 1;
++	return tmp;
++}
++
++/**
++ * iwl_set_bits - Set a hardware bit-field value
++ * @dst: Address of __le32 hardware value
++ * @pos: bit-position (0-based) of first bit of value
++ * @len: length of bit-field
++ * @val: cpu endian value to encode into the bit-field
++ *
++ * iwl_set_bits will encode val into dst, masked to be len bits long at bit
++ * position pos.
++ *
++ * NOTE:  If used IWL_SET_BITS pos and len will be compile-constants and
++ *        will collapse to minimal code by the compiler.
++ */
++static inline void iwl_set_bits(__le32 *dst, u8 pos, u8 len, int val)
++{
++	u32 tmp = le32_to_cpu(*dst);
++
++	tmp &= ~(((1UL << len) - 1) << pos);
++	tmp |= (val & ((1UL << len) - 1)) << pos;
++	*dst = cpu_to_le32(tmp);
++}
++
++static inline void iwl_set_bits16(__le16 *dst, u8 pos, u8 len, int val)
++{
++	u16 tmp = le16_to_cpu(*dst);
++
++	tmp &= ~((1UL << (pos + len)) - (1UL << pos));
++	tmp |= (val & ((1UL << len) - 1)) << pos;
++	*dst = cpu_to_le16(tmp);
++}
++
++/*
++ * The bit-field definitions in iwl-xxxx-hw.h are in the form of:
++ *
++ * struct example {
++ *         __le32 val1;
++ * #define IWL_name_POS 8
++ * #define IWL_name_LEN 4
++ * #define IWL_name_SYM val1
++ * };
++ *
++ * The IWL_SET_BITS and IWL_GET_BITS macros are provided to allow the driver
++ * to call:
++ *
++ * struct example bar;
++ * u32 val = IWL_GET_BITS(bar, name);
++ * val = val * 2;
++ * IWL_SET_BITS(bar, name, val);
++ *
++ * All cpu / host ordering, masking, and shifts are performed by the macros
++ * and iwl_{get,set}_bits.
++ *
++ */
++#define IWL_SET_BITS(s, sym, v) \
++	iwl_set_bits(&(s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
++		     IWL_ ## sym ## _LEN, (v))
++
++#define IWL_SET_BITS16(s, sym, v) \
++	iwl_set_bits16(&(s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
++		       IWL_ ## sym ## _LEN, (v))
++
++#define IWL_GET_BITS(s, sym) \
++	iwl_get_bits((s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
++		      IWL_ ## sym ## _LEN)
++
++
++#define KELVIN_TO_CELSIUS(x) ((x)-273)
++#define CELSIUS_TO_KELVIN(x) ((x)+273)
++
++#define IEEE80211_CHAN_W_RADAR_DETECT 0x00000010
++
++static inline struct ieee80211_conf *ieee80211_get_hw_conf(
++	struct ieee80211_hw *hw)
++{
++	return &hw->conf;
++}
++
++#define QOS_CONTROL_LEN 2
++
++#define IEEE80211_STYPE_BACK_REQ	0x0080
++#define IEEE80211_STYPE_BACK		0x0090
++
++
++static inline int ieee80211_is_management(u16 fc)
++{
++	return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT;
++}
++
++static inline int ieee80211_is_control(u16 fc)
++{
++	return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL;
++}
++
++static inline int ieee80211_is_data(u16 fc)
++{
++	return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA;
++}
++
++static inline int ieee80211_is_back_request(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ);
++}
++
++static inline int ieee80211_is_probe_response(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP);
++}
++
++static inline int ieee80211_is_probe_request(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_REQ);
++}
++
++static inline int ieee80211_is_beacon(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON);
++}
++
++static inline int ieee80211_is_atim(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ATIM);
++}
++
++static inline int ieee80211_is_assoc_request(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ);
++}
++
++static inline int ieee80211_is_assoc_response(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_RESP);
++}
++
++static inline int ieee80211_is_auth(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ);
++}
++
++static inline int ieee80211_is_deauth(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ);
++}
++
++static inline int ieee80211_is_disassoc(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ);
++}
++
++static inline int ieee80211_is_reassoc_request(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ);
++}
++
++static inline int ieee80211_is_reassoc_response(u16 fc)
++{
++	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
++	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_RESP);
++}
++
++static inline int iwl_check_bits(unsigned long field, unsigned long mask)
++{
++	return ((field & mask) == mask) ? 1 : 0;
++}
++
++static inline unsigned long elapsed_jiffies(unsigned long start,
++					    unsigned long end)
++{
++	if (end > start)
++		return end - start;
++
++	return end + (MAX_JIFFY_OFFSET - start);
++}
++
++#endif				/* __iwl_helpers_h__ */
+diff --git a/drivers/net/wireless/iwl-hw.h b/drivers/net/wireless/iwl-hw.h
+new file mode 100644
+index 0000000..b5ac994
+--- /dev/null
++++ b/drivers/net/wireless/iwl-hw.h
+@@ -0,0 +1,576 @@
++/******************************************************************************
++ *
++ * This file is provided under a dual BSD/GPLv2 license.  When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU Geeral Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ *  * Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ *  * Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *  * Neither the name Intel Corporation nor the names of its
++ *    contributors may be used to endorse or promote products derived
++ *    from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *****************************************************************************/
++
++#ifndef	__iwlwifi_hw_h__
++#define __iwlwifi_hw_h__
++
++/*
++ * This file defines hardware constants common to 3945 and 4965.
++ *
++ * Device-specific constants are defined in iwl-3945-hw.h and iwl-4965-hw.h,
++ * although this file contains a few definitions for which the .c
++ * implementation is the same for 3945 and 4965, except for the value of
++ * a constant.
++ *
++ * uCode API constants are defined in iwl-commands.h.
++ *
++ * NOTE:  DO NOT PUT OS IMPLEMENTATION-SPECIFIC DECLARATIONS HERE
++ *
++ * The iwl-*hw.h (and files they include) files should remain OS/driver
++ * implementation independent, declaring only the hardware interface.
++ */
++
++/* uCode queue management definitions */
++#define IWL_CMD_QUEUE_NUM       4
++#define IWL_CMD_FIFO_NUM        4
++#define IWL_BACK_QUEUE_FIRST_ID 7
++
++/* Tx rates */
++#define IWL_CCK_RATES 4
++#define IWL_OFDM_RATES 8
++
++#if IWL == 3945
++#define IWL_HT_RATES 0
++#elif IWL == 4965
++#define IWL_HT_RATES 16
++#endif
++
++#define IWL_MAX_RATES  (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES)
++
++/* Time constants */
++#define SHORT_SLOT_TIME 9
++#define LONG_SLOT_TIME 20
++
++/* RSSI to dBm */
++#if IWL == 3945
++#define IWL_RSSI_OFFSET	95
++#elif IWL == 4965
++#define IWL_RSSI_OFFSET	44
++#endif
++
++#include "iwl-eeprom.h"
++#include "iwl-commands.h"
++
++#define PCI_LINK_CTRL      0x0F0
++#define PCI_POWER_SOURCE   0x0C8
++#define PCI_REG_WUM8       0x0E8
++#define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT         (0x80000000)
++
++/*=== CSR (control and status registers) ===*/
++#define CSR_BASE    (0x000)
++
++#define CSR_SW_VER              (CSR_BASE+0x000)
++#define CSR_HW_IF_CONFIG_REG    (CSR_BASE+0x000) /* hardware interface config */
++#define CSR_INT_COALESCING      (CSR_BASE+0x004) /* accum ints, 32-usec units */
++#define CSR_INT                 (CSR_BASE+0x008) /* host interrupt status/ack */
++#define CSR_INT_MASK            (CSR_BASE+0x00c) /* host interrupt enable */
++#define CSR_FH_INT_STATUS       (CSR_BASE+0x010) /* busmaster int status/ack*/
++#define CSR_GPIO_IN             (CSR_BASE+0x018) /* read external chip pins */
++#define CSR_RESET               (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
++#define CSR_GP_CNTRL            (CSR_BASE+0x024)
++#define CSR_HW_REV              (CSR_BASE+0x028)
++#define CSR_EEPROM_REG          (CSR_BASE+0x02c)
++#define CSR_EEPROM_GP           (CSR_BASE+0x030)
++#define CSR_GP_UCODE		(CSR_BASE+0x044)
++#define CSR_UCODE_DRV_GP1       (CSR_BASE+0x054)
++#define CSR_UCODE_DRV_GP1_SET   (CSR_BASE+0x058)
++#define CSR_UCODE_DRV_GP1_CLR   (CSR_BASE+0x05c)
++#define CSR_UCODE_DRV_GP2       (CSR_BASE+0x060)
++#define CSR_LED_REG		(CSR_BASE+0x094)
++#define CSR_DRAM_INT_TBL_CTL	(CSR_BASE+0x0A0)
++#define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
++#define CSR_ANA_PLL_CFG         (CSR_BASE+0x20c)
++#define CSR_HW_REV_WA_REG	(CSR_BASE+0x22C)
++
++/* HW I/F configuration */
++#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB         (0x00000100)
++#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM         (0x00000200)
++#define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC            (0x00000400)
++#define CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE         (0x00000800)
++#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A    (0x00000000)
++#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B    (0x00001000)
++#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM     (0x00200000)
++
++/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
++ * acknowledged (reset) by host writing "1" to flagged bits. */
++#define CSR_INT_BIT_FH_RX        (1<<31) /* Rx DMA, cmd responses, FH_INT[17:16] */
++#define CSR_INT_BIT_HW_ERR       (1<<29) /* DMA hardware error FH_INT[31] */
++#define CSR_INT_BIT_DNLD         (1<<28) /* uCode Download */
++#define CSR_INT_BIT_FH_TX        (1<<27) /* Tx DMA FH_INT[1:0] */
++#define CSR_INT_BIT_MAC_CLK_ACTV (1<<26) /* NIC controller's clock toggled on/off */
++#define CSR_INT_BIT_SW_ERR       (1<<25) /* uCode error */
++#define CSR_INT_BIT_RF_KILL      (1<<7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
++#define CSR_INT_BIT_CT_KILL      (1<<6)  /* Critical temp (chip too hot) rfkill */
++#define CSR_INT_BIT_SW_RX        (1<<3)  /* Rx, command responses, 3945 */
++#define CSR_INT_BIT_WAKEUP       (1<<1)  /* NIC controller waking up (pwr mgmt) */
++#define CSR_INT_BIT_ALIVE        (1<<0)  /* uCode interrupts once it initializes */
++
++#define CSR_INI_SET_MASK	(CSR_INT_BIT_FH_RX   | \
++				 CSR_INT_BIT_HW_ERR  | \
++				 CSR_INT_BIT_FH_TX   | \
++				 CSR_INT_BIT_SW_ERR  | \
++				 CSR_INT_BIT_RF_KILL | \
++				 CSR_INT_BIT_SW_RX   | \
++				 CSR_INT_BIT_WAKEUP  | \
++				 CSR_INT_BIT_ALIVE)
++
++/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
++#define CSR_FH_INT_BIT_ERR       (1<<31) /* Error */
++#define CSR_FH_INT_BIT_HI_PRIOR  (1<<30) /* High priority Rx, bypass coalescing */
++#define CSR_FH_INT_BIT_RX_CHNL2  (1<<18) /* Rx channel 2 (3945 only) */
++#define CSR_FH_INT_BIT_RX_CHNL1  (1<<17) /* Rx channel 1 */
++#define CSR_FH_INT_BIT_RX_CHNL0  (1<<16) /* Rx channel 0 */
++#define CSR_FH_INT_BIT_TX_CHNL6  (1<<6)  /* Tx channel 6 (3945 only) */
++#define CSR_FH_INT_BIT_TX_CHNL1  (1<<1)  /* Tx channel 1 */
++#define CSR_FH_INT_BIT_TX_CHNL0  (1<<0)  /* Tx channel 0 */
++
++#define CSR_FH_INT_RX_MASK	(CSR_FH_INT_BIT_HI_PRIOR | \
++				 CSR_FH_INT_BIT_RX_CHNL2 | \
++				 CSR_FH_INT_BIT_RX_CHNL1 | \
++				 CSR_FH_INT_BIT_RX_CHNL0)
++
++#define CSR_FH_INT_TX_MASK	(CSR_FH_INT_BIT_TX_CHNL6 | \
++				 CSR_FH_INT_BIT_TX_CHNL1 | \
++				 CSR_FH_INT_BIT_TX_CHNL0 )
++
++
++/* RESET */
++#define CSR_RESET_REG_FLAG_NEVO_RESET                (0x00000001)
++#define CSR_RESET_REG_FLAG_FORCE_NMI                 (0x00000002)
++#define CSR_RESET_REG_FLAG_SW_RESET                  (0x00000080)
++#define CSR_RESET_REG_FLAG_MASTER_DISABLED           (0x00000100)
++#define CSR_RESET_REG_FLAG_STOP_MASTER               (0x00000200)
++
++/* GP (general purpose) CONTROL */
++#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY        (0x00000001)
++#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE              (0x00000004)
++#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ         (0x00000008)
++#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP         (0x00000010)
++
++#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN           (0x00000001)
++
++#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE         (0x07000000)
++#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE         (0x04000000)
++#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW          (0x08000000)
++
++
++/* EEPROM REG */
++#define CSR_EEPROM_REG_READ_VALID_MSK	(0x00000001)
++#define CSR_EEPROM_REG_BIT_CMD		(0x00000002)
++
++/* EEPROM GP */
++#define CSR_EEPROM_GP_VALID_MSK		(0x00000006)
++#define CSR_EEPROM_GP_BAD_SIGNATURE	(0x00000000)
++#define CSR_EEPROM_GP_IF_OWNER_MSK	(0x00000180)
++
++/* UCODE DRV GP */
++#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP             (0x00000001)
++#define CSR_UCODE_SW_BIT_RFKILL                     (0x00000002)
++#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED           (0x00000004)
++#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT      (0x00000008)
++
++/* GPIO */
++#define CSR_GPIO_IN_BIT_AUX_POWER                   (0x00000200)
++#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC                (0x00000000)
++#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC		CSR_GPIO_IN_BIT_AUX_POWER
++
++/* GI Chicken Bits */
++#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)
++#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)
++
++/* CSR_ANA_PLL_CFG */
++#define CSR_ANA_PLL_CFG_SH		(0x00880300)
++
++#define CSR_LED_REG_TRUN_ON		(0x00000078)
++#define CSR_LED_REG_TRUN_OFF		(0x00000038)
++#define CSR_LED_BSM_CTRL_MSK		(0xFFFFFFDF)
++
++/* DRAM_INT_TBL_CTRL */
++#define CSR_DRAM_INT_TBL_CTRL_EN	(1<<31)
++#define CSR_DRAM_INT_TBL_CTRL_WRAP_CHK	(1<<27)
++
++/*=== HBUS (Host-side Bus) ===*/
++#define HBUS_BASE	(0x400)
++
++#define HBUS_TARG_MEM_RADDR     (HBUS_BASE+0x00c)
++#define HBUS_TARG_MEM_WADDR     (HBUS_BASE+0x010)
++#define HBUS_TARG_MEM_WDAT      (HBUS_BASE+0x018)
++#define HBUS_TARG_MEM_RDAT      (HBUS_BASE+0x01c)
++#define HBUS_TARG_PRPH_WADDR    (HBUS_BASE+0x044)
++#define HBUS_TARG_PRPH_RADDR    (HBUS_BASE+0x048)
++#define HBUS_TARG_PRPH_WDAT     (HBUS_BASE+0x04c)
++#define HBUS_TARG_PRPH_RDAT     (HBUS_BASE+0x050)
++#define HBUS_TARG_WRPTR         (HBUS_BASE+0x060)
++
++#define HBUS_TARG_MBX_C         (HBUS_BASE+0x030)
++
++
++/* SCD (Scheduler) */
++#define SCD_BASE                        (CSR_BASE + 0x2E00)
++
++#define SCD_MODE_REG                    (SCD_BASE + 0x000)
++#define SCD_ARASTAT_REG                 (SCD_BASE + 0x004)
++#define SCD_TXFACT_REG                  (SCD_BASE + 0x010)
++#define SCD_TXF4MF_REG                  (SCD_BASE + 0x014)
++#define SCD_TXF5MF_REG                  (SCD_BASE + 0x020)
++#define SCD_SBYP_MODE_1_REG             (SCD_BASE + 0x02C)
++#define SCD_SBYP_MODE_2_REG             (SCD_BASE + 0x030)
++
++/*=== FH (data Flow Handler) ===*/
++#define FH_BASE     (0x800)
++
++#define FH_CBCC_TABLE           (FH_BASE+0x140)
++#define FH_TFDB_TABLE           (FH_BASE+0x180)
++#define FH_RCSR_TABLE           (FH_BASE+0x400)
++#define FH_RSSR_TABLE           (FH_BASE+0x4c0)
++#define FH_TCSR_TABLE           (FH_BASE+0x500)
++#define FH_TSSR_TABLE           (FH_BASE+0x680)
++
++/* TFDB (Transmit Frame Buffer Descriptor) */
++#define FH_TFDB(_channel, buf) \
++	(FH_TFDB_TABLE+((_channel)*2+(buf))*0x28)
++#define ALM_FH_TFDB_CHNL_BUF_CTRL_REG(_channel) \
++	(FH_TFDB_TABLE + 0x50 * _channel)
++/* CBCC _channel is [0,2] */
++#define FH_CBCC(_channel)           (FH_CBCC_TABLE+(_channel)*0x8)
++#define FH_CBCC_CTRL(_channel)      (FH_CBCC(_channel)+0x00)
++#define FH_CBCC_BASE(_channel)      (FH_CBCC(_channel)+0x04)
++
++/* RCSR _channel is [0,2] */
++#define FH_RCSR(_channel)           (FH_RCSR_TABLE+(_channel)*0x40)
++#define FH_RCSR_CONFIG(_channel)    (FH_RCSR(_channel)+0x00)
++#define FH_RCSR_RBD_BASE(_channel)  (FH_RCSR(_channel)+0x04)
++#define FH_RCSR_WPTR(_channel)      (FH_RCSR(_channel)+0x20)
++#define FH_RCSR_RPTR_ADDR(_channel) (FH_RCSR(_channel)+0x24)
++
++#if IWL == 3945
++#define FH_RSCSR_CHNL0_WPTR        (FH_RCSR_WPTR(0))
++#elif IWL == 4965
++#define FH_RSCSR_CHNL0_WPTR        (FH_RSCSR_CHNL0_RBDCB_WPTR_REG)
++#endif
++
++/* RSSR */
++#define FH_RSSR_CTRL            (FH_RSSR_TABLE+0x000)
++#define FH_RSSR_STATUS          (FH_RSSR_TABLE+0x004)
++/* TCSR */
++#define FH_TCSR(_channel)           (FH_TCSR_TABLE+(_channel)*0x20)
++#define FH_TCSR_CONFIG(_channel)    (FH_TCSR(_channel)+0x00)
++#define FH_TCSR_CREDIT(_channel)    (FH_TCSR(_channel)+0x04)
++#define FH_TCSR_BUFF_STTS(_channel) (FH_TCSR(_channel)+0x08)
++/* TSSR */
++#define FH_TSSR_CBB_BASE        (FH_TSSR_TABLE+0x000)
++#define FH_TSSR_MSG_CONFIG      (FH_TSSR_TABLE+0x008)
++#define FH_TSSR_TX_STATUS       (FH_TSSR_TABLE+0x010)
++/* 18 - reserved */
++
++/* card static random access memory (SRAM) for processor data and instructs */
++#define RTC_INST_LOWER_BOUND			(0x000000)
++#define RTC_DATA_LOWER_BOUND			(0x800000)
++
++
++/* DBM */
++
++#define ALM_FH_SRVC_CHNL                            (6)
++
++#define ALM_FH_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE     (20)
++#define ALM_FH_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH      (4)
++
++#define ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN    (0x08000000)
++
++#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE        (0x80000000)
++
++#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE           (0x20000000)
++
++#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128         (0x01000000)
++
++#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST         (0x00001000)
++
++#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH               (0x00000000)
++
++#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF              (0x00000000)
++#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER           (0x00000001)
++
++#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL    (0x00000000)
++#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL     (0x00000008)
++
++#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD           (0x00200000)
++
++#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT            (0x00000000)
++
++#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE            (0x00000000)
++#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE           (0x80000000)
++
++#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID          (0x00004000)
++
++#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR           (0x00000001)
++
++#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON      (0xFF000000)
++#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON      (0x00FF0000)
++
++#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B    (0x00000400)
++
++#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON       (0x00000100)
++#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON       (0x00000080)
++
++#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH     (0x00000020)
++#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH           (0x00000005)
++
++#define ALM_TB_MAX_BYTES_COUNT      (0xFFF0)
++
++#define ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) \
++	((1LU << _channel) << 24)
++#define ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel) \
++	((1LU << _channel) << 16)
++
++#define ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_channel) \
++	(ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) | \
++	 ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel))
++#define PCI_CFG_REV_ID_BIT_BASIC_SKU                (0x40)	/* bit 6    */
++#define PCI_CFG_REV_ID_BIT_RTP                      (0x80)	/* bit 7    */
++
++#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED         (0x00000004)
++
++#define TFD_QUEUE_MIN           0
++#define TFD_QUEUE_MAX           6
++#define TFD_QUEUE_SIZE_MAX      (256)
++
++/* spectrum and channel data structures */
++#define IWL_NUM_SCAN_RATES         (2)
++
++#define IWL_SCAN_FLAG_24GHZ  (1<<0)
++#define IWL_SCAN_FLAG_52GHZ  (1<<1)
++#define IWL_SCAN_FLAG_ACTIVE (1<<2)
++#define IWL_SCAN_FLAG_DIRECT (1<<3)
++
++#define IWL_MAX_CMD_SIZE 1024
++
++/* LEDs mode */
++
++#define IWL_DEFAULT_TX_RETRY  15
++#define IWL_MAX_TX_RETRY      16
++
++/*********************************************/
++
++#define RFD_SIZE                              4
++#define NUM_TFD_CHUNKS                        4
++
++#define RX_QUEUE_SIZE                         256
++#define RX_QUEUE_MASK                         255
++#define RX_QUEUE_SIZE_LOG                     8
++
++/*
++ * TX Queue Flag Definitions
++ */
++
++/* abort attempt if mgmt frame is rx'd */
++
++/* require CTS */
++
++/* use short preamble */
++#define DCT_FLAG_LONG_PREAMBLE             0x00
++#define DCT_FLAG_SHORT_PREAMBLE            0x04
++
++/* RTS/CTS first */
++
++/* don't calculate duration field */
++
++/* even if MAC WEP set (allows pre-encrypt) */
++#define IWL_
++/* overwrite TSF field */
++
++/* ACK rx is expected to follow */
++#define DCT_FLAG_ACK_REQD                  0x80
++
++#define IWL_MB_DISASSOCIATE_THRESHOLD_DEFAULT           24
++#define IWL_MB_ROAMING_THRESHOLD_DEFAULT                8
++#define IWL_REAL_RATE_RX_PACKET_THRESHOLD               300
++
++/* QoS  definitions */
++
++#define CW_MIN_OFDM          15
++#define CW_MAX_OFDM          1023
++#define CW_MIN_CCK           31
++#define CW_MAX_CCK           1023
++
++#define QOS_TX0_CW_MIN_OFDM      CW_MIN_OFDM
++#define QOS_TX1_CW_MIN_OFDM      CW_MIN_OFDM
++#define QOS_TX2_CW_MIN_OFDM      ((CW_MIN_OFDM + 1) / 2 - 1)
++#define QOS_TX3_CW_MIN_OFDM      ((CW_MIN_OFDM + 1) / 4 - 1)
++
++#define QOS_TX0_CW_MIN_CCK       CW_MIN_CCK
++#define QOS_TX1_CW_MIN_CCK       CW_MIN_CCK
++#define QOS_TX2_CW_MIN_CCK       ((CW_MIN_CCK + 1) / 2 - 1)
++#define QOS_TX3_CW_MIN_CCK       ((CW_MIN_CCK + 1) / 4 - 1)
++
++#define QOS_TX0_CW_MAX_OFDM      CW_MAX_OFDM
++#define QOS_TX1_CW_MAX_OFDM      CW_MAX_OFDM
++#define QOS_TX2_CW_MAX_OFDM      CW_MIN_OFDM
++#define QOS_TX3_CW_MAX_OFDM      ((CW_MIN_OFDM + 1) / 2 - 1)
++
++#define QOS_TX0_CW_MAX_CCK       CW_MAX_CCK
++#define QOS_TX1_CW_MAX_CCK       CW_MAX_CCK
++#define QOS_TX2_CW_MAX_CCK       CW_MIN_CCK
++#define QOS_TX3_CW_MAX_CCK       ((CW_MIN_CCK + 1) / 2 - 1)
++
++#define QOS_TX0_AIFS            3
++#define QOS_TX1_AIFS            7
++#define QOS_TX2_AIFS            2
++#define QOS_TX3_AIFS            2
++
++#define QOS_TX0_ACM             0
++#define QOS_TX1_ACM             0
++#define QOS_TX2_ACM             0
++#define QOS_TX3_ACM             0
++
++#define QOS_TX0_TXOP_LIMIT_CCK          0
++#define QOS_TX1_TXOP_LIMIT_CCK          0
++#define QOS_TX2_TXOP_LIMIT_CCK          6016
++#define QOS_TX3_TXOP_LIMIT_CCK          3264
++
++#define QOS_TX0_TXOP_LIMIT_OFDM      0
++#define QOS_TX1_TXOP_LIMIT_OFDM      0
++#define QOS_TX2_TXOP_LIMIT_OFDM      3008
++#define QOS_TX3_TXOP_LIMIT_OFDM      1504
++
++#define DEF_TX0_CW_MIN_OFDM      CW_MIN_OFDM
++#define DEF_TX1_CW_MIN_OFDM      CW_MIN_OFDM
++#define DEF_TX2_CW_MIN_OFDM      CW_MIN_OFDM
++#define DEF_TX3_CW_MIN_OFDM      CW_MIN_OFDM
++
++#define DEF_TX0_CW_MIN_CCK       CW_MIN_CCK
++#define DEF_TX1_CW_MIN_CCK       CW_MIN_CCK
++#define DEF_TX2_CW_MIN_CCK       CW_MIN_CCK
++#define DEF_TX3_CW_MIN_CCK       CW_MIN_CCK
++
++#define DEF_TX0_CW_MAX_OFDM      CW_MAX_OFDM
++#define DEF_TX1_CW_MAX_OFDM      CW_MAX_OFDM
++#define DEF_TX2_CW_MAX_OFDM      CW_MAX_OFDM
++#define DEF_TX3_CW_MAX_OFDM      CW_MAX_OFDM
++
++#define DEF_TX0_CW_MAX_CCK       CW_MAX_CCK
++#define DEF_TX1_CW_MAX_CCK       CW_MAX_CCK
++#define DEF_TX2_CW_MAX_CCK       CW_MAX_CCK
++#define DEF_TX3_CW_MAX_CCK       CW_MAX_CCK
++
++#define DEF_TX0_AIFS            (2)
++#define DEF_TX1_AIFS            (2)
++#define DEF_TX2_AIFS            (2)
++#define DEF_TX3_AIFS            (2)
++
++#define DEF_TX0_ACM             0
++#define DEF_TX1_ACM             0
++#define DEF_TX2_ACM             0
++#define DEF_TX3_ACM             0
++
++#define DEF_TX0_TXOP_LIMIT_CCK        0
++#define DEF_TX1_TXOP_LIMIT_CCK        0
++#define DEF_TX2_TXOP_LIMIT_CCK        0
++#define DEF_TX3_TXOP_LIMIT_CCK        0
++
++#define DEF_TX0_TXOP_LIMIT_OFDM       0
++#define DEF_TX1_TXOP_LIMIT_OFDM       0
++#define DEF_TX2_TXOP_LIMIT_OFDM       0
++#define DEF_TX3_TXOP_LIMIT_OFDM       0
++
++#define QOS_QOS_SETS                  3
++#define QOS_PARAM_SET_ACTIVE          0
++#define QOS_PARAM_SET_DEF_CCK         1
++#define QOS_PARAM_SET_DEF_OFDM        2
++
++#define CTRL_QOS_NO_ACK               (0x0020)
++#define DCT_FLAG_EXT_QOS_ENABLED      (0x10)
++
++#define IWL_TX_QUEUE_AC0        0
++#define IWL_TX_QUEUE_AC1        1
++#define IWL_TX_QUEUE_AC2        2
++#define IWL_TX_QUEUE_AC3        3
++#define IWL_TX_QUEUE_HCCA_1     5
++#define IWL_TX_QUEUE_HCCA_2     6
++
++#define U32_PAD(n)		((4-(n))&0x3)
++
++#define AC_BE_TID_MASK 0x9	/* TID 0 and 3 */
++#define AC_BK_TID_MASK 0x6	/* TID 1 and 2 */
++
++/*
++ * Generic queue structure
++ *
++ * Contains common data for Rx and Tx queues
++ */
++#define TFD_CTL_COUNT_SET(n)       (n<<24)
++#define TFD_CTL_COUNT_GET(ctl)     ((ctl>>24) & 7)
++#define TFD_CTL_PAD_SET(n)         (n<<28)
++#define TFD_CTL_PAD_GET(ctl)       (ctl>>28)
++
++#define TFD_TX_CMD_SLOTS 256
++#define TFD_CMD_SLOTS 32
++
++#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \
++			      sizeof(struct iwl_cmd_meta))
++
++/*
++ * RX related structures and functions
++ */
++#define RX_FREE_BUFFERS 64
++#define RX_LOW_WATERMARK 8
++
++#endif				/* __iwlwifi_hw_h__ */
+diff --git a/drivers/net/wireless/iwl-io.h b/drivers/net/wireless/iwl-io.h
+new file mode 100644
+index 0000000..1ab5f54
+--- /dev/null
++++ b/drivers/net/wireless/iwl-io.h
+@@ -0,0 +1,470 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef __iwl_io_h__
++#define __iwl_io_h__
++
++#include <linux/io.h>
++
++#include "iwl-debug.h"
++
++/*
++ * IO, register, and NIC memory access functions
++ *
++ * NOTE on naming convention and macro usage for these
++ *
++ * A single _ prefix before a an access function means that no state
++ * check or debug information is printed when that function is called.
++ *
++ * A double __ prefix before an access function means that state is checked
++ * (in the case of *restricted calls) and the current line number is printed
++ * in addition to any other debug output.
++ *
++ * The non-prefixed name is the #define that maps the caller into a
++ * #define that provides the caller's __LINE__ to the double prefix version.
++ *
++ * If you wish to call the function without any debug or state checking,
++ * you should use the single _ prefix version (as is used by dependent IO
++ * routines, for example _iwl_read_restricted calls the non-check version of
++ * _iwl_read32.)
++ *
++ * These declarations are *extremely* useful in quickly isolating code deltas
++ * which result in misconfiguring of the hardware I/O.  In combination with
++ * git-bisect and the IO debug level you can quickly determine the specific
++ * commit which breaks the IO sequence to the hardware.
++ *
++ */
++
++#define _iwl_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs))
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *ipw,
++				 u32 ofs, u32 val)
++{
++	IWL_DEBUG_IO("write_direct32(0x%08X, 0x%08X) - %s %d\n",
++		     (u32) (ofs), (u32) (val), f, l);
++	_iwl_write32(ipw, ofs, val);
++}
++#define iwl_write32(ipw, ofs, val) \
++	__iwl_write32(__FILE__, __LINE__, ipw, ofs, val)
++#else
++#define iwl_write32(ipw, ofs, val) _iwl_write32(ipw, ofs, val)
++#endif
++
++#define _iwl_read32(ipw, ofs) readl((ipw)->hw_base + (ofs))
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *ipw, u32 ofs)
++{
++	IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
++	return _iwl_read32(ipw, ofs);
++}
++#define iwl_read32(ipw, ofs) __iwl_read32(__FILE__, __LINE__, ipw, ofs)
++#else
++#define iwl_read32(p, o) _iwl_read32(p, o)
++#endif
++
++static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr,
++				u32 bits, u32 mask, int timeout)
++{
++	int i = 0;
++
++	do {
++		if ((_iwl_read32(priv, addr) & mask) == (bits & mask))
++			return i;
++		mdelay(10);
++		i += 10;
++	} while (i < timeout);
++
++	return -ETIMEDOUT;
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline int __iwl_poll_bit(const char *f, u32 l,
++				 struct iwl_priv *priv, u32 addr,
++				 u32 bits, u32 mask, int timeout)
++{
++	int rc = _iwl_poll_bit(priv, addr, bits, mask, timeout);
++	if (unlikely(rc == -ETIMEDOUT))
++		IWL_DEBUG_IO
++		    ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
++		     addr, bits, mask, f, l);
++	else
++		IWL_DEBUG_IO
++		    ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
++		     addr, bits, mask, rc, f, l);
++	return rc;
++}
++#define iwl_poll_bit(ipw, addr, bits, mask, timeout) \
++	__iwl_poll_bit(__FILE__, __LINE__, ipw, addr, bits, mask, timeout)
++#else
++#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t)
++#endif
++
++static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
++{
++	_iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_set_bit(const char *f, u32 l,
++				 struct iwl_priv *priv, u32 reg, u32 mask)
++{
++	u32 val = _iwl_read32(priv, reg) | mask;
++	IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
++	_iwl_write32(priv, reg, val);
++}
++#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m)
++#else
++#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m)
++#endif
++
++static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
++{
++	_iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_clear_bit(const char *f, u32 l,
++				   struct iwl_priv *priv, u32 reg, u32 mask)
++{
++	u32 val = _iwl_read32(priv, reg) & ~mask;
++	IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
++	_iwl_write32(priv, reg, val);
++}
++#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m)
++#else
++#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m)
++#endif
++
++static inline int _iwl_grab_restricted_access(struct iwl_priv *priv)
++{
++	int rc;
++	u32 gp_ctl;
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (atomic_read(&priv->restrict_refcnt))
++		return 0;
++#endif
++	if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++	    test_bit(STATUS_RF_KILL_SW, &priv->status)) {
++		IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
++			"wakes up NIC\n");
++
++		/* 10 msec allows time for NIC to complete its data save */
++		gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL);
++		if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
++			IWL_DEBUG_RF_KILL("Wait for complete power-down, "
++				"gpctl = 0x%08x\n", gp_ctl);
++			mdelay(10);
++		} else
++			IWL_DEBUG_RF_KILL("power-down complete, "
++					  "gpctl = 0x%08x\n", gp_ctl);
++	}
++
++	/* this bit wakes up the NIC */
++	_iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++	rc = _iwl_poll_bit(priv, CSR_GP_CNTRL,
++			   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
++			   (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
++			    CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
++	if (rc < 0) {
++		IWL_ERROR("MAC is in deep sleep!\n");
++		return -EIO;
++	}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	atomic_inc(&priv->restrict_refcnt);
++#endif
++	return 0;
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline int __iwl_grab_restricted_access(const char *f, u32 l,
++					       struct iwl_priv *priv)
++{
++	if (atomic_read(&priv->restrict_refcnt))
++		IWL_DEBUG_INFO("Grabbing access while already held at "
++			       "line %d.\n", l);
++
++	IWL_DEBUG_IO("grabbing restricted access - %s %d\n", f, l);
++
++	return _iwl_grab_restricted_access(priv);
++}
++#define iwl_grab_restricted_access(priv) \
++	__iwl_grab_restricted_access(__FILE__, __LINE__, priv)
++#else
++#define iwl_grab_restricted_access(priv) \
++	_iwl_grab_restricted_access(priv)
++#endif
++
++static inline void _iwl_release_restricted_access(struct iwl_priv *priv)
++{
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (atomic_dec_and_test(&priv->restrict_refcnt))
++#endif
++		_iwl_clear_bit(priv, CSR_GP_CNTRL,
++			       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_release_restricted_access(const char *f, u32 l,
++						   struct iwl_priv *priv)
++{
++	if (atomic_read(&priv->restrict_refcnt) <= 0)
++		IWL_ERROR("Release unheld restricted access at line %d.\n", l);
++
++	IWL_DEBUG_IO("releasing restricted access - %s %d\n", f, l);
++	_iwl_release_restricted_access(priv);
++}
++#define iwl_release_restricted_access(priv) \
++	__iwl_release_restricted_access(__FILE__, __LINE__, priv)
++#else
++#define iwl_release_restricted_access(priv) \
++	_iwl_release_restricted_access(priv)
++#endif
++
++static inline u32 _iwl_read_restricted(struct iwl_priv *priv, u32 reg)
++{
++	return _iwl_read32(priv, reg);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline u32 __iwl_read_restricted(const char *f, u32 l,
++					struct iwl_priv *priv, u32 reg)
++{
++	u32 value = _iwl_read_restricted(priv, reg);
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Unrestricted access from %s %d\n", f, l);
++	IWL_DEBUG_IO("read_restricted(0x%4X) = 0x%08x - %s %d \n", reg, value,
++		     f, l);
++	return value;
++}
++#define iwl_read_restricted(priv, reg) \
++	__iwl_read_restricted(__FILE__, __LINE__, priv, reg)
++#else
++#define iwl_read_restricted _iwl_read_restricted
++#endif
++
++static inline void _iwl_write_restricted(struct iwl_priv *priv,
++					 u32 reg, u32 value)
++{
++	_iwl_write32(priv, reg, value);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static void __iwl_write_restricted(u32 line,
++				   struct iwl_priv *priv, u32 reg, u32 value)
++{
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Unrestricted access from line %d\n", line);
++	_iwl_write_restricted(priv, reg, value);
++}
++#define iwl_write_restricted(priv, reg, value) \
++	__iwl_write_restricted(__LINE__, priv, reg, value)
++#else
++#define iwl_write_restricted _iwl_write_restricted
++#endif
++
++static inline void iwl_write_buffer_restricted(struct iwl_priv *priv,
++					       u32 reg, u32 len, u32 *values)
++{
++	u32 count = sizeof(u32);
++
++	if ((priv != NULL) && (values != NULL)) {
++		for (; 0 < len; len -= count, reg += count, values++)
++			_iwl_write_restricted(priv, reg, *values);
++	}
++}
++
++static inline int _iwl_poll_restricted_bit(struct iwl_priv *priv,
++					   u32 addr, u32 mask, int timeout)
++{
++	int i = 0;
++
++	do {
++		if ((_iwl_read_restricted(priv, addr) & mask) == mask)
++			return i;
++		mdelay(10);
++		i += 10;
++	} while (i < timeout);
++
++	return -ETIMEDOUT;
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline int __iwl_poll_restricted_bit(const char *f, u32 l,
++					    struct iwl_priv *priv,
++					    u32 addr, u32 mask, int timeout)
++{
++	int rc = _iwl_poll_restricted_bit(priv, addr, mask, timeout);
++
++	if (unlikely(rc == -ETIMEDOUT))
++		IWL_DEBUG_IO("poll_restricted_bit(0x%08X, 0x%08X) - "
++			     "timedout - %s %d\n", addr, mask, f, l);
++	else
++		IWL_DEBUG_IO("poll_restricted_bit(0x%08X, 0x%08X) = 0x%08X "
++			     "- %s %d\n", addr, mask, rc, f, l);
++	return rc;
++}
++#define iwl_poll_restricted_bit(ipw, addr, mask, timeout) \
++	__iwl_poll_restricted_bit(__FILE__, __LINE__, ipw, addr, mask, timeout)
++#else
++#define iwl_poll_restricted_bit _iwl_poll_restricted_bit
++#endif
++
++static inline u32 _iwl_read_restricted_reg(struct iwl_priv *priv, u32 reg)
++{
++	_iwl_write_restricted(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
++	return _iwl_read_restricted(priv, HBUS_TARG_PRPH_RDAT);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline u32 __iwl_read_restricted_reg(u32 line,
++					    struct iwl_priv *priv, u32 reg)
++{
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Unrestricted access from line %d\n", line);
++	return _iwl_read_restricted_reg(priv, reg);
++}
++
++#define iwl_read_restricted_reg(priv, reg) \
++	__iwl_read_restricted_reg(__LINE__, priv, reg)
++#else
++#define iwl_read_restricted_reg _iwl_read_restricted_reg
++#endif
++
++static inline void _iwl_write_restricted_reg(struct iwl_priv *priv,
++					     u32 addr, u32 val)
++{
++	_iwl_write_restricted(priv, HBUS_TARG_PRPH_WADDR,
++			      ((addr & 0x0000FFFF) | (3 << 24)));
++	_iwl_write_restricted(priv, HBUS_TARG_PRPH_WDAT, val);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_write_restricted_reg(u32 line,
++					      struct iwl_priv *priv,
++					      u32 addr, u32 val)
++{
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Unrestricted access from line %d\n", line);
++	_iwl_write_restricted_reg(priv, addr, val);
++}
++
++#define iwl_write_restricted_reg(priv, addr, val) \
++	__iwl_write_restricted_reg(__LINE__, priv, addr, val);
++#else
++#define iwl_write_restricted_reg _iwl_write_restricted_reg
++#endif
++
++#define _iwl_set_bits_restricted_reg(priv, reg, mask) \
++	_iwl_write_restricted_reg(priv, reg, \
++				  (_iwl_read_restricted_reg(priv, reg) | mask))
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_set_bits_restricted_reg(u32 line, struct iwl_priv
++						 *priv, u32 reg, u32 mask)
++{
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Unrestricted access from line %d\n", line);
++	_iwl_set_bits_restricted_reg(priv, reg, mask);
++}
++#define iwl_set_bits_restricted_reg(priv, reg, mask) \
++	__iwl_set_bits_restricted_reg(__LINE__, priv, reg, mask)
++#else
++#define iwl_set_bits_restricted_reg _iwl_set_bits_restricted_reg
++#endif
++
++#define _iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask) \
++	_iwl_write_restricted_reg( \
++	    priv, reg, ((_iwl_read_restricted_reg(priv, reg) & mask) | bits))
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_set_bits_mask_restricted_reg(u32 line,
++		struct iwl_priv *priv, u32 reg, u32 bits, u32 mask)
++{
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Unrestricted access from line %d\n", line);
++	_iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask);
++}
++
++#define iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask) \
++	__iwl_set_bits_mask_restricted_reg(__LINE__, priv, reg, bits, mask)
++#else
++#define iwl_set_bits_mask_restricted_reg _iwl_set_bits_mask_restricted_reg
++#endif
++
++static inline void iwl_clear_bits_restricted_reg(struct iwl_priv
++						 *priv, u32 reg, u32 mask)
++{
++	u32 val = _iwl_read_restricted_reg(priv, reg);
++	_iwl_write_restricted_reg(priv, reg, (val & ~mask));
++}
++
++static inline u32 iwl_read_restricted_mem(struct iwl_priv *priv, u32 addr)
++{
++	iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR, addr);
++	return iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
++}
++
++static inline void iwl_write_restricted_mem(struct iwl_priv *priv, u32 addr,
++					    u32 val)
++{
++	iwl_write_restricted(priv, HBUS_TARG_MEM_WADDR, addr);
++	iwl_write_restricted(priv, HBUS_TARG_MEM_WDAT, val);
++}
++
++static inline void iwl_write_restricted_mems(struct iwl_priv *priv, u32 addr,
++					     u32 len, u32 *values)
++{
++	iwl_write_restricted(priv, HBUS_TARG_MEM_WADDR, addr);
++	for (; 0 < len; len -= sizeof(u32), values++)
++		iwl_write_restricted(priv, HBUS_TARG_MEM_WDAT, *values);
++}
++
++static inline void iwl_write_restricted_regs(struct iwl_priv *priv, u32 reg,
++					     u32 len, u8 *values)
++{
++	u32 reg_offset = reg;
++	u32 aligment = reg & 0x3;
++
++	/* write any non-dword-aligned stuff at the beginning */
++	if (len < sizeof(u32)) {
++		if ((aligment + len) <= sizeof(u32)) {
++			u8 size;
++			u32 value = 0;
++			size = len - 1;
++			memcpy(&value, values, len);
++			reg_offset = (reg_offset & 0x0000FFFF);
++
++			_iwl_write_restricted(priv,
++					      HBUS_TARG_PRPH_WADDR,
++					      (reg_offset | (size << 24)));
++			_iwl_write_restricted(priv, HBUS_TARG_PRPH_WDAT,
++					      value);
++		}
++
++		return;
++	}
++
++	/* now write all the dword-aligned stuff */
++	for (; reg_offset < (reg + len);
++	     reg_offset += sizeof(u32), values += sizeof(u32))
++		_iwl_write_restricted_reg(priv, reg_offset, *((u32 *) values));
++}
++
++#endif
+diff --git a/drivers/net/wireless/iwl-priv.h b/drivers/net/wireless/iwl-priv.h
+new file mode 100644
+index 0000000..ffd3d79
+--- /dev/null
++++ b/drivers/net/wireless/iwl-priv.h
+@@ -0,0 +1,308 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef __iwl_priv_h__
++#define __iwl_priv_h__
++
++#include <linux/workqueue.h>
++
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++
++enum {
++	MEASUREMENT_READY = (1 << 0),
++	MEASUREMENT_ACTIVE = (1 << 1),
++};
++
++#endif
++
++struct iwl_priv {
++
++	/* ieee device used by generic ieee processing code */
++	struct ieee80211_hw *hw;
++	struct ieee80211_channel *ieee_channels;
++	struct ieee80211_rate *ieee_rates;
++
++	/* temporary frame storage list */
++	struct list_head free_frames;
++	int frames_count;
++
++	u8 phymode;
++	int alloc_rxb_skb;
++
++	void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
++				       struct iwl_rx_mem_buffer *rxb);
++
++	const struct ieee80211_hw_mode *modes;
++
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++	/* spectrum measurement report caching */
++	struct iwl_spectrum_notification measure_report;
++	u8 measurement_status;
++#endif
++	/* ucode beacon time */
++	u32 ucode_beacon_time;
++
++	/* we allocate array of iwl_channel_info for NIC's valid channels.
++	 *    Access via channel # using indirect index array */
++	struct iwl_channel_info *channel_info;	/* channel info array */
++	u8 channel_count;	/* # of channels */
++
++	/* each calibration channel group in the EEPROM has a derived
++	 * clip setting for each rate. */
++	const struct iwl_clip_group clip_groups[5];
++
++	/* thermal calibration */
++	s32 temperature;	/* degrees Kelvin */
++	s32 last_temperature;
++
++	/* Scan related variables */
++	unsigned long last_scan_jiffies;
++	unsigned long scan_start;
++	unsigned long scan_pass_start;
++	unsigned long scan_start_tsf;
++	int scan_bands;
++	int one_direct_scan;
++	u8 direct_ssid_len;
++	u8 direct_ssid[IW_ESSID_MAX_SIZE];
++	struct iwl_scan_cmd *scan;
++	u8 only_active_channel;
++
++	/* spinlock */
++	spinlock_t lock;	/* protect general shared data */
++	spinlock_t hcmd_lock;	/* protect hcmd */
++	struct mutex mutex;
++
++	/* basic pci-network driver stuff */
++	struct pci_dev *pci_dev;
++
++	/* pci hardware address support */
++	void __iomem *hw_base;
++
++	/* uCode images, save to reload in case of failure */
++	struct fw_image_desc ucode_code;	/* runtime inst */
++	struct fw_image_desc ucode_data;	/* runtime data original */
++	struct fw_image_desc ucode_data_backup;	/* runtime data save/restore */
++	struct fw_image_desc ucode_init;	/* initialization inst */
++	struct fw_image_desc ucode_init_data;	/* initialization data */
++	struct fw_image_desc ucode_boot;	/* bootstrap inst */
++
++
++	struct iwl_rxon_time_cmd rxon_timing;
++
++	/* We declare this const so it can only be
++	 * changed via explicit cast within the
++	 * routines that actually update the physical
++	 * hardware */
++	const struct iwl_rxon_cmd active_rxon;
++	struct iwl_rxon_cmd staging_rxon;
++
++	int error_recovering;
++	struct iwl_rxon_cmd recovery_rxon;
++
++	/* 1st responses from initialize and runtime uCode images.
++	 * 4965's initialize alive response contains some calibration data. */
++	struct iwl_init_alive_resp card_alive_init;
++	struct iwl_alive_resp card_alive;
++
++#ifdef LED
++	/* LED related variables */
++	struct iwl_activity_blink activity;
++	unsigned long led_packets;
++	int led_state;
++#endif
++
++	u16 active_rate;
++	u16 active_rate_basic;
++
++	u8 call_post_assoc_from_beacon;
++	u8 assoc_station_added;
++#if IWL == 4965
++	u8 use_ant_b_for_management_frame;	/* Tx antenna selection */
++	/* HT variables */
++	u8 is_dup;
++	u8 is_ht_enabled;
++	u8 channel_width;	/* 0=20MHZ, 1=40MHZ */
++	u8 current_channel_width;
++	u8 valid_antenna;	/* Bit mask of antennas actually connected */
++#ifdef CONFIG_IWLWIFI_SENSITIVITY
++	struct iwl_sensitivity_data sensitivity_data;
++	struct iwl_chain_noise_data chain_noise_data;
++	u8 start_calib;
++	__le16 sensitivity_tbl[HD_TABLE_SIZE];
++#endif /*CONFIG_IWLWIFI_SENSITIVITY*/
++
++#ifdef CONFIG_IWLWIFI_HT
++	struct sta_ht_info current_assoc_ht;
++#endif
++	u8 active_rate_ht[2];
++	u8 last_phy_res[100];
++
++	/* Rate scaling data */
++	struct iwl_lq_mngr lq_mngr;
++#endif
++
++	/* Rate scaling data */
++	s8 data_retry_limit;
++	u8 retry_rate;
++
++	wait_queue_head_t wait_command_queue;
++
++	int activity_timer_active;
++
++	/* Rx and Tx DMA processing queues */
++	struct iwl_rx_queue rxq;
++	struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES];
++#if IWL == 4965
++	unsigned long txq_ctx_active_msk;
++	struct iwl_kw kw;	/* keep warm address */
++	u32 scd_base_addr;	/* scheduler sram base address */
++#endif
++
++	unsigned long status;
++	u32 config;
++
++	int last_rx_rssi;	/* From Rx packet statisitics */
++	int last_rx_noise;	/* From beacon statistics */
++
++	struct iwl_power_mgr power_data;
++
++	struct iwl_notif_statistics statistics;
++	unsigned long last_statistics_time;
++
++	/* context information */
++	u8 essid[IW_ESSID_MAX_SIZE];
++	u8 essid_len;
++	u16 rates_mask;
++
++	u32 power_mode;
++	u32 antenna;
++	u8 bssid[ETH_ALEN];
++	u16 rts_threshold;
++	u8 mac_addr[ETH_ALEN];
++
++	/*station table variables */
++	spinlock_t sta_lock;
++	u8 num_stations;
++	struct iwl_station_entry stations[IWL_STATION_COUNT];
++
++	/* Indication if ieee80211_ops->open has been called */
++	int is_open;
++
++	u8 mac80211_registered;
++	int is_abg;
++
++	u32 notif_missed_beacons;
++
++	/* Rx'd packet timing information */
++	u32 last_beacon_time;
++	u64 last_tsf;
++
++	/* Duplicate packet detection */
++	u16 last_seq_num;
++	u16 last_frag_num;
++	unsigned long last_packet_time;
++	struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE];
++
++	/* eeprom */
++	struct iwl_eeprom eeprom;
++
++	int iw_mode;
++
++	struct sk_buff *ibss_beacon;
++
++	/* Last Rx'd beacon timestamp */
++	u32 timestamp0;
++	u32 timestamp1;
++	u16 beacon_int;
++	struct iwl_driver_hw_info hw_setting;
++	int interface_id;
++
++	/* Current association information needed to configure the
++	 * hardware */
++	u16 assoc_id;
++	u16 assoc_capability;
++	u8 ps_mode;
++
++#ifdef CONFIG_IWLWIFI_QOS
++	struct iwl_qos_info qos_data;
++#endif /*CONFIG_IWLWIFI_QOS */
++
++	struct workqueue_struct *workqueue;
++
++	struct work_struct up;
++	struct work_struct restart;
++	struct work_struct calibrated_work;
++	struct work_struct scan_completed;
++	struct work_struct rx_replenish;
++	struct work_struct rf_kill;
++	struct work_struct abort_scan;
++	struct work_struct update_link_led;
++	struct work_struct auth_work;
++	struct work_struct report_work;
++	struct work_struct request_scan;
++	struct work_struct beacon_update;
++
++	struct tasklet_struct irq_tasklet;
++
++	struct delayed_work init_alive_start;
++	struct delayed_work alive_start;
++	struct delayed_work activity_timer;
++	struct delayed_work thermal_periodic;
++	struct delayed_work gather_stats;
++	struct delayed_work scan_check;
++	struct delayed_work post_associate;
++
++#define IWL_DEFAULT_TX_POWER 0x0F
++	s8 user_txpower_limit;
++	s8 max_channel_txpower_limit;
++	u32 cck_power_index_compensation;
++
++#ifdef CONFIG_PM
++	u32 pm_state[16];
++#endif
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	/* debugging info */
++	u32 framecnt_to_us;
++	atomic_t restrict_refcnt;
++#endif
++
++#if IWL == 4965
++	struct work_struct txpower_work;
++#ifdef CONFIG_IWLWIFI_SENSITIVITY
++	struct work_struct sensitivity_work;
++#endif
++	struct work_struct statistics_work;
++	struct timer_list statistics_periodic;
++
++#ifdef CONFIG_IWLWIFI_HT_AGG
++	struct work_struct agg_work;
++#endif
++
++#endif /* 4965 */
++};				/*iwl_priv */
++
++#endif /* __iwl_priv_h__ */
+diff --git a/drivers/net/wireless/iwl-prph.h b/drivers/net/wireless/iwl-prph.h
+new file mode 100644
+index 0000000..0df4114
+--- /dev/null
++++ b/drivers/net/wireless/iwl-prph.h
+@@ -0,0 +1,229 @@
++/******************************************************************************
++ *
++ * This file is provided under a dual BSD/GPLv2 license.  When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU Geeral Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ *  * Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ *  * Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *  * Neither the name Intel Corporation nor the names of its
++ *    contributors may be used to endorse or promote products derived
++ *    from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *****************************************************************************/
++
++#ifndef	__iwl_prph_h__
++#define __iwl_prph_h__
++
++
++#define PRPH_BASE	(0x00000)
++#define PRPH_END	(0xFFFFF)
++
++/* APMG (power management) constants */
++#define APMG_BASE			(PRPH_BASE + 0x3000)
++#define APMG_CLK_CTRL_REG		(APMG_BASE + 0x0000)
++#define APMG_CLK_EN_REG			(APMG_BASE + 0x0004)
++#define APMG_CLK_DIS_REG		(APMG_BASE + 0x0008)
++#define APMG_PS_CTRL_REG		(APMG_BASE + 0x000c)
++#define APMG_PCIDEV_STT_REG		(APMG_BASE + 0x0010)
++#define APMG_RFKILL_REG			(APMG_BASE + 0x0014)
++#define APMG_RTC_INT_STT_REG		(APMG_BASE + 0x001c)
++#define APMG_RTC_INT_MSK_REG		(APMG_BASE + 0x0020)
++
++#define APMG_CLK_VAL_DMA_CLK_RQT	(0x00000200)
++#define APMG_CLK_VAL_BSM_CLK_RQT	(0x00000800)
++
++#define APMG_PS_CTRL_VAL_RESET_REQ	(0x04000000)
++
++#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS	(0x00000800)
++
++#define APMG_PS_CTRL_MSK_PWR_SRC              (0x03000000)
++#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN        (0x00000000)
++#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX         (0x01000000)
++
++
++/**
++ * BSM (Bootstrap State Machine)
++ *
++ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
++ * in special SRAM that does not power down when the embedded control
++ * processor is sleeping (e.g. for periodic power-saving shutdowns of radio).
++ *
++ * When powering back up after sleeps (or during initial uCode load), the BSM
++ * internally loads the short bootstrap program from the special SRAM into the
++ * embedded processor's instruction SRAM, and starts the processor so it runs
++ * the bootstrap program.
++ *
++ * This bootstrap program loads (via PCI busmaster DMA) instructions and data
++ * images for a uCode program from host DRAM locations.  The host driver
++ * indicates DRAM locations and sizes for instruction and data images via the
++ * four BSM_DRAM_* registers.  Once the bootstrap program loads the new program,
++ * the new program starts automatically.
++ *
++ * The uCode used for open-source drivers includes two programs:
++ *
++ * 1)  Initialization -- performs hardware calibration and sets up some
++ *     internal data, then notifies host via "initialize alive" notification
++ *     (struct iwl_init_alive_resp) that it has completed all of its work.
++ *     After signal from host, it then loads and starts the runtime program.
++ *     The initialization program must be used when initially setting up the
++ *     NIC after loading the driver.
++ *
++ * 2)  Runtime/Protocol -- performs all normal runtime operations.  This
++ *     notifies host via "alive" notification (struct iwl_alive_resp) that it
++ *     is ready to be used.
++ *
++ * When initializing the NIC, the host driver does the following procedure:
++ *
++ * 1)  Load bootstrap program (instructions only, no data image for bootstrap)
++ *     into bootstrap memory.  Use dword writes starting at BSM_SRAM_LOWER_BOUND
++ *
++ * 2)  Point (via BSM_DRAM_*) to the "initialize" uCode data and instruction
++ *     images in host DRAM.
++ *
++ * 3)  Set up BSM to copy from BSM SRAM into uCode instruction SRAM when asked:
++ *     BSM_WR_MEM_SRC_REG = 0
++ *     BSM_WR_MEM_DST_REG = RTC_INST_LOWER_BOUND
++ *     BSM_WR_MEM_DWCOUNT_REG = # dwords in bootstrap instruction image
++ *
++ * 4)  Load bootstrap into instruction SRAM:
++ *     BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START
++ *
++ * 5)  Wait for load completion:
++ *     Poll BSM_WR_CTRL_REG for BSM_WR_CTRL_REG_BIT_START = 0
++ *
++ * 6)  Enable future boot loads whenever NIC's power management triggers it:
++ *     BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START_EN
++ *
++ * 7)  Start the NIC by removing all reset bits:
++ *     CSR_RESET = 0
++ *
++ *     The bootstrap uCode (already in instruction SRAM) loads initialization
++ *     uCode.  Initialization uCode performs data initialization, sends
++ *     "initialize alive" notification to host, and waits for a signal from
++ *     host to load runtime code.
++ *
++ * 4)  Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction
++ *     images in host DRAM.  The last register loaded must be the instruction
++ *     bytecount register ("1" in MSbit tells initialization uCode to load
++ *     the runtime uCode):
++ *     BSM_DRAM_INST_BYTECOUNT_REG = bytecount | BSM_DRAM_INST_LOAD
++ *
++ * 5)  Wait for "alive" notification, then issue normal runtime commands.
++ *
++ * Data caching during power-downs:
++ *
++ * Just before the embedded controller powers down (e.g for automatic
++ * power-saving modes, or for RFKILL), uCode stores (via PCI busmaster DMA)
++ * a current snapshot of the embedded processor's data SRAM into host DRAM.
++ * This caches the data while the embedded processor's memory is powered down.
++ * Location and size are controlled by BSM_DRAM_DATA_* registers.
++ *
++ * NOTE:  Instruction SRAM does not need to be saved, since that doesn't
++ *        change during operation; the original image (from uCode distribution
++ *        file) can be used for reload.
++ *
++ * When powering back up, the BSM loads the bootstrap program.  Bootstrap looks
++ * at the BSM_DRAM_* registers, which now point to the runtime instruction
++ * image and the cached (modified) runtime data (*not* the initialization
++ * uCode).  Bootstrap reloads these runtime images into SRAM, and restarts the
++ * uCode from where it left off before the power-down.
++ *
++ * NOTE:  Initialization uCode does *not* run as part of the save/restore
++ *        procedure.
++ *
++ * This save/restore method is mostly for autonomous power management during
++ * normal operation (result of POWER_TABLE_CMD).  Platform suspend/resume and
++ * RFKILL should use complete restarts (with total re-initialization) of uCode,
++ * allowing total shutdown (including BSM memory).
++ *
++ * Note that, during normal operation, the host DRAM that held the initial
++ * startup data for the runtime code is now being used as a backup data cache
++ * for modified data!  If you need to completely re-initialize the NIC, make
++ * sure that you use the runtime data image from the uCode distribution file,
++ * not the modified/saved runtime data.  You may want to store a separate
++ * "clean" runtime data image in DRAM to avoid disk reads of distribution file.
++ */
++
++/* BSM bit fields */
++#define BSM_WR_CTRL_REG_BIT_START     (0x80000000) /* start boot load now */
++#define BSM_WR_CTRL_REG_BIT_START_EN  (0x40000000) /* enable boot after pwrup*/
++#define BSM_DRAM_INST_LOAD            (0x80000000) /* start program load now */
++
++/* BSM addresses */
++#define BSM_BASE                     (PRPH_BASE + 0x3400)
++#define BSM_END                      (PRPH_BASE + 0x3800)
++
++#define BSM_WR_CTRL_REG              (BSM_BASE + 0x000) /* ctl and status */
++#define BSM_WR_MEM_SRC_REG           (BSM_BASE + 0x004) /* source in BSM mem */
++#define BSM_WR_MEM_DST_REG           (BSM_BASE + 0x008) /* dest in SRAM mem */
++#define BSM_WR_DWCOUNT_REG           (BSM_BASE + 0x00C) /* bytes */
++#define BSM_WR_STATUS_REG            (BSM_BASE + 0x010) /* bit 0:  1 == done */
++
++/*
++ * Pointers and size regs for bootstrap load and data SRAM save/restore.
++ * NOTE:  3945 pointers use bits 31:0 of DRAM address.
++ *        4965 pointers use bits 35:4 of DRAM address.
++ */
++#define BSM_DRAM_INST_PTR_REG        (BSM_BASE + 0x090)
++#define BSM_DRAM_INST_BYTECOUNT_REG  (BSM_BASE + 0x094)
++#define BSM_DRAM_DATA_PTR_REG        (BSM_BASE + 0x098)
++#define BSM_DRAM_DATA_BYTECOUNT_REG  (BSM_BASE + 0x09C)
++
++/*
++ * BSM special memory, stays powered on during power-save sleeps.
++ * Read/write, address range from LOWER_BOUND to (LOWER_BOUND + SIZE -1)
++ */
++#define BSM_SRAM_LOWER_BOUND         (PRPH_BASE + 0x3800)
++#define BSM_SRAM_SIZE			(1024) /* bytes */
++
++
++#endif				/* __iwl_prph_h__ */
+diff --git a/drivers/net/wireless/iwl-spectrum.h b/drivers/net/wireless/iwl-spectrum.h
+new file mode 100644
+index 0000000..b576ff2
+--- /dev/null
++++ b/drivers/net/wireless/iwl-spectrum.h
+@@ -0,0 +1,91 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ieee80211 subsystem header files.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef __iwl_spectrum_h__
++#define __iwl_spectrum_h__
++enum {				/* ieee80211_basic_report.map */
++	IEEE80211_BASIC_MAP_BSS = (1 << 0),
++	IEEE80211_BASIC_MAP_OFDM = (1 << 1),
++	IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2),
++	IEEE80211_BASIC_MAP_RADAR = (1 << 3),
++	IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4),
++	/* Bits 5-7 are reserved */
++
++};
++struct ieee80211_basic_report {
++	u8 channel;
++	__le64 start_time;
++	__le16 duration;
++	u8 map;
++} __attribute__ ((packed));
++
++enum {				/* ieee80211_measurement_request.mode */
++	/* Bit 0 is reserved */
++	IEEE80211_MEASUREMENT_ENABLE = (1 << 1),
++	IEEE80211_MEASUREMENT_REQUEST = (1 << 2),
++	IEEE80211_MEASUREMENT_REPORT = (1 << 3),
++	/* Bits 4-7 are reserved */
++};
++
++enum {
++	IEEE80211_REPORT_BASIC = 0,	/* required */
++	IEEE80211_REPORT_CCA = 1,	/* optional */
++	IEEE80211_REPORT_RPI = 2,	/* optional */
++	/* 3-255 reserved */
++};
++
++struct ieee80211_measurement_params {
++	u8 channel;
++	__le64 start_time;
++	__le16 duration;
++} __attribute__ ((packed));
++
++struct ieee80211_info_element {
++	u8 id;
++	u8 len;
++	u8 data[0];
++} __attribute__ ((packed));
++
++struct ieee80211_measurement_request {
++	struct ieee80211_info_element ie;
++	u8 token;
++	u8 mode;
++	u8 type;
++	struct ieee80211_measurement_params params[0];
++} __attribute__ ((packed));
++
++struct ieee80211_measurement_report {
++	struct ieee80211_info_element ie;
++	u8 token;
++	u8 mode;
++	u8 type;
++	union {
++		struct ieee80211_basic_report basic[0];
++	} u;
++} __attribute__ ((packed));
++#endif
+diff --git a/drivers/net/wireless/iwl3945-base.c b/drivers/net/wireless/iwl3945-base.c
+new file mode 100644
+index 0000000..c2c20f4
+--- /dev/null
++++ b/drivers/net/wireless/iwl3945-base.c
+@@ -0,0 +1,8758 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project, as well
++ * as portions of the ieee80211 subsystem header files.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++/*
++ * NOTE:  This file (iwl-base.c) is used to build to multiple hardware targets
++ * by defining IWL to either 3945 or 4965.  The Makefile used when building
++ * the base targets will create base-3945.o and base-4965.o
++ *
++ * The eventual goal is to move as many of the #if IWL / #endif blocks out of
++ * this file and into the hardware specific implementation files (iwl-XXXX.c)
++ * and leave only the common (non #ifdef sprinkled) code in this file
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <linux/delay.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/wireless.h>
++#include <linux/firmware.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/if_arp.h>
++
++#include <net/ieee80211_radiotap.h>
++#include <net/mac80211.h>
++
++#include <asm/div64.h>
++
++#include "iwlwifi.h"
++#include "iwl-3945.h"
++#include "iwl-helpers.h"
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++u32 iwl_debug_level;
++#endif
++
++/******************************************************************************
++ *
++ * module boiler plate
++ *
++ ******************************************************************************/
++
++/* module parameters */
++int iwl_param_disable_hw_scan;
++int iwl_param_debug;
++int iwl_param_disable;      /* def: enable radio */
++int iwl_param_antenna;      /* def: 0 = both antennas (use diversity) */
++int iwl_param_hwcrypto;     /* def: using software encryption */
++int iwl_param_qos_enable = 1;
++int iwl_param_queues_num = IWL_MAX_NUM_QUEUES;
++
++/*
++ * module name, copyright, version, etc.
++ * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk
++ */
++
++#define DRV_DESCRIPTION	\
++"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++#define VD "d"
++#else
++#define VD
++#endif
++
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++#define VS "s"
++#else
++#define VS
++#endif
++
++#define IWLWIFI_VERSION "0.1.13k" VD VS
++#define DRV_COPYRIGHT	"Copyright(c) 2003-2007 Intel Corporation"
++#define DRV_VERSION     IWLWIFI_VERSION
++
++/* Change firmware file name, using "-" and incrementing number,
++ *   *only* when uCode interface or architecture changes so that it
++ *   is not compatible with earlier drivers.
++ * This number will also appear in << 8 position of 1st dword of uCode file */
++#define IWL3945_UCODE_API "-1"
++
++MODULE_DESCRIPTION(DRV_DESCRIPTION);
++MODULE_VERSION(DRV_VERSION);
++MODULE_AUTHOR(DRV_COPYRIGHT);
++MODULE_LICENSE("GPL");
++
++__le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
++{
++	u16 fc = le16_to_cpu(hdr->frame_control);
++	int hdr_len = ieee80211_get_hdrlen(fc);
++
++	if ((fc & 0x00cc) == (IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA))
++		return (__le16 *) ((u8 *) hdr + hdr_len - QOS_CONTROL_LEN);
++	return NULL;
++}
++
++static const struct ieee80211_hw_mode *iwl_get_hw_mode(
++		struct iwl_priv *priv, int mode)
++{
++	int i;
++
++	for (i = 0; i < 3; i++)
++		if (priv->modes[i].mode == mode)
++			return &priv->modes[i];
++
++	return NULL;
++}
++
++static int iwl_is_empty_essid(const char *essid, int essid_len)
++{
++	/* Single white space is for Linksys APs */
++	if (essid_len == 1 && essid[0] == ' ')
++		return 1;
++
++	/* Otherwise, if the entire essid is 0, we assume it is hidden */
++	while (essid_len) {
++		essid_len--;
++		if (essid[essid_len] != '\0')
++			return 0;
++	}
++
++	return 1;
++}
++
++static const char *iwl_escape_essid(const char *essid, u8 essid_len)
++{
++	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
++	const char *s = essid;
++	char *d = escaped;
++
++	if (iwl_is_empty_essid(essid, essid_len)) {
++		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
++		return escaped;
++	}
++
++	essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
++	while (essid_len--) {
++		if (*s == '\0') {
++			*d++ = '\\';
++			*d++ = '0';
++			s++;
++		} else
++			*d++ = *s++;
++	}
++	*d = '\0';
++	return escaped;
++}
++
++static void iwl_print_hex_dump(int level, void *p, u32 len)
++{
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (!(iwl_debug_level & level))
++		return;
++
++	print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
++			p, len, 1);
++#endif
++}
++
++/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
++ * DMA services
++ *
++ * Theory of operation
++ *
++ * A queue is a circular buffers with 'Read' and 'Write' pointers.
++ * 2 empty entries always kept in the buffer to protect from overflow.
++ *
++ * For Tx queue, there are low mark and high mark limits. If, after queuing
++ * the packet for Tx, free space become < low mark, Tx queue stopped. When
++ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
++ * Tx queue resumed.
++ *
++ * The IPW operates with six queues, one receive queue in the device's
++ * sram, one transmit queue for sending commands to the device firmware,
++ * and four transmit queues for data.
++ *
++ * The four transmit queues allow for performing quality of service (qos)
++ * transmissions as per the 802.11 protocol.  Currently Linux does not
++ * provide a mechanism to the user for utilizing prioritized queues, so
++ * we only utilize the first data transmit queue (queue1).
++ ***************************************************/
++
++static int iwl_queue_space(const struct iwl_queue *q)
++{
++	int s = q->last_used - q->first_empty;
++
++	if (q->last_used > q->first_empty)
++		s -= q->n_bd;
++
++	if (s <= 0)
++		s += q->n_window;
++	/* keep some reserve to not confuse empty and full situations */
++	s -= 2;
++	if (s < 0)
++		s = 0;
++	return s;
++}
++
++/* XXX: n_bd must be power-of-two size */
++static inline int iwl_queue_inc_wrap(int index, int n_bd)
++{
++	return ++index & (n_bd - 1);
++}
++
++/* XXX: n_bd must be power-of-two size */
++static inline int iwl_queue_dec_wrap(int index, int n_bd)
++{
++	return --index & (n_bd - 1);
++}
++
++static inline int x2_queue_used(const struct iwl_queue *q, int i)
++{
++	return q->first_empty > q->last_used ?
++		(i >= q->last_used && i < q->first_empty) :
++		!(i < q->last_used && i >= q->first_empty);
++}
++
++static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
++{
++	if (is_huge)
++		return q->n_window;
++
++	return index & (q->n_window - 1);
++}
++
++static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
++			  int count, int slots_num, u32 id)
++{
++	q->n_bd = count;
++	q->n_window = slots_num;
++	q->id = id;
++
++	/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
++	 * and iwl_queue_dec_wrap are broken. */
++	BUG_ON(!is_power_of_2(count));
++
++	/* slots_num must be power-of-two size, otherwise
++	 * get_cmd_index is broken. */
++	BUG_ON(!is_power_of_2(slots_num));
++
++	q->low_mark = q->n_window / 4;
++	if (q->low_mark < 4)
++		q->low_mark = 4;
++
++	q->high_mark = q->n_window / 8;
++	if (q->high_mark < 2)
++		q->high_mark = 2;
++
++	q->first_empty = q->last_used = 0;
++
++	return 0;
++}
++
++static int iwl_tx_queue_alloc(struct iwl_priv *priv,
++			      struct iwl_tx_queue *txq, u32 id)
++{
++	struct pci_dev *dev = priv->pci_dev;
++
++	if (id != IWL_CMD_QUEUE_NUM) {
++		txq->txb = kmalloc(sizeof(txq->txb[0]) *
++				   TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
++		if (!txq->txb) {
++			IWL_ERROR("kmalloc for auxilary BD "
++				  "structures failed\n");
++			goto error;
++		}
++	} else
++		txq->txb = NULL;
++
++	txq->bd = pci_alloc_consistent(dev,
++			sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
++			&txq->q.dma_addr);
++
++	if (!txq->bd) {
++		IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
++			  sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
++		goto error;
++	}
++	txq->q.id = id;
++
++	return 0;
++
++ error:
++	if (txq->txb) {
++		kfree(txq->txb);
++		txq->txb = NULL;
++	}
++
++	return -ENOMEM;
++}
++
++int iwl_tx_queue_init(struct iwl_priv *priv,
++		      struct iwl_tx_queue *txq, int slots_num, u32 txq_id)
++{
++	struct pci_dev *dev = priv->pci_dev;
++	int len;
++	int rc = 0;
++
++	/* alocate command space + one big command for scan since scan
++	 * command is very huge the system will not have two scan at the
++	 * same time */
++	len = sizeof(struct iwl_cmd) * slots_num;
++	if (txq_id == IWL_CMD_QUEUE_NUM)
++		len +=  IWL_MAX_SCAN_SIZE;
++	txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
++	if (!txq->cmd)
++		return -ENOMEM;
++
++	rc = iwl_tx_queue_alloc(priv, txq, txq_id);
++	if (rc) {
++		pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
++
++		return -ENOMEM;
++	}
++	txq->need_update = 0;
++
++	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
++	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
++	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
++	iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
++
++	iwl_hw_tx_queue_init(priv, txq);
++
++	return 0;
++}
++
++/**
++ * iwl_tx_queue_free - Deallocate DMA queue.
++ * @txq: Transmit queue to deallocate.
++ *
++ * Empty queue by removing and destroying all BD's.
++ * Free all buffers.  txq itself is not freed.
++ *
++ */
++void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
++{
++	struct iwl_queue *q = &txq->q;
++	struct pci_dev *dev = priv->pci_dev;
++	int len;
++
++	if (q->n_bd == 0)
++		return;
++
++	/* first, empty all BD's */
++	for (; q->first_empty != q->last_used;
++	     q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd))
++		iwl_hw_txq_free_tfd(priv, txq);
++
++	len = sizeof(struct iwl_cmd) * q->n_window;
++	if (q->id == IWL_CMD_QUEUE_NUM)
++		len += IWL_MAX_SCAN_SIZE;
++
++	pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
++
++	/* free buffers belonging to queue itself */
++	if (txq->q.n_bd)
++		pci_free_consistent(dev, sizeof(struct iwl_tfd_frame) *
++				    txq->q.n_bd, txq->bd, txq->q.dma_addr);
++
++	if (txq->txb) {
++		kfree(txq->txb);
++		txq->txb = NULL;
++	}
++
++	/* 0 fill whole structure */
++	memset(txq, 0, sizeof(*txq));
++}
++
++const u8 BROADCAST_ADDR[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
++
++/*************** STATION TABLE MANAGEMENT ****
++ *
++ * NOTE:  This needs to be overhauled to better synchronize between
++ * how the iwl-4965.c is using iwl_hw_find_station vs. iwl-3945.c
++ *
++ * mac80211 should also be examined to determine if sta_info is duplicating
++ * the functionality provided here
++ */
++
++/**************************************************************/
++
++static u8 iwl_remove_station(struct iwl_priv *priv, const u8 *bssid, int is_ap)
++{
++	int index = IWL_INVALID_STATION;
++	int i;
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->sta_lock, flags);
++
++	if (is_ap) {
++		index = IWL_AP_ID;
++		if ((priv->stations[index].used))
++			priv->stations[index].used = 0;
++	} else if (is_broadcast_ether_addr(bssid)) {
++		index = IWL_BROADCAST_ID;
++		if ((priv->stations[index].used))
++			priv->stations[index].used = 0;
++	} else {
++		for (i = IWL_STA_ID; i < priv->num_stations + IWL_STA_ID; i++) {
++			if (priv->stations[i].used &&
++			    !compare_ether_addr(priv->stations[i].sta.sta.addr,
++						bssid)) {
++				index = i;
++				priv->stations[index].used = 0;
++				break;
++			}
++		}
++	}
++	if (index != IWL_INVALID_STATION) {
++		if (priv->num_stations > 0)
++			priv->num_stations--;
++	}
++
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++	return 0;
++}
++
++static void iwl_clear_stations_table(struct iwl_priv *priv)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->sta_lock, flags);
++
++	priv->num_stations = 0;
++	memset(priv->stations, 0, sizeof(priv->stations));
++
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++}
++
++u8 iwl_add_station(struct iwl_priv *priv, const u8 *bssid, int is_ap, u8 flags)
++{
++	int i = IWL_STATION_COUNT;
++	int index = IWL_INVALID_STATION;
++	struct iwl_station_entry *station;
++	unsigned long flags_spin;
++	u8 rate;
++
++	spin_lock_irqsave(&priv->sta_lock, flags_spin);
++	if (is_ap) {
++		index = IWL_AP_ID;
++		if (priv->stations[index].used &&
++		    !compare_ether_addr(priv->stations[index].sta.sta.addr,
++					bssid))
++			goto done;
++	} else if (is_broadcast_ether_addr(bssid)) {
++		index = IWL_BROADCAST_ID;
++		if (priv->stations[index].used &&
++		    !compare_ether_addr(priv->stations[index].sta.sta.addr,
++					bssid))
++			goto done;
++	} else {
++		for (i = IWL_STA_ID; i < priv->num_stations + IWL_STA_ID; i++) {
++			if (priv->stations[i].used &&
++			    !compare_ether_addr(priv->stations[i].sta.sta.addr,
++						bssid))
++				goto done;
++
++			if (!priv->stations[i].used &&
++			    index == IWL_INVALID_STATION)
++				index = i;
++		}
++	}
++
++	if (index != IWL_INVALID_STATION)
++		i = index;
++
++	if (i == IWL_STATION_COUNT) {
++		index = IWL_INVALID_STATION;
++		goto done;
++	}
++
++	IWL_DEBUG_ASSOC("Adding STA ID %d: " MAC_FMT "\n", i, MAC_ARG(bssid));
++	station = &priv->stations[i];
++
++	station->used = 1;
++	memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
++	memcpy(station->sta.sta.addr, bssid, ETH_ALEN);
++	station->sta.mode = 0;
++	station->sta.sta.sta_id = i;
++	station->sta.station_flags = 0;
++	rate = (priv->phymode == MODE_IEEE80211A) ? IWL_RATE_6M_PLCP :
++			IWL_RATE_1M_PLCP | priv->hw_setting.cck_flag;
++
++	/* Turn on both antennas for the station... */
++	station->sta.rate_n_flags =
++			iwl_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK);
++
++	station->sta.station_flags |= STA_FLG_TX_RATE_MSK;
++
++	station->current_rate.rate_n_flags =
++		le16_to_cpu(station->sta.rate_n_flags);
++
++	priv->num_stations++;
++	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
++	iwl_send_add_station(priv, &station->sta, flags);
++	return i;
++
++ done:
++	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
++	return index;
++}
++
++/*************** DRIVER STATUS FUNCTIONS   *****/
++
++static inline int iwl_is_ready(struct iwl_priv *priv)
++{
++	/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
++	 * set but EXIT_PENDING is not */
++	return test_bit(STATUS_READY, &priv->status) &&
++	       test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
++	       !test_bit(STATUS_EXIT_PENDING, &priv->status);
++}
++
++static inline int iwl_is_alive(struct iwl_priv *priv)
++{
++	return test_bit(STATUS_ALIVE, &priv->status);
++}
++
++static inline int iwl_is_init(struct iwl_priv *priv)
++{
++	return test_bit(STATUS_INIT, &priv->status);
++}
++
++static inline int iwl_is_rfkill(struct iwl_priv *priv)
++{
++	return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++	       test_bit(STATUS_RF_KILL_SW, &priv->status);
++}
++
++static inline int iwl_is_ready_rf(struct iwl_priv *priv)
++{
++
++	if (iwl_is_rfkill(priv))
++		return 0;
++
++	return iwl_is_ready(priv);
++}
++
++/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
++
++#define IWL_CMD(x) case x : return #x
++
++static const char *get_cmd_string(u8 cmd)
++{
++	switch (cmd) {
++		IWL_CMD(REPLY_ALIVE);
++		IWL_CMD(REPLY_ERROR);
++		IWL_CMD(REPLY_RXON);
++		IWL_CMD(REPLY_RXON_ASSOC);
++		IWL_CMD(REPLY_QOS_PARAM);
++		IWL_CMD(REPLY_RXON_TIMING);
++		IWL_CMD(REPLY_ADD_STA);
++		IWL_CMD(REPLY_REMOVE_STA);
++		IWL_CMD(REPLY_REMOVE_ALL_STA);
++		IWL_CMD(REPLY_3945_RX);
++		IWL_CMD(REPLY_TX);
++		IWL_CMD(REPLY_RATE_SCALE);
++		IWL_CMD(REPLY_LEDS_CMD);
++		IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
++		IWL_CMD(RADAR_NOTIFICATION);
++		IWL_CMD(REPLY_QUIET_CMD);
++		IWL_CMD(REPLY_CHANNEL_SWITCH);
++		IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
++		IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
++		IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
++		IWL_CMD(POWER_TABLE_CMD);
++		IWL_CMD(PM_SLEEP_NOTIFICATION);
++		IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
++		IWL_CMD(REPLY_SCAN_CMD);
++		IWL_CMD(REPLY_SCAN_ABORT_CMD);
++		IWL_CMD(SCAN_START_NOTIFICATION);
++		IWL_CMD(SCAN_RESULTS_NOTIFICATION);
++		IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
++		IWL_CMD(BEACON_NOTIFICATION);
++		IWL_CMD(REPLY_TX_BEACON);
++		IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
++		IWL_CMD(QUIET_NOTIFICATION);
++		IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
++		IWL_CMD(MEASURE_ABORT_NOTIFICATION);
++		IWL_CMD(REPLY_BT_CONFIG);
++		IWL_CMD(REPLY_STATISTICS_CMD);
++		IWL_CMD(STATISTICS_NOTIFICATION);
++		IWL_CMD(REPLY_CARD_STATE_CMD);
++		IWL_CMD(CARD_STATE_NOTIFICATION);
++		IWL_CMD(MISSED_BEACONS_NOTIFICATION);
++	default:
++		return "UNKNOWN";
++
++	}
++}
++
++#define HOST_COMPLETE_TIMEOUT (HZ / 2)
++
++/**
++ * iwl_enqueue_hcmd - enqueue a uCode command
++ * @priv: device private data point
++ * @cmd: a point to the ucode command structure
++ *
++ * The function returns < 0 values to indicate the operation is
++ * failed. On success, it turns the index (> 0) of command in the
++ * command queue.
++ */
++static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
++	struct iwl_queue *q = &txq->q;
++	struct iwl_tfd_frame *tfd;
++	u32 *control_flags;
++	struct iwl_cmd *out_cmd;
++	u32 idx;
++	u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
++	dma_addr_t phys_addr;
++	int pad;
++	u16 count;
++	int ret;
++	unsigned long flags;
++
++	/* If any of the command structures end up being larger than
++	 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
++	 * we will need to increase the size of the TFD entries */
++	BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
++	       !(cmd->meta.flags & CMD_SIZE_HUGE));
++
++	if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
++		IWL_ERROR("No space for Tx\n");
++		return -ENOSPC;
++	}
++
++	spin_lock_irqsave(&priv->hcmd_lock, flags);
++
++	tfd = &txq->bd[q->first_empty];
++	memset(tfd, 0, sizeof(*tfd));
++
++	control_flags = (u32 *) tfd;
++
++	idx = get_cmd_index(q, q->first_empty, cmd->meta.flags & CMD_SIZE_HUGE);
++	out_cmd = &txq->cmd[idx];
++
++	out_cmd->hdr.cmd = cmd->id;
++	memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta));
++	memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
++
++	/* At this point, the out_cmd now has all of the incoming cmd
++	 * information */
++
++	out_cmd->hdr.flags = 0;
++	out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
++			INDEX_TO_SEQ(q->first_empty));
++	if (out_cmd->meta.flags & CMD_SIZE_HUGE)
++		out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
++
++	phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
++			offsetof(struct iwl_cmd, hdr);
++	iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
++
++	pad = U32_PAD(cmd->len);
++	count = TFD_CTL_COUNT_GET(*control_flags);
++	*control_flags = TFD_CTL_COUNT_SET(count) | TFD_CTL_PAD_SET(pad);
++
++	IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
++		     "%d bytes at %d[%d]:%d\n",
++		     get_cmd_string(out_cmd->hdr.cmd),
++		     out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
++		     fix_size, q->first_empty, idx, IWL_CMD_QUEUE_NUM);
++
++	txq->need_update = 1;
++	q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
++	ret = iwl_tx_queue_update_write_ptr(priv, txq);
++
++	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
++	return ret ? ret : idx;
++}
++
++int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++	int ret;
++
++	BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
++
++	/* An asynchronous command can not expect an SKB to be set. */
++	BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
++
++	/* An asynchronous command MUST have a callback. */
++	BUG_ON(!cmd->meta.u.callback);
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return -EBUSY;
++
++	ret = iwl_enqueue_hcmd(priv, cmd);
++	if (ret < 0) {
++		IWL_ERROR("Error sending %s: iwl_enqueue_hcmd failed: %d\n",
++			  get_cmd_string(cmd->id), ret);
++		return ret;
++	}
++	return 0;
++}
++
++int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++	int cmd_idx;
++	int ret;
++	static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
++
++	BUG_ON(cmd->meta.flags & CMD_ASYNC);
++
++	 /* A synchronous command can not have a callback set. */
++	BUG_ON(cmd->meta.u.callback != NULL);
++
++	if (atomic_xchg(&entry, 1)) {
++		IWL_ERROR("Error sending %s: Already sending a host command\n",
++			  get_cmd_string(cmd->id));
++		return -EBUSY;
++	}
++
++	set_bit(STATUS_HCMD_ACTIVE, &priv->status);
++
++	if (cmd->meta.flags & CMD_WANT_SKB)
++		cmd->meta.source = &cmd->meta;
++
++	cmd_idx = iwl_enqueue_hcmd(priv, cmd);
++	if (cmd_idx < 0) {
++		ret = cmd_idx;
++		IWL_ERROR("Error sending %s: iwl_enqueue_hcmd failed: %d\n",
++			  get_cmd_string(cmd->id), ret);
++		goto out;
++	}
++
++	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
++			!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
++			HOST_COMPLETE_TIMEOUT);
++	if (!ret) {
++		if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
++			IWL_ERROR("Error sending %s: time out after %dms.\n",
++				  get_cmd_string(cmd->id),
++				  jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
++
++			clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
++			ret = -ETIMEDOUT;
++			goto cancel;
++		}
++	}
++
++	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
++		IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
++			       get_cmd_string(cmd->id));
++		ret = -ECANCELED;
++		goto fail;
++	}
++	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
++		IWL_DEBUG_INFO("Command %s failed: FW Error\n",
++			       get_cmd_string(cmd->id));
++		ret = -EIO;
++		goto fail;
++	}
++	if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
++		IWL_ERROR("Error: Response NULL in '%s'\n",
++			  get_cmd_string(cmd->id));
++		ret = -EIO;
++		goto out;
++	}
++
++	ret = 0;
++	goto out;
++
++cancel:
++	if (cmd->meta.flags & CMD_WANT_SKB) {
++		struct iwl_cmd *qcmd;
++
++		/* Cancel the CMD_WANT_SKB flag for the cmd in the
++		 * TX cmd queue. Otherwise in case the cmd comes
++		 * in later, it will possibly set an invalid
++		 * address (cmd->meta.source). */
++		qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
++		qcmd->meta.flags &= ~CMD_WANT_SKB;
++	}
++fail:
++	if (cmd->meta.u.skb) {
++		dev_kfree_skb_any(cmd->meta.u.skb);
++		cmd->meta.u.skb = NULL;
++	}
++out:
++	atomic_set(&entry, 0);
++	return ret;
++}
++
++int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++	/* A command can not be asynchronous AND expect an SKB to be set. */
++	BUG_ON((cmd->meta.flags & CMD_ASYNC) &&
++	       (cmd->meta.flags & CMD_WANT_SKB));
++
++	if (cmd->meta.flags & CMD_ASYNC)
++		return iwl_send_cmd_async(priv, cmd);
++
++	return iwl_send_cmd_sync(priv, cmd);
++}
++
++int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
++{
++	struct iwl_host_cmd cmd = {
++		.id = id,
++		.len = len,
++		.data = data,
++	};
++
++	return iwl_send_cmd_sync(priv, &cmd);
++}
++
++static int __must_check iwl_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val)
++{
++	struct iwl_host_cmd cmd = {
++		.id = id,
++		.len = sizeof(val),
++		.data = &val,
++	};
++
++	return iwl_send_cmd_sync(priv, &cmd);
++}
++
++int iwl_send_statistics_request(struct iwl_priv *priv)
++{
++	return iwl_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
++}
++
++/**
++ * iwl_rxon_add_station - add station into station table.
++ *
++ * there is only one AP station with id= IWL_AP_ID
++ * NOTE: mutex must be held before calling the this fnction
++*/
++static int iwl_rxon_add_station(struct iwl_priv *priv,
++				const u8 *addr, int is_ap)
++{
++	u8 rc;
++
++	/* Remove this station if it happens to already exist */
++	iwl_remove_station(priv, addr, is_ap);
++
++	rc = iwl_add_station(priv, addr, is_ap, 0);
++
++	return rc;
++}
++
++/**
++ * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
++ * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
++ * @channel: Any channel valid for the requested phymode
++
++ * In addition to setting the staging RXON, priv->phymode is also set.
++ *
++ * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
++ * in the staging RXON flag structure based on the phymode
++ */
++static int iwl_set_rxon_channel(struct iwl_priv *priv, u8 phymode, u16 channel)
++{
++	if (!iwl_get_channel_info(priv, phymode, channel)) {
++		IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
++			       channel, phymode);
++		return -EINVAL;
++	}
++
++	if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
++	    (priv->phymode == phymode))
++		return 0;
++
++	priv->staging_rxon.channel = cpu_to_le16(channel);
++	if (phymode == MODE_IEEE80211A)
++		priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
++	else
++		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
++
++	priv->phymode = phymode;
++
++	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
++
++	return 0;
++}
++
++/**
++ * iwl_check_rxon_cmd - validate RXON structure is valid
++ *
++ * NOTE:  This is really only useful during development and can eventually
++ * be #ifdef'd out once the driver is stable and folks aren't actively
++ * making changes
++ */
++static int iwl_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
++{
++	int error = 0;
++	int counter = 1;
++
++	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
++		error |= le32_to_cpu(rxon->flags &
++				(RXON_FLG_TGJ_NARROW_BAND_MSK |
++				 RXON_FLG_RADAR_DETECT_MSK));
++		if (error)
++			IWL_WARNING("check 24G fields %d | %d\n",
++				    counter++, error);
++	} else {
++		error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
++				0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
++		if (error)
++			IWL_WARNING("check 52 fields %d | %d\n",
++				    counter++, error);
++		error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
++		if (error)
++			IWL_WARNING("check 52 CCK %d | %d\n",
++				    counter++, error);
++	}
++	error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
++	if (error)
++		IWL_WARNING("check mac addr %d | %d\n", counter++, error);
++
++	/* make sure basic rates 6Mbps and 1Mbps are supported */
++	error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
++		  ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
++	if (error)
++		IWL_WARNING("check basic rate %d | %d\n", counter++, error);
++
++	error |= (le16_to_cpu(rxon->assoc_id) > 2007);
++	if (error)
++		IWL_WARNING("check assoc id %d | %d\n", counter++, error);
++
++	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
++			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
++	if (error)
++		IWL_WARNING("check CCK and short slot %d | %d\n",
++			    counter++, error);
++
++	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
++			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
++	if (error)
++		IWL_WARNING("check CCK & auto detect %d | %d\n",
++			    counter++, error);
++
++	error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
++			RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
++	if (error)
++		IWL_WARNING("check TGG and auto detect %d | %d\n",
++			    counter++, error);
++
++	if ((rxon->flags & RXON_FLG_DIS_DIV_MSK))
++		error |= ((rxon->flags & (RXON_FLG_ANT_B_MSK |
++				RXON_FLG_ANT_A_MSK)) == 0);
++	if (error)
++		IWL_WARNING("check antenna %d %d\n", counter++, error);
++
++	if (error)
++		IWL_WARNING("Tuning to channel %d\n",
++			    le16_to_cpu(rxon->channel));
++
++	if (error) {
++		IWL_ERROR("Not a valid iwl_rxon_assoc_cmd field values\n");
++		return -1;
++	}
++	return 0;
++}
++
++/**
++ * iwl_full_rxon_required - determine if RXON_ASSOC can be used in RXON commit
++ * @priv: staging_rxon is comapred to active_rxon
++ *
++ * If the RXON structure is changing sufficient to require a new
++ * tune or to clear and reset the RXON_FILTER_ASSOC_MSK then return 1
++ * to indicate a new tune is required.
++ */
++static int iwl_full_rxon_required(struct iwl_priv *priv)
++{
++
++	/* These items are only settable from the full RXON command */
++	if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ||
++	    compare_ether_addr(priv->staging_rxon.bssid_addr,
++			       priv->active_rxon.bssid_addr) ||
++	    compare_ether_addr(priv->staging_rxon.node_addr,
++			       priv->active_rxon.node_addr) ||
++	    compare_ether_addr(priv->staging_rxon.wlap_bssid_addr,
++			       priv->active_rxon.wlap_bssid_addr) ||
++	    (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) ||
++	    (priv->staging_rxon.channel != priv->active_rxon.channel) ||
++	    (priv->staging_rxon.air_propagation !=
++	     priv->active_rxon.air_propagation) ||
++	    (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
++		return 1;
++
++	/* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can
++	 * be updated with the RXON_ASSOC command -- however only some
++	 * flag transitions are allowed using RXON_ASSOC */
++
++	/* Check if we are not switching bands */
++	if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) !=
++	    (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK))
++		return 1;
++
++	/* Check if we are switching association toggle */
++	if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) !=
++		(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK))
++		return 1;
++
++	return 0;
++}
++
++static int iwl_send_rxon_assoc(struct iwl_priv *priv)
++{
++	int rc = 0;
++	struct iwl_rx_packet *res = NULL;
++	struct iwl_rxon_assoc_cmd rxon_assoc;
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_RXON_ASSOC,
++		.len = sizeof(rxon_assoc),
++		.meta.flags = CMD_WANT_SKB,
++		.data = &rxon_assoc,
++	};
++	const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
++	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
++
++	if ((rxon1->flags == rxon2->flags) &&
++	    (rxon1->filter_flags == rxon2->filter_flags) &&
++	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
++	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
++		IWL_DEBUG_INFO("Using current RXON_ASSOC.  Not resending.\n");
++		return 0;
++	}
++
++	rxon_assoc.flags = priv->staging_rxon.flags;
++	rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
++	rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
++	rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
++	rxon_assoc.reserved = 0;
++
++	rc = iwl_send_cmd_sync(priv, &cmd);
++	if (rc)
++		return rc;
++
++	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
++	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
++		IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n");
++		rc = -EIO;
++	}
++
++	priv->alloc_rxb_skb--;
++	dev_kfree_skb_any(cmd.meta.u.skb);
++
++	return rc;
++}
++
++/**
++ * iwl_commit_rxon - commit staging_rxon to hardware
++ *
++ * The RXON command in staging_rxon is commited to the hardware and
++ * the active_rxon structure is updated with the new data.  This
++ * function correctly transitions out of the RXON_ASSOC_MSK state if
++ * a HW tune is required based on the RXON structure changes.
++ */
++static int iwl_commit_rxon(struct iwl_priv *priv)
++{
++	/* cast away the const for active_rxon in this function */
++	struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
++	int rc = 0;
++
++	if (!iwl_is_alive(priv))
++		return -1;
++
++	/* always get timestamp with Rx frame */
++	priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
++
++	/* select antenna */
++	priv->staging_rxon.flags &=
++	    ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
++	priv->staging_rxon.flags |= iwl3945_get_antenna_flags(priv);
++
++	rc = iwl_check_rxon_cmd(&priv->staging_rxon);
++	if (rc) {
++		IWL_ERROR("Invalid RXON configuration.  Not committing.\n");
++		return -EINVAL;
++	}
++
++	/* If we don't need to send a full RXON, we can use
++	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
++	 * and other flags for the current radio configuration. */
++	if (!iwl_full_rxon_required(priv)) {
++		rc = iwl_send_rxon_assoc(priv);
++		if (rc) {
++			IWL_ERROR("Error setting RXON_ASSOC "
++				  "configuration (%d).\n", rc);
++			return rc;
++		}
++
++		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
++
++		return 0;
++	}
++
++	/* station table will be cleared */
++	priv->assoc_station_added = 0;
++
++	/* If we are currently associated and the new config requires
++	 * an RXON_ASSOC and the new config wants the associated mask enabled,
++	 * we must clear the associated from the active configuration
++	 * before we apply the new config */
++	if (iwl_is_associated(priv) &&
++	    (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
++		IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
++		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++
++		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
++				      sizeof(struct iwl_rxon_cmd),
++				      &priv->active_rxon);
++
++		/* If the mask clearing failed then we set
++		 * active_rxon back to what it was previously */
++		if (rc) {
++			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
++			IWL_ERROR("Error clearing ASSOC_MSK on current "
++				  "configuration (%d).\n", rc);
++			return rc;
++		}
++
++		/* The RXON bit toggling will have cleared out the
++		 * station table in the uCode, so blank it in the driver
++		 * as well */
++		iwl_clear_stations_table(priv);
++	} else if (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) {
++		/* When switching from non-associated to associated, the
++		 * uCode clears out the station table; so clear it in the
++		 * driver as well */
++		iwl_clear_stations_table(priv);
++	}
++
++	IWL_DEBUG_INFO("Sending RXON\n"
++		       "* with%s RXON_FILTER_ASSOC_MSK\n"
++		       "* channel = %d\n"
++		       "* bssid = " MAC_FMT "\n",
++		       ((priv->staging_rxon.filter_flags &
++			 RXON_FILTER_ASSOC_MSK) ? "" : "out"),
++		       le16_to_cpu(priv->staging_rxon.channel),
++		       MAC_ARG(priv->staging_rxon.bssid_addr));
++
++	/* Apply the new configuration */
++	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
++			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
++	if (rc) {
++		IWL_ERROR("Error setting new configuration (%d).\n", rc);
++		return rc;
++	}
++
++	memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
++
++	/* If we issue a new RXON command which required a tune then we must
++	 * send a new TXPOWER command or we won't be able to Tx any frames */
++	rc = iwl_hw_reg_send_txpower(priv);
++	if (rc) {
++		IWL_ERROR("Error setting Tx power (%d).\n", rc);
++		return rc;
++	}
++
++	/* Add the broadcast address so we can send broadcast frames */
++	if (iwl_rxon_add_station(priv, BROADCAST_ADDR, 0) ==
++	    IWL_INVALID_STATION) {
++		IWL_ERROR("Error adding BROADCAST address for transmit.\n");
++		return -EIO;
++	}
++
++	/* If we have set the ASSOC_MSK and we are in BSS mode then
++	 * add the IWL_AP_ID to the station rate table */
++	if (iwl_is_associated(priv) &&
++	    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
++		if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
++		    == IWL_INVALID_STATION) {
++			IWL_ERROR("Error adding AP address for transmit.\n");
++			return -EIO;
++		}
++		priv->assoc_station_added = 1;
++	}
++
++	/* Init the hardware's rate fallback order based on the
++	 * phymode */
++	rc = iwl3945_init_hw_rate_table(priv);
++	if (rc) {
++		IWL_ERROR("Error setting HW rate table: %02X\n", rc);
++		return -EIO;
++	}
++
++	return 0;
++}
++
++static int iwl_send_bt_config(struct iwl_priv *priv)
++{
++	struct iwl_bt_cmd bt_cmd = {
++		.flags = 3,
++		.lead_time = 0xAA,
++		.max_kill = 1,
++		.kill_ack_mask = 0,
++		.kill_cts_mask = 0,
++	};
++
++	return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
++				sizeof(struct iwl_bt_cmd), &bt_cmd);
++}
++
++static int iwl_send_scan_abort(struct iwl_priv *priv)
++{
++	int rc = 0;
++	struct iwl_rx_packet *res;
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_SCAN_ABORT_CMD,
++		.meta.flags = CMD_WANT_SKB,
++	};
++
++	/* If there isn't a scan actively going on in the hardware
++	 * then we are in between scan bands and not actually
++	 * actively scanning, so don't send the abort command */
++	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
++		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
++		return 0;
++	}
++
++	rc = iwl_send_cmd_sync(priv, &cmd);
++	if (rc) {
++		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
++		return rc;
++	}
++
++	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
++	if (res->u.status != CAN_ABORT_STATUS) {
++		/* The scan abort will return 1 for success or
++		 * 2 for "failure".  A failure condition can be
++		 * due to simply not being in an active scan which
++		 * can occur if we send the scan abort before we
++		 * the microcode has notified us that a scan is
++		 * completed. */
++		IWL_DEBUG_INFO("SCAN_ABORT returned %d.\n", res->u.status);
++		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
++		clear_bit(STATUS_SCAN_HW, &priv->status);
++	}
++
++	dev_kfree_skb_any(cmd.meta.u.skb);
++
++	return rc;
++}
++
++static int iwl_card_state_sync_callback(struct iwl_priv *priv,
++					struct iwl_cmd *cmd,
++					struct sk_buff *skb)
++{
++	return 1;
++}
++
++/*
++ * CARD_STATE_CMD
++ *
++ * Use: Sets the internal card state to enable, disable, or halt
++ *
++ * When in the 'enable' state the card operates as normal.
++ * When in the 'disable' state, the card enters into a low power mode.
++ * When in the 'halt' state, the card is shut down and must be fully
++ * restarted to come back on.
++ */
++static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
++{
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_CARD_STATE_CMD,
++		.len = sizeof(u32),
++		.data = &flags,
++		.meta.flags = meta_flag,
++	};
++
++	if (meta_flag & CMD_ASYNC)
++		cmd.meta.u.callback = iwl_card_state_sync_callback;
++
++	return iwl_send_cmd(priv, &cmd);
++}
++
++static int iwl_add_sta_sync_callback(struct iwl_priv *priv,
++				     struct iwl_cmd *cmd, struct sk_buff *skb)
++{
++	struct iwl_rx_packet *res = NULL;
++
++	if (!skb) {
++		IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
++		return 1;
++	}
++
++	res = (struct iwl_rx_packet *)skb->data;
++	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
++		IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
++			  res->hdr.flags);
++		return 1;
++	}
++
++	switch (res->u.add_sta.status) {
++	case ADD_STA_SUCCESS_MSK:
++		break;
++	default:
++		break;
++	}
++
++	/* We didn't cache the SKB; let the caller free it */
++	return 1;
++}
++
++int iwl_send_add_station(struct iwl_priv *priv,
++			 struct iwl_addsta_cmd *sta, u8 flags)
++{
++	struct iwl_rx_packet *res = NULL;
++	int rc = 0;
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_ADD_STA,
++		.len = sizeof(struct iwl_addsta_cmd),
++		.meta.flags = flags,
++		.data = sta,
++	};
++
++	if (flags & CMD_ASYNC)
++		cmd.meta.u.callback = iwl_add_sta_sync_callback;
++	else
++		cmd.meta.flags |= CMD_WANT_SKB;
++
++	rc = iwl_send_cmd(priv, &cmd);
++
++	if (rc || (flags & CMD_ASYNC))
++		return rc;
++
++	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
++	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
++		IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
++			  res->hdr.flags);
++		rc = -EIO;
++	}
++
++	if (rc == 0) {
++		switch (res->u.add_sta.status) {
++		case ADD_STA_SUCCESS_MSK:
++			IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n");
++			break;
++		default:
++			rc = -EIO;
++			IWL_WARNING("REPLY_ADD_STA failed\n");
++			break;
++		}
++	}
++
++	priv->alloc_rxb_skb--;
++	dev_kfree_skb_any(cmd.meta.u.skb);
++
++	return rc;
++}
++
++static int iwl_update_sta_key_info(struct iwl_priv *priv,
++				   struct ieee80211_key_conf *keyconf,
++				   u8 sta_id)
++{
++	unsigned long flags;
++	__le16 key_flags = 0;
++
++	switch (keyconf->alg) {
++	case ALG_CCMP:
++		key_flags |= STA_KEY_FLG_CCMP;
++		key_flags |= cpu_to_le16(
++				keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
++		key_flags &= ~STA_KEY_FLG_INVALID;
++		break;
++	case ALG_TKIP:
++	case ALG_WEP:
++		return -EINVAL;
++	default:
++		return -EINVAL;
++	}
++	spin_lock_irqsave(&priv->sta_lock, flags);
++	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
++	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
++	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
++	       keyconf->keylen);
++
++	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
++	       keyconf->keylen);
++	priv->stations[sta_id].sta.key.key_flags = key_flags;
++	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
++	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
++
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++	IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
++	iwl_send_add_station(priv, &priv->stations[sta_id].sta, 0);
++	return 0;
++}
++
++static void iwl_clear_free_frames(struct iwl_priv *priv)
++{
++	struct list_head *element;
++
++	IWL_DEBUG_INFO("%d frames on pre-allocated heap on clear.\n",
++		       priv->frames_count);
++
++	while (!list_empty(&priv->free_frames)) {
++		element = priv->free_frames.next;
++		list_del(element);
++		kfree(list_entry(element, struct iwl_frame, list));
++		priv->frames_count--;
++	}
++
++	if (priv->frames_count) {
++		IWL_WARNING("%d frames still in use.  Did we lose one?\n",
++			    priv->frames_count);
++		priv->frames_count = 0;
++	}
++}
++
++static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
++{
++	struct iwl_frame *frame;
++	struct list_head *element;
++	if (list_empty(&priv->free_frames)) {
++		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
++		if (!frame) {
++			IWL_ERROR("Could not allocate frame!\n");
++			return NULL;
++		}
++
++		priv->frames_count++;
++		return frame;
++	}
++
++	element = priv->free_frames.next;
++	list_del(element);
++	return list_entry(element, struct iwl_frame, list);
++}
++
++static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
++{
++	memset(frame, 0, sizeof(*frame));
++	list_add(&frame->list, &priv->free_frames);
++}
++
++unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
++				struct ieee80211_hdr *hdr,
++				const u8 *dest, int left)
++{
++
++	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
++	    ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
++	     (priv->iw_mode != IEEE80211_IF_TYPE_AP)))
++		return 0;
++
++	if (priv->ibss_beacon->len > left)
++		return 0;
++
++	memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
++
++	return priv->ibss_beacon->len;
++}
++
++static int iwl_rate_index_from_plcp(int plcp)
++{
++	int i = 0;
++
++	for (i = 0; i < IWL_RATE_COUNT; i++)
++		if (iwl_rates[i].plcp == plcp)
++			return i;
++	return -1;
++}
++
++static u8 iwl_rate_get_lowest_plcp(int rate_mask)
++{
++	u8 i;
++
++	for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
++	     i = iwl_rates[i].next_ieee) {
++		if (rate_mask & (1 << i))
++			return iwl_rates[i].plcp;
++	}
++
++	return IWL_RATE_INVALID;
++}
++
++static int iwl_send_beacon_cmd(struct iwl_priv *priv)
++{
++	struct iwl_frame *frame;
++	unsigned int frame_size;
++	int rc;
++	u8 rate;
++
++	frame = iwl_get_free_frame(priv);
++
++	if (!frame) {
++		IWL_ERROR("Could not obtain free frame buffer for beacon "
++			  "command.\n");
++		return -ENOMEM;
++	}
++
++	if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) {
++		rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic &
++						0xFF0);
++		if (rate == IWL_INVALID_RATE)
++			rate = IWL_RATE_6M_PLCP;
++	} else {
++		rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic & 0xF);
++		if (rate == IWL_INVALID_RATE)
++			rate = IWL_RATE_1M_PLCP;
++	}
++
++	frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate);
++
++	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
++			      &frame->u.cmd[0]);
++
++	iwl_free_frame(priv, frame);
++
++	return rc;
++}
++
++/******************************************************************************
++ *
++ * EEPROM related functions
++ *
++ ******************************************************************************/
++
++static void get_eeprom_mac(struct iwl_priv *priv, u8 *mac)
++{
++	memcpy(mac, priv->eeprom.mac_address, 6);
++}
++
++/**
++ * iwl_eeprom_init - read EEPROM contents
++ *
++ * Load the EEPROM from adapter into priv->eeprom
++ *
++ * NOTE:  This routine uses the non-debug IO access functions.
++ */
++int iwl_eeprom_init(struct iwl_priv *priv)
++{
++	u16 *e = (u16 *)&priv->eeprom;
++	u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
++	u32 r;
++	int sz = sizeof(priv->eeprom);
++	int rc;
++	int i;
++	u16 addr;
++
++	/* The EEPROM structure has several padding buffers within it
++	 * and when adding new EEPROM maps is subject to programmer errors
++	 * which may be very difficult to identify without explicitly
++	 * checking the resulting size of the eeprom map. */
++	BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
++
++	if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
++		IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
++		return -ENOENT;
++	}
++
++	rc = iwl_eeprom_aqcuire_semaphore(priv);
++	if (rc < 0) {
++		IWL_ERROR("Failed to aqcuire EEPROM semaphore.\n");
++		return -ENOENT;
++	}
++
++	/* eeprom is an array of 16bit values */
++	for (addr = 0; addr < sz; addr += sizeof(u16)) {
++		_iwl_write32(priv, CSR_EEPROM_REG, addr << 1);
++		_iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
++
++		for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
++					i += IWL_EEPROM_ACCESS_DELAY) {
++			r = _iwl_read_restricted(priv, CSR_EEPROM_REG);
++			if (r & CSR_EEPROM_REG_READ_VALID_MSK)
++				break;
++			udelay(IWL_EEPROM_ACCESS_DELAY);
++		}
++
++		if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
++			IWL_ERROR("Time out reading EEPROM[%d]", addr);
++			return -ETIMEDOUT;
++		}
++		e[addr / 2] = le16_to_cpu(r >> 16);
++	}
++
++	return 0;
++}
++
++/******************************************************************************
++ *
++ * Misc. internal state and helper functions
++ *
++ ******************************************************************************/
++#ifdef CONFIG_IWLWIFI_DEBUG
++
++/**
++ * iwl_report_frame - dump frame to syslog during debug sessions
++ *
++ * hack this function to show different aspects of received frames,
++ * including selective frame dumps.
++ * group100 parameter selects whether to show 1 out of 100 good frames.
++ *
++ * TODO:  ieee80211_hdr stuff is common to 3945 and 4965, so frame type
++ *        info output is okay, but some of this stuff (e.g. iwl_rx_frame_stats)
++ *        is 3945-specific and gives bad output for 4965.  Need to split the
++ *        functionality, keep common stuff here.
++ */
++void iwl_report_frame(struct iwl_priv *priv,
++		      struct iwl_rx_packet *pkt,
++		      struct ieee80211_hdr *header, int group100)
++{
++	u32 to_us;
++	u32 print_summary = 0;
++	u32 print_dump = 0;	/* set to 1 to dump all frames' contents */
++	u32 hundred = 0;
++	u32 dataframe = 0;
++	u16 fc;
++	u16 seq_ctl;
++	u16 channel;
++	u16 phy_flags;
++	int rate_sym;
++	u16 length;
++	u16 status;
++	u16 bcn_tmr;
++	u32 tsf_low;
++	u64 tsf;
++	u8 rssi;
++	u8 agc;
++	u16 sig_avg;
++	u16 noise_diff;
++	struct iwl_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
++	struct iwl_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
++	struct iwl_rx_frame_end *rx_end = IWL_RX_END(pkt);
++	u8 *data = IWL_RX_DATA(pkt);
++
++	/* MAC header */
++	fc = le16_to_cpu(header->frame_control);
++	seq_ctl = le16_to_cpu(header->seq_ctrl);
++
++	/* metadata */
++	channel = le16_to_cpu(rx_hdr->channel);
++	phy_flags = le16_to_cpu(rx_hdr->phy_flags);
++	rate_sym = rx_hdr->rate;
++	length = le16_to_cpu(rx_hdr->len);
++
++	/* end-of-frame status and timestamp */
++	status = le32_to_cpu(rx_end->status);
++	bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
++	tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
++	tsf = le64_to_cpu(rx_end->timestamp);
++
++	/* signal statistics */
++	rssi = rx_stats->rssi;
++	agc = rx_stats->agc;
++	sig_avg = le16_to_cpu(rx_stats->sig_avg);
++	noise_diff = le16_to_cpu(rx_stats->noise_diff);
++
++	to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
++
++	/* if data frame is to us and all is good,
++	 *   (optionally) print summary for only 1 out of every 100 */
++	if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
++	    (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
++		dataframe = 1;
++		if (!group100)
++			print_summary = 1;	/* print each frame */
++		else if (priv->framecnt_to_us < 100) {
++			priv->framecnt_to_us++;
++			print_summary = 0;
++		} else {
++			priv->framecnt_to_us = 0;
++			print_summary = 1;
++			hundred = 1;
++		}
++	} else {
++		/* print summary for all other frames */
++		print_summary = 1;
++	}
++
++	if (print_summary) {
++		char *title;
++		u32 rate;
++
++		if (hundred)
++			title = "100Frames";
++		else if (fc & IEEE80211_FCTL_RETRY)
++			title = "Retry";
++		else if (ieee80211_is_assoc_response(fc))
++			title = "AscRsp";
++		else if (ieee80211_is_reassoc_response(fc))
++			title = "RasRsp";
++		else if (ieee80211_is_probe_response(fc)) {
++			title = "PrbRsp";
++			print_dump = 1;	/* dump frame contents */
++		} else if (ieee80211_is_beacon(fc)) {
++			title = "Beacon";
++			print_dump = 1;	/* dump frame contents */
++		} else if (ieee80211_is_atim(fc))
++			title = "ATIM";
++		else if (ieee80211_is_auth(fc))
++			title = "Auth";
++		else if (ieee80211_is_deauth(fc))
++			title = "DeAuth";
++		else if (ieee80211_is_disassoc(fc))
++			title = "DisAssoc";
++		else
++			title = "Frame";
++
++		rate = iwl_rate_index_from_plcp(rate_sym);
++		if (rate == -1)
++			rate = 0;
++		else
++			rate = iwl_rates[rate].ieee / 2;
++
++		/* print frame summary.
++		 * MAC addresses show just the last byte (for brevity),
++		 *    but you can hack it to show more, if you'd like to. */
++		if (dataframe)
++			IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
++				     "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
++				     title, fc, header->addr1[5],
++				     length, rssi, channel, rate);
++		else {
++			/* src/dst addresses assume managed mode */
++			IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
++				     "src=0x%02x, rssi=%u, tim=%lu usec, "
++				     "phy=0x%02x, chnl=%d\n",
++				     title, fc, header->addr1[5],
++				     header->addr3[5], rssi,
++				     tsf_low - priv->scan_start_tsf,
++				     phy_flags, channel);
++		}
++	}
++	if (print_dump)
++		iwl_print_hex_dump(IWL_DL_RX, data, length);
++}
++#endif
++
++static void iwl_unset_hw_setting(struct iwl_priv *priv)
++{
++	if (priv->hw_setting.shared_virt)
++		pci_free_consistent(priv->pci_dev,
++				    sizeof(struct iwl_shared),
++				    priv->hw_setting.shared_virt,
++				    priv->hw_setting.shared_phys);
++}
++
++/**
++ * iwl_supported_rate_to_ie - fill in the supported rate in IE field
++ *
++ * return : set the bit for each supported rate insert in ie
++ */
++static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
++				    u16 basic_rate, int max_count)
++{
++	u16 ret_rates = 0, bit;
++	int i;
++	u8 *rates;
++
++	rates = &(ie[1]);
++
++	for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
++		if (bit & supported_rate) {
++			ret_rates |= bit;
++			rates[*ie] = iwl_rates[i].ieee |
++			    ((bit & basic_rate) ? 0x80 : 0x00);
++			*ie = *ie + 1;
++			if (*ie >= max_count)
++				break;
++		}
++	}
++
++	return ret_rates;
++}
++
++/**
++ * iwl_fill_probe_req - fill in all required fields and IE for probe request
++ */
++static u16 iwl_fill_probe_req(struct iwl_priv *priv,
++			      struct ieee80211_mgmt *frame,
++			      int left, int is_direct)
++{
++	int len = 0;
++	u8 *pos = NULL;
++	u16 ret_rates;
++
++	/* Make sure there is enough space for the probe request,
++	 * two mandatory IEs and the data */
++	left -= 24;
++	if (left < 0)
++		return 0;
++	len += 24;
++
++	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
++	memcpy(frame->da, BROADCAST_ADDR, ETH_ALEN);
++	memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
++	memcpy(frame->bssid, BROADCAST_ADDR, ETH_ALEN);
++	frame->seq_ctrl = 0;
++
++	/* fill in our indirect SSID IE */
++	/* ...next IE... */
++
++	left -= 2;
++	if (left < 0)
++		return 0;
++	len += 2;
++	pos = &(frame->u.probe_req.variable[0]);
++	*pos++ = WLAN_EID_SSID;
++	*pos++ = 0;
++
++	/* fill in our direct SSID IE... */
++	if (is_direct) {
++		/* ...next IE... */
++		left -= 2 + priv->essid_len;
++		if (left < 0)
++			return 0;
++		/* ... fill it in... */
++		*pos++ = WLAN_EID_SSID;
++		*pos++ = priv->essid_len;
++		memcpy(pos, priv->essid, priv->essid_len);
++		pos += priv->essid_len;
++		len += 2 + priv->essid_len;
++	}
++
++	/* fill in supported rate */
++	/* ...next IE... */
++	left -= 2;
++	if (left < 0)
++		return 0;
++	/* ... fill it in... */
++	*pos++ = WLAN_EID_SUPP_RATES;
++	*pos = 0;
++	ret_rates = priv->active_rate = priv->rates_mask;
++	priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
++
++	iwl_supported_rate_to_ie(pos, priv->active_rate,
++				 priv->active_rate_basic, left);
++	len += 2 + *pos;
++	pos += (*pos) + 1;
++	ret_rates = ~ret_rates & priv->active_rate;
++
++	if (ret_rates == 0)
++		goto fill_end;
++
++	/* fill in supported extended rate */
++	/* ...next IE... */
++	left -= 2;
++	if (left < 0)
++		return 0;
++	/* ... fill it in... */
++	*pos++ = WLAN_EID_EXT_SUPP_RATES;
++	*pos = 0;
++	iwl_supported_rate_to_ie(pos, ret_rates, priv->active_rate_basic, left);
++	if (*pos > 0)
++		len += 2 + *pos;
++
++ fill_end:
++	return (u16)len;
++}
++
++/*
++ * QoS  support
++*/
++#ifdef CONFIG_IWLWIFI_QOS
++static int iwl_send_qos_params_command(struct iwl_priv *priv,
++				       struct iwl_qosparam_cmd *qos)
++{
++
++	return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
++				sizeof(struct iwl_qosparam_cmd), qos);
++}
++
++static void iwl_reset_qos(struct iwl_priv *priv)
++{
++	u16 cw_min = 15;
++	u16 cw_max = 1023;
++	u8 aifs = 2;
++	u8 is_legacy = 0;
++	unsigned long flags;
++	int i;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->qos_data.qos_active = 0;
++
++	if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
++		if (priv->qos_data.qos_enable)
++			priv->qos_data.qos_active = 1;
++		if (!(priv->active_rate & 0xfff0)) {
++			cw_min = 31;
++			is_legacy = 1;
++		}
++	} else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
++		if (priv->qos_data.qos_enable)
++			priv->qos_data.qos_active = 1;
++	} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
++		cw_min = 31;
++		is_legacy = 1;
++	}
++
++	if (priv->qos_data.qos_active)
++		aifs = 3;
++
++	priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
++	priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
++	priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
++	priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
++	priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
++
++	if (priv->qos_data.qos_active) {
++		i = 1;
++		priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
++		priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
++		priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
++		priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
++		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++
++		i = 2;
++		priv->qos_data.def_qos_parm.ac[i].cw_min =
++			cpu_to_le16((cw_min + 1) / 2 - 1);
++		priv->qos_data.def_qos_parm.ac[i].cw_max =
++			cpu_to_le16(cw_max);
++		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
++		if (is_legacy)
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(6016);
++		else
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(3008);
++		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++
++		i = 3;
++		priv->qos_data.def_qos_parm.ac[i].cw_min =
++			cpu_to_le16((cw_min + 1) / 4 - 1);
++		priv->qos_data.def_qos_parm.ac[i].cw_max =
++			cpu_to_le16((cw_max + 1) / 2 - 1);
++		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
++		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++		if (is_legacy)
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(3264);
++		else
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(1504);
++	} else {
++		for (i = 1; i < 4; i++) {
++			priv->qos_data.def_qos_parm.ac[i].cw_min =
++				cpu_to_le16(cw_min);
++			priv->qos_data.def_qos_parm.ac[i].cw_max =
++				cpu_to_le16(cw_max);
++			priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
++			priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
++			priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++		}
++	}
++	IWL_DEBUG_QOS("set QoS to default \n");
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++}
++
++static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
++{
++	unsigned long flags;
++
++	if (priv == NULL)
++		return;
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	if (!priv->qos_data.qos_enable)
++		return;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->qos_data.def_qos_parm.qos_flags = 0;
++
++	if (priv->qos_data.qos_cap.q_AP.queue_request &&
++	    !priv->qos_data.qos_cap.q_AP.txop_request)
++		priv->qos_data.def_qos_parm.qos_flags |=
++			QOS_PARAM_FLG_TXOP_TYPE_MSK;
++
++	if (priv->qos_data.qos_active)
++		priv->qos_data.def_qos_parm.qos_flags |=
++			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	if (force || iwl_is_associated(priv)) {
++		IWL_DEBUG_QOS("send QoS cmd with Qos active %d \n",
++			      priv->qos_data.qos_active);
++
++		iwl_send_qos_params_command(priv,
++				&(priv->qos_data.def_qos_parm));
++	}
++}
++
++#endif /* CONFIG_IWLWIFI_QOS */
++/*
++ * Power management (not Tx power!) functions
++ */
++#define MSEC_TO_USEC 1024
++
++#define NOSLP __constant_cpu_to_le32(0)
++#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK
++#define SLP_TIMEOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC)
++#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \
++				     __constant_cpu_to_le32(X1), \
++				     __constant_cpu_to_le32(X2), \
++				     __constant_cpu_to_le32(X3), \
++				     __constant_cpu_to_le32(X4)}
++
++
++/* default power management (not Tx power) table values */
++/* for tim  0-10 */
++static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = {
++	{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
++	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
++	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0},
++	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100), SLP_VEC(2, 6, 9, 9, 10)}, 0},
++	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 10)}, 1},
++	{{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1}
++};
++
++/* for tim > 10 */
++static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = {
++	{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
++	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500),
++		 SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
++	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300),
++		 SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
++	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100),
++		 SLP_VEC(2, 6, 9, 9, 0xFF)}, 0},
++	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
++	{{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25),
++		 SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
++};
++
++int iwl_power_init_handle(struct iwl_priv *priv)
++{
++	int rc = 0, i;
++	struct iwl_power_mgr *pow_data;
++	int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_AC;
++	u16 pci_pm;
++
++	IWL_DEBUG_POWER("Initialize power \n");
++
++	pow_data = &(priv->power_data);
++
++	memset(pow_data, 0, sizeof(*pow_data));
++
++	pow_data->active_index = IWL_POWER_RANGE_0;
++	pow_data->dtim_val = 0xffff;
++
++	memcpy(&pow_data->pwr_range_0[0], &range_0[0], size);
++	memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
++
++	rc = pci_read_config_word(priv->pci_dev, PCI_LINK_CTRL, &pci_pm);
++	if (rc != 0)
++		return 0;
++	else {
++		struct iwl_powertable_cmd *cmd;
++
++		IWL_DEBUG_POWER("adjust power command flags\n");
++
++		for (i = 0; i < IWL_POWER_AC; i++) {
++			cmd = &pow_data->pwr_range_0[i].cmd;
++
++			if (pci_pm & 0x1)
++				cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
++			else
++				cmd->flags |= IWL_POWER_PCI_PM_MSK;
++		}
++	}
++	return rc;
++}
++
++static int iwl_update_power_cmd(struct iwl_priv *priv,
++				struct iwl_powertable_cmd *cmd, u32 mode)
++{
++	int rc = 0, i;
++	u8 skip;
++	u32 max_sleep = 0;
++	struct iwl_power_vec_entry *range;
++	u8 period = 0;
++	struct iwl_power_mgr *pow_data;
++
++	if (mode > IWL_POWER_INDEX_5) {
++		IWL_DEBUG_POWER("Error invalid power mode \n");
++		return -1;
++	}
++	pow_data = &(priv->power_data);
++
++	if (pow_data->active_index == IWL_POWER_RANGE_0)
++		range = &pow_data->pwr_range_0[0];
++	else
++		range = &pow_data->pwr_range_1[1];
++
++	memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd));
++
++#ifdef IWL_MAC80211_DISABLE
++	if (priv->assoc_network != NULL) {
++		unsigned long flags;
++
++		period = priv->assoc_network->tim.tim_period;
++	}
++#endif	/*IWL_MAC80211_DISABLE */
++	skip = range[mode].no_dtim;
++
++	if (period == 0) {
++		period = 1;
++		skip = 0;
++	}
++
++	if (skip == 0) {
++		max_sleep = period;
++		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
++	} else {
++		__le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
++		max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
++		cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
++	}
++
++	for (i = 0; i < IWL_POWER_VEC_SIZE; i++) {
++		if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
++			cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
++	}
++
++	IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags);
++	IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
++	IWL_DEBUG_POWER("Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
++	IWL_DEBUG_POWER("Sleep interval vector = { %d , %d , %d , %d , %d }\n",
++			le32_to_cpu(cmd->sleep_interval[0]),
++			le32_to_cpu(cmd->sleep_interval[1]),
++			le32_to_cpu(cmd->sleep_interval[2]),
++			le32_to_cpu(cmd->sleep_interval[3]),
++			le32_to_cpu(cmd->sleep_interval[4]));
++
++	return rc;
++}
++
++static int iwl_send_power_mode(struct iwl_priv *priv, u32 mode)
++{
++	u32 final_mode = mode;
++	int rc;
++	struct iwl_powertable_cmd cmd;
++
++	/* If on battery, set to 3,
++	 * if plugged into AC power, set to CAM ("continuosly aware mode"),
++	 * else user level */
++	switch (mode) {
++	case IWL_POWER_BATTERY:
++		final_mode = IWL_POWER_INDEX_3;
++		break;
++	case IWL_POWER_AC:
++		final_mode = IWL_POWER_MODE_CAM;
++		break;
++	default:
++		final_mode = mode;
++		break;
++	}
++
++	iwl_update_power_cmd(priv, &cmd, final_mode);
++
++	rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
++
++	if (final_mode == IWL_POWER_MODE_CAM)
++		clear_bit(STATUS_POWER_PMI, &priv->status);
++	else
++		set_bit(STATUS_POWER_PMI, &priv->status);
++
++	return rc;
++}
++
++int iwl_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
++{
++	/* Filter incoming packets to determine if they are targeted toward
++	 * this network, discarding packets coming from ourselves */
++	switch (priv->iw_mode) {
++	case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source    | BSSID */
++		/* packets from our adapter are dropped (echo) */
++		if (!compare_ether_addr(header->addr2, priv->mac_addr))
++			return 0;
++		/* {broad,multi}cast packets to our IBSS go through */
++		if (is_multicast_ether_addr(header->addr1))
++			return !compare_ether_addr(header->addr3, priv->bssid);
++		/* packets to our adapter go through */
++		return !compare_ether_addr(header->addr1, priv->mac_addr);
++	case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
++		/* packets from our adapter are dropped (echo) */
++		if (!compare_ether_addr(header->addr3, priv->mac_addr))
++			return 0;
++		/* {broad,multi}cast packets to our BSS go through */
++		if (is_multicast_ether_addr(header->addr1))
++			return !compare_ether_addr(header->addr2, priv->bssid);
++		/* packets to our adapter go through */
++		return !compare_ether_addr(header->addr1, priv->mac_addr);
++	}
++
++	return 1;
++}
++
++#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
++
++const char *iwl_get_tx_fail_reason(u32 status)
++{
++	switch (status & TX_STATUS_MSK) {
++	case TX_STATUS_SUCCESS:
++		return "SUCCESS";
++		TX_STATUS_ENTRY(SHORT_LIMIT);
++		TX_STATUS_ENTRY(LONG_LIMIT);
++		TX_STATUS_ENTRY(FIFO_UNDERRUN);
++		TX_STATUS_ENTRY(MGMNT_ABORT);
++		TX_STATUS_ENTRY(NEXT_FRAG);
++		TX_STATUS_ENTRY(LIFE_EXPIRE);
++		TX_STATUS_ENTRY(DEST_PS);
++		TX_STATUS_ENTRY(ABORTED);
++		TX_STATUS_ENTRY(BT_RETRY);
++		TX_STATUS_ENTRY(STA_INVALID);
++		TX_STATUS_ENTRY(FRAG_DROPPED);
++		TX_STATUS_ENTRY(TID_DISABLE);
++		TX_STATUS_ENTRY(FRAME_FLUSHED);
++		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
++		TX_STATUS_ENTRY(TX_LOCKED);
++		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
++	}
++
++	return "UNKNOWN";
++}
++
++/**
++ * iwl_scan_cancel - Cancel any currently executing HW scan
++ *
++ * NOTE: priv->mutex is not required before calling this function
++ */
++static int iwl_scan_cancel(struct iwl_priv *priv)
++{
++	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
++		clear_bit(STATUS_SCANNING, &priv->status);
++		return 0;
++	}
++
++	if (test_bit(STATUS_SCANNING, &priv->status)) {
++		if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++			IWL_DEBUG_SCAN("Queuing scan abort.\n");
++			set_bit(STATUS_SCAN_ABORTING, &priv->status);
++			queue_work(priv->workqueue, &priv->abort_scan);
++
++		} else
++			IWL_DEBUG_SCAN("Scan abort already in progress.\n");
++
++		return test_bit(STATUS_SCANNING, &priv->status);
++	}
++
++	return 0;
++}
++
++/**
++ * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
++ * @ms: amount of time to wait (in milliseconds) for scan to abort
++ *
++ * NOTE: priv->mutex must be held before calling this function
++ */
++static int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
++{
++	unsigned long now = jiffies;
++	int ret;
++
++	ret = iwl_scan_cancel(priv);
++	if (ret && ms) {
++		mutex_unlock(&priv->mutex);
++		while (!time_after(jiffies, now + msecs_to_jiffies(ms)) &&
++				test_bit(STATUS_SCANNING, &priv->status))
++			msleep(1);
++		mutex_lock(&priv->mutex);
++
++		return test_bit(STATUS_SCANNING, &priv->status);
++	}
++
++	return ret;
++}
++
++static void iwl_sequence_reset(struct iwl_priv *priv)
++{
++	/* Reset ieee stats */
++
++	/* We don't reset the net_device_stats (ieee->stats) on
++	 * re-association */
++
++	priv->last_seq_num = -1;
++	priv->last_frag_num = -1;
++	priv->last_packet_time = 0;
++
++	iwl_scan_cancel(priv);
++}
++
++#define MAX_UCODE_BEACON_INTERVAL	1024
++#define INTEL_CONN_LISTEN_INTERVAL	__constant_cpu_to_le16(0xA)
++
++static __le16 iwl_adjust_beacon_interval(u16 beacon_val)
++{
++	u16 new_val = 0;
++	u16 beacon_factor = 0;
++
++	beacon_factor =
++	    (beacon_val + MAX_UCODE_BEACON_INTERVAL)
++		/ MAX_UCODE_BEACON_INTERVAL;
++	new_val = beacon_val / beacon_factor;
++
++	return cpu_to_le16(new_val);
++}
++
++static void iwl_setup_rxon_timing(struct iwl_priv *priv)
++{
++	u64 interval_tm_unit;
++	u64 tsf, result;
++	unsigned long flags;
++	struct ieee80211_conf *conf = NULL;
++	u16 beacon_int = 0;
++
++	conf = ieee80211_get_hw_conf(priv->hw);
++
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp1);
++	priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp0);
++
++	priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;
++
++	tsf = priv->timestamp1;
++	tsf = ((tsf << 32) | priv->timestamp0);
++
++	beacon_int = priv->beacon_int;
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
++		if (beacon_int == 0) {
++			priv->rxon_timing.beacon_interval = cpu_to_le16(100);
++			priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
++		} else {
++			priv->rxon_timing.beacon_interval =
++				cpu_to_le16(beacon_int);
++			priv->rxon_timing.beacon_interval =
++			    iwl_adjust_beacon_interval(
++				le16_to_cpu(priv->rxon_timing.beacon_interval));
++		}
++
++		priv->rxon_timing.atim_window = 0;
++	} else {
++		priv->rxon_timing.beacon_interval =
++			iwl_adjust_beacon_interval(conf->beacon_int);
++		/* TODO: we need to get atim_window from upper stack
++		 * for now we set to 0 */
++		priv->rxon_timing.atim_window = 0;
++	}
++
++	interval_tm_unit =
++		(le16_to_cpu(priv->rxon_timing.beacon_interval) * 1024);
++	result = do_div(tsf, interval_tm_unit);
++	priv->rxon_timing.beacon_init_val =
++	    cpu_to_le32((u32) ((u64) interval_tm_unit - result));
++
++	IWL_DEBUG_ASSOC
++	    ("beacon interval %d beacon timer %d beacon tim %d\n",
++		le16_to_cpu(priv->rxon_timing.beacon_interval),
++		le32_to_cpu(priv->rxon_timing.beacon_init_val),
++		le16_to_cpu(priv->rxon_timing.atim_window));
++}
++
++static int iwl_scan_initiate(struct iwl_priv *priv)
++{
++	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
++		IWL_ERROR("APs don't scan.\n");
++		return 0;
++	}
++
++	if (!iwl_is_ready_rf(priv)) {
++		IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
++		return -EIO;
++	}
++
++	if (test_bit(STATUS_SCANNING, &priv->status)) {
++		IWL_DEBUG_SCAN("Scan already in progress.\n");
++		return -EAGAIN;
++	}
++
++	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++		IWL_DEBUG_SCAN("Scan request while abort pending.  "
++			       "Queuing.\n");
++		return -EAGAIN;
++	}
++
++	IWL_DEBUG_INFO("Starting scan...\n");
++	priv->scan_bands = 2;
++	set_bit(STATUS_SCANNING, &priv->status);
++	priv->scan_start = jiffies;
++	priv->scan_pass_start = priv->scan_start;
++
++	queue_work(priv->workqueue, &priv->request_scan);
++
++	return 0;
++}
++
++static int iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
++{
++	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
++
++	if (hw_decrypt)
++		rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
++	else
++		rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
++
++	return 0;
++}
++
++static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode)
++{
++	if (phymode == MODE_IEEE80211A) {
++		priv->staging_rxon.flags &=
++		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
++		      | RXON_FLG_CCK_MSK);
++		priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
++	} else {
++		/* Copied from iwl_bg_post_associate() */
++		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
++			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
++		else
++			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
++
++		if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
++			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
++
++		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
++		priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
++		priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
++	}
++}
++
++/*
++ * initilize rxon structure with default values fromm eeprom
++ */
++static void iwl_connection_init_rx_config(struct iwl_priv *priv)
++{
++	const struct iwl_channel_info *ch_info;
++
++	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
++
++	switch (priv->iw_mode) {
++	case IEEE80211_IF_TYPE_AP:
++		priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
++		break;
++
++	case IEEE80211_IF_TYPE_STA:
++		priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
++		priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
++		break;
++
++	case IEEE80211_IF_TYPE_IBSS:
++		priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
++		priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
++		priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
++						  RXON_FILTER_ACCEPT_GRP_MSK;
++		break;
++
++	case IEEE80211_IF_TYPE_MNTR:
++		priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
++		priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
++		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
++		break;
++	}
++
++#if 0
++	/* TODO:  Figure out when short_preamble would be set and cache from
++	 * that */
++	if (!hw_to_local(priv->hw)->short_preamble)
++		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
++	else
++		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
++#endif
++
++	ch_info = iwl_get_channel_info(priv, priv->phymode,
++				       le16_to_cpu(priv->staging_rxon.channel));
++
++	if (!ch_info)
++		ch_info = &priv->channel_info[0];
++
++	/*
++	 * in some case A channels are all non IBSS
++	 * in this case force B/G channel
++	 */
++	if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
++	    !(is_channel_ibss(ch_info)))
++		ch_info = &priv->channel_info[0];
++
++	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
++	if (is_channel_a_band(ch_info))
++		priv->phymode = MODE_IEEE80211A;
++	else
++		priv->phymode = MODE_IEEE80211G;
++
++	iwl_set_flags_for_phymode(priv, priv->phymode);
++
++	priv->staging_rxon.ofdm_basic_rates =
++	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
++	priv->staging_rxon.cck_basic_rates =
++	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
++}
++
++static int iwl_set_mode(struct iwl_priv *priv, int mode)
++{
++	if (!iwl_is_ready_rf(priv))
++		return -EAGAIN;
++
++	if (mode == IEEE80211_IF_TYPE_IBSS) {
++		const struct iwl_channel_info *ch_info;
++
++		ch_info = iwl_get_channel_info(priv,
++			priv->phymode,
++			le16_to_cpu(priv->staging_rxon.channel));
++
++		if (!ch_info || !is_channel_ibss(ch_info)) {
++			IWL_ERROR("channel %d not IBSS channel\n",
++				  le16_to_cpu(priv->staging_rxon.channel));
++			return -EINVAL;
++		}
++	}
++
++	cancel_delayed_work(&priv->scan_check);
++	if (iwl_scan_cancel_timeout(priv, 100)) {
++		IWL_WARNING("Aborted scan still in progress after 100ms\n");
++		IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
++		return -EAGAIN;
++	}
++
++	priv->iw_mode = mode;
++
++	iwl_connection_init_rx_config(priv);
++	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
++
++	iwl_clear_stations_table(priv);
++
++	iwl_commit_rxon(priv);
++
++	return 0;
++}
++
++static void iwl_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
++				      struct ieee80211_tx_control *ctl,
++				      struct iwl_cmd *cmd,
++				      struct sk_buff *skb_frag,
++				      int last_frag)
++{
++	struct iwl_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
++
++	switch (keyinfo->alg) {
++	case ALG_CCMP:
++		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
++
++		cmd->cmd.tx.hdr[0].frame_control |=
++		    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++		/* XXX: ACK flag must be set for CCMP even if it
++		 * is a multicast/broadcast packet, because CCMP
++		 * group communication encrypted by GTK is
++		 * actually done by the AP. */
++		cmd->cmd.tx.tx_flags |= TX_CMD_FLG_ACK_MSK;
++		memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
++		IWL_DEBUG_TX("tx_cmd with aes  hwcrypto\n");
++		break;
++	case ALG_TKIP:
++#if 0
++		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
++
++		if (last_frag)
++			memcpy(cmd->cmd.tx.tkip_mic.byte, skb_frag->tail - 8,
++			       8);
++		else
++			memset(cmd->cmd.tx.tkip_mic.byte, 0, 8);
++
++		cmd->cmd.tx.hdr[0].frame_control |=
++		    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++		/* XXX: ACK flag must be set for CCMP even if it
++		 * is a multicast/broadcast packet, because CCMP
++		 * group communication encrypted by GTK is
++		 * actually done by the AP. */
++		cmd->cmd.tx.tx_flags |= TX_CMD_FLG_ACK_MSK;
++#endif
++		break;
++	case ALG_WEP:
++		cmd->cmd.tx.sec_ctl = 1 |	/* WEP */
++		    (ctl->key_idx & 0x3) << 6;
++
++		if (keyinfo->keylen == 13)
++			cmd->cmd.tx.sec_ctl |= (1 << 3);	/* 128-bit */
++
++		memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen);
++
++		cmd->cmd.tx.hdr[0].frame_control |=
++		    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++
++		IWL_DEBUG_TX("Configuring packet for WEP encryption "
++			     "with key %d\n", ctl->key_idx);
++		break;
++
++	case ALG_NONE:
++		IWL_DEBUG_TX("Tx packet in the clear "
++			     "(encrypt requested).\n");
++		break;
++
++	default:
++		printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
++		break;
++	}
++
++}
++
++/*
++ * handle build REPLY_TX command notification.
++ */
++static void iwl_build_tx_cmd_basic(struct iwl_priv *priv,
++				  struct iwl_cmd *cmd,
++				  struct ieee80211_tx_control *ctrl,
++				  struct ieee80211_hdr *hdr,
++				  int is_unicast, u8 std_id)
++{
++	__le16 *qc;
++	u16 fc = le16_to_cpu(hdr->frame_control);
++	__le32 tx_flags = cmd->cmd.tx.tx_flags;
++
++	cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
++	if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) {
++		tx_flags |= TX_CMD_FLG_ACK_MSK;
++		if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
++			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
++		if (ieee80211_is_probe_response(fc) &&
++		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
++			tx_flags |= TX_CMD_FLG_TSF_MSK;
++	} else {
++		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
++		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
++	}
++
++	cmd->cmd.tx.sta_id = std_id;
++	if (ieee80211_get_morefrag(hdr))
++		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
++
++	qc = ieee80211_get_qos_ctrl(hdr);
++	if (qc) {
++		cmd->cmd.tx.tid_tspec = (u8) (le16_to_cpu(*qc) & 0xf);
++		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
++	} else
++		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
++
++	if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
++		tx_flags |= TX_CMD_FLG_RTS_MSK;
++		tx_flags &= ~TX_CMD_FLG_CTS_MSK;
++	} else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
++		tx_flags &= ~TX_CMD_FLG_RTS_MSK;
++		tx_flags |= TX_CMD_FLG_CTS_MSK;
++	}
++
++	if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
++		tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
++
++	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
++	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
++		if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ ||
++		    (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
++			cmd->cmd.tx.timeout.pm_frame_timeout =
++				cpu_to_le16(3);
++		else
++			cmd->cmd.tx.timeout.pm_frame_timeout =
++				cpu_to_le16(2);
++	} else
++		cmd->cmd.tx.timeout.pm_frame_timeout = 0;
++
++	cmd->cmd.tx.driver_txop = 0;
++	cmd->cmd.tx.tx_flags = tx_flags;
++	cmd->cmd.tx.next_frame_len = 0;
++}
++
++static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
++{
++	int sta_id;
++	u16 fc = le16_to_cpu(hdr->frame_control);
++
++	/* If this frame is broadcast or not data then use the broadcast
++	 * station id */
++	if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
++	    is_multicast_ether_addr(hdr->addr1))
++		return IWL_BROADCAST_ID;
++
++	switch (priv->iw_mode) {
++
++	/* If this frame is part of a BSS network (we're a station), then
++	 * we use the AP's station id */
++	case IEEE80211_IF_TYPE_STA:
++		return IWL_AP_ID;
++
++	/* If we are an AP, then find the station, or use BCAST */
++	case IEEE80211_IF_TYPE_AP:
++		sta_id = iwl_hw_find_station(priv, hdr->addr1);
++		if (sta_id != IWL_INVALID_STATION)
++			return sta_id;
++		return IWL_BROADCAST_ID;
++
++	/* If this frame is part of a IBSS network, then we use the
++	 * target specific station id */
++	case IEEE80211_IF_TYPE_IBSS:
++		sta_id = iwl_hw_find_station(priv, hdr->addr1);
++		if (sta_id != IWL_INVALID_STATION)
++			return sta_id;
++
++		sta_id = iwl_add_station(priv, hdr->addr1, 0, CMD_ASYNC);
++
++		if (sta_id != IWL_INVALID_STATION)
++			return sta_id;
++
++		IWL_DEBUG_DROP("Station " MAC_FMT " not in station map. "
++			       "Defaulting to broadcast...\n",
++			       MAC_ARG(hdr->addr1));
++		iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
++		return IWL_BROADCAST_ID;
++
++	default:
++		IWL_WARNING("Unkown mode of operation: %d", priv->iw_mode);
++		return IWL_BROADCAST_ID;
++	}
++}
++
++/*
++ * start REPLY_TX command process
++ */
++static int iwl_tx_skb(struct iwl_priv *priv,
++		      struct sk_buff *skb, struct ieee80211_tx_control *ctl)
++{
++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++	struct iwl_tfd_frame *tfd;
++	u32 *control_flags;
++	int txq_id = ctl->queue;
++	struct iwl_tx_queue *txq = NULL;
++	struct iwl_queue *q = NULL;
++	dma_addr_t phys_addr;
++	dma_addr_t txcmd_phys;
++	struct iwl_cmd *out_cmd = NULL;
++	u16 len, idx, len_org;
++	u8 id, hdr_len, unicast;
++	u8 sta_id;
++	u16 seq_number = 0;
++	u16 fc;
++	__le16 *qc;
++	u8 wait_write_ptr = 0;
++	unsigned long flags;
++	int rc;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	if (iwl_is_rfkill(priv)) {
++		IWL_DEBUG_DROP("Dropping - RF KILL\n");
++		goto drop_unlock;
++	}
++
++	if (!priv->interface_id) {
++		IWL_DEBUG_DROP("Dropping - !priv->interface_id\n");
++		goto drop_unlock;
++	}
++
++	if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
++		IWL_ERROR("ERROR: No TX rate available.\n");
++		goto drop_unlock;
++	}
++
++	unicast = !is_multicast_ether_addr(hdr->addr1);
++	id = 0;
++
++	fc = le16_to_cpu(hdr->frame_control);
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (ieee80211_is_auth(fc))
++		IWL_DEBUG_TX("Sending AUTH frame\n");
++	else if (ieee80211_is_assoc_request(fc))
++		IWL_DEBUG_TX("Sending ASSOC frame\n");
++	else if (ieee80211_is_reassoc_request(fc))
++		IWL_DEBUG_TX("Sending REASSOC frame\n");
++#endif
++
++	if (!iwl_is_associated(priv) &&
++	    ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
++		IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
++		goto drop_unlock;
++	}
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	hdr_len = ieee80211_get_hdrlen(fc);
++	sta_id = iwl_get_sta_id(priv, hdr);
++	if (sta_id == IWL_INVALID_STATION) {
++		IWL_DEBUG_DROP("Dropping - INVALID STATION: " MAC_FMT "\n",
++			       MAC_ARG(hdr->addr1));
++		goto drop;
++	}
++
++	IWL_DEBUG_RATE("station Id %d\n", sta_id);
++
++	qc = ieee80211_get_qos_ctrl(hdr);
++	if (qc) {
++		u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
++		seq_number = priv->stations[sta_id].tid[tid].seq_number &
++				IEEE80211_SCTL_SEQ;
++		hdr->seq_ctrl = cpu_to_le16(seq_number) |
++			(hdr->seq_ctrl &
++				__constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
++		seq_number += 0x10;
++	}
++	txq = &priv->txq[txq_id];
++	q = &txq->q;
++
++	spin_lock_irqsave(&priv->lock, flags);
++
++	tfd = &txq->bd[q->first_empty];
++	memset(tfd, 0, sizeof(*tfd));
++	control_flags = (u32 *) tfd;
++	idx = get_cmd_index(q, q->first_empty, 0);
++
++	memset(&(txq->txb[q->first_empty]), 0, sizeof(struct iwl_tx_info));
++	txq->txb[q->first_empty].skb[0] = skb;
++	memcpy(&(txq->txb[q->first_empty].status.control),
++	       ctl, sizeof(struct ieee80211_tx_control));
++	out_cmd = &txq->cmd[idx];
++	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
++	memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx));
++	out_cmd->hdr.cmd = REPLY_TX;
++	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
++				INDEX_TO_SEQ(q->first_empty)));
++	/* copy frags header */
++	memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len);
++
++	/* hdr = (struct ieee80211_hdr *)out_cmd->cmd.tx.hdr; */
++	len = priv->hw_setting.tx_cmd_len +
++		sizeof(struct iwl_cmd_header) + hdr_len;
++
++	len_org = len;
++	len = (len + 3) & ~3;
++
++	if (len_org != len)
++		len_org = 1;
++	else
++		len_org = 0;
++
++	txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
++		     offsetof(struct iwl_cmd, hdr);
++
++	iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
++
++	if (ctl->key_idx != -1)
++		iwl_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
++
++	/* 802.11 null functions have no payload... */
++	len = skb->len - hdr_len;
++	if (len) {
++		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
++					   len, PCI_DMA_TODEVICE);
++		iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
++	}
++
++	/* If there is no payload, then only one TFD is used */
++	if (!len)
++		*control_flags = TFD_CTL_COUNT_SET(1);
++	else
++		*control_flags = TFD_CTL_COUNT_SET(2) |
++			TFD_CTL_PAD_SET(U32_PAD(len));
++
++	len = (u16)skb->len;
++	out_cmd->cmd.tx.len = cpu_to_le16(len);
++
++	/* TODO need this for burst mode later on */
++	iwl_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
++
++	/* set is_hcca to 0; it probably will never be implemented */
++	iwl_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
++
++	out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
++	out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
++
++	if (!ieee80211_get_morefrag(hdr)) {
++		txq->need_update = 1;
++		if (qc) {
++			u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
++			priv->stations[sta_id].tid[tid].seq_number = seq_number;
++		}
++	} else {
++		wait_write_ptr = 1;
++		txq->need_update = 0;
++	}
++
++	iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
++			   sizeof(out_cmd->cmd.tx));
++
++	iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
++			   ieee80211_get_hdrlen(fc));
++
++	q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
++	rc = iwl_tx_queue_update_write_ptr(priv, txq);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	if (rc)
++		return rc;
++
++	if ((iwl_queue_space(q) < q->high_mark)
++	    && priv->mac80211_registered) {
++		if (wait_write_ptr) {
++			spin_lock_irqsave(&priv->lock, flags);
++			txq->need_update = 1;
++			iwl_tx_queue_update_write_ptr(priv, txq);
++			spin_unlock_irqrestore(&priv->lock, flags);
++		}
++
++		ieee80211_stop_queue(priv->hw, ctl->queue);
++	}
++
++	return 0;
++
++drop_unlock:
++	spin_unlock_irqrestore(&priv->lock, flags);
++drop:
++	return -1;
++}
++
++static void iwl_set_rate(struct iwl_priv *priv)
++{
++	const struct ieee80211_hw_mode *hw = NULL;
++	struct ieee80211_rate *rate;
++	int i;
++
++	hw = iwl_get_hw_mode(priv, priv->phymode);
++
++	priv->active_rate = 0;
++	priv->active_rate_basic = 0;
++
++	IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
++		       hw->mode == MODE_IEEE80211A ?
++		       'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
++
++	for (i = 0; i < hw->num_rates; i++) {
++		rate = &(hw->rates[i]);
++		if ((rate->val < IWL_RATE_COUNT) &&
++		    (rate->flags & IEEE80211_RATE_SUPPORTED)) {
++			IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
++				       rate->val, iwl_rates[rate->val].plcp,
++				       (rate->flags & IEEE80211_RATE_BASIC) ?
++				       "*" : "");
++			priv->active_rate |= (1 << rate->val);
++			if (rate->flags & IEEE80211_RATE_BASIC)
++				priv->active_rate_basic |= (1 << rate->val);
++		} else
++			IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
++				       rate->val, iwl_rates[rate->val].plcp);
++	}
++
++	IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
++		       priv->active_rate, priv->active_rate_basic);
++
++	/*
++	 * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK)
++	 * otherwise set it to the default of all CCK rates and 6, 12, 24 for
++	 * OFDM
++	 */
++	if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK)
++		priv->staging_rxon.cck_basic_rates =
++		    ((priv->active_rate_basic &
++		      IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF;
++	else
++		priv->staging_rxon.cck_basic_rates =
++		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
++
++	if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK)
++		priv->staging_rxon.ofdm_basic_rates =
++		    ((priv->active_rate_basic &
++		      (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >>
++		      IWL_FIRST_OFDM_RATE) & 0xFF;
++	else
++		priv->staging_rxon.ofdm_basic_rates =
++		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
++}
++
++static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
++{
++	unsigned long flags;
++
++	if (disable_radio ? 1 : 0 ==
++	    test_bit(STATUS_RF_KILL_SW, &priv->status) ? 1 : 0)
++		return;
++
++	IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO %s\n",
++			  disable_radio ? "OFF" : "ON");
++
++	if (disable_radio) {
++		iwl_scan_cancel(priv);
++		/* FIXME: This is a workaround for AP */
++		if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
++			spin_lock_irqsave(&priv->lock, flags);
++			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
++				    CSR_UCODE_SW_BIT_RFKILL);
++			spin_unlock_irqrestore(&priv->lock, flags);
++			iwl_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
++			set_bit(STATUS_RF_KILL_SW, &priv->status);
++		}
++		return;
++	}
++
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++
++	clear_bit(STATUS_RF_KILL_SW, &priv->status);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	/* wake up ucode */
++	msleep(10);
++
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl_read32(priv, CSR_UCODE_DRV_GP1);
++	if (!iwl_grab_restricted_access(priv))
++		iwl_release_restricted_access(priv);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
++		IWL_DEBUG_RF_KILL("Can not turn radio back on - "
++				  "disabled by HW switch\n");
++		return;
++	}
++
++	queue_work(priv->workqueue, &priv->restart);
++	return;
++}
++
++void iwl_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
++			    u32 decrypt_res, struct ieee80211_rx_status *stats)
++{
++	u16 fc =
++	    le16_to_cpu(((struct ieee80211_hdr *)skb->data)->frame_control);
++
++	if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
++		return;
++
++	if (!(fc & IEEE80211_FCTL_PROTECTED))
++		return;
++
++	IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res);
++	switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
++	case RX_RES_STATUS_SEC_TYPE_TKIP:
++		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
++		    RX_RES_STATUS_BAD_ICV_MIC)
++			stats->flag |= RX_FLAG_MMIC_ERROR;
++	case RX_RES_STATUS_SEC_TYPE_WEP:
++	case RX_RES_STATUS_SEC_TYPE_CCMP:
++		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
++		    RX_RES_STATUS_DECRYPT_OK) {
++			IWL_DEBUG_RX("hw decrypt successfully!!!\n");
++			stats->flag |= RX_FLAG_DECRYPTED;
++		}
++		break;
++
++	default:
++		break;
++	}
++}
++
++void iwl_handle_data_packet_monitor(struct iwl_priv *priv,
++				    struct iwl_rx_mem_buffer *rxb,
++				    void *data, short len,
++				    struct ieee80211_rx_status *stats,
++				    u16 phy_flags)
++{
++	struct iwl_rt_rx_hdr *iwl_rt;
++
++	/* First cache any information we need before we overwrite
++	 * the information provided in the skb from the hardware */
++	s8 signal = stats->ssi;
++	s8 noise = 0;
++	int rate = stats->rate;
++	u64 tsf = stats->mactime;
++	__le16 phy_flags_hw = cpu_to_le16(phy_flags);
++
++	/* We received data from the HW, so stop the watchdog */
++	if (len > IWL_RX_BUF_SIZE - sizeof(*iwl_rt)) {
++		IWL_DEBUG_DROP("Dropping too large packet in monitor\n");
++		return;
++	}
++
++	/* copy the frame data to write after where the radiotap header goes */
++	iwl_rt = (void *)rxb->skb->data;
++	memmove(iwl_rt->payload, data, len);
++
++	iwl_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
++	iwl_rt->rt_hdr.it_pad = 0; /* always good to zero */
++
++	/* total header + data */
++	iwl_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*iwl_rt));
++
++	/* Set the size of the skb to the size of the frame */
++	skb_put(rxb->skb, sizeof(*iwl_rt) + len);
++
++	/* Big bitfield of all the fields we provide in radiotap */
++	iwl_rt->rt_hdr.it_present =
++	    cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
++			(1 << IEEE80211_RADIOTAP_FLAGS) |
++			(1 << IEEE80211_RADIOTAP_RATE) |
++			(1 << IEEE80211_RADIOTAP_CHANNEL) |
++			(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
++			(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
++			(1 << IEEE80211_RADIOTAP_ANTENNA));
++
++	/* Zero the flags, we'll add to them as we go */
++	iwl_rt->rt_flags = 0;
++
++	iwl_rt->rt_tsf = cpu_to_le64(tsf);
++
++	/* Convert to dBm */
++	iwl_rt->rt_dbmsignal = signal;
++	iwl_rt->rt_dbmnoise = noise;
++
++	/* Convert the channel frequency and set the flags */
++	iwl_rt->rt_channelMHz = cpu_to_le16(stats->freq);
++	if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
++		iwl_rt->rt_chbitmask =
++		    cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
++	else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
++		iwl_rt->rt_chbitmask =
++		    cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
++	else	/* 802.11g */
++		iwl_rt->rt_chbitmask =
++		    cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ));
++
++	rate = iwl_rate_index_from_plcp(rate);
++	if (rate == -1)
++		iwl_rt->rt_rate = 0;
++	else
++		iwl_rt->rt_rate = iwl_rates[rate].ieee;
++
++	/* antenna number */
++	iwl_rt->rt_antenna =
++		le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
++
++	/* set the preamble flag if we have it */
++	if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
++		iwl_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
++
++	IWL_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
++
++	stats->flag |= RX_FLAG_RADIOTAP;
++	ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
++	rxb->skb = NULL;
++}
++
++
++#define IWL_PACKET_RETRY_TIME HZ
++
++int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
++{
++	u16 sc = le16_to_cpu(header->seq_ctrl);
++	u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
++	u16 frag = sc & IEEE80211_SCTL_FRAG;
++	u16 *last_seq, *last_frag;
++	unsigned long *last_time;
++
++	switch (priv->iw_mode) {
++	case IEEE80211_IF_TYPE_IBSS:{
++		struct list_head *p;
++		struct iwl_ibss_seq *entry = NULL;
++		u8 *mac = header->addr2;
++		int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
++
++		__list_for_each(p, &priv->ibss_mac_hash[index]) {
++			entry =
++				list_entry(p, struct iwl_ibss_seq, list);
++			if (!compare_ether_addr(entry->mac, mac))
++				break;
++		}
++		if (p == &priv->ibss_mac_hash[index]) {
++			entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
++			if (!entry) {
++				IWL_ERROR
++					("Cannot malloc new mac entry\n");
++				return 0;
++			}
++			memcpy(entry->mac, mac, ETH_ALEN);
++			entry->seq_num = seq;
++			entry->frag_num = frag;
++			entry->packet_time = jiffies;
++			list_add(&entry->list,
++				 &priv->ibss_mac_hash[index]);
++			return 0;
++		}
++		last_seq = &entry->seq_num;
++		last_frag = &entry->frag_num;
++		last_time = &entry->packet_time;
++		break;
++	}
++	case IEEE80211_IF_TYPE_STA:
++		last_seq = &priv->last_seq_num;
++		last_frag = &priv->last_frag_num;
++		last_time = &priv->last_packet_time;
++		break;
++	default:
++		return 0;
++	}
++	if ((*last_seq == seq) &&
++	    time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
++		if (*last_frag == frag)
++			goto drop;
++		if (*last_frag + 1 != frag)
++			/* out-of-order fragment */
++			goto drop;
++	} else
++		*last_seq = seq;
++
++	*last_frag = frag;
++	*last_time = jiffies;
++	return 0;
++
++ drop:
++	return 1;
++}
++
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++
++#include "iwl-spectrum.h"
++
++#define BEACON_TIME_MASK_LOW	0x00FFFFFF
++#define BEACON_TIME_MASK_HIGH	0xFF000000
++#define TIME_UNIT		1024
++
++/*
++ * extended beacon time format
++ * time in usec will be changed into a 32-bit value in 8:24 format
++ * the high 1 byte is the beacon counts
++ * the lower 3 bytes is the time in usec within one beacon interval
++ */
++
++static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
++{
++	u32 quot;
++	u32 rem;
++	u32 interval = beacon_interval * 1024;
++
++	if (!interval || !usec)
++		return 0;
++
++	quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
++	rem = (usec % interval) & BEACON_TIME_MASK_LOW;
++
++	return (quot << 24) + rem;
++}
++
++/* base is usually what we get from ucode with each received frame,
++ * the same as HW timer counter counting down
++ */
++
++static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
++{
++	u32 base_low = base & BEACON_TIME_MASK_LOW;
++	u32 addon_low = addon & BEACON_TIME_MASK_LOW;
++	u32 interval = beacon_interval * TIME_UNIT;
++	u32 res = (base & BEACON_TIME_MASK_HIGH) +
++	    (addon & BEACON_TIME_MASK_HIGH);
++
++	if (base_low > addon_low)
++		res += base_low - addon_low;
++	else if (base_low < addon_low) {
++		res += interval + base_low - addon_low;
++		res += (1 << 24);
++	} else
++		res += (1 << 24);
++
++	return cpu_to_le32(res);
++}
++
++static int iwl_get_measurement(struct iwl_priv *priv,
++			       struct ieee80211_measurement_params *params,
++			       u8 type)
++{
++	struct iwl_spectrum_cmd spectrum;
++	struct iwl_rx_packet *res;
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
++		.data = (void *)&spectrum,
++		.meta.flags = CMD_WANT_SKB,
++	};
++	u32 add_time = le64_to_cpu(params->start_time);
++	int rc;
++	int spectrum_resp_status;
++	int duration = le16_to_cpu(params->duration);
++
++	if (iwl_is_associated(priv))
++		add_time =
++		    iwl_usecs_to_beacons(
++			le64_to_cpu(params->start_time) - priv->last_tsf,
++			le16_to_cpu(priv->rxon_timing.beacon_interval));
++
++	memset(&spectrum, 0, sizeof(spectrum));
++
++	spectrum.channel_count = cpu_to_le16(1);
++	spectrum.flags =
++	    RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
++	spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
++	cmd.len = sizeof(spectrum);
++	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
++
++	if (iwl_is_associated(priv))
++		spectrum.start_time =
++		    iwl_add_beacon_time(priv->last_beacon_time,
++				add_time,
++				le16_to_cpu(priv->rxon_timing.beacon_interval));
++	else
++		spectrum.start_time = 0;
++
++	spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
++	spectrum.channels[0].channel = params->channel;
++	spectrum.channels[0].type = type;
++	if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
++		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
++		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
++
++	rc = iwl_send_cmd_sync(priv, &cmd);
++	if (rc)
++		return rc;
++
++	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
++	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
++		IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n");
++		rc = -EIO;
++	}
++
++	spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
++	switch (spectrum_resp_status) {
++	case 0:		/* Command will be handled */
++		if (res->u.spectrum.id != 0xff) {
++			IWL_DEBUG_INFO
++			    ("Replaced existing measurement: %d\n",
++			     res->u.spectrum.id);
++			priv->measurement_status &= ~MEASUREMENT_READY;
++		}
++		priv->measurement_status |= MEASUREMENT_ACTIVE;
++		rc = 0;
++		break;
++
++	case 1:		/* Command will not be handled */
++		rc = -EAGAIN;
++		break;
++	}
++
++	dev_kfree_skb_any(cmd.meta.u.skb);
++
++	return rc;
++}
++#endif
++
++static void iwl_txstatus_to_ieee(struct iwl_priv *priv,
++				 struct iwl_tx_info *tx_sta)
++{
++
++	tx_sta->status.ack_signal = 0;
++	tx_sta->status.excessive_retries = 0;
++	tx_sta->status.queue_length = 0;
++	tx_sta->status.queue_number = 0;
++
++	if (in_interrupt())
++		ieee80211_tx_status_irqsafe(priv->hw,
++					    tx_sta->skb[0], &(tx_sta->status));
++	else
++		ieee80211_tx_status(priv->hw,
++				    tx_sta->skb[0], &(tx_sta->status));
++
++	tx_sta->skb[0] = NULL;
++}
++
++/**
++ * iwl_tx_queue_reclaim - Reclaim Tx queue entries no more used by NIC.
++ *
++ * When FW advances 'R' index, all entries between old and
++ * new 'R' index need to be reclaimed. As result, some free space
++ * forms. If there is enough free space (> low mark), wake Tx queue.
++ */
++int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
++{
++	struct iwl_tx_queue *txq = &priv->txq[txq_id];
++	struct iwl_queue *q = &txq->q;
++	int nfreed = 0;
++
++	if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) {
++		IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
++			  "is out of range [0-%d] %d %d.\n", txq_id,
++			  index, q->n_bd, q->first_empty, q->last_used);
++		return 0;
++	}
++
++	for (index = iwl_queue_inc_wrap(index, q->n_bd);
++		q->last_used != index;
++		q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd)) {
++		if (txq_id != IWL_CMD_QUEUE_NUM) {
++			iwl_txstatus_to_ieee(priv,
++					&(txq->txb[txq->q.last_used]));
++			iwl_hw_txq_free_tfd(priv, txq);
++		} else if (nfreed > 1) {
++			IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
++					q->first_empty, q->last_used);
++			queue_work(priv->workqueue, &priv->restart);
++		}
++		nfreed++;
++	}
++
++	if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
++			(txq_id != IWL_CMD_QUEUE_NUM) &&
++			priv->mac80211_registered)
++		ieee80211_wake_queue(priv->hw, txq_id);
++
++
++	return nfreed;
++}
++
++static int iwl_is_tx_success(u32 status)
++{
++	return (status & 0xFF) == 0x1;
++}
++
++/******************************************************************************
++ *
++ * Generic RX handler implementations
++ *
++ ******************************************************************************/
++static void iwl_rx_reply_tx(struct iwl_priv *priv,
++			    struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
++	int txq_id = SEQ_TO_QUEUE(sequence);
++	int index = SEQ_TO_INDEX(sequence);
++	struct iwl_tx_queue *txq = &priv->txq[txq_id];
++	struct ieee80211_tx_status *tx_status;
++	struct iwl_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
++	u32  status = le32_to_cpu(tx_resp->status);
++
++	if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
++		IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
++			  "is out of range [0-%d] %d %d\n", txq_id,
++			  index, txq->q.n_bd, txq->q.first_empty,
++			  txq->q.last_used);
++		return;
++	}
++
++	tx_status = &(txq->txb[txq->q.last_used].status);
++
++	tx_status->retry_count = tx_resp->failure_frame;
++	tx_status->queue_number = status;
++	tx_status->queue_length = tx_resp->bt_kill_count;
++	tx_status->queue_length |= tx_resp->failure_rts;
++
++	tx_status->flags =
++	    iwl_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
++
++	tx_status->control.tx_rate = iwl_rate_index_from_plcp(tx_resp->rate);
++
++	IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
++			txq_id, iwl_get_tx_fail_reason(status), status,
++			tx_resp->rate, tx_resp->failure_frame);
++
++	IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
++	if (index != -1)
++		iwl_tx_queue_reclaim(priv, txq_id, index);
++
++	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
++		IWL_ERROR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
++}
++
++
++static void iwl_rx_reply_alive(struct iwl_priv *priv,
++			       struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_alive_resp *palive;
++	struct delayed_work *pwork;
++
++	palive = &pkt->u.alive_frame;
++
++	IWL_DEBUG_INFO("Alive ucode status 0x%08X revision "
++		       "0x%01X 0x%01X\n",
++		       palive->is_valid, palive->ver_type,
++		       palive->ver_subtype);
++
++	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
++		IWL_DEBUG_INFO("Initialization Alive received.\n");
++		memcpy(&priv->card_alive_init,
++		       &pkt->u.alive_frame,
++		       sizeof(struct iwl_init_alive_resp));
++		pwork = &priv->init_alive_start;
++	} else {
++		IWL_DEBUG_INFO("Runtime Alive received.\n");
++		memcpy(&priv->card_alive, &pkt->u.alive_frame,
++		       sizeof(struct iwl_alive_resp));
++		pwork = &priv->alive_start;
++		iwl_disable_events(priv);
++	}
++
++	/* We delay the ALIVE response by 5ms to
++	 * give the HW RF Kill time to activate... */
++	if (palive->is_valid == UCODE_VALID_OK)
++		queue_delayed_work(priv->workqueue, pwork,
++				   msecs_to_jiffies(5));
++	else
++		IWL_WARNING("uCode did not respond OK.\n");
++}
++
++static void iwl_rx_reply_add_sta(struct iwl_priv *priv,
++				 struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++
++	IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
++	return;
++}
++
++static void iwl_rx_reply_error(struct iwl_priv *priv,
++			       struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++
++	IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) "
++		"seq 0x%04X ser 0x%08X\n",
++		le32_to_cpu(pkt->u.err_resp.error_type),
++		get_cmd_string(pkt->u.err_resp.cmd_id),
++		pkt->u.err_resp.cmd_id,
++		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
++		le32_to_cpu(pkt->u.err_resp.error_info));
++}
++
++#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
++
++static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
++	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
++	IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
++		      le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
++	rxon->channel = csa->channel;
++	priv->staging_rxon.channel = csa->channel;
++}
++
++static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
++					  struct iwl_rx_mem_buffer *rxb)
++{
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
++
++	if (!report->state) {
++		IWL_DEBUG(IWL_DL_11H | IWL_DL_INFO,
++			  "Spectrum Measure Notification: Start\n");
++		return;
++	}
++
++	memcpy(&priv->measure_report, report, sizeof(*report));
++	priv->measurement_status |= MEASUREMENT_READY;
++#endif
++}
++
++static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
++				  struct iwl_rx_mem_buffer *rxb)
++{
++#ifdef CONFIG_IWLWIFI_DEBUG
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
++	IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
++		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
++#endif
++}
++
++static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
++					     struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
++			"notification for %s:\n",
++			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
++	iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
++}
++
++static void iwl_bg_beacon_update(struct work_struct *work)
++{
++	struct iwl_priv *priv =
++		container_of(work, struct iwl_priv, beacon_update);
++	struct sk_buff *beacon;
++
++	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
++	beacon = ieee80211_beacon_get(priv->hw, priv->interface_id, NULL);
++
++	if (!beacon) {
++		IWL_ERROR("update beacon failed\n");
++		return;
++	}
++
++	mutex_lock(&priv->mutex);
++	/* new beacon skb is allocated every time; dispose previous.*/
++	if (priv->ibss_beacon)
++		dev_kfree_skb(priv->ibss_beacon);
++
++	priv->ibss_beacon = beacon;
++	mutex_unlock(&priv->mutex);
++
++	iwl_send_beacon_cmd(priv);
++}
++
++static void iwl_rx_beacon_notif(struct iwl_priv *priv,
++				struct iwl_rx_mem_buffer *rxb)
++{
++#ifdef CONFIG_IWLWIFI_DEBUG
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_beacon_notif *beacon = &(pkt->u.beacon_status);
++	u8 rate = beacon->beacon_notify_hdr.rate;
++
++	IWL_DEBUG_RX("beacon status %x retries %d iss %d "
++		"tsf %d %d rate %d\n",
++		le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
++		beacon->beacon_notify_hdr.failure_frame,
++		le32_to_cpu(beacon->ibss_mgr_status),
++		le32_to_cpu(beacon->high_tsf),
++		le32_to_cpu(beacon->low_tsf), rate);
++#endif
++
++	if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
++	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
++		queue_work(priv->workqueue, &priv->beacon_update);
++}
++
++/* Service response to REPLY_SCAN_CMD (0x80) */
++static void iwl_rx_reply_scan(struct iwl_priv *priv,
++			      struct iwl_rx_mem_buffer *rxb)
++{
++#ifdef CONFIG_IWLWIFI_DEBUG
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_scanreq_notification *notif =
++	    (struct iwl_scanreq_notification *)pkt->u.raw;
++
++	IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status);
++#endif
++}
++
++/* Service SCAN_START_NOTIFICATION (0x82) */
++static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
++				    struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_scanstart_notification *notif =
++	    (struct iwl_scanstart_notification *)pkt->u.raw;
++	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
++	IWL_DEBUG_SCAN("Scan start: "
++		       "%d [802.11%s] "
++		       "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
++		       notif->channel,
++		       notif->band ? "bg" : "a",
++		       notif->tsf_high,
++		       notif->tsf_low, notif->status, notif->beacon_timer);
++}
++
++/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
++static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
++				      struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_scanresults_notification *notif =
++	    (struct iwl_scanresults_notification *)pkt->u.raw;
++
++	IWL_DEBUG_SCAN("Scan ch.res: "
++		       "%d [802.11%s] "
++		       "(TSF: 0x%08X:%08X) - %d "
++		       "elapsed=%lu usec (%dms since last)\n",
++		       notif->channel,
++		       notif->band ? "bg" : "a",
++		       le32_to_cpu(notif->tsf_high),
++		       le32_to_cpu(notif->tsf_low),
++		       le32_to_cpu(notif->statistics[0]),
++		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf,
++		       jiffies_to_msecs(elapsed_jiffies
++					(priv->last_scan_jiffies, jiffies)));
++
++	priv->last_scan_jiffies = jiffies;
++}
++
++/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
++static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
++				       struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
++
++	IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
++		       scan_notif->scanned_channels,
++		       scan_notif->tsf_low,
++		       scan_notif->tsf_high, scan_notif->status);
++
++	/* The HW is no longer scanning */
++	clear_bit(STATUS_SCAN_HW, &priv->status);
++
++	/* The scan completion notification came in, so kill that timer... */
++	cancel_delayed_work(&priv->scan_check);
++
++	IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n",
++		       (priv->scan_bands == 2) ? "2.4" : "5.2",
++		       jiffies_to_msecs(elapsed_jiffies
++					(priv->scan_pass_start, jiffies)));
++
++	/* Remove this scanned band from the list
++	 * of pending bands to scan */
++	priv->scan_bands--;
++
++	/* If a request to abort was given, or the scan did not succeed
++	 * then we reset the scan state machine and terminate,
++	 * re-queuing another scan if one has been requested */
++	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++		IWL_DEBUG_INFO("Aborted scan completed.\n");
++		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
++	} else {
++		/* If there are more bands on this scan pass reschedule */
++		if (priv->scan_bands > 0)
++			goto reschedule;
++	}
++
++	priv->last_scan_jiffies = jiffies;
++	IWL_DEBUG_INFO("Setting scan to off\n");
++
++	clear_bit(STATUS_SCANNING, &priv->status);
++
++	IWL_DEBUG_INFO("Scan took %dms\n",
++		jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));
++
++	queue_work(priv->workqueue, &priv->scan_completed);
++
++	return;
++
++reschedule:
++	priv->scan_pass_start = jiffies;
++	queue_work(priv->workqueue, &priv->request_scan);
++}
++
++/* Handle notification from uCode that card's power state is changing
++ * due to software, hardware, or critical temperature RFKILL */
++static void iwl_rx_card_state_notif(struct iwl_priv *priv,
++				    struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
++	unsigned long status = priv->status;
++
++	IWL_DEBUG_RF_KILL("Card state received: HW:%s SW:%s\n",
++			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
++			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");
++
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
++		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
++
++	if (flags & HW_CARD_DISABLED)
++		set_bit(STATUS_RF_KILL_HW, &priv->status);
++	else
++		clear_bit(STATUS_RF_KILL_HW, &priv->status);
++
++
++	if (flags & SW_CARD_DISABLED)
++		set_bit(STATUS_RF_KILL_SW, &priv->status);
++	else
++		clear_bit(STATUS_RF_KILL_SW, &priv->status);
++
++	iwl_scan_cancel(priv);
++
++	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
++	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
++	    (test_bit(STATUS_RF_KILL_SW, &status) !=
++	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
++		queue_work(priv->workqueue, &priv->rf_kill);
++	else
++		wake_up_interruptible(&priv->wait_command_queue);
++}
++
++/**
++ * iwl_setup_rx_handlers - Initialize Rx handler callbacks
++ *
++ * Setup the RX handlers for each of the reply types sent from the uCode
++ * to the host.
++ *
++ * This function chains into the hardware specific files for them to setup
++ * any hardware specific handlers as well.
++ */
++static void iwl_setup_rx_handlers(struct iwl_priv *priv)
++{
++	priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
++	priv->rx_handlers[REPLY_ADD_STA] = iwl_rx_reply_add_sta;
++	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
++	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
++	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
++	    iwl_rx_spectrum_measure_notif;
++	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
++	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
++	    iwl_rx_pm_debug_statistics_notif;
++	priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
++
++	/* NOTE:  iwl_rx_statistics is different based on whether
++	 * the build is for the 3945 or the 4965.  See the
++	 * corresponding implementation in iwl-XXXX.c
++	 *
++	 * The same handler is used for both the REPLY to a
++	 * discrete statistics request from the host as well as
++	 * for the periodic statistics notification from the uCode
++	 */
++	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_hw_rx_statistics;
++	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_hw_rx_statistics;
++
++	priv->rx_handlers[REPLY_SCAN_CMD] = iwl_rx_reply_scan;
++	priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl_rx_scan_start_notif;
++	priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
++	    iwl_rx_scan_results_notif;
++	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
++	    iwl_rx_scan_complete_notif;
++	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
++	priv->rx_handlers[REPLY_TX] = iwl_rx_reply_tx;
++
++	/* Setup hardware specific Rx handlers */
++	iwl_hw_rx_handler_setup(priv);
++}
++
++/**
++ * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
++ * @rxb: Rx buffer to reclaim
++ *
++ * If an Rx buffer has an async callback associated with it the callback
++ * will be executed.  The attached skb (if present) will only be freed
++ * if the callback returns 1
++ */
++static void iwl_tx_cmd_complete(struct iwl_priv *priv,
++				struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
++	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
++	int txq_id = SEQ_TO_QUEUE(sequence);
++	int index = SEQ_TO_INDEX(sequence);
++	int huge = sequence & SEQ_HUGE_FRAME;
++	int cmd_index;
++	struct iwl_cmd *cmd;
++
++	/* If a Tx command is being handled and it isn't in the actual
++	 * command queue then there a command routing bug has been introduced
++	 * in the queue management code. */
++	if (txq_id != IWL_CMD_QUEUE_NUM)
++		IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
++			  txq_id, pkt->hdr.cmd);
++	BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
++
++	cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
++	cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
++
++	/* Input error checking is done when commands are added to queue. */
++	if (cmd->meta.flags & CMD_WANT_SKB) {
++		cmd->meta.source->u.skb = rxb->skb;
++		rxb->skb = NULL;
++	} else if (cmd->meta.u.callback &&
++		   !cmd->meta.u.callback(priv, cmd, rxb->skb))
++		rxb->skb = NULL;
++
++	iwl_tx_queue_reclaim(priv, txq_id, index);
++
++	if (!(cmd->meta.flags & CMD_ASYNC)) {
++		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
++		wake_up_interruptible(&priv->wait_command_queue);
++	}
++}
++
++/************************** RX-FUNCTIONS ****************************/
++/*
++ * Rx theory of operation
++ *
++ * The host allocates 32 DMA target addresses and passes the host address
++ * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
++ * 0 to 31
++ *
++ * Rx Queue Indexes
++ * The host/firmware share two index registers for managing the Rx buffers.
++ *
++ * The READ index maps to the first position that the firmware may be writing
++ * to -- the driver can read up to (but not including) this position and get
++ * good data.
++ * The READ index is managed by the firmware once the card is enabled.
++ *
++ * The WRITE index maps to the last position the driver has read from -- the
++ * position preceding WRITE is the last slot the firmware can place a packet.
++ *
++ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
++ * WRITE = READ.
++ *
++ * During initialization the host sets up the READ queue position to the first
++ * INDEX position, and WRITE to the last (READ - 1 wrapped)
++ *
++ * When the firmware places a packet in a buffer it will advance the READ index
++ * and fire the RX interrupt.  The driver can then query the READ index and
++ * process as many packets as possible, moving the WRITE index forward as it
++ * resets the Rx queue buffers with new memory.
++ *
++ * The management in the driver is as follows:
++ * + A list of pre-allocated SKBs is stored in ipw->rxq->rx_free.  When
++ *   ipw->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
++ *   to replensish the ipw->rxq->rx_free.
++ * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
++ *   ipw->rxq is replenished and the READ INDEX is updated (updating the
++ *   'processed' and 'read' driver indexes as well)
++ * + A received packet is processed and handed to the kernel network stack,
++ *   detached from the ipw->rxq.  The driver 'processed' index is updated.
++ * + The Host/Firmware ipw->rxq is replenished at tasklet time from the rx_free
++ *   list. If there are no allocated buffers in ipw->rxq->rx_free, the READ
++ *   INDEX is not incremented and ipw->status(RX_STALLED) is set.  If there
++ *   were enough free buffers and RX_STALLED is set it is cleared.
++ *
++ *
++ * Driver sequence:
++ *
++ * iwl_rx_queue_alloc()       Allocates rx_free
++ * iwl_rx_replenish()         Replenishes rx_free list from rx_used, and calls
++ *                            iwl_rx_queue_restock
++ * iwl_rx_queue_restock()     Moves available buffers from rx_free into Rx
++ *                            queue, updates firmware pointers, and updates
++ *                            the WRITE index.  If insufficient rx_free buffers
++ *                            are available, schedules iwl_rx_replenish
++ *
++ * -- enable interrupts --
++ * ISR - iwl_rx()             Detach iwl_rx_mem_buffers from pool up to the
++ *                            READ INDEX, detaching the SKB from the pool.
++ *                            Moves the packet buffer from queue to rx_used.
++ *                            Calls iwl_rx_queue_restock to refill any empty
++ *                            slots.
++ * ...
++ *
++ */
++
++/**
++ * iwl_rx_queue_space - Return number of free slots available in queue.
++ */
++static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
++{
++	int s = q->read - q->write;
++	if (s <= 0)
++		s += RX_QUEUE_SIZE;
++	/* keep some buffer to not confuse full and empty queue */
++	s -= 2;
++	if (s < 0)
++		s = 0;
++	return s;
++}
++
++/**
++ * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
++ *
++ * NOTE: This function has 3945 and 4965 specific code sections
++ * but is declared in base due to the majority of the
++ * implementation being the same (only a numeric constant is
++ * different)
++ *
++ */
++int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
++{
++	u32 reg = 0;
++	int rc = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&q->lock, flags);
++
++	if (q->need_update == 0)
++		goto exit_unlock;
++
++	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
++		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
++
++		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
++			iwl_set_bit(priv, CSR_GP_CNTRL,
++				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++			goto exit_unlock;
++		}
++
++		rc = iwl_grab_restricted_access(priv);
++		if (rc)
++			goto exit_unlock;
++
++		iwl_write_restricted(priv, FH_RSCSR_CHNL0_WPTR,
++				     q->write & ~0x7);
++		iwl_release_restricted_access(priv);
++	} else
++		iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
++
++
++	q->need_update = 0;
++
++ exit_unlock:
++	spin_unlock_irqrestore(&q->lock, flags);
++	return rc;
++}
++
++/**
++ * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer pointer.
++ *
++ * NOTE: This function has 3945 and 4965 specific code paths in it.
++ */
++static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
++					  dma_addr_t dma_addr)
++{
++	return cpu_to_le32((u32)dma_addr);
++}
++
++/**
++ * iwl_rx_queue_restock - refill RX queue from pre-allocated pool
++ *
++ * If there are slots in the RX queue that  need to be restocked,
++ * and we have free pre-allocated buffers, fill the ranks as much
++ * as we can pulling from rx_free.
++ *
++ * This moves the 'write' index forward to catch up with 'processed', and
++ * also updates the memory address in the firmware to reference the new
++ * target buffer.
++ */
++int iwl_rx_queue_restock(struct iwl_priv *priv)
++{
++	struct iwl_rx_queue *rxq = &priv->rxq;
++	struct list_head *element;
++	struct iwl_rx_mem_buffer *rxb;
++	unsigned long flags;
++	int write, rc;
++
++	spin_lock_irqsave(&rxq->lock, flags);
++	write = rxq->write & ~0x7;
++	while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
++		element = rxq->rx_free.next;
++		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
++		list_del(element);
++		rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->dma_addr);
++		rxq->queue[rxq->write] = rxb;
++		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
++		rxq->free_count--;
++	}
++	spin_unlock_irqrestore(&rxq->lock, flags);
++	/* If the pre-allocated buffer pool is dropping low, schedule to
++	 * refill it */
++	if (rxq->free_count <= RX_LOW_WATERMARK)
++		queue_work(priv->workqueue, &priv->rx_replenish);
++
++
++	/* If we've added more space for the firmware to place data, tell it */
++	if ((write != (rxq->write & ~0x7))
++	    || (abs(rxq->write - rxq->read) > 7)) {
++		spin_lock_irqsave(&rxq->lock, flags);
++		rxq->need_update = 1;
++		spin_unlock_irqrestore(&rxq->lock, flags);
++		rc = iwl_rx_queue_update_write_ptr(priv, rxq);
++		if (rc)
++			return rc;
++	}
++
++	return 0;
++}
++
++/**
++ * iwl_rx_replensih - Move all used packet from rx_used to rx_free
++ *
++ * When moving to rx_free an SKB is allocated for the slot.
++ *
++ * Also restock the Rx queue via iwl_rx_queue_restock.
++ * This is called as a scheduled work item (except for during intialization)
++ */
++void iwl_rx_replenish(void *data)
++{
++	struct iwl_priv *priv = data;
++	struct iwl_rx_queue *rxq = &priv->rxq;
++	struct list_head *element;
++	struct iwl_rx_mem_buffer *rxb;
++	unsigned long flags;
++	spin_lock_irqsave(&rxq->lock, flags);
++	while (!list_empty(&rxq->rx_used)) {
++		element = rxq->rx_used.next;
++		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
++		rxb->skb =
++		    alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC);
++		if (!rxb->skb) {
++			if (net_ratelimit())
++				printk(KERN_CRIT DRV_NAME
++				       ": Can not allocate SKB buffers\n");
++			/* We don't reschedule replenish work here -- we will
++			 * call the restock method and if it still needs
++			 * more buffers it will schedule replenish */
++			break;
++		}
++		priv->alloc_rxb_skb++;
++		list_del(element);
++		rxb->dma_addr =
++		    pci_map_single(priv->pci_dev, rxb->skb->data,
++				   IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
++		list_add_tail(&rxb->list, &rxq->rx_free);
++		rxq->free_count++;
++	}
++	spin_unlock_irqrestore(&rxq->lock, flags);
++
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl_rx_queue_restock(priv);
++	spin_unlock_irqrestore(&priv->lock, flags);
++}
++
++/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
++ * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
++ * This free routine walks the list of POOL entries and if SKB is set to
++ * non NULL it is unmapped and freed
++ */
++void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
++{
++	int i;
++	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
++		if (rxq->pool[i].skb != NULL) {
++			pci_unmap_single(priv->pci_dev,
++					 rxq->pool[i].dma_addr,
++					 IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
++			dev_kfree_skb(rxq->pool[i].skb);
++		}
++	}
++
++	pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
++			    rxq->dma_addr);
++	rxq->bd = NULL;
++}
++
++int iwl_rx_queue_alloc(struct iwl_priv *priv)
++{
++	struct iwl_rx_queue *rxq = &priv->rxq;
++	struct pci_dev *dev = priv->pci_dev;
++	int i;
++
++	spin_lock_init(&rxq->lock);
++	INIT_LIST_HEAD(&rxq->rx_free);
++	INIT_LIST_HEAD(&rxq->rx_used);
++	rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
++	if (!rxq->bd)
++		return -ENOMEM;
++	/* Fill the rx_used queue with _all_ of the Rx buffers */
++	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
++		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
++	/* Set us so that we have processed and used all buffers, but have
++	 * not restocked the Rx queue with fresh buffers */
++	rxq->read = rxq->write = 0;
++	rxq->free_count = 0;
++	rxq->need_update = 0;
++	return 0;
++}
++
++void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
++{
++	unsigned long flags;
++	int i;
++	spin_lock_irqsave(&rxq->lock, flags);
++	INIT_LIST_HEAD(&rxq->rx_free);
++	INIT_LIST_HEAD(&rxq->rx_used);
++	/* Fill the rx_used queue with _all_ of the Rx buffers */
++	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
++		/* In the reset function, these buffers may have been allocated
++		 * to an SKB, so we need to unmap and free potential storage */
++		if (rxq->pool[i].skb != NULL) {
++			pci_unmap_single(priv->pci_dev,
++					 rxq->pool[i].dma_addr,
++					 IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
++			priv->alloc_rxb_skb--;
++			dev_kfree_skb(rxq->pool[i].skb);
++			rxq->pool[i].skb = NULL;
++		}
++		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
++	}
++
++	/* Set us so that we have processed and used all buffers, but have
++	 * not restocked the Rx queue with fresh buffers */
++	rxq->read = rxq->write = 0;
++	rxq->free_count = 0;
++	spin_unlock_irqrestore(&rxq->lock, flags);
++}
++
++/* Convert linear signal-to-noise ratio into dB */
++static u8 ratio2dB[100] = {
++/*	 0   1   2   3   4   5   6   7   8   9 */
++	 0,  0,  6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
++	20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
++	26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
++	29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
++	32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
++	34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
++	36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
++	37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
++	38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
++	39, 39, 39, 39, 39, 40, 40, 40, 40, 40  /* 90 - 99 */
++};
++
++/* Calculates a relative dB value from a ratio of linear
++ *   (i.e. not dB) signal levels.
++ * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
++int iwl_calc_db_from_ratio(int sig_ratio)
++{
++	/* Anything above 1000:1 just report as 60 dB */
++	if (sig_ratio > 1000)
++		return 60;
++
++	/* Above 100:1, divide by 10 and use table,
++	 *   add 20 dB to make up for divide by 10 */
++	if (sig_ratio > 100)
++		return (20 + (int)ratio2dB[sig_ratio/10]);
++
++	/* We shouldn't see this */
++	if (sig_ratio < 1)
++		return 0;
++
++	/* Use table for ratios 1:1 - 99:1 */
++	return (int)ratio2dB[sig_ratio];
++}
++
++#define PERFECT_RSSI (-20) /* dBm */
++#define WORST_RSSI (-95)   /* dBm */
++#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
++
++/* Calculate an indication of rx signal quality (a percentage, not dBm!).
++ * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
++ *   about formulas used below. */
++int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
++{
++	int sig_qual;
++	int degradation = PERFECT_RSSI - rssi_dbm;
++
++	/* If we get a noise measurement, use signal-to-noise ratio (SNR)
++	 * as indicator; formula is (signal dbm - noise dbm).
++	 * SNR at or above 40 is a great signal (100%).
++	 * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
++	 * Weakest usable signal is usually 10 - 15 dB SNR. */
++	if (noise_dbm) {
++		if (rssi_dbm - noise_dbm >= 40)
++			return 100;
++		else if (rssi_dbm < noise_dbm)
++			return 0;
++		sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
++
++	/* Else use just the signal level.
++	 * This formula is a least squares fit of data points collected and
++	 *   compared with a reference system that had a percentage (%) display
++	 *   for signal quality. */
++	} else
++		sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
++			    (15 * RSSI_RANGE + 62 * degradation)) /
++			   (RSSI_RANGE * RSSI_RANGE);
++
++	if (sig_qual > 100)
++		sig_qual = 100;
++	else if (sig_qual < 1)
++		sig_qual = 0;
++
++	return sig_qual;
++}
++
++/**
++ * iwl_rx_handle - Main entry function for receiving responses from the uCode
++ *
++ * Uses the priv->rx_handlers callback function array to invoke
++ * the appropriate handlers, including command responses,
++ * frame-received notifications, and other notifications.
++ */
++static void iwl_rx_handle(struct iwl_priv *priv)
++{
++	struct iwl_rx_mem_buffer *rxb;
++	struct iwl_rx_packet *pkt;
++	struct iwl_rx_queue *rxq = &priv->rxq;
++	u32 r, i;
++	int reclaim;
++	unsigned long flags;
++
++	r = iwl_hw_get_rx_read(priv);
++	i = rxq->read;
++
++	/* Rx interrupt, but nothing sent from uCode */
++	if (i == r)
++		IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
++
++	while (i != r) {
++		rxb = rxq->queue[i];
++
++		/* If an RXB doesn't have a queue slot associated with it
++		 * then a bug has been introduced in the queue refilling
++		 * routines -- catch it here */
++		BUG_ON(rxb == NULL);
++
++		rxq->queue[i] = NULL;
++
++		pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
++					    IWL_RX_BUF_SIZE,
++					    PCI_DMA_FROMDEVICE);
++		pkt = (struct iwl_rx_packet *)rxb->skb->data;
++
++		/* Reclaim a command buffer only if this packet is a response
++		 *   to a (driver-originated) command.
++		 * If the packet (e.g. Rx frame) originated from uCode,
++		 *   there is no command buffer to reclaim.
++		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
++		 *   but apparently a few don't get set; catch them here. */
++		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
++			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
++			(pkt->hdr.cmd != REPLY_TX);
++
++		/* Based on type of command response or notification,
++		 *   handle those that need handling via function in
++		 *   rx_handlers table.  See iwl_setup_rx_handlers() */
++		if (priv->rx_handlers[pkt->hdr.cmd]) {
++			IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
++				"r = %d, i = %d, %s, 0x%02x\n", r, i,
++				get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
++			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
++		} else {
++			/* No handling needed */
++			IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
++				"r %d i %d No handler needed for %s, 0x%02x\n",
++				r, i, get_cmd_string(pkt->hdr.cmd),
++				pkt->hdr.cmd);
++		}
++
++		if (reclaim) {
++			/* Invoke any callbacks, transfer the skb to caller,
++			 * and fire off the (possibly) blocking iwl_send_cmd()
++			 * as we reclaim the driver command queue */
++			if (rxb && rxb->skb)
++				iwl_tx_cmd_complete(priv, rxb);
++			else
++				IWL_WARNING("Claim null rxb?\n");
++		}
++
++		/* For now we just don't re-use anything.  We can tweak this
++		 * later to try and re-use notification packets and SKBs that
++		 * fail to Rx correctly */
++		if (rxb->skb != NULL) {
++			priv->alloc_rxb_skb--;
++			dev_kfree_skb_any(rxb->skb);
++			rxb->skb = NULL;
++		}
++
++		pci_unmap_single(priv->pci_dev, rxb->dma_addr,
++				 IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
++		spin_lock_irqsave(&rxq->lock, flags);
++		list_add_tail(&rxb->list, &priv->rxq.rx_used);
++		spin_unlock_irqrestore(&rxq->lock, flags);
++		i = (i + 1) & RX_QUEUE_MASK;
++	}
++
++	/* Backtrack one entry */
++	priv->rxq.read = i;
++	iwl_rx_queue_restock(priv);
++}
++
++int iwl_tx_queue_update_write_ptr(struct iwl_priv *priv,
++				  struct iwl_tx_queue *txq)
++{
++	u32 reg = 0;
++	int rc = 0;
++	int txq_id = txq->q.id;
++
++	if (txq->need_update == 0)
++		return rc;
++
++	/* if we're trying to save power */
++	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
++		/* wake up nic if it's powered down ...
++		 * uCode will wake up, and interrupt us again, so next
++		 * time we'll skip this part. */
++		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
++
++		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
++			IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
++			iwl_set_bit(priv, CSR_GP_CNTRL,
++				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++			return rc;
++		}
++
++		/* restore this queue's parameters in nic hardware. */
++		rc = iwl_grab_restricted_access(priv);
++		if (rc)
++			return rc;
++		iwl_write_restricted(priv, HBUS_TARG_WRPTR,
++				     txq->q.first_empty | (txq_id << 8));
++		iwl_release_restricted_access(priv);
++
++	/* else not in power-save mode, uCode will never sleep when we're
++	 * trying to tx (during RFKILL, we're not trying to tx). */
++	} else
++		iwl_write32(priv, HBUS_TARG_WRPTR,
++			    txq->q.first_empty | (txq_id << 8));
++
++	txq->need_update = 0;
++
++	return rc;
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static void iwl_print_rx_config_cmd(struct iwl_rxon_cmd *rxon)
++{
++	IWL_DEBUG_RADIO("RX CONFIG:\n");
++	iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
++	IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
++	IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
++	IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
++			le32_to_cpu(rxon->filter_flags));
++	IWL_DEBUG_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type);
++	IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
++			rxon->ofdm_basic_rates);
++	IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
++	IWL_DEBUG_RADIO("u8[6] node_addr: " MAC_FMT "\n",
++			MAC_ARG(rxon->node_addr));
++	IWL_DEBUG_RADIO("u8[6] bssid_addr: " MAC_FMT "\n",
++			MAC_ARG(rxon->bssid_addr));
++	IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
++}
++#endif
++
++static void iwl_enable_interrupts(struct iwl_priv *priv)
++{
++	IWL_DEBUG_ISR("Enabling interrupts\n");
++	set_bit(STATUS_INT_ENABLED, &priv->status);
++	iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
++}
++
++static inline void iwl_disable_interrupts(struct iwl_priv *priv)
++{
++	clear_bit(STATUS_INT_ENABLED, &priv->status);
++
++	/* disable interrupts from uCode/NIC to host */
++	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
++
++	/* acknowledge/clear/reset any interrupts still pending
++	 * from uCode or flow handler (Rx/Tx DMA) */
++	iwl_write32(priv, CSR_INT, 0xffffffff);
++	iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
++	IWL_DEBUG_ISR("Disabled interrupts\n");
++}
++
++static const char *desc_lookup(int i)
++{
++	switch (i) {
++	case 1:
++		return "FAIL";
++	case 2:
++		return "BAD_PARAM";
++	case 3:
++		return "BAD_CHECKSUM";
++	case 4:
++		return "NMI_INTERRUPT";
++	case 5:
++		return "SYSASSERT";
++	case 6:
++		return "FATAL_ERROR";
++	}
++
++	return "UNKNOWN";
++}
++
++#define ERROR_START_OFFSET  (1 * sizeof(u32))
++#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
++
++static void iwl_dump_nic_error_log(struct iwl_priv *priv)
++{
++	u32 i;
++	u32 desc, time, count, base, data1;
++	u32 blink1, blink2, ilink1, ilink2;
++	int rc;
++
++	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
++
++	if (!iwl_hw_valid_rtc_data_addr(base)) {
++		IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
++		return;
++	}
++
++	rc = iwl_grab_restricted_access(priv);
++	if (rc) {
++		IWL_WARNING("Can not read from adapter at this time.\n");
++		return;
++	}
++
++	count = iwl_read_restricted_mem(priv, base);
++
++	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
++		IWL_ERROR("Start IWL Error Log Dump:\n");
++		IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n",
++			  priv->status, priv->config, count);
++	}
++
++	IWL_ERROR("Desc       Time       asrtPC  blink2 "
++		  "ilink1  nmiPC   Line\n");
++	for (i = ERROR_START_OFFSET;
++	     i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
++	     i += ERROR_ELEM_SIZE) {
++		desc = iwl_read_restricted_mem(priv, base + i);
++		time =
++		    iwl_read_restricted_mem(priv, base + i + 1 * sizeof(u32));
++		blink1 =
++		    iwl_read_restricted_mem(priv, base + i + 2 * sizeof(u32));
++		blink2 =
++		    iwl_read_restricted_mem(priv, base + i + 3 * sizeof(u32));
++		ilink1 =
++		    iwl_read_restricted_mem(priv, base + i + 4 * sizeof(u32));
++		ilink2 =
++		    iwl_read_restricted_mem(priv, base + i + 5 * sizeof(u32));
++		data1 =
++		    iwl_read_restricted_mem(priv, base + i + 6 * sizeof(u32));
++
++		IWL_ERROR
++		    ("%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
++		     desc_lookup(desc), desc, time, blink1, blink2,
++		     ilink1, ilink2, data1);
++	}
++
++	iwl_release_restricted_access(priv);
++
++}
++
++#define EVENT_START_OFFSET  (4 * sizeof(u32))
++
++/**
++ * iwl_print_event_log - Dump error event log to syslog
++ *
++ * NOTE: Must be called with iwl_grab_restricted_access() already obtained!
++ */
++static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
++				u32 num_events, u32 mode)
++{
++	u32 i;
++	u32 base;       /* SRAM byte address of event log header */
++	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
++	u32 ptr;        /* SRAM byte address of log data */
++	u32 ev, time, data; /* event log data */
++
++	if (num_events == 0)
++		return;
++
++	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
++
++	if (mode == 0)
++		event_size = 2 * sizeof(u32);
++	else
++		event_size = 3 * sizeof(u32);
++
++	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
++
++	/* "time" is actually "data" for mode 0 (no timestamp).
++	 * place event id # at far right for easier visual parsing. */
++	for (i = 0; i < num_events; i++) {
++		ev = iwl_read_restricted_mem(priv, ptr);
++		ptr += sizeof(u32);
++		time = iwl_read_restricted_mem(priv, ptr);
++		ptr += sizeof(u32);
++		if (mode == 0)
++			IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
++		else {
++			data = iwl_read_restricted_mem(priv, ptr);
++			ptr += sizeof(u32);
++			IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
++		}
++	}
++}
++
++static void iwl_dump_nic_event_log(struct iwl_priv *priv)
++{
++	int rc;
++	u32 base;       /* SRAM byte address of event log header */
++	u32 capacity;   /* event log capacity in # entries */
++	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
++	u32 num_wraps;  /* # times uCode wrapped to top of log */
++	u32 next_entry; /* index of next entry to be written by uCode */
++	u32 size;       /* # entries that we'll print */
++
++	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
++	if (!iwl_hw_valid_rtc_data_addr(base)) {
++		IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
++		return;
++	}
++
++	rc = iwl_grab_restricted_access(priv);
++	if (rc) {
++		IWL_WARNING("Can not read from adapter at this time.\n");
++		return;
++	}
++
++	/* event log header */
++	capacity = iwl_read_restricted_mem(priv, base);
++	mode = iwl_read_restricted_mem(priv, base + (1 * sizeof(u32)));
++	num_wraps = iwl_read_restricted_mem(priv, base + (2 * sizeof(u32)));
++	next_entry = iwl_read_restricted_mem(priv, base + (3 * sizeof(u32)));
++
++	size = num_wraps ? capacity : next_entry;
++
++	/* bail out if nothing in log */
++	if (size == 0) {
++		IWL_ERROR("Start IPW Event Log Dump: nothing in log\n");
++		iwl_release_restricted_access(priv);
++		return;
++	}
++
++	IWL_ERROR("Start IPW Event Log Dump: display count %d, wraps %d\n",
++		  size, num_wraps);
++
++	/* if uCode has wrapped back to top of log, start at the oldest entry,
++	 * i.e the next one that uCode would fill. */
++	if (num_wraps)
++		iwl_print_event_log(priv, next_entry,
++				    capacity - next_entry, mode);
++
++	/* (then/else) start at top of log */
++	iwl_print_event_log(priv, 0, next_entry, mode);
++
++	iwl_release_restricted_access(priv);
++}
++
++/**
++ * iwl_irq_handle_error - called for HW or SW error interrupt from card
++ */
++static void iwl_irq_handle_error(struct iwl_priv *priv)
++{
++	/* Set the FW error flag -- cleared on iwl_down */
++	set_bit(STATUS_FW_ERROR, &priv->status);
++
++	/* Cancel currently queued command. */
++	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & IWL_DL_FW_ERRORS) {
++		iwl_dump_nic_error_log(priv);
++		iwl_dump_nic_event_log(priv);
++		iwl_print_rx_config_cmd(&priv->staging_rxon);
++	}
++#endif
++
++	wake_up_interruptible(&priv->wait_command_queue);
++
++	/* Keep the restart process from trying to send host
++	 * commands by clearing the INIT status bit */
++	clear_bit(STATUS_READY, &priv->status);
++
++	if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
++		IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS,
++			  "Restarting adapter due to uCode error.\n");
++
++		if (iwl_is_associated(priv)) {
++			memcpy(&priv->recovery_rxon, &priv->active_rxon,
++			       sizeof(priv->recovery_rxon));
++			priv->error_recovering = 1;
++		}
++		queue_work(priv->workqueue, &priv->restart);
++	}
++}
++
++static void iwl_error_recovery(struct iwl_priv *priv)
++{
++	unsigned long flags;
++
++	memcpy(&priv->staging_rxon, &priv->recovery_rxon,
++	       sizeof(priv->staging_rxon));
++	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++	iwl_commit_rxon(priv);
++
++	iwl_rxon_add_station(priv, priv->bssid, 1);
++
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
++	priv->error_recovering = 0;
++	spin_unlock_irqrestore(&priv->lock, flags);
++}
++
++static void iwl_irq_tasklet(struct iwl_priv *priv)
++{
++	u32 inta, handled = 0;
++	u32 inta_fh;
++	unsigned long flags;
++#ifdef CONFIG_IWLWIFI_DEBUG
++	u32 inta_mask;
++#endif
++
++	spin_lock_irqsave(&priv->lock, flags);
++
++	/* Ack/clear/reset pending uCode interrupts.
++	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
++	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
++	inta = iwl_read32(priv, CSR_INT);
++	iwl_write32(priv, CSR_INT, inta);
++
++	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
++	 * Any new interrupts that happen after this, either while we're
++	 * in this tasklet, or later, will show up in next ISR/tasklet. */
++	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
++	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & IWL_DL_ISR) {
++		inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
++		IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
++			      inta, inta_mask, inta_fh);
++	}
++#endif
++
++	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
++	 * atomic, make sure that inta covers all the interrupts that
++	 * we've discovered, even if FH interrupt came in just after
++	 * reading CSR_INT. */
++	if (inta_fh & CSR_FH_INT_RX_MASK)
++		inta |= CSR_INT_BIT_FH_RX;
++	if (inta_fh & CSR_FH_INT_TX_MASK)
++		inta |= CSR_INT_BIT_FH_TX;
++
++	/* Now service all interrupt bits discovered above. */
++	if (inta & CSR_INT_BIT_HW_ERR) {
++		IWL_ERROR("Microcode HW error detected.  Restarting.\n");
++
++		/* Tell the device to stop sending interrupts */
++		iwl_disable_interrupts(priv);
++
++		iwl_irq_handle_error(priv);
++
++		handled |= CSR_INT_BIT_HW_ERR;
++
++		spin_unlock_irqrestore(&priv->lock, flags);
++
++		return;
++	}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & (IWL_DL_ISR)) {
++		/* NIC fires this, but we don't use it, redundant with WAKEUP */
++		if (inta & CSR_INT_BIT_MAC_CLK_ACTV)
++			IWL_DEBUG_ISR("Microcode started or stopped.\n");
++
++		/* Alive notification via Rx interrupt will do the real work */
++		if (inta & CSR_INT_BIT_ALIVE)
++			IWL_DEBUG_ISR("Alive interrupt\n");
++	}
++#endif
++	/* Safely ignore these bits for debug checks below */
++	inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE);
++
++	/* HW RF KILL switch toggled (4965 only) */
++	if (inta & CSR_INT_BIT_RF_KILL) {
++		int hw_rf_kill = 0;
++		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
++				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
++			hw_rf_kill = 1;
++
++		IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR,
++				"RF_KILL bit toggled to %s.\n",
++				hw_rf_kill ? "disable radio":"enable radio");
++
++		/* Queue restart only if RF_KILL switch was set to "kill"
++		 *   when we loaded driver, and is now set to "enable".
++		 * After we're Alive, RF_KILL gets handled by
++		 *   iwl_rx_card_state_notif() */
++		if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status))
++			queue_work(priv->workqueue, &priv->restart);
++
++		handled |= CSR_INT_BIT_RF_KILL;
++	}
++
++	/* Chip got too hot and stopped itself (4965 only) */
++	if (inta & CSR_INT_BIT_CT_KILL) {
++		IWL_ERROR("Microcode CT kill error detected.\n");
++		handled |= CSR_INT_BIT_CT_KILL;
++	}
++
++	/* Error detected by uCode */
++	if (inta & CSR_INT_BIT_SW_ERR) {
++		IWL_ERROR("Microcode SW error detected.  Restarting 0x%X.\n",
++			  inta);
++		iwl_irq_handle_error(priv);
++		handled |= CSR_INT_BIT_SW_ERR;
++	}
++
++	/* uCode wakes up after power-down sleep */
++	if (inta & CSR_INT_BIT_WAKEUP) {
++		IWL_DEBUG_ISR("Wakeup interrupt\n");
++		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[0]);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[1]);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[2]);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[3]);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[4]);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[5]);
++
++		handled |= CSR_INT_BIT_WAKEUP;
++	}
++
++	/* All uCode command responses, including Tx command responses,
++	 * Rx "responses" (frame-received notification), and other
++	 * notifications from uCode come through here*/
++	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
++		iwl_rx_handle(priv);
++		handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
++	}
++
++	if (inta & CSR_INT_BIT_FH_TX) {
++		IWL_DEBUG_ISR("Tx interrupt\n");
++
++		iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
++		if (!iwl_grab_restricted_access(priv)) {
++			iwl_write_restricted(priv,
++					     FH_TCSR_CREDIT
++					     (ALM_FH_SRVC_CHNL), 0x0);
++			iwl_release_restricted_access(priv);
++		}
++		handled |= CSR_INT_BIT_FH_TX;
++	}
++
++	if (inta & ~handled)
++		IWL_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
++
++	if (inta & ~CSR_INI_SET_MASK) {
++		IWL_WARNING("Disabled INTA bits 0x%08x were pending\n",
++			 inta & ~CSR_INI_SET_MASK);
++		IWL_WARNING("   with FH_INT = 0x%08x\n", inta_fh);
++	}
++
++	/* Re-enable all interrupts */
++	iwl_enable_interrupts(priv);
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & (IWL_DL_ISR)) {
++		inta = iwl_read32(priv, CSR_INT);
++		inta_mask = iwl_read32(priv, CSR_INT_MASK);
++		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
++		IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
++			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
++	}
++#endif
++	spin_unlock_irqrestore(&priv->lock, flags);
++}
++
++static irqreturn_t iwl_isr(int irq, void *data)
++{
++	struct iwl_priv *priv = data;
++	u32 inta, inta_mask;
++	u32 inta_fh;
++	if (!priv)
++		return IRQ_NONE;
++
++	spin_lock(&priv->lock);
++
++	/* Disable (but don't clear!) interrupts here to avoid
++	 *    back-to-back ISRs and sporadic interrupts from our NIC.
++	 * If we have something to service, the tasklet will re-enable ints.
++	 * If we *don't* have something, we'll re-enable before leaving here. */
++	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
++	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
++
++	/* Discover which interrupts are active/pending */
++	inta = iwl_read32(priv, CSR_INT);
++	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
++
++	/* Ignore interrupt if there's nothing in NIC to service.
++	 * This may be due to IRQ shared with another device,
++	 * or due to sporadic interrupts thrown from our NIC. */
++	if (!inta && !inta_fh) {
++		IWL_DEBUG_ISR("Ignore interrupt, inta == 0, inta_fh == 0\n");
++		goto none;
++	}
++
++	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
++		/* Hardware disappeared */
++		IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
++		goto none;
++	}
++
++	IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
++		      inta, inta_mask, inta_fh);
++
++	/* iwl_irq_tasklet() will service interrupts and re-enable them */
++	tasklet_schedule(&priv->irq_tasklet);
++	spin_unlock(&priv->lock);
++
++	return IRQ_HANDLED;
++
++ none:
++	/* re-enable interrupts here since we don't have anything to service. */
++	iwl_enable_interrupts(priv);
++	spin_unlock(&priv->lock);
++	return IRQ_NONE;
++}
++
++/************************** EEPROM BANDS ****************************
++ *
++ * The iwl_eeprom_band definitions below provide the mapping from the
++ * EEPROM contents to the specific channel number supported for each
++ * band.
++ *
++ * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
++ * definition below maps to physical channel 42 in the 5.2GHz spectrum.
++ * The specific geography and calibration information for that channel
++ * is contained in the eeprom map itself.
++ *
++ * During init, we copy the eeprom information and channel map
++ * information into priv->channel_info_24/52 and priv->channel_map_24/52
++ *
++ * channel_map_24/52 provides the index in the channel_info array for a
++ * given channel.  We have to have two separate maps as there is channel
++ * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
++ * band_2
++ *
++ * A value of 0xff stored in the channel_map indicates that the channel
++ * is not supported by the hardware at all.
++ *
++ * A value of 0xfe in the channel_map indicates that the channel is not
++ * valid for Tx with the current hardware.  This means that
++ * while the system can tune and receive on a given channel, it may not
++ * be able to associate or transmit any frames on that
++ * channel.  There is no corresponding channel information for that
++ * entry.
++ *
++ *********************************************************************/
++
++/* 2.4 GHz */
++static const u8 iwl_eeprom_band_1[14] = {
++	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
++};
++
++/* 5.2 GHz bands */
++static const u8 iwl_eeprom_band_2[] = {
++	183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
++};
++
++static const u8 iwl_eeprom_band_3[] = {	/* 5205-5320MHz */
++	34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
++};
++
++static const u8 iwl_eeprom_band_4[] = {	/* 5500-5700MHz */
++	100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
++};
++
++static const u8 iwl_eeprom_band_5[] = {	/* 5725-5825MHz */
++	145, 149, 153, 157, 161, 165
++};
++
++static void iwl_init_band_reference(const struct iwl_priv *priv, int band,
++				    int *eeprom_ch_count,
++				    const struct iwl_eeprom_channel
++				    **eeprom_ch_info,
++				    const u8 **eeprom_ch_index)
++{
++	switch (band) {
++	case 1:		/* 2.4GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
++		*eeprom_ch_info = priv->eeprom.band_1_channels;
++		*eeprom_ch_index = iwl_eeprom_band_1;
++		break;
++	case 2:		/* 5.2GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
++		*eeprom_ch_info = priv->eeprom.band_2_channels;
++		*eeprom_ch_index = iwl_eeprom_band_2;
++		break;
++	case 3:		/* 5.2GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
++		*eeprom_ch_info = priv->eeprom.band_3_channels;
++		*eeprom_ch_index = iwl_eeprom_band_3;
++		break;
++	case 4:		/* 5.2GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
++		*eeprom_ch_info = priv->eeprom.band_4_channels;
++		*eeprom_ch_index = iwl_eeprom_band_4;
++		break;
++	case 5:		/* 5.2GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
++		*eeprom_ch_info = priv->eeprom.band_5_channels;
++		*eeprom_ch_index = iwl_eeprom_band_5;
++		break;
++	default:
++		BUG();
++		return;
++	}
++}
++
++const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
++						    int phymode, u16 channel)
++{
++	int i;
++
++	switch (phymode) {
++	case MODE_IEEE80211A:
++		for (i = 14; i < priv->channel_count; i++) {
++			if (priv->channel_info[i].channel == channel)
++				return &priv->channel_info[i];
++		}
++		break;
++
++	case MODE_IEEE80211B:
++	case MODE_IEEE80211G:
++		if (channel >= 1 && channel <= 14)
++			return &priv->channel_info[channel - 1];
++		break;
++
++	}
++
++	return NULL;
++}
++
++#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
++			    ? # x " " : "")
++
++static int iwl_init_channel_map(struct iwl_priv *priv)
++{
++	int eeprom_ch_count = 0;
++	const u8 *eeprom_ch_index = NULL;
++	const struct iwl_eeprom_channel *eeprom_ch_info = NULL;
++	int band, ch;
++	struct iwl_channel_info *ch_info;
++
++	if (priv->channel_count) {
++		IWL_DEBUG_INFO("Channel map already initialized.\n");
++		return 0;
++	}
++
++	if (priv->eeprom.version < 0x2f) {
++		IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
++			    priv->eeprom.version);
++		return -EINVAL;
++	}
++
++	IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
++
++	priv->channel_count =
++	    ARRAY_SIZE(iwl_eeprom_band_1) +
++	    ARRAY_SIZE(iwl_eeprom_band_2) +
++	    ARRAY_SIZE(iwl_eeprom_band_3) +
++	    ARRAY_SIZE(iwl_eeprom_band_4) +
++	    ARRAY_SIZE(iwl_eeprom_band_5);
++
++	IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
++
++	priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
++				     priv->channel_count, GFP_KERNEL);
++	if (!priv->channel_info) {
++		IWL_ERROR("Could not allocate channel_info\n");
++		priv->channel_count = 0;
++		return -ENOMEM;
++	}
++
++	ch_info = priv->channel_info;
++
++	/* Loop through the 5 EEPROM bands adding them in order to the
++	 * channel map we maintain (that contains additional information than
++	 * what just in the EEPROM) */
++	for (band = 1; band <= 5; band++) {
++
++		iwl_init_band_reference(priv, band, &eeprom_ch_count,
++					&eeprom_ch_info, &eeprom_ch_index);
++
++		/* Loop through each band adding each of the channels */
++		for (ch = 0; ch < eeprom_ch_count; ch++) {
++			ch_info->channel = eeprom_ch_index[ch];
++			ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
++			    MODE_IEEE80211A;
++
++			/* permanently store EEPROM's channel regulatory flags
++			 *   and max power in channel info database. */
++			ch_info->eeprom = eeprom_ch_info[ch];
++
++			/* Copy the run-time flags so they are there even on
++			 * invalid channels */
++			ch_info->flags = eeprom_ch_info[ch].flags;
++
++			if (!(is_channel_valid(ch_info))) {
++				IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - "
++					       "No traffic\n",
++					       ch_info->channel,
++					       ch_info->flags,
++					       is_channel_a_band(ch_info) ?
++					       "5.2" : "2.4");
++				ch_info++;
++				continue;
++			}
++
++			/* Initialize regulatory-based run-time data */
++			ch_info->max_power_avg = ch_info->curr_txpow =
++			    eeprom_ch_info[ch].max_power_avg;
++			ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
++			ch_info->min_power = 0;
++
++			IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
++				       " %ddBm): Ad-Hoc %ssupported\n",
++				       ch_info->channel,
++				       is_channel_a_band(ch_info) ?
++				       "5.2" : "2.4",
++				       CHECK_AND_PRINT(IBSS),
++				       CHECK_AND_PRINT(ACTIVE),
++				       CHECK_AND_PRINT(RADAR),
++				       CHECK_AND_PRINT(WIDE),
++				       CHECK_AND_PRINT(NARROW),
++				       CHECK_AND_PRINT(DFS),
++				       eeprom_ch_info[ch].flags,
++				       eeprom_ch_info[ch].max_power_avg,
++				       ((eeprom_ch_info[ch].
++					 flags & EEPROM_CHANNEL_IBSS)
++					&& !(eeprom_ch_info[ch].
++					     flags & EEPROM_CHANNEL_RADAR))
++				       ? "" : "not ");
++
++			/* Set the user_txpower_limit to the highest power
++			 * supported by any channel */
++			if (eeprom_ch_info[ch].max_power_avg >
++			    priv->user_txpower_limit)
++				priv->user_txpower_limit =
++				    eeprom_ch_info[ch].max_power_avg;
++
++			ch_info++;
++		}
++	}
++
++	if (iwl3945_txpower_set_from_eeprom(priv))
++		return -EIO;
++
++	return 0;
++}
++
++/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
++ * sending probe req.  This should be set long enough to hear probe responses
++ * from more than one AP.  */
++#define IWL_ACTIVE_DWELL_TIME_24    (20)	/* all times in msec */
++#define IWL_ACTIVE_DWELL_TIME_52    (10)
++
++/* For faster active scanning, scan will move to the next channel if fewer than
++ * PLCP_QUIET_THRESH packets are heard on this channel within
++ * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell
++ * time if it's a quiet channel (nothing responded to our probe, and there's
++ * no other traffic).
++ * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
++#define IWL_PLCP_QUIET_THRESH       __constant_cpu_to_le16(1)	/* packets */
++#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(5)	/* msec */
++
++/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
++ * Must be set longer than active dwell time.
++ * For the most reliable scan, set > AP beacon interval (typically 100msec). */
++#define IWL_PASSIVE_DWELL_TIME_24   (20)	/* all times in msec */
++#define IWL_PASSIVE_DWELL_TIME_52   (10)
++#define IWL_PASSIVE_DWELL_BASE      (100)
++#define IWL_CHANNEL_TUNE_TIME       5
++
++static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, int phymode)
++{
++	if (phymode == MODE_IEEE80211A)
++		return IWL_ACTIVE_DWELL_TIME_52;
++	else
++		return IWL_ACTIVE_DWELL_TIME_24;
++}
++
++static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, int phymode)
++{
++	u16 active = iwl_get_active_dwell_time(priv, phymode);
++	u16 passive = (phymode != MODE_IEEE80211A) ?
++	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
++	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
++
++	if (iwl_is_associated(priv)) {
++		/* If we're associated, we clamp the maximum passive
++		 * dwell time to be 98% of the beacon interval (minus
++		 * 2 * channel tune time) */
++		passive = priv->beacon_int;
++		if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
++			passive = IWL_PASSIVE_DWELL_BASE;
++		passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
++	}
++
++	if (passive <= active)
++		passive = active + 1;
++
++	return passive;
++}
++
++static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
++				     u8 is_active, u8 direct_mask,
++				     struct iwl_scan_channel *scan_ch)
++{
++	const struct ieee80211_channel *channels = NULL;
++	const struct ieee80211_hw_mode *hw_mode;
++	const struct iwl_channel_info *ch_info;
++	u16 passive_dwell = 0;
++	u16 active_dwell = 0;
++	int added, i;
++
++	hw_mode = iwl_get_hw_mode(priv, phymode);
++	if (!hw_mode)
++		return 0;
++
++	channels = hw_mode->channels;
++
++	active_dwell = iwl_get_active_dwell_time(priv, phymode);
++	passive_dwell = iwl_get_passive_dwell_time(priv, phymode);
++
++	for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
++		if (channels[i].chan ==
++		    le16_to_cpu(priv->active_rxon.channel)) {
++			if (iwl_is_associated(priv)) {
++				IWL_DEBUG_SCAN
++				    ("Skipping current channel %d\n",
++				     le16_to_cpu(priv->active_rxon.channel));
++				continue;
++			}
++		} else if (priv->only_active_channel)
++			continue;
++
++		scan_ch->channel = channels[i].chan;
++
++		ch_info = iwl_get_channel_info(priv, phymode, scan_ch->channel);
++		if (!is_channel_valid(ch_info)) {
++			IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
++				       scan_ch->channel);
++			continue;
++		}
++
++		if (!is_active || is_channel_passive(ch_info) ||
++		    !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
++			scan_ch->type = 0;	/* passive */
++		else
++			scan_ch->type = 1;	/* active */
++
++		if (scan_ch->type & 1)
++			scan_ch->type |= (direct_mask << 1);
++
++		if (is_channel_narrow(ch_info))
++			scan_ch->type |= (1 << 7);
++
++		scan_ch->active_dwell = cpu_to_le16(active_dwell);
++		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
++
++		/* Set power levels to defaults */
++		scan_ch->tpc.dsp_atten = 110;
++		/* scan_pwr_info->tpc.dsp_atten; */
++
++		/*scan_pwr_info->tpc.tx_gain; */
++		if (phymode == MODE_IEEE80211A)
++			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
++		else {
++			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
++			/* NOTE: if we were doing 6Mb OFDM for scans we'd use
++			 * power level
++			 scan_ch->tpc.tx_gain = ((1<<5) | (2 << 3)) | 3;
++			 */
++		}
++
++		IWL_DEBUG_SCAN("Scanning %d [%s %d]\n",
++			       scan_ch->channel,
++			       (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
++			       (scan_ch->type & 1) ?
++			       active_dwell : passive_dwell);
++
++		scan_ch++;
++		added++;
++	}
++
++	IWL_DEBUG_SCAN("total channels to scan %d \n", added);
++	return added;
++}
++
++static void iwl_reset_channel_flag(struct iwl_priv *priv)
++{
++	int i, j;
++	for (i = 0; i < 3; i++) {
++		struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
++		for (j = 0; j < hw_mode->num_channels; j++)
++			hw_mode->channels[j].flag = hw_mode->channels[j].val;
++	}
++}
++
++static void iwl_init_hw_rates(struct iwl_priv *priv,
++			      struct ieee80211_rate *rates)
++{
++	int i;
++
++	for (i = 0; i < IWL_RATE_COUNT; i++) {
++		rates[i].rate = iwl_rates[i].ieee * 5;
++		rates[i].val = i; /* Rate scaling will work on indexes */
++		rates[i].val2 = i;
++		rates[i].flags = IEEE80211_RATE_SUPPORTED;
++		/* Only OFDM have the bits-per-symbol set */
++		if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
++			rates[i].flags |= IEEE80211_RATE_OFDM;
++		else {
++			/*
++			 * If CCK 1M then set rate flag to CCK else CCK_2
++			 * which is CCK | PREAMBLE2
++			 */
++			rates[i].flags |= (iwl_rates[i].plcp == 10) ?
++				IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
++		}
++
++		/* Set up which ones are basic rates... */
++		if (IWL_BASIC_RATES_MASK & (1 << i))
++			rates[i].flags |= IEEE80211_RATE_BASIC;
++	}
++}
++
++/**
++ * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom
++ */
++static int iwl_init_geos(struct iwl_priv *priv)
++{
++	struct iwl_channel_info *ch;
++	struct ieee80211_hw_mode *modes;
++	struct ieee80211_channel *channels;
++	struct ieee80211_channel *geo_ch;
++	struct ieee80211_rate *rates;
++	int i = 0;
++	enum {
++		A = 0,
++		B = 1,
++		G = 2,
++	};
++	int mode_count = 3;
++
++	if (priv->modes) {
++		IWL_DEBUG_INFO("Geography modes already initialized.\n");
++		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
++		return 0;
++	}
++
++	modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
++			GFP_KERNEL);
++	if (!modes)
++		return -ENOMEM;
++
++	channels = kzalloc(sizeof(struct ieee80211_channel) *
++			   priv->channel_count, GFP_KERNEL);
++	if (!channels) {
++		kfree(modes);
++		return -ENOMEM;
++	}
++
++	rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
++			GFP_KERNEL);
++	if (!rates) {
++		kfree(modes);
++		kfree(channels);
++		return -ENOMEM;
++	}
++
++	/* 0 = 802.11a
++	 * 1 = 802.11b
++	 * 2 = 802.11g
++	 */
++
++	/* 5.2GHz channels start after the 2.4GHz channels */
++	modes[A].mode = MODE_IEEE80211A;
++	modes[A].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
++	modes[A].rates = rates;
++	modes[A].num_rates = 8;	/* just OFDM */
++	modes[A].num_channels = 0;
++
++	modes[B].mode = MODE_IEEE80211B;
++	modes[B].channels = channels;
++	modes[B].rates = &rates[8];
++	modes[B].num_rates = 4;	/* just CCK */
++	modes[B].num_channels = 0;
++
++	modes[G].mode = MODE_IEEE80211G;
++	modes[G].channels = channels;
++	modes[G].rates = rates;
++	modes[G].num_rates = 12;	/* OFDM & CCK */
++	modes[G].num_channels = 0;
++
++	priv->ieee_channels = channels;
++	priv->ieee_rates = rates;
++
++	iwl_init_hw_rates(priv, rates);
++
++	for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
++		ch = &priv->channel_info[i];
++
++		if (!is_channel_valid(ch)) {
++			IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- "
++				    "skipping.\n",
++				    ch->channel, is_channel_a_band(ch) ?
++				    "5.2" : "2.4");
++			continue;
++		}
++
++		if (is_channel_a_band(ch))
++			geo_ch = &modes[A].channels[modes[A].num_channels++];
++		else {
++			geo_ch = &modes[B].channels[modes[B].num_channels++];
++			modes[G].num_channels++;
++		}
++
++		geo_ch->freq = ieee80211chan2mhz(ch->channel);
++		geo_ch->chan = ch->channel;
++		geo_ch->power_level = ch->max_power_avg;
++		geo_ch->antenna_max = 0xff;
++
++		if (is_channel_valid(ch)) {
++			geo_ch->flag = IEEE80211_CHAN_W_SCAN;
++			if (ch->flags & EEPROM_CHANNEL_IBSS)
++				geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
++
++			if (ch->flags & EEPROM_CHANNEL_ACTIVE)
++				geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
++
++			if (ch->flags & EEPROM_CHANNEL_RADAR)
++				geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
++
++			if (ch->max_power_avg > priv->max_channel_txpower_limit)
++				priv->max_channel_txpower_limit =
++				    ch->max_power_avg;
++		}
++
++		geo_ch->val = geo_ch->flag;
++	}
++
++	if ((modes[A].num_channels == 0) && priv->is_abg) {
++		printk(KERN_INFO DRV_NAME
++		       ": Incorrectly detected BG card as ABG.  Please send "
++		       "your PCI ID 0x%04X:0x%04X to maintainer.\n",
++		       priv->pci_dev->device, priv->pci_dev->subsystem_device);
++		priv->is_abg = 0;
++	}
++
++	printk(KERN_INFO DRV_NAME
++	       ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
++	       modes[G].num_channels, modes[A].num_channels);
++
++	/*
++	 * NOTE:  We register these in preference of order -- the
++	 * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
++	 * a phymode based on rates or AP capabilities but seems to
++	 * configure it purely on if the channel being configured
++	 * is supported by a mode -- and the first match is taken
++	 */
++
++	if (modes[G].num_channels)
++		ieee80211_register_hwmode(priv->hw, &modes[G]);
++	if (modes[B].num_channels)
++		ieee80211_register_hwmode(priv->hw, &modes[B]);
++	if (modes[A].num_channels)
++		ieee80211_register_hwmode(priv->hw, &modes[A]);
++
++	priv->modes = modes;
++	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
++
++	return 0;
++}
++
++/******************************************************************************
++ *
++ * uCode download functions
++ *
++ ******************************************************************************/
++
++static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
++{
++	if (priv->ucode_code.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_code.len,
++				    priv->ucode_code.v_addr,
++				    priv->ucode_code.p_addr);
++		priv->ucode_code.v_addr = NULL;
++	}
++	if (priv->ucode_data.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_data.len,
++				    priv->ucode_data.v_addr,
++				    priv->ucode_data.p_addr);
++		priv->ucode_data.v_addr = NULL;
++	}
++	if (priv->ucode_data_backup.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_data_backup.len,
++				    priv->ucode_data_backup.v_addr,
++				    priv->ucode_data_backup.p_addr);
++		priv->ucode_data_backup.v_addr = NULL;
++	}
++	if (priv->ucode_init.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_init.len,
++				    priv->ucode_init.v_addr,
++				    priv->ucode_init.p_addr);
++		priv->ucode_init.v_addr = NULL;
++	}
++	if (priv->ucode_init_data.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_init_data.len,
++				    priv->ucode_init_data.v_addr,
++				    priv->ucode_init_data.p_addr);
++		priv->ucode_init_data.v_addr = NULL;
++	}
++	if (priv->ucode_boot.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_boot.len,
++				    priv->ucode_boot.v_addr,
++				    priv->ucode_boot.p_addr);
++		priv->ucode_boot.v_addr = NULL;
++	}
++}
++
++/**
++ * iwl_verify_inst_full - verify runtime uCode image in card vs. host,
++ *     looking at all data.
++ */
++static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 * image, u32 len)
++{
++	u32 val;
++	u32 save_len = len;
++	int rc = 0;
++	u32 errcnt;
++
++	IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
++
++	rc = iwl_grab_restricted_access(priv);
++	if (rc)
++		return rc;
++
++	iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
++
++	errcnt = 0;
++	for (; len > 0; len -= sizeof(u32), image++) {
++		/* read data comes through single port, auto-incr addr */
++		/* NOTE: Use the debugless read so we don't flood kernel log
++		 * if IWL_DL_IO is set */
++		val = _iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
++		if (val != le32_to_cpu(*image)) {
++			IWL_ERROR("uCode INST section is invalid at "
++				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
++				  save_len - len, val, le32_to_cpu(*image));
++			rc = -EIO;
++			errcnt++;
++			if (errcnt >= 20)
++				break;
++		}
++	}
++
++	iwl_release_restricted_access(priv);
++
++	if (!errcnt)
++		IWL_DEBUG_INFO
++		    ("ucode image in INSTRUCTION memory is good\n");
++
++	return rc;
++}
++
++
++/**
++ * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
++ *   using sample data 100 bytes apart.  If these sample points are good,
++ *   it's a pretty good bet that everything between them is good, too.
++ */
++static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
++{
++	u32 val;
++	int rc = 0;
++	u32 errcnt = 0;
++	u32 i;
++
++	IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
++
++	rc = iwl_grab_restricted_access(priv);
++	if (rc)
++		return rc;
++
++	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
++		/* read data comes through single port, auto-incr addr */
++		/* NOTE: Use the debugless read so we don't flood kernel log
++		 * if IWL_DL_IO is set */
++		iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR,
++			i + RTC_INST_LOWER_BOUND);
++		val = _iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
++		if (val != le32_to_cpu(*image)) {
++#if 0 /* Enable this if you want to see details */
++			IWL_ERROR("uCode INST section is invalid at "
++				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
++				  i, val, *image);
++#endif
++			rc = -EIO;
++			errcnt++;
++			if (errcnt >= 3)
++				break;
++		}
++	}
++
++	iwl_release_restricted_access(priv);
++
++	return rc;
++}
++
++
++/**
++ * iwl_verify_ucode - determine which instruction image is in SRAM,
++ *    and verify its contents
++ */
++static int iwl_verify_ucode(struct iwl_priv *priv)
++{
++	__le32 *image;
++	u32 len;
++	int rc = 0;
++
++	/* Try bootstrap */
++	image = (__le32 *)priv->ucode_boot.v_addr;
++	len = priv->ucode_boot.len;
++	rc = iwl_verify_inst_sparse(priv, image, len);
++	if (rc == 0) {
++		IWL_DEBUG_INFO("Bootstrap uCode is good in inst SRAM\n");
++		return 0;
++	}
++
++	/* Try initialize */
++	image = (__le32 *)priv->ucode_init.v_addr;
++	len = priv->ucode_init.len;
++	rc = iwl_verify_inst_sparse(priv, image, len);
++	if (rc == 0) {
++		IWL_DEBUG_INFO("Initialize uCode is good in inst SRAM\n");
++		return 0;
++	}
++
++	/* Try runtime/protocol */
++	image = (__le32 *)priv->ucode_code.v_addr;
++	len = priv->ucode_code.len;
++	rc = iwl_verify_inst_sparse(priv, image, len);
++	if (rc == 0) {
++		IWL_DEBUG_INFO("Runtime uCode is good in inst SRAM\n");
++		return 0;
++	}
++
++	IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
++
++	/* Show first several data entries in instruction SRAM.
++	 * Selection of bootstrap image is arbitrary. */
++	image = (__le32 *)priv->ucode_boot.v_addr;
++	len = priv->ucode_boot.len;
++	rc = iwl_verify_inst_full(priv, image, len);
++
++	return rc;
++}
++
++
++/* check contents of special bootstrap uCode SRAM */
++static int iwl_verify_bsm(struct iwl_priv *priv)
++{
++	__le32 *image = priv->ucode_boot.v_addr;
++	u32 len = priv->ucode_boot.len;
++	u32 reg;
++	u32 val;
++
++	IWL_DEBUG_INFO("Begin verify bsm\n");
++
++	/* verify BSM SRAM contents */
++	val = iwl_read_restricted_reg(priv, BSM_WR_DWCOUNT_REG);
++	for (reg = BSM_SRAM_LOWER_BOUND;
++	     reg < BSM_SRAM_LOWER_BOUND + len;
++	     reg += sizeof(u32), image ++) {
++		val = iwl_read_restricted_reg(priv, reg);
++		if (val != le32_to_cpu(*image)) {
++			IWL_ERROR("BSM uCode verification failed at "
++				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
++				  BSM_SRAM_LOWER_BOUND,
++				  reg - BSM_SRAM_LOWER_BOUND, len,
++				  val, le32_to_cpu(*image));
++			return -EIO;
++		}
++	}
++
++	IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
++
++	return 0;
++}
++
++/**
++ * iwl_load_bsm - Load bootstrap instructions
++ *
++ * BSM operation:
++ *
++ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
++ * in special SRAM that does not power down during RFKILL.  When powering back
++ * up after power-saving sleeps (or during initial uCode load), the BSM loads
++ * the bootstrap program into the on-board processor, and starts it.
++ *
++ * The bootstrap program loads (via DMA) instructions and data for a new
++ * program from host DRAM locations indicated by the host driver in the
++ * BSM_DRAM_* registers.  Once the new program is loaded, it starts
++ * automatically.
++ *
++ * When initializing the NIC, the host driver points the BSM to the
++ * "initialize" uCode image.  This uCode sets up some internal data, then
++ * notifies host via "initialize alive" that it is complete.
++ *
++ * The host then replaces the BSM_DRAM_* pointer values to point to the
++ * normal runtime uCode instructions and a backup uCode data cache buffer
++ * (filled initially with starting data values for the on-board processor),
++ * then triggers the "initialize" uCode to load and launch the runtime uCode,
++ * which begins normal operation.
++ *
++ * When doing a power-save shutdown, runtime uCode saves data SRAM into
++ * the backup data cache in DRAM before SRAM is powered down.
++ *
++ * When powering back up, the BSM loads the bootstrap program.  This reloads
++ * the runtime uCode instructions and the backup data cache into SRAM,
++ * and re-launches the runtime uCode from where it left off.
++ */
++static int iwl_load_bsm(struct iwl_priv *priv)
++{
++	__le32 *image = priv->ucode_boot.v_addr;
++	u32 len = priv->ucode_boot.len;
++	dma_addr_t pinst;
++	dma_addr_t pdata;
++	u32 inst_len;
++	u32 data_len;
++	int rc;
++	int i;
++	u32 done;
++	u32 reg_offset;
++
++	IWL_DEBUG_INFO("Begin load bsm\n");
++
++	/* make sure bootstrap program is no larger than BSM's SRAM size */
++	if (len > IWL_MAX_BSM_SIZE)
++		return -EINVAL;
++
++	/* Tell bootstrap uCode where to find the "Initialize" uCode
++	 *   in host DRAM ... bits 31:0 for 3945, bits 35:4 for 4965.
++	 * NOTE:  iwl_initialize_alive_start() will replace these values,
++	 *        after the "initialize" uCode has run, to point to
++	 *        runtime/protocol instructions and backup data cache. */
++	pinst = priv->ucode_init.p_addr;
++	pdata = priv->ucode_init_data.p_addr;
++	inst_len = priv->ucode_init.len;
++	data_len = priv->ucode_init_data.len;
++
++	rc = iwl_grab_restricted_access(priv);
++	if (rc)
++		return rc;
++
++	iwl_write_restricted_reg(priv, BSM_DRAM_INST_PTR_REG, pinst);
++	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_PTR_REG, pdata);
++	iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
++	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
++
++	/* Fill BSM memory with bootstrap instructions */
++	for (reg_offset = BSM_SRAM_LOWER_BOUND;
++	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
++	     reg_offset += sizeof(u32), image++)
++		_iwl_write_restricted_reg(priv, reg_offset,
++					  le32_to_cpu(*image));
++
++	rc = iwl_verify_bsm(priv);
++	if (rc) {
++		iwl_release_restricted_access(priv);
++		return rc;
++	}
++
++	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
++	iwl_write_restricted_reg(priv, BSM_WR_MEM_SRC_REG, 0x0);
++	iwl_write_restricted_reg(priv, BSM_WR_MEM_DST_REG,
++				 RTC_INST_LOWER_BOUND);
++	iwl_write_restricted_reg(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
++
++	/* Load bootstrap code into instruction SRAM now,
++	 *   to prepare to load "initialize" uCode */
++	iwl_write_restricted_reg(priv, BSM_WR_CTRL_REG,
++		BSM_WR_CTRL_REG_BIT_START);
++
++	/* Wait for load of bootstrap uCode to finish */
++	for (i = 0; i < 100; i++) {
++		done = iwl_read_restricted_reg(priv, BSM_WR_CTRL_REG);
++		if (!(done & BSM_WR_CTRL_REG_BIT_START))
++			break;
++		udelay(10);
++	}
++	if (i < 100)
++		IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
++	else {
++		IWL_ERROR("BSM write did not complete!\n");
++		return -EIO;
++	}
++
++	/* Enable future boot loads whenever power management unit triggers it
++	 *   (e.g. when powering back up after power-save shutdown) */
++	iwl_write_restricted_reg(priv, BSM_WR_CTRL_REG,
++		BSM_WR_CTRL_REG_BIT_START_EN);
++
++	iwl_release_restricted_access(priv);
++
++	return 0;
++}
++
++static void iwl_nic_start(struct iwl_priv *priv)
++{
++	/* Remove all resets to allow NIC to operate */
++	iwl_write32(priv, CSR_RESET, 0);
++}
++
++/**
++ * iwl_read_ucode - Read uCode images from disk file.
++ *
++ * Copy into buffers for card to fetch via bus-mastering
++ */
++static int iwl_read_ucode(struct iwl_priv *priv)
++{
++	struct iwl_ucode *ucode;
++	int rc = 0;
++	const struct firmware *ucode_raw;
++	/* firmware file name contains uCode/driver compatibility version */
++	const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode";
++	u8 *src;
++	size_t len;
++	u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
++
++	/* Ask kernel firmware_class module to get the boot firmware off disk.
++	 * request_firmware() is synchronous, file is in memory on return. */
++	rc = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
++	if (rc < 0) {
++		IWL_ERROR("%s firmware file req failed: Reason %d\n", name, rc);
++		goto error;
++	}
++
++	IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
++		       name, ucode_raw->size);
++
++	/* Make sure that we got at least our header! */
++	if (ucode_raw->size < sizeof(*ucode)) {
++		IWL_ERROR("File size way too small!\n");
++		rc = -EINVAL;
++		goto err_release;
++	}
++
++	/* Data from ucode file:  header followed by uCode images */
++	ucode = (void *)ucode_raw->data;
++
++	ver = le32_to_cpu(ucode->ver);
++	inst_size = le32_to_cpu(ucode->inst_size);
++	data_size = le32_to_cpu(ucode->data_size);
++	init_size = le32_to_cpu(ucode->init_size);
++	init_data_size = le32_to_cpu(ucode->init_data_size);
++	boot_size = le32_to_cpu(ucode->boot_size);
++
++	IWL_DEBUG_INFO("f/w package hdr ucode version = 0x%x\n", ver);
++	IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n",
++		       inst_size);
++	IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n",
++		       data_size);
++	IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n",
++		       init_size);
++	IWL_DEBUG_INFO("f/w package hdr init data size = %u\n",
++		       init_data_size);
++	IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n",
++		       boot_size);
++
++	/* Verify size of file vs. image size info in file's header */
++	if (ucode_raw->size < sizeof(*ucode) +
++		inst_size + data_size + init_size +
++		init_data_size + boot_size) {
++
++		IWL_DEBUG_INFO("uCode file size %d too small\n",
++			       (int)ucode_raw->size);
++		rc = -EINVAL;
++		goto err_release;
++	}
++
++	/* Verify that uCode images will fit in card's SRAM */
++	if (inst_size > IWL_MAX_INST_SIZE) {
++		IWL_DEBUG_INFO("uCode instr len %d too large to fit in card\n",
++			       (int)inst_size);
++		rc = -EINVAL;
++		goto err_release;
++	}
++
++	if (data_size > IWL_MAX_DATA_SIZE) {
++		IWL_DEBUG_INFO("uCode data len %d too large to fit in card\n",
++			       (int)data_size);
++		rc = -EINVAL;
++		goto err_release;
++	}
++	if (init_size > IWL_MAX_INST_SIZE) {
++		IWL_DEBUG_INFO
++		    ("uCode init instr len %d too large to fit in card\n",
++		     (int)init_size);
++		rc = -EINVAL;
++		goto err_release;
++	}
++	if (init_data_size > IWL_MAX_DATA_SIZE) {
++		IWL_DEBUG_INFO
++		    ("uCode init data len %d too large to fit in card\n",
++		     (int)init_data_size);
++		rc = -EINVAL;
++		goto err_release;
++	}
++	if (boot_size > IWL_MAX_BSM_SIZE) {
++		IWL_DEBUG_INFO
++		    ("uCode boot instr len %d too large to fit in bsm\n",
++		     (int)boot_size);
++		rc = -EINVAL;
++		goto err_release;
++	}
++
++	/* Allocate ucode buffers for card's bus-master loading ... */
++
++	/* Runtime instructions and 2 copies of data:
++	 * 1) unmodified from disk
++	 * 2) backup cache for save/restore during power-downs */
++	priv->ucode_code.len = inst_size;
++	priv->ucode_code.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_code.len,
++				 &(priv->ucode_code.p_addr));
++
++	priv->ucode_data.len = data_size;
++	priv->ucode_data.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_data.len,
++				 &(priv->ucode_data.p_addr));
++
++	priv->ucode_data_backup.len = data_size;
++	priv->ucode_data_backup.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_data_backup.len,
++				 &(priv->ucode_data_backup.p_addr));
++
++
++	/* Initialization instructions and data */
++	priv->ucode_init.len = init_size;
++	priv->ucode_init.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_init.len,
++				 &(priv->ucode_init.p_addr));
++
++	priv->ucode_init_data.len = init_data_size;
++	priv->ucode_init_data.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_init_data.len,
++				 &(priv->ucode_init_data.p_addr));
++
++	/* Bootstrap (instructions only, no data) */
++	priv->ucode_boot.len = boot_size;
++	priv->ucode_boot.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_boot.len,
++				 &(priv->ucode_boot.p_addr));
++
++	if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
++	    !priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr ||
++	    !priv->ucode_boot.v_addr || !priv->ucode_data_backup.v_addr)
++		goto err_pci_alloc;
++
++	/* Copy images into buffers for card's bus-master reads ... */
++
++	/* Runtime instructions (first block of data in file) */
++	src = &ucode->data[0];
++	len = priv->ucode_code.len;
++	IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %d\n",
++		       (int)len);
++	memcpy(priv->ucode_code.v_addr, src, len);
++	IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
++		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
++
++	/* Runtime data (2nd block)
++	 * NOTE:  Copy into backup buffer will be done in iwl_up()  */
++	src = &ucode->data[inst_size];
++	len = priv->ucode_data.len;
++	IWL_DEBUG_INFO("Copying (but not loading) uCode data len %d\n",
++		       (int)len);
++	memcpy(priv->ucode_data.v_addr, src, len);
++	memcpy(priv->ucode_data_backup.v_addr, src, len);
++
++	/* Initialization instructions (3rd block) */
++	if (init_size) {
++		src = &ucode->data[inst_size + data_size];
++		len = priv->ucode_init.len;
++		IWL_DEBUG_INFO("Copying (but not loading) init instr len %d\n",
++			       (int)len);
++		memcpy(priv->ucode_init.v_addr, src, len);
++	}
++
++	/* Initialization data (4th block) */
++	if (init_data_size) {
++		src = &ucode->data[inst_size + data_size + init_size];
++		len = priv->ucode_init_data.len;
++		IWL_DEBUG_INFO("Copying (but not loading) init data len %d\n",
++			       (int)len);
++		memcpy(priv->ucode_init_data.v_addr, src, len);
++	}
++
++	/* Bootstrap instructions (5th block) */
++	src = &ucode->data[inst_size + data_size + init_size + init_data_size];
++	len = priv->ucode_boot.len;
++	IWL_DEBUG_INFO("Copying (but not loading) boot instr len %d\n",
++		       (int)len);
++	memcpy(priv->ucode_boot.v_addr, src, len);
++
++	/* We have our copies now, allow OS release its copies */
++	release_firmware(ucode_raw);
++	return 0;
++
++ err_pci_alloc:
++	IWL_ERROR("failed to allocate pci memory\n");
++	rc = -ENOMEM;
++	iwl_dealloc_ucode_pci(priv);
++
++ err_release:
++	release_firmware(ucode_raw);
++
++ error:
++	return rc;
++}
++
++
++/**
++ * iwl_set_ucode_ptrs - Set uCode address location
++ *
++ * Tell initialization uCode where to find runtime uCode.
++ *
++ * BSM registers initially contain pointers to initialization uCode.
++ * We need to replace them to load runtime uCode inst and data,
++ * and to save runtime data when powering down.
++ */
++static int iwl_set_ucode_ptrs(struct iwl_priv *priv)
++{
++	dma_addr_t pinst;
++	dma_addr_t pdata;
++	int rc = 0;
++	unsigned long flags;
++
++	/* bits 31:0 for 3945 */
++	pinst = priv->ucode_code.p_addr;
++	pdata = priv->ucode_data_backup.p_addr;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	rc = iwl_grab_restricted_access(priv);
++	if (rc) {
++		spin_unlock_irqrestore(&priv->lock, flags);
++		return rc;
++	}
++
++	/* Tell bootstrap uCode where to find image to load */
++	iwl_write_restricted_reg(priv, BSM_DRAM_INST_PTR_REG, pinst);
++	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_PTR_REG, pdata);
++	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
++				 priv->ucode_data.len);
++
++	/* Inst bytecount must be last to set up, bit 31 signals uCode
++	 *   that all new ptr/size info is in place */
++	iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG,
++				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
++
++	iwl_release_restricted_access(priv);
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	IWL_DEBUG_INFO("Runtime uCode pointers are set.\n");
++
++	return rc;
++}
++
++/**
++ * iwl_init_alive_start - Called after REPLY_ALIVE notification receieved
++ *
++ * Called after REPLY_ALIVE notification received from "initialize" uCode.
++ *
++ * The 4965 "initialize" ALIVE reply contains calibration data for:
++ *   Voltage, temperature, and MIMO tx gain correction, now stored in priv
++ *   (3945 does not contain this data).
++ *
++ * Tell "initialize" uCode to go ahead and load the runtime uCode.
++*/
++static void iwl_init_alive_start(struct iwl_priv *priv)
++{
++	/* Check alive response for "valid" sign from uCode */
++	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
++		/* We had an error bringing up the hardware, so take it
++		 * all the way back down so we can try again */
++		IWL_DEBUG_INFO("Initialize Alive failed.\n");
++		goto restart;
++	}
++
++	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
++	 * This is a paranoid check, because we would not have gotten the
++	 * "initialize" alive if code weren't properly loaded.  */
++	if (iwl_verify_ucode(priv)) {
++		/* Runtime instruction load was bad;
++		 * take it all the way back down so we can try again */
++		IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
++		goto restart;
++	}
++
++	/* Send pointers to protocol/runtime uCode image ... init code will
++	 * load and launch runtime uCode, which will send us another "Alive"
++	 * notification. */
++	IWL_DEBUG_INFO("Initialization Alive received.\n");
++	if (iwl_set_ucode_ptrs(priv)) {
++		/* Runtime instruction load won't happen;
++		 * take it all the way back down so we can try again */
++		IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n");
++		goto restart;
++	}
++	return;
++
++ restart:
++	queue_work(priv->workqueue, &priv->restart);
++}
++
++
++/**
++ * iwl_alive_start - called after REPLY_ALIVE notification received
++ *                   from protocol/runtime uCode (initialization uCode's
++ *                   Alive gets handled by iwl_init_alive_start()).
++ */
++static void iwl_alive_start(struct iwl_priv *priv)
++{
++	int rc = 0;
++	int thermal_spin = 0;
++	u32 rfkill;
++
++	IWL_DEBUG_INFO("Runtime Alive received.\n");
++
++	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
++		/* We had an error bringing up the hardware, so take it
++		 * all the way back down so we can try again */
++		IWL_DEBUG_INFO("Alive failed.\n");
++		goto restart;
++	}
++
++	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
++	 * This is a paranoid check, because we would not have gotten the
++	 * "runtime" alive if code weren't properly loaded.  */
++	if (iwl_verify_ucode(priv)) {
++		/* Runtime instruction load was bad;
++		 * take it all the way back down so we can try again */
++		IWL_DEBUG_INFO("Bad runtime uCode load.\n");
++		goto restart;
++	}
++
++	iwl_clear_stations_table(priv);
++
++	rc = iwl_grab_restricted_access(priv);
++	if (rc) {
++		IWL_WARNING("Can not read rfkill status from adapter\n");
++		return;
++	}
++
++	rfkill = iwl_read_restricted_reg(priv, APMG_RFKILL_REG);
++	IWL_DEBUG_INFO("RFKILL status: 0x%x\n", rfkill);
++	iwl_release_restricted_access(priv);
++
++	if (rfkill & 0x1) {
++		clear_bit(STATUS_RF_KILL_HW, &priv->status);
++		/* if rfkill is not on, then wait for thermal
++		 * sensor in adapter to kick in */
++		while (iwl_hw_get_temperature(priv) == 0) {
++			thermal_spin++;
++			udelay(10);
++		}
++
++		if (thermal_spin)
++			IWL_DEBUG_INFO("Thermal calibration took %dus\n",
++				       thermal_spin * 10);
++	} else
++		set_bit(STATUS_RF_KILL_HW, &priv->status);
++
++	/* After the ALIVE response, we can process host commands */
++	set_bit(STATUS_ALIVE, &priv->status);
++
++	/* Clear out the uCode error bit if it is set */
++	clear_bit(STATUS_FW_ERROR, &priv->status);
++
++	rc = iwl_init_channel_map(priv);
++	if (rc) {
++		IWL_ERROR("initializing regulatory failed: %d\n", rc);
++		return;
++	}
++
++	iwl_init_geos(priv);
++
++	if (iwl_is_rfkill(priv))
++		return;
++
++	if (!priv->mac80211_registered) {
++		/* Unlock so any user space entry points can call back into
++		 * the driver without a deadlock... */
++		mutex_unlock(&priv->mutex);
++		iwl_rate_control_register(priv->hw);
++		rc = ieee80211_register_hw(priv->hw);
++		priv->hw->conf.beacon_int = 100;
++		mutex_lock(&priv->mutex);
++
++		if (rc) {
++			IWL_ERROR("Failed to register network "
++				  "device (error %d)\n", rc);
++			return;
++		}
++
++		priv->mac80211_registered = 1;
++
++		iwl_reset_channel_flag(priv);
++	} else
++		ieee80211_start_queues(priv->hw);
++
++	priv->active_rate = priv->rates_mask;
++	priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
++
++	iwl_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode));
++
++	if (iwl_is_associated(priv)) {
++		struct iwl_rxon_cmd *active_rxon =
++				(struct iwl_rxon_cmd *)(&priv->active_rxon);
++
++		memcpy(&priv->staging_rxon, &priv->active_rxon,
++		       sizeof(priv->staging_rxon));
++		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++	} else {
++		/* Initialize our rx_config data */
++		iwl_connection_init_rx_config(priv);
++		memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
++	}
++
++	/* Configure BT coexistence */
++	iwl_send_bt_config(priv);
++
++	/* Configure the adapter for unassociated operation */
++	iwl_commit_rxon(priv);
++
++	/* At this point, the NIC is initialized and operational */
++	priv->notif_missed_beacons = 0;
++	set_bit(STATUS_READY, &priv->status);
++
++	iwl3945_reg_txpower_periodic(priv);
++
++	IWL_DEBUG_INFO("ALIVE processing complete.\n");
++
++	if (priv->error_recovering)
++		iwl_error_recovery(priv);
++
++	return;
++
++ restart:
++	queue_work(priv->workqueue, &priv->restart);
++}
++
++static void iwl_cancel_deferred_work(struct iwl_priv *priv);
++
++static void __iwl_down(struct iwl_priv *priv)
++{
++	unsigned long flags;
++	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
++	struct ieee80211_conf *conf = NULL;
++
++	IWL_DEBUG_INFO(DRV_NAME " is going down\n");
++
++	conf = ieee80211_get_hw_conf(priv->hw);
++
++	if (!exit_pending)
++		set_bit(STATUS_EXIT_PENDING, &priv->status);
++
++	iwl_clear_stations_table(priv);
++
++	/* Unblock any waiting calls */
++	wake_up_interruptible_all(&priv->wait_command_queue);
++
++	iwl_cancel_deferred_work(priv);
++
++	/* Wipe out the EXIT_PENDING status bit if we are not actually
++	 * exiting the module */
++	if (!exit_pending)
++		clear_bit(STATUS_EXIT_PENDING, &priv->status);
++
++	/* stop and reset the on-board processor */
++	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
++
++	/* tell the device to stop sending interrupts */
++	iwl_disable_interrupts(priv);
++
++	if (priv->mac80211_registered)
++		ieee80211_stop_queues(priv->hw);
++
++	/* If we have not previously called iwl_init() then
++	 * clear all bits but the RF Kill and SUSPEND bits and return */
++	if (!iwl_is_init(priv)) {
++		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
++					STATUS_RF_KILL_HW |
++			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
++					STATUS_RF_KILL_SW |
++			       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
++					STATUS_IN_SUSPEND;
++		goto exit;
++	}
++
++	/* ...otherwise clear out all the status bits but the RF Kill and
++	 * SUSPEND bits and continue taking the NIC down. */
++	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
++				STATUS_RF_KILL_HW |
++			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
++				STATUS_RF_KILL_SW |
++			test_bit(STATUS_IN_SUSPEND, &priv->status) <<
++				STATUS_IN_SUSPEND |
++			test_bit(STATUS_FW_ERROR, &priv->status) <<
++				STATUS_FW_ERROR;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	iwl_hw_txq_ctx_stop(priv);
++	iwl_hw_rxq_stop(priv);
++
++	spin_lock_irqsave(&priv->lock, flags);
++	if (!iwl_grab_restricted_access(priv)) {
++		iwl_write_restricted_reg(priv, APMG_CLK_DIS_REG,
++					 APMG_CLK_VAL_DMA_CLK_RQT);
++		iwl_release_restricted_access(priv);
++	}
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	udelay(5);
++
++	iwl_hw_nic_stop_master(priv);
++	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
++	iwl_hw_nic_reset(priv);
++
++ exit:
++	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
++
++	if (priv->ibss_beacon)
++		dev_kfree_skb(priv->ibss_beacon);
++	priv->ibss_beacon = NULL;
++
++	/* clear out any free frames */
++	iwl_clear_free_frames(priv);
++}
++
++static void iwl_down(struct iwl_priv *priv)
++{
++	mutex_lock(&priv->mutex);
++	__iwl_down(priv);
++	mutex_unlock(&priv->mutex);
++}
++
++#define MAX_HW_RESTARTS 5
++
++static int __iwl_up(struct iwl_priv *priv)
++{
++	int rc, i;
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
++		IWL_WARNING("Exit pending; will not bring the NIC up\n");
++		return -EIO;
++	}
++
++	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
++		IWL_WARNING("Radio disabled by SW RF kill (module "
++			    "parameter)\n");
++		return 0;
++	}
++
++	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
++
++	rc = iwl_hw_nic_init(priv);
++	if (rc) {
++		IWL_ERROR("Unable to int nic\n");
++		return rc;
++	}
++
++	/* make sure rfkill handshake bits are cleared */
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
++
++	/* clear (again), then enable host interrupts */
++	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
++	iwl_enable_interrupts(priv);
++
++	/* really make sure rfkill handshake bits are cleared */
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++
++	/* Copy original ucode data image from disk into backup cache.
++	 * This will be used to initialize the on-board processor's
++	 * data SRAM for a clean start when the runtime program first loads. */
++	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
++			priv->ucode_data.len);
++
++	for (i = 0; i < MAX_HW_RESTARTS; i++) {
++
++		iwl_clear_stations_table(priv);
++
++		/* load bootstrap state machine,
++		 * load bootstrap program into processor's memory,
++		 * prepare to load the "initialize" uCode */
++		rc = iwl_load_bsm(priv);
++
++		if (rc) {
++			IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc);
++			continue;
++		}
++
++		/* start card; "initialize" will load runtime ucode */
++		iwl_nic_start(priv);
++
++		/* MAC Address location in EEPROM same for 3945/4965 */
++		get_eeprom_mac(priv, priv->mac_addr);
++		IWL_DEBUG_INFO("MAC address: " MAC_FMT "\n",
++			       MAC_ARG(priv->mac_addr));
++
++		SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
++
++		IWL_DEBUG_INFO(DRV_NAME " is coming up\n");
++
++		return 0;
++	}
++
++	set_bit(STATUS_EXIT_PENDING, &priv->status);
++	__iwl_down(priv);
++
++	/* tried to restart and config the device for as long as our
++	 * patience could withstand */
++	IWL_ERROR("Unable to initialize device after %d attempts.\n", i);
++	return -EIO;
++}
++
++
++/*****************************************************************************
++ *
++ * Workqueue callbacks
++ *
++ *****************************************************************************/
++
++static void iwl_bg_init_alive_start(struct work_struct *data)
++{
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, init_alive_start.work);
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	mutex_lock(&priv->mutex);
++	iwl_init_alive_start(priv);
++	mutex_unlock(&priv->mutex);
++}
++
++static void iwl_bg_alive_start(struct work_struct *data)
++{
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, alive_start.work);
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	mutex_lock(&priv->mutex);
++	iwl_alive_start(priv);
++	mutex_unlock(&priv->mutex);
++}
++
++static void iwl_bg_rf_kill(struct work_struct *work)
++{
++	struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
++
++	wake_up_interruptible(&priv->wait_command_queue);
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	mutex_lock(&priv->mutex);
++
++	if (!iwl_is_rfkill(priv)) {
++		IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
++			  "HW and/or SW RF Kill no longer active, restarting "
++			  "device\n");
++		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
++			queue_work(priv->workqueue, &priv->restart);
++	} else {
++
++		if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
++			IWL_DEBUG_RF_KILL("Can not turn radio back on - "
++					  "disabled by SW switch\n");
++		else
++			IWL_WARNING("Radio Frequency Kill Switch is On:\n"
++				    "Kill switch must be turned off for "
++				    "wireless networking to work.\n");
++	}
++	mutex_unlock(&priv->mutex);
++}
++
++#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
++
++static void iwl_bg_scan_check(struct work_struct *data)
++{
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, scan_check.work);
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	mutex_lock(&priv->mutex);
++	if (test_bit(STATUS_SCANNING, &priv->status) ||
++	    test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++		IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN,
++			  "Scan completion watchdog resetting adapter (%dms)\n",
++			  jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
++		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
++			queue_work(priv->workqueue, &priv->restart);
++	}
++	mutex_unlock(&priv->mutex);
++}
++
++static void iwl_bg_request_scan(struct work_struct *data)
++{
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, request_scan);
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_SCAN_CMD,
++		.len = sizeof(struct iwl_scan_cmd),
++		.meta.flags = CMD_SIZE_HUGE,
++	};
++	int rc = 0;
++	struct iwl_scan_cmd *scan;
++	struct ieee80211_conf *conf = NULL;
++	u8 direct_mask;
++	int phymode;
++
++	conf = ieee80211_get_hw_conf(priv->hw);
++
++	mutex_lock(&priv->mutex);
++
++	if (!iwl_is_ready(priv)) {
++		IWL_WARNING("request scan called when driver not ready.\n");
++		goto done;
++	}
++
++	/* Make sure the scan wasn't cancelled before this queued work
++	 * was given the chance to run... */
++	if (!test_bit(STATUS_SCANNING, &priv->status))
++		goto done;
++
++	/* This should never be called or scheduled if there is currently
++	 * a scan active in the hardware. */
++	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
++		IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. "
++			       "Ignoring second request.\n");
++		rc = -EIO;
++		goto done;
++	}
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
++		IWL_DEBUG_SCAN("Aborting scan due to device shutdown\n");
++		goto done;
++	}
++
++	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++		IWL_DEBUG_HC("Scan request while abort pending.  Queuing.\n");
++		goto done;
++	}
++
++	if (iwl_is_rfkill(priv)) {
++		IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
++		goto done;
++	}
++
++	if (!test_bit(STATUS_READY, &priv->status)) {
++		IWL_DEBUG_HC("Scan request while uninitialized.  Queuing.\n");
++		goto done;
++	}
++
++	if (!priv->scan_bands) {
++		IWL_DEBUG_HC("Aborting scan due to no requested bands\n");
++		goto done;
++	}
++
++	if (!priv->scan) {
++		priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
++				     IWL_MAX_SCAN_SIZE, GFP_KERNEL);
++		if (!priv->scan) {
++			rc = -ENOMEM;
++			goto done;
++		}
++	}
++	scan = priv->scan;
++	memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
++
++	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
++	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
++
++	if (iwl_is_associated(priv)) {
++		u16 interval = 0;
++		u32 extra;
++		u32 suspend_time = 100;
++		u32 scan_suspend_time = 100;
++		unsigned long flags;
++
++		IWL_DEBUG_INFO("Scanning while associated...\n");
++
++		spin_lock_irqsave(&priv->lock, flags);
++		interval = priv->beacon_int;
++		spin_unlock_irqrestore(&priv->lock, flags);
++
++		scan->suspend_time = 0;
++		scan->max_out_time = cpu_to_le32(600 * 1024);
++		if (!interval)
++			interval = suspend_time;
++		/*
++		 * suspend time format:
++		 *  0-19: beacon interval in usec (time before exec.)
++		 * 20-23: 0
++		 * 24-31: number of beacons (suspend between channels)
++		 */
++
++		extra = (suspend_time / interval) << 24;
++		scan_suspend_time = 0xFF0FFFFF &
++		    (extra | ((suspend_time % interval) * 1024));
++
++		scan->suspend_time = cpu_to_le32(scan_suspend_time);
++		IWL_DEBUG_SCAN("suspend_time 0x%X beacon interval %d\n",
++			       scan_suspend_time, interval);
++	}
++
++	/* We should add the ability for user to lock to PASSIVE ONLY */
++	if (priv->one_direct_scan) {
++		IWL_DEBUG_SCAN
++		    ("Kicking off one direct scan for '%s'\n",
++		     iwl_escape_essid(priv->direct_ssid,
++				      priv->direct_ssid_len));
++		scan->direct_scan[0].id = WLAN_EID_SSID;
++		scan->direct_scan[0].len = priv->direct_ssid_len;
++		memcpy(scan->direct_scan[0].ssid,
++		       priv->direct_ssid, priv->direct_ssid_len);
++		direct_mask = 1;
++	} else if (!iwl_is_associated(priv)) {
++		scan->direct_scan[0].id = WLAN_EID_SSID;
++		scan->direct_scan[0].len = priv->essid_len;
++		memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
++		direct_mask = 1;
++	} else
++		direct_mask = 0;
++
++	/* We don't build a direct scan probe request; the uCode will do
++	 * that based on the direct_mask added to each channel entry */
++	scan->tx_cmd.len = cpu_to_le16(
++		iwl_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
++			IWL_MAX_SCAN_SIZE - sizeof(scan), 0));
++	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
++	scan->tx_cmd.sta_id = IWL_BROADCAST_ID;
++	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
++
++	/* flags + rate selection */
++
++	switch (priv->scan_bands) {
++	case 2:
++		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
++		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
++		scan->good_CRC_th = 0;
++		phymode = MODE_IEEE80211G;
++		break;
++
++	case 1:
++		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
++		scan->good_CRC_th = IWL_GOOD_CRC_TH;
++		phymode = MODE_IEEE80211A;
++		break;
++
++	default:
++		IWL_WARNING("Invalid scan band count\n");
++		goto done;
++	}
++
++	/* select Rx antennas */
++	scan->flags |= iwl3945_get_antenna_flags(priv);
++
++	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
++		scan->filter_flags = RXON_FILTER_PROMISC_MSK;
++
++	if (direct_mask)
++		IWL_DEBUG_SCAN
++		    ("Initiating direct scan for %s.\n",
++		     iwl_escape_essid(priv->essid, priv->essid_len));
++	else
++		IWL_DEBUG_SCAN("Initiating indirect scan.\n");
++
++	scan->channel_count =
++		iwl_get_channels_for_scan(
++			priv, phymode, 1, /* active */
++			direct_mask,
++			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++
++	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
++	    scan->channel_count * sizeof(struct iwl_scan_channel);
++	cmd.data = scan;
++	scan->len = cpu_to_le16(cmd.len);
++
++	set_bit(STATUS_SCAN_HW, &priv->status);
++	rc = iwl_send_cmd_sync(priv, &cmd);
++	if (rc)
++		goto done;
++
++	queue_delayed_work(priv->workqueue, &priv->scan_check,
++			   IWL_SCAN_CHECK_WATCHDOG);
++
++	mutex_unlock(&priv->mutex);
++	return;
++
++ done:
++	/* inform mac80211 sacn aborted */
++	queue_work(priv->workqueue, &priv->scan_completed);
++	mutex_unlock(&priv->mutex);
++}
++
++static void iwl_bg_up(struct work_struct *data)
 +{
-+	u32 to_us;
-+	u32 print_summary = 0;
-+	u32 print_dump = 0;	/* set to 1 to dump all frames' contents */
-+	u32 hundred = 0;
-+	u32 dataframe = 0;
-+	u16 fc;
-+	u16 seq_ctl;
-+	u16 channel;
-+	u16 phy_flags;
-+	int rate_sym;
-+	u16 length;
-+	u16 status;
-+	u16 bcn_tmr;
-+	u32 tsf_low;
-+	u64 tsf;
-+	u8 rssi;
-+	u8 agc;
-+	u16 sig_avg;
-+	u16 noise_diff;
-+	struct iwl_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
-+	struct iwl_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-+	struct iwl_rx_frame_end *rx_end = IWL_RX_END(pkt);
-+	u8 *data = IWL_RX_DATA(pkt);
++	struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	mutex_lock(&priv->mutex);
++	__iwl_up(priv);
++	mutex_unlock(&priv->mutex);
++}
++
++static void iwl_bg_restart(struct work_struct *data)
++{
++	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	iwl_down(priv);
++	queue_work(priv->workqueue, &priv->up);
++}
++
++static void iwl_bg_rx_replenish(struct work_struct *data)
++{
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, rx_replenish);
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	mutex_lock(&priv->mutex);
++	iwl_rx_replenish(priv);
++	mutex_unlock(&priv->mutex);
++}
++
++static void iwl_bg_post_associate(struct work_struct *data)
++{
++	struct iwl_priv *priv = container_of(data, struct iwl_priv,
++					     post_associate.work);
++
++	int rc = 0;
++	struct ieee80211_conf *conf = NULL;
++
++	IWL_DEBUG_ASSOC("Associated as %d to: " MAC_FMT "\n",
++			priv->assoc_id, MAC_ARG(priv->active_rxon.bssid_addr));
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	mutex_lock(&priv->mutex);
++
++	conf = ieee80211_get_hw_conf(priv->hw);
++
++	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++	iwl_commit_rxon(priv);
++
++	memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
++	iwl_setup_rxon_timing(priv);
++	rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
++			      sizeof(priv->rxon_timing), &priv->rxon_timing);
++	if (rc)
++		IWL_WARNING("REPLY_RXON_TIMING failed - "
++			    "Attempting to continue.\n");
++
++	priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
++
++	priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
++
++	IWL_DEBUG_ASSOC("assoc id %d beacon interval %d\n",
++			priv->assoc_id, priv->beacon_int);
++
++	if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
++		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
++	else
++		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
++
++	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
++		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
++			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
++		else
++			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
++
++		if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
++			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 +
-+	/* MAC header */
-+	fc = le16_to_cpu(header->frame_control);
-+	seq_ctl = le16_to_cpu(header->seq_ctrl);
++	}
 +
-+	/* metadata */
-+	channel = le16_to_cpu(rx_hdr->channel);
-+	phy_flags = le16_to_cpu(rx_hdr->phy_flags);
-+	rate_sym = rx_hdr->rate;
-+	length = le16_to_cpu(rx_hdr->len);
++	iwl_commit_rxon(priv);
 +
-+	/* end-of-frame status and timestamp */
-+	status = le32_to_cpu(rx_end->status);
-+	bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
-+	tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
-+	tsf = le64_to_cpu(rx_end->timestamp);
++	switch (priv->iw_mode) {
++	case IEEE80211_IF_TYPE_STA:
++		iwl_rate_scale_init(priv->hw, IWL_AP_ID);
++		break;
 +
-+	/* signal statistics */
-+	rssi = rx_stats->rssi;
-+	agc = rx_stats->agc;
-+	sig_avg = le16_to_cpu(rx_stats->sig_avg);
-+	noise_diff = le16_to_cpu(rx_stats->noise_diff);
++	case IEEE80211_IF_TYPE_IBSS:
 +
-+	to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
++		/* clear out the station table */
++		iwl_clear_stations_table(priv);
 +
-+	/* if data frame is to us and all is good,
-+	 *   (optionally) print summary for only 1 out of every 100 */
-+	if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
-+	    (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
-+		dataframe = 1;
-+		if (!group100)
-+			print_summary = 1;	/* print each frame */
-+		else if (priv->framecnt_to_us < 100) {
-+			priv->framecnt_to_us++;
-+			print_summary = 0;
-+		} else {
-+			priv->framecnt_to_us = 0;
-+			print_summary = 1;
-+			hundred = 1;
-+		}
-+	} else {
-+		/* print summary for all other frames */
-+		print_summary = 1;
-+	}
++		iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
++		iwl_rxon_add_station(priv, priv->bssid, 0);
++		iwl3945_sync_sta(priv, IWL_STA_ID,
++				 (priv->phymode == MODE_IEEE80211A)?
++				 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
++				 CMD_ASYNC);
++		iwl_rate_scale_init(priv->hw, IWL_STA_ID);
++		iwl_send_beacon_cmd(priv);
 +
-+	if (print_summary) {
-+		char *title;
-+		u32 rate;
++		break;
 +
-+		if (hundred)
-+			title = "100Frames";
-+		else if (fc & IEEE80211_FCTL_RETRY)
-+			title = "Retry";
-+		else if (ieee80211_is_assoc_response(fc))
-+			title = "AscRsp";
-+		else if (ieee80211_is_reassoc_response(fc))
-+			title = "RasRsp";
-+		else if (ieee80211_is_probe_response(fc)) {
-+			title = "PrbRsp";
-+			print_dump = 1;	/* dump frame contents */
-+		} else if (ieee80211_is_beacon(fc)) {
-+			title = "Beacon";
-+			print_dump = 1;	/* dump frame contents */
-+		} else if (ieee80211_is_atim(fc))
-+			title = "ATIM";
-+		else if (ieee80211_is_auth(fc))
-+			title = "Auth";
-+		else if (ieee80211_is_deauth(fc))
-+			title = "DeAuth";
-+		else if (ieee80211_is_disassoc(fc))
-+			title = "DisAssoc";
-+		else
-+			title = "Frame";
++	case IEEE80211_IF_TYPE_AP:
 +
-+		rate = iwl_rate_index_from_plcp(rate_sym);
-+		if (rate == -1)
-+			rate = 0;
-+		else
-+			rate = iwl_rates[rate].ieee / 2;
++		/* clear out the station table */
++		iwl_clear_stations_table(priv);
 +
-+		/* print frame summary.
-+		 * MAC addresses show just the last byte (for brevity),
-+		 *    but you can hack it to show more, if you'd like to. */
-+		if (dataframe)
-+			IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
-+				     "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
-+				     title, fc, header->addr1[5],
-+				     length, rssi, channel, rate);
-+		else {
-+			/* src/dst addresses assume managed mode */
-+			IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
-+				     "src=0x%02x, rssi=%u, tim=%lu usec, "
-+				     "phy=0x%02x, chnl=%d\n",
-+				     title, fc, header->addr1[5],
-+				     header->addr3[5], rssi,
-+				     tsf_low - priv->scan_start_tsf,
-+				     phy_flags, channel);
-+		}
++		iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
++		iwl_send_beacon_cmd(priv);
++
++		break;
 +	}
-+	if (print_dump)
-+		iwl_print_hex_dump(IWL_DL_RX, data, length);
++
++	/* FIXME: not sure why this doesn't work in AP mode */
++	if (priv->iw_mode != IEEE80211_IF_TYPE_AP)
++		iwl_sequence_reset(priv);
++
++	if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
++		priv->assoc_station_added = 1;
++
++#ifdef CONFIG_IWLWIFI_QOS
++	iwl_activate_qos(priv, 0);
++#endif /* CONFIG_IWLWIFI_QOS */
++	mutex_unlock(&priv->mutex);
 +}
-+#endif
 +
-+static void iwl_unset_hw_setting(struct iwl_priv *priv)
++static void iwl_bg_abort_scan(struct work_struct *work)
 +{
-+	if (priv->hw_setting.shared_virt)
-+		pci_free_consistent(priv->pci_dev,
-+				    sizeof(struct iwl_shared),
-+				    priv->hw_setting.shared_virt,
-+				    priv->hw_setting.shared_phys);
++	struct iwl_priv *priv = container_of(work, struct iwl_priv,
++					     abort_scan);
++
++	if (!iwl_is_ready(priv))
++		return;
++
++	mutex_lock(&priv->mutex);
++
++	set_bit(STATUS_SCAN_ABORTING, &priv->status);
++	iwl_send_scan_abort(priv);
++
++	mutex_unlock(&priv->mutex);
 +}
 +
-+/**
-+ * iwl_supported_rate_to_ie - fill in the supported rate in IE field
++static void iwl_bg_scan_completed(struct work_struct *work)
++{
++	struct iwl_priv *priv =
++	    container_of(work, struct iwl_priv, scan_completed);
++
++	IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	ieee80211_scan_completed(priv->hw);
++
++	/* Since setting the TXPOWER may have been deferred while
++	 * performing the scan, fire one off */
++	mutex_lock(&priv->mutex);
++	iwl_hw_reg_send_txpower(priv);
++	mutex_unlock(&priv->mutex);
++}
++
++/*****************************************************************************
 + *
-+ * return : set the bit for each supported rate insert in ie
-+ */
-+static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
-+				    u16 basic_rate, int max_count)
++ * mac80211 entry point functions
++ *
++ *****************************************************************************/
++
++static int iwl_mac_open(struct ieee80211_hw *hw)
 +{
-+	u16 ret_rates = 0, bit;
-+	int i;
-+	u8 *rates;
++	struct iwl_priv *priv = hw->priv;
 +
-+	rates = &(ie[1]);
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+	for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
-+		if (bit & supported_rate) {
-+			ret_rates |= bit;
-+			rates[*ie] = iwl_rates[i].ieee |
-+			    ((bit & basic_rate) ? 0x80 : 0x00);
-+			*ie = *ie + 1;
-+			if (*ie >= max_count)
-+				break;
-+		}
++	/* we should be verifying the device is ready to be opened */
++	mutex_lock(&priv->mutex);
++
++	priv->is_open = 1;
++
++	if (!iwl_is_rfkill(priv))
++		ieee80211_start_queues(priv->hw);
++
++	mutex_unlock(&priv->mutex);
++	IWL_DEBUG_MAC80211("leave\n");
++	return 0;
++}
++
++static int iwl_mac_stop(struct ieee80211_hw *hw)
++{
++	struct iwl_priv *priv = hw->priv;
++
++	IWL_DEBUG_MAC80211("enter\n");
++	priv->is_open = 0;
++	/*netif_stop_queue(dev); */
++	flush_workqueue(priv->workqueue);
++	IWL_DEBUG_MAC80211("leave\n");
++
++	return 0;
++}
++
++static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
++		      struct ieee80211_tx_control *ctl)
++{
++	struct iwl_priv *priv = hw->priv;
++
++	IWL_DEBUG_MAC80211("enter\n");
++
++	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
++		IWL_DEBUG_MAC80211("leave - monitor\n");
++		return -1;
++	}
++
++	IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
++		     ctl->tx_rate);
++
++	if (iwl_tx_skb(priv, skb, ctl))
++		dev_kfree_skb_any(skb);
++
++	IWL_DEBUG_MAC80211("leave\n");
++	return 0;
++}
++
++static int iwl_mac_add_interface(struct ieee80211_hw *hw,
++				 struct ieee80211_if_init_conf *conf)
++{
++	struct iwl_priv *priv = hw->priv;
++	unsigned long flags;
++
++	IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type);
++	if (conf->mac_addr)
++		IWL_DEBUG_MAC80211("enter: MAC " MAC_FMT "\n",
++				   MAC_ARG(conf->mac_addr));
++
++	if (priv->interface_id) {
++		IWL_DEBUG_MAC80211("leave - interface_id != 0\n");
++		return 0;
 +	}
 +
-+	return ret_rates;
-+}
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->interface_id = conf->if_id;
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	mutex_lock(&priv->mutex);
++	iwl_set_mode(priv, conf->type);
++
++	IWL_DEBUG_MAC80211("leave\n");
++	mutex_unlock(&priv->mutex);
 +
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+void static iwl_set_ht_capab(struct ieee80211_hw *hw,
-+			     struct ieee80211_ht_capability *ht_cap,
-+			     u8 use_wide_chan);
-+#endif
-+#endif
++	return 0;
++}
 +
 +/**
-+ * iwl_fill_probe_req - fill in all required fields and IE for probe request
++ * iwl_mac_config - mac80211 config callback
++ *
++ * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
++ * be set inappropriately and the driver currently sets the hardware up to
++ * use it whenever needed.
 + */
-+static u16 iwl_fill_probe_req(struct iwl_priv *priv,
-+			      struct ieee80211_mgmt *frame,
-+			      int left, int is_direct)
++static int iwl_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
 +{
-+	int len = 0;
-+	u8 *pos = NULL;
-+	u16 ret_rates;
-+
-+	/* Make sure there is enough space for the probe request,
-+	 * two mandatory IEs and the data */
-+	left -= 24;
-+	if (left < 0)
-+		return 0;
-+	len += 24;
++	struct iwl_priv *priv = hw->priv;
++	const struct iwl_channel_info *ch_info;
++	unsigned long flags;
 +
-+	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
-+	memcpy(frame->da, BROADCAST_ADDR, ETH_ALEN);
-+	memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
-+	memcpy(frame->bssid, BROADCAST_ADDR, ETH_ALEN);
-+	frame->seq_ctrl = 0;
++	mutex_lock(&priv->mutex);
++	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
 +
-+	/* fill in our indirect SSID IE */
-+	/* ...next IE... */
++	if (!iwl_is_ready(priv)) {
++		IWL_DEBUG_MAC80211("leave - not ready\n");
++		mutex_unlock(&priv->mutex);
++		return -EIO;
++	}
 +
-+	left -= 2;
-+	if (left < 0)
++	/* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only
++	 * what is exposed through include/ declrations */
++	if (unlikely(!iwl_param_disable_hw_scan &&
++		     test_bit(STATUS_SCANNING, &priv->status))) {
++		IWL_DEBUG_MAC80211("leave - scanning\n");
++		mutex_unlock(&priv->mutex);
 +		return 0;
-+	len += 2;
-+	pos = &(frame->u.probe_req.variable[0]);
-+	*pos++ = WLAN_EID_SSID;
-+	*pos++ = 0;
++	}
 +
-+	/* fill in our direct SSID IE... */
-+	if (is_direct) {
-+		/* ...next IE... */
-+		left -= 2 + priv->essid_len;
-+		if (left < 0)
-+			return 0;
-+		/* ... fill it in... */
-+		*pos++ = WLAN_EID_SSID;
-+		*pos++ = priv->essid_len;
-+		memcpy(pos, priv->essid, priv->essid_len);
-+		pos += priv->essid_len;
-+		len += 2 + priv->essid_len;
++	spin_lock_irqsave(&priv->lock, flags);
++
++	ch_info = iwl_get_channel_info(priv, conf->phymode, conf->channel);
++	if (!is_channel_valid(ch_info)) {
++		IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
++			       conf->channel, conf->phymode);
++		IWL_DEBUG_MAC80211("leave - invalid channel\n");
++		spin_unlock_irqrestore(&priv->lock, flags);
++		mutex_unlock(&priv->mutex);
++		return -EINVAL;
 +	}
 +
-+	/* fill in supported rate */
-+	/* ...next IE... */
-+	left -= 2;
-+	if (left < 0)
-+		return 0;
-+	/* ... fill it in... */
-+	*pos++ = WLAN_EID_SUPP_RATES;
-+	*pos = 0;
-+	ret_rates = priv->active_rate = priv->rates_mask;
-+	priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
++	iwl_set_rxon_channel(priv, conf->phymode, conf->channel);
 +
-+	iwl_supported_rate_to_ie(pos, priv->active_rate,
-+				 priv->active_rate_basic, left);
-+	len += 2 + *pos;
-+	pos += (*pos) + 1;
-+	ret_rates = ~ret_rates & priv->active_rate;
++	iwl_set_flags_for_phymode(priv, conf->phymode);
 +
-+	if (ret_rates == 0)
-+		goto fill_end;
++	/* The list of supported rates and rate mask can be different
++	 * for each phymode; since the phymode may have changed, reset
++	 * the rate mask to what mac80211 lists */
++	iwl_set_rate(priv);
 +
-+	/* fill in supported extended rate */
-+	/* ...next IE... */
-+	left -= 2;
-+	if (left < 0)
-+		return 0;
-+	/* ... fill it in... */
-+	*pos++ = WLAN_EID_EXT_SUPP_RATES;
-+	*pos = 0;
-+	iwl_supported_rate_to_ie(pos, ret_rates, priv->active_rate_basic, left);
-+	if (*pos > 0)
-+		len += 2 + *pos;
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+	if (is_direct && priv->is_ht_enabled) {
-+		u8 use_wide_chan = 1;
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+		if (priv->channel_width != IWL_CHANNEL_WIDTH_40MHZ)
-+			use_wide_chan = 0;
-+		pos += (*pos) + 1;
-+		*pos++ = WLAN_EID_HT_CAPABILITY;
-+		*pos++ = sizeof(struct ieee80211_ht_capability);
-+		iwl_set_ht_capab(NULL, (struct ieee80211_ht_capability *)pos,
-+				 use_wide_chan);
-+		len += 2 + sizeof(struct ieee80211_ht_capability);
++#ifdef IEEE80211_CONF_CHANNEL_SWITCH
++	if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
++		iwl_hw_channel_switch(priv, conf->channel);
++		mutex_unlock(&priv->mutex);
++		return 0;
 +	}
-+#endif  /*CONFIG_IWLWIFI_HT */
 +#endif
 +
-+ fill_end:
-+	return (u16)len;
-+}
++	iwl_radio_kill_sw(priv, !conf->radio_enabled);
 +
-+/*
-+ * QoS  support
-+*/
-+#ifdef CONFIG_IWLWIFI_QOS
-+static int iwl_send_qos_params_command(struct iwl_priv *priv,
-+				       struct iwl_qosparam_cmd *qos)
-+{
++	if (!conf->radio_enabled) {
++		IWL_DEBUG_MAC80211("leave - radio disabled\n");
++		mutex_unlock(&priv->mutex);
++		return 0;
++	}
 +
-+	return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
-+				sizeof(struct iwl_qosparam_cmd), qos);
++	if (iwl_is_rfkill(priv)) {
++		IWL_DEBUG_MAC80211("leave - RF kill\n");
++		mutex_unlock(&priv->mutex);
++		return -EIO;
++	}
++
++	iwl_set_rate(priv);
++
++	if (memcmp(&priv->active_rxon,
++		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
++		iwl_commit_rxon(priv);
++	else
++		IWL_DEBUG_INFO("No re-sending same RXON configuration.\n");
++
++	IWL_DEBUG_MAC80211("leave\n");
++
++	mutex_unlock(&priv->mutex);
++
++	return 0;
 +}
 +
-+static void iwl_reset_qos(struct iwl_priv *priv)
++static void iwl_config_ap(struct iwl_priv *priv)
 +{
-+	u16 cw_min = 15;
-+	u16 cw_max = 1023;
-+	u8 aifs = 2;
-+	u8 is_legacy = 0;
-+	unsigned long flags;
-+	int i;
++	int rc = 0;
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	priv->qos_data.qos_active = 0;
++	if (priv->status & STATUS_EXIT_PENDING)
++		return;
 +
-+	if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
-+		if (priv->qos_data.qos_enable)
-+			priv->qos_data.qos_active = IPW_QOS_WMM;
-+		if (!(priv->active_rate & 0xfff0)) {
-+			cw_min = 31;
-+			is_legacy = 1;
-+		}
-+	} else {
-+		if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
-+			cw_min = 31;
-+			is_legacy = 1;
-+		}
-+	}
++	/* The following should be done only at AP bring up */
++	if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) {
 +
-+	if (priv->qos_data.qos_active)
-+		aifs = 3;
++		/* RXON - unassoc (to set timing command) */
++		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++		iwl_commit_rxon(priv);
 +
-+	priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
-+	priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
-+	priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
-+	priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
-+	priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
++		/* RXON Timing */
++		memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
++		iwl_setup_rxon_timing(priv);
++		rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
++				sizeof(priv->rxon_timing), &priv->rxon_timing);
++		if (rc)
++			IWL_WARNING("REPLY_RXON_TIMING failed - "
++					"Attempting to continue.\n");
 +
-+	if (priv->qos_data.qos_active) {
-+		i = 1;
-+		priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
-+		priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
-+		priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
-+		priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
-+		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++#ifdef CONFIG_IWL_QOS
++		iwl_reset_qos(priv);
++#endif /* CONFIG_IWL_QOS */
 +
-+		i = 2;
-+		priv->qos_data.def_qos_parm.ac[i].cw_min =
-+			cpu_to_le16((cw_min + 1) / 2 - 1);
-+		priv->qos_data.def_qos_parm.ac[i].cw_max =
-+			cpu_to_le16(cw_max);
-+		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
-+		if (is_legacy)
-+			priv->qos_data.def_qos_parm.ac[i].edca_txop =
-+				cpu_to_le16(6016);
++		/* FIXME: what should be the assoc_id for AP? */
++		priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
++		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
++			priv->staging_rxon.flags |=
++				RXON_FLG_SHORT_PREAMBLE_MSK;
 +		else
-+			priv->qos_data.def_qos_parm.ac[i].edca_txop =
-+				cpu_to_le16(3008);
-+		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++			priv->staging_rxon.flags &=
++				~RXON_FLG_SHORT_PREAMBLE_MSK;
++
++		if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
++			if (priv->assoc_capability &
++				WLAN_CAPABILITY_SHORT_SLOT_TIME)
++				priv->staging_rxon.flags |=
++					RXON_FLG_SHORT_SLOT_MSK;
++			else
++				priv->staging_rxon.flags &=
++					~RXON_FLG_SHORT_SLOT_MSK;
 +
-+		i = 3;
-+		priv->qos_data.def_qos_parm.ac[i].cw_min =
-+			cpu_to_le16((cw_min + 1) / 4 - 1);
-+		priv->qos_data.def_qos_parm.ac[i].cw_max =
-+			cpu_to_le16((cw_max + 1) / 2 - 1);
-+		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
-+		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-+		if (is_legacy)
-+			priv->qos_data.def_qos_parm.ac[i].edca_txop =
-+				cpu_to_le16(3264);
-+		else
-+			priv->qos_data.def_qos_parm.ac[i].edca_txop =
-+				cpu_to_le16(1504);
-+	} else {
-+		for (i = 1; i < 4; i++) {
-+			priv->qos_data.def_qos_parm.ac[i].cw_min =
-+				cpu_to_le16(cw_min);
-+			priv->qos_data.def_qos_parm.ac[i].cw_max =
-+				cpu_to_le16(cw_max);
-+			priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
-+			priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
-+			priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++			if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
++				priv->staging_rxon.flags &=
++					~RXON_FLG_SHORT_SLOT_MSK;
 +		}
-+	}
-+	IWL_DEBUG_QOS("set QoS to default \n");
++		/* restore RXON assoc */
++		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
++		iwl_commit_rxon(priv);
++		iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
++		iwl_send_beacon_cmd(priv);
++	} else
++		iwl_send_beacon_cmd(priv);
 +
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	/* FIXME - we need to add code here to detect a totally new
++	 * configuration, reset the AP, unassoc, rxon timing, assoc,
++	 * clear sta table, add BCAST sta... */
 +}
 +
-+static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
++static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
++				    struct ieee80211_if_conf *conf)
 +{
++	struct iwl_priv *priv = hw->priv;
 +	unsigned long flags;
++	int rc;
 +
-+	if (priv == NULL)
-+		return;
-+
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+		return;
-+
-+	if (!priv->qos_data.qos_enable)
-+		return;
-+
-+	spin_lock_irqsave(&priv->lock, flags);
-+	priv->qos_data.def_qos_parm.qos_flags = 0;
++	if (conf == NULL)
++		return -EIO;
 +
-+	if (priv->qos_data.qos_cap.q_AP.queue_request &&
-+	    !priv->qos_data.qos_cap.q_AP.txop_request)
-+		priv->qos_data.def_qos_parm.qos_flags |=
-+			QOS_PARAM_FLG_TXOP_TYPE_MSK;
++	if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
++	    (!conf->beacon || !conf->ssid_len)) {
++		IWL_DEBUG_MAC80211
++		    ("Leaving in AP mode because HostAPD is not ready.\n");
++		return 0;
++	}
 +
-+	if (priv->qos_data.qos_active)
-+		priv->qos_data.def_qos_parm.qos_flags |=
-+			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
++	mutex_lock(&priv->mutex);
 +
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	IWL_DEBUG_MAC80211("enter: interface id %d\n", if_id);
++	if (conf->bssid)
++		IWL_DEBUG_MAC80211("bssid: " MAC_FMT "\n",
++				   MAC_ARG(conf->bssid));
 +
-+	if (force || iwl_is_associated(priv)) {
-+		IWL_DEBUG_QOS("send QoS cmd with Qos active %d \n",
-+			      priv->qos_data.qos_active);
++	if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
++	    !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
++		IWL_DEBUG_MAC80211("leave - scanning\n");
++		mutex_unlock(&priv->mutex);
++		return 0;
++	}
 +
-+		iwl_send_qos_params_command(priv,
-+				&(priv->qos_data.def_qos_parm));
++	if (priv->interface_id != if_id) {
++		IWL_DEBUG_MAC80211("leave - interface_id != if_id\n");
++		mutex_unlock(&priv->mutex);
++		return 0;
 +	}
-+}
 +
-+#endif /* CONFIG_IWLWIFI_QOS */
-+/*
-+ * Power management (not Tx power!) functions
-+ */
-+#define MSEC_TO_USEC 1024
++	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
++		if (!conf->bssid) {
++			conf->bssid = priv->mac_addr;
++			memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
++			IWL_DEBUG_MAC80211("bssid was set to: " MAC_FMT "\n",
++					   MAC_ARG(conf->bssid));
++		}
++		if (priv->ibss_beacon)
++			dev_kfree_skb(priv->ibss_beacon);
 +
-+#if IWL == 3945
-+#define NOSLP __constant_cpu_to_le32(0)
-+#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK
-+#elif IWL == 4965
-+#define NOSLP __constant_cpu_to_le16(0), 0, 0
-+#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
-+#endif
-+#define SLP_TIMEOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC)
-+#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \
-+				     __constant_cpu_to_le32(X1), \
-+				     __constant_cpu_to_le32(X2), \
-+				     __constant_cpu_to_le32(X3), \
-+				     __constant_cpu_to_le32(X4)}
++		priv->ibss_beacon = conf->beacon;
++	}
 +
++	if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
++	    !is_multicast_ether_addr(conf->bssid)) {
++		/* If there is currently a HW scan going on in the background
++		 * then we need to cancel it else the RXON below will fail. */
++		if (iwl_scan_cancel_timeout(priv, 100)) {
++			IWL_WARNING("Aborted scan still in progress "
++				    "after 100ms\n");
++			IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
++			mutex_unlock(&priv->mutex);
++			return -EAGAIN;
++		}
++		memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);
 +
-+/* default power management (not Tx power) table values */
-+/* for tim  0-10 */
-+static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = {
-+	{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
-+	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
-+	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0},
-+	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100), SLP_VEC(2, 6, 9, 9, 10)}, 0},
-+	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 10)}, 1},
-+	{{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1}
-+};
++		/* TODO: Audit driver for usage of these members and see
++		 * if mac80211 deprecates them (priv->bssid looks like it
++		 * shouldn't be there, but I haven't scanned the IBSS code
++		 * to verify) - jpk */
++		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
 +
-+/* for tim > 10 */
-+static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = {
-+	{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
-+	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500),
-+		 SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
-+	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300),
-+		 SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
-+	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100),
-+		 SLP_VEC(2, 6, 9, 9, 0xFF)}, 0},
-+	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
-+	{{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25),
-+		 SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
-+};
++		if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
++			iwl_config_ap(priv);
++		else {
++			priv->staging_rxon.filter_flags |=
++						RXON_FILTER_ASSOC_MSK;
++			rc = iwl_commit_rxon(priv);
++			if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
++				iwl_rxon_add_station(
++					priv, priv->active_rxon.bssid_addr, 1);
++		}
 +
-+int iwl_power_init_handle(struct iwl_priv *priv)
-+{
-+	int rc = 0, i;
-+	struct iwl_power_mgr *pow_data;
-+	int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_AC;
-+	u16 pci_pm;
++	} else {
++		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++		iwl_commit_rxon(priv);
++	}
 +
-+	IWL_DEBUG_POWER("Initialize power \n");
++	spin_lock_irqsave(&priv->lock, flags);
++	if (!conf->ssid_len)
++		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
++	else
++		memcpy(priv->essid, conf->ssid, conf->ssid_len);
 +
-+	pow_data = &(priv->power_data);
++	priv->essid_len = conf->ssid_len;
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+	memset(pow_data, 0, sizeof(*pow_data));
++	IWL_DEBUG_MAC80211("leave\n");
++	mutex_unlock(&priv->mutex);
 +
-+	pow_data->active_index = IWL_POWER_RANGE_0;
-+	pow_data->dtim_val = 0xffff;
++	return 0;
++}
 +
-+	memcpy(&pow_data->pwr_range_0[0], &range_0[0], size);
-+	memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
++static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
++				     struct ieee80211_if_init_conf *conf)
++{
++	struct iwl_priv *priv = hw->priv;
 +
-+	rc = pci_read_config_word(priv->pci_dev, PCI_LINK_CTRL, &pci_pm);
-+	if (rc != 0)
-+		return 0;
-+	else {
-+		struct iwl_powertable_cmd *cmd;
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+		IWL_DEBUG_POWER("adjust power command flags\n");
++	mutex_lock(&priv->mutex);
++	if (priv->interface_id == conf->if_id) {
++		priv->interface_id = 0;
++		memset(priv->bssid, 0, ETH_ALEN);
++		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
++		priv->essid_len = 0;
++	}
++	mutex_unlock(&priv->mutex);
 +
-+		for (i = 0; i < IWL_POWER_AC; i++) {
-+			cmd = &pow_data->pwr_range_0[i].cmd;
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+			if (pci_pm & 0x1)
-+				cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
-+			else
-+				cmd->flags |= IWL_POWER_PCI_PM_MSK;
-+		}
-+	}
-+	return rc;
 +}
 +
-+static int iwl_update_power_cmd(struct iwl_priv *priv,
-+				struct iwl_powertable_cmd *cmd, u32 mode)
++#define IWL_DELAY_NEXT_SCAN (HZ*2)
++static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
 +{
-+	int rc = 0, i;
-+	u8 skip;
-+	u32 max_sleep = 0;
-+	struct iwl_power_vec_entry *range;
-+	u8 period = 0;
-+	struct iwl_power_mgr *pow_data;
-+
-+	if (mode > IWL_POWER_INDEX_5) {
-+		IWL_DEBUG_POWER("Error invalid power mode \n");
-+		return -1;
-+	}
-+	pow_data = &(priv->power_data);
-+
-+	if (pow_data->active_index == IWL_POWER_RANGE_0)
-+		range = &pow_data->pwr_range_0[0];
-+	else
-+		range = &pow_data->pwr_range_1[1];
-+
-+	memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd));
++	int rc = 0;
++	unsigned long flags;
++	struct iwl_priv *priv = hw->priv;
 +
-+#ifdef IWL_MAC80211_DISABLE
-+	if (priv->assoc_network != NULL) {
-+		unsigned long flags;
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+		period = priv->assoc_network->tim.tim_period;
++	spin_lock_irqsave(&priv->lock, flags);
++
++	if (!iwl_is_ready_rf(priv)) {
++		rc = -EIO;
++		IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
++		goto out_unlock;
 +	}
-+#endif	/*IWL_MAC80211_DISABLE */
-+	skip = range[mode].no_dtim;
 +
-+	if (period == 0) {
-+		period = 1;
-+		skip = 0;
++	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {	/* APs don't scan */
++		rc = -EIO;
++		IWL_ERROR("ERROR: APs don't scan\n");
++		goto out_unlock;
 +	}
 +
-+	if (skip == 0) {
-+		max_sleep = period;
-+		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
-+	} else {
-+		__le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
-+		max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
-+		cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
++	/* if we just finished scan ask for delay */
++	if (priv->last_scan_jiffies &&
++	    time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
++		       jiffies)) {
++		rc = -EAGAIN;
++		goto out_unlock;
 +	}
++	if (len) {
++		IWL_DEBUG_SCAN("direct scan for  "
++			       "%s [%d]\n ",
++			       iwl_escape_essid(ssid, len), (int)len);
 +
-+	for (i = 0; i < IWL_POWER_VEC_SIZE; i++) {
-+		if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
-+			cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
++		priv->one_direct_scan = 1;
++		priv->direct_ssid_len = (u8)
++		    min((u8) len, (u8) IW_ESSID_MAX_SIZE);
++		memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
 +	}
 +
-+	IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags);
-+	IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
-+	IWL_DEBUG_POWER("Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
-+	IWL_DEBUG_POWER("Sleep interval vector = { %d , %d , %d , %d , %d }\n",
-+			le32_to_cpu(cmd->sleep_interval[0]),
-+			le32_to_cpu(cmd->sleep_interval[1]),
-+			le32_to_cpu(cmd->sleep_interval[2]),
-+			le32_to_cpu(cmd->sleep_interval[3]),
-+			le32_to_cpu(cmd->sleep_interval[4]));
++	rc = iwl_scan_initiate(priv);
++
++	IWL_DEBUG_MAC80211("leave\n");
++
++out_unlock:
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
 +	return rc;
 +}
 +
-+static int iwl_send_power_mode(struct iwl_priv *priv, u32 mode)
++static int iwl_mac_set_key(struct ieee80211_hw *hw, set_key_cmd cmd, u8 *addr,
++			   struct ieee80211_key_conf *key, int aid)
 +{
-+	u32 final_mode = mode;
-+	int rc;
-+	struct iwl_powertable_cmd cmd;
++	struct iwl_priv *priv = hw->priv;
++	int rc = 0;
++	u8 sta_id;
 +
-+	/* If on battery, set to 3,
-+	 * if plugged into AC power, set to CAM ("continuosly aware mode"),
-+	 * else user level */
-+	switch (mode) {
-+	case IWL_POWER_BATTERY:
-+		final_mode = IWL_POWER_INDEX_3;
-+		break;
-+	case IWL_POWER_AC:
-+		final_mode = IWL_POWER_MODE_CAM;
-+		break;
-+	default:
-+		final_mode = mode;
-+		break;
-+	}
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+#if IWL == 4965
-+	cmd.keep_alive_beacons = 0;
-+#endif
++	if (!iwl_param_hwcrypto) {
++		IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
++		return -EOPNOTSUPP;
++	}
 +
-+	iwl_update_power_cmd(priv, &cmd, final_mode);
++	sta_id = iwl_hw_find_station(priv, addr);
++	if (sta_id == IWL_INVALID_STATION) {
++		IWL_DEBUG_MAC80211("leave - " MAC_FMT " not in station map.\n",
++				   MAC_ARG(addr));
++		return -EINVAL;
++	}
 +
-+	rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
++	mutex_lock(&priv->mutex);
 +
-+	if (final_mode == IWL_POWER_MODE_CAM)
-+		clear_bit(STATUS_POWER_PMI, &priv->status);
++	if (cmd == SET_KEY)
++		rc = iwl_update_sta_key_info(priv, key, sta_id);
 +	else
-+		set_bit(STATUS_POWER_PMI, &priv->status);
++		rc = -EINVAL;
++
++	if (!rc) {
++		iwl_set_rxon_hwcrypto(priv, 1);
++		iwl_commit_rxon(priv);
++		key->flags &= ~IEEE80211_KEY_FORCE_SW_ENCRYPT;
++		key->hw_key_idx = sta_id;
++		IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n");
++	}
++
++	IWL_DEBUG_MAC80211("leave\n");
++	mutex_unlock(&priv->mutex);
 +
 +	return rc;
 +}
 +
-+int iwl_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
++static int iwl_mac_conf_tx(struct ieee80211_hw *hw, int queue,
++			   const struct ieee80211_tx_queue_params *params)
 +{
-+	/* Filter incoming packets to determine if they are targeted toward
-+	 * this network, discarding packets coming from ourselves */
-+	switch (priv->iw_mode) {
-+	case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source    | BSSID */
-+		/* packets from our adapter are dropped (echo) */
-+		if (!compare_ether_addr(header->addr2, priv->mac_addr))
-+			return 0;
-+		/* {broad,multi}cast packets to our IBSS go through */
-+		if (is_multicast_ether_addr(header->addr1))
-+			return !compare_ether_addr(header->addr3, priv->bssid);
-+		/* packets to our adapter go through */
-+		return !compare_ether_addr(header->addr1, priv->mac_addr);
-+	case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
-+		/* packets from our adapter are dropped (echo) */
-+		if (!compare_ether_addr(header->addr3, priv->mac_addr))
-+			return 0;
-+		/* {broad,multi}cast packets to our BSS go through */
-+		if (is_multicast_ether_addr(header->addr1))
-+			return !compare_ether_addr(header->addr2, priv->bssid);
-+		/* packets to our adapter go through */
-+		return !compare_ether_addr(header->addr1, priv->mac_addr);
-+	}
-+
-+	return 1;
-+}
++	struct iwl_priv *priv = hw->priv;
++#ifdef CONFIG_IWLWIFI_QOS
++	unsigned long flags;
++	int q;
++#endif /* CONFIG_IWL_QOS */
 +
-+#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+const char *iwl_get_tx_fail_reason(u32 status)
-+{
-+	switch (status & TX_STATUS_MSK) {
-+	case TX_STATUS_SUCCESS:
-+		return "SUCCESS";
-+		TX_STATUS_ENTRY(SHORT_LIMIT);
-+		TX_STATUS_ENTRY(LONG_LIMIT);
-+		TX_STATUS_ENTRY(FIFO_UNDERRUN);
-+		TX_STATUS_ENTRY(MGMNT_ABORT);
-+		TX_STATUS_ENTRY(NEXT_FRAG);
-+		TX_STATUS_ENTRY(LIFE_EXPIRE);
-+		TX_STATUS_ENTRY(DEST_PS);
-+		TX_STATUS_ENTRY(ABORTED);
-+		TX_STATUS_ENTRY(BT_RETRY);
-+		TX_STATUS_ENTRY(STA_INVALID);
-+		TX_STATUS_ENTRY(FRAG_DROPPED);
-+		TX_STATUS_ENTRY(TID_DISABLE);
-+		TX_STATUS_ENTRY(FRAME_FLUSHED);
-+		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
-+		TX_STATUS_ENTRY(TX_LOCKED);
-+		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
++	if (!iwl_is_ready_rf(priv)) {
++		IWL_DEBUG_MAC80211("leave - RF not ready\n");
++		return -EIO;
 +	}
 +
-+	return "UNKNOWN";
-+}
++	if (queue >= AC_NUM) {
++		IWL_DEBUG_MAC80211("leave - queue >= AC_NUM %d\n", queue);
++		return 0;
++	}
 +
-+/**
-+ * iwl_scan_cancel - Cancel any currently executing HW scan
-+ *
-+ * NOTE: priv->mutex is not required before calling this function
-+ */
-+static int iwl_scan_cancel(struct iwl_priv *priv)
-+{
-+	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
-+		clear_bit(STATUS_SCANNING, &priv->status);
++#ifdef CONFIG_IWLWIFI_QOS
++	if (!priv->qos_data.qos_enable) {
++		priv->qos_data.qos_active = 0;
++		IWL_DEBUG_MAC80211("leave - qos not enabled\n");
 +		return 0;
 +	}
++	q = AC_NUM - 1 - queue;
 +
-+	if (test_bit(STATUS_SCANNING, &priv->status)) {
-+		if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-+			IWL_DEBUG_SCAN("Queuing scan abort.\n");
-+			set_bit(STATUS_SCAN_ABORTING, &priv->status);
-+			queue_work(priv->workqueue, &priv->abort_scan);
++	spin_lock_irqsave(&priv->lock, flags);
 +
-+		} else
-+			IWL_DEBUG_SCAN("Scan abort already in progress.\n");
++	priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
++	priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
++	priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
++	priv->qos_data.def_qos_parm.ac[q].edca_txop =
++			cpu_to_le16((params->burst_time * 100));
 +
-+		return test_bit(STATUS_SCANNING, &priv->status);
-+	}
++	priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
++	priv->qos_data.qos_active = 1;
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	mutex_lock(&priv->mutex);
++	if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
++		iwl_activate_qos(priv, 1);
++	else if (priv->assoc_id && iwl_is_associated(priv))
++		iwl_activate_qos(priv, 0);
++
++	mutex_unlock(&priv->mutex);
++
++#endif /*CONFIG_IWLWIFI_QOS */
 +
++	IWL_DEBUG_MAC80211("leave\n");
 +	return 0;
 +}
 +
-+/**
-+ * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
-+ * @ms: amount of time to wait (in milliseconds) for scan to abort
-+ *
-+ * NOTE: priv->mutex must be held before calling this function
-+ */
-+static int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
++static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
++				struct ieee80211_tx_queue_stats *stats)
 +{
-+	unsigned long now = jiffies;
-+	int ret;
++	struct iwl_priv *priv = hw->priv;
++	int i, avail;
++	struct iwl_tx_queue *txq;
++	struct iwl_queue *q;
++	unsigned long flags;
 +
-+	ret = iwl_scan_cancel(priv);
-+	if (ret && ms) {
-+		mutex_unlock(&priv->mutex);
-+		while (!time_after(jiffies, now + msecs_to_jiffies(ms)) &&
-+				test_bit(STATUS_SCANNING, &priv->status))
-+			msleep(1);
-+		mutex_lock(&priv->mutex);
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+		return test_bit(STATUS_SCANNING, &priv->status);
++	if (!iwl_is_ready_rf(priv)) {
++		IWL_DEBUG_MAC80211("leave - RF not ready\n");
++		return -EIO;
 +	}
 +
-+	return ret;
-+}
++	spin_lock_irqsave(&priv->lock, flags);
 +
-+static void iwl_sequence_reset(struct iwl_priv *priv)
-+{
-+	/* Reset ieee stats */
++	for (i = 0; i < AC_NUM; i++) {
++		txq = &priv->txq[i];
++		q = &txq->q;
++		avail = iwl_queue_space(q);
 +
-+	/* We don't reset the net_device_stats (ieee->stats) on
-+	 * re-association */
++		stats->data[i].len = q->n_window - avail;
++		stats->data[i].limit = q->n_window - q->high_mark;
++		stats->data[i].count = q->n_window;
 +
-+	priv->last_seq_num = -1;
-+	priv->last_frag_num = -1;
-+	priv->last_packet_time = 0;
++	}
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+	iwl_scan_cancel(priv);
-+}
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+#if IWL == 4965
-+#define MAX_UCODE_BEACON_INTERVAL	4096
-+#else
-+#define MAX_UCODE_BEACON_INTERVAL	1024
-+#endif
-+#define INTEL_CONN_LISTEN_INTERVAL	__constant_cpu_to_le16(0xA)
++	return 0;
++}
 +
-+static __le16 iwl_adjust_beacon_interval(u16 beacon_val)
++static int iwl_mac_get_stats(struct ieee80211_hw *hw,
++			     struct ieee80211_low_level_stats *stats)
 +{
-+	u16 new_val = 0;
-+	u16 beacon_factor = 0;
++	IWL_DEBUG_MAC80211("enter\n");
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+	beacon_factor =
-+	    (beacon_val + MAX_UCODE_BEACON_INTERVAL)
-+		/ MAX_UCODE_BEACON_INTERVAL;
-+	new_val = beacon_val / beacon_factor;
++	return 0;
++}
 +
-+	return cpu_to_le16(new_val);
++static u64 iwl_mac_get_tsf(struct ieee80211_hw *hw)
++{
++	IWL_DEBUG_MAC80211("enter\n");
++	IWL_DEBUG_MAC80211("leave\n");
++
++	return 0;
 +}
 +
-+static void iwl_setup_rxon_timing(struct iwl_priv *priv)
++static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
 +{
-+	u64 interval_tm_unit;
-+	u64 tsf, result;
++	struct iwl_priv *priv = hw->priv;
 +	unsigned long flags;
-+	struct ieee80211_conf *conf = NULL;
-+	u16 beacon_int = 0;
 +
-+	conf = ieee80211_get_hw_conf(priv->hw);
++	mutex_lock(&priv->mutex);
++	IWL_DEBUG_MAC80211("enter\n");
++
++#ifdef CONFIG_IWLWIFI_QOS
++	iwl_reset_qos(priv);
++#endif
++	cancel_delayed_work(&priv->post_associate);
 +
 +	spin_lock_irqsave(&priv->lock, flags);
-+	priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp1);
-+	priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp0);
++	priv->assoc_id = 0;
++	priv->assoc_capability = 0;
++	priv->call_post_assoc_from_beacon = 0;
++	priv->assoc_station_added = 0;
 +
-+	priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;
++	/* new association get rid of ibss beacon skb */
++	if (priv->ibss_beacon)
++		dev_kfree_skb(priv->ibss_beacon);
 +
-+	tsf = priv->timestamp1;
-+	tsf = ((tsf << 32) | priv->timestamp0);
++	priv->ibss_beacon = NULL;
++
++	priv->beacon_int = priv->hw->conf.beacon_int;
++	priv->timestamp1 = 0;
++	priv->timestamp0 = 0;
++	if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
++		priv->beacon_int = 0;
 +
-+	beacon_int = priv->beacon_int;
 +	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+	if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
-+		if (beacon_int == 0) {
-+			priv->rxon_timing.beacon_interval = cpu_to_le16(100);
-+			priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
-+		} else {
-+			priv->rxon_timing.beacon_interval =
-+				cpu_to_le16(beacon_int);
-+			priv->rxon_timing.beacon_interval =
-+			    iwl_adjust_beacon_interval(
-+				le16_to_cpu(priv->rxon_timing.beacon_interval));
-+		}
++	/* Per mac80211.h: This is only used in IBSS mode... */
++	if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
++		IWL_DEBUG_MAC80211("leave - not in IBSS\n");
++		mutex_unlock(&priv->mutex);
++		return;
++	}
 +
-+		priv->rxon_timing.atim_window = 0;
-+	} else {
-+		priv->rxon_timing.beacon_interval =
-+			iwl_adjust_beacon_interval(conf->beacon_int);
-+		/* TODO: we need to get atim_window from upper stack
-+		 * for now we set to 0 */
-+		priv->rxon_timing.atim_window = 0;
++	if (!iwl_is_ready_rf(priv)) {
++		IWL_DEBUG_MAC80211("leave - not ready\n");
++		mutex_unlock(&priv->mutex);
++		return;
 +	}
 +
-+	interval_tm_unit =
-+		(le16_to_cpu(priv->rxon_timing.beacon_interval) * 1024);
-+	result = do_div(tsf, interval_tm_unit);
-+	priv->rxon_timing.beacon_init_val =
-+	    cpu_to_le32((u32) ((u64) interval_tm_unit - result));
++	priv->only_active_channel = 0;
++
++	iwl_set_rate(priv);
++
++	mutex_unlock(&priv->mutex);
++
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+	IWL_DEBUG_ASSOC
-+	    ("beacon interval %d beacon timer %d beacon tim %d\n",
-+		le16_to_cpu(priv->rxon_timing.beacon_interval),
-+		le32_to_cpu(priv->rxon_timing.beacon_init_val),
-+		le16_to_cpu(priv->rxon_timing.atim_window));
 +}
 +
-+static int iwl_scan_initiate(struct iwl_priv *priv)
++static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
++				 struct ieee80211_tx_control *control)
 +{
-+	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
-+		IWL_ERROR("APs don't scan.\n");
-+		return 0;
-+	}
++	struct iwl_priv *priv = hw->priv;
++	unsigned long flags;
++
++	mutex_lock(&priv->mutex);
++	IWL_DEBUG_MAC80211("enter\n");
 +
 +	if (!iwl_is_ready_rf(priv)) {
-+		IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
++		IWL_DEBUG_MAC80211("leave - RF not ready\n");
++		mutex_unlock(&priv->mutex);
 +		return -EIO;
 +	}
 +
-+	if (test_bit(STATUS_SCANNING, &priv->status)) {
-+		IWL_DEBUG_SCAN("Scan already in progress.\n");
-+		return -EAGAIN;
++	if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
++		IWL_DEBUG_MAC80211("leave - not IBSS\n");
++		mutex_unlock(&priv->mutex);
++		return -EIO;
 +	}
 +
-+	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-+		IWL_DEBUG_SCAN("Scan request while abort pending.  "
-+			       "Queuing.\n");
-+		return -EAGAIN;
-+	}
++	spin_lock_irqsave(&priv->lock, flags);
 +
-+	IWL_DEBUG_INFO("Starting scan...\n");
-+	priv->scan_bands = 2;
-+	set_bit(STATUS_SCANNING, &priv->status);
-+	priv->scan_start = jiffies;
-+	priv->scan_pass_start = priv->scan_start;
++	if (priv->ibss_beacon)
++		dev_kfree_skb(priv->ibss_beacon);
 +
-+	queue_work(priv->workqueue, &priv->request_scan);
++	priv->ibss_beacon = skb;
 +
-+	return 0;
-+}
++	priv->assoc_id = 0;
 +
-+static int iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
-+{
-+	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
++	IWL_DEBUG_MAC80211("leave\n");
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+	if (hw_decrypt)
-+		rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
-+	else
-+		rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
++#ifdef CONFIG_IWLWIFI_QOS
++	iwl_reset_qos(priv);
++#endif
++
++	queue_work(priv->workqueue, &priv->post_associate.work);
++
++	mutex_unlock(&priv->mutex);
 +
 +	return 0;
 +}
 +
-+static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode)
++/*****************************************************************************
++ *
++ * sysfs attributes
++ *
++ *****************************************************************************/
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++
++/*
++ * The following adds a new attribute to the sysfs representation
++ * of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/)
++ * used for controlling the debug level.
++ *
++ * See the level definitions in ipw for details.
++ */
++
++static ssize_t show_debug_level(struct device_driver *d, char *buf)
 +{
-+	if (phymode == MODE_IEEE80211A) {
-+		priv->staging_rxon.flags &=
-+		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
-+		      | RXON_FLG_CCK_MSK);
-+		priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
-+	} else {
-+		/* Copied from iwl_bg_post_associate() */
-+		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
-+			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
-+		else
-+			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
++	return sprintf(buf, "0x%08X\n", iwl_debug_level);
++}
++static ssize_t store_debug_level(struct device_driver *d,
++				 const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++	u32 val;
 +
-+		if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
-+			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
++	val = simple_strtoul(p, &p, 0);
++	if (p == buf)
++		printk(KERN_INFO DRV_NAME
++		       ": %s is not in hex or decimal form.\n", buf);
++	else
++		iwl_debug_level = val;
 +
-+		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
-+		priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
-+		priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
-+	}
++	return strnlen(buf, count);
 +}
 +
-+/*
-+ * initilize rxon structure with default values fromm eeprom
-+ */
-+static void iwl_connection_init_rx_config(struct iwl_priv *priv)
++static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
++		   show_debug_level, store_debug_level);
++
++#endif /* CONFIG_IWLWIFI_DEBUG */
++
++static ssize_t show_rf_kill(struct device *d,
++			    struct device_attribute *attr, char *buf)
 +{
-+	const struct iwl_channel_info *ch_info;
++	/*
++	 * 0 - RF kill not enabled
++	 * 1 - SW based RF kill active (sysfs)
++	 * 2 - HW based RF kill active
++	 * 3 - Both HW and SW based RF kill active
++	 */
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
++		  (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
 +
-+	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
++	return sprintf(buf, "%i\n", val);
++}
 +
-+	switch (priv->iw_mode) {
-+	case IEEE80211_IF_TYPE_AP:
-+		priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
-+		break;
++static ssize_t store_rf_kill(struct device *d,
++			     struct device_attribute *attr,
++			     const char *buf, size_t count)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 +
-+	case IEEE80211_IF_TYPE_STA:
-+		priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
-+		priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
-+		break;
++	mutex_lock(&priv->mutex);
++	iwl_radio_kill_sw(priv, buf[0] == '1');
++	mutex_unlock(&priv->mutex);
 +
-+	case IEEE80211_IF_TYPE_IBSS:
-+		priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
-+		priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
-+		priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
-+						  RXON_FILTER_ACCEPT_GRP_MSK;
-+		break;
++	return count;
++}
 +
-+	case IEEE80211_IF_TYPE_MNTR:
-+		priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
-+		priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
-+		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
-+		break;
-+	}
++static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
 +
-+#if 0
-+	/* TODO:  Figure out when short_preamble would be set and cache from
-+	 * that */
-+	if (!hw_to_local(priv->hw)->short_preamble)
-+		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-+	else
-+		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-+#endif
++static ssize_t show_temperature(struct device *d,
++				struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 +
-+	ch_info = iwl_get_channel_info(priv, priv->phymode,
-+				       le16_to_cpu(priv->staging_rxon.channel));
++	if (!iwl_is_alive(priv))
++		return -EAGAIN;
 +
-+	if (!ch_info)
-+		ch_info = &priv->channel_info[0];
++	return sprintf(buf, "%d\n", iwl_hw_get_temperature(priv));
++}
 +
-+	/*
-+	 * in some case A channels are all non IBSS
-+	 * in this case force B/G channel
-+	 */
-+	if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
-+	    !(is_channel_ibss(ch_info)))
-+		ch_info = &priv->channel_info[0];
++static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
 +
-+	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
-+	if (is_channel_a_band(ch_info))
-+		priv->phymode = MODE_IEEE80211A;
-+	else
-+		priv->phymode = MODE_IEEE80211G;
++static ssize_t show_rs_window(struct device *d,
++			      struct device_attribute *attr,
++			      char *buf)
++{
++	struct iwl_priv *priv = d->driver_data;
++	return iwl_fill_rs_info(priv->hw, buf, IWL_AP_ID);
++}
++static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
 +
-+	iwl_set_flags_for_phymode(priv, priv->phymode);
++static ssize_t show_tx_power(struct device *d,
++			     struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	return sprintf(buf, "%d\n", priv->user_txpower_limit);
++}
 +
-+	priv->staging_rxon.ofdm_basic_rates =
-+	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
-+	priv->staging_rxon.cck_basic_rates =
-+	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
++static ssize_t store_tx_power(struct device *d,
++			      struct device_attribute *attr,
++			      const char *buf, size_t count)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	char *p = (char *)buf;
++	u32 val;
 +
-+#if IWL == 4965
-+	priv->staging_rxon.flags |= RXON_FLG_CHANNEL_MODE_LEGACY_MSK;
-+	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
-+	memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN);
-+	priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff;
-+	priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff;
-+	iwl4965_set_rxon_chain(priv);
-+#endif
++	val = simple_strtoul(p, &p, 10);
++	if (p == buf)
++		printk(KERN_INFO DRV_NAME
++		       ": %s is not in decimal form.\n", buf);
++	else
++		iwl_hw_reg_set_txpower(priv, val);
++
++	return count;
 +}
 +
-+static int iwl_set_mode(struct iwl_priv *priv, int mode)
++static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
++
++static ssize_t show_flags(struct device *d,
++			  struct device_attribute *attr, char *buf)
 +{
-+	if (!iwl_is_ready_rf(priv))
-+		return -EAGAIN;
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 +
-+	if (mode == IEEE80211_IF_TYPE_IBSS) {
-+		const struct iwl_channel_info *ch_info;
++	return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
++}
 +
-+		ch_info = iwl_get_channel_info(priv,
-+			priv->phymode,
-+			le16_to_cpu(priv->staging_rxon.channel));
++static ssize_t store_flags(struct device *d,
++			   struct device_attribute *attr,
++			   const char *buf, size_t count)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	u32 flags = simple_strtoul(buf, NULL, 0);
 +
-+		if (!ch_info || !is_channel_ibss(ch_info)) {
-+			IWL_ERROR("channel %d not IBSS channel\n",
-+				  le16_to_cpu(priv->staging_rxon.channel));
-+			return -EINVAL;
++	mutex_lock(&priv->mutex);
++	if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
++		/* Cancel any currently running scans... */
++		if (iwl_scan_cancel_timeout(priv, 100))
++			IWL_WARNING("Could not cancel scan.\n");
++		else {
++			IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n",
++				       flags);
++			priv->staging_rxon.flags = cpu_to_le32(flags);
++			iwl_commit_rxon(priv);
 +		}
 +	}
++	mutex_unlock(&priv->mutex);
 +
-+	cancel_delayed_work(&priv->scan_check);
-+	if (iwl_scan_cancel_timeout(priv, 100)) {
-+		IWL_WARNING("Aborted scan still in progress after 100ms\n");
-+		IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
-+		return -EAGAIN;
-+	}
++	return count;
++}
 +
-+	priv->iw_mode = mode;
++static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
 +
-+	iwl_connection_init_rx_config(priv);
-+	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
++static ssize_t show_filter_flags(struct device *d,
++				 struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 +
-+	iwl_clear_stations_table(priv);
++	return sprintf(buf, "0x%04X\n",
++		le32_to_cpu(priv->active_rxon.filter_flags));
++}
 +
-+	iwl_commit_rxon(priv);
++static ssize_t store_filter_flags(struct device *d,
++				  struct device_attribute *attr,
++				  const char *buf, size_t count)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	u32 filter_flags = simple_strtoul(buf, NULL, 0);
 +
-+	return 0;
++	mutex_lock(&priv->mutex);
++	if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
++		/* Cancel any currently running scans... */
++		if (iwl_scan_cancel_timeout(priv, 100))
++			IWL_WARNING("Could not cancel scan.\n");
++		else {
++			IWL_DEBUG_INFO("Committing rxon.filter_flags = "
++				       "0x%04X\n", filter_flags);
++			priv->staging_rxon.filter_flags =
++				cpu_to_le32(filter_flags);
++			iwl_commit_rxon(priv);
++		}
++	}
++	mutex_unlock(&priv->mutex);
++
++	return count;
 +}
 +
-+static void iwl_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
-+				      struct ieee80211_tx_control *ctl,
-+				      struct iwl_cmd *cmd,
-+				      struct sk_buff *skb_frag,
-+				      int last_frag)
-+{
-+	struct iwl_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
++static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
++		   store_filter_flags);
 +
-+	switch (keyinfo->alg) {
-+	case ALG_CCMP:
-+		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
++static ssize_t show_tune(struct device *d,
++			 struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 +
-+		cmd->cmd.tx.hdr[0].frame_control |=
-+		    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-+		/* XXX: ACK flag must be set for CCMP even if it
-+		 * is a multicast/broadcast packet, because CCMP
-+		 * group communication encrypted by GTK is
-+		 * actually done by the AP. */
-+		cmd->cmd.tx.tx_flags |= TX_CMD_FLG_ACK_MSK;
-+		memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
-+		IWL_DEBUG_TX("tx_cmd with aes  hwcrypto\n");
-+		break;
-+	case ALG_TKIP:
-+#if 0
-+		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
++	return sprintf(buf, "0x%04X\n",
++		       (priv->phymode << 8) |
++			le16_to_cpu(priv->active_rxon.channel));
++}
 +
-+		if (last_frag)
-+			memcpy(cmd->cmd.tx.tkip_mic.byte, skb_frag->tail - 8,
-+			       8);
-+		else
-+			memset(cmd->cmd.tx.tkip_mic.byte, 0, 8);
++static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode);
 +
-+		cmd->cmd.tx.hdr[0].frame_control |=
-+		    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-+		/* XXX: ACK flag must be set for CCMP even if it
-+		 * is a multicast/broadcast packet, because CCMP
-+		 * group communication encrypted by GTK is
-+		 * actually done by the AP. */
-+		cmd->cmd.tx.tx_flags |= TX_CMD_FLG_ACK_MSK;
-+#endif
-+		break;
-+	case ALG_WEP:
-+		cmd->cmd.tx.sec_ctl = 1 |	/* WEP */
-+		    (ctl->key_idx & 0x3) << 6;
++static ssize_t store_tune(struct device *d,
++			  struct device_attribute *attr,
++			  const char *buf, size_t count)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	char *p = (char *)buf;
++	u16 tune = simple_strtoul(p, &p, 0);
++	u8 phymode = (tune >> 8) & 0xff;
++	u16 channel = tune & 0xff;
 +
-+		if (keyinfo->keylen == 13)
-+			cmd->cmd.tx.sec_ctl |= (1 << 3);	/* 128-bit */
++	IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
 +
-+		memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen);
++	mutex_lock(&priv->mutex);
++	if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
++	    (priv->phymode != phymode)) {
++		const struct iwl_channel_info *ch_info;
 +
-+		cmd->cmd.tx.hdr[0].frame_control |=
-+		    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++		ch_info = iwl_get_channel_info(priv, phymode, channel);
++		if (!ch_info) {
++			IWL_WARNING("Requested invalid phymode/channel "
++				    "combination: %d %d\n", phymode, channel);
++			mutex_unlock(&priv->mutex);
++			return -EINVAL;
++		}
 +
-+		IWL_DEBUG_TX("Configuring packet for WEP encryption "
-+			     "with key %d\n", ctl->key_idx);
-+		break;
++		/* Cancel any currently running scans... */
++		if (iwl_scan_cancel_timeout(priv, 100))
++			IWL_WARNING("Could not cancel scan.\n");
++		else {
++			IWL_DEBUG_INFO("Committing phymode and "
++				       "rxon.channel = %d %d\n",
++				       phymode, channel);
 +
-+	case ALG_NONE:
-+		IWL_DEBUG_TX("Tx packet in the clear "
-+			     "(encrypt requested).\n");
-+		break;
++			iwl_set_rxon_channel(priv, phymode, channel);
++			iwl_set_flags_for_phymode(priv, phymode);
 +
-+	default:
-+		printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
-+		break;
++			iwl_set_rate(priv);
++			iwl_commit_rxon(priv);
++		}
 +	}
++	mutex_unlock(&priv->mutex);
 +
++	return count;
 +}
 +
-+/*
-+ * handle build REPLY_TX command notification.
-+ */
-+static void iwl_build_tx_cmd_basic(struct iwl_priv *priv,
-+				  struct iwl_cmd *cmd,
-+				  struct ieee80211_tx_control *ctrl,
-+				  struct ieee80211_hdr *hdr,
-+				  int is_unicast, u8 std_id)
-+{
-+	__le16 *qc;
-+	u16 fc = le16_to_cpu(hdr->frame_control);
-+	__le32 tx_flags = cmd->cmd.tx.tx_flags;
-+
-+	cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-+	if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) {
-+		tx_flags |= TX_CMD_FLG_ACK_MSK;
-+		if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
-+			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-+		if (ieee80211_is_probe_response(fc) &&
-+		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
-+			tx_flags |= TX_CMD_FLG_TSF_MSK;
-+	} else {
-+		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
-+		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-+	}
++static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
 +
-+	cmd->cmd.tx.sta_id = std_id;
-+	if (ieee80211_get_morefrag(hdr))
-+		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
 +
-+	qc = ieee80211_get_qos_ctrl(hdr);
-+	if (qc) {
-+		cmd->cmd.tx.tid_tspec = (u8) (le16_to_cpu(*qc) & 0xf);
-+		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
-+	} else
-+		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
++static ssize_t show_measurement(struct device *d,
++				struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	struct iwl_spectrum_notification measure_report;
++	u32 size = sizeof(measure_report), len = 0, ofs = 0;
++	u8 *data = (u8 *) & measure_report;
++	unsigned long flags;
 +
-+	if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
-+		tx_flags |= TX_CMD_FLG_RTS_MSK;
-+		tx_flags &= ~TX_CMD_FLG_CTS_MSK;
-+	} else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
-+		tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-+		tx_flags |= TX_CMD_FLG_CTS_MSK;
++	spin_lock_irqsave(&priv->lock, flags);
++	if (!(priv->measurement_status & MEASUREMENT_READY)) {
++		spin_unlock_irqrestore(&priv->lock, flags);
++		return 0;
 +	}
++	memcpy(&measure_report, &priv->measure_report, size);
++	priv->measurement_status = 0;
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+	if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
-+		tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
++	while (size && (PAGE_SIZE - len)) {
++		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
++				   PAGE_SIZE - len, 1);
++		len = strlen(buf);
++		if (PAGE_SIZE - len)
++			buf[len++] = '\n';
 +
-+	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
-+	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
-+		if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ ||
-+		    (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
-+			cmd->cmd.tx.timeout.pm_frame_timeout =
-+				cpu_to_le16(3);
-+		else
-+			cmd->cmd.tx.timeout.pm_frame_timeout =
-+				cpu_to_le16(2);
-+	} else
-+		cmd->cmd.tx.timeout.pm_frame_timeout = 0;
++		ofs += 16;
++		size -= min(size, 16U);
++	}
 +
-+	cmd->cmd.tx.driver_txop = 0;
-+	cmd->cmd.tx.tx_flags = tx_flags;
-+	cmd->cmd.tx.next_frame_len = 0;
++	return len;
 +}
 +
-+static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
++static ssize_t store_measurement(struct device *d,
++				 struct device_attribute *attr,
++				 const char *buf, size_t count)
 +{
-+	int sta_id;
-+	u16 fc = le16_to_cpu(hdr->frame_control);
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	struct ieee80211_measurement_params params = {
++		.channel = le16_to_cpu(priv->active_rxon.channel),
++		.start_time = cpu_to_le64(priv->last_tsf),
++		.duration = cpu_to_le16(1),
++	};
++	u8 type = IWL_MEASURE_BASIC;
++	u8 buffer[32];
++	u8 channel;
 +
-+	/* If this frame is broadcast or not data then use the broadcast
-+	 * station id */
-+	if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
-+	    is_multicast_ether_addr(hdr->addr1))
-+		return IWL_BROADCAST_ID;
++	if (count) {
++		char *p = buffer;
++		strncpy(buffer, buf, min(sizeof(buffer), count));
++		channel = simple_strtoul(p, NULL, 0);
++		if (channel)
++			params.channel = channel;
 +
-+	switch (priv->iw_mode) {
++		p = buffer;
++		while (*p && *p != ' ')
++			p++;
++		if (*p)
++			type = simple_strtoul(p + 1, NULL, 0);
++	}
 +
-+	/* If this frame is part of a BSS network (we're a station), then
-+	 * we use the AP's station id */
-+	case IEEE80211_IF_TYPE_STA:
-+		return IWL_AP_ID;
++	IWL_DEBUG_INFO("Invoking measurement of type %d on "
++		       "channel %d (for '%s')\n", type, params.channel, buf);
++	iwl_get_measurement(priv, &params, type);
 +
-+	/* If we are an AP, then find the station, or use BCAST */
-+	case IEEE80211_IF_TYPE_AP:
-+		sta_id = iwl_hw_find_station(priv, hdr->addr1);
-+		if (sta_id != IWL_INVALID_STATION)
-+			return sta_id;
-+		return IWL_BROADCAST_ID;
++	return count;
++}
 +
-+	/* If this frame is part of a IBSS network, then we use the
-+	 * target specific station id */
-+	case IEEE80211_IF_TYPE_IBSS:
-+		sta_id = iwl_hw_find_station(priv, hdr->addr1);
-+		if (sta_id != IWL_INVALID_STATION)
-+			return sta_id;
++static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
++		   show_measurement, store_measurement);
++#endif /* CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT */
 +
-+		sta_id = iwl_add_station(priv, hdr->addr1, 0, CMD_ASYNC);
++static ssize_t show_rate(struct device *d,
++			 struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	unsigned long flags;
++	int i;
 +
-+		if (sta_id != IWL_INVALID_STATION)
-+			return sta_id;
++	spin_lock_irqsave(&priv->sta_lock, flags);
++	if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
++		i = priv->stations[IWL_AP_ID].current_rate.s.rate;
++	else
++		i = priv->stations[IWL_STA_ID].current_rate.s.rate;
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
 +
-+		IWL_DEBUG_DROP("Station " MAC_FMT " not in station map. "
-+			       "Defaulting to broadcast...\n",
-+			       MAC_ARG(hdr->addr1));
-+		iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
-+		return IWL_BROADCAST_ID;
++	i = iwl_rate_index_from_plcp(i);
++	if (i == -1)
++		return sprintf(buf, "0\n");
 +
-+	default:
-+		IWL_WARNING("Unkown mode of operation: %d", priv->iw_mode);
-+		return IWL_BROADCAST_ID;
-+	}
++	return sprintf(buf, "%d%s\n",
++		       (iwl_rates[i].ieee >> 1),
++		       (iwl_rates[i].ieee & 0x1) ? ".5" : "");
 +}
 +
-+/*
-+ * start REPLY_TX command process
-+ */
-+static int iwl_tx_skb(struct iwl_priv *priv,
-+		      struct sk_buff *skb, struct ieee80211_tx_control *ctl)
-+{
-+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+	struct iwl_tfd_frame *tfd;
-+	u32 *control_flags;
-+	int txq_id = ctl->queue;
-+	struct iwl_tx_queue *txq = NULL;
-+	struct iwl_queue *q = NULL;
-+	dma_addr_t phys_addr;
-+	dma_addr_t txcmd_phys;
-+	struct iwl_cmd *out_cmd = NULL;
-+	u16 len, idx, len_org;
-+	u8 id, hdr_len, unicast;
-+	u8 sta_id;
-+	u16 seq_number = 0;
-+	u16 fc;
-+	__le16 *qc;
-+	u8 wait_write_ptr = 0;
-+	unsigned long flags;
-+	int rc;
-+
-+	spin_lock_irqsave(&priv->lock, flags);
-+	if (iwl_is_rfkill(priv)) {
-+		IWL_DEBUG_DROP("Dropping - RF KILL\n");
-+		goto drop_unlock;
-+	}
-+
-+	if (!priv->interface_id) {
-+		IWL_DEBUG_DROP("Dropping - !priv->interface_id\n");
-+		goto drop_unlock;
-+	}
++static DEVICE_ATTR(rate, S_IRUSR, show_rate, NULL);
 +
-+	if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
-+		IWL_ERROR("ERROR: No TX rate available.\n");
-+		goto drop_unlock;
-+	}
++static ssize_t store_retry_rate(struct device *d,
++				struct device_attribute *attr,
++				const char *buf, size_t count)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
 +
-+	unicast = !is_multicast_ether_addr(hdr->addr1);
-+	id = 0;
++	priv->retry_rate = simple_strtoul(buf, NULL, 0);
++	if (priv->retry_rate <= 0)
++		priv->retry_rate = 1;
 +
-+	fc = le16_to_cpu(hdr->frame_control);
++	return count;
++}
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	if (ieee80211_is_auth(fc))
-+		IWL_DEBUG_TX("Sending AUTH frame\n");
-+	else if (ieee80211_is_assoc_request(fc))
-+		IWL_DEBUG_TX("Sending ASSOC frame\n");
-+	else if (ieee80211_is_reassoc_request(fc))
-+		IWL_DEBUG_TX("Sending REASSOC frame\n");
-+#endif
++static ssize_t show_retry_rate(struct device *d,
++			       struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	return sprintf(buf, "%d", priv->retry_rate);
++}
 +
-+	if (!iwl_is_associated(priv) &&
-+	    ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
-+		IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
-+		goto drop_unlock;
-+	}
++static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
++		   store_retry_rate);
 +
-+	spin_unlock_irqrestore(&priv->lock, flags);
++static ssize_t store_power_level(struct device *d,
++				 struct device_attribute *attr,
++				 const char *buf, size_t count)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	int rc;
++	int mode;
 +
-+	hdr_len = ieee80211_get_hdrlen(fc);
-+	sta_id = iwl_get_sta_id(priv, hdr);
-+	if (sta_id == IWL_INVALID_STATION) {
-+		IWL_DEBUG_DROP("Dropping - INVALID STATION: " MAC_FMT "\n",
-+			       MAC_ARG(hdr->addr1));
-+		goto drop;
++	mode = simple_strtoul(buf, NULL, 0);
++	mutex_lock(&priv->mutex);
++
++	if (!iwl_is_ready(priv)) {
++		rc = -EAGAIN;
++		goto out;
 +	}
 +
-+	IWL_DEBUG_RATE("station Id %d\n", sta_id);
++	if ((mode < 1) || (mode > IWL_POWER_LIMIT) || (mode == IWL_POWER_AC))
++		mode = IWL_POWER_AC;
++	else
++		mode |= IWL_POWER_ENABLED;
 +
-+	qc = ieee80211_get_qos_ctrl(hdr);
-+	if (qc) {
-+		u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
-+		seq_number = priv->stations[sta_id].tid[tid].seq_number &
-+				IEEE80211_SCTL_SEQ;
-+		hdr->seq_ctrl = cpu_to_le16(seq_number) |
-+			(hdr->seq_ctrl &
-+				__constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
-+		seq_number += 0x10;
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+#ifdef CONFIG_IWLWIFI_HT_AGG
-+		/* aggregation is on for this <sta,tid> */
-+		if (ctl->flags & IEEE80211_TXCTL_HT_MPDU_AGG)
-+			txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
-+#endif /* CONFIG_IWLWIFI_HT_AGG */
-+#endif /* CONFIG_IWLWIFI_HT */
-+#endif
++	if (mode != priv->power_mode) {
++		rc = iwl_send_power_mode(priv, IWL_POWER_LEVEL(mode));
++		if (rc) {
++			IWL_DEBUG_MAC80211("failed setting power mode.\n");
++			goto out;
++		}
++		priv->power_mode = mode;
 +	}
-+	txq = &priv->txq[txq_id];
-+	q = &txq->q;
 +
-+	spin_lock_irqsave(&priv->lock, flags);
++	rc = count;
 +
-+	tfd = &txq->bd[q->first_empty];
-+	memset(tfd, 0, sizeof(*tfd));
-+	control_flags = (u32 *) tfd;
-+	idx = get_cmd_index(q, q->first_empty, 0);
++ out:
++	mutex_unlock(&priv->mutex);
++	return rc;
++}
 +
-+	memset(&(txq->txb[q->first_empty]), 0, sizeof(struct iwl_tx_info));
-+	txq->txb[q->first_empty].skb[0] = skb;
-+	memcpy(&(txq->txb[q->first_empty].status.control),
-+	       ctl, sizeof(struct ieee80211_tx_control));
-+	out_cmd = &txq->cmd[idx];
-+	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
-+	memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx));
-+	out_cmd->hdr.cmd = REPLY_TX;
-+	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
-+				INDEX_TO_SEQ(q->first_empty)));
-+	/* copy frags header */
-+	memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len);
++#define MAX_WX_STRING 80
 +
-+	/* hdr = (struct ieee80211_hdr *)out_cmd->cmd.tx.hdr; */
-+	len = priv->hw_setting.tx_cmd_len +
-+		sizeof(struct iwl_cmd_header) + hdr_len;
++/* Values are in microsecond */
++static const s32 timeout_duration[] = {
++	350000,
++	250000,
++	75000,
++	37000,
++	25000,
++};
++static const s32 period_duration[] = {
++	400000,
++	700000,
++	1000000,
++	1000000,
++	1000000
++};
 +
-+	len_org = len;
-+	len = (len + 3) & ~3;
++static ssize_t show_power_level(struct device *d,
++				struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	int level = IWL_POWER_LEVEL(priv->power_mode);
++	char *p = buf;
 +
-+	if (len_org != len)
-+		len_org = 1;
++	p += sprintf(p, "%d ", level);
++	switch (level) {
++	case IWL_POWER_MODE_CAM:
++	case IWL_POWER_AC:
++		p += sprintf(p, "(AC)");
++		break;
++	case IWL_POWER_BATTERY:
++		p += sprintf(p, "(BATTERY)");
++		break;
++	default:
++		p += sprintf(p,
++			     "(Timeout %dms, Period %dms)",
++			     timeout_duration[level - 1] / 1000,
++			     period_duration[level - 1] / 1000);
++	}
++
++	if (!(priv->power_mode & IWL_POWER_ENABLED))
++		p += sprintf(p, " OFF\n");
 +	else
-+		len_org = 0;
++		p += sprintf(p, " \n");
 +
-+	txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
-+		     offsetof(struct iwl_cmd, hdr);
++	return (p - buf + 1);
 +
-+	iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
++}
 +
-+	if (ctl->key_idx != -1)
-+		iwl_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
++static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
++		   store_power_level);
 +
-+	/* 802.11 null functions have no payload... */
-+	len = skb->len - hdr_len;
-+	if (len) {
-+		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
-+					   len, PCI_DMA_TODEVICE);
-+		iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
-+	}
++static ssize_t show_channels(struct device *d,
++			     struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	int len = 0, i;
++	struct ieee80211_channel *channels = NULL;
++	const struct ieee80211_hw_mode *hw_mode = NULL;
++	int count = 0;
 +
-+#if IWL == 3945
-+	/* If there is no payload, then only one TFD is used */
-+	if (!len)
-+		*control_flags = TFD_CTL_COUNT_SET(1);
-+	else
-+		*control_flags = TFD_CTL_COUNT_SET(2) |
-+			TFD_CTL_PAD_SET(U32_PAD(len));
-+#else
-+	if (len_org)
-+		out_cmd->cmd.tx.tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
-+#endif
-+	len = (u16)skb->len;
-+	out_cmd->cmd.tx.len = cpu_to_le16(len);
++	if (!iwl_is_ready(priv))
++		return -EAGAIN;
 +
-+	/* TODO need this for burst mode later on */
-+	iwl_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
++	hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211G);
++	if (!hw_mode)
++		hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211B);
++	if (hw_mode) {
++		channels = hw_mode->channels;
++		count = hw_mode->num_channels;
++	}
 +
-+	/* set is_hcca to 0; it probably will never be implemented */
-+	iwl_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
++	len +=
++	    sprintf(&buf[len],
++		    "Displaying %d channels in 2.4GHz band "
++		    "(802.11bg):\n", count);
 +
-+#if IWL == 4965
-+	iwl4965_tx_cmd(priv, out_cmd, sta_id, txcmd_phys,
-+		       hdr, hdr_len, ctl, NULL);
-+#elif IWL == 3945
-+	out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
-+	out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
-+#endif
++	for (i = 0; i < count; i++)
++		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
++			       channels[i].chan,
++			       channels[i].power_level,
++			       channels[i].
++			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
++			       " (IEEE 802.11h required)" : "",
++			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
++				|| (channels[i].
++				    flag &
++				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
++			       ", IBSS",
++			       channels[i].
++			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
++			       "active/passive" : "passive only");
 +
-+	if (!ieee80211_get_morefrag(hdr)) {
-+		txq->need_update = 1;
-+		if (qc) {
-+			u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
-+			priv->stations[sta_id].tid[tid].seq_number = seq_number;
-+		}
++	hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211A);
++	if (hw_mode) {
++		channels = hw_mode->channels;
++		count = hw_mode->num_channels;
 +	} else {
-+		wait_write_ptr = 1;
-+		txq->need_update = 0;
++		channels = NULL;
++		count = 0;
 +	}
 +
-+	iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
-+			   sizeof(out_cmd->cmd.tx));
++	len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
++		       "(802.11a):\n", count);
 +
-+	iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
-+			   ieee80211_get_hdrlen(fc));
++	for (i = 0; i < count; i++)
++		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
++			       channels[i].chan,
++			       channels[i].power_level,
++			       channels[i].
++			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
++			       " (IEEE 802.11h required)" : "",
++			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
++				|| (channels[i].
++				    flag &
++				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
++			       ", IBSS",
++			       channels[i].
++			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
++			       "active/passive" : "passive only");
 +
-+	iwl4965_tx_queue_update_wr_ptr(priv, txq, len);
++	return len;
++}
 +
-+	q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
-+	rc = iwl_tx_queue_update_write_ptr(priv, txq);
-+	spin_unlock_irqrestore(&priv->lock, flags);
++static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
 +
-+	if (rc)
-+		return rc;
++static ssize_t show_statistics(struct device *d,
++			       struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	u32 size = sizeof(struct iwl_notif_statistics);
++	u32 len = 0, ofs = 0;
++	u8 *data = (u8 *) & priv->statistics;
++	int rc = 0;
++
++	if (!iwl_is_alive(priv))
++		return -EAGAIN;
 +
-+	if ((iwl_queue_space(q) < q->high_mark)
-+	    && priv->mac80211_registered) {
-+		if (wait_write_ptr) {
-+			spin_lock_irqsave(&priv->lock, flags);
-+			txq->need_update = 1;
-+			iwl_tx_queue_update_write_ptr(priv, txq);
-+			spin_unlock_irqrestore(&priv->lock, flags);
-+		}
++	mutex_lock(&priv->mutex);
++	rc = iwl_send_statistics_request(priv);
++	mutex_unlock(&priv->mutex);
 +
-+		ieee80211_stop_queue(priv->hw, ctl->queue);
++	if (rc) {
++		len = sprintf(buf,
++			      "Error sending statistics request: 0x%08X\n", rc);
++		return len;
 +	}
 +
-+	return 0;
++	while (size && (PAGE_SIZE - len)) {
++		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
++				   PAGE_SIZE - len, 1);
++		len = strlen(buf);
++		if (PAGE_SIZE - len)
++			buf[len++] = '\n';
 +
-+drop_unlock:
-+	spin_unlock_irqrestore(&priv->lock, flags);
-+drop:
-+	return -1;
++		ofs += 16;
++		size -= min(size, 16U);
++	}
++
++	return len;
 +}
 +
-+static void iwl_set_rate(struct iwl_priv *priv)
++static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
++
++static ssize_t show_antenna(struct device *d,
++			    struct device_attribute *attr, char *buf)
 +{
-+	const struct ieee80211_hw_mode *hw = NULL;
-+	struct ieee80211_rate *rate;
-+	int i;
++	struct iwl_priv *priv = dev_get_drvdata(d);
 +
-+	hw = iwl_get_hw_mode(priv, priv->phymode);
++	if (!iwl_is_alive(priv))
++		return -EAGAIN;
 +
-+	priv->active_rate = 0;
-+	priv->active_rate_basic = 0;
++	return sprintf(buf, "%d\n", priv->antenna);
++}
 +
-+	IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
-+		       hw->mode == MODE_IEEE80211A ?
-+		       'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
++static ssize_t store_antenna(struct device *d,
++			     struct device_attribute *attr,
++			     const char *buf, size_t count)
++{
++	int ant;
++	struct iwl_priv *priv = dev_get_drvdata(d);
 +
-+	for (i = 0; i < hw->num_rates; i++) {
-+		rate = &(hw->rates[i]);
-+		if ((rate->val < IWL_RATE_COUNT) &&
-+		    (rate->flags & IEEE80211_RATE_SUPPORTED)) {
-+			IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
-+				       rate->val, iwl_rates[rate->val].plcp,
-+				       (rate->flags & IEEE80211_RATE_BASIC) ?
-+				       "*" : "");
-+			priv->active_rate |= (1 << rate->val);
-+			if (rate->flags & IEEE80211_RATE_BASIC)
-+				priv->active_rate_basic |= (1 << rate->val);
-+		} else
-+			IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
-+				       rate->val, iwl_rates[rate->val].plcp);
++	if (count == 0)
++		return 0;
++
++	if (sscanf(buf, "%1i", &ant) != 1) {
++		IWL_DEBUG_INFO("not in hex or decimal form.\n");
++		return count;
 +	}
 +
-+	IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
-+		       priv->active_rate, priv->active_rate_basic);
++	if ((ant >= 0) && (ant <= 2)) {
++		IWL_DEBUG_INFO("Setting antenna select to %d.\n", ant);
++		priv->antenna = (enum iwl_antenna)ant;
++	} else
++		IWL_DEBUG_INFO("Bad antenna select value %d.\n", ant);
 +
-+	/*
-+	 * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK)
-+	 * otherwise set it to the default of all CCK rates and 6, 12, 24 for
-+	 * OFDM
-+	 */
-+	if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK)
-+		priv->staging_rxon.cck_basic_rates =
-+		    ((priv->active_rate_basic &
-+		      IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF;
-+	else
-+		priv->staging_rxon.cck_basic_rates =
-+		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
 +
-+	if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK)
-+		priv->staging_rxon.ofdm_basic_rates =
-+		    ((priv->active_rate_basic &
-+		      (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >>
-+		      IWL_FIRST_OFDM_RATE) & 0xFF;
-+	else
-+		priv->staging_rxon.ofdm_basic_rates =
-+		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
++	return count;
 +}
 +
-+static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
-+{
-+	unsigned long flags;
++static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
 +
-+	if (disable_radio ? 1 : 0 ==
-+	    test_bit(STATUS_RF_KILL_SW, &priv->status) ? 1 : 0)
-+		return;
++static ssize_t show_status(struct device *d,
++			   struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	if (!iwl_is_alive(priv))
++		return -EAGAIN;
++	return sprintf(buf, "0x%08x\n", (int)priv->status);
++}
 +
-+	IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO %s\n",
-+			  disable_radio ? "OFF" : "ON");
++static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
 +
-+	if (disable_radio) {
-+		iwl_scan_cancel(priv);
-+		/* FIXME: This is a workaround for AP */
-+		if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
-+			spin_lock_irqsave(&priv->lock, flags);
-+			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-+				    CSR_UCODE_SW_BIT_RFKILL);
-+			spin_unlock_irqrestore(&priv->lock, flags);
-+			iwl_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
-+			set_bit(STATUS_RF_KILL_SW, &priv->status);
-+		}
-+		return;
-+	}
++static ssize_t dump_error_log(struct device *d,
++			      struct device_attribute *attr,
++			      const char *buf, size_t count)
++{
++	char *p = (char *)buf;
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	if (p[0] == '1')
++		iwl_dump_nic_error_log((struct iwl_priv *)d->driver_data);
 +
-+	clear_bit(STATUS_RF_KILL_SW, &priv->status);
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	return strnlen(buf, count);
++}
 +
-+	/* wake up ucode */
-+	msleep(10);
++static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	iwl_read32(priv, CSR_UCODE_DRV_GP1);
-+	if (!iwl_grab_restricted_access(priv))
-+		iwl_release_restricted_access(priv);
-+	spin_unlock_irqrestore(&priv->lock, flags);
++static ssize_t dump_event_log(struct device *d,
++			      struct device_attribute *attr,
++			      const char *buf, size_t count)
++{
++	char *p = (char *)buf;
 +
-+	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-+		IWL_DEBUG_RF_KILL("Can not turn radio back on - "
-+				  "disabled by HW switch\n");
-+		return;
-+	}
++	if (p[0] == '1')
++		iwl_dump_nic_event_log((struct iwl_priv *)d->driver_data);
 +
-+	queue_work(priv->workqueue, &priv->restart);
-+	return;
++	return strnlen(buf, count);
 +}
 +
-+void iwl_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
-+			    u32 decrypt_res, struct ieee80211_rx_status *stats)
++static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
++
++/*****************************************************************************
++ *
++ * driver setup and teardown
++ *
++ *****************************************************************************/
++
++static void iwl_setup_deferred_work(struct iwl_priv *priv)
 +{
-+	u16 fc =
-+	    le16_to_cpu(((struct ieee80211_hdr *)skb->data)->frame_control);
++	priv->workqueue = create_workqueue(DRV_NAME);
 +
-+	if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
-+		return;
++	init_waitqueue_head(&priv->wait_command_queue);
 +
-+	if (!(fc & IEEE80211_FCTL_PROTECTED))
-+		return;
++	INIT_WORK(&priv->up, iwl_bg_up);
++	INIT_WORK(&priv->restart, iwl_bg_restart);
++	INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
++	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
++	INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
++	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
++	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
++	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
++	INIT_DELAYED_WORK(&priv->post_associate, iwl_bg_post_associate);
++	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
++	INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
++	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
 +
-+	IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res);
-+	switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
-+	case RX_RES_STATUS_SEC_TYPE_TKIP:
-+		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
-+		    RX_RES_STATUS_BAD_ICV_MIC)
-+			stats->flag |= RX_FLAG_MMIC_ERROR;
-+	case RX_RES_STATUS_SEC_TYPE_WEP:
-+	case RX_RES_STATUS_SEC_TYPE_CCMP:
-+		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
-+		    RX_RES_STATUS_DECRYPT_OK) {
-+			IWL_DEBUG_RX("hw decrypt successfully!!!\n");
-+			stats->flag |= RX_FLAG_DECRYPTED;
-+		}
-+		break;
++	iwl_hw_setup_deferred_work(priv);
 +
-+	default:
-+		break;
-+	}
++	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
++		     iwl_irq_tasklet, (unsigned long)priv);
 +}
 +
-+void iwl_handle_data_packet_monitor(struct iwl_priv *priv,
-+				    struct iwl_rx_mem_buffer *rxb,
-+				    void *data, short len,
-+				    struct ieee80211_rx_status *stats,
-+				    u16 phy_flags)
++static void iwl_cancel_deferred_work(struct iwl_priv *priv)
 +{
-+	struct iwl_rt_rx_hdr *iwl_rt;
-+
-+	/* First cache any information we need before we overwrite
-+	 * the information provided in the skb from the hardware */
-+	s8 signal = stats->ssi;
-+	s8 noise = 0;
-+	int rate = stats->rate;
-+	u64 tsf = stats->mactime;
-+	__le16 phy_flags_hw = cpu_to_le16(phy_flags);
-+
-+	/* We received data from the HW, so stop the watchdog */
-+	if (len > IWL_RX_BUF_SIZE - sizeof(*iwl_rt)) {
-+		IWL_DEBUG_DROP("Dropping too large packet in monitor\n");
-+		return;
-+	}
++	iwl_hw_cancel_deferred_work(priv);
 +
-+	/* copy the frame data to write after where the radiotap header goes */
-+	iwl_rt = (void *)rxb->skb->data;
-+	memmove(iwl_rt->payload, data, len);
++	cancel_delayed_work(&priv->scan_check);
++	cancel_delayed_work(&priv->alive_start);
++	cancel_delayed_work(&priv->post_associate);
++	cancel_work_sync(&priv->beacon_update);
++}
 +
-+	iwl_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
-+	iwl_rt->rt_hdr.it_pad = 0; /* always good to zero */
++static struct attribute *iwl_sysfs_entries[] = {
++	&dev_attr_antenna.attr,
++	&dev_attr_channels.attr,
++	&dev_attr_dump_errors.attr,
++	&dev_attr_dump_events.attr,
++	&dev_attr_flags.attr,
++	&dev_attr_filter_flags.attr,
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++	&dev_attr_measurement.attr,
++#endif
++	&dev_attr_power_level.attr,
++	&dev_attr_rate.attr,
++	&dev_attr_retry_rate.attr,
++	&dev_attr_rf_kill.attr,
++	&dev_attr_rs_window.attr,
++	&dev_attr_statistics.attr,
++	&dev_attr_status.attr,
++	&dev_attr_temperature.attr,
++	&dev_attr_tune.attr,
++	&dev_attr_tx_power.attr,
 +
-+	/* total header + data */
-+	iwl_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*iwl_rt));
++	NULL
++};
 +
-+	/* Set the size of the skb to the size of the frame */
-+	skb_put(rxb->skb, sizeof(*iwl_rt) + len);
++static struct attribute_group iwl_attribute_group = {
++	.name = NULL,		/* put in device directory */
++	.attrs = iwl_sysfs_entries,
++};
 +
-+	/* Big bitfield of all the fields we provide in radiotap */
-+	iwl_rt->rt_hdr.it_present =
-+	    cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
-+			(1 << IEEE80211_RADIOTAP_FLAGS) |
-+			(1 << IEEE80211_RADIOTAP_RATE) |
-+			(1 << IEEE80211_RADIOTAP_CHANNEL) |
-+			(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
-+			(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
-+			(1 << IEEE80211_RADIOTAP_ANTENNA));
++static struct ieee80211_ops iwl_hw_ops = {
++	.tx = iwl_mac_tx,
++	.open = iwl_mac_open,
++	.stop = iwl_mac_stop,
++	.add_interface = iwl_mac_add_interface,
++	.remove_interface = iwl_mac_remove_interface,
++	.config = iwl_mac_config,
++	.config_interface = iwl_mac_config_interface,
++	.set_key = iwl_mac_set_key,
++	.get_stats = iwl_mac_get_stats,
++	.get_tx_stats = iwl_mac_get_tx_stats,
++	.conf_tx = iwl_mac_conf_tx,
++	.get_tsf = iwl_mac_get_tsf,
++	.reset_tsf = iwl_mac_reset_tsf,
++	.beacon_update = iwl_mac_beacon_update,
++	.hw_scan = iwl_mac_hw_scan
++};
 +
-+	/* Zero the flags, we'll add to them as we go */
-+	iwl_rt->rt_flags = 0;
++static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
++{
++	int err = 0;
++	u32 pci_id;
++	struct iwl_priv *priv;
++	struct ieee80211_hw *hw;
++	int i;
 +
-+	iwl_rt->rt_tsf = cpu_to_le64(tsf);
++	if (iwl_param_disable_hw_scan) {
++		IWL_DEBUG_INFO("Disabling hw_scan\n");
++		iwl_hw_ops.hw_scan = NULL;
++	}
 +
-+	/* Convert to dBm */
-+	iwl_rt->rt_dbmsignal = signal;
-+	iwl_rt->rt_dbmnoise = noise;
++	if ((iwl_param_queues_num > IWL_MAX_NUM_QUEUES) ||
++	    (iwl_param_queues_num < IWL_MIN_NUM_QUEUES)) {
++		IWL_ERROR("invalid queues_num, should be between %d and %d\n",
++			  IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
++		err = -EINVAL;
++		goto out;
++	}
 +
-+	/* Convert the channel frequency and set the flags */
-+	iwl_rt->rt_channelMHz = cpu_to_le16(stats->freq);
-+	if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
-+		iwl_rt->rt_chbitmask =
-+		    cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
-+	else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
-+		iwl_rt->rt_chbitmask =
-+		    cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
-+	else	/* 802.11g */
-+		iwl_rt->rt_chbitmask =
-+		    cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ));
++	/* mac80211 allocates memory for this device instance, including
++	 *   space for this driver's private structure */
++	hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl_hw_ops);
++	if (hw == NULL) {
++		IWL_ERROR("Can not allocate network device\n");
++		err = -ENOMEM;
++		goto out;
++	}
++	SET_IEEE80211_DEV(hw, &pdev->dev);
 +
-+	rate = iwl_rate_index_from_plcp(rate);
-+	if (rate == -1)
-+		iwl_rt->rt_rate = 0;
-+	else
-+		iwl_rt->rt_rate = iwl_rates[rate].ieee;
++	IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
++	priv = hw->priv;
++	priv->hw = hw;
 +
-+	/* antenna number */
-+	iwl_rt->rt_antenna =
-+		le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
++	priv->pci_dev = pdev;
++	priv->antenna = (enum iwl_antenna)iwl_param_antenna;
++#ifdef CONFIG_IWLWIFI_DEBUG
++	iwl_debug_level = iwl_param_debug;
++	atomic_set(&priv->restrict_refcnt, 0);
++#endif
++	priv->retry_rate = 1;
 +
-+	/* set the preamble flag if we have it */
-+	if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-+		iwl_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
++	priv->ibss_beacon = NULL;
 +
-+	IWL_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
++	/* Tell mac80211 and its clients (e.g. Wireless Extensions)
++	 *   the range of signal quality values that we'll provide.
++	 * Negative values for level/noise indicate that we'll provide dBm.
++	 * For WE, at least, non-0 values here *enable* display of values
++	 *   in app (iwconfig). */
++	hw->max_rssi = -20;	/* signal level, negative indicates dBm */
++	hw->max_noise = -20;	/* noise level, negative indicates dBm */
++	hw->max_signal = 100;	/* link quality indication (%) */
 +
-+	stats->flag |= RX_FLAG_RADIOTAP;
-+	ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
-+	rxb->skb = NULL;
-+}
++	/* Tell mac80211 our Tx characteristics */
++	hw->flags = IEEE80211_HW_WEP_INCLUDE_IV |
++	    IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
 +
++	hw->queues = 4;
 +
-+#define IWL_PACKET_RETRY_TIME HZ
++	spin_lock_init(&priv->lock);
++	spin_lock_init(&priv->power_data.lock);
++	spin_lock_init(&priv->sta_lock);
++	spin_lock_init(&priv->hcmd_lock);
 +
-+int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
-+{
-+	u16 sc = le16_to_cpu(header->seq_ctrl);
-+	u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
-+	u16 frag = sc & IEEE80211_SCTL_FRAG;
-+	u16 *last_seq, *last_frag;
-+	unsigned long *last_time;
++	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
++		INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
 +
-+	switch (priv->iw_mode) {
-+	case IEEE80211_IF_TYPE_IBSS:{
-+		struct list_head *p;
-+		struct iwl_ibss_seq *entry = NULL;
-+		u8 *mac = header->addr2;
-+		int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
++	INIT_LIST_HEAD(&priv->free_frames);
 +
-+		__list_for_each(p, &priv->ibss_mac_hash[index]) {
-+			entry =
-+				list_entry(p, struct iwl_ibss_seq, list);
-+			if (!compare_ether_addr(entry->mac, mac))
-+				break;
-+		}
-+		if (p == &priv->ibss_mac_hash[index]) {
-+			entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
-+			if (!entry) {
-+				IWL_ERROR
-+					("Cannot malloc new mac entry\n");
-+				return 0;
-+			}
-+			memcpy(entry->mac, mac, ETH_ALEN);
-+			entry->seq_num = seq;
-+			entry->frag_num = frag;
-+			entry->packet_time = jiffies;
-+			list_add(&entry->list,
-+				 &priv->ibss_mac_hash[index]);
-+			return 0;
-+		}
-+		last_seq = &entry->seq_num;
-+		last_frag = &entry->frag_num;
-+		last_time = &entry->packet_time;
-+		break;
-+	}
-+	case IEEE80211_IF_TYPE_STA:
-+		last_seq = &priv->last_seq_num;
-+		last_frag = &priv->last_frag_num;
-+		last_time = &priv->last_packet_time;
-+		break;
-+	default:
-+		return 0;
++	mutex_init(&priv->mutex);
++	if (pci_enable_device(pdev)) {
++		err = -ENODEV;
++		goto out_ieee80211_free_hw;
 +	}
-+	if ((*last_seq == seq) &&
-+	    time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
-+		if (*last_frag == frag)
-+			goto drop;
-+		if (*last_frag + 1 != frag)
-+			/* out-of-order fragment */
-+			goto drop;
-+	} else
-+		*last_seq = seq;
-+
-+	*last_frag = frag;
-+	*last_time = jiffies;
-+	return 0;
 +
-+ drop:
-+	return 1;
-+}
++	pci_set_master(pdev);
 +
-+#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++	iwl_clear_stations_table(priv);
 +
-+#include "iwl-spectrum.h"
++	priv->data_retry_limit = -1;
++	priv->ieee_channels = NULL;
++	priv->ieee_rates = NULL;
++	priv->phymode = -1;
 +
-+#define BEACON_TIME_MASK_LOW	0x00FFFFFF
-+#define BEACON_TIME_MASK_HIGH	0xFF000000
-+#define TIME_UNIT		1024
++	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
++	if (!err)
++		err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
++	if (err) {
++		printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n");
++		goto out_pci_disable_device;
++	}
 +
-+/*
-+ * extended beacon time format
-+ * time in usec will be changed into a 32-bit value in 8:24 format
-+ * the high 1 byte is the beacon counts
-+ * the lower 3 bytes is the time in usec within one beacon interval
-+ */
++	pci_set_drvdata(pdev, priv);
++	err = pci_request_regions(pdev, DRV_NAME);
++	if (err)
++		goto out_pci_disable_device;
++	/* We disable the RETRY_TIMEOUT register (0x41) to keep
++	 * PCI Tx retries from interfering with C3 CPU state */
++	pci_write_config_byte(pdev, 0x41, 0x00);
++	priv->hw_base = pci_iomap(pdev, 0, 0);
++	if (!priv->hw_base) {
++		err = -ENODEV;
++		goto out_pci_release_regions;
++	}
 +
-+static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
-+{
-+	u32 quot;
-+	u32 rem;
-+	u32 interval = beacon_interval * 1024;
++	IWL_DEBUG_INFO("pci_resource_len = 0x%08llx\n",
++			(unsigned long long) pci_resource_len(pdev, 0));
++	IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
 +
-+	if (!interval || !usec)
-+		return 0;
++	/* Initialize module parameter values here */
 +
-+	quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
-+	rem = (usec % interval) & BEACON_TIME_MASK_LOW;
++	if (iwl_param_disable) {
++		set_bit(STATUS_RF_KILL_SW, &priv->status);
++		IWL_DEBUG_INFO("Radio disabled.\n");
++	}
 +
-+	return (quot << 24) + rem;
-+}
++	priv->iw_mode = IEEE80211_IF_TYPE_STA;
 +
-+/* base is usually what we get from ucode with each received frame,
-+ * the same as HW timer counter counting down
-+ */
++	pci_id =
++	    (priv->pci_dev->device << 16) | priv->pci_dev->subsystem_device;
 +
-+static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
-+{
-+	u32 base_low = base & BEACON_TIME_MASK_LOW;
-+	u32 addon_low = addon & BEACON_TIME_MASK_LOW;
-+	u32 interval = beacon_interval * TIME_UNIT;
-+	u32 res = (base & BEACON_TIME_MASK_HIGH) +
-+	    (addon & BEACON_TIME_MASK_HIGH);
++	switch (pci_id) {
++	case 0x42221005:	/* 0x4222 0x8086 0x1005 is BG SKU */
++	case 0x42221034:	/* 0x4222 0x8086 0x1034 is BG SKU */
++	case 0x42271014:	/* 0x4227 0x8086 0x1014 is BG SKU */
++	case 0x42221044:	/* 0x4222 0x8086 0x1044 is BG SKU */
++		priv->is_abg = 0;
++		break;
 +
-+	if (base_low > addon_low)
-+		res += base_low - addon_low;
-+	else if (base_low < addon_low) {
-+		res += interval + base_low - addon_low;
-+		res += (1 << 24);
-+	} else
-+		res += (1 << 24);
++	/*
++	 * Rest are assumed ABG SKU -- if this is not the
++	 * case then the card will get the wrong 'Detected'
++	 * line in the kernel log however the code that
++	 * initializes the GEO table will detect no A-band
++	 * channels and remove the is_abg mask.
++	 */
++	default:
++		priv->is_abg = 1;
++		break;
++	}
 +
-+	return cpu_to_le32(res);
-+}
++	printk(KERN_INFO DRV_NAME
++	       ": Detected Intel PRO/Wireless 3945%sBG Network Connection\n",
++	       priv->is_abg ? "A" : "");
 +
-+static int iwl_get_measurement(struct iwl_priv *priv,
-+			       struct ieee80211_measurement_params *params,
-+			       u8 type)
-+{
-+	struct iwl_spectrum_cmd spectrum;
-+	struct iwl_rx_packet *res;
-+	struct iwl_host_cmd cmd = {
-+		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
-+		.data = (void *)&spectrum,
-+		.meta.flags = CMD_WANT_SKB,
-+	};
-+	u32 add_time = le64_to_cpu(params->start_time);
-+	int rc;
-+	int spectrum_resp_status;
-+	int duration = le16_to_cpu(params->duration);
++	/* Device-specific setup */
++	if (iwl_hw_set_hw_setting(priv)) {
++		IWL_ERROR("failed to set hw settings\n");
++		mutex_unlock(&priv->mutex);
++		goto out_iounmap;
++	}
 +
-+	if (iwl_is_associated(priv))
-+		add_time =
-+		    iwl_usecs_to_beacons(
-+			le64_to_cpu(params->start_time) - priv->last_tsf,
-+			le16_to_cpu(priv->rxon_timing.beacon_interval));
++#ifdef CONFIG_IWLWIFI_QOS
++	if (iwl_param_qos_enable)
++		priv->qos_data.qos_enable = 1;
 +
-+	memset(&spectrum, 0, sizeof(spectrum));
++	iwl_reset_qos(priv);
 +
-+	spectrum.channel_count = cpu_to_le16(1);
-+	spectrum.flags =
-+	    RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
-+	spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
-+	cmd.len = sizeof(spectrum);
-+	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
++	priv->qos_data.qos_active = 0;
++	priv->qos_data.qos_cap.val = 0;
++#endif /* CONFIG_IWLWIFI_QOS */
 +
-+	if (iwl_is_associated(priv))
-+		spectrum.start_time =
-+		    iwl_add_beacon_time(priv->last_beacon_time,
-+				add_time,
-+				le16_to_cpu(priv->rxon_timing.beacon_interval));
-+	else
-+		spectrum.start_time = 0;
++	iwl_set_rxon_channel(priv, MODE_IEEE80211G, 6);
++	iwl_setup_deferred_work(priv);
++	iwl_setup_rx_handlers(priv);
 +
-+	spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
-+	spectrum.channels[0].channel = params->channel;
-+	spectrum.channels[0].type = type;
-+	if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
-+		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
-+		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
++	priv->rates_mask = IWL_RATES_MASK;
++	/* If power management is turned on, default to AC mode */
++	priv->power_mode = IWL_POWER_AC;
++	priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
 +
-+	rc = iwl_send_cmd_sync(priv, &cmd);
-+	if (rc)
-+		return rc;
++	pci_enable_msi(pdev);
 +
-+	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
-+	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-+		IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n");
-+		rc = -EIO;
++	err = request_irq(pdev->irq, iwl_isr, IRQF_SHARED, DRV_NAME, priv);
++	if (err) {
++		IWL_ERROR("Error allocating IRQ %d\n", pdev->irq);
++		goto out_disable_msi;
 +	}
 +
-+	spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
-+	switch (spectrum_resp_status) {
-+	case 0:		/* Command will be handled */
-+		if (res->u.spectrum.id != 0xff) {
-+			IWL_DEBUG_INFO
-+			    ("Replaced existing measurement: %d\n",
-+			     res->u.spectrum.id);
-+			priv->measurement_status &= ~MEASUREMENT_READY;
-+		}
-+		priv->measurement_status |= MEASUREMENT_ACTIVE;
-+		rc = 0;
-+		break;
++	mutex_lock(&priv->mutex);
 +
-+	case 1:		/* Command will not be handled */
-+		rc = -EAGAIN;
-+		break;
++	err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
++	if (err) {
++		IWL_ERROR("failed to create sysfs device attributes\n");
++		mutex_unlock(&priv->mutex);
++		goto out_release_irq;
 +	}
 +
-+	dev_kfree_skb_any(cmd.meta.u.skb);
-+
-+	return rc;
-+}
-+#endif
-+
-+static void iwl_txstatus_to_ieee(struct iwl_priv *priv,
-+				 struct iwl_tx_info *tx_sta)
-+{
++	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
++	 * ucode filename and max sizes are card-specific. */
++	err = iwl_read_ucode(priv);
++	if (err) {
++		IWL_ERROR("Could not read microcode: %d\n", err);
++		mutex_unlock(&priv->mutex);
++		goto out_pci_alloc;
++	}
 +
-+	tx_sta->status.ack_signal = 0;
-+	tx_sta->status.excessive_retries = 0;
-+	tx_sta->status.queue_length = 0;
-+	tx_sta->status.queue_number = 0;
++	mutex_unlock(&priv->mutex);
 +
-+	if (in_interrupt())
-+		ieee80211_tx_status_irqsafe(priv->hw,
-+					    tx_sta->skb[0], &(tx_sta->status));
-+	else
-+		ieee80211_tx_status(priv->hw,
-+				    tx_sta->skb[0], &(tx_sta->status));
++	IWL_DEBUG_INFO("Queing UP work.\n");
 +
-+	tx_sta->skb[0] = NULL;
-+}
++	queue_work(priv->workqueue, &priv->up);
 +
-+/**
-+ * iwl_tx_queue_reclaim - Reclaim Tx queue entries no more used by NIC.
-+ *
-+ * When FW advances 'R' index, all entries between old and
-+ * new 'R' index need to be reclaimed. As result, some free space
-+ * forms. If there is enough free space (> low mark), wake Tx queue.
-+ */
-+int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
-+{
-+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-+	struct iwl_queue *q = &txq->q;
-+	int nfreed = 0;
++	return 0;
 +
-+	if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) {
-+		IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
-+			  "is out of range [0-%d] %d %d.\n", txq_id,
-+			  index, q->n_bd, q->first_empty, q->last_used);
-+		return 0;
-+	}
++ out_pci_alloc:
++	iwl_dealloc_ucode_pci(priv);
 +
-+	for (index = iwl_queue_inc_wrap(index, q->n_bd);
-+		q->last_used != index;
-+		q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd)) {
-+		if (txq_id != IWL_CMD_QUEUE_NUM) {
-+			iwl_txstatus_to_ieee(priv,
-+					&(txq->txb[txq->q.last_used]));
-+			iwl_hw_txq_free_tfd(priv, txq);
-+		} else if (nfreed > 1) {
-+			IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
-+					q->first_empty, q->last_used);
-+			queue_work(priv->workqueue, &priv->restart);
-+		}
-+		nfreed++;
-+	}
++	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
 +
-+	if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
-+			(txq_id != IWL_CMD_QUEUE_NUM) &&
-+			priv->mac80211_registered)
-+		ieee80211_wake_queue(priv->hw, txq_id);
++ out_release_irq:
++	free_irq(pdev->irq, priv);
 +
++ out_disable_msi:
++	pci_disable_msi(pdev);
++	destroy_workqueue(priv->workqueue);
++	priv->workqueue = NULL;
++	iwl_unset_hw_setting(priv);
 +
-+	return nfreed;
++ out_iounmap:
++	pci_iounmap(pdev, priv->hw_base);
++ out_pci_release_regions:
++	pci_release_regions(pdev);
++ out_pci_disable_device:
++	pci_disable_device(pdev);
++	pci_set_drvdata(pdev, NULL);
++ out_ieee80211_free_hw:
++	ieee80211_free_hw(priv->hw);
++ out:
++	return err;
 +}
 +
-+static int iwl_is_tx_success(u32 status)
++static void iwl_pci_remove(struct pci_dev *pdev)
 +{
-+#if IWL == 3945
-+	return (status & 0xFF) == 0x1;
-+#elif IWL == 4965
-+	status &= TX_STATUS_MSK;
-+	return (status == TX_STATUS_SUCCESS)
-+	    || (status == TX_STATUS_DIRECT_DONE);
-+#endif
-+}
++	struct iwl_priv *priv = pci_get_drvdata(pdev);
++	struct list_head *p, *q;
++	int i;
++
++	if (!priv)
++		return;
++
++	IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n");
 +
-+/******************************************************************************
-+ *
-+ * Generic RX handler implementations
-+ *
-+ ******************************************************************************/
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+#ifdef CONFIG_IWLWIFI_HT_AGG
++	mutex_lock(&priv->mutex);
++	set_bit(STATUS_EXIT_PENDING, &priv->status);
++	__iwl_down(priv);
++	mutex_unlock(&priv->mutex);
 +
-+static inline int iwl_get_ra_sta_id(struct iwl_priv *priv,
-+				    struct ieee80211_hdr *hdr)
-+{
-+	if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
-+		return IWL_AP_ID;
-+	else {
-+		u8 *da = ieee80211_get_DA(hdr);
-+		return iwl_hw_find_station(priv, da);
++	/* Free MAC hash list for ADHOC */
++	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
++		list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
++			list_del(p);
++			kfree(list_entry(p, struct iwl_ibss_seq, list));
++		}
 +	}
-+}
 +
-+static struct ieee80211_hdr *iwl_tx_queue_get_hdr(
-+	struct iwl_priv *priv, int txq_id, int idx)
-+{
-+	if (priv->txq[txq_id].txb[idx].skb[0])
-+		return (struct ieee80211_hdr *)priv->txq[txq_id].
-+				txb[idx].skb[0]->data;
-+	return NULL;
-+}
++	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
 +
-+static inline u32 iwl_get_scd_ssn(struct iwl_tx_resp *tx_resp)
-+{
-+	__le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
-+				tx_resp->frame_count);
-+	return le32_to_cpu(*scd_ssn) & MAX_SN;
++	iwl_dealloc_ucode_pci(priv);
 +
-+}
-+static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
-+				      struct iwl_ht_agg *agg,
-+				      struct iwl_tx_resp *tx_resp,
-+				      u16 start_idx)
-+{
-+	u32 status;
-+	__le32 *frame_status = &tx_resp->status;
-+	struct ieee80211_tx_status *tx_status = NULL;
-+	struct ieee80211_hdr *hdr = NULL;
-+	int i, sh;
-+	int txq_id, idx;
-+	u16 seq;
++	if (priv->rxq.bd)
++		iwl_rx_queue_free(priv, &priv->rxq);
++	iwl_hw_txq_ctx_free(priv);
 +
-+	if (agg->wait_for_ba)
-+		IWL_DEBUG_TX_REPLY("got tx repsons w/o back\n");
++	iwl_unset_hw_setting(priv);
++	iwl_clear_stations_table(priv);
 +
-+	agg->frame_count = tx_resp->frame_count;
-+	agg->start_idx = start_idx;
-+	agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
-+	agg->bitmap0 = agg->bitmap1 = 0;
++	if (priv->mac80211_registered) {
++		ieee80211_unregister_hw(priv->hw);
++		iwl_rate_control_unregister(priv->hw);
++	}
 +
-+	if (agg->frame_count == 1) {
-+		struct iwl_tx_queue *txq ;
-+		status = le32_to_cpu(frame_status[0]);
++	/* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
++	 * priv->workqueue... so we can't take down the workqueue
++	 * until now... */
++	destroy_workqueue(priv->workqueue);
++	priv->workqueue = NULL;
 +
-+		txq_id = agg->txq_id;
-+		txq = &priv->txq[txq_id];
-+		/* FIXME: code repetition */
-+		IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d \n",
-+				   agg->frame_count, agg->start_idx);
++	free_irq(pdev->irq, priv);
++	pci_disable_msi(pdev);
++	pci_iounmap(pdev, priv->hw_base);
++	pci_release_regions(pdev);
++	pci_disable_device(pdev);
++	pci_set_drvdata(pdev, NULL);
 +
-+		tx_status = &(priv->txq[txq_id].txb[txq->q.last_used].status);
-+		tx_status->retry_count = tx_resp->failure_frame;
-+		tx_status->queue_number = status & 0xff;
-+		tx_status->queue_length = tx_resp->bt_kill_count;
-+		tx_status->queue_length |= tx_resp->failure_rts;
++	kfree(priv->channel_info);
 +
-+		tx_status->flags = iwl_is_tx_success(status)?
-+			IEEE80211_TX_STATUS_ACK : 0;
-+		tx_status->control.tx_rate =
-+				iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags);
-+		/* FIXME: code repetition end */
++	kfree(priv->ieee_channels);
++	kfree(priv->ieee_rates);
 +
-+		IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
-+				    status & 0xff, tx_resp->failure_frame);
-+		IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n",
-+				iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags));
++	if (priv->ibss_beacon)
++		dev_kfree_skb(priv->ibss_beacon);
 +
-+		agg->wait_for_ba = 0;
-+	} else {
-+		u64 bitmap = 0;
-+		int start = agg->start_idx;
++	ieee80211_free_hw(priv->hw);
++}
 +
-+		for (i = 0; i < agg->frame_count; i++) {
-+			u16 sc;
-+			status = le32_to_cpu(frame_status[i]);
-+			seq  = status >> 16;
-+			idx = SEQ_TO_INDEX(seq);
-+			txq_id = SEQ_TO_QUEUE(seq);
++#ifdef CONFIG_PM
 +
-+			if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
-+				      AGG_TX_STATE_ABORT_MSK))
-+				continue;
++static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++	struct iwl_priv *priv = pci_get_drvdata(pdev);
 +
-+			IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
-+					   agg->frame_count, txq_id, idx);
++	mutex_lock(&priv->mutex);
 +
-+			hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
++	set_bit(STATUS_IN_SUSPEND, &priv->status);
 +
-+			sc = le16_to_cpu(hdr->seq_ctrl);
-+			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
-+				IWL_ERROR("BUG_ON idx doesn't match seq control"
-+					  " idx=%d, seq_idx=%d, seq=%d\n",
-+					  idx, SEQ_TO_SN(sc),
-+					  hdr->seq_ctrl);
-+				return -1;
-+			}
++	/* Take down the device; powers it off, etc. */
++	__iwl_down(priv);
 +
-+			IWL_DEBUG_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n",
-+					   i, idx, SEQ_TO_SN(sc));
++	if (priv->mac80211_registered)
++		ieee80211_stop_queues(priv->hw);
 +
-+			sh = idx - start;
-+			if (sh > 64) {
-+				sh = (start - idx) + 0xff;
-+				bitmap = bitmap << sh;
-+				sh = 0;
-+				start = idx;
-+			} else if (sh < -64)
-+				sh  = 0xff - (start - idx);
-+			else if (sh < 0) {
-+				sh = start - idx;
-+				start = idx;
-+				bitmap = bitmap << sh;
-+				sh = 0;
-+			}
-+			bitmap |= (1 << sh);
-+			IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n",
-+					   start, (u32)(bitmap & 0xFFFFFFFF));
-+		}
++	pci_save_state(pdev);
++	pci_disable_device(pdev);
++	pci_set_power_state(pdev, PCI_D3hot);
 +
-+		agg->bitmap0 = bitmap & 0xFFFFFFFF;
-+		agg->bitmap1 = bitmap >> 32;
-+		agg->start_idx = start;
-+		agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
-+		IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%x\n",
-+				   agg->frame_count, agg->start_idx,
-+				   agg->bitmap0);
++	mutex_unlock(&priv->mutex);
 +
-+		if (bitmap)
-+			agg->wait_for_ba = 1;
-+	}
 +	return 0;
 +}
-+#endif
-+#endif
-+#endif
 +
-+static void iwl_rx_reply_tx(struct iwl_priv *priv,
-+			    struct iwl_rx_mem_buffer *rxb)
++static void iwl_resume(struct iwl_priv *priv)
 +{
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-+	int txq_id = SEQ_TO_QUEUE(sequence);
-+	int index = SEQ_TO_INDEX(sequence);
-+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-+	struct ieee80211_tx_status *tx_status;
-+	struct iwl_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-+	u32  status = le32_to_cpu(tx_resp->status);
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+#ifdef CONFIG_IWLWIFI_HT_AGG
-+	int tid, sta_id;
-+#endif
-+#endif
-+#endif
++	unsigned long flags;
 +
-+	if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
-+		IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
-+			  "is out of range [0-%d] %d %d\n", txq_id,
-+			  index, txq->q.n_bd, txq->q.first_empty,
-+			  txq->q.last_used);
-+		return;
++	/* The following it a temporary work around due to the
++	 * suspend / resume not fully initializing the NIC correctly.
++	 * Without all of the following, resume will not attempt to take
++	 * down the NIC (it shouldn't really need to) and will just try
++	 * and bring the NIC back up.  However that fails during the
++	 * ucode verification process.  This then causes iwl_down to be
++	 * called *after* iwl_hw_nic_init() has succeeded -- which
++	 * then lets the next init sequence succeed.  So, we've
++	 * replicated all of that NIC init code here... */
++
++	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
++
++	iwl_hw_nic_init(priv);
++
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
++	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++
++	/* tell the device to stop sending interrupts */
++	iwl_disable_interrupts(priv);
++
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++
++	if (!iwl_grab_restricted_access(priv)) {
++		iwl_write_restricted_reg(priv, APMG_CLK_DIS_REG,
++					 APMG_CLK_VAL_DMA_CLK_RQT);
++		iwl_release_restricted_access(priv);
 +	}
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+#ifdef CONFIG_IWLWIFI_HT_AGG
-+	if (txq->sched_retry) {
-+		const u32 scd_ssn = iwl_get_scd_ssn(tx_resp);
-+		struct ieee80211_hdr *hdr =
-+			iwl_tx_queue_get_hdr(priv, txq_id, index);
-+		struct iwl_ht_agg *agg = NULL;
-+		__le16 *qc = ieee80211_get_qos_ctrl(hdr);
++	udelay(5);
 +
-+		if (qc == NULL) {
-+			IWL_ERROR("BUG_ON qc is null!!!!\n");
-+			return;
-+		}
++	iwl_hw_nic_reset(priv);
 +
-+		tid = le16_to_cpu(*qc) & 0xf;
++	/* Bring the device back up */
++	clear_bit(STATUS_IN_SUSPEND, &priv->status);
++	queue_work(priv->workqueue, &priv->up);
++}
 +
-+		sta_id = iwl_get_ra_sta_id(priv, hdr);
-+		if (unlikely(sta_id == IWL_INVALID_STATION)) {
-+			IWL_ERROR("Station not known for\n");
-+			return;
-+		}
++static int iwl_pci_resume(struct pci_dev *pdev)
++{
++	struct iwl_priv *priv = pci_get_drvdata(pdev);
++	int err;
 +
-+		agg = &priv->stations[sta_id].tid[tid].agg;
++	printk(KERN_INFO "Coming out of suspend...\n");
 +
-+		iwl4965_tx_status_reply_tx(priv, agg, tx_resp, index);
++	mutex_lock(&priv->mutex);
 +
-+		if ((tx_resp->frame_count == 1) &&
-+		    !iwl_is_tx_success(status)) {
-+			/* TODO: send BAR */
-+		}
++	pci_set_power_state(pdev, PCI_D0);
++	err = pci_enable_device(pdev);
++	pci_restore_state(pdev);
 +
-+		if ((txq->q.last_used != (scd_ssn & 0xff))) {
-+			index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
-+			IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
-+					   "%d index %d\n", scd_ssn , index);
-+			iwl_tx_queue_reclaim(priv, txq_id, index);
-+		}
-+	} else {
-+#endif /* CONFIG_IWLWIFI_HT_AGG */
-+#endif /* CONFIG_IWLWIFI_HT */
-+#endif /* 4965 */
-+	tx_status = &(txq->txb[txq->q.last_used].status);
++	/*
++	 * Suspend/Resume resets the PCI configuration space, so we have to
++	 * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
++	 * from interfering with C3 CPU state. pci_restore_state won't help
++	 * here since it only restores the first 64 bytes pci config header.
++	 */
++	pci_write_config_byte(pdev, 0x41, 0x00);
 +
-+	tx_status->retry_count = tx_resp->failure_frame;
-+	tx_status->queue_number = status;
-+	tx_status->queue_length = tx_resp->bt_kill_count;
-+	tx_status->queue_length |= tx_resp->failure_rts;
++	iwl_resume(priv);
++	mutex_unlock(&priv->mutex);
 +
-+	tx_status->flags =
-+	    iwl_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
++	return 0;
++}
 +
-+#if IWL == 3945
-+	tx_status->control.tx_rate = iwl_rate_index_from_plcp(tx_resp->rate);
++#endif /* CONFIG_PM */
 +
-+	IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
-+			txq_id, iwl_get_tx_fail_reason(status), status,
-+			tx_resp->rate, tx_resp->failure_frame);
-+#elif IWL == 4965
-+	tx_status->control.tx_rate =
-+		iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags);
++/*****************************************************************************
++ *
++ * driver and module entry point
++ *
++ *****************************************************************************/
 +
-+	IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
-+		     "retries %d\n", txq_id, iwl_get_tx_fail_reason(status),
-+		     status, le32_to_cpu(tx_resp->rate_n_flags),
-+		     tx_resp->failure_frame);
++static struct pci_driver iwl_driver = {
++	.name = DRV_NAME,
++	.id_table = iwl_hw_card_ids,
++	.probe = iwl_pci_probe,
++	.remove = __devexit_p(iwl_pci_remove),
++#ifdef CONFIG_PM
++	.suspend = iwl_pci_suspend,
++	.resume = iwl_pci_resume,
 +#endif
++};
 +
-+	IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
-+	if (index != -1)
-+		iwl_tx_queue_reclaim(priv, txq_id, index);
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+#ifdef CONFIG_IWLWIFI_HT_AGG
++static int __init iwl_init(void)
++{
++
++	int ret;
++	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
++	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
++	ret = pci_register_driver(&iwl_driver);
++	if (ret) {
++		IWL_ERROR("Unable to initialize PCI module\n");
++		return ret;
 +	}
-+#endif /* CONFIG_IWLWIFI_HT_AGG */
-+#endif /* CONFIG_IWLWIFI_HT */
-+#endif /* 4965 */
++#ifdef CONFIG_IWLWIFI_DEBUG
++	ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level);
++	if (ret) {
++		IWL_ERROR("Unable to create driver sysfs file\n");
++		pci_unregister_driver(&iwl_driver);
++		return ret;
++	}
++#endif
 +
-+	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
-+		IWL_ERROR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
++	return ret;
 +}
 +
-+
-+static void iwl_rx_reply_alive(struct iwl_priv *priv,
-+			       struct iwl_rx_mem_buffer *rxb)
++static void __exit iwl_exit(void)
 +{
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_alive_resp *palive;
-+	struct delayed_work *pwork;
++#ifdef CONFIG_IWLWIFI_DEBUG
++	driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level);
++#endif
++	pci_unregister_driver(&iwl_driver);
++}
 +
-+	palive = &pkt->u.alive_frame;
++module_param_named(antenna, iwl_param_antenna, int, 0444);
++MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
++module_param_named(disable, iwl_param_disable, int, 0444);
++MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
++module_param_named(hwcrypto, iwl_param_hwcrypto, int, 0444);
++MODULE_PARM_DESC(hwcrypto,
++		 "using hardware crypto engine (default 0 [software])\n");
++module_param_named(debug, iwl_param_debug, int, 0444);
++MODULE_PARM_DESC(debug, "debug output mask");
++module_param_named(disable_hw_scan, iwl_param_disable_hw_scan, int, 0444);
++MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
 +
-+	IWL_DEBUG_INFO("Alive ucode status 0x%08X revision "
-+		       "0x%01X 0x%01X\n",
-+		       palive->is_valid, palive->ver_type,
-+		       palive->ver_subtype);
++module_param_named(queues_num, iwl_param_queues_num, int, 0444);
++MODULE_PARM_DESC(queues_num, "number of hw queues.");
 +
-+	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
-+		IWL_DEBUG_INFO("Initialization Alive received.\n");
-+		memcpy(&priv->card_alive_init,
-+		       &pkt->u.alive_frame,
-+		       sizeof(struct iwl_init_alive_resp));
-+		pwork = &priv->init_alive_start;
-+	} else {
-+		IWL_DEBUG_INFO("Runtime Alive received.\n");
-+		memcpy(&priv->card_alive, &pkt->u.alive_frame,
-+		       sizeof(struct iwl_alive_resp));
-+		pwork = &priv->alive_start;
-+#if IWL == 3945
-+		/* For debugging (selective disable not supported in 4965) */
-+		iwl_disable_events(priv);
-+#endif
-+	}
++/* QoS */
++module_param_named(qos_enable, iwl_param_qos_enable, int, 0444);
++MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
 +
-+	/* We delay the ALIVE response by 5ms to
-+	 * give the HW RF Kill time to activate... */
-+	if (palive->is_valid == UCODE_VALID_OK)
-+		queue_delayed_work(priv->workqueue, pwork,
-+				   msecs_to_jiffies(5));
-+	else
-+		IWL_WARNING("uCode did not respond OK.\n");
-+}
++module_exit(iwl_exit);
++module_init(iwl_init);
+diff --git a/drivers/net/wireless/iwl4965-base.c b/drivers/net/wireless/iwl4965-base.c
+new file mode 100644
+index 0000000..47e2fdf
+--- /dev/null
++++ b/drivers/net/wireless/iwl4965-base.c
+@@ -0,0 +1,9326 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project, as well
++ * as portions of the ieee80211 subsystem header files.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
 +
-+static void iwl_rx_reply_add_sta(struct iwl_priv *priv,
-+				 struct iwl_rx_mem_buffer *rxb)
-+{
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
-+	return;
-+}
++/*
++ * NOTE:  This file (iwl-base.c) is used to build to multiple hardware targets
++ * by defining IWL to either 3945 or 4965.  The Makefile used when building
++ * the base targets will create base-3945.o and base-4965.o
++ *
++ * The eventual goal is to move as many of the #if IWL / #endif blocks out of
++ * this file and into the hardware specific implementation files (iwl-XXXX.c)
++ * and leave only the common (non #ifdef sprinkled) code in this file
++ */
 +
-+static void iwl_rx_reply_error(struct iwl_priv *priv,
-+			       struct iwl_rx_mem_buffer *rxb)
-+{
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <linux/delay.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/wireless.h>
++#include <linux/firmware.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/if_arp.h>
++
++#include <net/ieee80211_radiotap.h>
++#include <net/mac80211.h>
++
++#include <asm/div64.h>
++
++#include "iwlwifi.h"
++#include "iwl-4965.h"
++#include "iwl-helpers.h"
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++u32 iwl_debug_level;
++#endif
++
++/******************************************************************************
++ *
++ * module boiler plate
++ *
++ ******************************************************************************/
++
++/* module parameters */
++int iwl_param_disable_hw_scan;
++int iwl_param_debug;
++int iwl_param_disable;      /* def: enable radio */
++int iwl_param_antenna;      /* def: 0 = both antennas (use diversity) */
++int iwl_param_hwcrypto;     /* def: using software encryption */
++int iwl_param_qos_enable = 1;
++int iwl_param_queues_num = IWL_MAX_NUM_QUEUES;
 +
-+	IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) "
-+		"seq 0x%04X ser 0x%08X\n",
-+		le32_to_cpu(pkt->u.err_resp.error_type),
-+		get_cmd_string(pkt->u.err_resp.cmd_id),
-+		pkt->u.err_resp.cmd_id,
-+		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
-+		le32_to_cpu(pkt->u.err_resp.error_info));
-+}
++/*
++ * module name, copyright, version, etc.
++ * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk
++ */
 +
-+#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
++#define DRV_DESCRIPTION	"Intel(R) Wireless WiFi Link 4965AGN driver for Linux"
 +
-+static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
-+{
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
-+	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
-+	IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
-+		      le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
-+	rxon->channel = csa->channel;
-+	priv->staging_rxon.channel = csa->channel;
-+}
++#ifdef CONFIG_IWLWIFI_DEBUG
++#define VD "d"
++#else
++#define VD
++#endif
 +
-+static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
-+					  struct iwl_rx_mem_buffer *rxb)
-+{
 +#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
++#define VS "s"
++#else
++#define VS
++#endif
 +
-+	if (!report->state) {
-+		IWL_DEBUG(IWL_DL_11H | IWL_DL_INFO,
-+			  "Spectrum Measure Notification: Start\n");
-+		return;
-+	}
++#define IWLWIFI_VERSION "0.1.14k" VD VS
++#define DRV_COPYRIGHT	"Copyright(c) 2003-2007 Intel Corporation"
++#define DRV_VERSION     IWLWIFI_VERSION
 +
-+	memcpy(&priv->measure_report, report, sizeof(*report));
-+	priv->measurement_status |= MEASUREMENT_READY;
-+#endif
-+}
++/* Change firmware file name, using "-" and incrementing number,
++ *   *only* when uCode interface or architecture changes so that it
++ *   is not compatible with earlier drivers.
++ * This number will also appear in << 8 position of 1st dword of uCode file */
++#define IWL4965_UCODE_API "-1"
 +
-+static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
-+				  struct iwl_rx_mem_buffer *rxb)
-+{
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
-+	IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
-+		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
-+#endif
-+}
++MODULE_DESCRIPTION(DRV_DESCRIPTION);
++MODULE_VERSION(DRV_VERSION);
++MODULE_AUTHOR(DRV_COPYRIGHT);
++MODULE_LICENSE("GPL");
 +
-+static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
-+					     struct iwl_rx_mem_buffer *rxb)
++__le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
 +{
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
-+			"notification for %s:\n",
-+			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
-+	iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
++	u16 fc = le16_to_cpu(hdr->frame_control);
++	int hdr_len = ieee80211_get_hdrlen(fc);
++
++	if ((fc & 0x00cc) == (IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA))
++		return (__le16 *) ((u8 *) hdr + hdr_len - QOS_CONTROL_LEN);
++	return NULL;
 +}
 +
-+static void iwl_bg_beacon_update(struct work_struct *work)
++static const struct ieee80211_hw_mode *iwl_get_hw_mode(
++		struct iwl_priv *priv, int mode)
 +{
-+	struct iwl_priv *priv =
-+		container_of(work, struct iwl_priv, beacon_update);
-+	struct sk_buff *beacon;
++	int i;
 +
-+	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
-+	beacon = ieee80211_beacon_get(priv->hw, priv->interface_id, NULL);
++	for (i = 0; i < 3; i++)
++		if (priv->modes[i].mode == mode)
++			return &priv->modes[i];
 +
-+	if (!beacon) {
-+		IWL_ERROR("update beacon failed\n");
-+		return;
-+	}
++	return NULL;
++}
 +
-+	mutex_lock(&priv->mutex);
-+	/* new beacon skb is allocated every time; dispose previous.*/
-+	if (priv->ibss_beacon)
-+		dev_kfree_skb(priv->ibss_beacon);
++static int iwl_is_empty_essid(const char *essid, int essid_len)
++{
++	/* Single white space is for Linksys APs */
++	if (essid_len == 1 && essid[0] == ' ')
++		return 1;
 +
-+	priv->ibss_beacon = beacon;
-+	mutex_unlock(&priv->mutex);
++	/* Otherwise, if the entire essid is 0, we assume it is hidden */
++	while (essid_len) {
++		essid_len--;
++		if (essid[essid_len] != '\0')
++			return 0;
++	}
 +
-+	iwl_send_beacon_cmd(priv);
++	return 1;
 +}
 +
-+static void iwl_rx_beacon_notif(struct iwl_priv *priv,
-+				struct iwl_rx_mem_buffer *rxb)
++static const char *iwl_escape_essid(const char *essid, u8 essid_len)
 +{
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_beacon_notif *beacon = &(pkt->u.beacon_status);
-+#if IWL == 3945
-+	u8 rate = beacon->beacon_notify_hdr.rate;
-+#elif IWL == 4965
-+	u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
-+#endif
-+	IWL_DEBUG_RX("beacon status %x retries %d iss %d "
-+		"tsf %d %d rate %d\n",
-+		le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
-+		beacon->beacon_notify_hdr.failure_frame,
-+		le32_to_cpu(beacon->ibss_mgr_status),
-+		le32_to_cpu(beacon->high_tsf),
-+		le32_to_cpu(beacon->low_tsf), rate);
-+#endif
++	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
++	const char *s = essid;
++	char *d = escaped;
 +
-+	if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
-+	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
-+		queue_work(priv->workqueue, &priv->beacon_update);
++	if (iwl_is_empty_essid(essid, essid_len)) {
++		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
++		return escaped;
++	}
++
++	essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
++	while (essid_len--) {
++		if (*s == '\0') {
++			*d++ = '\\';
++			*d++ = '0';
++			s++;
++		} else
++			*d++ = *s++;
++	}
++	*d = '\0';
++	return escaped;
 +}
 +
-+/* Service response to REPLY_SCAN_CMD (0x80) */
-+static void iwl_rx_reply_scan(struct iwl_priv *priv,
-+			      struct iwl_rx_mem_buffer *rxb)
++static void iwl_print_hex_dump(int level, void *p, u32 len)
 +{
 +#ifdef CONFIG_IWLWIFI_DEBUG
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_scanreq_notification *notif =
-+	    (struct iwl_scanreq_notification *)pkt->u.raw;
++	if (!(iwl_debug_level & level))
++		return;
 +
-+	IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status);
++	print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
++			p, len, 1);
 +#endif
 +}
 +
-+/* Service SCAN_START_NOTIFICATION (0x82) */
-+static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
-+				    struct iwl_rx_mem_buffer *rxb)
-+{
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_scanstart_notification *notif =
-+	    (struct iwl_scanstart_notification *)pkt->u.raw;
-+	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
-+	IWL_DEBUG_SCAN("Scan start: "
-+		       "%d [802.11%s] "
-+		       "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
-+		       notif->channel,
-+		       notif->band ? "bg" : "a",
-+		       notif->tsf_high,
-+		       notif->tsf_low, notif->status, notif->beacon_timer);
-+}
++/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
++ * DMA services
++ *
++ * Theory of operation
++ *
++ * A queue is a circular buffers with 'Read' and 'Write' pointers.
++ * 2 empty entries always kept in the buffer to protect from overflow.
++ *
++ * For Tx queue, there are low mark and high mark limits. If, after queuing
++ * the packet for Tx, free space become < low mark, Tx queue stopped. When
++ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
++ * Tx queue resumed.
++ *
++ * The IPW operates with six queues, one receive queue in the device's
++ * sram, one transmit queue for sending commands to the device firmware,
++ * and four transmit queues for data.
++ *
++ * The four transmit queues allow for performing quality of service (qos)
++ * transmissions as per the 802.11 protocol.  Currently Linux does not
++ * provide a mechanism to the user for utilizing prioritized queues, so
++ * we only utilize the first data transmit queue (queue1).
++ ***************************************************/
 +
-+/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
-+static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
-+				      struct iwl_rx_mem_buffer *rxb)
++static int iwl_queue_space(const struct iwl_queue *q)
 +{
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_scanresults_notification *notif =
-+	    (struct iwl_scanresults_notification *)pkt->u.raw;
++	int s = q->last_used - q->first_empty;
 +
-+	IWL_DEBUG_SCAN("Scan ch.res: "
-+		       "%d [802.11%s] "
-+		       "(TSF: 0x%08X:%08X) - %d "
-+		       "elapsed=%lu usec (%dms since last)\n",
-+		       notif->channel,
-+		       notif->band ? "bg" : "a",
-+		       le32_to_cpu(notif->tsf_high),
-+		       le32_to_cpu(notif->tsf_low),
-+		       le32_to_cpu(notif->statistics[0]),
-+		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf,
-+		       jiffies_to_msecs(elapsed_jiffies
-+					(priv->last_scan_jiffies, jiffies)));
++	if (q->last_used > q->first_empty)
++		s -= q->n_bd;
 +
-+	priv->last_scan_jiffies = jiffies;
++	if (s <= 0)
++		s += q->n_window;
++	/* keep some reserve to not confuse empty and full situations */
++	s -= 2;
++	if (s < 0)
++		s = 0;
++	return s;
 +}
 +
-+/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
-+static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
-+				       struct iwl_rx_mem_buffer *rxb)
++/* XXX: n_bd must be power-of-two size */
++static inline int iwl_queue_inc_wrap(int index, int n_bd)
 +{
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
-+
-+	IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
-+		       scan_notif->scanned_channels,
-+		       scan_notif->tsf_low,
-+		       scan_notif->tsf_high, scan_notif->status);
-+
-+	/* The HW is no longer scanning */
-+	clear_bit(STATUS_SCAN_HW, &priv->status);
++	return ++index & (n_bd - 1);
++}
 +
-+	/* The scan completion notification came in, so kill that timer... */
-+	cancel_delayed_work(&priv->scan_check);
++/* XXX: n_bd must be power-of-two size */
++static inline int iwl_queue_dec_wrap(int index, int n_bd)
++{
++	return --index & (n_bd - 1);
++}
 +
-+	IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n",
-+		       (priv->scan_bands == 2) ? "2.4" : "5.2",
-+		       jiffies_to_msecs(elapsed_jiffies
-+					(priv->scan_pass_start, jiffies)));
++static inline int x2_queue_used(const struct iwl_queue *q, int i)
++{
++	return q->first_empty > q->last_used ?
++		(i >= q->last_used && i < q->first_empty) :
++		!(i < q->last_used && i >= q->first_empty);
++}
 +
-+	/* Remove this scanned band from the list
-+	 * of pending bands to scan */
-+	priv->scan_bands--;
++static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
++{
++	if (is_huge)
++		return q->n_window;
 +
-+	/* If a request to abort was given, or the scan did not succeed
-+	 * then we reset the scan state machine and terminate,
-+	 * re-queuing another scan if one has been requested */
-+	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-+		IWL_DEBUG_INFO("Aborted scan completed.\n");
-+		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-+	} else {
-+		/* If there are more bands on this scan pass reschedule */
-+		if (priv->scan_bands > 0)
-+			goto reschedule;
-+	}
++	return index & (q->n_window - 1);
++}
 +
-+	priv->last_scan_jiffies = jiffies;
-+	IWL_DEBUG_INFO("Setting scan to off\n");
++static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
++			  int count, int slots_num, u32 id)
++{
++	q->n_bd = count;
++	q->n_window = slots_num;
++	q->id = id;
 +
-+	clear_bit(STATUS_SCANNING, &priv->status);
++	/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
++	 * and iwl_queue_dec_wrap are broken. */
++	BUG_ON(!is_power_of_2(count));
 +
-+	IWL_DEBUG_INFO("Scan took %dms\n",
-+		jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));
++	/* slots_num must be power-of-two size, otherwise
++	 * get_cmd_index is broken. */
++	BUG_ON(!is_power_of_2(slots_num));
 +
-+	queue_work(priv->workqueue, &priv->scan_completed);
++	q->low_mark = q->n_window / 4;
++	if (q->low_mark < 4)
++		q->low_mark = 4;
 +
-+	return;
++	q->high_mark = q->n_window / 8;
++	if (q->high_mark < 2)
++		q->high_mark = 2;
 +
-+reschedule:
-+	priv->scan_pass_start = jiffies;
-+	queue_work(priv->workqueue, &priv->request_scan);
++	q->first_empty = q->last_used = 0;
++
++	return 0;
 +}
 +
-+/* Handle notification from uCode that card's power state is changing
-+ * due to software, hardware, or critical temperature RFKILL */
-+static void iwl_rx_card_state_notif(struct iwl_priv *priv,
-+				    struct iwl_rx_mem_buffer *rxb)
++static int iwl_tx_queue_alloc(struct iwl_priv *priv,
++			      struct iwl_tx_queue *txq, u32 id)
 +{
-+	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
-+	unsigned long status = priv->status;
-+	IWL_DEBUG_RF_KILL("Card state received: HW:%s SW:%s\n",
-+			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
-+			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");
-+#if IWL == 4965
-+	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
-+		     RF_CARD_DISABLED)) {
-+
-+		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-+			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-+
-+		if (!iwl_grab_restricted_access(priv)) {
-+			iwl_write_restricted(
-+				priv, HBUS_TARG_MBX_C,
-+				HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
++	struct pci_dev *dev = priv->pci_dev;
 +
-+			iwl_release_restricted_access(priv);
++	if (id != IWL_CMD_QUEUE_NUM) {
++		txq->txb = kmalloc(sizeof(txq->txb[0]) *
++				   TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
++		if (!txq->txb) {
++			IWL_ERROR("kmalloc for auxilary BD "
++				  "structures failed\n");
++			goto error;
 +		}
++	} else
++		txq->txb = NULL;
 +
-+		if (!(flags & RXON_CARD_DISABLED)) {
-+			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-+				    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-+			if (!iwl_grab_restricted_access(priv)) {
-+				iwl_write_restricted(
-+					priv, HBUS_TARG_MBX_C,
-+					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-+
-+				iwl_release_restricted_access(priv);
-+			}
-+		}
++	txq->bd = pci_alloc_consistent(dev,
++			sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
++			&txq->q.dma_addr);
 +
-+		if (flags & RF_CARD_DISABLED) {
-+			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-+				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-+			iwl_read32(priv, CSR_UCODE_DRV_GP1);
-+			if (!iwl_grab_restricted_access(priv))
-+				iwl_release_restricted_access(priv);
-+		}
++	if (!txq->bd) {
++		IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
++			  sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
++		goto error;
 +	}
-+#else
-+	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-+		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-+#endif
-+	if (flags & HW_CARD_DISABLED)
-+		set_bit(STATUS_RF_KILL_HW, &priv->status);
-+	else
-+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
-+
++	txq->q.id = id;
 +
-+	if (flags & SW_CARD_DISABLED)
-+		set_bit(STATUS_RF_KILL_SW, &priv->status);
-+	else
-+		clear_bit(STATUS_RF_KILL_SW, &priv->status);
++	return 0;
 +
-+#if IWL == 4965
-+	if (!(flags & RXON_CARD_DISABLED))
-+#endif
-+		iwl_scan_cancel(priv);
++ error:
++	if (txq->txb) {
++		kfree(txq->txb);
++		txq->txb = NULL;
++	}
 +
-+	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-+	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
-+	    (test_bit(STATUS_RF_KILL_SW, &status) !=
-+	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
-+		queue_work(priv->workqueue, &priv->rf_kill);
-+	else
-+		wake_up_interruptible(&priv->wait_command_queue);
++	return -ENOMEM;
 +}
 +
-+/**
-+ * iwl_setup_rx_handlers - Initialize Rx handler callbacks
-+ *
-+ * Setup the RX handlers for each of the reply types sent from the uCode
-+ * to the host.
-+ *
-+ * This function chains into the hardware specific files for them to setup
-+ * any hardware specific handlers as well.
-+ */
-+static void iwl_setup_rx_handlers(struct iwl_priv *priv)
++int iwl_tx_queue_init(struct iwl_priv *priv,
++		      struct iwl_tx_queue *txq, int slots_num, u32 txq_id)
 +{
-+	priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
-+	priv->rx_handlers[REPLY_ADD_STA] = iwl_rx_reply_add_sta;
-+	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
-+	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
-+	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
-+	    iwl_rx_spectrum_measure_notif;
-+	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
-+	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
-+	    iwl_rx_pm_debug_statistics_notif;
-+	priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
++	struct pci_dev *dev = priv->pci_dev;
++	int len;
++	int rc = 0;
 +
-+	/* NOTE:  iwl_rx_statistics is different based on whether
-+	 * the build is for the 3945 or the 4965.  See the
-+	 * corresponding implementation in iwl-XXXX.c
-+	 *
-+	 * The same handler is used for both the REPLY to a
-+	 * discrete statistics request from the host as well as
-+	 * for the periodic statistics notification from the uCode
-+	 */
-+	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_hw_rx_statistics;
-+	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_hw_rx_statistics;
++	/* alocate command space + one big command for scan since scan
++	 * command is very huge the system will not have two scan at the
++	 * same time */
++	len = sizeof(struct iwl_cmd) * slots_num;
++	if (txq_id == IWL_CMD_QUEUE_NUM)
++		len +=  IWL_MAX_SCAN_SIZE;
++	txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
++	if (!txq->cmd)
++		return -ENOMEM;
 +
-+	priv->rx_handlers[REPLY_SCAN_CMD] = iwl_rx_reply_scan;
-+	priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl_rx_scan_start_notif;
-+	priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
-+	    iwl_rx_scan_results_notif;
-+	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
-+	    iwl_rx_scan_complete_notif;
-+	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
-+	priv->rx_handlers[REPLY_TX] = iwl_rx_reply_tx;
++	rc = iwl_tx_queue_alloc(priv, txq, txq_id);
++	if (rc) {
++		pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
 +
-+	/* Setup hardware specific Rx handlers */
-+	iwl_hw_rx_handler_setup(priv);
++		return -ENOMEM;
++	}
++	txq->need_update = 0;
++
++	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
++	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
++	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
++	iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
++
++	iwl_hw_tx_queue_init(priv, txq);
++
++	return 0;
 +}
 +
 +/**
-+ * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
-+ * @rxb: Rx buffer to reclaim
++ * iwl_tx_queue_free - Deallocate DMA queue.
++ * @txq: Transmit queue to deallocate.
++ *
++ * Empty queue by removing and destroying all BD's.
++ * Free all buffers.  txq itself is not freed.
 + *
-+ * If an Rx buffer has an async callback associated with it the callback
-+ * will be executed.  The attached skb (if present) will only be freed
-+ * if the callback returns 1
 + */
-+static void iwl_tx_cmd_complete(struct iwl_priv *priv,
-+				struct iwl_rx_mem_buffer *rxb)
++void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
 +{
-+	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-+	int txq_id = SEQ_TO_QUEUE(sequence);
-+	int index = SEQ_TO_INDEX(sequence);
-+	int huge = sequence & SEQ_HUGE_FRAME;
-+	int cmd_index;
-+	struct iwl_cmd *cmd;
-+
-+	/* If a Tx command is being handled and it isn't in the actual
-+	 * command queue then there a command routing bug has been introduced
-+	 * in the queue management code. */
-+	if (txq_id != IWL_CMD_QUEUE_NUM)
-+		IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
-+			  txq_id, pkt->hdr.cmd);
-+	BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
++	struct iwl_queue *q = &txq->q;
++	struct pci_dev *dev = priv->pci_dev;
++	int len;
 +
-+	cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
-+	cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
++	if (q->n_bd == 0)
++		return;
 +
-+	/* Input error checking is done when commands are added to queue. */
-+	if (cmd->meta.flags & CMD_WANT_SKB) {
-+		cmd->meta.source->u.skb = rxb->skb;
-+		rxb->skb = NULL;
-+	} else if (cmd->meta.u.callback &&
-+		   !cmd->meta.u.callback(priv, cmd, rxb->skb))
-+		rxb->skb = NULL;
++	/* first, empty all BD's */
++	for (; q->first_empty != q->last_used;
++	     q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd))
++		iwl_hw_txq_free_tfd(priv, txq);
 +
-+	iwl_tx_queue_reclaim(priv, txq_id, index);
++	len = sizeof(struct iwl_cmd) * q->n_window;
++	if (q->id == IWL_CMD_QUEUE_NUM)
++		len += IWL_MAX_SCAN_SIZE;
 +
-+	if (!(cmd->meta.flags & CMD_ASYNC)) {
-+		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-+		wake_up_interruptible(&priv->wait_command_queue);
++	pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
++
++	/* free buffers belonging to queue itself */
++	if (txq->q.n_bd)
++		pci_free_consistent(dev, sizeof(struct iwl_tfd_frame) *
++				    txq->q.n_bd, txq->bd, txq->q.dma_addr);
++
++	if (txq->txb) {
++		kfree(txq->txb);
++		txq->txb = NULL;
 +	}
++
++	/* 0 fill whole structure */
++	memset(txq, 0, sizeof(*txq));
 +}
 +
-+/************************** RX-FUNCTIONS ****************************/
-+/*
-+ * Rx theory of operation
-+ *
-+ * The host allocates 32 DMA target addresses and passes the host address
-+ * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
-+ * 0 to 31
-+ *
-+ * Rx Queue Indexes
-+ * The host/firmware share two index registers for managing the Rx buffers.
-+ *
-+ * The READ index maps to the first position that the firmware may be writing
-+ * to -- the driver can read up to (but not including) this position and get
-+ * good data.
-+ * The READ index is managed by the firmware once the card is enabled.
-+ *
-+ * The WRITE index maps to the last position the driver has read from -- the
-+ * position preceding WRITE is the last slot the firmware can place a packet.
-+ *
-+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
-+ * WRITE = READ.
-+ *
-+ * During initialization the host sets up the READ queue position to the first
-+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
-+ *
-+ * When the firmware places a packet in a buffer it will advance the READ index
-+ * and fire the RX interrupt.  The driver can then query the READ index and
-+ * process as many packets as possible, moving the WRITE index forward as it
-+ * resets the Rx queue buffers with new memory.
-+ *
-+ * The management in the driver is as follows:
-+ * + A list of pre-allocated SKBs is stored in ipw->rxq->rx_free.  When
-+ *   ipw->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
-+ *   to replensish the ipw->rxq->rx_free.
-+ * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
-+ *   ipw->rxq is replenished and the READ INDEX is updated (updating the
-+ *   'processed' and 'read' driver indexes as well)
-+ * + A received packet is processed and handed to the kernel network stack,
-+ *   detached from the ipw->rxq.  The driver 'processed' index is updated.
-+ * + The Host/Firmware ipw->rxq is replenished at tasklet time from the rx_free
-+ *   list. If there are no allocated buffers in ipw->rxq->rx_free, the READ
-+ *   INDEX is not incremented and ipw->status(RX_STALLED) is set.  If there
-+ *   were enough free buffers and RX_STALLED is set it is cleared.
-+ *
-+ *
-+ * Driver sequence:
-+ *
-+ * iwl_rx_queue_alloc()       Allocates rx_free
-+ * iwl_rx_replenish()         Replenishes rx_free list from rx_used, and calls
-+ *                            iwl_rx_queue_restock
-+ * iwl_rx_queue_restock()     Moves available buffers from rx_free into Rx
-+ *                            queue, updates firmware pointers, and updates
-+ *                            the WRITE index.  If insufficient rx_free buffers
-+ *                            are available, schedules iwl_rx_replenish
++const u8 BROADCAST_ADDR[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
++
++/*************** STATION TABLE MANAGEMENT ****
 + *
-+ * -- enable interrupts --
-+ * ISR - iwl_rx()             Detach iwl_rx_mem_buffers from pool up to the
-+ *                            READ INDEX, detaching the SKB from the pool.
-+ *                            Moves the packet buffer from queue to rx_used.
-+ *                            Calls iwl_rx_queue_restock to refill any empty
-+ *                            slots.
-+ * ...
++ * NOTE:  This needs to be overhauled to better synchronize between
++ * how the iwl-4965.c is using iwl_hw_find_station vs. iwl-3945.c
 + *
++ * mac80211 should also be examined to determine if sta_info is duplicating
++ * the functionality provided here
 + */
 +
-+/**
-+ * iwl_rx_queue_space - Return number of free slots available in queue.
-+ */
-+static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
++/**************************************************************/
++
++static u8 iwl_remove_station(struct iwl_priv *priv, const u8 *bssid, int is_ap)
 +{
-+	int s = q->read - q->write;
-+	if (s <= 0)
-+		s += RX_QUEUE_SIZE;
-+	/* keep some buffer to not confuse full and empty queue */
-+	s -= 2;
-+	if (s < 0)
-+		s = 0;
-+	return s;
++	int index = IWL_INVALID_STATION;
++	int i;
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->sta_lock, flags);
++
++	if (is_ap) {
++		index = IWL_AP_ID;
++		if ((priv->stations[index].used))
++			priv->stations[index].used = 0;
++	} else if (is_broadcast_ether_addr(bssid)) {
++		index = IWL_BROADCAST_ID;
++		if ((priv->stations[index].used))
++			priv->stations[index].used = 0;
++	} else {
++		for (i = IWL_STA_ID; i < priv->num_stations + IWL_STA_ID; i++) {
++			if (priv->stations[i].used &&
++			    !compare_ether_addr(priv->stations[i].sta.sta.addr,
++						bssid)) {
++				index = i;
++				priv->stations[index].used = 0;
++				break;
++			}
++		}
++	}
++	if (index != IWL_INVALID_STATION) {
++		if (priv->num_stations > 0)
++			priv->num_stations--;
++	}
++
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++	return 0;
 +}
 +
-+/**
-+ * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
-+ *
-+ * NOTE: This function has 3945 and 4965 specific code sections
-+ * but is declared in base due to the majority of the
-+ * implementation being the same (only a numeric constant is
-+ * different)
-+ *
-+ */
-+int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
++static void iwl_clear_stations_table(struct iwl_priv *priv)
 +{
-+	u32 reg = 0;
-+	int rc = 0;
 +	unsigned long flags;
 +
-+	spin_lock_irqsave(&q->lock, flags);
++	spin_lock_irqsave(&priv->sta_lock, flags);
 +
-+	if (q->need_update == 0)
-+		goto exit_unlock;
++	priv->num_stations = 0;
++	memset(priv->stations, 0, sizeof(priv->stations));
 +
-+	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-+		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++}
 +
-+		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-+			iwl_set_bit(priv, CSR_GP_CNTRL,
-+				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-+			goto exit_unlock;
++u8 iwl_add_station(struct iwl_priv *priv, const u8 *bssid, int is_ap, u8 flags)
++{
++	int i = IWL_STATION_COUNT;
++	int index = IWL_INVALID_STATION;
++	struct iwl_station_entry *station;
++	unsigned long flags_spin;
++
++	spin_lock_irqsave(&priv->sta_lock, flags_spin);
++	if (is_ap) {
++		index = IWL_AP_ID;
++		if (priv->stations[index].used &&
++		    !compare_ether_addr(priv->stations[index].sta.sta.addr,
++					bssid))
++			goto done;
++	} else if (is_broadcast_ether_addr(bssid)) {
++		index = IWL_BROADCAST_ID;
++		if (priv->stations[index].used &&
++		    !compare_ether_addr(priv->stations[index].sta.sta.addr,
++					bssid))
++			goto done;
++	} else {
++		for (i = IWL_STA_ID; i < priv->num_stations + IWL_STA_ID; i++) {
++			if (priv->stations[i].used &&
++			    !compare_ether_addr(priv->stations[i].sta.sta.addr,
++						bssid))
++				goto done;
++
++			if (!priv->stations[i].used &&
++			    index == IWL_INVALID_STATION)
++				index = i;
 +		}
++	}
++
++	if (index != IWL_INVALID_STATION)
++		i = index;
++
++	if (i == IWL_STATION_COUNT) {
++		index = IWL_INVALID_STATION;
++		goto done;
++	}
++
++	IWL_DEBUG_ASSOC("Adding STA ID %d: " MAC_FMT "\n", i, MAC_ARG(bssid));
++	station = &priv->stations[i];
++
++	station->used = 1;
++	memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
++	memcpy(station->sta.sta.addr, bssid, ETH_ALEN);
++	station->sta.mode = 0;
++	station->sta.sta.sta_id = i;
++	station->sta.station_flags = 0;
++
++#ifdef CONFIG_IWLWIFI_HT
++	if (is_ap) {
++		iwl4965_set_ht_add_station(priv, i);
++		iwl4965_set_rxon_chain(priv);
++	}
++#endif /*CONFIG_IWLWIFI_HT*/
++
++	priv->num_stations++;
++	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
++	iwl_send_add_station(priv, &station->sta, flags);
++	return i;
++
++ done:
++	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
++	return index;
++}
++
++/*************** DRIVER STATUS FUNCTIONS   *****/
++
++static inline int iwl_is_ready(struct iwl_priv *priv)
++{
++	/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
++	 * set but EXIT_PENDING is not */
++	return test_bit(STATUS_READY, &priv->status) &&
++	       test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
++	       !test_bit(STATUS_EXIT_PENDING, &priv->status);
++}
++
++static inline int iwl_is_alive(struct iwl_priv *priv)
++{
++	return test_bit(STATUS_ALIVE, &priv->status);
++}
 +
-+		rc = iwl_grab_restricted_access(priv);
-+		if (rc)
-+			goto exit_unlock;
++static inline int iwl_is_init(struct iwl_priv *priv)
++{
++	return test_bit(STATUS_INIT, &priv->status);
++}
 +
-+		iwl_write_restricted(priv, FH_RSCSR_CHNL0_WPTR,
-+				     q->write & ~0x7);
-+		iwl_release_restricted_access(priv);
-+	} else
-+		iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
++static inline int iwl_is_rfkill(struct iwl_priv *priv)
++{
++	return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++	       test_bit(STATUS_RF_KILL_SW, &priv->status);
++}
 +
++static inline int iwl_is_ready_rf(struct iwl_priv *priv)
++{
 +
-+	q->need_update = 0;
++	if (iwl_is_rfkill(priv))
++		return 0;
 +
-+ exit_unlock:
-+	spin_unlock_irqrestore(&q->lock, flags);
-+	return rc;
++	return iwl_is_ready(priv);
 +}
 +
-+/**
-+ * iwl_rx_queue_restock - refill RX queue from pre-allocated pool
-+ *
-+ * If there are slots in the RX queue that  need to be restocked,
-+ * and we have free pre-allocated buffers, fill the ranks as much
-+ * as we can pulling from rx_free.
-+ *
-+ * This moves the 'write' index forward to catch up with 'processed', and
-+ * also updates the memory address in the firmware to reference the new
-+ * target buffer.
-+ */
-+int iwl_rx_queue_restock(struct iwl_priv *priv)
-+{
-+	struct iwl_rx_queue *rxq = &priv->rxq;
-+	struct list_head *element;
-+	struct iwl_rx_mem_buffer *rxb;
-+	unsigned long flags;
-+	int write, rc;
++/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
 +
-+	spin_lock_irqsave(&rxq->lock, flags);
-+	write = rxq->write & ~0x7;
-+	while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
-+		element = rxq->rx_free.next;
-+		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-+		list_del(element);
-+		rxq->bd[rxq->write] =
-+		    iwl_dma_addr2rbd_ptr(priv, rxb->dma_addr);
-+		rxq->queue[rxq->write] = rxb;
-+		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
-+		rxq->free_count--;
-+	}
-+	spin_unlock_irqrestore(&rxq->lock, flags);
-+	/* If the pre-allocated buffer pool is dropping low, schedule to
-+	 * refill it */
-+	if (rxq->free_count <= RX_LOW_WATERMARK)
-+		queue_work(priv->workqueue, &priv->rx_replenish);
++#define IWL_CMD(x) case x : return #x
 +
++static const char *get_cmd_string(u8 cmd)
++{
++	switch (cmd) {
++		IWL_CMD(REPLY_ALIVE);
++		IWL_CMD(REPLY_ERROR);
++		IWL_CMD(REPLY_RXON);
++		IWL_CMD(REPLY_RXON_ASSOC);
++		IWL_CMD(REPLY_QOS_PARAM);
++		IWL_CMD(REPLY_RXON_TIMING);
++		IWL_CMD(REPLY_ADD_STA);
++		IWL_CMD(REPLY_REMOVE_STA);
++		IWL_CMD(REPLY_REMOVE_ALL_STA);
++		IWL_CMD(REPLY_TX);
++		IWL_CMD(REPLY_RATE_SCALE);
++		IWL_CMD(REPLY_LEDS_CMD);
++		IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
++		IWL_CMD(RADAR_NOTIFICATION);
++		IWL_CMD(REPLY_QUIET_CMD);
++		IWL_CMD(REPLY_CHANNEL_SWITCH);
++		IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
++		IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
++		IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
++		IWL_CMD(POWER_TABLE_CMD);
++		IWL_CMD(PM_SLEEP_NOTIFICATION);
++		IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
++		IWL_CMD(REPLY_SCAN_CMD);
++		IWL_CMD(REPLY_SCAN_ABORT_CMD);
++		IWL_CMD(SCAN_START_NOTIFICATION);
++		IWL_CMD(SCAN_RESULTS_NOTIFICATION);
++		IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
++		IWL_CMD(BEACON_NOTIFICATION);
++		IWL_CMD(REPLY_TX_BEACON);
++		IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
++		IWL_CMD(QUIET_NOTIFICATION);
++		IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
++		IWL_CMD(MEASURE_ABORT_NOTIFICATION);
++		IWL_CMD(REPLY_BT_CONFIG);
++		IWL_CMD(REPLY_STATISTICS_CMD);
++		IWL_CMD(STATISTICS_NOTIFICATION);
++		IWL_CMD(REPLY_CARD_STATE_CMD);
++		IWL_CMD(CARD_STATE_NOTIFICATION);
++		IWL_CMD(MISSED_BEACONS_NOTIFICATION);
++		IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
++		IWL_CMD(SENSITIVITY_CMD);
++		IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
++		IWL_CMD(REPLY_RX_PHY_CMD);
++		IWL_CMD(REPLY_RX_MPDU_CMD);
++		IWL_CMD(REPLY_4965_RX);
++		IWL_CMD(REPLY_COMPRESSED_BA);
++	default:
++		return "UNKNOWN";
 +
-+	/* If we've added more space for the firmware to place data, tell it */
-+	if ((write != (rxq->write & ~0x7))
-+	    || (abs(rxq->write - rxq->read) > 7)) {
-+		spin_lock_irqsave(&rxq->lock, flags);
-+		rxq->need_update = 1;
-+		spin_unlock_irqrestore(&rxq->lock, flags);
-+		rc = iwl_rx_queue_update_write_ptr(priv, rxq);
-+		if (rc)
-+			return rc;
 +	}
-+
-+	return 0;
 +}
 +
++#define HOST_COMPLETE_TIMEOUT (HZ / 2)
++
 +/**
-+ * iwl_rx_replensih - Move all used packet from rx_used to rx_free
-+ *
-+ * When moving to rx_free an SKB is allocated for the slot.
++ * iwl_enqueue_hcmd - enqueue a uCode command
++ * @priv: device private data point
++ * @cmd: a point to the ucode command structure
 + *
-+ * Also restock the Rx queue via iwl_rx_queue_restock.
-+ * This is called as a scheduled work item (except for during intialization)
++ * The function returns < 0 values to indicate the operation is
++ * failed. On success, it turns the index (> 0) of command in the
++ * command queue.
 + */
-+void iwl_rx_replenish(void *data)
++static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 +{
-+	struct iwl_priv *priv = data;
-+	struct iwl_rx_queue *rxq = &priv->rxq;
-+	struct list_head *element;
-+	struct iwl_rx_mem_buffer *rxb;
++	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
++	struct iwl_queue *q = &txq->q;
++	struct iwl_tfd_frame *tfd;
++	u32 *control_flags;
++	struct iwl_cmd *out_cmd;
++	u32 idx;
++	u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
++	dma_addr_t phys_addr;
++	int ret;
 +	unsigned long flags;
-+	spin_lock_irqsave(&rxq->lock, flags);
-+	while (!list_empty(&rxq->rx_used)) {
-+		element = rxq->rx_used.next;
-+		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-+		rxb->skb =
-+		    alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC);
-+		if (!rxb->skb) {
-+			if (net_ratelimit())
-+				printk(KERN_CRIT DRV_NAME
-+				       ": Can not allocate SKB buffers\n");
-+			/* We don't reschedule replenish work here -- we will
-+			 * call the restock method and if it still needs
-+			 * more buffers it will schedule replenish */
-+			break;
-+		}
-+		priv->alloc_rxb_skb++;
-+		list_del(element);
-+		rxb->dma_addr =
-+		    pci_map_single(priv->pci_dev, rxb->skb->data,
-+				   IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-+		list_add_tail(&rxb->list, &rxq->rx_free);
-+		rxq->free_count++;
-+	}
-+	spin_unlock_irqrestore(&rxq->lock, flags);
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	iwl_rx_queue_restock(priv);
-+	spin_unlock_irqrestore(&priv->lock, flags);
-+}
++	/* If any of the command structures end up being larger than
++	 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
++	 * we will need to increase the size of the TFD entries */
++	BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
++	       !(cmd->meta.flags & CMD_SIZE_HUGE));
 +
-+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
-+ * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
-+ * This free routine walks the list of POOL entries and if SKB is set to
-+ * non NULL it is unmapped and freed
-+ */
-+void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-+{
-+	int i;
-+	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
-+		if (rxq->pool[i].skb != NULL) {
-+			pci_unmap_single(priv->pci_dev,
-+					 rxq->pool[i].dma_addr,
-+					 IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-+			dev_kfree_skb(rxq->pool[i].skb);
-+		}
++	if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
++		IWL_ERROR("No space for Tx\n");
++		return -ENOSPC;
 +	}
 +
-+	pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-+			    rxq->dma_addr);
-+	rxq->bd = NULL;
-+}
-+
-+int iwl_rx_queue_alloc(struct iwl_priv *priv)
-+{
-+	struct iwl_rx_queue *rxq = &priv->rxq;
-+	struct pci_dev *dev = priv->pci_dev;
-+	int i;
-+
-+	spin_lock_init(&rxq->lock);
-+	INIT_LIST_HEAD(&rxq->rx_free);
-+	INIT_LIST_HEAD(&rxq->rx_used);
-+	rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
-+	if (!rxq->bd)
-+		return -ENOMEM;
-+	/* Fill the rx_used queue with _all_ of the Rx buffers */
-+	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
-+		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-+	/* Set us so that we have processed and used all buffers, but have
-+	 * not restocked the Rx queue with fresh buffers */
-+	rxq->read = rxq->write = 0;
-+	rxq->free_count = 0;
-+	rxq->need_update = 0;
-+	return 0;
-+}
++	spin_lock_irqsave(&priv->hcmd_lock, flags);
 +
-+void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-+{
-+	unsigned long flags;
-+	int i;
-+	spin_lock_irqsave(&rxq->lock, flags);
-+	INIT_LIST_HEAD(&rxq->rx_free);
-+	INIT_LIST_HEAD(&rxq->rx_used);
-+	/* Fill the rx_used queue with _all_ of the Rx buffers */
-+	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
-+		/* In the reset function, these buffers may have been allocated
-+		 * to an SKB, so we need to unmap and free potential storage */
-+		if (rxq->pool[i].skb != NULL) {
-+			pci_unmap_single(priv->pci_dev,
-+					 rxq->pool[i].dma_addr,
-+					 IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-+			priv->alloc_rxb_skb--;
-+			dev_kfree_skb(rxq->pool[i].skb);
-+			rxq->pool[i].skb = NULL;
-+		}
-+		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-+	}
++	tfd = &txq->bd[q->first_empty];
++	memset(tfd, 0, sizeof(*tfd));
 +
-+	/* Set us so that we have processed and used all buffers, but have
-+	 * not restocked the Rx queue with fresh buffers */
-+	rxq->read = rxq->write = 0;
-+	rxq->free_count = 0;
-+	spin_unlock_irqrestore(&rxq->lock, flags);
-+}
++	control_flags = (u32 *) tfd;
 +
-+/* Convert linear signal-to-noise ratio into dB */
-+static u8 ratio2dB[100] = {
-+/*	 0   1   2   3   4   5   6   7   8   9 */
-+	 0,  0,  6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
-+	20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
-+	26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
-+	29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
-+	32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
-+	34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
-+	36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
-+	37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
-+	38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
-+	39, 39, 39, 39, 39, 40, 40, 40, 40, 40  /* 90 - 99 */
-+};
++	idx = get_cmd_index(q, q->first_empty, cmd->meta.flags & CMD_SIZE_HUGE);
++	out_cmd = &txq->cmd[idx];
 +
-+/* Calculates a relative dB value from a ratio of linear
-+ *   (i.e. not dB) signal levels.
-+ * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
-+int iwl_calc_db_from_ratio(int sig_ratio)
-+{
-+	/* Anything above 1000:1 just report as 60 dB */
-+	if (sig_ratio > 1000)
-+		return 60;
++	out_cmd->hdr.cmd = cmd->id;
++	memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta));
++	memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
 +
-+	/* Above 100:1, divide by 10 and use table,
-+	 *   add 20 dB to make up for divide by 10 */
-+	if (sig_ratio > 100)
-+		return (20 + (int)ratio2dB[sig_ratio/10]);
++	/* At this point, the out_cmd now has all of the incoming cmd
++	 * information */
 +
-+	/* We shouldn't see this */
-+	if (sig_ratio < 1)
-+		return 0;
++	out_cmd->hdr.flags = 0;
++	out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
++			INDEX_TO_SEQ(q->first_empty));
++	if (out_cmd->meta.flags & CMD_SIZE_HUGE)
++		out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
 +
-+	/* Use table for ratios 1:1 - 99:1 */
-+	return (int)ratio2dB[sig_ratio];
-+}
++	phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
++			offsetof(struct iwl_cmd, hdr);
++	iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
 +
-+#define PERFECT_RSSI (-20) /* dBm */
-+#define WORST_RSSI (-95)   /* dBm */
-+#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
++	IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
++		     "%d bytes at %d[%d]:%d\n",
++		     get_cmd_string(out_cmd->hdr.cmd),
++		     out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
++		     fix_size, q->first_empty, idx, IWL_CMD_QUEUE_NUM);
 +
-+/* Calculate an indication of rx signal quality (a percentage, not dBm!).
-+ * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
-+ *   about formulas used below. */
-+int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
++	txq->need_update = 1;
++	ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0);
++	q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
++	iwl_tx_queue_update_write_ptr(priv, txq);
++
++	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
++	return ret ? ret : idx;
++}
++
++int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 +{
-+	int sig_qual;
-+	int degradation = PERFECT_RSSI - rssi_dbm;
++	int ret;
 +
-+	/* If we get a noise measurement, use signal-to-noise ratio (SNR)
-+	 * as indicator; formula is (signal dbm - noise dbm).
-+	 * SNR at or above 40 is a great signal (100%).
-+	 * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
-+	 * Weakest usable signal is usually 10 - 15 dB SNR. */
-+	if (noise_dbm) {
-+		if (rssi_dbm - noise_dbm >= 40)
-+			return 100;
-+		else if (rssi_dbm < noise_dbm)
-+			return 0;
-+		sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
++	BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
 +
-+	/* Else use just the signal level.
-+	 * This formula is a least squares fit of data points collected and
-+	 *   compared with a reference system that had a percentage (%) display
-+	 *   for signal quality. */
-+	} else
-+		sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
-+			    (15 * RSSI_RANGE + 62 * degradation)) /
-+			   (RSSI_RANGE * RSSI_RANGE);
++	/* An asynchronous command can not expect an SKB to be set. */
++	BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
 +
-+	if (sig_qual > 100)
-+		sig_qual = 100;
-+	else if (sig_qual < 1)
-+		sig_qual = 0;
++	/* An asynchronous command MUST have a callback. */
++	BUG_ON(!cmd->meta.u.callback);
 +
-+	return sig_qual;
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return -EBUSY;
++
++	ret = iwl_enqueue_hcmd(priv, cmd);
++	if (ret < 0) {
++		IWL_ERROR("Error sending %s: iwl_enqueue_hcmd failed: %d\n",
++			  get_cmd_string(cmd->id), ret);
++		return ret;
++	}
++	return 0;
 +}
 +
-+/**
-+ * iwl_rx_handle - Main entry function for receiving responses from the uCode
-+ *
-+ * Uses the priv->rx_handlers callback function array to invoke
-+ * the appropriate handlers, including command responses,
-+ * frame-received notifications, and other notifications.
-+ */
-+static void iwl_rx_handle(struct iwl_priv *priv)
++int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 +{
-+	struct iwl_rx_mem_buffer *rxb;
-+	struct iwl_rx_packet *pkt;
-+	struct iwl_rx_queue *rxq = &priv->rxq;
-+	u32 r, i;
-+	int reclaim;
-+	unsigned long flags;
++	int cmd_idx;
++	int ret;
++	static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
 +
-+	r = iwl_hw_get_rx_read(priv);
-+	i = rxq->read;
++	BUG_ON(cmd->meta.flags & CMD_ASYNC);
 +
-+	/* Rx interrupt, but nothing sent from uCode */
-+	if (i == r)
-+		IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
++	 /* A synchronous command can not have a callback set. */
++	BUG_ON(cmd->meta.u.callback != NULL);
 +
-+	while (i != r) {
-+		rxb = rxq->queue[i];
++	if (atomic_xchg(&entry, 1)) {
++		IWL_ERROR("Error sending %s: Already sending a host command\n",
++			  get_cmd_string(cmd->id));
++		return -EBUSY;
++	}
 +
-+		/* If an RXB doesn't have a queue slot associated with it
-+		 * then a bug has been introduced in the queue refilling
-+		 * routines -- catch it here */
-+		BUG_ON(rxb == NULL);
++	set_bit(STATUS_HCMD_ACTIVE, &priv->status);
 +
-+		rxq->queue[i] = NULL;
++	if (cmd->meta.flags & CMD_WANT_SKB)
++		cmd->meta.source = &cmd->meta;
 +
-+		pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
-+					    IWL_RX_BUF_SIZE,
-+					    PCI_DMA_FROMDEVICE);
-+		pkt = (struct iwl_rx_packet *)rxb->skb->data;
++	cmd_idx = iwl_enqueue_hcmd(priv, cmd);
++	if (cmd_idx < 0) {
++		ret = cmd_idx;
++		IWL_ERROR("Error sending %s: iwl_enqueue_hcmd failed: %d\n",
++			  get_cmd_string(cmd->id), ret);
++		goto out;
++	}
 +
-+		/* Reclaim a command buffer only if this packet is a response
-+		 *   to a (driver-originated) command.
-+		 * If the packet (e.g. Rx frame) originated from uCode,
-+		 *   there is no command buffer to reclaim.
-+		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
-+		 *   but apparently a few don't get set; catch them here. */
-+		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
-+#if IWL == 4965
-+			(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
-+			(pkt->hdr.cmd != REPLY_4965_RX) &&
-+#endif
-+			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
-+			(pkt->hdr.cmd != REPLY_TX);
++	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
++			!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
++			HOST_COMPLETE_TIMEOUT);
++	if (!ret) {
++		if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
++			IWL_ERROR("Error sending %s: time out after %dms.\n",
++				  get_cmd_string(cmd->id),
++				  jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
 +
-+		/* Based on type of command response or notification,
-+		 *   handle those that need handling via function in
-+		 *   rx_handlers table.  See iwl_setup_rx_handlers() */
-+		if (priv->rx_handlers[pkt->hdr.cmd]) {
-+			IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
-+				"r = %d, i = %d, %s, 0x%02x\n", r, i,
-+				get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
-+			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
-+		} else {
-+			/* No handling needed */
-+			IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
-+				"r %d i %d No handler needed for %s, 0x%02x\n",
-+				r, i, get_cmd_string(pkt->hdr.cmd),
-+				pkt->hdr.cmd);
++			clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
++			ret = -ETIMEDOUT;
++			goto cancel;
 +		}
++	}
 +
-+		if (reclaim) {
-+			/* Invoke any callbacks, transfer the skb to caller,
-+			 * and fire off the (possibly) blocking iwl_send_cmd()
-+			 * as we reclaim the driver command queue */
-+			if (rxb && rxb->skb)
-+				iwl_tx_cmd_complete(priv, rxb);
-+			else
-+				IWL_WARNING("Claim null rxb?\n");
-+		}
++	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
++		IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
++			       get_cmd_string(cmd->id));
++		ret = -ECANCELED;
++		goto fail;
++	}
++	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
++		IWL_DEBUG_INFO("Command %s failed: FW Error\n",
++			       get_cmd_string(cmd->id));
++		ret = -EIO;
++		goto fail;
++	}
++	if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
++		IWL_ERROR("Error: Response NULL in '%s'\n",
++			  get_cmd_string(cmd->id));
++		ret = -EIO;
++		goto out;
++	}
++
++	ret = 0;
++	goto out;
++
++cancel:
++	if (cmd->meta.flags & CMD_WANT_SKB) {
++		struct iwl_cmd *qcmd;
++
++		/* Cancel the CMD_WANT_SKB flag for the cmd in the
++		 * TX cmd queue. Otherwise in case the cmd comes
++		 * in later, it will possibly set an invalid
++		 * address (cmd->meta.source). */
++		qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
++		qcmd->meta.flags &= ~CMD_WANT_SKB;
++	}
++fail:
++	if (cmd->meta.u.skb) {
++		dev_kfree_skb_any(cmd->meta.u.skb);
++		cmd->meta.u.skb = NULL;
++	}
++out:
++	atomic_set(&entry, 0);
++	return ret;
++}
++
++int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++	/* A command can not be asynchronous AND expect an SKB to be set. */
++	BUG_ON((cmd->meta.flags & CMD_ASYNC) &&
++	       (cmd->meta.flags & CMD_WANT_SKB));
 +
-+		/* For now we just don't re-use anything.  We can tweak this
-+		 * later to try and re-use notification packets and SKBs that
-+		 * fail to Rx correctly */
-+		if (rxb->skb != NULL) {
-+			priv->alloc_rxb_skb--;
-+			dev_kfree_skb_any(rxb->skb);
-+			rxb->skb = NULL;
-+		}
++	if (cmd->meta.flags & CMD_ASYNC)
++		return iwl_send_cmd_async(priv, cmd);
 +
-+		pci_unmap_single(priv->pci_dev, rxb->dma_addr,
-+				 IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-+		spin_lock_irqsave(&rxq->lock, flags);
-+		list_add_tail(&rxb->list, &priv->rxq.rx_used);
-+		spin_unlock_irqrestore(&rxq->lock, flags);
-+		i = (i + 1) & RX_QUEUE_MASK;
-+	}
++	return iwl_send_cmd_sync(priv, cmd);
++}
 +
-+	/* Backtrack one entry */
-+	priv->rxq.read = i;
-+	iwl_rx_queue_restock(priv);
++int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
++{
++	struct iwl_host_cmd cmd = {
++		.id = id,
++		.len = len,
++		.data = data,
++	};
++
++	return iwl_send_cmd_sync(priv, &cmd);
 +}
 +
-+int iwl_tx_queue_update_write_ptr(struct iwl_priv *priv,
-+				  struct iwl_tx_queue *txq)
++static int __must_check iwl_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val)
 +{
-+	u32 reg = 0;
-+	int rc = 0;
-+	int txq_id = txq->q.id;
++	struct iwl_host_cmd cmd = {
++		.id = id,
++		.len = sizeof(val),
++		.data = &val,
++	};
 +
-+	if (txq->need_update == 0)
-+		return rc;
++	return iwl_send_cmd_sync(priv, &cmd);
++}
 +
-+	/* if we're trying to save power */
-+	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-+		/* wake up nic if it's powered down ...
-+		 * uCode will wake up, and interrupt us again, so next
-+		 * time we'll skip this part. */
-+		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
++int iwl_send_statistics_request(struct iwl_priv *priv)
++{
++	return iwl_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
++}
 +
-+		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-+			IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
-+			iwl_set_bit(priv, CSR_GP_CNTRL,
-+				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-+			return rc;
-+		}
++/**
++ * iwl_rxon_add_station - add station into station table.
++ *
++ * there is only one AP station with id= IWL_AP_ID
++ * NOTE: mutex must be held before calling the this fnction
++*/
++static int iwl_rxon_add_station(struct iwl_priv *priv,
++				const u8 *addr, int is_ap)
++{
++	u8 rc;
 +
-+		/* restore this queue's parameters in nic hardware. */
-+		rc = iwl_grab_restricted_access(priv);
-+		if (rc)
-+			return rc;
-+		iwl_write_restricted(priv, HBUS_TARG_WRPTR,
-+				     txq->q.first_empty | (txq_id << 8));
-+		iwl_release_restricted_access(priv);
++	/* Remove this station if it happens to already exist */
++	iwl_remove_station(priv, addr, is_ap);
 +
-+	/* else not in power-save mode, uCode will never sleep when we're
-+	 * trying to tx (during RFKILL, we're not trying to tx). */
-+	} else
-+		iwl_write32(priv, HBUS_TARG_WRPTR,
-+			    txq->q.first_empty | (txq_id << 8));
++	rc = iwl_add_station(priv, addr, is_ap, 0);
 +
-+	txq->need_update = 0;
++	iwl4965_add_station(priv, addr, is_ap);
 +
 +	return rc;
 +}
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static void iwl_print_rx_config_cmd(struct iwl_rxon_cmd *rxon)
-+{
-+	IWL_DEBUG_RADIO("RX CONFIG:\n");
-+	iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
-+	IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
-+	IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
-+	IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
-+			le32_to_cpu(rxon->filter_flags));
-+	IWL_DEBUG_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type);
-+	IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
-+			rxon->ofdm_basic_rates);
-+	IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
-+	IWL_DEBUG_RADIO("u8[6] node_addr: " MAC_FMT "\n",
-+			MAC_ARG(rxon->node_addr));
-+	IWL_DEBUG_RADIO("u8[6] bssid_addr: " MAC_FMT "\n",
-+			MAC_ARG(rxon->bssid_addr));
-+	IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
-+}
-+#endif
++/**
++ * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
++ * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
++ * @channel: Any channel valid for the requested phymode
 +
-+static void iwl_enable_interrupts(struct iwl_priv *priv)
++ * In addition to setting the staging RXON, priv->phymode is also set.
++ *
++ * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
++ * in the staging RXON flag structure based on the phymode
++ */
++static int iwl_set_rxon_channel(struct iwl_priv *priv, u8 phymode, u16 channel)
 +{
-+	IWL_DEBUG_ISR("Enabling interrupts\n");
-+	set_bit(STATUS_INT_ENABLED, &priv->status);
-+	iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
++	if (!iwl_get_channel_info(priv, phymode, channel)) {
++		IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
++			       channel, phymode);
++		return -EINVAL;
++	}
++
++	if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
++	    (priv->phymode == phymode))
++		return 0;
++
++	priv->staging_rxon.channel = cpu_to_le16(channel);
++	if (phymode == MODE_IEEE80211A)
++		priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
++	else
++		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
++
++	priv->phymode = phymode;
++
++	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
++
++	return 0;
 +}
 +
-+static inline void iwl_disable_interrupts(struct iwl_priv *priv)
++/**
++ * iwl_check_rxon_cmd - validate RXON structure is valid
++ *
++ * NOTE:  This is really only useful during development and can eventually
++ * be #ifdef'd out once the driver is stable and folks aren't actively
++ * making changes
++ */
++static int iwl_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
 +{
-+	clear_bit(STATUS_INT_ENABLED, &priv->status);
++	int error = 0;
++	int counter = 1;
 +
-+	/* disable interrupts from uCode/NIC to host */
-+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
++	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
++		error |= le32_to_cpu(rxon->flags &
++				(RXON_FLG_TGJ_NARROW_BAND_MSK |
++				 RXON_FLG_RADAR_DETECT_MSK));
++		if (error)
++			IWL_WARNING("check 24G fields %d | %d\n",
++				    counter++, error);
++	} else {
++		error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
++				0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
++		if (error)
++			IWL_WARNING("check 52 fields %d | %d\n",
++				    counter++, error);
++		error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
++		if (error)
++			IWL_WARNING("check 52 CCK %d | %d\n",
++				    counter++, error);
++	}
++	error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
++	if (error)
++		IWL_WARNING("check mac addr %d | %d\n", counter++, error);
 +
-+	/* acknowledge/clear/reset any interrupts still pending
-+	 * from uCode or flow handler (Rx/Tx DMA) */
-+	iwl_write32(priv, CSR_INT, 0xffffffff);
-+	iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
-+	IWL_DEBUG_ISR("Disabled interrupts\n");
++	/* make sure basic rates 6Mbps and 1Mbps are supported */
++	error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
++		  ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
++	if (error)
++		IWL_WARNING("check basic rate %d | %d\n", counter++, error);
++
++	error |= (le16_to_cpu(rxon->assoc_id) > 2007);
++	if (error)
++		IWL_WARNING("check assoc id %d | %d\n", counter++, error);
++
++	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
++			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
++	if (error)
++		IWL_WARNING("check CCK and short slot %d | %d\n",
++			    counter++, error);
++
++	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
++			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
++	if (error)
++		IWL_WARNING("check CCK & auto detect %d | %d\n",
++			    counter++, error);
++
++	error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
++			RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
++	if (error)
++		IWL_WARNING("check TGG and auto detect %d | %d\n",
++			    counter++, error);
++
++	if (error)
++		IWL_WARNING("Tuning to channel %d\n",
++			    le16_to_cpu(rxon->channel));
++
++	if (error) {
++		IWL_ERROR("Not a valid iwl_rxon_assoc_cmd field values\n");
++		return -1;
++	}
++	return 0;
 +}
 +
-+static const char *desc_lookup(int i)
++/**
++ * iwl_full_rxon_required - determine if RXON_ASSOC can be used in RXON commit
++ * @priv: staging_rxon is comapred to active_rxon
++ *
++ * If the RXON structure is changing sufficient to require a new
++ * tune or to clear and reset the RXON_FILTER_ASSOC_MSK then return 1
++ * to indicate a new tune is required.
++ */
++static int iwl_full_rxon_required(struct iwl_priv *priv)
 +{
-+	switch (i) {
-+	case 1:
-+		return "FAIL";
-+	case 2:
-+		return "BAD_PARAM";
-+	case 3:
-+		return "BAD_CHECKSUM";
-+	case 4:
-+		return "NMI_INTERRUPT";
-+	case 5:
-+		return "SYSASSERT";
-+	case 6:
-+		return "FATAL_ERROR";
-+	}
 +
-+	return "UNKNOWN";
-+}
++	/* These items are only settable from the full RXON command */
++	if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ||
++	    compare_ether_addr(priv->staging_rxon.bssid_addr,
++			       priv->active_rxon.bssid_addr) ||
++	    compare_ether_addr(priv->staging_rxon.node_addr,
++			       priv->active_rxon.node_addr) ||
++	    compare_ether_addr(priv->staging_rxon.wlap_bssid_addr,
++			       priv->active_rxon.wlap_bssid_addr) ||
++	    (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) ||
++	    (priv->staging_rxon.channel != priv->active_rxon.channel) ||
++	    (priv->staging_rxon.air_propagation !=
++	     priv->active_rxon.air_propagation) ||
++	    (priv->staging_rxon.ofdm_ht_single_stream_basic_rates !=
++	     priv->active_rxon.ofdm_ht_single_stream_basic_rates) ||
++	    (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates !=
++	     priv->active_rxon.ofdm_ht_dual_stream_basic_rates) ||
++	    (priv->staging_rxon.rx_chain != priv->active_rxon.rx_chain) ||
++	    (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
++		return 1;
++
++	/* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can
++	 * be updated with the RXON_ASSOC command -- however only some
++	 * flag transitions are allowed using RXON_ASSOC */
 +
-+#define ERROR_START_OFFSET  (1 * sizeof(u32))
-+#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
++	/* Check if we are not switching bands */
++	if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) !=
++	    (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK))
++		return 1;
 +
-+static void iwl_dump_nic_error_log(struct iwl_priv *priv)
-+{
-+#if IWL == 3945
-+	u32 i;
-+#else /* IWL == 4965 */
-+	u32 data2, line;
-+#endif
-+	u32 desc, time, count, base, data1;
-+	u32 blink1, blink2, ilink1, ilink2;
-+	int rc;
++	/* Check if we are switching association toggle */
++	if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) !=
++		(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK))
++		return 1;
 +
-+	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
++	return 0;
++}
 +
-+	if (!iwl_hw_valid_rtc_data_addr(base)) {
-+		IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
-+		return;
-+	}
++static int iwl_send_rxon_assoc(struct iwl_priv *priv)
++{
++	int rc = 0;
++	struct iwl_rx_packet *res = NULL;
++	struct iwl_rxon_assoc_cmd rxon_assoc;
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_RXON_ASSOC,
++		.len = sizeof(rxon_assoc),
++		.meta.flags = CMD_WANT_SKB,
++		.data = &rxon_assoc,
++	};
++	const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
++	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
 +
-+	rc = iwl_grab_restricted_access(priv);
-+	if (rc) {
-+		IWL_WARNING("Can not read from adapter at this time.\n");
-+		return;
++	if ((rxon1->flags == rxon2->flags) &&
++	    (rxon1->filter_flags == rxon2->filter_flags) &&
++	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
++	    (rxon1->ofdm_ht_single_stream_basic_rates ==
++	     rxon2->ofdm_ht_single_stream_basic_rates) &&
++	    (rxon1->ofdm_ht_dual_stream_basic_rates ==
++	     rxon2->ofdm_ht_dual_stream_basic_rates) &&
++	    (rxon1->rx_chain == rxon2->rx_chain) &&
++	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
++		IWL_DEBUG_INFO("Using current RXON_ASSOC.  Not resending.\n");
++		return 0;
 +	}
 +
-+	count = iwl_read_restricted_mem(priv, base);
-+
-+	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
-+		IWL_ERROR("Start IWL Error Log Dump:\n");
-+		IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n",
-+			  priv->status, priv->config, count);
-+	}
++	rxon_assoc.flags = priv->staging_rxon.flags;
++	rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
++	rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
++	rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
++	rxon_assoc.reserved = 0;
++	rxon_assoc.ofdm_ht_single_stream_basic_rates =
++	    priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
++	rxon_assoc.ofdm_ht_dual_stream_basic_rates =
++	    priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
++	rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
 +
-+#if IWL == 3945
-+	IWL_ERROR("Desc       Time       asrtPC  blink2 "
-+		  "ilink1  nmiPC   Line\n");
-+	for (i = ERROR_START_OFFSET;
-+	     i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
-+	     i += ERROR_ELEM_SIZE) {
-+		desc = iwl_read_restricted_mem(priv, base + i);
-+		time =
-+		    iwl_read_restricted_mem(priv, base + i + 1 * sizeof(u32));
-+		blink1 =
-+		    iwl_read_restricted_mem(priv, base + i + 2 * sizeof(u32));
-+		blink2 =
-+		    iwl_read_restricted_mem(priv, base + i + 3 * sizeof(u32));
-+		ilink1 =
-+		    iwl_read_restricted_mem(priv, base + i + 4 * sizeof(u32));
-+		ilink2 =
-+		    iwl_read_restricted_mem(priv, base + i + 5 * sizeof(u32));
-+		data1 =
-+		    iwl_read_restricted_mem(priv, base + i + 6 * sizeof(u32));
++	rc = iwl_send_cmd_sync(priv, &cmd);
++	if (rc)
++		return rc;
 +
-+		IWL_ERROR
-+		    ("%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
-+		     desc_lookup(desc), desc, time, blink1, blink2,
-+		     ilink1, ilink2, data1);
++	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
++	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
++		IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n");
++		rc = -EIO;
 +	}
-+#else  /* 4965 Error format */
-+	desc = iwl_read_restricted_mem(priv, base + 1 * sizeof(u32));
-+	blink1 = iwl_read_restricted_mem(priv, base + 3 * sizeof(u32));
-+	blink2 = iwl_read_restricted_mem(priv, base + 4 * sizeof(u32));
-+	ilink1 = iwl_read_restricted_mem(priv, base + 5 * sizeof(u32));
-+	ilink2 = iwl_read_restricted_mem(priv, base + 6 * sizeof(u32));
-+	data1 = iwl_read_restricted_mem(priv, base + 7 * sizeof(u32));
-+	data2 = iwl_read_restricted_mem(priv, base + 8 * sizeof(u32));
-+	line = iwl_read_restricted_mem(priv, base + 9 * sizeof(u32));
-+	time = iwl_read_restricted_mem(priv, base + 11 * sizeof(u32));
-+
-+	IWL_ERROR("Desc               Time       "
-+		  "data1      data2      line\n");
-+	IWL_ERROR
-+	    ("%-13s (#%d) %010u 0x%08X 0x%08X %u\n",
-+	     desc_lookup(desc), desc, time, data1, data2, line);
-+	IWL_ERROR("blink1  blink2  ilink1  ilink2\n");
-+	IWL_ERROR
-+	    ("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, ilink1, ilink2);
 +
-+#endif  /* IWL 3945 */
-+
-+	iwl_release_restricted_access(priv);
++	priv->alloc_rxb_skb--;
++	dev_kfree_skb_any(cmd.meta.u.skb);
 +
++	return rc;
 +}
 +
-+#define EVENT_START_OFFSET  (4 * sizeof(u32))
-+
 +/**
-+ * iwl_print_event_log - Dump error event log to syslog
++ * iwl_commit_rxon - commit staging_rxon to hardware
 + *
-+ * NOTE: Must be called with iwl_grab_restricted_access() already obtained!
++ * The RXON command in staging_rxon is commited to the hardware and
++ * the active_rxon structure is updated with the new data.  This
++ * function correctly transitions out of the RXON_ASSOC_MSK state if
++ * a HW tune is required based on the RXON structure changes.
 + */
-+static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
-+				u32 num_events, u32 mode)
++static int iwl_commit_rxon(struct iwl_priv *priv)
 +{
-+	u32 i;
-+	u32 base;       /* SRAM byte address of event log header */
-+	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
-+	u32 ptr;        /* SRAM byte address of log data */
-+	u32 ev, time, data; /* event log data */
-+
-+	if (num_events == 0)
-+		return;
++	/* cast away the const for active_rxon in this function */
++	struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
++	int rc = 0;
 +
-+	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
++	if (!iwl_is_alive(priv))
++		return -1;
 +
-+	if (mode == 0)
-+		event_size = 2 * sizeof(u32);
-+	else
-+		event_size = 3 * sizeof(u32);
++	/* always get timestamp with Rx frame */
++	priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
 +
-+	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
++	rc = iwl_check_rxon_cmd(&priv->staging_rxon);
++	if (rc) {
++		IWL_ERROR("Invalid RXON configuration.  Not committing.\n");
++		return -EINVAL;
++	}
 +
-+	/* "time" is actually "data" for mode 0 (no timestamp).
-+	 * place event id # at far right for easier visual parsing. */
-+	for (i = 0; i < num_events; i++) {
-+		ev = iwl_read_restricted_mem(priv, ptr);
-+		ptr += sizeof(u32);
-+		time = iwl_read_restricted_mem(priv, ptr);
-+		ptr += sizeof(u32);
-+		if (mode == 0)
-+			IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
-+		else {
-+			data = iwl_read_restricted_mem(priv, ptr);
-+			ptr += sizeof(u32);
-+			IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
++	/* If we don't need to send a full RXON, we can use
++	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
++	 * and other flags for the current radio configuration. */
++	if (!iwl_full_rxon_required(priv)) {
++		rc = iwl_send_rxon_assoc(priv);
++		if (rc) {
++			IWL_ERROR("Error setting RXON_ASSOC "
++				  "configuration (%d).\n", rc);
++			return rc;
 +		}
-+	}
-+}
 +
-+static void iwl_dump_nic_event_log(struct iwl_priv *priv)
-+{
-+	int rc;
-+	u32 base;       /* SRAM byte address of event log header */
-+	u32 capacity;   /* event log capacity in # entries */
-+	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-+	u32 num_wraps;  /* # times uCode wrapped to top of log */
-+	u32 next_entry; /* index of next entry to be written by uCode */
-+	u32 size;       /* # entries that we'll print */
++		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
 +
-+	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-+	if (!iwl_hw_valid_rtc_data_addr(base)) {
-+		IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
-+		return;
++		return 0;
 +	}
 +
-+	rc = iwl_grab_restricted_access(priv);
-+	if (rc) {
-+		IWL_WARNING("Can not read from adapter at this time.\n");
-+		return;
-+	}
++	/* station table will be cleared */
++	priv->assoc_station_added = 0;
 +
-+	/* event log header */
-+	capacity = iwl_read_restricted_mem(priv, base);
-+	mode = iwl_read_restricted_mem(priv, base + (1 * sizeof(u32)));
-+	num_wraps = iwl_read_restricted_mem(priv, base + (2 * sizeof(u32)));
-+	next_entry = iwl_read_restricted_mem(priv, base + (3 * sizeof(u32)));
++#ifdef CONFIG_IWLWIFI_SENSITIVITY
++	priv->sensitivity_data.state = IWL_SENS_CALIB_NEED_REINIT;
++	if (!priv->error_recovering)
++		priv->start_calib = 0;
 +
-+	size = num_wraps ? capacity : next_entry;
++	iwl4965_init_sensitivity(priv, CMD_ASYNC, 1);
++#endif /* CONFIG_IWLWIFI_SENSITIVITY */
 +
-+	/* bail out if nothing in log */
-+	if (size == 0) {
-+		IWL_ERROR("Start IPW Event Log Dump: nothing in log\n");
-+		iwl_release_restricted_access(priv);
-+		return;
++	/* If we are currently associated and the new config requires
++	 * an RXON_ASSOC and the new config wants the associated mask enabled,
++	 * we must clear the associated from the active configuration
++	 * before we apply the new config */
++	if (iwl_is_associated(priv) &&
++	    (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
++		IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
++		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++
++		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
++				      sizeof(struct iwl_rxon_cmd),
++				      &priv->active_rxon);
++
++		/* If the mask clearing failed then we set
++		 * active_rxon back to what it was previously */
++		if (rc) {
++			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
++			IWL_ERROR("Error clearing ASSOC_MSK on current "
++				  "configuration (%d).\n", rc);
++			return rc;
++		}
++
++		/* The RXON bit toggling will have cleared out the
++		 * station table in the uCode, so blank it in the driver
++		 * as well */
++		iwl_clear_stations_table(priv);
++	} else if (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) {
++		/* When switching from non-associated to associated, the
++		 * uCode clears out the station table; so clear it in the
++		 * driver as well */
++		iwl_clear_stations_table(priv);
 +	}
 +
-+	IWL_ERROR("Start IPW Event Log Dump: display count %d, wraps %d\n",
-+		  size, num_wraps);
-+
-+	/* if uCode has wrapped back to top of log, start at the oldest entry,
-+	 * i.e the next one that uCode would fill. */
-+	if (num_wraps)
-+		iwl_print_event_log(priv, next_entry,
-+				    capacity - next_entry, mode);
++	IWL_DEBUG_INFO("Sending RXON\n"
++		       "* with%s RXON_FILTER_ASSOC_MSK\n"
++		       "* channel = %d\n"
++		       "* bssid = " MAC_FMT "\n",
++		       ((priv->staging_rxon.filter_flags &
++			 RXON_FILTER_ASSOC_MSK) ? "" : "out"),
++		       le16_to_cpu(priv->staging_rxon.channel),
++		       MAC_ARG(priv->staging_rxon.bssid_addr));
 +
-+	/* (then/else) start at top of log */
-+	iwl_print_event_log(priv, 0, next_entry, mode);
++	/* Apply the new configuration */
++	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
++			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
++	if (rc) {
++		IWL_ERROR("Error setting new configuration (%d).\n", rc);
++		return rc;
++	}
 +
-+	iwl_release_restricted_access(priv);
-+}
++#ifdef CONFIG_IWLWIFI_SENSITIVITY
++	if (!priv->error_recovering)
++		priv->start_calib = 0;
 +
-+/**
-+ * iwl_irq_handle_error - called for HW or SW error interrupt from card
-+ */
-+static void iwl_irq_handle_error(struct iwl_priv *priv)
-+{
-+	/* Set the FW error flag -- cleared on iwl_down */
-+	set_bit(STATUS_FW_ERROR, &priv->status);
++	priv->sensitivity_data.state = IWL_SENS_CALIB_NEED_REINIT;
++	iwl4965_init_sensitivity(priv, CMD_ASYNC, 1);
++#endif /* CONFIG_IWLWIFI_SENSITIVITY */
 +
-+	/* Cancel currently queued command. */
-+	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
++	memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	if (iwl_debug_level & IWL_DL_FW_ERRORS) {
-+		iwl_dump_nic_error_log(priv);
-+		iwl_dump_nic_event_log(priv);
-+		iwl_print_rx_config_cmd(&priv->staging_rxon);
++	/* If we issue a new RXON command which required a tune then we must
++	 * send a new TXPOWER command or we won't be able to Tx any frames */
++	rc = iwl_hw_reg_send_txpower(priv);
++	if (rc) {
++		IWL_ERROR("Error setting Tx power (%d).\n", rc);
++		return rc;
 +	}
-+#endif
-+
-+	wake_up_interruptible(&priv->wait_command_queue);
 +
-+	/* Keep the restart process from trying to send host
-+	 * commands by clearing the INIT status bit */
-+	clear_bit(STATUS_READY, &priv->status);
-+
-+	if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-+		IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS,
-+			  "Restarting adapter due to uCode error.\n");
++	/* Add the broadcast address so we can send broadcast frames */
++	if (iwl_rxon_add_station(priv, BROADCAST_ADDR, 0) ==
++	    IWL_INVALID_STATION) {
++		IWL_ERROR("Error adding BROADCAST address for transmit.\n");
++		return -EIO;
++	}
 +
-+		if (iwl_is_associated(priv)) {
-+			memcpy(&priv->recovery_rxon, &priv->active_rxon,
-+			       sizeof(priv->recovery_rxon));
-+			priv->error_recovering = 1;
++	/* If we have set the ASSOC_MSK and we are in BSS mode then
++	 * add the IWL_AP_ID to the station rate table */
++	if (iwl_is_associated(priv) &&
++	    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
++		if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
++		    == IWL_INVALID_STATION) {
++			IWL_ERROR("Error adding AP address for transmit.\n");
++			return -EIO;
 +		}
-+		queue_work(priv->workqueue, &priv->restart);
++		priv->assoc_station_added = 1;
 +	}
++
++	return 0;
 +}
 +
-+static void iwl_error_recovery(struct iwl_priv *priv)
++static int iwl_send_bt_config(struct iwl_priv *priv)
 +{
-+	unsigned long flags;
-+
-+	memcpy(&priv->staging_rxon, &priv->recovery_rxon,
-+	       sizeof(priv->staging_rxon));
-+	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-+	iwl_commit_rxon(priv);
-+
-+	iwl_rxon_add_station(priv, priv->bssid, 1);
++	struct iwl_bt_cmd bt_cmd = {
++		.flags = 3,
++		.lead_time = 0xAA,
++		.max_kill = 1,
++		.kill_ack_mask = 0,
++		.kill_cts_mask = 0,
++	};
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
-+	priv->error_recovering = 0;
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
++				sizeof(struct iwl_bt_cmd), &bt_cmd);
 +}
 +
-+static void iwl_irq_tasklet(struct iwl_priv *priv)
++static int iwl_send_scan_abort(struct iwl_priv *priv)
 +{
-+	u32 inta, handled = 0;
-+	u32 inta_fh;
-+	unsigned long flags;
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	u32 inta_mask;
-+#endif
-+
-+	spin_lock_irqsave(&priv->lock, flags);
-+
-+	/* Ack/clear/reset pending uCode interrupts.
-+	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
-+	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
-+	inta = iwl_read32(priv, CSR_INT);
-+	iwl_write32(priv, CSR_INT, inta);
++	int rc = 0;
++	struct iwl_rx_packet *res;
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_SCAN_ABORT_CMD,
++		.meta.flags = CMD_WANT_SKB,
++	};
 +
-+	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
-+	 * Any new interrupts that happen after this, either while we're
-+	 * in this tasklet, or later, will show up in next ISR/tasklet. */
-+	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-+	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
++	/* If there isn't a scan actively going on in the hardware
++	 * then we are in between scan bands and not actually
++	 * actively scanning, so don't send the abort command */
++	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
++		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
++		return 0;
++	}
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	if (iwl_debug_level & IWL_DL_ISR) {
-+		inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
-+		IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-+			      inta, inta_mask, inta_fh);
++	rc = iwl_send_cmd_sync(priv, &cmd);
++	if (rc) {
++		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
++		return rc;
 +	}
-+#endif
 +
-+	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
-+	 * atomic, make sure that inta covers all the interrupts that
-+	 * we've discovered, even if FH interrupt came in just after
-+	 * reading CSR_INT. */
-+	if (inta_fh & FH_INT_RX_MASK)
-+		inta |= BIT_INT_FH_RX;
-+	if (inta_fh & FH_INT_TX_MASK)
-+		inta |= BIT_INT_FH_TX;
++	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
++	if (res->u.status != CAN_ABORT_STATUS) {
++		/* The scan abort will return 1 for success or
++		 * 2 for "failure".  A failure condition can be
++		 * due to simply not being in an active scan which
++		 * can occur if we send the scan abort before we
++		 * the microcode has notified us that a scan is
++		 * completed. */
++		IWL_DEBUG_INFO("SCAN_ABORT returned %d.\n", res->u.status);
++		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
++		clear_bit(STATUS_SCAN_HW, &priv->status);
++	}
 +
-+	/* Now service all interrupt bits discovered above. */
-+	if (inta & BIT_INT_ERR) {
-+		IWL_ERROR("Microcode HW error detected.  Restarting.\n");
++	dev_kfree_skb_any(cmd.meta.u.skb);
 +
-+		/* Tell the device to stop sending interrupts */
-+		iwl_disable_interrupts(priv);
++	return rc;
++}
 +
-+		iwl_irq_handle_error(priv);
++static int iwl_card_state_sync_callback(struct iwl_priv *priv,
++					struct iwl_cmd *cmd,
++					struct sk_buff *skb)
++{
++	return 1;
++}
 +
-+		handled |= BIT_INT_ERR;
++/*
++ * CARD_STATE_CMD
++ *
++ * Use: Sets the internal card state to enable, disable, or halt
++ *
++ * When in the 'enable' state the card operates as normal.
++ * When in the 'disable' state, the card enters into a low power mode.
++ * When in the 'halt' state, the card is shut down and must be fully
++ * restarted to come back on.
++ */
++static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
++{
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_CARD_STATE_CMD,
++		.len = sizeof(u32),
++		.data = &flags,
++		.meta.flags = meta_flag,
++	};
 +
-+		spin_unlock_irqrestore(&priv->lock, flags);
++	if (meta_flag & CMD_ASYNC)
++		cmd.meta.u.callback = iwl_card_state_sync_callback;
 +
-+		return;
-+	}
++	return iwl_send_cmd(priv, &cmd);
++}
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	if (iwl_debug_level & (IWL_DL_ISR)) {
-+		/* NIC fires this, but we don't use it, redundant with WAKEUP */
-+		if (inta & BIT_INT_MAC_CLK_ACTV)
-+			IWL_DEBUG_ISR("Microcode started or stopped.\n");
++static int iwl_add_sta_sync_callback(struct iwl_priv *priv,
++				     struct iwl_cmd *cmd, struct sk_buff *skb)
++{
++	struct iwl_rx_packet *res = NULL;
 +
-+		/* Alive notification via Rx interrupt will do the real work */
-+		if (inta & BIT_INT_ALIVE)
-+			IWL_DEBUG_ISR("Alive interrupt\n");
++	if (!skb) {
++		IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
++		return 1;
 +	}
-+#endif
-+	/* Safely ignore these bits for debug checks below */
-+	inta &= ~(BIT_INT_MAC_CLK_ACTV | BIT_INT_ALIVE);
-+
-+	/* HW RF KILL switch toggled (4965 only) */
-+	if (inta & BIT_INT_RF_KILL) {
-+		int hw_rf_kill = 0;
-+		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
-+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
-+			hw_rf_kill = 1;
-+
-+		IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR,
-+				"RF_KILL bit toggled to %s.\n",
-+				hw_rf_kill ? "disable radio":"enable radio");
 +
-+		/* Queue restart only if RF_KILL switch was set to "kill"
-+		 *   when we loaded driver, and is now set to "enable".
-+		 * After we're Alive, RF_KILL gets handled by
-+		 *   iwl_rx_card_state_notif() */
-+		if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status))
-+			queue_work(priv->workqueue, &priv->restart);
++	res = (struct iwl_rx_packet *)skb->data;
++	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
++		IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
++			  res->hdr.flags);
++		return 1;
++	}
 +
-+		handled |= BIT_INT_RF_KILL;
++	switch (res->u.add_sta.status) {
++	case ADD_STA_SUCCESS_MSK:
++		break;
++	default:
++		break;
 +	}
 +
-+	/* Chip got too hot and stopped itself (4965 only) */
-+	if (inta & BIT_INT_CT_KILL) {
-+		IWL_ERROR("Microcode CT kill error detected.\n");
-+		handled |= BIT_INT_CT_KILL;
-+	}
++	/* We didn't cache the SKB; let the caller free it */
++	return 1;
++}
 +
-+	/* Error detected by uCode */
-+	if (inta & BIT_INT_SWERROR) {
-+		IWL_ERROR("Microcode SW error detected.  Restarting 0x%X.\n",
-+			  inta);
-+		iwl_irq_handle_error(priv);
-+		handled |= BIT_INT_SWERROR;
-+	}
++int iwl_send_add_station(struct iwl_priv *priv,
++			 struct iwl_addsta_cmd *sta, u8 flags)
++{
++	struct iwl_rx_packet *res = NULL;
++	int rc = 0;
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_ADD_STA,
++		.len = sizeof(struct iwl_addsta_cmd),
++		.meta.flags = flags,
++		.data = sta,
++	};
 +
-+	/* uCode wakes up after power-down sleep */
-+	if (inta & BIT_INT_WAKEUP) {
-+		IWL_DEBUG_ISR("Wakeup interrupt\n");
-+		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
-+		iwl_tx_queue_update_write_ptr(priv, &priv->txq[0]);
-+		iwl_tx_queue_update_write_ptr(priv, &priv->txq[1]);
-+		iwl_tx_queue_update_write_ptr(priv, &priv->txq[2]);
-+		iwl_tx_queue_update_write_ptr(priv, &priv->txq[3]);
-+		iwl_tx_queue_update_write_ptr(priv, &priv->txq[4]);
-+		iwl_tx_queue_update_write_ptr(priv, &priv->txq[5]);
++	if (flags & CMD_ASYNC)
++		cmd.meta.u.callback = iwl_add_sta_sync_callback;
++	else
++		cmd.meta.flags |= CMD_WANT_SKB;
 +
-+		handled |= BIT_INT_WAKEUP;
-+	}
++	rc = iwl_send_cmd(priv, &cmd);
 +
-+	/* All uCode command responses, including Tx command responses,
-+	 * Rx "responses" (frame-received notification), and other
-+	 * notifications from uCode come through here*/
-+	if (inta & (BIT_INT_FH_RX | BIT_INT_SW_RX)) {
-+		iwl_rx_handle(priv);
-+		handled |= (BIT_INT_FH_RX | BIT_INT_SW_RX);
-+	}
++	if (rc || (flags & CMD_ASYNC))
++		return rc;
 +
-+	if (inta & BIT_INT_FH_TX) {
-+		IWL_DEBUG_ISR("Tx interrupt\n");
++	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
++	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
++		IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
++			  res->hdr.flags);
++		rc = -EIO;
++	}
 +
-+#if IWL == 3945
-+		iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
-+		if (!iwl_grab_restricted_access(priv)) {
-+			iwl_write_restricted(priv,
-+					     FH_TCSR_CREDIT
-+					     (ALM_FH_SRVC_CHNL), 0x0);
-+			iwl_release_restricted_access(priv);
++	if (rc == 0) {
++		switch (res->u.add_sta.status) {
++		case ADD_STA_SUCCESS_MSK:
++			IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n");
++			break;
++		default:
++			rc = -EIO;
++			IWL_WARNING("REPLY_ADD_STA failed\n");
++			break;
 +		}
-+#endif /* IWL == 3945 */
-+		handled |= BIT_INT_FH_TX;
 +	}
 +
-+	if (inta & ~handled)
-+		IWL_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
++	priv->alloc_rxb_skb--;
++	dev_kfree_skb_any(cmd.meta.u.skb);
 +
-+	if (inta & ~CSR_INI_SET_MASK) {
-+		IWL_WARNING("Disabled INTA bits 0x%08x were pending\n",
-+			 inta & ~CSR_INI_SET_MASK);
-+		IWL_WARNING("   with FH_INT = 0x%08x\n", inta_fh);
-+	}
++	return rc;
++}
 +
-+	/* Re-enable all interrupts */
-+	iwl_enable_interrupts(priv);
++static int iwl_update_sta_key_info(struct iwl_priv *priv,
++				   struct ieee80211_key_conf *keyconf,
++				   u8 sta_id)
++{
++	unsigned long flags;
++	__le16 key_flags = 0;
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	if (iwl_debug_level & (IWL_DL_ISR)) {
-+		inta = iwl_read32(priv, CSR_INT);
-+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
-+		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-+		IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
-+			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
++	switch (keyconf->alg) {
++	case ALG_CCMP:
++		key_flags |= STA_KEY_FLG_CCMP;
++		key_flags |= cpu_to_le16(
++				keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
++		key_flags &= ~STA_KEY_FLG_INVALID;
++		break;
++	case ALG_TKIP:
++	case ALG_WEP:
++		return -EINVAL;
++	default:
++		return -EINVAL;
 +	}
-+#endif
-+	spin_unlock_irqrestore(&priv->lock, flags);
-+}
++	spin_lock_irqsave(&priv->sta_lock, flags);
++	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
++	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
++	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
++	       keyconf->keylen);
 +
-+static irqreturn_t iwl_isr(int irq, void *data)
-+{
-+	struct iwl_priv *priv = data;
-+	u32 inta, inta_mask;
-+	u32 inta_fh;
-+	if (!priv)
-+		return IRQ_NONE;
++	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
++	       keyconf->keylen);
++	priv->stations[sta_id].sta.key.key_flags = key_flags;
++	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
++	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 +
-+	spin_lock(&priv->lock);
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
 +
-+	/* Disable (but don't clear!) interrupts here to avoid
-+	 *    back-to-back ISRs and sporadic interrupts from our NIC.
-+	 * If we have something to service, the tasklet will re-enable ints.
-+	 * If we *don't* have something, we'll re-enable before leaving here. */
-+	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
-+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
++	IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
++	iwl_send_add_station(priv, &priv->stations[sta_id].sta, 0);
++	return 0;
++}
 +
-+	/* Discover which interrupts are active/pending */
-+	inta = iwl_read32(priv, CSR_INT);
-+	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
++static void iwl_clear_free_frames(struct iwl_priv *priv)
++{
++	struct list_head *element;
 +
-+	/* Ignore interrupt if there's nothing in NIC to service.
-+	 * This may be due to IRQ shared with another device,
-+	 * or due to sporadic interrupts thrown from our NIC. */
-+	if (!inta && !inta_fh) {
-+		IWL_DEBUG_ISR("Ignore interrupt, inta == 0, inta_fh == 0\n");
-+		goto none;
++	IWL_DEBUG_INFO("%d frames on pre-allocated heap on clear.\n",
++		       priv->frames_count);
++
++	while (!list_empty(&priv->free_frames)) {
++		element = priv->free_frames.next;
++		list_del(element);
++		kfree(list_entry(element, struct iwl_frame, list));
++		priv->frames_count--;
 +	}
 +
-+	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-+		/* Hardware disappeared */
-+		IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
-+		goto none;
++	if (priv->frames_count) {
++		IWL_WARNING("%d frames still in use.  Did we lose one?\n",
++			    priv->frames_count);
++		priv->frames_count = 0;
 +	}
++}
 +
-+	IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-+		      inta, inta_mask, inta_fh);
++static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
++{
++	struct iwl_frame *frame;
++	struct list_head *element;
++	if (list_empty(&priv->free_frames)) {
++		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
++		if (!frame) {
++			IWL_ERROR("Could not allocate frame!\n");
++			return NULL;
++		}
 +
-+	/* iwl_irq_tasklet() will service interrupts and re-enable them */
-+	tasklet_schedule(&priv->irq_tasklet);
-+	spin_unlock(&priv->lock);
++		priv->frames_count++;
++		return frame;
++	}
 +
-+	return IRQ_HANDLED;
++	element = priv->free_frames.next;
++	list_del(element);
++	return list_entry(element, struct iwl_frame, list);
++}
 +
-+ none:
-+	/* re-enable interrupts here since we don't have anything to service. */
-+	iwl_enable_interrupts(priv);
-+	spin_unlock(&priv->lock);
-+	return IRQ_NONE;
++static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
++{
++	memset(frame, 0, sizeof(*frame));
++	list_add(&frame->list, &priv->free_frames);
 +}
 +
-+/************************** EEPROM BANDS ****************************
-+ *
-+ * The iwl_eeprom_band definitions below provide the mapping from the
-+ * EEPROM contents to the specific channel number supported for each
-+ * band.
-+ *
-+ * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
-+ * definition below maps to physical channel 42 in the 5.2GHz spectrum.
-+ * The specific geography and calibration information for that channel
-+ * is contained in the eeprom map itself.
-+ *
-+ * During init, we copy the eeprom information and channel map
-+ * information into priv->channel_info_24/52 and priv->channel_map_24/52
-+ *
-+ * channel_map_24/52 provides the index in the channel_info array for a
-+ * given channel.  We have to have two separate maps as there is channel
-+ * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
-+ * band_2
-+ *
-+ * A value of 0xff stored in the channel_map indicates that the channel
-+ * is not supported by the hardware at all.
-+ *
-+ * A value of 0xfe in the channel_map indicates that the channel is not
-+ * valid for Tx with the current hardware.  This means that
-+ * while the system can tune and receive on a given channel, it may not
-+ * be able to associate or transmit any frames on that
-+ * channel.  There is no corresponding channel information for that
-+ * entry.
-+ *
-+ *********************************************************************/
++unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
++				struct ieee80211_hdr *hdr,
++				const u8 *dest, int left)
++{
 +
-+/* 2.4 GHz */
-+static const u8 iwl_eeprom_band_1[14] = {
-+	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
-+};
++	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
++	    ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
++	     (priv->iw_mode != IEEE80211_IF_TYPE_AP)))
++		return 0;
 +
-+/* 5.2 GHz bands */
-+static const u8 iwl_eeprom_band_2[] = {
-+	183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
-+};
++	if (priv->ibss_beacon->len > left)
++		return 0;
 +
-+static const u8 iwl_eeprom_band_3[] = {	/* 5205-5320MHz */
-+	34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
-+};
++	memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
 +
-+static const u8 iwl_eeprom_band_4[] = {	/* 5500-5700MHz */
-+	100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
-+};
++	return priv->ibss_beacon->len;
++}
++
++int iwl_rate_index_from_plcp(int plcp)
++{
++	int i = 0;
 +
-+static const u8 iwl_eeprom_band_5[] = {	/* 5725-5825MHz */
-+	145, 149, 153, 157, 161, 165
-+};
++	if (plcp & RATE_MCS_HT_MSK) {
++		i = (plcp & 0xff);
 +
-+#if IWL == 4965
-+static u8 iwl_eeprom_band_6[] = {       /* 2.4 FAT channel */
-+	1, 2, 3, 4, 5, 6, 7
-+};
++		if (i >= IWL_RATE_MIMO_6M_PLCP)
++			i = i - IWL_RATE_MIMO_6M_PLCP;
 +
-+static u8 iwl_eeprom_band_7[] = {       /* 5.2 FAT channel */
-+	36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
-+};
-+#endif
++		i += IWL_FIRST_OFDM_RATE;
++		/* skip 9M not supported in ht*/
++		if (i >= IWL_RATE_9M_INDEX)
++			i += 1;
++		if ((i >= IWL_FIRST_OFDM_RATE) &&
++		    (i <= IWL_LAST_OFDM_RATE))
++			return i;
++	} else {
++		for (i = 0; i < ARRAY_SIZE(iwl_rates); i++)
++			if (iwl_rates[i].plcp == (plcp &0xFF))
++				return i;
++	}
++	return -1;
++}
 +
-+static void iwl_init_band_reference(const struct iwl_priv *priv, int band,
-+				    int *eeprom_ch_count,
-+				    const struct iwl_eeprom_channel
-+				    **eeprom_ch_info,
-+				    const u8 **eeprom_ch_index)
++static u8 iwl_rate_get_lowest_plcp(int rate_mask)
 +{
-+	switch (band) {
-+	case 1:		/* 2.4GHz band */
-+		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
-+		*eeprom_ch_info = priv->eeprom.band_1_channels;
-+		*eeprom_ch_index = iwl_eeprom_band_1;
-+		break;
-+	case 2:		/* 5.2GHz band */
-+		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
-+		*eeprom_ch_info = priv->eeprom.band_2_channels;
-+		*eeprom_ch_index = iwl_eeprom_band_2;
-+		break;
-+	case 3:		/* 5.2GHz band */
-+		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
-+		*eeprom_ch_info = priv->eeprom.band_3_channels;
-+		*eeprom_ch_index = iwl_eeprom_band_3;
-+		break;
-+	case 4:		/* 5.2GHz band */
-+		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
-+		*eeprom_ch_info = priv->eeprom.band_4_channels;
-+		*eeprom_ch_index = iwl_eeprom_band_4;
-+		break;
-+	case 5:		/* 5.2GHz band */
-+		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
-+		*eeprom_ch_info = priv->eeprom.band_5_channels;
-+		*eeprom_ch_index = iwl_eeprom_band_5;
-+		break;
-+#if IWL == 4965
-+	case 6:
-+		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
-+		*eeprom_ch_info = priv->eeprom.band_24_channels;
-+		*eeprom_ch_index = iwl_eeprom_band_6;
-+		break;
-+	case 7:
-+		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
-+		*eeprom_ch_info = priv->eeprom.band_52_channels;
-+		*eeprom_ch_index = iwl_eeprom_band_7;
-+		break;
-+#endif
-+	default:
-+		BUG();
-+		return;
++	u8 i;
++
++	for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
++	     i = iwl_rates[i].next_ieee) {
++		if (rate_mask & (1 << i))
++			return iwl_rates[i].plcp;
 +	}
++
++	return IWL_RATE_INVALID;
 +}
 +
-+const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
-+						    int phymode, u16 channel)
++static int iwl_send_beacon_cmd(struct iwl_priv *priv)
 +{
-+	int i;
++	struct iwl_frame *frame;
++	unsigned int frame_size;
++	int rc;
++	u8 rate;
 +
-+	switch (phymode) {
-+	case MODE_IEEE80211A:
-+		for (i = 14; i < priv->channel_count; i++) {
-+			if (priv->channel_info[i].channel == channel)
-+				return &priv->channel_info[i];
-+		}
-+		break;
++	frame = iwl_get_free_frame(priv);
 +
-+	case MODE_IEEE80211B:
-+	case MODE_IEEE80211G:
-+		if (channel >= 1 && channel <= 14)
-+			return &priv->channel_info[channel - 1];
-+		break;
++	if (!frame) {
++		IWL_ERROR("Could not obtain free frame buffer for beacon "
++			  "command.\n");
++		return -ENOMEM;
++	}
 +
++	if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) {
++		rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic &
++						0xFF0);
++		if (rate == IWL_INVALID_RATE)
++			rate = IWL_RATE_6M_PLCP;
++	} else {
++		rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic & 0xF);
++		if (rate == IWL_INVALID_RATE)
++			rate = IWL_RATE_1M_PLCP;
 +	}
 +
-+	return NULL;
++	frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate);
++
++	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
++			      &frame->u.cmd[0]);
++
++	iwl_free_frame(priv, frame);
++
++	return rc;
 +}
 +
-+#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
-+			    ? # x " " : "")
++/******************************************************************************
++ *
++ * EEPROM related functions
++ *
++ ******************************************************************************/
 +
-+static int iwl_init_channel_map(struct iwl_priv *priv)
++static void get_eeprom_mac(struct iwl_priv *priv, u8 *mac)
 +{
-+	int eeprom_ch_count = 0;
-+	const u8 *eeprom_ch_index = NULL;
-+	const struct iwl_eeprom_channel *eeprom_ch_info = NULL;
-+	int band, ch;
-+	struct iwl_channel_info *ch_info;
++	memcpy(mac, priv->eeprom.mac_address, 6);
++}
 +
-+	if (priv->channel_count) {
-+		IWL_DEBUG_INFO("Channel map already initialized.\n");
-+		return 0;
-+	}
++/**
++ * iwl_eeprom_init - read EEPROM contents
++ *
++ * Load the EEPROM from adapter into priv->eeprom
++ *
++ * NOTE:  This routine uses the non-debug IO access functions.
++ */
++int iwl_eeprom_init(struct iwl_priv *priv)
++{
++	u16 *e = (u16 *)&priv->eeprom;
++	u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
++	u32 r;
++	int sz = sizeof(priv->eeprom);
++	int rc;
++	int i;
++	u16 addr;
 +
-+	if (priv->eeprom.version < 0x2f) {
-+		IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
-+			    priv->eeprom.version);
-+		return -EINVAL;
++	/* The EEPROM structure has several padding buffers within it
++	 * and when adding new EEPROM maps is subject to programmer errors
++	 * which may be very difficult to identify without explicitly
++	 * checking the resulting size of the eeprom map. */
++	BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
++
++	if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
++		IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
++		return -ENOENT;
 +	}
 +
-+	IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
++	rc = iwl_eeprom_aqcuire_semaphore(priv);
++	if (rc < 0) {
++		IWL_ERROR("Failed to aqcuire EEPROM semaphore.\n");
++		return -ENOENT;
++	}
 +
-+	priv->channel_count =
-+	    ARRAY_SIZE(iwl_eeprom_band_1) +
-+	    ARRAY_SIZE(iwl_eeprom_band_2) +
-+	    ARRAY_SIZE(iwl_eeprom_band_3) +
-+	    ARRAY_SIZE(iwl_eeprom_band_4) +
-+	    ARRAY_SIZE(iwl_eeprom_band_5);
++	/* eeprom is an array of 16bit values */
++	for (addr = 0; addr < sz; addr += sizeof(u16)) {
++		_iwl_write32(priv, CSR_EEPROM_REG, addr << 1);
++		_iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
 +
-+	IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
++		for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
++					i += IWL_EEPROM_ACCESS_DELAY) {
++			r = _iwl_read_restricted(priv, CSR_EEPROM_REG);
++			if (r & CSR_EEPROM_REG_READ_VALID_MSK)
++				break;
++			udelay(IWL_EEPROM_ACCESS_DELAY);
++		}
 +
-+	priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
-+				     priv->channel_count, GFP_KERNEL);
-+	if (!priv->channel_info) {
-+		IWL_ERROR("Could not allocate channel_info\n");
-+		priv->channel_count = 0;
-+		return -ENOMEM;
++		if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
++			IWL_ERROR("Time out reading EEPROM[%d]", addr);
++			rc = -ETIMEDOUT;
++			goto done;
++		}
++		e[addr / 2] = le16_to_cpu(r >> 16);
 +	}
++	rc = 0;
 +
-+	ch_info = priv->channel_info;
-+
-+	/* Loop through the 5 EEPROM bands adding them in order to the
-+	 * channel map we maintain (that contains additional information than
-+	 * what just in the EEPROM) */
-+	for (band = 1; band <= 5; band++) {
-+
-+		iwl_init_band_reference(priv, band, &eeprom_ch_count,
-+					&eeprom_ch_info, &eeprom_ch_index);
++done:
++	iwl_eeprom_release_semaphore(priv);
++	return rc;
++}
 +
-+		/* Loop through each band adding each of the channels */
-+		for (ch = 0; ch < eeprom_ch_count; ch++) {
-+			ch_info->channel = eeprom_ch_index[ch];
-+			ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
-+			    MODE_IEEE80211A;
++/******************************************************************************
++ *
++ * Misc. internal state and helper functions
++ *
++ ******************************************************************************/
++#ifdef CONFIG_IWLWIFI_DEBUG
 +
-+			/* permanently store EEPROM's channel regulatory flags
-+			 *   and max power in channel info database. */
-+			ch_info->eeprom = eeprom_ch_info[ch];
++/**
++ * iwl_report_frame - dump frame to syslog during debug sessions
++ *
++ * hack this function to show different aspects of received frames,
++ * including selective frame dumps.
++ * group100 parameter selects whether to show 1 out of 100 good frames.
++ *
++ * TODO:  ieee80211_hdr stuff is common to 3945 and 4965, so frame type
++ *        info output is okay, but some of this stuff (e.g. iwl_rx_frame_stats)
++ *        is 3945-specific and gives bad output for 4965.  Need to split the
++ *        functionality, keep common stuff here.
++ */
++void iwl_report_frame(struct iwl_priv *priv,
++		      struct iwl_rx_packet *pkt,
++		      struct ieee80211_hdr *header, int group100)
++{
++	u32 to_us;
++	u32 print_summary = 0;
++	u32 print_dump = 0;	/* set to 1 to dump all frames' contents */
++	u32 hundred = 0;
++	u32 dataframe = 0;
++	u16 fc;
++	u16 seq_ctl;
++	u16 channel;
++	u16 phy_flags;
++	int rate_sym;
++	u16 length;
++	u16 status;
++	u16 bcn_tmr;
++	u32 tsf_low;
++	u64 tsf;
++	u8 rssi;
++	u8 agc;
++	u16 sig_avg;
++	u16 noise_diff;
++	struct iwl_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
++	struct iwl_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
++	struct iwl_rx_frame_end *rx_end = IWL_RX_END(pkt);
++	u8 *data = IWL_RX_DATA(pkt);
 +
-+			/* Copy the run-time flags so they are there even on
-+			 * invalid channels */
-+			ch_info->flags = eeprom_ch_info[ch].flags;
++	/* MAC header */
++	fc = le16_to_cpu(header->frame_control);
++	seq_ctl = le16_to_cpu(header->seq_ctrl);
 +
-+			if (!(is_channel_valid(ch_info))) {
-+				IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - "
-+					       "No traffic\n",
-+					       ch_info->channel,
-+					       ch_info->flags,
-+					       is_channel_a_band(ch_info) ?
-+					       "5.2" : "2.4");
-+				ch_info++;
-+				continue;
-+			}
++	/* metadata */
++	channel = le16_to_cpu(rx_hdr->channel);
++	phy_flags = le16_to_cpu(rx_hdr->phy_flags);
++	rate_sym = rx_hdr->rate;
++	length = le16_to_cpu(rx_hdr->len);
 +
-+			/* Initialize regulatory-based run-time data */
-+			ch_info->max_power_avg = ch_info->curr_txpow =
-+			    eeprom_ch_info[ch].max_power_avg;
-+			ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
-+			ch_info->min_power = 0;
++	/* end-of-frame status and timestamp */
++	status = le32_to_cpu(rx_end->status);
++	bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
++	tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
++	tsf = le64_to_cpu(rx_end->timestamp);
 +
-+			IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
-+				       " %ddBm): Ad-Hoc %ssupported\n",
-+				       ch_info->channel,
-+				       is_channel_a_band(ch_info) ?
-+				       "5.2" : "2.4",
-+				       CHECK_AND_PRINT(IBSS),
-+				       CHECK_AND_PRINT(ACTIVE),
-+				       CHECK_AND_PRINT(RADAR),
-+				       CHECK_AND_PRINT(WIDE),
-+				       CHECK_AND_PRINT(NARROW),
-+				       CHECK_AND_PRINT(DFS),
-+				       eeprom_ch_info[ch].flags,
-+				       eeprom_ch_info[ch].max_power_avg,
-+				       ((eeprom_ch_info[ch].
-+					 flags & EEPROM_CHANNEL_IBSS)
-+					&& !(eeprom_ch_info[ch].
-+					     flags & EEPROM_CHANNEL_RADAR))
-+				       ? "" : "not ");
++	/* signal statistics */
++	rssi = rx_stats->rssi;
++	agc = rx_stats->agc;
++	sig_avg = le16_to_cpu(rx_stats->sig_avg);
++	noise_diff = le16_to_cpu(rx_stats->noise_diff);
 +
-+			/* Set the user_txpower_limit to the highest power
-+			 * supported by any channel */
-+			if (eeprom_ch_info[ch].max_power_avg >
-+			    priv->user_txpower_limit)
-+				priv->user_txpower_limit =
-+				    eeprom_ch_info[ch].max_power_avg;
++	to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
 +
-+			ch_info++;
++	/* if data frame is to us and all is good,
++	 *   (optionally) print summary for only 1 out of every 100 */
++	if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
++	    (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
++		dataframe = 1;
++		if (!group100)
++			print_summary = 1;	/* print each frame */
++		else if (priv->framecnt_to_us < 100) {
++			priv->framecnt_to_us++;
++			print_summary = 0;
++		} else {
++			priv->framecnt_to_us = 0;
++			print_summary = 1;
++			hundred = 1;
 +		}
++	} else {
++		/* print summary for all other frames */
++		print_summary = 1;
 +	}
-+#if IWL == 4965
-+	for (band = 6; band <= 7; band++) {
-+		int phymode;
-+		u8 fat_extension_chan;
 +
-+		iwl_init_band_reference(priv, band, &eeprom_ch_count,
-+					&eeprom_ch_info, &eeprom_ch_index);
-+
-+		phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A;
-+		/* Loop through each band adding each of the channels */
-+		for (ch = 0; ch < eeprom_ch_count; ch++) {
++	if (print_summary) {
++		char *title;
++		u32 rate;
 +
-+			if ((band == 6) &&
-+			    ((eeprom_ch_index[ch] == 5) ||
-+			    (eeprom_ch_index[ch] == 6) ||
-+			    (eeprom_ch_index[ch] == 7)))
-+			       fat_extension_chan = HT_IE_EXT_CHANNEL_MAX;
-+			else
-+				fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;
++		if (hundred)
++			title = "100Frames";
++		else if (fc & IEEE80211_FCTL_RETRY)
++			title = "Retry";
++		else if (ieee80211_is_assoc_response(fc))
++			title = "AscRsp";
++		else if (ieee80211_is_reassoc_response(fc))
++			title = "RasRsp";
++		else if (ieee80211_is_probe_response(fc)) {
++			title = "PrbRsp";
++			print_dump = 1;	/* dump frame contents */
++		} else if (ieee80211_is_beacon(fc)) {
++			title = "Beacon";
++			print_dump = 1;	/* dump frame contents */
++		} else if (ieee80211_is_atim(fc))
++			title = "ATIM";
++		else if (ieee80211_is_auth(fc))
++			title = "Auth";
++		else if (ieee80211_is_deauth(fc))
++			title = "DeAuth";
++		else if (ieee80211_is_disassoc(fc))
++			title = "DisAssoc";
++		else
++			title = "Frame";
 +
-+			iwl4965_set_fat_chan_info(priv, phymode,
-+						  eeprom_ch_index[ch],
-+						  &(eeprom_ch_info[ch]),
-+						  fat_extension_chan);
++		rate = iwl_rate_index_from_plcp(rate_sym);
++		if (rate == -1)
++			rate = 0;
++		else
++			rate = iwl_rates[rate].ieee / 2;
 +
-+			iwl4965_set_fat_chan_info(priv, phymode,
-+						  (eeprom_ch_index[ch] + 4),
-+						  &(eeprom_ch_info[ch]),
-+						  HT_IE_EXT_CHANNEL_BELOW);
++		/* print frame summary.
++		 * MAC addresses show just the last byte (for brevity),
++		 *    but you can hack it to show more, if you'd like to. */
++		if (dataframe)
++			IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
++				     "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
++				     title, fc, header->addr1[5],
++				     length, rssi, channel, rate);
++		else {
++			/* src/dst addresses assume managed mode */
++			IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
++				     "src=0x%02x, rssi=%u, tim=%lu usec, "
++				     "phy=0x%02x, chnl=%d\n",
++				     title, fc, header->addr1[5],
++				     header->addr3[5], rssi,
++				     tsf_low - priv->scan_start_tsf,
++				     phy_flags, channel);
 +		}
 +	}
-+#endif
-+
-+	if (iwl3945_txpower_set_from_eeprom(priv))
-+		return -EIO;
-+
-+	return 0;
++	if (print_dump)
++		iwl_print_hex_dump(IWL_DL_RX, data, length);
 +}
++#endif
 +
-+/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
-+ * sending probe req.  This should be set long enough to hear probe responses
-+ * from more than one AP.  */
-+#define IWL_ACTIVE_DWELL_TIME_24    (20)	/* all times in msec */
-+#define IWL_ACTIVE_DWELL_TIME_52    (10)
-+
-+/* For faster active scanning, scan will move to the next channel if fewer than
-+ * PLCP_QUIET_THRESH packets are heard on this channel within
-+ * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell
-+ * time if it's a quiet channel (nothing responded to our probe, and there's
-+ * no other traffic).
-+ * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
-+#define IWL_PLCP_QUIET_THRESH       __constant_cpu_to_le16(1)	/* packets */
-+#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(5)	/* msec */
-+
-+/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
-+ * Must be set longer than active dwell time.
-+ * For the most reliable scan, set > AP beacon interval (typically 100msec). */
-+#define IWL_PASSIVE_DWELL_TIME_24   (20)	/* all times in msec */
-+#define IWL_PASSIVE_DWELL_TIME_52   (10)
-+#define IWL_PASSIVE_DWELL_BASE      (100)
-+#define IWL_CHANNEL_TUNE_TIME       5
-+
-+static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, int phymode)
++static void iwl_unset_hw_setting(struct iwl_priv *priv)
 +{
-+	if (phymode == MODE_IEEE80211A)
-+		return IWL_ACTIVE_DWELL_TIME_52;
-+	else
-+		return IWL_ACTIVE_DWELL_TIME_24;
++	if (priv->hw_setting.shared_virt)
++		pci_free_consistent(priv->pci_dev,
++				    sizeof(struct iwl_shared),
++				    priv->hw_setting.shared_virt,
++				    priv->hw_setting.shared_phys);
 +}
 +
-+static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, int phymode)
++/**
++ * iwl_supported_rate_to_ie - fill in the supported rate in IE field
++ *
++ * return : set the bit for each supported rate insert in ie
++ */
++static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
++				    u16 basic_rate, int max_count)
 +{
-+	u16 active = iwl_get_active_dwell_time(priv, phymode);
-+	u16 passive = (phymode != MODE_IEEE80211A) ?
-+	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
-+	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
++	u16 ret_rates = 0, bit;
++	int i;
++	u8 *rates;
 +
-+	if (iwl_is_associated(priv)) {
-+		/* If we're associated, we clamp the maximum passive
-+		 * dwell time to be 98% of the beacon interval (minus
-+		 * 2 * channel tune time) */
-+		passive = priv->beacon_int;
-+		if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
-+			passive = IWL_PASSIVE_DWELL_BASE;
-+		passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
-+	}
++	rates = &(ie[1]);
 +
-+	if (passive <= active)
-+		passive = active + 1;
++	for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
++		if (bit & supported_rate) {
++			ret_rates |= bit;
++			rates[*ie] = iwl_rates[i].ieee |
++			    ((bit & basic_rate) ? 0x80 : 0x00);
++			*ie = *ie + 1;
++			if (*ie >= max_count)
++				break;
++		}
++	}
 +
-+	return passive;
++	return ret_rates;
 +}
 +
-+static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
-+				     u8 is_active, u8 direct_mask,
-+				     struct iwl_scan_channel *scan_ch)
++#ifdef CONFIG_IWLWIFI_HT
++void static iwl_set_ht_capab(struct ieee80211_hw *hw,
++			     struct ieee80211_ht_capability *ht_cap,
++			     u8 use_wide_chan);
++#endif
++
++/**
++ * iwl_fill_probe_req - fill in all required fields and IE for probe request
++ */
++static u16 iwl_fill_probe_req(struct iwl_priv *priv,
++			      struct ieee80211_mgmt *frame,
++			      int left, int is_direct)
 +{
-+	const struct ieee80211_channel *channels = NULL;
-+	const struct ieee80211_hw_mode *hw_mode;
-+	const struct iwl_channel_info *ch_info;
-+	u16 passive_dwell = 0;
-+	u16 active_dwell = 0;
-+	int added, i;
++	int len = 0;
++	u8 *pos = NULL;
++	u16 ret_rates;
 +
-+	hw_mode = iwl_get_hw_mode(priv, phymode);
-+	if (!hw_mode)
++	/* Make sure there is enough space for the probe request,
++	 * two mandatory IEs and the data */
++	left -= 24;
++	if (left < 0)
 +		return 0;
++	len += 24;
 +
-+	channels = hw_mode->channels;
-+
-+	active_dwell = iwl_get_active_dwell_time(priv, phymode);
-+	passive_dwell = iwl_get_passive_dwell_time(priv, phymode);
-+
-+	for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
-+		if (channels[i].chan ==
-+		    le16_to_cpu(priv->active_rxon.channel)) {
-+			if (iwl_is_associated(priv)) {
-+				IWL_DEBUG_SCAN
-+				    ("Skipping current channel %d\n",
-+				     le16_to_cpu(priv->active_rxon.channel));
-+				continue;
-+			}
-+		} else if (priv->only_active_channel)
-+			continue;
-+
-+		scan_ch->channel = channels[i].chan;
++	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
++	memcpy(frame->da, BROADCAST_ADDR, ETH_ALEN);
++	memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
++	memcpy(frame->bssid, BROADCAST_ADDR, ETH_ALEN);
++	frame->seq_ctrl = 0;
 +
-+		ch_info = iwl_get_channel_info(priv, phymode, scan_ch->channel);
-+		if (!is_channel_valid(ch_info)) {
-+			IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
-+				       scan_ch->channel);
-+			continue;
-+		}
++	/* fill in our indirect SSID IE */
++	/* ...next IE... */
 +
-+		if (!is_active || is_channel_passive(ch_info) ||
-+		    !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
-+			scan_ch->type = 0;	/* passive */
-+		else
-+			scan_ch->type = 1;	/* active */
++	left -= 2;
++	if (left < 0)
++		return 0;
++	len += 2;
++	pos = &(frame->u.probe_req.variable[0]);
++	*pos++ = WLAN_EID_SSID;
++	*pos++ = 0;
 +
-+		if (scan_ch->type & 1)
-+			scan_ch->type |= (direct_mask << 1);
++	/* fill in our direct SSID IE... */
++	if (is_direct) {
++		/* ...next IE... */
++		left -= 2 + priv->essid_len;
++		if (left < 0)
++			return 0;
++		/* ... fill it in... */
++		*pos++ = WLAN_EID_SSID;
++		*pos++ = priv->essid_len;
++		memcpy(pos, priv->essid, priv->essid_len);
++		pos += priv->essid_len;
++		len += 2 + priv->essid_len;
++	}
 +
-+		if (is_channel_narrow(ch_info))
-+			scan_ch->type |= (1 << 7);
++	/* fill in supported rate */
++	/* ...next IE... */
++	left -= 2;
++	if (left < 0)
++		return 0;
++	/* ... fill it in... */
++	*pos++ = WLAN_EID_SUPP_RATES;
++	*pos = 0;
++	ret_rates = priv->active_rate = priv->rates_mask;
++	priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
 +
-+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
-+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
++	iwl_supported_rate_to_ie(pos, priv->active_rate,
++				 priv->active_rate_basic, left);
++	len += 2 + *pos;
++	pos += (*pos) + 1;
++	ret_rates = ~ret_rates & priv->active_rate;
 +
-+		/* Set power levels to defaults */
-+		scan_ch->tpc.dsp_atten = 110;
-+		/* scan_pwr_info->tpc.dsp_atten; */
++	if (ret_rates == 0)
++		goto fill_end;
 +
-+		/*scan_pwr_info->tpc.tx_gain; */
-+		if (phymode == MODE_IEEE80211A)
-+			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
-+		else {
-+			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
-+			/* NOTE: if we were doing 6Mb OFDM for scans we'd use
-+			 * power level
-+			 scan_ch->tpc.tx_gain = ((1<<5) | (2 << 3)) | 3;
-+			 */
-+		}
++	/* fill in supported extended rate */
++	/* ...next IE... */
++	left -= 2;
++	if (left < 0)
++		return 0;
++	/* ... fill it in... */
++	*pos++ = WLAN_EID_EXT_SUPP_RATES;
++	*pos = 0;
++	iwl_supported_rate_to_ie(pos, ret_rates, priv->active_rate_basic, left);
++	if (*pos > 0)
++		len += 2 + *pos;
 +
-+		IWL_DEBUG_SCAN("Scanning %d [%s %d]\n",
-+			       scan_ch->channel,
-+			       (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
-+			       (scan_ch->type & 1) ?
-+			       active_dwell : passive_dwell);
++#ifdef CONFIG_IWLWIFI_HT
++	if (is_direct && priv->is_ht_enabled) {
++		u8 use_wide_chan = 1;
 +
-+		scan_ch++;
-+		added++;
++		if (priv->channel_width != IWL_CHANNEL_WIDTH_40MHZ)
++			use_wide_chan = 0;
++		pos += (*pos) + 1;
++		*pos++ = WLAN_EID_HT_CAPABILITY;
++		*pos++ = sizeof(struct ieee80211_ht_capability);
++		iwl_set_ht_capab(NULL, (struct ieee80211_ht_capability *)pos,
++				 use_wide_chan);
++		len += 2 + sizeof(struct ieee80211_ht_capability);
 +	}
++#endif  /*CONFIG_IWLWIFI_HT */
 +
-+	IWL_DEBUG_SCAN("total channels to scan %d \n", added);
-+	return added;
++ fill_end:
++	return (u16)len;
 +}
 +
-+static void iwl_reset_channel_flag(struct iwl_priv *priv)
++/*
++ * QoS  support
++*/
++#ifdef CONFIG_IWLWIFI_QOS
++static int iwl_send_qos_params_command(struct iwl_priv *priv,
++				       struct iwl_qosparam_cmd *qos)
 +{
-+	int i, j;
-+	for (i = 0; i < 3; i++) {
-+		struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
-+		for (j = 0; j < hw_mode->num_channels; j++)
-+			hw_mode->channels[j].flag = hw_mode->channels[j].val;
-+	}
++
++	return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
++				sizeof(struct iwl_qosparam_cmd), qos);
 +}
 +
-+static void iwl_init_hw_rates(struct iwl_priv *priv,
-+			      struct ieee80211_rate *rates)
++static void iwl_reset_qos(struct iwl_priv *priv)
 +{
++	u16 cw_min = 15;
++	u16 cw_max = 1023;
++	u8 aifs = 2;
++	u8 is_legacy = 0;
++	unsigned long flags;
 +	int i;
 +
-+	for (i = 0; i < IWL_RATE_COUNT; i++) {
-+		rates[i].rate = iwl_rates[i].ieee * 5;
-+		rates[i].val = i; /* Rate scaling will work on indexes */
-+		rates[i].val2 = i;
-+		rates[i].flags = IEEE80211_RATE_SUPPORTED;
-+		/* Only OFDM have the bits-per-symbol set */
-+		if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
-+			rates[i].flags |= IEEE80211_RATE_OFDM;
-+		else {
-+			/*
-+			 * If CCK 1M then set rate flag to CCK else CCK_2
-+			 * which is CCK | PREAMBLE2
-+			 */
-+			rates[i].flags |= (iwl_rates[i].plcp == 10) ?
-+				IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->qos_data.qos_active = 0;
++
++	if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
++		if (priv->qos_data.qos_enable)
++			priv->qos_data.qos_active = 1;
++		if (!(priv->active_rate & 0xfff0)) {
++			cw_min = 31;
++			is_legacy = 1;
++		}
++	} else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
++		if (priv->qos_data.qos_enable)
++			priv->qos_data.qos_active = 1;
++	} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
++		cw_min = 31;
++		is_legacy = 1;
++	}
++
++	if (priv->qos_data.qos_active)
++		aifs = 3;
++
++	priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
++	priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
++	priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
++	priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
++	priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
++
++	if (priv->qos_data.qos_active) {
++		i = 1;
++		priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
++		priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
++		priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
++		priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
++		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++
++		i = 2;
++		priv->qos_data.def_qos_parm.ac[i].cw_min =
++			cpu_to_le16((cw_min + 1) / 2 - 1);
++		priv->qos_data.def_qos_parm.ac[i].cw_max =
++			cpu_to_le16(cw_max);
++		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
++		if (is_legacy)
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(6016);
++		else
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(3008);
++		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++
++		i = 3;
++		priv->qos_data.def_qos_parm.ac[i].cw_min =
++			cpu_to_le16((cw_min + 1) / 4 - 1);
++		priv->qos_data.def_qos_parm.ac[i].cw_max =
++			cpu_to_le16((cw_max + 1) / 2 - 1);
++		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
++		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++		if (is_legacy)
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(3264);
++		else
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(1504);
++	} else {
++		for (i = 1; i < 4; i++) {
++			priv->qos_data.def_qos_parm.ac[i].cw_min =
++				cpu_to_le16(cw_min);
++			priv->qos_data.def_qos_parm.ac[i].cw_max =
++				cpu_to_le16(cw_max);
++			priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
++			priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
++			priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
 +		}
-+
-+		/* Set up which ones are basic rates... */
-+		if (IWL_BASIC_RATES_MASK & (1 << i))
-+			rates[i].flags |= IEEE80211_RATE_BASIC;
 +	}
++	IWL_DEBUG_QOS("set QoS to default \n");
 +
-+#if IWL == 4965
-+	iwl4965_init_hw_rates(priv, rates);
-+#endif
++	spin_unlock_irqrestore(&priv->lock, flags);
 +}
 +
-+/**
-+ * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom
-+ */
-+static int iwl_init_geos(struct iwl_priv *priv)
++static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
 +{
-+	struct iwl_channel_info *ch;
-+	struct ieee80211_hw_mode *modes;
-+	struct ieee80211_channel *channels;
-+	struct ieee80211_channel *geo_ch;
-+	struct ieee80211_rate *rates;
-+	int i = 0;
-+#if IWL == 4965
-+	enum {
-+		A = 0,
-+		B = 1,
-+		G = 2,
-+		A_11N = 3,
-+		G_11N = 4,
-+	};
-+	int mode_count = 5;
-+#else
-+	enum {
-+		A = 0,
-+		B = 1,
-+		G = 2,
-+	};
-+	int mode_count = 3;
-+#endif
-+
-+	if (priv->modes) {
-+		IWL_DEBUG_INFO("Geography modes already initialized.\n");
-+		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
-+		return 0;
-+	}
-+
-+	modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
-+			GFP_KERNEL);
-+	if (!modes)
-+		return -ENOMEM;
-+
-+	channels = kzalloc(sizeof(struct ieee80211_channel) *
-+			   priv->channel_count, GFP_KERNEL);
-+	if (!channels) {
-+		kfree(modes);
-+		return -ENOMEM;
-+	}
-+
-+	rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
-+			GFP_KERNEL);
-+	if (!rates) {
-+		kfree(modes);
-+		kfree(channels);
-+		return -ENOMEM;
-+	}
++	unsigned long flags;
 +
-+	/* 0 = 802.11a
-+	 * 1 = 802.11b
-+	 * 2 = 802.11g
-+	 */
++	if (priv == NULL)
++		return;
 +
-+	/* 5.2GHz channels start after the 2.4GHz channels */
-+	modes[A].mode = MODE_IEEE80211A;
-+	modes[A].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
-+	modes[A].rates = rates;
-+	modes[A].num_rates = 8;	/* just OFDM */
-+#if IWL == 4965
-+	modes[A].rates = &rates[4];
-+#endif
-+	modes[A].num_channels = 0;
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
 +
-+	modes[B].mode = MODE_IEEE80211B;
-+	modes[B].channels = channels;
-+#if IWL == 3945
-+	modes[B].rates = &rates[8];
-+#elif IWL == 4965
-+	modes[B].rates = rates;
-+#endif
-+	modes[B].num_rates = 4;	/* just CCK */
-+	modes[B].num_channels = 0;
++	if (!priv->qos_data.qos_enable)
++		return;
 +
-+	modes[G].mode = MODE_IEEE80211G;
-+	modes[G].channels = channels;
-+	modes[G].rates = rates;
-+	modes[G].num_rates = 12;	/* OFDM & CCK */
-+	modes[G].num_channels = 0;
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->qos_data.def_qos_parm.qos_flags = 0;
 +
-+#if IWL == 4965
-+	modes[G_11N].mode = MODE_IEEE80211G;
-+	modes[G_11N].channels = channels;
-+	modes[G_11N].num_rates = 13;        /* OFDM & CCK */
-+	modes[G_11N].rates = rates;
-+	modes[G_11N].num_channels = 0;
++	if (priv->qos_data.qos_cap.q_AP.queue_request &&
++	    !priv->qos_data.qos_cap.q_AP.txop_request)
++		priv->qos_data.def_qos_parm.qos_flags |=
++			QOS_PARAM_FLG_TXOP_TYPE_MSK;
 +
-+	modes[A_11N].mode = MODE_IEEE80211A;
-+	modes[A_11N].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
-+	modes[A_11N].rates = &rates[4];
-+	modes[A_11N].num_rates = 9; /* just OFDM */
-+	modes[A_11N].num_channels = 0;
-+#endif
-+	priv->ieee_channels = channels;
-+	priv->ieee_rates = rates;
++	if (priv->qos_data.qos_active)
++		priv->qos_data.def_qos_parm.qos_flags |=
++			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
 +
-+	iwl_init_hw_rates(priv, rates);
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+	for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
-+		ch = &priv->channel_info[i];
++	if (force || iwl_is_associated(priv)) {
++		IWL_DEBUG_QOS("send QoS cmd with Qos active %d \n",
++			      priv->qos_data.qos_active);
 +
-+		if (!is_channel_valid(ch)) {
-+			IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- "
-+				    "skipping.\n",
-+				    ch->channel, is_channel_a_band(ch) ?
-+				    "5.2" : "2.4");
-+			continue;
-+		}
++		iwl_send_qos_params_command(priv,
++				&(priv->qos_data.def_qos_parm));
++	}
++}
 +
-+		if (is_channel_a_band(ch)) {
-+			geo_ch = &modes[A].channels[modes[A].num_channels++];
-+#if IWL == 4965
-+			modes[A_11N].num_channels++;
-+#endif
-+		} else {
-+			geo_ch = &modes[B].channels[modes[B].num_channels++];
-+			modes[G].num_channels++;
-+#if IWL == 4965
-+			modes[G_11N].num_channels++;
-+#endif
-+		}
++#endif /* CONFIG_IWLWIFI_QOS */
++/*
++ * Power management (not Tx power!) functions
++ */
++#define MSEC_TO_USEC 1024
 +
-+		geo_ch->freq = ieee80211chan2mhz(ch->channel);
-+		geo_ch->chan = ch->channel;
-+		geo_ch->power_level = ch->max_power_avg;
-+		geo_ch->antenna_max = 0xff;
++#define NOSLP __constant_cpu_to_le16(0), 0, 0
++#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
++#define SLP_TIMEOUT(T) __constant_cpu_to_le32((T) * MSEC_TO_USEC)
++#define SLP_VEC(X0, X1, X2, X3, X4) {__constant_cpu_to_le32(X0), \
++				     __constant_cpu_to_le32(X1), \
++				     __constant_cpu_to_le32(X2), \
++				     __constant_cpu_to_le32(X3), \
++				     __constant_cpu_to_le32(X4)}
 +
-+		if (is_channel_valid(ch)) {
-+			geo_ch->flag = IEEE80211_CHAN_W_SCAN;
-+			if (ch->flags & EEPROM_CHANNEL_IBSS)
-+				geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
 +
-+			if (ch->flags & EEPROM_CHANNEL_ACTIVE)
-+				geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
++/* default power management (not Tx power) table values */
++/* for tim  0-10 */
++static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = {
++	{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
++	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
++	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0},
++	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100), SLP_VEC(2, 6, 9, 9, 10)}, 0},
++	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 10)}, 1},
++	{{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1}
++};
 +
-+			if (ch->flags & EEPROM_CHANNEL_RADAR)
-+				geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
++/* for tim > 10 */
++static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = {
++	{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
++	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500),
++		 SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
++	{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300),
++		 SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
++	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(100),
++		 SLP_VEC(2, 6, 9, 9, 0xFF)}, 0},
++	{{SLP, SLP_TIMEOUT(50), SLP_TIMEOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
++	{{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25),
++		 SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
++};
 +
-+			if (ch->max_power_avg > priv->max_channel_txpower_limit)
-+				priv->max_channel_txpower_limit =
-+				    ch->max_power_avg;
-+		}
++int iwl_power_init_handle(struct iwl_priv *priv)
++{
++	int rc = 0, i;
++	struct iwl_power_mgr *pow_data;
++	int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_AC;
++	u16 pci_pm;
 +
-+		geo_ch->val = geo_ch->flag;
-+	}
++	IWL_DEBUG_POWER("Initialize power \n");
 +
-+	if ((modes[A].num_channels == 0) && priv->is_abg) {
-+		printk(KERN_INFO DRV_NAME
-+		       ": Incorrectly detected BG card as ABG.  Please send "
-+		       "your PCI ID 0x%04X:0x%04X to maintainer.\n",
-+		       priv->pci_dev->device, priv->pci_dev->subsystem_device);
-+		priv->is_abg = 0;
-+	}
++	pow_data = &(priv->power_data);
 +
-+	printk(KERN_INFO DRV_NAME
-+	       ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
-+	       modes[G].num_channels, modes[A].num_channels);
++	memset(pow_data, 0, sizeof(*pow_data));
 +
-+	/*
-+	 * NOTE:  We register these in preference of order -- the
-+	 * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
-+	 * a phymode based on rates or AP capabilities but seems to
-+	 * configure it purely on if the channel being configured
-+	 * is supported by a mode -- and the first match is taken
-+	 */
++	pow_data->active_index = IWL_POWER_RANGE_0;
++	pow_data->dtim_val = 0xffff;
 +
-+	if (modes[G].num_channels)
-+		ieee80211_register_hwmode(priv->hw, &modes[G]);
-+	if (modes[B].num_channels)
-+		ieee80211_register_hwmode(priv->hw, &modes[B]);
-+	if (modes[A].num_channels)
-+		ieee80211_register_hwmode(priv->hw, &modes[A]);
++	memcpy(&pow_data->pwr_range_0[0], &range_0[0], size);
++	memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
 +
-+	priv->modes = modes;
-+	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
++	rc = pci_read_config_word(priv->pci_dev, PCI_LINK_CTRL, &pci_pm);
++	if (rc != 0)
++		return 0;
++	else {
++		struct iwl_powertable_cmd *cmd;
 +
-+	return 0;
-+}
++		IWL_DEBUG_POWER("adjust power command flags\n");
 +
-+/******************************************************************************
-+ *
-+ * uCode download functions
-+ *
-+ ******************************************************************************/
++		for (i = 0; i < IWL_POWER_AC; i++) {
++			cmd = &pow_data->pwr_range_0[i].cmd;
 +
-+static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
-+{
-+	if (priv->ucode_code.v_addr != NULL) {
-+		pci_free_consistent(priv->pci_dev,
-+				    priv->ucode_code.len,
-+				    priv->ucode_code.v_addr,
-+				    priv->ucode_code.p_addr);
-+		priv->ucode_code.v_addr = NULL;
-+	}
-+	if (priv->ucode_data.v_addr != NULL) {
-+		pci_free_consistent(priv->pci_dev,
-+				    priv->ucode_data.len,
-+				    priv->ucode_data.v_addr,
-+				    priv->ucode_data.p_addr);
-+		priv->ucode_data.v_addr = NULL;
-+	}
-+	if (priv->ucode_data_backup.v_addr != NULL) {
-+		pci_free_consistent(priv->pci_dev,
-+				    priv->ucode_data_backup.len,
-+				    priv->ucode_data_backup.v_addr,
-+				    priv->ucode_data_backup.p_addr);
-+		priv->ucode_data_backup.v_addr = NULL;
-+	}
-+	if (priv->ucode_init.v_addr != NULL) {
-+		pci_free_consistent(priv->pci_dev,
-+				    priv->ucode_init.len,
-+				    priv->ucode_init.v_addr,
-+				    priv->ucode_init.p_addr);
-+		priv->ucode_init.v_addr = NULL;
-+	}
-+	if (priv->ucode_init_data.v_addr != NULL) {
-+		pci_free_consistent(priv->pci_dev,
-+				    priv->ucode_init_data.len,
-+				    priv->ucode_init_data.v_addr,
-+				    priv->ucode_init_data.p_addr);
-+		priv->ucode_init_data.v_addr = NULL;
-+	}
-+	if (priv->ucode_boot.v_addr != NULL) {
-+		pci_free_consistent(priv->pci_dev,
-+				    priv->ucode_boot.len,
-+				    priv->ucode_boot.v_addr,
-+				    priv->ucode_boot.p_addr);
-+		priv->ucode_boot.v_addr = NULL;
++			if (pci_pm & 0x1)
++				cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
++			else
++				cmd->flags |= IWL_POWER_PCI_PM_MSK;
++		}
 +	}
++	return rc;
 +}
 +
-+/**
-+ * iwl_verify_inst_full - verify runtime uCode image in card vs. host,
-+ *     looking at all data.
-+ */
-+static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 * image, u32 len)
++static int iwl_update_power_cmd(struct iwl_priv *priv,
++				struct iwl_powertable_cmd *cmd, u32 mode)
 +{
-+	u32 val;
-+	u32 save_len = len;
-+	int rc = 0;
-+	u32 errcnt;
++	int rc = 0, i;
++	u8 skip;
++	u32 max_sleep = 0;
++	struct iwl_power_vec_entry *range;
++	u8 period = 0;
++	struct iwl_power_mgr *pow_data;
 +
-+	IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
++	if (mode > IWL_POWER_INDEX_5) {
++		IWL_DEBUG_POWER("Error invalid power mode \n");
++		return -1;
++	}
++	pow_data = &(priv->power_data);
 +
-+	rc = iwl_grab_restricted_access(priv);
-+	if (rc)
-+		return rc;
++	if (pow_data->active_index == IWL_POWER_RANGE_0)
++		range = &pow_data->pwr_range_0[0];
++	else
++		range = &pow_data->pwr_range_1[1];
 +
-+	iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
++	memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd));
 +
-+	errcnt = 0;
-+	for (; len > 0; len -= sizeof(u32), image++) {
-+		/* read data comes through single port, auto-incr addr */
-+		/* NOTE: Use the debugless read so we don't flood kernel log
-+		 * if IWL_DL_IO is set */
-+		val = _iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
-+		if (val != le32_to_cpu(*image)) {
-+			IWL_ERROR("uCode INST section is invalid at "
-+				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
-+				  save_len - len, val, le32_to_cpu(*image));
-+			rc = -EIO;
-+			errcnt++;
-+			if (errcnt >= 20)
-+				break;
-+		}
++#ifdef IWL_MAC80211_DISABLE
++	if (priv->assoc_network != NULL) {
++		unsigned long flags;
++
++		period = priv->assoc_network->tim.tim_period;
 +	}
++#endif	/*IWL_MAC80211_DISABLE */
++	skip = range[mode].no_dtim;
 +
-+	iwl_release_restricted_access(priv);
++	if (period == 0) {
++		period = 1;
++		skip = 0;
++	}
 +
-+	if (!errcnt)
-+		IWL_DEBUG_INFO
-+		    ("ucode image in INSTRUCTION memory is good\n");
++	if (skip == 0) {
++		max_sleep = period;
++		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
++	} else {
++		__le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
++		max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
++		cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
++	}
++
++	for (i = 0; i < IWL_POWER_VEC_SIZE; i++) {
++		if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
++			cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
++	}
++
++	IWL_DEBUG_POWER("Flags value = 0x%08X\n", cmd->flags);
++	IWL_DEBUG_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
++	IWL_DEBUG_POWER("Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
++	IWL_DEBUG_POWER("Sleep interval vector = { %d , %d , %d , %d , %d }\n",
++			le32_to_cpu(cmd->sleep_interval[0]),
++			le32_to_cpu(cmd->sleep_interval[1]),
++			le32_to_cpu(cmd->sleep_interval[2]),
++			le32_to_cpu(cmd->sleep_interval[3]),
++			le32_to_cpu(cmd->sleep_interval[4]));
 +
 +	return rc;
 +}
 +
-+
-+/**
-+ * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
-+ *   using sample data 100 bytes apart.  If these sample points are good,
-+ *   it's a pretty good bet that everything between them is good, too.
-+ */
-+static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
++static int iwl_send_power_mode(struct iwl_priv *priv, u32 mode)
 +{
-+	u32 val;
-+	int rc = 0;
-+	u32 errcnt = 0;
-+	u32 i;
++	u32 final_mode = mode;
++	int rc;
++	struct iwl_powertable_cmd cmd;
 +
-+	IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
++	/* If on battery, set to 3,
++	 * if plugged into AC power, set to CAM ("continuosly aware mode"),
++	 * else user level */
++	switch (mode) {
++	case IWL_POWER_BATTERY:
++		final_mode = IWL_POWER_INDEX_3;
++		break;
++	case IWL_POWER_AC:
++		final_mode = IWL_POWER_MODE_CAM;
++		break;
++	default:
++		final_mode = mode;
++		break;
++	}
 +
-+	rc = iwl_grab_restricted_access(priv);
-+	if (rc)
-+		return rc;
++	cmd.keep_alive_beacons = 0;
 +
-+	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
-+		/* read data comes through single port, auto-incr addr */
-+		/* NOTE: Use the debugless read so we don't flood kernel log
-+		 * if IWL_DL_IO is set */
-+		iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR,
-+			i + RTC_INST_LOWER_BOUND);
-+		val = _iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
-+		if (val != le32_to_cpu(*image)) {
-+#if 0 /* Enable this if you want to see details */
-+			IWL_ERROR("uCode INST section is invalid at "
-+				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
-+				  i, val, *image);
-+#endif
-+			rc = -EIO;
-+			errcnt++;
-+			if (errcnt >= 3)
-+				break;
-+		}
-+	}
++	iwl_update_power_cmd(priv, &cmd, final_mode);
 +
-+	iwl_release_restricted_access(priv);
++	rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
++
++	if (final_mode == IWL_POWER_MODE_CAM)
++		clear_bit(STATUS_POWER_PMI, &priv->status);
++	else
++		set_bit(STATUS_POWER_PMI, &priv->status);
 +
 +	return rc;
 +}
 +
-+
-+/**
-+ * iwl_verify_ucode - determine which instruction image is in SRAM,
-+ *    and verify its contents
-+ */
-+static int iwl_verify_ucode(struct iwl_priv *priv)
++int iwl_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
 +{
-+	__le32 *image;
-+	u32 len;
-+	int rc = 0;
-+
-+	/* Try bootstrap */
-+	image = (__le32 *)priv->ucode_boot.v_addr;
-+	len = priv->ucode_boot.len;
-+	rc = iwl_verify_inst_sparse(priv, image, len);
-+	if (rc == 0) {
-+		IWL_DEBUG_INFO("Bootstrap uCode is good in inst SRAM\n");
-+		return 0;
-+	}
-+
-+	/* Try initialize */
-+	image = (__le32 *)priv->ucode_init.v_addr;
-+	len = priv->ucode_init.len;
-+	rc = iwl_verify_inst_sparse(priv, image, len);
-+	if (rc == 0) {
-+		IWL_DEBUG_INFO("Initialize uCode is good in inst SRAM\n");
-+		return 0;
-+	}
-+
-+	/* Try runtime/protocol */
-+	image = (__le32 *)priv->ucode_code.v_addr;
-+	len = priv->ucode_code.len;
-+	rc = iwl_verify_inst_sparse(priv, image, len);
-+	if (rc == 0) {
-+		IWL_DEBUG_INFO("Runtime uCode is good in inst SRAM\n");
-+		return 0;
++	/* Filter incoming packets to determine if they are targeted toward
++	 * this network, discarding packets coming from ourselves */
++	switch (priv->iw_mode) {
++	case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source    | BSSID */
++		/* packets from our adapter are dropped (echo) */
++		if (!compare_ether_addr(header->addr2, priv->mac_addr))
++			return 0;
++		/* {broad,multi}cast packets to our IBSS go through */
++		if (is_multicast_ether_addr(header->addr1))
++			return !compare_ether_addr(header->addr3, priv->bssid);
++		/* packets to our adapter go through */
++		return !compare_ether_addr(header->addr1, priv->mac_addr);
++	case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
++		/* packets from our adapter are dropped (echo) */
++		if (!compare_ether_addr(header->addr3, priv->mac_addr))
++			return 0;
++		/* {broad,multi}cast packets to our BSS go through */
++		if (is_multicast_ether_addr(header->addr1))
++			return !compare_ether_addr(header->addr2, priv->bssid);
++		/* packets to our adapter go through */
++		return !compare_ether_addr(header->addr1, priv->mac_addr);
 +	}
 +
-+	IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
-+
-+	/* Show first several data entries in instruction SRAM.
-+	 * Selection of bootstrap image is arbitrary. */
-+	image = (__le32 *)priv->ucode_boot.v_addr;
-+	len = priv->ucode_boot.len;
-+	rc = iwl_verify_inst_full(priv, image, len);
-+
-+	return rc;
++	return 1;
 +}
 +
++#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
 +
-+/* check contents of special bootstrap uCode SRAM */
-+static int iwl_verify_bsm(struct iwl_priv *priv)
++const char *iwl_get_tx_fail_reason(u32 status)
 +{
-+	__le32 *image = priv->ucode_boot.v_addr;
-+	u32 len = priv->ucode_boot.len;
-+	u32 reg;
-+	u32 val;
-+
-+	IWL_DEBUG_INFO("Begin verify bsm\n");
-+
-+	/* verify BSM SRAM contents */
-+	val = iwl_read_restricted_reg(priv, BSM_WR_DWCOUNT_REG);
-+	for (reg = BSM_SRAM_LOWER_BOUND;
-+	     reg < BSM_SRAM_LOWER_BOUND + len;
-+	     reg += sizeof(u32), image ++) {
-+		val = iwl_read_restricted_reg(priv, reg);
-+		if (val != le32_to_cpu(*image)) {
-+			IWL_ERROR("BSM uCode verification failed at "
-+				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
-+				  BSM_SRAM_LOWER_BOUND,
-+				  reg - BSM_SRAM_LOWER_BOUND, len,
-+				  val, le32_to_cpu(*image));
-+			return -EIO;
-+		}
++	switch (status & TX_STATUS_MSK) {
++	case TX_STATUS_SUCCESS:
++		return "SUCCESS";
++		TX_STATUS_ENTRY(SHORT_LIMIT);
++		TX_STATUS_ENTRY(LONG_LIMIT);
++		TX_STATUS_ENTRY(FIFO_UNDERRUN);
++		TX_STATUS_ENTRY(MGMNT_ABORT);
++		TX_STATUS_ENTRY(NEXT_FRAG);
++		TX_STATUS_ENTRY(LIFE_EXPIRE);
++		TX_STATUS_ENTRY(DEST_PS);
++		TX_STATUS_ENTRY(ABORTED);
++		TX_STATUS_ENTRY(BT_RETRY);
++		TX_STATUS_ENTRY(STA_INVALID);
++		TX_STATUS_ENTRY(FRAG_DROPPED);
++		TX_STATUS_ENTRY(TID_DISABLE);
++		TX_STATUS_ENTRY(FRAME_FLUSHED);
++		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
++		TX_STATUS_ENTRY(TX_LOCKED);
++		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
 +	}
 +
-+	IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
-+
-+	return 0;
++	return "UNKNOWN";
 +}
 +
 +/**
-+ * iwl_load_bsm - Load bootstrap instructions
-+ *
-+ * BSM operation:
-+ *
-+ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
-+ * in special SRAM that does not power down during RFKILL.  When powering back
-+ * up after power-saving sleeps (or during initial uCode load), the BSM loads
-+ * the bootstrap program into the on-board processor, and starts it.
-+ *
-+ * The bootstrap program loads (via DMA) instructions and data for a new
-+ * program from host DRAM locations indicated by the host driver in the
-+ * BSM_DRAM_* registers.  Once the new program is loaded, it starts
-+ * automatically.
-+ *
-+ * When initializing the NIC, the host driver points the BSM to the
-+ * "initialize" uCode image.  This uCode sets up some internal data, then
-+ * notifies host via "initialize alive" that it is complete.
-+ *
-+ * The host then replaces the BSM_DRAM_* pointer values to point to the
-+ * normal runtime uCode instructions and a backup uCode data cache buffer
-+ * (filled initially with starting data values for the on-board processor),
-+ * then triggers the "initialize" uCode to load and launch the runtime uCode,
-+ * which begins normal operation.
-+ *
-+ * When doing a power-save shutdown, runtime uCode saves data SRAM into
-+ * the backup data cache in DRAM before SRAM is powered down.
++ * iwl_scan_cancel - Cancel any currently executing HW scan
 + *
-+ * When powering back up, the BSM loads the bootstrap program.  This reloads
-+ * the runtime uCode instructions and the backup data cache into SRAM,
-+ * and re-launches the runtime uCode from where it left off.
++ * NOTE: priv->mutex is not required before calling this function
 + */
-+static int iwl_load_bsm(struct iwl_priv *priv)
++static int iwl_scan_cancel(struct iwl_priv *priv)
 +{
-+	__le32 *image = priv->ucode_boot.v_addr;
-+	u32 len = priv->ucode_boot.len;
-+	dma_addr_t pinst;
-+	dma_addr_t pdata;
-+	u32 inst_len;
-+	u32 data_len;
-+	int rc;
-+	int i;
-+	u32 done;
-+	u32 reg_offset;
++	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
++		clear_bit(STATUS_SCANNING, &priv->status);
++		return 0;
++	}
 +
-+	IWL_DEBUG_INFO("Begin load bsm\n");
++	if (test_bit(STATUS_SCANNING, &priv->status)) {
++		if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++			IWL_DEBUG_SCAN("Queuing scan abort.\n");
++			set_bit(STATUS_SCAN_ABORTING, &priv->status);
++			queue_work(priv->workqueue, &priv->abort_scan);
 +
-+	/* make sure bootstrap program is no larger than BSM's SRAM size */
-+	if (len > IWL_MAX_BSM_SIZE)
-+		return -EINVAL;
++		} else
++			IWL_DEBUG_SCAN("Scan abort already in progress.\n");
 +
-+	/* Tell bootstrap uCode where to find the "Initialize" uCode
-+	 *   in host DRAM ... bits 31:0 for 3945, bits 35:4 for 4965.
-+	 * NOTE:  iwl_initialize_alive_start() will replace these values,
-+	 *        after the "initialize" uCode has run, to point to
-+	 *        runtime/protocol instructions and backup data cache. */
-+#if IWL == 3945
-+	pinst = priv->ucode_init.p_addr;
-+	pdata = priv->ucode_init_data.p_addr;
-+#elif IWL == 4965
-+	pinst = priv->ucode_init.p_addr >> 4;
-+	pdata = priv->ucode_init_data.p_addr >> 4;
-+#endif
-+	inst_len = priv->ucode_init.len;
-+	data_len = priv->ucode_init_data.len;
++		return test_bit(STATUS_SCANNING, &priv->status);
++	}
 +
-+	rc = iwl_grab_restricted_access(priv);
-+	if (rc)
-+		return rc;
++	return 0;
++}
 +
-+	iwl_write_restricted_reg(priv, BSM_DRAM_INST_PTR_REG, pinst);
-+	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-+	iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
-+	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
++/**
++ * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
++ * @ms: amount of time to wait (in milliseconds) for scan to abort
++ *
++ * NOTE: priv->mutex must be held before calling this function
++ */
++static int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
++{
++	unsigned long now = jiffies;
++	int ret;
 +
-+	/* Fill BSM memory with bootstrap instructions */
-+	for (reg_offset = BSM_SRAM_LOWER_BOUND;
-+	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
-+	     reg_offset += sizeof(u32), image++)
-+		_iwl_write_restricted_reg(priv, reg_offset,
-+					  le32_to_cpu(*image));
++	ret = iwl_scan_cancel(priv);
++	if (ret && ms) {
++		mutex_unlock(&priv->mutex);
++		while (!time_after(jiffies, now + msecs_to_jiffies(ms)) &&
++				test_bit(STATUS_SCANNING, &priv->status))
++			msleep(1);
++		mutex_lock(&priv->mutex);
 +
-+	rc = iwl_verify_bsm(priv);
-+	if (rc) {
-+		iwl_release_restricted_access(priv);
-+		return rc;
++		return test_bit(STATUS_SCANNING, &priv->status);
 +	}
 +
-+	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
-+	iwl_write_restricted_reg(priv, BSM_WR_MEM_SRC_REG, 0x0);
-+	iwl_write_restricted_reg(priv, BSM_WR_MEM_DST_REG,
-+				 RTC_INST_LOWER_BOUND);
-+	iwl_write_restricted_reg(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
-+
-+	/* Load bootstrap code into instruction SRAM now,
-+	 *   to prepare to load "initialize" uCode */
-+	iwl_write_restricted_reg(priv, BSM_WR_CTRL_REG,
-+		BSM_WR_CTRL_REG_BIT_START);
++	return ret;
++}
 +
-+	/* Wait for load of bootstrap uCode to finish */
-+	for (i = 0; i < 100; i++) {
-+		done = iwl_read_restricted_reg(priv, BSM_WR_CTRL_REG);
-+		if (!(done & BSM_WR_CTRL_REG_BIT_START))
-+			break;
-+		udelay(10);
-+	}
-+	if (i < 100)
-+		IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
-+	else {
-+		IWL_ERROR("BSM write did not complete!\n");
-+		return -EIO;
-+	}
++static void iwl_sequence_reset(struct iwl_priv *priv)
++{
++	/* Reset ieee stats */
 +
-+	/* Enable future boot loads whenever power management unit triggers it
-+	 *   (e.g. when powering back up after power-save shutdown) */
-+	iwl_write_restricted_reg(priv, BSM_WR_CTRL_REG,
-+		BSM_WR_CTRL_REG_BIT_START_EN);
++	/* We don't reset the net_device_stats (ieee->stats) on
++	 * re-association */
 +
-+	iwl_release_restricted_access(priv);
++	priv->last_seq_num = -1;
++	priv->last_frag_num = -1;
++	priv->last_packet_time = 0;
 +
-+	return 0;
++	iwl_scan_cancel(priv);
 +}
 +
-+static void iwl_nic_start(struct iwl_priv *priv)
-+{
-+	/* Remove all resets to allow NIC to operate */
-+	iwl_write32(priv, CSR_RESET, 0);
-+}
++#define MAX_UCODE_BEACON_INTERVAL	4096
++#define INTEL_CONN_LISTEN_INTERVAL	__constant_cpu_to_le16(0xA)
 +
-+/**
-+ * iwl_read_ucode - Read uCode images from disk file.
-+ *
-+ * Copy into buffers for card to fetch via bus-mastering
-+ */
-+static int iwl_read_ucode(struct iwl_priv *priv)
++static __le16 iwl_adjust_beacon_interval(u16 beacon_val)
 +{
-+	struct iwl_ucode *ucode;
-+	int rc = 0;
-+	const struct firmware *ucode_raw;
-+#if IWL == 3945
-+	/* firmware file name contains uCode/driver compatibility version */
-+	const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode";
-+#elif IWL == 4965
-+	const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode";
-+#endif
-+	u8 *src;
-+	size_t len;
-+	u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
++	u16 new_val = 0;
++	u16 beacon_factor = 0;
 +
-+	/* Ask kernel firmware_class module to get the boot firmware off disk.
-+	 * request_firmware() is synchronous, file is in memory on return. */
-+	rc = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
-+	if (rc < 0) {
-+		IWL_ERROR("%s firmware file req failed: Reason %d\n", name, rc);
-+		goto error;
-+	}
++	beacon_factor =
++	    (beacon_val + MAX_UCODE_BEACON_INTERVAL)
++		/ MAX_UCODE_BEACON_INTERVAL;
++	new_val = beacon_val / beacon_factor;
++
++	return cpu_to_le16(new_val);
++}
 +
-+	IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
-+		       name, ucode_raw->size);
++static void iwl_setup_rxon_timing(struct iwl_priv *priv)
++{
++	u64 interval_tm_unit;
++	u64 tsf, result;
++	unsigned long flags;
++	struct ieee80211_conf *conf = NULL;
++	u16 beacon_int = 0;
 +
-+	/* Make sure that we got at least our header! */
-+	if (ucode_raw->size < sizeof(*ucode)) {
-+		IWL_ERROR("File size way too small!\n");
-+		rc = -EINVAL;
-+		goto err_release;
-+	}
++	conf = ieee80211_get_hw_conf(priv->hw);
 +
-+	/* Data from ucode file:  header followed by uCode images */
-+	ucode = (void *)ucode_raw->data;
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp1);
++	priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp0);
 +
-+	ver = le32_to_cpu(ucode->ver);
-+	inst_size = le32_to_cpu(ucode->inst_size);
-+	data_size = le32_to_cpu(ucode->data_size);
-+	init_size = le32_to_cpu(ucode->init_size);
-+	init_data_size = le32_to_cpu(ucode->init_data_size);
-+	boot_size = le32_to_cpu(ucode->boot_size);
++	priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;
 +
-+	IWL_DEBUG_INFO("f/w package hdr ucode version = 0x%x\n", ver);
-+	IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n",
-+		       inst_size);
-+	IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n",
-+		       data_size);
-+	IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n",
-+		       init_size);
-+	IWL_DEBUG_INFO("f/w package hdr init data size = %u\n",
-+		       init_data_size);
-+	IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n",
-+		       boot_size);
++	tsf = priv->timestamp1;
++	tsf = ((tsf << 32) | priv->timestamp0);
 +
-+	/* Verify size of file vs. image size info in file's header */
-+	if (ucode_raw->size < sizeof(*ucode) +
-+		inst_size + data_size + init_size +
-+		init_data_size + boot_size) {
++	beacon_int = priv->beacon_int;
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+		IWL_DEBUG_INFO("uCode file size %d too small\n",
-+			       (int)ucode_raw->size);
-+		rc = -EINVAL;
-+		goto err_release;
-+	}
++	if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
++		if (beacon_int == 0) {
++			priv->rxon_timing.beacon_interval = cpu_to_le16(100);
++			priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
++		} else {
++			priv->rxon_timing.beacon_interval =
++				cpu_to_le16(beacon_int);
++			priv->rxon_timing.beacon_interval =
++			    iwl_adjust_beacon_interval(
++				le16_to_cpu(priv->rxon_timing.beacon_interval));
++		}
 +
-+	/* Verify that uCode images will fit in card's SRAM */
-+	if (inst_size > IWL_MAX_INST_SIZE) {
-+		IWL_DEBUG_INFO("uCode instr len %d too large to fit in card\n",
-+			       (int)inst_size);
-+		rc = -EINVAL;
-+		goto err_release;
++		priv->rxon_timing.atim_window = 0;
++	} else {
++		priv->rxon_timing.beacon_interval =
++			iwl_adjust_beacon_interval(conf->beacon_int);
++		/* TODO: we need to get atim_window from upper stack
++		 * for now we set to 0 */
++		priv->rxon_timing.atim_window = 0;
 +	}
 +
-+	if (data_size > IWL_MAX_DATA_SIZE) {
-+		IWL_DEBUG_INFO("uCode data len %d too large to fit in card\n",
-+			       (int)data_size);
-+		rc = -EINVAL;
-+		goto err_release;
++	interval_tm_unit =
++		(le16_to_cpu(priv->rxon_timing.beacon_interval) * 1024);
++	result = do_div(tsf, interval_tm_unit);
++	priv->rxon_timing.beacon_init_val =
++	    cpu_to_le32((u32) ((u64) interval_tm_unit - result));
++
++	IWL_DEBUG_ASSOC
++	    ("beacon interval %d beacon timer %d beacon tim %d\n",
++		le16_to_cpu(priv->rxon_timing.beacon_interval),
++		le32_to_cpu(priv->rxon_timing.beacon_init_val),
++		le16_to_cpu(priv->rxon_timing.atim_window));
++}
++
++static int iwl_scan_initiate(struct iwl_priv *priv)
++{
++	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
++		IWL_ERROR("APs don't scan.\n");
++		return 0;
 +	}
-+	if (init_size > IWL_MAX_INST_SIZE) {
-+		IWL_DEBUG_INFO
-+		    ("uCode init instr len %d too large to fit in card\n",
-+		     (int)init_size);
-+		rc = -EINVAL;
-+		goto err_release;
++
++	if (!iwl_is_ready_rf(priv)) {
++		IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
++		return -EIO;
 +	}
-+	if (init_data_size > IWL_MAX_DATA_SIZE) {
-+		IWL_DEBUG_INFO
-+		    ("uCode init data len %d too large to fit in card\n",
-+		     (int)init_data_size);
-+		rc = -EINVAL;
-+		goto err_release;
++
++	if (test_bit(STATUS_SCANNING, &priv->status)) {
++		IWL_DEBUG_SCAN("Scan already in progress.\n");
++		return -EAGAIN;
 +	}
-+	if (boot_size > IWL_MAX_BSM_SIZE) {
-+		IWL_DEBUG_INFO
-+		    ("uCode boot instr len %d too large to fit in bsm\n",
-+		     (int)boot_size);
-+		rc = -EINVAL;
-+		goto err_release;
++
++	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++		IWL_DEBUG_SCAN("Scan request while abort pending.  "
++			       "Queuing.\n");
++		return -EAGAIN;
 +	}
 +
-+	/* Allocate ucode buffers for card's bus-master loading ... */
++	IWL_DEBUG_INFO("Starting scan...\n");
++	priv->scan_bands = 2;
++	set_bit(STATUS_SCANNING, &priv->status);
++	priv->scan_start = jiffies;
++	priv->scan_pass_start = priv->scan_start;
 +
-+	/* Runtime instructions and 2 copies of data:
-+	 * 1) unmodified from disk
-+	 * 2) backup cache for save/restore during power-downs */
-+	priv->ucode_code.len = inst_size;
-+	priv->ucode_code.v_addr =
-+	    pci_alloc_consistent(priv->pci_dev,
-+				 priv->ucode_code.len,
-+				 &(priv->ucode_code.p_addr));
++	queue_work(priv->workqueue, &priv->request_scan);
 +
-+	priv->ucode_data.len = data_size;
-+	priv->ucode_data.v_addr =
-+	    pci_alloc_consistent(priv->pci_dev,
-+				 priv->ucode_data.len,
-+				 &(priv->ucode_data.p_addr));
++	return 0;
++}
 +
-+	priv->ucode_data_backup.len = data_size;
-+	priv->ucode_data_backup.v_addr =
-+	    pci_alloc_consistent(priv->pci_dev,
-+				 priv->ucode_data_backup.len,
-+				 &(priv->ucode_data_backup.p_addr));
++static int iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
++{
++	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
 +
++	if (hw_decrypt)
++		rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
++	else
++		rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
 +
-+	/* Initialization instructions and data */
-+	priv->ucode_init.len = init_size;
-+	priv->ucode_init.v_addr =
-+	    pci_alloc_consistent(priv->pci_dev,
-+				 priv->ucode_init.len,
-+				 &(priv->ucode_init.p_addr));
++	return 0;
++}
 +
-+	priv->ucode_init_data.len = init_data_size;
-+	priv->ucode_init_data.v_addr =
-+	    pci_alloc_consistent(priv->pci_dev,
-+				 priv->ucode_init_data.len,
-+				 &(priv->ucode_init_data.p_addr));
++static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode)
++{
++	if (phymode == MODE_IEEE80211A) {
++		priv->staging_rxon.flags &=
++		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
++		      | RXON_FLG_CCK_MSK);
++		priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
++	} else {
++		/* Copied from iwl_bg_post_associate() */
++		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
++			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
++		else
++			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 +
-+	/* Bootstrap (instructions only, no data) */
-+	priv->ucode_boot.len = boot_size;
-+	priv->ucode_boot.v_addr =
-+	    pci_alloc_consistent(priv->pci_dev,
-+				 priv->ucode_boot.len,
-+				 &(priv->ucode_boot.p_addr));
++		if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
++			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 +
-+	if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
-+	    !priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr ||
-+	    !priv->ucode_boot.v_addr || !priv->ucode_data_backup.v_addr)
-+		goto err_pci_alloc;
++		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
++		priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
++		priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
++	}
++}
 +
-+	/* Copy images into buffers for card's bus-master reads ... */
++/*
++ * initilize rxon structure with default values fromm eeprom
++ */
++static void iwl_connection_init_rx_config(struct iwl_priv *priv)
++{
++	const struct iwl_channel_info *ch_info;
 +
-+	/* Runtime instructions (first block of data in file) */
-+	src = &ucode->data[0];
-+	len = priv->ucode_code.len;
-+	IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %d\n",
-+		       (int)len);
-+	memcpy(priv->ucode_code.v_addr, src, len);
-+	IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
-+		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
++	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
 +
-+	/* Runtime data (2nd block)
-+	 * NOTE:  Copy into backup buffer will be done in iwl_up()  */
-+	src = &ucode->data[inst_size];
-+	len = priv->ucode_data.len;
-+	IWL_DEBUG_INFO("Copying (but not loading) uCode data len %d\n",
-+		       (int)len);
-+	memcpy(priv->ucode_data.v_addr, src, len);
-+	memcpy(priv->ucode_data_backup.v_addr, src, len);
++	switch (priv->iw_mode) {
++	case IEEE80211_IF_TYPE_AP:
++		priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
++		break;
 +
-+	/* Initialization instructions (3rd block) */
-+	if (init_size) {
-+		src = &ucode->data[inst_size + data_size];
-+		len = priv->ucode_init.len;
-+		IWL_DEBUG_INFO("Copying (but not loading) init instr len %d\n",
-+			       (int)len);
-+		memcpy(priv->ucode_init.v_addr, src, len);
++	case IEEE80211_IF_TYPE_STA:
++		priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
++		priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
++		break;
++
++	case IEEE80211_IF_TYPE_IBSS:
++		priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
++		priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
++		priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
++						  RXON_FILTER_ACCEPT_GRP_MSK;
++		break;
++
++	case IEEE80211_IF_TYPE_MNTR:
++		priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
++		priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
++		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
++		break;
 +	}
 +
-+	/* Initialization data (4th block) */
-+	if (init_data_size) {
-+		src = &ucode->data[inst_size + data_size + init_size];
-+		len = priv->ucode_init_data.len;
-+		IWL_DEBUG_INFO("Copying (but not loading) init data len %d\n",
-+			       (int)len);
-+		memcpy(priv->ucode_init_data.v_addr, src, len);
-+	}
++#if 0
++	/* TODO:  Figure out when short_preamble would be set and cache from
++	 * that */
++	if (!hw_to_local(priv->hw)->short_preamble)
++		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
++	else
++		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
++#endif
 +
-+	/* Bootstrap instructions (5th block) */
-+	src = &ucode->data[inst_size + data_size + init_size + init_data_size];
-+	len = priv->ucode_boot.len;
-+	IWL_DEBUG_INFO("Copying (but not loading) boot instr len %d\n",
-+		       (int)len);
-+	memcpy(priv->ucode_boot.v_addr, src, len);
++	ch_info = iwl_get_channel_info(priv, priv->phymode,
++				       le16_to_cpu(priv->staging_rxon.channel));
 +
-+	/* We have our copies now, allow OS release its copies */
-+	release_firmware(ucode_raw);
-+	return 0;
++	if (!ch_info)
++		ch_info = &priv->channel_info[0];
 +
-+ err_pci_alloc:
-+	IWL_ERROR("failed to allocate pci memory\n");
-+	rc = -ENOMEM;
-+	iwl_dealloc_ucode_pci(priv);
++	/*
++	 * in some case A channels are all non IBSS
++	 * in this case force B/G channel
++	 */
++	if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
++	    !(is_channel_ibss(ch_info)))
++		ch_info = &priv->channel_info[0];
 +
-+ err_release:
-+	release_firmware(ucode_raw);
++	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
++	if (is_channel_a_band(ch_info))
++		priv->phymode = MODE_IEEE80211A;
++	else
++		priv->phymode = MODE_IEEE80211G;
 +
-+ error:
-+	return rc;
-+}
++	iwl_set_flags_for_phymode(priv, priv->phymode);
 +
++	priv->staging_rxon.ofdm_basic_rates =
++	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
++	priv->staging_rxon.cck_basic_rates =
++	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
 +
-+/**
-+ * iwl_set_ucode_ptrs - Set uCode address location
-+ *
-+ * Tell initialization uCode where to find runtime uCode.
-+ *
-+ * BSM registers initially contain pointers to initialization uCode.
-+ * We need to replace them to load runtime uCode inst and data,
-+ * and to save runtime data when powering down.
-+ */
-+static int iwl_set_ucode_ptrs(struct iwl_priv *priv)
++	priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
++					RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
++	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
++	memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN);
++	priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff;
++	priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff;
++	iwl4965_set_rxon_chain(priv);
++}
++
++static int iwl_set_mode(struct iwl_priv *priv, int mode)
 +{
-+	dma_addr_t pinst;
-+	dma_addr_t pdata;
-+	int rc = 0;
-+	unsigned long flags;
++	if (!iwl_is_ready_rf(priv))
++		return -EAGAIN;
 +
-+#if IWL == 3945
-+	/* bits 31:0 for 3945 */
-+	pinst = priv->ucode_code.p_addr;
-+	pdata = priv->ucode_data_backup.p_addr;
-+#else
-+	/* bits 35:4 for 4965 */
-+	pinst = priv->ucode_code.p_addr >> 4;
-+	pdata = priv->ucode_data_backup.p_addr >> 4;
-+#endif
++	if (mode == IEEE80211_IF_TYPE_IBSS) {
++		const struct iwl_channel_info *ch_info;
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	rc = iwl_grab_restricted_access(priv);
-+	if (rc) {
-+		spin_unlock_irqrestore(&priv->lock, flags);
-+		return rc;
++		ch_info = iwl_get_channel_info(priv,
++			priv->phymode,
++			le16_to_cpu(priv->staging_rxon.channel));
++
++		if (!ch_info || !is_channel_ibss(ch_info)) {
++			IWL_ERROR("channel %d not IBSS channel\n",
++				  le16_to_cpu(priv->staging_rxon.channel));
++			return -EINVAL;
++		}
 +	}
 +
-+	/* Tell bootstrap uCode where to find image to load */
-+	iwl_write_restricted_reg(priv, BSM_DRAM_INST_PTR_REG, pinst);
-+	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-+	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
-+				 priv->ucode_data.len);
++	cancel_delayed_work(&priv->scan_check);
++	if (iwl_scan_cancel_timeout(priv, 100)) {
++		IWL_WARNING("Aborted scan still in progress after 100ms\n");
++		IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
++		return -EAGAIN;
++	}
 +
-+	/* Inst bytecount must be last to set up, bit 31 signals uCode
-+	 *   that all new ptr/size info is in place */
-+	iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG,
-+				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
++	priv->iw_mode = mode;
 +
-+	iwl_release_restricted_access(priv);
++	iwl_connection_init_rx_config(priv);
++	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
 +
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	iwl_clear_stations_table(priv);
 +
-+	IWL_DEBUG_INFO("Runtime uCode pointers are set.\n");
++	iwl_commit_rxon(priv);
 +
-+	return rc;
++	return 0;
 +}
 +
-+/**
-+ * iwl_init_alive_start - Called after REPLY_ALIVE notification receieved
-+ *
-+ * Called after REPLY_ALIVE notification received from "initialize" uCode.
-+ *
-+ * The 4965 "initialize" ALIVE reply contains calibration data for:
-+ *   Voltage, temperature, and MIMO tx gain correction, now stored in priv
-+ *   (3945 does not contain this data).
-+ *
-+ * Tell "initialize" uCode to go ahead and load the runtime uCode.
-+*/
-+static void iwl_init_alive_start(struct iwl_priv *priv)
++static void iwl_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
++				      struct ieee80211_tx_control *ctl,
++				      struct iwl_cmd *cmd,
++				      struct sk_buff *skb_frag,
++				      int last_frag)
 +{
-+	/* Check alive response for "valid" sign from uCode */
-+	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
-+		/* We had an error bringing up the hardware, so take it
-+		 * all the way back down so we can try again */
-+		IWL_DEBUG_INFO("Initialize Alive failed.\n");
-+		goto restart;
-+	}
++	struct iwl_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
 +
-+	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
-+	 * This is a paranoid check, because we would not have gotten the
-+	 * "initialize" alive if code weren't properly loaded.  */
-+	if (iwl_verify_ucode(priv)) {
-+		/* Runtime instruction load was bad;
-+		 * take it all the way back down so we can try again */
-+		IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
-+		goto restart;
-+	}
++	switch (keyinfo->alg) {
++	case ALG_CCMP:
++		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
 +
-+#if IWL == 4965
-+	/* Calculate temperature */
-+	priv->temperature = iwl4965_get_temperature(priv);
++		cmd->cmd.tx.hdr[0].frame_control |=
++		    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++		/* XXX: ACK flag must be set for CCMP even if it
++		 * is a multicast/broadcast packet, because CCMP
++		 * group communication encrypted by GTK is
++		 * actually done by the AP. */
++		cmd->cmd.tx.tx_flags |= TX_CMD_FLG_ACK_MSK;
++		memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
++		IWL_DEBUG_TX("tx_cmd with aes  hwcrypto\n");
++		break;
++	case ALG_TKIP:
++#if 0
++		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
++
++		if (last_frag)
++			memcpy(cmd->cmd.tx.tkip_mic.byte, skb_frag->tail - 8,
++			       8);
++		else
++			memset(cmd->cmd.tx.tkip_mic.byte, 0, 8);
++
++		cmd->cmd.tx.hdr[0].frame_control |=
++		    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++		/* XXX: ACK flag must be set for CCMP even if it
++		 * is a multicast/broadcast packet, because CCMP
++		 * group communication encrypted by GTK is
++		 * actually done by the AP. */
++		cmd->cmd.tx.tx_flags |= TX_CMD_FLG_ACK_MSK;
 +#endif
++		break;
++	case ALG_WEP:
++		cmd->cmd.tx.sec_ctl = 1 |	/* WEP */
++		    (ctl->key_idx & 0x3) << 6;
 +
-+	/* Send pointers to protocol/runtime uCode image ... init code will
-+	 * load and launch runtime uCode, which will send us another "Alive"
-+	 * notification. */
-+	IWL_DEBUG_INFO("Initialization Alive received.\n");
-+	if (iwl_set_ucode_ptrs(priv)) {
-+		/* Runtime instruction load won't happen;
-+		 * take it all the way back down so we can try again */
-+		IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n");
-+		goto restart;
++		if (keyinfo->keylen == 13)
++			cmd->cmd.tx.sec_ctl |= (1 << 3);	/* 128-bit */
++
++		memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen);
++
++		cmd->cmd.tx.hdr[0].frame_control |=
++		    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++
++		IWL_DEBUG_TX("Configuring packet for WEP encryption "
++			     "with key %d\n", ctl->key_idx);
++		break;
++
++	case ALG_NONE:
++		IWL_DEBUG_TX("Tx packet in the clear "
++			     "(encrypt requested).\n");
++		break;
++
++	default:
++		printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
++		break;
 +	}
-+	return;
 +
-+ restart:
-+	queue_work(priv->workqueue, &priv->restart);
 +}
 +
-+
-+/**
-+ * iwl_alive_start - called after REPLY_ALIVE notification received
-+ *                   from protocol/runtime uCode (initialization uCode's
-+ *                   Alive gets handled by iwl_init_alive_start()).
++/*
++ * handle build REPLY_TX command notification.
 + */
-+static void iwl_alive_start(struct iwl_priv *priv)
++static void iwl_build_tx_cmd_basic(struct iwl_priv *priv,
++				  struct iwl_cmd *cmd,
++				  struct ieee80211_tx_control *ctrl,
++				  struct ieee80211_hdr *hdr,
++				  int is_unicast, u8 std_id)
 +{
-+	int rc = 0;
-+#if IWL == 3945
-+	int thermal_spin = 0;
-+	u32 rfkill;
-+#endif
-+
-+	IWL_DEBUG_INFO("Runtime Alive received.\n");
++	__le16 *qc;
++	u16 fc = le16_to_cpu(hdr->frame_control);
++	__le32 tx_flags = cmd->cmd.tx.tx_flags;
 +
-+	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
-+		/* We had an error bringing up the hardware, so take it
-+		 * all the way back down so we can try again */
-+		IWL_DEBUG_INFO("Alive failed.\n");
-+		goto restart;
++	cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
++	if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) {
++		tx_flags |= TX_CMD_FLG_ACK_MSK;
++		if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
++			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
++		if (ieee80211_is_probe_response(fc) &&
++		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
++			tx_flags |= TX_CMD_FLG_TSF_MSK;
++	} else {
++		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
++		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
 +	}
 +
-+	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
-+	 * This is a paranoid check, because we would not have gotten the
-+	 * "runtime" alive if code weren't properly loaded.  */
-+	if (iwl_verify_ucode(priv)) {
-+		/* Runtime instruction load was bad;
-+		 * take it all the way back down so we can try again */
-+		IWL_DEBUG_INFO("Bad runtime uCode load.\n");
-+		goto restart;
-+	}
++	cmd->cmd.tx.sta_id = std_id;
++	if (ieee80211_get_morefrag(hdr))
++		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
 +
-+	iwl_clear_stations_table(priv);
++	qc = ieee80211_get_qos_ctrl(hdr);
++	if (qc) {
++		cmd->cmd.tx.tid_tspec = (u8) (le16_to_cpu(*qc) & 0xf);
++		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
++	} else
++		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
 +
-+#if IWL == 4965
-+	rc = iwl4965_alive_notify(priv);
-+	if (rc) {
-+		IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
-+			    rc);
-+		goto restart;
-+	}
-+#elif IWL == 3945
-+	rc = iwl_grab_restricted_access(priv);
-+	if (rc) {
-+		IWL_WARNING("Can not read rfkill status from adapter\n");
-+		return;
++	if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
++		tx_flags |= TX_CMD_FLG_RTS_MSK;
++		tx_flags &= ~TX_CMD_FLG_CTS_MSK;
++	} else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
++		tx_flags &= ~TX_CMD_FLG_RTS_MSK;
++		tx_flags |= TX_CMD_FLG_CTS_MSK;
 +	}
 +
-+	rfkill = iwl_read_restricted_reg(priv, ALM_APMG_RFKILL);
-+	IWL_DEBUG_INFO("RFKILL status: 0x%x\n", rfkill);
-+	iwl_release_restricted_access(priv);
-+
-+	if (rfkill & 0x1) {
-+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
-+		/* if rfkill is not on, then wait for thermal
-+		 * sensor in adapter to kick in */
-+		while (iwl_hw_get_temperature(priv) == 0) {
-+			thermal_spin++;
-+			udelay(10);
-+		}
++	if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
++		tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
 +
-+		if (thermal_spin)
-+			IWL_DEBUG_INFO("Thermal calibration took %dus\n",
-+				       thermal_spin * 10);
++	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
++	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
++		if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ ||
++		    (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
++			cmd->cmd.tx.timeout.pm_frame_timeout =
++				cpu_to_le16(3);
++		else
++			cmd->cmd.tx.timeout.pm_frame_timeout =
++				cpu_to_le16(2);
 +	} else
-+		set_bit(STATUS_RF_KILL_HW, &priv->status);
-+#endif
++		cmd->cmd.tx.timeout.pm_frame_timeout = 0;
 +
-+	/* After the ALIVE response, we can process host commands */
-+	set_bit(STATUS_ALIVE, &priv->status);
++	cmd->cmd.tx.driver_txop = 0;
++	cmd->cmd.tx.tx_flags = tx_flags;
++	cmd->cmd.tx.next_frame_len = 0;
++}
 +
-+	/* Clear out the uCode error bit if it is set */
-+	clear_bit(STATUS_FW_ERROR, &priv->status);
++static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
++{
++	int sta_id;
++	u16 fc = le16_to_cpu(hdr->frame_control);
 +
-+	rc = iwl_init_channel_map(priv);
-+	if (rc) {
-+		IWL_ERROR("initializing regulatory failed: %d\n", rc);
-+		return;
-+	}
++	/* If this frame is broadcast or not data then use the broadcast
++	 * station id */
++	if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
++	    is_multicast_ether_addr(hdr->addr1))
++		return IWL_BROADCAST_ID;
 +
-+	iwl_init_geos(priv);
++	switch (priv->iw_mode) {
 +
-+	if (iwl_is_rfkill(priv))
-+		return;
++	/* If this frame is part of a BSS network (we're a station), then
++	 * we use the AP's station id */
++	case IEEE80211_IF_TYPE_STA:
++		return IWL_AP_ID;
 +
-+	if (!priv->mac80211_registered) {
-+		/* Unlock so any user space entry points can call back into
-+		 * the driver without a deadlock... */
-+		mutex_unlock(&priv->mutex);
-+		iwl_rate_control_register(priv->hw);
-+		rc = ieee80211_register_hw(priv->hw);
-+		priv->hw->conf.beacon_int = 100;
-+		mutex_lock(&priv->mutex);
++	/* If we are an AP, then find the station, or use BCAST */
++	case IEEE80211_IF_TYPE_AP:
++		sta_id = iwl_hw_find_station(priv, hdr->addr1);
++		if (sta_id != IWL_INVALID_STATION)
++			return sta_id;
++		return IWL_BROADCAST_ID;
 +
-+		if (rc) {
-+			IWL_ERROR("Failed to register network "
-+				  "device (error %d)\n", rc);
-+			return;
-+		}
++	/* If this frame is part of a IBSS network, then we use the
++	 * target specific station id */
++	case IEEE80211_IF_TYPE_IBSS:
++		sta_id = iwl_hw_find_station(priv, hdr->addr1);
++		if (sta_id != IWL_INVALID_STATION)
++			return sta_id;
 +
-+		priv->mac80211_registered = 1;
++		sta_id = iwl_add_station(priv, hdr->addr1, 0, CMD_ASYNC);
 +
-+		iwl_reset_channel_flag(priv);
-+	} else
-+		ieee80211_start_queues(priv->hw);
++		if (sta_id != IWL_INVALID_STATION)
++			return sta_id;
 +
-+	priv->active_rate = priv->rates_mask;
-+	priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
++		IWL_DEBUG_DROP("Station " MAC_FMT " not in station map. "
++			       "Defaulting to broadcast...\n",
++			       MAC_ARG(hdr->addr1));
++		iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
++		return IWL_BROADCAST_ID;
 +
-+	iwl_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode));
++	default:
++		IWL_WARNING("Unkown mode of operation: %d", priv->iw_mode);
++		return IWL_BROADCAST_ID;
++	}
++}
 +
-+	if (iwl_is_associated(priv)) {
-+		struct iwl_rxon_cmd *active_rxon =
-+				(struct iwl_rxon_cmd *)(&priv->active_rxon);
++/*
++ * start REPLY_TX command process
++ */
++static int iwl_tx_skb(struct iwl_priv *priv,
++		      struct sk_buff *skb, struct ieee80211_tx_control *ctl)
++{
++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++	struct iwl_tfd_frame *tfd;
++	u32 *control_flags;
++	int txq_id = ctl->queue;
++	struct iwl_tx_queue *txq = NULL;
++	struct iwl_queue *q = NULL;
++	dma_addr_t phys_addr;
++	dma_addr_t txcmd_phys;
++	struct iwl_cmd *out_cmd = NULL;
++	u16 len, idx, len_org;
++	u8 id, hdr_len, unicast;
++	u8 sta_id;
++	u16 seq_number = 0;
++	u16 fc;
++	__le16 *qc;
++	u8 wait_write_ptr = 0;
++	unsigned long flags;
++	int rc;
 +
-+		memcpy(&priv->staging_rxon, &priv->active_rxon,
-+		       sizeof(priv->staging_rxon));
-+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-+	} else {
-+		/* Initialize our rx_config data */
-+		iwl_connection_init_rx_config(priv);
-+		memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
++	spin_lock_irqsave(&priv->lock, flags);
++	if (iwl_is_rfkill(priv)) {
++		IWL_DEBUG_DROP("Dropping - RF KILL\n");
++		goto drop_unlock;
 +	}
 +
-+	/* Configure BT coexistence */
-+	iwl_send_bt_config(priv);
++	if (!priv->interface_id) {
++		IWL_DEBUG_DROP("Dropping - !priv->interface_id\n");
++		goto drop_unlock;
++	}
 +
-+	/* Configure the adapter for unassociated operation */
-+	iwl_commit_rxon(priv);
++	if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
++		IWL_ERROR("ERROR: No TX rate available.\n");
++		goto drop_unlock;
++	}
 +
-+	/* At this point, the NIC is initialized and operational */
-+	priv->notif_missed_beacons = 0;
-+	set_bit(STATUS_READY, &priv->status);
++	unicast = !is_multicast_ether_addr(hdr->addr1);
++	id = 0;
 +
-+	iwl3945_reg_txpower_periodic(priv);
++	fc = le16_to_cpu(hdr->frame_control);
 +
-+#if IWL == 4965
-+	iwl4965_rf_kill_ct_config(priv);
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (ieee80211_is_auth(fc))
++		IWL_DEBUG_TX("Sending AUTH frame\n");
++	else if (ieee80211_is_assoc_request(fc))
++		IWL_DEBUG_TX("Sending ASSOC frame\n");
++	else if (ieee80211_is_reassoc_request(fc))
++		IWL_DEBUG_TX("Sending REASSOC frame\n");
 +#endif
-+	IWL_DEBUG_INFO("ALIVE processing complete.\n");
 +
-+	if (priv->error_recovering)
-+		iwl_error_recovery(priv);
++	if (!iwl_is_associated(priv) &&
++	    ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
++		IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
++		goto drop_unlock;
++	}
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	hdr_len = ieee80211_get_hdrlen(fc);
++	sta_id = iwl_get_sta_id(priv, hdr);
++	if (sta_id == IWL_INVALID_STATION) {
++		IWL_DEBUG_DROP("Dropping - INVALID STATION: " MAC_FMT "\n",
++			       MAC_ARG(hdr->addr1));
++		goto drop;
++	}
++
++	IWL_DEBUG_RATE("station Id %d\n", sta_id);
++
++	qc = ieee80211_get_qos_ctrl(hdr);
++	if (qc) {
++		u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
++		seq_number = priv->stations[sta_id].tid[tid].seq_number &
++				IEEE80211_SCTL_SEQ;
++		hdr->seq_ctrl = cpu_to_le16(seq_number) |
++			(hdr->seq_ctrl &
++				__constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
++		seq_number += 0x10;
++#ifdef CONFIG_IWLWIFI_HT
++#ifdef CONFIG_IWLWIFI_HT_AGG
++		/* aggregation is on for this <sta,tid> */
++		if (ctl->flags & IEEE80211_TXCTL_HT_MPDU_AGG)
++			txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
++#endif /* CONFIG_IWLWIFI_HT_AGG */
++#endif /* CONFIG_IWLWIFI_HT */
++	}
++	txq = &priv->txq[txq_id];
++	q = &txq->q;
++
++	spin_lock_irqsave(&priv->lock, flags);
 +
-+	return;
++	tfd = &txq->bd[q->first_empty];
++	memset(tfd, 0, sizeof(*tfd));
++	control_flags = (u32 *) tfd;
++	idx = get_cmd_index(q, q->first_empty, 0);
 +
-+ restart:
-+	queue_work(priv->workqueue, &priv->restart);
-+}
++	memset(&(txq->txb[q->first_empty]), 0, sizeof(struct iwl_tx_info));
++	txq->txb[q->first_empty].skb[0] = skb;
++	memcpy(&(txq->txb[q->first_empty].status.control),
++	       ctl, sizeof(struct ieee80211_tx_control));
++	out_cmd = &txq->cmd[idx];
++	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
++	memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx));
++	out_cmd->hdr.cmd = REPLY_TX;
++	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
++				INDEX_TO_SEQ(q->first_empty)));
++	/* copy frags header */
++	memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len);
 +
-+static void iwl_cancel_deferred_work(struct iwl_priv *priv);
++	/* hdr = (struct ieee80211_hdr *)out_cmd->cmd.tx.hdr; */
++	len = priv->hw_setting.tx_cmd_len +
++		sizeof(struct iwl_cmd_header) + hdr_len;
 +
-+static void __iwl_down(struct iwl_priv *priv)
-+{
-+	unsigned long flags;
-+	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
-+	struct ieee80211_conf *conf = NULL;
++	len_org = len;
++	len = (len + 3) & ~3;
 +
-+	IWL_WARNING("ipw going down \n");
++	if (len_org != len)
++		len_org = 1;
++	else
++		len_org = 0;
 +
-+	conf = ieee80211_get_hw_conf(priv->hw);
++	txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
++		     offsetof(struct iwl_cmd, hdr);
 +
-+	if (!exit_pending)
-+		set_bit(STATUS_EXIT_PENDING, &priv->status);
++	iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
 +
-+	iwl_clear_stations_table(priv);
++	if (ctl->key_idx != -1)
++		iwl_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
 +
-+	/* Unblock any waiting calls */
-+	wake_up_interruptible_all(&priv->wait_command_queue);
++	/* 802.11 null functions have no payload... */
++	len = skb->len - hdr_len;
++	if (len) {
++		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
++					   len, PCI_DMA_TODEVICE);
++		iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
++	}
 +
-+	iwl_cancel_deferred_work(priv);
++	if (len_org)
++		out_cmd->cmd.tx.tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
 +
-+	/* Wipe out the EXIT_PENDING status bit if we are not actually
-+	 * exiting the module */
-+	if (!exit_pending)
-+		clear_bit(STATUS_EXIT_PENDING, &priv->status);
++	len = (u16)skb->len;
++	out_cmd->cmd.tx.len = cpu_to_le16(len);
 +
-+	/* stop and reset the on-board processor */
-+	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
++	/* TODO need this for burst mode later on */
++	iwl_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
 +
-+	/* tell the device to stop sending interrupts */
-+	iwl_disable_interrupts(priv);
++	/* set is_hcca to 0; it probably will never be implemented */
++	iwl_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
 +
-+	if (priv->mac80211_registered)
-+		ieee80211_stop_queues(priv->hw);
++	iwl4965_tx_cmd(priv, out_cmd, sta_id, txcmd_phys,
++		       hdr, hdr_len, ctl, NULL);
 +
-+	/* If we have not previously called iwl_init() then
-+	 * clear all bits but the RF Kill and SUSPEND bits and return */
-+	if (!iwl_is_init(priv)) {
-+		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
-+					STATUS_RF_KILL_HW |
-+			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-+					STATUS_RF_KILL_SW |
-+			       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-+					STATUS_IN_SUSPEND;
-+		goto exit;
++	if (!ieee80211_get_morefrag(hdr)) {
++		txq->need_update = 1;
++		if (qc) {
++			u8 tid = (u8)(le16_to_cpu(*qc) & 0xf);
++			priv->stations[sta_id].tid[tid].seq_number = seq_number;
++		}
++	} else {
++		wait_write_ptr = 1;
++		txq->need_update = 0;
 +	}
 +
-+	/* ...otherwise clear out all the status bits but the RF Kill and
-+	 * SUSPEND bits and continue taking the NIC down. */
-+	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
-+				STATUS_RF_KILL_HW |
-+			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-+				STATUS_RF_KILL_SW |
-+			test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-+				STATUS_IN_SUSPEND |
-+			test_bit(STATUS_FW_ERROR, &priv->status) <<
-+				STATUS_FW_ERROR;
++	iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
++			   sizeof(out_cmd->cmd.tx));
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
++			   ieee80211_get_hdrlen(fc));
 +
-+	iwl_hw_txq_ctx_stop(priv);
-+	iwl_hw_rxq_stop(priv);
++	iwl4965_tx_queue_update_wr_ptr(priv, txq, len);
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	if (!iwl_grab_restricted_access(priv)) {
-+		iwl_write_restricted_reg(priv, ALM_APMG_CLK_DIS,
-+					 APMG_CLK_REG_VAL_DMA_CLK_RQT);
-+		iwl_release_restricted_access(priv);
-+	}
++	q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
++	rc = iwl_tx_queue_update_write_ptr(priv, txq);
 +	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+	udelay(5);
++	if (rc)
++		return rc;
 +
-+	iwl_hw_nic_stop_master(priv);
-+	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
-+	iwl_hw_nic_reset(priv);
++	if ((iwl_queue_space(q) < q->high_mark)
++	    && priv->mac80211_registered) {
++		if (wait_write_ptr) {
++			spin_lock_irqsave(&priv->lock, flags);
++			txq->need_update = 1;
++			iwl_tx_queue_update_write_ptr(priv, txq);
++			spin_unlock_irqrestore(&priv->lock, flags);
++		}
 +
-+ exit:
-+	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
++		ieee80211_stop_queue(priv->hw, ctl->queue);
++	}
 +
-+	if (priv->ibss_beacon)
-+		dev_kfree_skb(priv->ibss_beacon);
-+	priv->ibss_beacon = NULL;
++	return 0;
 +
-+	/* clear out any free frames */
-+	iwl_clear_free_frames(priv);
++drop_unlock:
++	spin_unlock_irqrestore(&priv->lock, flags);
++drop:
++	return -1;
 +}
 +
-+static void iwl_down(struct iwl_priv *priv)
++static void iwl_set_rate(struct iwl_priv *priv)
 +{
-+	mutex_lock(&priv->mutex);
-+	__iwl_down(priv);
-+	mutex_unlock(&priv->mutex);
-+}
++	const struct ieee80211_hw_mode *hw = NULL;
++	struct ieee80211_rate *rate;
++	int i;
 +
-+#define MAX_HW_RESTARTS 5
++	hw = iwl_get_hw_mode(priv, priv->phymode);
 +
-+static int __iwl_up(struct iwl_priv *priv)
-+{
-+	int rc, i;
++	priv->active_rate = 0;
++	priv->active_rate_basic = 0;
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-+		IWL_WARNING("Exit pending; will not bring the NIC up\n");
-+		return -EIO;
-+	}
++	IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
++		       hw->mode == MODE_IEEE80211A ?
++		       'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
 +
-+	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
-+		IWL_WARNING("Radio disabled by SW RF kill (module "
-+			    "parameter)\n");
-+		return 0;
++	for (i = 0; i < hw->num_rates; i++) {
++		rate = &(hw->rates[i]);
++		if ((rate->val < IWL_RATE_COUNT) &&
++		    (rate->flags & IEEE80211_RATE_SUPPORTED)) {
++			IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
++				       rate->val, iwl_rates[rate->val].plcp,
++				       (rate->flags & IEEE80211_RATE_BASIC) ?
++				       "*" : "");
++			priv->active_rate |= (1 << rate->val);
++			if (rate->flags & IEEE80211_RATE_BASIC)
++				priv->active_rate_basic |= (1 << rate->val);
++		} else
++			IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
++				       rate->val, iwl_rates[rate->val].plcp);
 +	}
 +
-+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
++	IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
++		       priv->active_rate, priv->active_rate_basic);
 +
-+	rc = iwl_hw_nic_init(priv);
-+	if (rc) {
-+		IWL_ERROR("Unable to int nic\n");
-+		return rc;
-+	}
++	/*
++	 * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK)
++	 * otherwise set it to the default of all CCK rates and 6, 12, 24 for
++	 * OFDM
++	 */
++	if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK)
++		priv->staging_rxon.cck_basic_rates =
++		    ((priv->active_rate_basic &
++		      IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF;
++	else
++		priv->staging_rxon.cck_basic_rates =
++		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
 +
-+	/* make sure rfkill handshake bits are cleared */
-+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-+		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
++	if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK)
++		priv->staging_rxon.ofdm_basic_rates =
++		    ((priv->active_rate_basic &
++		      (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >>
++		      IWL_FIRST_OFDM_RATE) & 0xFF;
++	else
++		priv->staging_rxon.ofdm_basic_rates =
++		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
++}
 +
-+	/* clear (again), then enable host interrupts */
-+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-+	iwl_enable_interrupts(priv);
++static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
++{
++	unsigned long flags;
++
++	if (disable_radio ? 1 : 0 ==
++	    test_bit(STATUS_RF_KILL_SW, &priv->status) ? 1 : 0)
++		return;
++
++	IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO %s\n",
++			  disable_radio ? "OFF" : "ON");
++
++	if (disable_radio) {
++		iwl_scan_cancel(priv);
++		/* FIXME: This is a workaround for AP */
++		if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
++			spin_lock_irqsave(&priv->lock, flags);
++			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
++				    CSR_UCODE_SW_BIT_RFKILL);
++			spin_unlock_irqrestore(&priv->lock, flags);
++			iwl_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
++			set_bit(STATUS_RF_KILL_SW, &priv->status);
++		}
++		return;
++	}
 +
-+	/* really make sure rfkill handshake bits are cleared */
-+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	spin_lock_irqsave(&priv->lock, flags);
 +	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
 +
-+	/* Copy original ucode data image from disk into backup cache.
-+	 * This will be used to initialize the on-board processor's
-+	 * data SRAM for a clean start when the runtime program first loads. */
-+	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
-+			priv->ucode_data.len);
++	clear_bit(STATUS_RF_KILL_SW, &priv->status);
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+#if IWL == 4965
-+	{
-+		u32 hw_rf_kill = 0;
++	/* wake up ucode */
++	msleep(10);
 +
-+		/* If platform's RF_KILL switch is set to KILL,
-+		 * wait for BIT_INT_RF_KILL interrupt before loading uCode
-+		 * and getting things started */
-+		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
-+					CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
-+			hw_rf_kill = 1;
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl_read32(priv, CSR_UCODE_DRV_GP1);
++	if (!iwl_grab_restricted_access(priv))
++		iwl_release_restricted_access(priv);
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+		if (test_bit(STATUS_RF_KILL_HW, &priv->status) || hw_rf_kill) {
-+			IWL_WARNING("Radio disabled by HW RF Kill switch\n");
-+			return 0;
-+		}
++	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
++		IWL_DEBUG_RF_KILL("Can not turn radio back on - "
++				  "disabled by HW switch\n");
++		return;
 +	}
-+#endif
 +
-+	for (i = 0; i < MAX_HW_RESTARTS; i++) {
++	queue_work(priv->workqueue, &priv->restart);
++	return;
++}
 +
-+		iwl_clear_stations_table(priv);
++void iwl_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
++			    u32 decrypt_res, struct ieee80211_rx_status *stats)
++{
++	u16 fc =
++	    le16_to_cpu(((struct ieee80211_hdr *)skb->data)->frame_control);
 +
-+		/* load bootstrap state machine,
-+		 * load bootstrap program into processor's memory,
-+		 * prepare to load the "initialize" uCode */
-+		rc = iwl_load_bsm(priv);
++	if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
++		return;
 +
-+		if (rc) {
-+			IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc);
-+			continue;
++	if (!(fc & IEEE80211_FCTL_PROTECTED))
++		return;
++
++	IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res);
++	switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
++	case RX_RES_STATUS_SEC_TYPE_TKIP:
++		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
++		    RX_RES_STATUS_BAD_ICV_MIC)
++			stats->flag |= RX_FLAG_MMIC_ERROR;
++	case RX_RES_STATUS_SEC_TYPE_WEP:
++	case RX_RES_STATUS_SEC_TYPE_CCMP:
++		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
++		    RX_RES_STATUS_DECRYPT_OK) {
++			IWL_DEBUG_RX("hw decrypt successfully!!!\n");
++			stats->flag |= RX_FLAG_DECRYPTED;
 +		}
++		break;
 +
-+		/* start card; "initialize" will load runtime ucode */
-+		iwl_nic_start(priv);
++	default:
++		break;
++	}
++}
 +
-+		/* MAC Address location in EEPROM same for 3945/4965 */
-+		get_eeprom_mac(priv, priv->mac_addr);
-+		IWL_DEBUG_INFO("MAC address: " MAC_FMT "\n",
-+			       MAC_ARG(priv->mac_addr));
++void iwl_handle_data_packet_monitor(struct iwl_priv *priv,
++				    struct iwl_rx_mem_buffer *rxb,
++				    void *data, short len,
++				    struct ieee80211_rx_status *stats,
++				    u16 phy_flags)
++{
++	struct iwl_rt_rx_hdr *iwl_rt;
 +
-+		SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
++	/* First cache any information we need before we overwrite
++	 * the information provided in the skb from the hardware */
++	s8 signal = stats->ssi;
++	s8 noise = 0;
++	int rate = stats->rate;
++	u64 tsf = stats->mactime;
++	__le16 phy_flags_hw = cpu_to_le16(phy_flags);
 +
-+		return 0;
++	/* We received data from the HW, so stop the watchdog */
++	if (len > IWL_RX_BUF_SIZE - sizeof(*iwl_rt)) {
++		IWL_DEBUG_DROP("Dropping too large packet in monitor\n");
++		return;
 +	}
 +
-+	set_bit(STATUS_EXIT_PENDING, &priv->status);
-+	__iwl_down(priv);
-+
-+	/* tried to restart and config the device for as long as our
-+	 * patience could withstand */
-+	IWL_ERROR("Unable to initialize device after %d attempts.\n", i);
-+	return -EIO;
-+}
-+
++	/* copy the frame data to write after where the radiotap header goes */
++	iwl_rt = (void *)rxb->skb->data;
++	memmove(iwl_rt->payload, data, len);
 +
-+/*****************************************************************************
-+ *
-+ * Workqueue callbacks
-+ *
-+ *****************************************************************************/
++	iwl_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
++	iwl_rt->rt_hdr.it_pad = 0; /* always good to zero */
 +
-+static void iwl_bg_init_alive_start(struct work_struct *data)
-+{
-+	struct iwl_priv *priv =
-+	    container_of(data, struct iwl_priv, init_alive_start.work);
++	/* total header + data */
++	iwl_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*iwl_rt));
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+		return;
++	/* Set the size of the skb to the size of the frame */
++	skb_put(rxb->skb, sizeof(*iwl_rt) + len);
 +
-+	mutex_lock(&priv->mutex);
-+	iwl_init_alive_start(priv);
-+	mutex_unlock(&priv->mutex);
-+}
++	/* Big bitfield of all the fields we provide in radiotap */
++	iwl_rt->rt_hdr.it_present =
++	    cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
++			(1 << IEEE80211_RADIOTAP_FLAGS) |
++			(1 << IEEE80211_RADIOTAP_RATE) |
++			(1 << IEEE80211_RADIOTAP_CHANNEL) |
++			(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
++			(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
++			(1 << IEEE80211_RADIOTAP_ANTENNA));
 +
-+static void iwl_bg_alive_start(struct work_struct *data)
-+{
-+	struct iwl_priv *priv =
-+	    container_of(data, struct iwl_priv, alive_start.work);
++	/* Zero the flags, we'll add to them as we go */
++	iwl_rt->rt_flags = 0;
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+		return;
++	iwl_rt->rt_tsf = cpu_to_le64(tsf);
 +
-+	mutex_lock(&priv->mutex);
-+	iwl_alive_start(priv);
-+	mutex_unlock(&priv->mutex);
-+}
++	/* Convert to dBm */
++	iwl_rt->rt_dbmsignal = signal;
++	iwl_rt->rt_dbmnoise = noise;
 +
-+static void iwl_bg_rf_kill(struct work_struct *work)
-+{
-+	struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
++	/* Convert the channel frequency and set the flags */
++	iwl_rt->rt_channelMHz = cpu_to_le16(stats->freq);
++	if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
++		iwl_rt->rt_chbitmask =
++		    cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
++	else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
++		iwl_rt->rt_chbitmask =
++		    cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
++	else	/* 802.11g */
++		iwl_rt->rt_chbitmask =
++		    cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ));
 +
-+	wake_up_interruptible(&priv->wait_command_queue);
++	rate = iwl_rate_index_from_plcp(rate);
++	if (rate == -1)
++		iwl_rt->rt_rate = 0;
++	else
++		iwl_rt->rt_rate = iwl_rates[rate].ieee;
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+		return;
++	/* antenna number */
++	iwl_rt->rt_antenna =
++		le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
 +
-+	mutex_lock(&priv->mutex);
++	/* set the preamble flag if we have it */
++	if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
++		iwl_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
 +
-+	if (!iwl_is_rfkill(priv)) {
-+		IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
-+			  "HW and/or SW RF Kill no longer active, restarting "
-+			  "device\n");
-+		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
-+			queue_work(priv->workqueue, &priv->restart);
-+	} else {
++	IWL_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
 +
-+		if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
-+			IWL_DEBUG_RF_KILL("Can not turn radio back on - "
-+					  "disabled by SW switch\n");
-+		else
-+			IWL_WARNING("Radio Frequency Kill Switch is On:\n"
-+				    "Kill switch must be turned off for "
-+				    "wireless networking to work.\n");
-+	}
-+	mutex_unlock(&priv->mutex);
++	stats->flag |= RX_FLAG_RADIOTAP;
++	ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
++	rxb->skb = NULL;
 +}
 +
-+#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
 +
-+static void iwl_bg_scan_check(struct work_struct *data)
++#define IWL_PACKET_RETRY_TIME HZ
++
++int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
 +{
-+	struct iwl_priv *priv =
-+	    container_of(data, struct iwl_priv, scan_check.work);
++	u16 sc = le16_to_cpu(header->seq_ctrl);
++	u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
++	u16 frag = sc & IEEE80211_SCTL_FRAG;
++	u16 *last_seq, *last_frag;
++	unsigned long *last_time;
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+		return;
++	switch (priv->iw_mode) {
++	case IEEE80211_IF_TYPE_IBSS:{
++		struct list_head *p;
++		struct iwl_ibss_seq *entry = NULL;
++		u8 *mac = header->addr2;
++		int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
 +
-+	mutex_lock(&priv->mutex);
-+	if (test_bit(STATUS_SCANNING, &priv->status) ||
-+	    test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-+		IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN,
-+			  "Scan completion watchdog resetting adapter (%dms)\n",
-+			  jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
-+		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
-+			queue_work(priv->workqueue, &priv->restart);
++		__list_for_each(p, &priv->ibss_mac_hash[index]) {
++			entry =
++				list_entry(p, struct iwl_ibss_seq, list);
++			if (!compare_ether_addr(entry->mac, mac))
++				break;
++		}
++		if (p == &priv->ibss_mac_hash[index]) {
++			entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
++			if (!entry) {
++				IWL_ERROR
++					("Cannot malloc new mac entry\n");
++				return 0;
++			}
++			memcpy(entry->mac, mac, ETH_ALEN);
++			entry->seq_num = seq;
++			entry->frag_num = frag;
++			entry->packet_time = jiffies;
++			list_add(&entry->list,
++				 &priv->ibss_mac_hash[index]);
++			return 0;
++		}
++		last_seq = &entry->seq_num;
++		last_frag = &entry->frag_num;
++		last_time = &entry->packet_time;
++		break;
 +	}
-+	mutex_unlock(&priv->mutex);
-+}
-+
-+static void iwl_bg_request_scan(struct work_struct *data)
-+{
-+	struct iwl_priv *priv =
-+	    container_of(data, struct iwl_priv, request_scan);
-+	struct iwl_host_cmd cmd = {
-+		.id = REPLY_SCAN_CMD,
-+		.len = sizeof(struct iwl_scan_cmd),
-+		.meta.flags = CMD_SIZE_HUGE,
-+	};
-+	int rc = 0;
-+	struct iwl_scan_cmd *scan;
-+	struct ieee80211_conf *conf = NULL;
-+	u8 direct_mask;
-+	int phymode;
-+
-+	conf = ieee80211_get_hw_conf(priv->hw);
++	case IEEE80211_IF_TYPE_STA:
++		last_seq = &priv->last_seq_num;
++		last_frag = &priv->last_frag_num;
++		last_time = &priv->last_packet_time;
++		break;
++	default:
++		return 0;
++	}
++	if ((*last_seq == seq) &&
++	    time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
++		if (*last_frag == frag)
++			goto drop;
++		if (*last_frag + 1 != frag)
++			/* out-of-order fragment */
++			goto drop;
++	} else
++		*last_seq = seq;
 +
-+	mutex_lock(&priv->mutex);
++	*last_frag = frag;
++	*last_time = jiffies;
++	return 0;
 +
-+	if (!iwl_is_ready(priv)) {
-+		IWL_WARNING("request scan called when driver not ready.\n");
-+		goto done;
-+	}
++ drop:
++	return 1;
++}
 +
-+	/* Make sure the scan wasn't cancelled before this queued work
-+	 * was given the chance to run... */
-+	if (!test_bit(STATUS_SCANNING, &priv->status))
-+		goto done;
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
 +
-+	/* This should never be called or scheduled if there is currently
-+	 * a scan active in the hardware. */
-+	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-+		IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. "
-+			       "Ignoring second request.\n");
-+		rc = -EIO;
-+		goto done;
-+	}
++#include "iwl-spectrum.h"
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-+		IWL_DEBUG_SCAN("Aborting scan due to device shutdown\n");
-+		goto done;
-+	}
++#define BEACON_TIME_MASK_LOW	0x00FFFFFF
++#define BEACON_TIME_MASK_HIGH	0xFF000000
++#define TIME_UNIT		1024
 +
-+	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-+		IWL_DEBUG_HC("Scan request while abort pending.  Queuing.\n");
-+		goto done;
-+	}
++/*
++ * extended beacon time format
++ * time in usec will be changed into a 32-bit value in 8:24 format
++ * the high 1 byte is the beacon counts
++ * the lower 3 bytes is the time in usec within one beacon interval
++ */
 +
-+	if (iwl_is_rfkill(priv)) {
-+		IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
-+		goto done;
-+	}
++static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
++{
++	u32 quot;
++	u32 rem;
++	u32 interval = beacon_interval * 1024;
 +
-+	if (!test_bit(STATUS_READY, &priv->status)) {
-+		IWL_DEBUG_HC("Scan request while uninitialized.  Queuing.\n");
-+		goto done;
-+	}
++	if (!interval || !usec)
++		return 0;
 +
-+	if (!priv->scan_bands) {
-+		IWL_DEBUG_HC("Aborting scan due to no requested bands\n");
-+		goto done;
-+	}
++	quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
++	rem = (usec % interval) & BEACON_TIME_MASK_LOW;
 +
-+	if (!priv->scan) {
-+		priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
-+				     IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-+		if (!priv->scan) {
-+			rc = -ENOMEM;
-+			goto done;
-+		}
-+	}
-+	scan = priv->scan;
-+	memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
++	return (quot << 24) + rem;
++}
 +
-+	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
-+	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
++/* base is usually what we get from ucode with each received frame,
++ * the same as HW timer counter counting down
++ */
 +
-+	if (iwl_is_associated(priv)) {
-+		u16 interval = 0;
-+		u32 extra;
-+		u32 suspend_time = 100;
-+		u32 scan_suspend_time = 100;
-+		unsigned long flags;
++static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
++{
++	u32 base_low = base & BEACON_TIME_MASK_LOW;
++	u32 addon_low = addon & BEACON_TIME_MASK_LOW;
++	u32 interval = beacon_interval * TIME_UNIT;
++	u32 res = (base & BEACON_TIME_MASK_HIGH) +
++	    (addon & BEACON_TIME_MASK_HIGH);
 +
-+		IWL_DEBUG_INFO("Scanning while associated...\n");
++	if (base_low > addon_low)
++		res += base_low - addon_low;
++	else if (base_low < addon_low) {
++		res += interval + base_low - addon_low;
++		res += (1 << 24);
++	} else
++		res += (1 << 24);
 +
-+		spin_lock_irqsave(&priv->lock, flags);
-+		interval = priv->beacon_int;
-+		spin_unlock_irqrestore(&priv->lock, flags);
++	return cpu_to_le32(res);
++}
 +
-+		scan->suspend_time = 0;
-+		scan->max_out_time = cpu_to_le32(600 * 1024);
-+		if (!interval)
-+			interval = suspend_time;
-+#if IWL == 3945
-+		/*
-+		 * suspend time format:
-+		 *  0-19: beacon interval in usec (time before exec.)
-+		 * 20-23: 0
-+		 * 24-31: number of beacons (suspend between channels)
-+		 */
++static int iwl_get_measurement(struct iwl_priv *priv,
++			       struct ieee80211_measurement_params *params,
++			       u8 type)
++{
++	struct iwl_spectrum_cmd spectrum;
++	struct iwl_rx_packet *res;
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
++		.data = (void *)&spectrum,
++		.meta.flags = CMD_WANT_SKB,
++	};
++	u32 add_time = le64_to_cpu(params->start_time);
++	int rc;
++	int spectrum_resp_status;
++	int duration = le16_to_cpu(params->duration);
 +
-+		extra = (suspend_time / interval) << 24;
-+		scan_suspend_time = 0xFF0FFFFF &
-+		    (extra | ((suspend_time % interval) * 1024));
-+#else
-+		extra = (suspend_time / interval) << 22;
-+		scan_suspend_time = (extra |
-+		    ((suspend_time % interval) * 1024));
-+#endif
-+		scan->suspend_time = cpu_to_le32(scan_suspend_time);
-+		IWL_DEBUG_SCAN("suspend_time 0x%X beacon interval %d\n",
-+			       scan_suspend_time, interval);
-+	}
++	if (iwl_is_associated(priv))
++		add_time =
++		    iwl_usecs_to_beacons(
++			le64_to_cpu(params->start_time) - priv->last_tsf,
++			le16_to_cpu(priv->rxon_timing.beacon_interval));
 +
-+	/* We should add the ability for user to lock to PASSIVE ONLY */
-+	if (priv->one_direct_scan) {
-+		IWL_DEBUG_SCAN
-+		    ("Kicking off one direct scan for '%s'\n",
-+		     iwl_escape_essid(priv->direct_ssid,
-+				      priv->direct_ssid_len));
-+		scan->direct_scan[0].id = WLAN_EID_SSID;
-+		scan->direct_scan[0].len = priv->direct_ssid_len;
-+		memcpy(scan->direct_scan[0].ssid,
-+		       priv->direct_ssid, priv->direct_ssid_len);
-+		direct_mask = 1;
-+	} else if (!iwl_is_associated(priv)) {
-+		scan->direct_scan[0].id = WLAN_EID_SSID;
-+		scan->direct_scan[0].len = priv->essid_len;
-+		memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
-+		direct_mask = 1;
-+	} else
-+		direct_mask = 0;
++	memset(&spectrum, 0, sizeof(spectrum));
 +
-+	/* We don't build a direct scan probe request; the uCode will do
-+	 * that based on the direct_mask added to each channel entry */
-+	scan->tx_cmd.len = cpu_to_le16(
-+		iwl_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
-+			IWL_MAX_SCAN_SIZE - sizeof(scan), 0));
-+	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
-+	scan->tx_cmd.sta_id = IWL_BROADCAST_ID;
-+	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
++	spectrum.channel_count = cpu_to_le16(1);
++	spectrum.flags =
++	    RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
++	spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
++	cmd.len = sizeof(spectrum);
++	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
 +
-+	/* flags + rate selection */
++	if (iwl_is_associated(priv))
++		spectrum.start_time =
++		    iwl_add_beacon_time(priv->last_beacon_time,
++				add_time,
++				le16_to_cpu(priv->rxon_timing.beacon_interval));
++	else
++		spectrum.start_time = 0;
 +
-+#if IWL == 4965
-+	scan->tx_cmd.tx_flags |= cpu_to_le32(0x200);
-+#endif
++	spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
++	spectrum.channels[0].channel = params->channel;
++	spectrum.channels[0].type = type;
++	if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
++		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
++		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
 +
-+	switch (priv->scan_bands) {
-+	case 2:
-+		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
-+#if IWL == 3945
-+		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
-+#elif IWL == 4965
-+		scan->tx_cmd.rate_n_flags =
-+				iwl_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
-+				RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);
-+#endif
++	rc = iwl_send_cmd_sync(priv, &cmd);
++	if (rc)
++		return rc;
 +
-+		scan->good_CRC_th = 0;
-+		phymode = MODE_IEEE80211G;
-+		break;
++	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
++	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
++		IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n");
++		rc = -EIO;
++	}
 +
-+	case 1:
-+#if IWL == 3945
-+		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
-+#elif IWL == 4965
-+		scan->tx_cmd.rate_n_flags =
-+				iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
-+				RATE_MCS_ANT_B_MSK);
-+#endif
-+		scan->good_CRC_th = IWL_GOOD_CRC_TH;
-+		phymode = MODE_IEEE80211A;
++	spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
++	switch (spectrum_resp_status) {
++	case 0:		/* Command will be handled */
++		if (res->u.spectrum.id != 0xff) {
++			IWL_DEBUG_INFO
++			    ("Replaced existing measurement: %d\n",
++			     res->u.spectrum.id);
++			priv->measurement_status &= ~MEASUREMENT_READY;
++		}
++		priv->measurement_status |= MEASUREMENT_ACTIVE;
++		rc = 0;
 +		break;
 +
-+	default:
-+		IWL_WARNING("Invalid scan band count\n");
-+		goto done;
++	case 1:		/* Command will not be handled */
++		rc = -EAGAIN;
++		break;
 +	}
 +
-+	/* select Rx antennas/chains */
-+#if IWL == 3945
-+	scan->flags |= iwl3945_get_antenna_flags(priv);
++	dev_kfree_skb_any(cmd.meta.u.skb);
 +
-+#elif IWL == 4965
-+	/* Force use of chains B and C (0x6) for scan Rx.
-+	 * Avoid A (0x1) because of its off-channel reception on A-band.
-+	 * MIMO is not used here, but value is required to make uCode happy. */
-+	scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
-+			cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
-+			(0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
-+			(0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
++	return rc;
++}
 +#endif
 +
-+	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
-+		scan->filter_flags = RXON_FILTER_PROMISC_MSK;
++static void iwl_txstatus_to_ieee(struct iwl_priv *priv,
++				 struct iwl_tx_info *tx_sta)
++{
 +
-+	if (direct_mask)
-+		IWL_DEBUG_SCAN
-+		    ("Initiating direct scan for %s.\n",
-+		     iwl_escape_essid(priv->essid, priv->essid_len));
++	tx_sta->status.ack_signal = 0;
++	tx_sta->status.excessive_retries = 0;
++	tx_sta->status.queue_length = 0;
++	tx_sta->status.queue_number = 0;
++
++	if (in_interrupt())
++		ieee80211_tx_status_irqsafe(priv->hw,
++					    tx_sta->skb[0], &(tx_sta->status));
 +	else
-+		IWL_DEBUG_SCAN("Initiating indirect scan.\n");
++		ieee80211_tx_status(priv->hw,
++				    tx_sta->skb[0], &(tx_sta->status));
 +
-+	scan->channel_count =
-+		iwl_get_channels_for_scan(
-+			priv, phymode, 1, /* active */
-+			direct_mask,
-+			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++	tx_sta->skb[0] = NULL;
++}
 +
-+	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
-+	    scan->channel_count * sizeof(struct iwl_scan_channel);
-+	cmd.data = scan;
-+	scan->len = cpu_to_le16(cmd.len);
++/**
++ * iwl_tx_queue_reclaim - Reclaim Tx queue entries no more used by NIC.
++ *
++ * When FW advances 'R' index, all entries between old and
++ * new 'R' index need to be reclaimed. As result, some free space
++ * forms. If there is enough free space (> low mark), wake Tx queue.
++ */
++int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
++{
++	struct iwl_tx_queue *txq = &priv->txq[txq_id];
++	struct iwl_queue *q = &txq->q;
++	int nfreed = 0;
 +
-+	set_bit(STATUS_SCAN_HW, &priv->status);
-+	rc = iwl_send_cmd_sync(priv, &cmd);
-+	if (rc)
-+		goto done;
++	if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) {
++		IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
++			  "is out of range [0-%d] %d %d.\n", txq_id,
++			  index, q->n_bd, q->first_empty, q->last_used);
++		return 0;
++	}
 +
-+	queue_delayed_work(priv->workqueue, &priv->scan_check,
-+			   IWL_SCAN_CHECK_WATCHDOG);
++	for (index = iwl_queue_inc_wrap(index, q->n_bd);
++		q->last_used != index;
++		q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd)) {
++		if (txq_id != IWL_CMD_QUEUE_NUM) {
++			iwl_txstatus_to_ieee(priv,
++					&(txq->txb[txq->q.last_used]));
++			iwl_hw_txq_free_tfd(priv, txq);
++		} else if (nfreed > 1) {
++			IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
++					q->first_empty, q->last_used);
++			queue_work(priv->workqueue, &priv->restart);
++		}
++		nfreed++;
++	}
 +
-+	mutex_unlock(&priv->mutex);
-+	return;
++	if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
++			(txq_id != IWL_CMD_QUEUE_NUM) &&
++			priv->mac80211_registered)
++		ieee80211_wake_queue(priv->hw, txq_id);
 +
-+ done:
-+	/* inform mac80211 sacn aborted */
-+	queue_work(priv->workqueue, &priv->scan_completed);
-+	mutex_unlock(&priv->mutex);
++
++	return nfreed;
 +}
 +
-+static void iwl_bg_up(struct work_struct *data)
++static int iwl_is_tx_success(u32 status)
 +{
-+	struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
++	status &= TX_STATUS_MSK;
++	return (status == TX_STATUS_SUCCESS)
++	    || (status == TX_STATUS_DIRECT_DONE);
++}
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+		return;
++/******************************************************************************
++ *
++ * Generic RX handler implementations
++ *
++ ******************************************************************************/
++#ifdef CONFIG_IWLWIFI_HT
++#ifdef CONFIG_IWLWIFI_HT_AGG
 +
-+	mutex_lock(&priv->mutex);
-+	__iwl_up(priv);
-+	mutex_unlock(&priv->mutex);
++static inline int iwl_get_ra_sta_id(struct iwl_priv *priv,
++				    struct ieee80211_hdr *hdr)
++{
++	if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
++		return IWL_AP_ID;
++	else {
++		u8 *da = ieee80211_get_DA(hdr);
++		return iwl_hw_find_station(priv, da);
++	}
 +}
 +
-+static void iwl_bg_restart(struct work_struct *data)
++static struct ieee80211_hdr *iwl_tx_queue_get_hdr(
++	struct iwl_priv *priv, int txq_id, int idx)
 +{
-+	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
++	if (priv->txq[txq_id].txb[idx].skb[0])
++		return (struct ieee80211_hdr *)priv->txq[txq_id].
++				txb[idx].skb[0]->data;
++	return NULL;
++}
++
++static inline u32 iwl_get_scd_ssn(struct iwl_tx_resp *tx_resp)
++{
++	__le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
++				tx_resp->frame_count);
++	return le32_to_cpu(*scd_ssn) & MAX_SN;
++
++}
++static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
++				      struct iwl_ht_agg *agg,
++				      struct iwl_tx_resp *tx_resp,
++				      u16 start_idx)
++{
++	u32 status;
++	__le32 *frame_status = &tx_resp->status;
++	struct ieee80211_tx_status *tx_status = NULL;
++	struct ieee80211_hdr *hdr = NULL;
++	int i, sh;
++	int txq_id, idx;
++	u16 seq;
++
++	if (agg->wait_for_ba)
++		IWL_DEBUG_TX_REPLY("got tx repsons w/o back\n");
++
++	agg->frame_count = tx_resp->frame_count;
++	agg->start_idx = start_idx;
++	agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
++	agg->bitmap0 = agg->bitmap1 = 0;
++
++	if (agg->frame_count == 1) {
++		struct iwl_tx_queue *txq ;
++		status = le32_to_cpu(frame_status[0]);
++
++		txq_id = agg->txq_id;
++		txq = &priv->txq[txq_id];
++		/* FIXME: code repetition */
++		IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d \n",
++				   agg->frame_count, agg->start_idx);
++
++		tx_status = &(priv->txq[txq_id].txb[txq->q.last_used].status);
++		tx_status->retry_count = tx_resp->failure_frame;
++		tx_status->queue_number = status & 0xff;
++		tx_status->queue_length = tx_resp->bt_kill_count;
++		tx_status->queue_length |= tx_resp->failure_rts;
++
++		tx_status->flags = iwl_is_tx_success(status)?
++			IEEE80211_TX_STATUS_ACK : 0;
++		tx_status->control.tx_rate =
++				iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags);
++		/* FIXME: code repetition end */
++
++		IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
++				    status & 0xff, tx_resp->failure_frame);
++		IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n",
++				iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags));
++
++		agg->wait_for_ba = 0;
++	} else {
++		u64 bitmap = 0;
++		int start = agg->start_idx;
++
++		for (i = 0; i < agg->frame_count; i++) {
++			u16 sc;
++			status = le32_to_cpu(frame_status[i]);
++			seq  = status >> 16;
++			idx = SEQ_TO_INDEX(seq);
++			txq_id = SEQ_TO_QUEUE(seq);
++
++			if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
++				      AGG_TX_STATE_ABORT_MSK))
++				continue;
++
++			IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
++					   agg->frame_count, txq_id, idx);
++
++			hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
++
++			sc = le16_to_cpu(hdr->seq_ctrl);
++			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
++				IWL_ERROR("BUG_ON idx doesn't match seq control"
++					  " idx=%d, seq_idx=%d, seq=%d\n",
++					  idx, SEQ_TO_SN(sc),
++					  hdr->seq_ctrl);
++				return -1;
++			}
++
++			IWL_DEBUG_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n",
++					   i, idx, SEQ_TO_SN(sc));
++
++			sh = idx - start;
++			if (sh > 64) {
++				sh = (start - idx) + 0xff;
++				bitmap = bitmap << sh;
++				sh = 0;
++				start = idx;
++			} else if (sh < -64)
++				sh  = 0xff - (start - idx);
++			else if (sh < 0) {
++				sh = start - idx;
++				start = idx;
++				bitmap = bitmap << sh;
++				sh = 0;
++			}
++			bitmap |= (1 << sh);
++			IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n",
++					   start, (u32)(bitmap & 0xFFFFFFFF));
++		}
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+		return;
++		agg->bitmap0 = bitmap & 0xFFFFFFFF;
++		agg->bitmap1 = bitmap >> 32;
++		agg->start_idx = start;
++		agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
++		IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%x\n",
++				   agg->frame_count, agg->start_idx,
++				   agg->bitmap0);
 +
-+	iwl_down(priv);
-+	queue_work(priv->workqueue, &priv->up);
++		if (bitmap)
++			agg->wait_for_ba = 1;
++	}
++	return 0;
 +}
++#endif
++#endif
 +
-+static void iwl_bg_rx_replenish(struct work_struct *data)
++static void iwl_rx_reply_tx(struct iwl_priv *priv,
++			    struct iwl_rx_mem_buffer *rxb)
 +{
-+	struct iwl_priv *priv =
-+	    container_of(data, struct iwl_priv, rx_replenish);
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
++	int txq_id = SEQ_TO_QUEUE(sequence);
++	int index = SEQ_TO_INDEX(sequence);
++	struct iwl_tx_queue *txq = &priv->txq[txq_id];
++	struct ieee80211_tx_status *tx_status;
++	struct iwl_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
++	u32  status = le32_to_cpu(tx_resp->status);
++#ifdef CONFIG_IWLWIFI_HT
++#ifdef CONFIG_IWLWIFI_HT_AGG
++	int tid, sta_id;
++#endif
++#endif
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++	if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
++		IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
++			  "is out of range [0-%d] %d %d\n", txq_id,
++			  index, txq->q.n_bd, txq->q.first_empty,
++			  txq->q.last_used);
 +		return;
++	}
 +
-+	mutex_lock(&priv->mutex);
-+	iwl_rx_replenish(priv);
-+	mutex_unlock(&priv->mutex);
-+}
-+
-+static void iwl_bg_post_associate(struct work_struct *data)
-+{
-+	struct iwl_priv *priv = container_of(data, struct iwl_priv,
-+					     post_associate.work);
-+
-+	int rc = 0;
-+	struct ieee80211_conf *conf = NULL;
-+
-+	IWL_DEBUG_ASSOC("Associated as %d to: " MAC_FMT "\n",
-+			priv->assoc_id, MAC_ARG(priv->active_rxon.bssid_addr));
++#ifdef CONFIG_IWLWIFI_HT
++#ifdef CONFIG_IWLWIFI_HT_AGG
++	if (txq->sched_retry) {
++		const u32 scd_ssn = iwl_get_scd_ssn(tx_resp);
++		struct ieee80211_hdr *hdr =
++			iwl_tx_queue_get_hdr(priv, txq_id, index);
++		struct iwl_ht_agg *agg = NULL;
++		__le16 *qc = ieee80211_get_qos_ctrl(hdr);
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+		return;
++		if (qc == NULL) {
++			IWL_ERROR("BUG_ON qc is null!!!!\n");
++			return;
++		}
 +
-+	mutex_lock(&priv->mutex);
++		tid = le16_to_cpu(*qc) & 0xf;
 +
-+	conf = ieee80211_get_hw_conf(priv->hw);
++		sta_id = iwl_get_ra_sta_id(priv, hdr);
++		if (unlikely(sta_id == IWL_INVALID_STATION)) {
++			IWL_ERROR("Station not known for\n");
++			return;
++		}
 +
-+	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-+	iwl_commit_rxon(priv);
++		agg = &priv->stations[sta_id].tid[tid].agg;
 +
-+	memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
-+	iwl_setup_rxon_timing(priv);
-+	rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
-+			      sizeof(priv->rxon_timing), &priv->rxon_timing);
-+	if (rc)
-+		IWL_WARNING("REPLY_RXON_TIMING failed - "
-+			    "Attempting to continue.\n");
++		iwl4965_tx_status_reply_tx(priv, agg, tx_resp, index);
 +
-+	priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
++		if ((tx_resp->frame_count == 1) &&
++		    !iwl_is_tx_success(status)) {
++			/* TODO: send BAR */
++		}
 +
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+	if (priv->is_ht_enabled && priv->current_assoc_ht.is_ht)
-+		iwl4965_set_rxon_ht(priv, &priv->current_assoc_ht);
-+	else {
-+		priv->active_rate_ht[0] = 0;
-+		priv->active_rate_ht[1] = 0;
-+		priv->current_channel_width = IWL_CHANNEL_WIDTH_20MHZ;
-+	}
-+#endif /* CONFIG_IWLWIFI_HT*/
-+	iwl4965_set_rxon_chain(priv);
-+#endif
-+	priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
++		if ((txq->q.last_used != (scd_ssn & 0xff))) {
++			index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
++			IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
++					   "%d index %d\n", scd_ssn , index);
++			iwl_tx_queue_reclaim(priv, txq_id, index);
++		}
++	} else {
++#endif /* CONFIG_IWLWIFI_HT_AGG */
++#endif /* CONFIG_IWLWIFI_HT */
++	tx_status = &(txq->txb[txq->q.last_used].status);
 +
-+	IWL_DEBUG_ASSOC("assoc id %d beacon interval %d\n",
-+			priv->assoc_id, priv->beacon_int);
++	tx_status->retry_count = tx_resp->failure_frame;
++	tx_status->queue_number = status;
++	tx_status->queue_length = tx_resp->bt_kill_count;
++	tx_status->queue_length |= tx_resp->failure_rts;
 +
-+	if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
-+		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-+	else
-+		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
++	tx_status->flags =
++	    iwl_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
 +
-+	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
-+		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
-+			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
-+		else
-+			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
++	tx_status->control.tx_rate =
++		iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags);
 +
-+		if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
-+			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
++	IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
++		     "retries %d\n", txq_id, iwl_get_tx_fail_reason(status),
++		     status, le32_to_cpu(tx_resp->rate_n_flags),
++		     tx_resp->failure_frame);
 +
++	IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
++	if (index != -1)
++		iwl_tx_queue_reclaim(priv, txq_id, index);
++#ifdef CONFIG_IWLWIFI_HT
++#ifdef CONFIG_IWLWIFI_HT_AGG
 +	}
++#endif /* CONFIG_IWLWIFI_HT_AGG */
++#endif /* CONFIG_IWLWIFI_HT */
 +
-+	iwl_commit_rxon(priv);
++	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
++		IWL_ERROR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
++}
 +
-+	switch (priv->iw_mode) {
-+	case IEEE80211_IF_TYPE_STA:
-+		iwl_rate_scale_init(priv->hw, IWL_AP_ID);
-+		break;
 +
-+	case IEEE80211_IF_TYPE_IBSS:
++static void iwl_rx_reply_alive(struct iwl_priv *priv,
++			       struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_alive_resp *palive;
++	struct delayed_work *pwork;
 +
-+		/* clear out the station table */
-+		iwl_clear_stations_table(priv);
++	palive = &pkt->u.alive_frame;
 +
-+		iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
-+		iwl_rxon_add_station(priv, priv->bssid, 0);
-+		iwl3945_sync_sta(priv, IWL_STA_ID,
-+				 (priv->phymode == MODE_IEEE80211A)?
-+				 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
-+				 CMD_ASYNC);
-+		iwl_rate_scale_init(priv->hw, IWL_STA_ID);
-+		iwl_send_beacon_cmd(priv);
++	IWL_DEBUG_INFO("Alive ucode status 0x%08X revision "
++		       "0x%01X 0x%01X\n",
++		       palive->is_valid, palive->ver_type,
++		       palive->ver_subtype);
 +
-+		break;
++	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
++		IWL_DEBUG_INFO("Initialization Alive received.\n");
++		memcpy(&priv->card_alive_init,
++		       &pkt->u.alive_frame,
++		       sizeof(struct iwl_init_alive_resp));
++		pwork = &priv->init_alive_start;
++	} else {
++		IWL_DEBUG_INFO("Runtime Alive received.\n");
++		memcpy(&priv->card_alive, &pkt->u.alive_frame,
++		       sizeof(struct iwl_alive_resp));
++		pwork = &priv->alive_start;
++	}
 +
-+	case IEEE80211_IF_TYPE_AP:
++	/* We delay the ALIVE response by 5ms to
++	 * give the HW RF Kill time to activate... */
++	if (palive->is_valid == UCODE_VALID_OK)
++		queue_delayed_work(priv->workqueue, pwork,
++				   msecs_to_jiffies(5));
++	else
++		IWL_WARNING("uCode did not respond OK.\n");
++}
 +
-+		/* clear out the station table */
-+		iwl_clear_stations_table(priv);
++static void iwl_rx_reply_add_sta(struct iwl_priv *priv,
++				 struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
 +
-+		iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
-+		iwl_send_beacon_cmd(priv);
++	IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
++	return;
++}
 +
-+		break;
-+	}
++static void iwl_rx_reply_error(struct iwl_priv *priv,
++			       struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
 +
-+	/* FIXME: not sure why this doesn't work in AP mode */
-+	if (priv->iw_mode != IEEE80211_IF_TYPE_AP)
-+		iwl_sequence_reset(priv);
++	IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) "
++		"seq 0x%04X ser 0x%08X\n",
++		le32_to_cpu(pkt->u.err_resp.error_type),
++		get_cmd_string(pkt->u.err_resp.cmd_id),
++		pkt->u.err_resp.cmd_id,
++		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
++		le32_to_cpu(pkt->u.err_resp.error_info));
++}
 +
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_SENSITIVITY
-+	/* Enable Rx differential gain and sensitivity calibrations */
-+	iwl4965_chain_noise_reset(priv);
-+	priv->start_calib = 1;
-+#endif /* CONFIG_IWLWIFI_SENSITIVITY */
-+#endif /* IWL == 4965 */
++#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
 +
-+#ifdef CONFIG_IWLWIFI_QOS
-+	iwl_activate_qos(priv, 0);
-+#endif /* CONFIG_IWLWIFI_QOS */
-+	mutex_unlock(&priv->mutex);
++static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
++	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
++	IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
++		      le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
++	rxon->channel = csa->channel;
++	priv->staging_rxon.channel = csa->channel;
 +}
 +
-+static void iwl_bg_abort_scan(struct work_struct *work)
++static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
++					  struct iwl_rx_mem_buffer *rxb)
 +{
-+	struct iwl_priv *priv = container_of(work, struct iwl_priv,
-+					     abort_scan);
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
 +
-+	if (!iwl_is_ready(priv))
++	if (!report->state) {
++		IWL_DEBUG(IWL_DL_11H | IWL_DL_INFO,
++			  "Spectrum Measure Notification: Start\n");
 +		return;
++	}
 +
-+	mutex_lock(&priv->mutex);
++	memcpy(&priv->measure_report, report, sizeof(*report));
++	priv->measurement_status |= MEASUREMENT_READY;
++#endif
++}
 +
-+	set_bit(STATUS_SCAN_ABORTING, &priv->status);
-+	iwl_send_scan_abort(priv);
++static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
++				  struct iwl_rx_mem_buffer *rxb)
++{
++#ifdef CONFIG_IWLWIFI_DEBUG
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
++	IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
++		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
++#endif
++}
 +
-+	mutex_unlock(&priv->mutex);
++static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
++					     struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
++			"notification for %s:\n",
++			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
++	iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
 +}
 +
-+static void iwl_bg_scan_completed(struct work_struct *work)
++static void iwl_bg_beacon_update(struct work_struct *work)
 +{
 +	struct iwl_priv *priv =
-+	    container_of(work, struct iwl_priv, scan_completed);
++		container_of(work, struct iwl_priv, beacon_update);
++	struct sk_buff *beacon;
 +
-+	IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
++	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
++	beacon = ieee80211_beacon_get(priv->hw, priv->interface_id, NULL);
 +
-+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++	if (!beacon) {
++		IWL_ERROR("update beacon failed\n");
 +		return;
++	}
 +
-+	ieee80211_scan_completed(priv->hw);
-+
-+	/* Since setting the TXPOWER may have been deferred while
-+	 * performing the scan, fire one off */
 +	mutex_lock(&priv->mutex);
-+	iwl_hw_reg_send_txpower(priv);
++	/* new beacon skb is allocated every time; dispose previous.*/
++	if (priv->ibss_beacon)
++		dev_kfree_skb(priv->ibss_beacon);
++
++	priv->ibss_beacon = beacon;
 +	mutex_unlock(&priv->mutex);
-+}
 +
-+/*****************************************************************************
-+ *
-+ * mac80211 entry point functions
-+ *
-+ *****************************************************************************/
++	iwl_send_beacon_cmd(priv);
++}
 +
-+static int iwl_mac_open(struct ieee80211_hw *hw)
++static void iwl_rx_beacon_notif(struct iwl_priv *priv,
++				struct iwl_rx_mem_buffer *rxb)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+
-+	IWL_DEBUG_MAC80211("enter\n");
-+
-+	/* we should be verifying the device is ready to be opened */
-+	mutex_lock(&priv->mutex);
-+
-+	priv->is_open = 1;
++#ifdef CONFIG_IWLWIFI_DEBUG
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_beacon_notif *beacon = &(pkt->u.beacon_status);
++	u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
 +
-+	if (!iwl_is_rfkill(priv))
-+		ieee80211_start_queues(priv->hw);
++	IWL_DEBUG_RX("beacon status %x retries %d iss %d "
++		"tsf %d %d rate %d\n",
++		le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
++		beacon->beacon_notify_hdr.failure_frame,
++		le32_to_cpu(beacon->ibss_mgr_status),
++		le32_to_cpu(beacon->high_tsf),
++		le32_to_cpu(beacon->low_tsf), rate);
++#endif
 +
-+	mutex_unlock(&priv->mutex);
-+	IWL_DEBUG_MAC80211("leave\n");
-+	return 0;
++	if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
++	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
++		queue_work(priv->workqueue, &priv->beacon_update);
 +}
 +
-+static int iwl_mac_stop(struct ieee80211_hw *hw)
++/* Service response to REPLY_SCAN_CMD (0x80) */
++static void iwl_rx_reply_scan(struct iwl_priv *priv,
++			      struct iwl_rx_mem_buffer *rxb)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+
-+	IWL_DEBUG_MAC80211("enter\n");
-+	priv->is_open = 0;
-+	/*netif_stop_queue(dev); */
-+	flush_workqueue(priv->workqueue);
-+	IWL_DEBUG_MAC80211("leave\n");
++#ifdef CONFIG_IWLWIFI_DEBUG
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_scanreq_notification *notif =
++	    (struct iwl_scanreq_notification *)pkt->u.raw;
 +
-+	return 0;
++	IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status);
++#endif
 +}
 +
-+static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
-+		      struct ieee80211_tx_control *ctl)
++/* Service SCAN_START_NOTIFICATION (0x82) */
++static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
++				    struct iwl_rx_mem_buffer *rxb)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+
-+	IWL_DEBUG_MAC80211("enter\n");
-+
-+	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
-+		IWL_DEBUG_MAC80211("leave - monitor\n");
-+		return -1;
-+	}
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_scanstart_notification *notif =
++	    (struct iwl_scanstart_notification *)pkt->u.raw;
++	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
++	IWL_DEBUG_SCAN("Scan start: "
++		       "%d [802.11%s] "
++		       "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
++		       notif->channel,
++		       notif->band ? "bg" : "a",
++		       notif->tsf_high,
++		       notif->tsf_low, notif->status, notif->beacon_timer);
++}
 +
-+	IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-+		     ctl->tx_rate);
++/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
++static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
++				      struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_scanresults_notification *notif =
++	    (struct iwl_scanresults_notification *)pkt->u.raw;
 +
-+	if (iwl_tx_skb(priv, skb, ctl))
-+		dev_kfree_skb_any(skb);
++	IWL_DEBUG_SCAN("Scan ch.res: "
++		       "%d [802.11%s] "
++		       "(TSF: 0x%08X:%08X) - %d "
++		       "elapsed=%lu usec (%dms since last)\n",
++		       notif->channel,
++		       notif->band ? "bg" : "a",
++		       le32_to_cpu(notif->tsf_high),
++		       le32_to_cpu(notif->tsf_low),
++		       le32_to_cpu(notif->statistics[0]),
++		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf,
++		       jiffies_to_msecs(elapsed_jiffies
++					(priv->last_scan_jiffies, jiffies)));
 +
-+	IWL_DEBUG_MAC80211("leave\n");
-+	return 0;
++	priv->last_scan_jiffies = jiffies;
 +}
 +
-+static int iwl_mac_add_interface(struct ieee80211_hw *hw,
-+				 struct ieee80211_if_init_conf *conf)
++/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
++static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
++				       struct iwl_rx_mem_buffer *rxb)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+	unsigned long flags;
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
 +
-+	IWL_DEBUG_MAC80211("enter - id %d, type %d, MAC " MAC_FMT "\n",
-+			   conf->if_id, conf->type, MAC_ARG(conf->mac_addr));
++	IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
++		       scan_notif->scanned_channels,
++		       scan_notif->tsf_low,
++		       scan_notif->tsf_high, scan_notif->status);
 +
-+	if (priv->interface_id) {
-+		IWL_DEBUG_MAC80211("leave - interface_id != 0\n");
-+		return 0;
-+	}
++	/* The HW is no longer scanning */
++	clear_bit(STATUS_SCAN_HW, &priv->status);
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	priv->interface_id = conf->if_id;
++	/* The scan completion notification came in, so kill that timer... */
++	cancel_delayed_work(&priv->scan_check);
 +
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n",
++		       (priv->scan_bands == 2) ? "2.4" : "5.2",
++		       jiffies_to_msecs(elapsed_jiffies
++					(priv->scan_pass_start, jiffies)));
 +
-+	mutex_lock(&priv->mutex);
-+	iwl_set_mode(priv, conf->type);
++	/* Remove this scanned band from the list
++	 * of pending bands to scan */
++	priv->scan_bands--;
 +
-+	IWL_DEBUG_MAC80211("leave\n");
-+	mutex_unlock(&priv->mutex);
++	/* If a request to abort was given, or the scan did not succeed
++	 * then we reset the scan state machine and terminate,
++	 * re-queuing another scan if one has been requested */
++	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++		IWL_DEBUG_INFO("Aborted scan completed.\n");
++		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
++	} else {
++		/* If there are more bands on this scan pass reschedule */
++		if (priv->scan_bands > 0)
++			goto reschedule;
++	}
 +
-+	return 0;
-+}
++	priv->last_scan_jiffies = jiffies;
++	IWL_DEBUG_INFO("Setting scan to off\n");
 +
-+/**
-+ * iwl_mac_config - mac80211 config callback
-+ *
-+ * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
-+ * be set inappropriately and the driver currently sets the hardware up to
-+ * use it whenever needed.
-+ */
-+static int iwl_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
-+{
-+	struct iwl_priv *priv = hw->priv;
-+	const struct iwl_channel_info *ch_info;
-+	unsigned long flags;
++	clear_bit(STATUS_SCANNING, &priv->status);
 +
-+	mutex_lock(&priv->mutex);
-+	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
++	IWL_DEBUG_INFO("Scan took %dms\n",
++		jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));
 +
-+	if (!iwl_is_ready(priv)) {
-+		IWL_DEBUG_MAC80211("leave - not ready\n");
-+		mutex_unlock(&priv->mutex);
-+		return -EIO;
-+	}
++	queue_work(priv->workqueue, &priv->scan_completed);
 +
-+	/* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only
-+	 * what is exposed through include/ declrations */
-+	if (unlikely(!iwl_param_disable_hw_scan &&
-+		     test_bit(STATUS_SCANNING, &priv->status))) {
-+		IWL_DEBUG_MAC80211("leave - scanning\n");
-+		mutex_unlock(&priv->mutex);
-+		return 0;
-+	}
++	return;
 +
-+	spin_lock_irqsave(&priv->lock, flags);
++reschedule:
++	priv->scan_pass_start = jiffies;
++	queue_work(priv->workqueue, &priv->request_scan);
++}
 +
-+	ch_info = iwl_get_channel_info(priv, conf->phymode, conf->channel);
-+	if (!is_channel_valid(ch_info)) {
-+		IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
-+			       conf->channel, conf->phymode);
-+		IWL_DEBUG_MAC80211("leave - invalid channel\n");
-+		spin_unlock_irqrestore(&priv->lock, flags);
-+		mutex_unlock(&priv->mutex);
-+		return -EINVAL;
-+	}
++/* Handle notification from uCode that card's power state is changing
++ * due to software, hardware, or critical temperature RFKILL */
++static void iwl_rx_card_state_notif(struct iwl_priv *priv,
++				    struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
++	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
++	unsigned long status = priv->status;
 +
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+	/* if we are switching fron ht to 2.4 clear flags
-+	 * from any ht related info since 2.4 does not
-+	 * support ht */
-+	if ((le16_to_cpu(priv->staging_rxon.channel) != conf->channel)
-+#ifdef IEEE80211_CONF_CHANNEL_SWITCH
-+	    && !(conf->flags & IEEE80211_CONF_CHANNEL_SWITCH)
-+#endif
-+	)
-+		priv->staging_rxon.flags = 0;
-+#endif /* CONFIG_IWLWIFI_HT */
-+#endif /* IWL == 4965 */
++	IWL_DEBUG_RF_KILL("Card state received: HW:%s SW:%s\n",
++			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
++			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");
 +
-+	iwl_set_rxon_channel(priv, conf->phymode, conf->channel);
++	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
++		     RF_CARD_DISABLED)) {
 +
-+	iwl_set_flags_for_phymode(priv, conf->phymode);
++		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
++			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
 +
-+	/* The list of supported rates and rate mask can be different
-+	 * for each phymode; since the phymode may have changed, reset
-+	 * the rate mask to what mac80211 lists */
-+	iwl_set_rate(priv);
++		if (!iwl_grab_restricted_access(priv)) {
++			iwl_write_restricted(
++				priv, HBUS_TARG_MBX_C,
++				HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
 +
-+	spin_unlock_irqrestore(&priv->lock, flags);
++			iwl_release_restricted_access(priv);
++		}
 +
-+#ifdef IEEE80211_CONF_CHANNEL_SWITCH
-+	if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
-+		iwl_hw_channel_switch(priv, conf->channel);
-+		mutex_unlock(&priv->mutex);
-+		return 0;
-+	}
-+#endif
++		if (!(flags & RXON_CARD_DISABLED)) {
++			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++				    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
++			if (!iwl_grab_restricted_access(priv)) {
++				iwl_write_restricted(
++					priv, HBUS_TARG_MBX_C,
++					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
 +
-+	iwl_radio_kill_sw(priv, !conf->radio_enabled);
++				iwl_release_restricted_access(priv);
++			}
++		}
 +
-+	if (!conf->radio_enabled) {
-+		IWL_DEBUG_MAC80211("leave - radio disabled\n");
-+		mutex_unlock(&priv->mutex);
-+		return 0;
++		if (flags & RF_CARD_DISABLED) {
++			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
++				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
++			iwl_read32(priv, CSR_UCODE_DRV_GP1);
++			if (!iwl_grab_restricted_access(priv))
++				iwl_release_restricted_access(priv);
++		}
 +	}
 +
-+	if (iwl_is_rfkill(priv)) {
-+		IWL_DEBUG_MAC80211("leave - RF kill\n");
-+		mutex_unlock(&priv->mutex);
-+		return -EIO;
-+	}
++	if (flags & HW_CARD_DISABLED)
++		set_bit(STATUS_RF_KILL_HW, &priv->status);
++	else
++		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 +
-+	iwl_set_rate(priv);
 +
-+	if (memcmp(&priv->active_rxon,
-+		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
-+		iwl_commit_rxon(priv);
++	if (flags & SW_CARD_DISABLED)
++		set_bit(STATUS_RF_KILL_SW, &priv->status);
 +	else
-+		IWL_DEBUG_INFO("No re-sending same RXON configuration.\n");
-+
-+	IWL_DEBUG_MAC80211("leave\n");
++		clear_bit(STATUS_RF_KILL_SW, &priv->status);
 +
-+	mutex_unlock(&priv->mutex);
++	if (!(flags & RXON_CARD_DISABLED))
++		iwl_scan_cancel(priv);
 +
-+	return 0;
++	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
++	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
++	    (test_bit(STATUS_RF_KILL_SW, &status) !=
++	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
++		queue_work(priv->workqueue, &priv->rf_kill);
++	else
++		wake_up_interruptible(&priv->wait_command_queue);
 +}
 +
-+static void iwl_config_ap(struct iwl_priv *priv)
++/**
++ * iwl_setup_rx_handlers - Initialize Rx handler callbacks
++ *
++ * Setup the RX handlers for each of the reply types sent from the uCode
++ * to the host.
++ *
++ * This function chains into the hardware specific files for them to setup
++ * any hardware specific handlers as well.
++ */
++static void iwl_setup_rx_handlers(struct iwl_priv *priv)
 +{
-+	int rc = 0;
++	priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
++	priv->rx_handlers[REPLY_ADD_STA] = iwl_rx_reply_add_sta;
++	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
++	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
++	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
++	    iwl_rx_spectrum_measure_notif;
++	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
++	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
++	    iwl_rx_pm_debug_statistics_notif;
++	priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
 +
-+	if (priv->status & STATUS_EXIT_PENDING)
-+		return;
++	/* NOTE:  iwl_rx_statistics is different based on whether
++	 * the build is for the 3945 or the 4965.  See the
++	 * corresponding implementation in iwl-XXXX.c
++	 *
++	 * The same handler is used for both the REPLY to a
++	 * discrete statistics request from the host as well as
++	 * for the periodic statistics notification from the uCode
++	 */
++	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_hw_rx_statistics;
++	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_hw_rx_statistics;
 +
-+	/* The following should be done only at AP bring up */
-+	if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) {
++	priv->rx_handlers[REPLY_SCAN_CMD] = iwl_rx_reply_scan;
++	priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl_rx_scan_start_notif;
++	priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
++	    iwl_rx_scan_results_notif;
++	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
++	    iwl_rx_scan_complete_notif;
++	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
++	priv->rx_handlers[REPLY_TX] = iwl_rx_reply_tx;
 +
-+		/* RXON - unassoc (to set timing command) */
-+		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-+		iwl_commit_rxon(priv);
++	/* Setup hardware specific Rx handlers */
++	iwl_hw_rx_handler_setup(priv);
++}
 +
-+		/* RXON Timing */
-+		memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
-+		iwl_setup_rxon_timing(priv);
-+		rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
-+				sizeof(priv->rxon_timing), &priv->rxon_timing);
-+		if (rc)
-+			IWL_WARNING("REPLY_RXON_TIMING failed - "
-+					"Attempting to continue.\n");
++/**
++ * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
++ * @rxb: Rx buffer to reclaim
++ *
++ * If an Rx buffer has an async callback associated with it the callback
++ * will be executed.  The attached skb (if present) will only be freed
++ * if the callback returns 1
++ */
++static void iwl_tx_cmd_complete(struct iwl_priv *priv,
++				struct iwl_rx_mem_buffer *rxb)
++{
++	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
++	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
++	int txq_id = SEQ_TO_QUEUE(sequence);
++	int index = SEQ_TO_INDEX(sequence);
++	int huge = sequence & SEQ_HUGE_FRAME;
++	int cmd_index;
++	struct iwl_cmd *cmd;
 +
-+		iwl4965_set_rxon_chain(priv);
++	/* If a Tx command is being handled and it isn't in the actual
++	 * command queue then there a command routing bug has been introduced
++	 * in the queue management code. */
++	if (txq_id != IWL_CMD_QUEUE_NUM)
++		IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
++			  txq_id, pkt->hdr.cmd);
++	BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
 +
-+		/* FIXME: what should be the assoc_id for AP? */
-+		priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
-+		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
-+			priv->staging_rxon.flags |=
-+				RXON_FLG_SHORT_PREAMBLE_MSK;
-+		else
-+			priv->staging_rxon.flags &=
-+				~RXON_FLG_SHORT_PREAMBLE_MSK;
++	cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
++	cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
 +
-+		if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
-+			if (priv->assoc_capability &
-+				WLAN_CAPABILITY_SHORT_SLOT_TIME)
-+				priv->staging_rxon.flags |=
-+					RXON_FLG_SHORT_SLOT_MSK;
-+			else
-+				priv->staging_rxon.flags &=
-+					~RXON_FLG_SHORT_SLOT_MSK;
++	/* Input error checking is done when commands are added to queue. */
++	if (cmd->meta.flags & CMD_WANT_SKB) {
++		cmd->meta.source->u.skb = rxb->skb;
++		rxb->skb = NULL;
++	} else if (cmd->meta.u.callback &&
++		   !cmd->meta.u.callback(priv, cmd, rxb->skb))
++		rxb->skb = NULL;
 +
-+			if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
-+				priv->staging_rxon.flags &=
-+					~RXON_FLG_SHORT_SLOT_MSK;
-+		}
-+		/* restore RXON assoc */
-+		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
-+		iwl_commit_rxon(priv);
-+		iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
-+		iwl_send_beacon_cmd(priv);
-+	} else
-+		iwl_send_beacon_cmd(priv);
++	iwl_tx_queue_reclaim(priv, txq_id, index);
++
++	if (!(cmd->meta.flags & CMD_ASYNC)) {
++		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
++		wake_up_interruptible(&priv->wait_command_queue);
++	}
++}
++
++/************************** RX-FUNCTIONS ****************************/
++/*
++ * Rx theory of operation
++ *
++ * The host allocates 32 DMA target addresses and passes the host address
++ * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
++ * 0 to 31
++ *
++ * Rx Queue Indexes
++ * The host/firmware share two index registers for managing the Rx buffers.
++ *
++ * The READ index maps to the first position that the firmware may be writing
++ * to -- the driver can read up to (but not including) this position and get
++ * good data.
++ * The READ index is managed by the firmware once the card is enabled.
++ *
++ * The WRITE index maps to the last position the driver has read from -- the
++ * position preceding WRITE is the last slot the firmware can place a packet.
++ *
++ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
++ * WRITE = READ.
++ *
++ * During initialization the host sets up the READ queue position to the first
++ * INDEX position, and WRITE to the last (READ - 1 wrapped)
++ *
++ * When the firmware places a packet in a buffer it will advance the READ index
++ * and fire the RX interrupt.  The driver can then query the READ index and
++ * process as many packets as possible, moving the WRITE index forward as it
++ * resets the Rx queue buffers with new memory.
++ *
++ * The management in the driver is as follows:
++ * + A list of pre-allocated SKBs is stored in ipw->rxq->rx_free.  When
++ *   ipw->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
++ *   to replensish the ipw->rxq->rx_free.
++ * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
++ *   ipw->rxq is replenished and the READ INDEX is updated (updating the
++ *   'processed' and 'read' driver indexes as well)
++ * + A received packet is processed and handed to the kernel network stack,
++ *   detached from the ipw->rxq.  The driver 'processed' index is updated.
++ * + The Host/Firmware ipw->rxq is replenished at tasklet time from the rx_free
++ *   list. If there are no allocated buffers in ipw->rxq->rx_free, the READ
++ *   INDEX is not incremented and ipw->status(RX_STALLED) is set.  If there
++ *   were enough free buffers and RX_STALLED is set it is cleared.
++ *
++ *
++ * Driver sequence:
++ *
++ * iwl_rx_queue_alloc()       Allocates rx_free
++ * iwl_rx_replenish()         Replenishes rx_free list from rx_used, and calls
++ *                            iwl_rx_queue_restock
++ * iwl_rx_queue_restock()     Moves available buffers from rx_free into Rx
++ *                            queue, updates firmware pointers, and updates
++ *                            the WRITE index.  If insufficient rx_free buffers
++ *                            are available, schedules iwl_rx_replenish
++ *
++ * -- enable interrupts --
++ * ISR - iwl_rx()             Detach iwl_rx_mem_buffers from pool up to the
++ *                            READ INDEX, detaching the SKB from the pool.
++ *                            Moves the packet buffer from queue to rx_used.
++ *                            Calls iwl_rx_queue_restock to refill any empty
++ *                            slots.
++ * ...
++ *
++ */
 +
-+	/* FIXME - we need to add code here to detect a totally new
-+	 * configuration, reset the AP, unassoc, rxon timing, assoc,
-+	 * clear sta table, add BCAST sta... */
++/**
++ * iwl_rx_queue_space - Return number of free slots available in queue.
++ */
++static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
++{
++	int s = q->read - q->write;
++	if (s <= 0)
++		s += RX_QUEUE_SIZE;
++	/* keep some buffer to not confuse full and empty queue */
++	s -= 2;
++	if (s < 0)
++		s = 0;
++	return s;
 +}
 +
-+static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
-+				    struct ieee80211_if_conf *conf)
++/**
++ * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
++ *
++ * NOTE: This function has 3945 and 4965 specific code sections
++ * but is declared in base due to the majority of the
++ * implementation being the same (only a numeric constant is
++ * different)
++ *
++ */
++int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
 +{
-+	struct iwl_priv *priv = hw->priv;
++	u32 reg = 0;
++	int rc = 0;
 +	unsigned long flags;
-+	int rc;
-+
-+	if (conf == NULL)
-+		return -EIO;
-+
-+	if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
-+	    (!conf->beacon || !conf->ssid_len)) {
-+		IWL_DEBUG_MAC80211
-+		    ("Leaving in AP mode because HostAPD is not ready.\n");
-+		return 0;
-+	}
-+
-+	mutex_lock(&priv->mutex);
-+
-+	IWL_DEBUG_MAC80211("enter: interface id %d\n", if_id);
-+	if (conf->bssid)
-+		IWL_DEBUG_MAC80211("bssid: " MAC_FMT "\n",
-+				   MAC_ARG(conf->bssid));
 +
-+	if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
-+	    !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
-+		IWL_DEBUG_MAC80211("leave - scanning\n");
-+		mutex_unlock(&priv->mutex);
-+		return 0;
-+	}
-+
-+	if (priv->interface_id != if_id) {
-+		IWL_DEBUG_MAC80211("leave - interface_id != if_id\n");
-+		mutex_unlock(&priv->mutex);
-+		return 0;
-+	}
-+
-+	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
-+		if (!conf->bssid) {
-+			conf->bssid = priv->mac_addr;
-+			memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
-+			IWL_DEBUG_MAC80211("bssid was set to: " MAC_FMT "\n",
-+					   MAC_ARG(conf->bssid));
-+		}
-+		if (priv->ibss_beacon)
-+			dev_kfree_skb(priv->ibss_beacon);
-+
-+		priv->ibss_beacon = conf->beacon;
-+	}
++	spin_lock_irqsave(&q->lock, flags);
 +
-+	if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
-+	    !is_multicast_ether_addr(conf->bssid)) {
-+		/* If there is currently a HW scan going on in the background
-+		 * then we need to cancel it else the RXON below will fail. */
-+		if (iwl_scan_cancel_timeout(priv, 100)) {
-+			IWL_WARNING("Aborted scan still in progress "
-+				    "after 100ms\n");
-+			IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
-+			mutex_unlock(&priv->mutex);
-+			return -EAGAIN;
-+		}
-+		memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);
++	if (q->need_update == 0)
++		goto exit_unlock;
 +
-+		/* TODO: Audit driver for usage of these members and see
-+		 * if mac80211 deprecates them (priv->bssid looks like it
-+		 * shouldn't be there, but I haven't scanned the IBSS code
-+		 * to verify) - jpk */
-+		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
++	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
++		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
 +
-+		if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
-+			iwl_config_ap(priv);
-+		else {
-+			priv->staging_rxon.filter_flags |=
-+						RXON_FILTER_ASSOC_MSK;
-+			rc = iwl_commit_rxon(priv);
-+			if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
-+				iwl_rxon_add_station(
-+					priv, priv->active_rxon.bssid_addr, 1);
++		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
++			iwl_set_bit(priv, CSR_GP_CNTRL,
++				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++			goto exit_unlock;
 +		}
 +
-+	} else {
-+		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-+		iwl_commit_rxon(priv);
-+	}
++		rc = iwl_grab_restricted_access(priv);
++		if (rc)
++			goto exit_unlock;
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	if (!conf->ssid_len)
-+		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
-+	else
-+		memcpy(priv->essid, conf->ssid, conf->ssid_len);
++		iwl_write_restricted(priv, FH_RSCSR_CHNL0_WPTR,
++				     q->write & ~0x7);
++		iwl_release_restricted_access(priv);
++	} else
++		iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
 +
-+	priv->essid_len = conf->ssid_len;
-+	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+	IWL_DEBUG_MAC80211("leave\n");
-+	mutex_unlock(&priv->mutex);
++	q->need_update = 0;
 +
-+	return 0;
++ exit_unlock:
++	spin_unlock_irqrestore(&q->lock, flags);
++	return rc;
 +}
 +
-+static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
-+				     struct ieee80211_if_init_conf *conf)
++/**
++ * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer pointer.
++ *
++ * NOTE: This function has 3945 and 4965 specific code paths in it.
++ */
++static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
++					  dma_addr_t dma_addr)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+
-+	IWL_DEBUG_MAC80211("enter\n");
-+
-+	mutex_lock(&priv->mutex);
-+	if (priv->interface_id == conf->if_id) {
-+		priv->interface_id = 0;
-+		memset(priv->bssid, 0, ETH_ALEN);
-+		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
-+		priv->essid_len = 0;
-+	}
-+	mutex_unlock(&priv->mutex);
-+
-+	IWL_DEBUG_MAC80211("leave\n");
-+
++	return cpu_to_le32((u32)(dma_addr >> 8));
 +}
 +
-+#define IWL_DELAY_NEXT_SCAN (HZ*2)
-+static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
++
++/**
++ * iwl_rx_queue_restock - refill RX queue from pre-allocated pool
++ *
++ * If there are slots in the RX queue that  need to be restocked,
++ * and we have free pre-allocated buffers, fill the ranks as much
++ * as we can pulling from rx_free.
++ *
++ * This moves the 'write' index forward to catch up with 'processed', and
++ * also updates the memory address in the firmware to reference the new
++ * target buffer.
++ */
++int iwl_rx_queue_restock(struct iwl_priv *priv)
 +{
-+	int rc = 0;
++	struct iwl_rx_queue *rxq = &priv->rxq;
++	struct list_head *element;
++	struct iwl_rx_mem_buffer *rxb;
 +	unsigned long flags;
-+	struct iwl_priv *priv = hw->priv;
-+
-+	IWL_DEBUG_MAC80211("enter\n");
-+
-+	spin_lock_irqsave(&priv->lock, flags);
-+
-+	if (!iwl_is_ready_rf(priv)) {
-+		rc = -EIO;
-+		IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
-+		goto out_unlock;
-+	}
-+
-+	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {	/* APs don't scan */
-+		rc = -EIO;
-+		IWL_ERROR("ERROR: APs don't scan\n");
-+		goto out_unlock;
-+	}
++	int write, rc;
 +
-+	/* if we just finished scan ask for delay */
-+	if (priv->last_scan_jiffies &&
-+	    time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
-+		       jiffies)) {
-+		rc = -EAGAIN;
-+		goto out_unlock;
++	spin_lock_irqsave(&rxq->lock, flags);
++	write = rxq->write & ~0x7;
++	while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
++		element = rxq->rx_free.next;
++		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
++		list_del(element);
++		rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->dma_addr);
++		rxq->queue[rxq->write] = rxb;
++		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
++		rxq->free_count--;
 +	}
-+	if (len) {
-+		IWL_DEBUG_SCAN("direct scan for  "
-+			       "%s [%d]\n ",
-+			       iwl_escape_essid(ssid, len), (int)len);
++	spin_unlock_irqrestore(&rxq->lock, flags);
++	/* If the pre-allocated buffer pool is dropping low, schedule to
++	 * refill it */
++	if (rxq->free_count <= RX_LOW_WATERMARK)
++		queue_work(priv->workqueue, &priv->rx_replenish);
 +
-+		priv->one_direct_scan = 1;
-+		priv->direct_ssid_len = (u8)
-+		    min((u8) len, (u8) IW_ESSID_MAX_SIZE);
-+		memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
++
++	/* If we've added more space for the firmware to place data, tell it */
++	if ((write != (rxq->write & ~0x7))
++	    || (abs(rxq->write - rxq->read) > 7)) {
++		spin_lock_irqsave(&rxq->lock, flags);
++		rxq->need_update = 1;
++		spin_unlock_irqrestore(&rxq->lock, flags);
++		rc = iwl_rx_queue_update_write_ptr(priv, rxq);
++		if (rc)
++			return rc;
 +	}
 +
-+	rc = iwl_scan_initiate(priv);
++	return 0;
++}
 +
-+	IWL_DEBUG_MAC80211("leave\n");
++/**
++ * iwl_rx_replensih - Move all used packet from rx_used to rx_free
++ *
++ * When moving to rx_free an SKB is allocated for the slot.
++ *
++ * Also restock the Rx queue via iwl_rx_queue_restock.
++ * This is called as a scheduled work item (except for during intialization)
++ */
++void iwl_rx_replenish(void *data)
++{
++	struct iwl_priv *priv = data;
++	struct iwl_rx_queue *rxq = &priv->rxq;
++	struct list_head *element;
++	struct iwl_rx_mem_buffer *rxb;
++	unsigned long flags;
++	spin_lock_irqsave(&rxq->lock, flags);
++	while (!list_empty(&rxq->rx_used)) {
++		element = rxq->rx_used.next;
++		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
++		rxb->skb =
++		    alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC);
++		if (!rxb->skb) {
++			if (net_ratelimit())
++				printk(KERN_CRIT DRV_NAME
++				       ": Can not allocate SKB buffers\n");
++			/* We don't reschedule replenish work here -- we will
++			 * call the restock method and if it still needs
++			 * more buffers it will schedule replenish */
++			break;
++		}
++		priv->alloc_rxb_skb++;
++		list_del(element);
++		rxb->dma_addr =
++		    pci_map_single(priv->pci_dev, rxb->skb->data,
++				   IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
++		list_add_tail(&rxb->list, &rxq->rx_free);
++		rxq->free_count++;
++	}
++	spin_unlock_irqrestore(&rxq->lock, flags);
 +
-+out_unlock:
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl_rx_queue_restock(priv);
 +	spin_unlock_irqrestore(&priv->lock, flags);
-+
-+	return rc;
 +}
 +
-+static int iwl_mac_set_key(struct ieee80211_hw *hw, set_key_cmd cmd, u8 *addr,
-+			   struct ieee80211_key_conf *key, int aid)
++/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
++ * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
++ * This free routine walks the list of POOL entries and if SKB is set to
++ * non NULL it is unmapped and freed
++ */
++void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+	int rc = 0;
-+	u8 sta_id;
-+
-+	IWL_DEBUG_MAC80211("enter\n");
-+
-+	if (!iwl_param_hwcrypto) {
-+		IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
-+		return -EOPNOTSUPP;
-+	}
-+
-+	sta_id = iwl_hw_find_station(priv, addr);
-+	if (sta_id == IWL_INVALID_STATION) {
-+		IWL_DEBUG_MAC80211("leave - " MAC_FMT " not in station map.\n",
-+				   MAC_ARG(addr));
-+		return -EINVAL;
++	int i;
++	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
++		if (rxq->pool[i].skb != NULL) {
++			pci_unmap_single(priv->pci_dev,
++					 rxq->pool[i].dma_addr,
++					 IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
++			dev_kfree_skb(rxq->pool[i].skb);
++		}
 +	}
 +
-+	mutex_lock(&priv->mutex);
-+
-+	if (cmd == SET_KEY)
-+		rc = iwl_update_sta_key_info(priv, key, sta_id);
-+	else
-+		rc = -EINVAL;
-+
-+	if (!rc) {
-+		iwl_set_rxon_hwcrypto(priv, 1);
-+		iwl_commit_rxon(priv);
-+		key->flags &= ~IEEE80211_KEY_FORCE_SW_ENCRYPT;
-+		key->hw_key_idx = sta_id;
-+		IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n");
-+	}
++	pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
++			    rxq->dma_addr);
++	rxq->bd = NULL;
++}
 +
-+	IWL_DEBUG_MAC80211("leave\n");
-+	mutex_unlock(&priv->mutex);
++int iwl_rx_queue_alloc(struct iwl_priv *priv)
++{
++	struct iwl_rx_queue *rxq = &priv->rxq;
++	struct pci_dev *dev = priv->pci_dev;
++	int i;
 +
-+	return rc;
++	spin_lock_init(&rxq->lock);
++	INIT_LIST_HEAD(&rxq->rx_free);
++	INIT_LIST_HEAD(&rxq->rx_used);
++	rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
++	if (!rxq->bd)
++		return -ENOMEM;
++	/* Fill the rx_used queue with _all_ of the Rx buffers */
++	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
++		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
++	/* Set us so that we have processed and used all buffers, but have
++	 * not restocked the Rx queue with fresh buffers */
++	rxq->read = rxq->write = 0;
++	rxq->free_count = 0;
++	rxq->need_update = 0;
++	return 0;
 +}
 +
-+static int iwl_mac_conf_tx(struct ieee80211_hw *hw, int queue,
-+			   const struct ieee80211_tx_queue_params *params)
++void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+#ifdef CONFIG_IWLWIFI_QOS
 +	unsigned long flags;
 +	int i;
-+#endif /* CONFIG_IWL_QOS */
-+
-+	IWL_DEBUG_MAC80211("enter\n");
-+
-+	if (!iwl_is_ready_rf(priv)) {
-+		IWL_DEBUG_MAC80211("leave - RF not ready\n");
-+		return -EIO;
++	spin_lock_irqsave(&rxq->lock, flags);
++	INIT_LIST_HEAD(&rxq->rx_free);
++	INIT_LIST_HEAD(&rxq->rx_used);
++	/* Fill the rx_used queue with _all_ of the Rx buffers */
++	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
++		/* In the reset function, these buffers may have been allocated
++		 * to an SKB, so we need to unmap and free potential storage */
++		if (rxq->pool[i].skb != NULL) {
++			pci_unmap_single(priv->pci_dev,
++					 rxq->pool[i].dma_addr,
++					 IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
++			priv->alloc_rxb_skb--;
++			dev_kfree_skb(rxq->pool[i].skb);
++			rxq->pool[i].skb = NULL;
++		}
++		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
 +	}
 +
-+	if (queue >= AC_NUM) {
-+		IWL_DEBUG_MAC80211("leave - queue >= AC_NUM %d\n", queue);
-+		return 0;
-+	}
++	/* Set us so that we have processed and used all buffers, but have
++	 * not restocked the Rx queue with fresh buffers */
++	rxq->read = rxq->write = 0;
++	rxq->free_count = 0;
++	spin_unlock_irqrestore(&rxq->lock, flags);
++}
 +
-+#ifdef CONFIG_IWLWIFI_QOS
-+	if (!priv->qos_data.qos_enable) {
-+		priv->qos_data.qos_active = 0;
-+		IWL_DEBUG_MAC80211("leave - qos ! enabled\n");
-+		return 0;
-+	}
-+	i = AC_NUM - 1 - queue;
++/* Convert linear signal-to-noise ratio into dB */
++static u8 ratio2dB[100] = {
++/*	 0   1   2   3   4   5   6   7   8   9 */
++	 0,  0,  6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
++	20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
++	26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
++	29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
++	32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
++	34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
++	36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
++	37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
++	38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
++	39, 39, 39, 39, 39, 40, 40, 40, 40, 40  /* 90 - 99 */
++};
 +
-+	spin_lock_irqsave(&priv->lock, flags);
++/* Calculates a relative dB value from a ratio of linear
++ *   (i.e. not dB) signal levels.
++ * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
++int iwl_calc_db_from_ratio(int sig_ratio)
++{
++	/* Anything above 1000:1 just report as 60 dB */
++	if (sig_ratio > 1000)
++		return 60;
 +
-+	priv->qos_data.def_qos_parm.ac[i].cw_min = (__le16)
-+		cpu_to_le16(params->cw_min);
-+	priv->qos_data.def_qos_parm.ac[i].cw_max = (__le16)
-+		cpu_to_le16(params->cw_max);
-+	priv->qos_data.def_qos_parm.ac[i].aifsn = (u8)
-+		params->aifs;
-+	priv->qos_data.def_qos_parm.ac[i].edca_txop = (__le16)
-+		cpu_to_le16((params->burst_time * 100));
++	/* Above 100:1, divide by 10 and use table,
++	 *   add 20 dB to make up for divide by 10 */
++	if (sig_ratio > 100)
++		return (20 + (int)ratio2dB[sig_ratio/10]);
 +
-+	priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-+	priv->qos_data.qos_active = IPW_QOS_WMM;
++	/* We shouldn't see this */
++	if (sig_ratio < 1)
++		return 0;
 +
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	/* Use table for ratios 1:1 - 99:1 */
++	return (int)ratio2dB[sig_ratio];
++}
 +
-+	mutex_lock(&priv->mutex);
++#define PERFECT_RSSI (-20) /* dBm */
++#define WORST_RSSI (-95)   /* dBm */
++#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
 +
-+	/* we wait for the last queue then call qos ucode command */
-+	if (priv->assoc_id && iwl_is_associated(priv) && (i == (AC_NUM - 1)))
-+		iwl_activate_qos(priv, 0);
++/* Calculate an indication of rx signal quality (a percentage, not dBm!).
++ * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
++ *   about formulas used below. */
++int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
++{
++	int sig_qual;
++	int degradation = PERFECT_RSSI - rssi_dbm;
 +
-+	mutex_unlock(&priv->mutex);
++	/* If we get a noise measurement, use signal-to-noise ratio (SNR)
++	 * as indicator; formula is (signal dbm - noise dbm).
++	 * SNR at or above 40 is a great signal (100%).
++	 * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
++	 * Weakest usable signal is usually 10 - 15 dB SNR. */
++	if (noise_dbm) {
++		if (rssi_dbm - noise_dbm >= 40)
++			return 100;
++		else if (rssi_dbm < noise_dbm)
++			return 0;
++		sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
++
++	/* Else use just the signal level.
++	 * This formula is a least squares fit of data points collected and
++	 *   compared with a reference system that had a percentage (%) display
++	 *   for signal quality. */
++	} else
++		sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
++			    (15 * RSSI_RANGE + 62 * degradation)) /
++			   (RSSI_RANGE * RSSI_RANGE);
 +
-+#endif /*CONFIG_IWLWIFI_QOS */
++	if (sig_qual > 100)
++		sig_qual = 100;
++	else if (sig_qual < 1)
++		sig_qual = 0;
 +
-+	IWL_DEBUG_MAC80211("leave\n");
-+	return 0;
++	return sig_qual;
 +}
 +
-+static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
-+				struct ieee80211_tx_queue_stats *stats)
++/**
++ * iwl_rx_handle - Main entry function for receiving responses from the uCode
++ *
++ * Uses the priv->rx_handlers callback function array to invoke
++ * the appropriate handlers, including command responses,
++ * frame-received notifications, and other notifications.
++ */
++static void iwl_rx_handle(struct iwl_priv *priv)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+	int i, avail;
-+	struct iwl_tx_queue *txq;
-+	struct iwl_queue *q;
++	struct iwl_rx_mem_buffer *rxb;
++	struct iwl_rx_packet *pkt;
++	struct iwl_rx_queue *rxq = &priv->rxq;
++	u32 r, i;
++	int reclaim;
 +	unsigned long flags;
 +
-+	IWL_DEBUG_MAC80211("enter\n");
++	r = iwl_hw_get_rx_read(priv);
++	i = rxq->read;
 +
-+	if (!iwl_is_ready_rf(priv)) {
-+		IWL_DEBUG_MAC80211("leave - RF not ready\n");
-+		return -EIO;
-+	}
++	/* Rx interrupt, but nothing sent from uCode */
++	if (i == r)
++		IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
 +
-+	spin_lock_irqsave(&priv->lock, flags);
++	while (i != r) {
++		rxb = rxq->queue[i];
 +
-+	for (i = 0; i < AC_NUM; i++) {
-+		txq = &priv->txq[i];
-+		q = &txq->q;
-+		avail = iwl_queue_space(q);
++		/* If an RXB doesn't have a queue slot associated with it
++		 * then a bug has been introduced in the queue refilling
++		 * routines -- catch it here */
++		BUG_ON(rxb == NULL);
 +
-+		stats->data[i].len = q->n_window - avail;
-+		stats->data[i].limit = q->n_window - q->high_mark;
-+		stats->data[i].count = q->n_window;
++		rxq->queue[i] = NULL;
 +
-+	}
-+	spin_unlock_irqrestore(&priv->lock, flags);
++		pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
++					    IWL_RX_BUF_SIZE,
++					    PCI_DMA_FROMDEVICE);
++		pkt = (struct iwl_rx_packet *)rxb->skb->data;
 +
-+	IWL_DEBUG_MAC80211("leave\n");
++		/* Reclaim a command buffer only if this packet is a response
++		 *   to a (driver-originated) command.
++		 * If the packet (e.g. Rx frame) originated from uCode,
++		 *   there is no command buffer to reclaim.
++		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
++		 *   but apparently a few don't get set; catch them here. */
++		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
++			(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
++			(pkt->hdr.cmd != REPLY_4965_RX) &&
++			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
++			(pkt->hdr.cmd != REPLY_TX);
 +
-+	return 0;
-+}
++		/* Based on type of command response or notification,
++		 *   handle those that need handling via function in
++		 *   rx_handlers table.  See iwl_setup_rx_handlers() */
++		if (priv->rx_handlers[pkt->hdr.cmd]) {
++			IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
++				"r = %d, i = %d, %s, 0x%02x\n", r, i,
++				get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
++			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
++		} else {
++			/* No handling needed */
++			IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
++				"r %d i %d No handler needed for %s, 0x%02x\n",
++				r, i, get_cmd_string(pkt->hdr.cmd),
++				pkt->hdr.cmd);
++		}
 +
-+static int iwl_mac_get_stats(struct ieee80211_hw *hw,
-+			     struct ieee80211_low_level_stats *stats)
-+{
-+	IWL_DEBUG_MAC80211("enter\n");
-+	IWL_DEBUG_MAC80211("leave\n");
++		if (reclaim) {
++			/* Invoke any callbacks, transfer the skb to caller,
++			 * and fire off the (possibly) blocking iwl_send_cmd()
++			 * as we reclaim the driver command queue */
++			if (rxb && rxb->skb)
++				iwl_tx_cmd_complete(priv, rxb);
++			else
++				IWL_WARNING("Claim null rxb?\n");
++		}
 +
-+	return 0;
-+}
++		/* For now we just don't re-use anything.  We can tweak this
++		 * later to try and re-use notification packets and SKBs that
++		 * fail to Rx correctly */
++		if (rxb->skb != NULL) {
++			priv->alloc_rxb_skb--;
++			dev_kfree_skb_any(rxb->skb);
++			rxb->skb = NULL;
++		}
 +
-+static u64 iwl_mac_get_tsf(struct ieee80211_hw *hw)
-+{
-+	IWL_DEBUG_MAC80211("enter\n");
-+	IWL_DEBUG_MAC80211("leave\n");
++		pci_unmap_single(priv->pci_dev, rxb->dma_addr,
++				 IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
++		spin_lock_irqsave(&rxq->lock, flags);
++		list_add_tail(&rxb->list, &priv->rxq.rx_used);
++		spin_unlock_irqrestore(&rxq->lock, flags);
++		i = (i + 1) & RX_QUEUE_MASK;
++	}
 +
-+	return 0;
++	/* Backtrack one entry */
++	priv->rxq.read = i;
++	iwl_rx_queue_restock(priv);
 +}
 +
-+static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
++int iwl_tx_queue_update_write_ptr(struct iwl_priv *priv,
++				  struct iwl_tx_queue *txq)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+	unsigned long flags;
++	u32 reg = 0;
++	int rc = 0;
++	int txq_id = txq->q.id;
 +
-+	mutex_lock(&priv->mutex);
-+	IWL_DEBUG_MAC80211("enter\n");
++	if (txq->need_update == 0)
++		return rc;
 +
-+#if IWL == 4965
-+	priv->lq_mngr.lq_ready = 0;
-+#ifdef CONFIG_IWLWIFI_HT
-+	spin_lock_irqsave(&priv->lock, flags);
-+	memset(&priv->current_assoc_ht, 0, sizeof(struct sta_ht_info));
-+	spin_unlock_irqrestore(&priv->lock, flags);
-+#ifdef CONFIG_IWLWIFI_HT_AGG
-+/*	if (priv->lq_mngr.agg_ctrl.granted_ba)
-+		iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);*/
++	/* if we're trying to save power */
++	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
++		/* wake up nic if it's powered down ...
++		 * uCode will wake up, and interrupt us again, so next
++		 * time we'll skip this part. */
++		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
 +
-+	memset(&(priv->lq_mngr.agg_ctrl), 0, sizeof(struct iwl_agg_control));
-+	priv->lq_mngr.agg_ctrl.tid_traffic_load_threshold = 10;
-+	priv->lq_mngr.agg_ctrl.ba_timeout = 5000;
-+	priv->lq_mngr.agg_ctrl.auto_agg = 1;
++		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
++			IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
++			iwl_set_bit(priv, CSR_GP_CNTRL,
++				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++			return rc;
++		}
 +
-+	if (priv->lq_mngr.agg_ctrl.auto_agg)
-+		priv->lq_mngr.agg_ctrl.requested_ba = TID_ALL_ENABLED;
-+#endif /*CONFIG_IWLWIFI_HT_AGG */
-+#endif /* CONFIG_IWLWIFI_HT */
-+#endif /* IWL == 4965 */
++		/* restore this queue's parameters in nic hardware. */
++		rc = iwl_grab_restricted_access(priv);
++		if (rc)
++			return rc;
++		iwl_write_restricted(priv, HBUS_TARG_WRPTR,
++				     txq->q.first_empty | (txq_id << 8));
++		iwl_release_restricted_access(priv);
 +
-+#ifdef CONFIG_IWLWIFI_QOS
-+	iwl_reset_qos(priv);
-+#endif
++	/* else not in power-save mode, uCode will never sleep when we're
++	 * trying to tx (during RFKILL, we're not trying to tx). */
++	} else
++		iwl_write32(priv, HBUS_TARG_WRPTR,
++			    txq->q.first_empty | (txq_id << 8));
 +
-+	cancel_delayed_work(&priv->post_associate);
++	txq->need_update = 0;
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	priv->assoc_id = 0;
-+	priv->assoc_capability = 0;
-+	priv->call_post_assoc_from_beacon = 0;
++	return rc;
++}
 +
-+	/* new association get rid of ibss beacon skb */
-+	if (priv->ibss_beacon)
-+		dev_kfree_skb(priv->ibss_beacon);
++#ifdef CONFIG_IWLWIFI_DEBUG
++static void iwl_print_rx_config_cmd(struct iwl_rxon_cmd *rxon)
++{
++	IWL_DEBUG_RADIO("RX CONFIG:\n");
++	iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
++	IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
++	IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
++	IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
++			le32_to_cpu(rxon->filter_flags));
++	IWL_DEBUG_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type);
++	IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
++			rxon->ofdm_basic_rates);
++	IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
++	IWL_DEBUG_RADIO("u8[6] node_addr: " MAC_FMT "\n",
++			MAC_ARG(rxon->node_addr));
++	IWL_DEBUG_RADIO("u8[6] bssid_addr: " MAC_FMT "\n",
++			MAC_ARG(rxon->bssid_addr));
++	IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
++}
++#endif
 +
-+	priv->ibss_beacon = NULL;
++static void iwl_enable_interrupts(struct iwl_priv *priv)
++{
++	IWL_DEBUG_ISR("Enabling interrupts\n");
++	set_bit(STATUS_INT_ENABLED, &priv->status);
++	iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
++}
 +
-+	priv->beacon_int = priv->hw->conf.beacon_int;
-+	priv->timestamp1 = 0;
-+	priv->timestamp0 = 0;
-+	if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
-+		priv->beacon_int = 0;
++static inline void iwl_disable_interrupts(struct iwl_priv *priv)
++{
++	clear_bit(STATUS_INT_ENABLED, &priv->status);
 +
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	/* disable interrupts from uCode/NIC to host */
++	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
 +
-+	/* Per mac80211.h: This is only used in IBSS mode... */
-+	if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
-+		IWL_DEBUG_MAC80211("leave - not in IBSS\n");
-+		mutex_unlock(&priv->mutex);
-+		return;
-+	}
++	/* acknowledge/clear/reset any interrupts still pending
++	 * from uCode or flow handler (Rx/Tx DMA) */
++	iwl_write32(priv, CSR_INT, 0xffffffff);
++	iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
++	IWL_DEBUG_ISR("Disabled interrupts\n");
++}
 +
-+	if (!iwl_is_ready_rf(priv)) {
-+		IWL_DEBUG_MAC80211("leave - not ready\n");
-+		mutex_unlock(&priv->mutex);
-+		return;
++static const char *desc_lookup(int i)
++{
++	switch (i) {
++	case 1:
++		return "FAIL";
++	case 2:
++		return "BAD_PARAM";
++	case 3:
++		return "BAD_CHECKSUM";
++	case 4:
++		return "NMI_INTERRUPT";
++	case 5:
++		return "SYSASSERT";
++	case 6:
++		return "FATAL_ERROR";
 +	}
 +
-+	priv->only_active_channel = 0;
-+
-+	iwl_set_rate(priv);
-+
-+	mutex_unlock(&priv->mutex);
-+
-+	IWL_DEBUG_MAC80211("leave\n");
-+
++	return "UNKNOWN";
 +}
 +
-+static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-+				 struct ieee80211_tx_control *control)
++#define ERROR_START_OFFSET  (1 * sizeof(u32))
++#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
++
++static void iwl_dump_nic_error_log(struct iwl_priv *priv)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+	unsigned long flags;
++	u32 data2, line;
++	u32 desc, time, count, base, data1;
++	u32 blink1, blink2, ilink1, ilink2;
++	int rc;
 +
-+	mutex_lock(&priv->mutex);
-+	IWL_DEBUG_MAC80211("enter\n");
++	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
 +
-+	if (!iwl_is_ready_rf(priv)) {
-+		IWL_DEBUG_MAC80211("leave - RF not ready\n");
-+		mutex_unlock(&priv->mutex);
-+		return -EIO;
++	if (!iwl_hw_valid_rtc_data_addr(base)) {
++		IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
++		return;
 +	}
 +
-+	if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
-+		IWL_DEBUG_MAC80211("leave - not IBSS\n");
-+		mutex_unlock(&priv->mutex);
-+		return -EIO;
++	rc = iwl_grab_restricted_access(priv);
++	if (rc) {
++		IWL_WARNING("Can not read from adapter at this time.\n");
++		return;
 +	}
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+
-+	if (priv->ibss_beacon)
-+		dev_kfree_skb(priv->ibss_beacon);
-+
-+	priv->ibss_beacon = skb;
++	count = iwl_read_restricted_mem(priv, base);
 +
-+	priv->assoc_id = 0;
++	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
++		IWL_ERROR("Start IWL Error Log Dump:\n");
++		IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n",
++			  priv->status, priv->config, count);
++	}
 +
-+	IWL_DEBUG_MAC80211("leave\n");
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	desc = iwl_read_restricted_mem(priv, base + 1 * sizeof(u32));
++	blink1 = iwl_read_restricted_mem(priv, base + 3 * sizeof(u32));
++	blink2 = iwl_read_restricted_mem(priv, base + 4 * sizeof(u32));
++	ilink1 = iwl_read_restricted_mem(priv, base + 5 * sizeof(u32));
++	ilink2 = iwl_read_restricted_mem(priv, base + 6 * sizeof(u32));
++	data1 = iwl_read_restricted_mem(priv, base + 7 * sizeof(u32));
++	data2 = iwl_read_restricted_mem(priv, base + 8 * sizeof(u32));
++	line = iwl_read_restricted_mem(priv, base + 9 * sizeof(u32));
++	time = iwl_read_restricted_mem(priv, base + 11 * sizeof(u32));
 +
-+#ifdef CONFIG_IWLWIFI_QOS
-+	iwl_reset_qos(priv);
-+#endif
++	IWL_ERROR("Desc               Time       "
++		  "data1      data2      line\n");
++	IWL_ERROR("%-13s (#%d) %010u 0x%08X 0x%08X %u\n",
++		  desc_lookup(desc), desc, time, data1, data2, line);
++	IWL_ERROR("blink1  blink2  ilink1  ilink2\n");
++	IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
++		  ilink1, ilink2);
 +
-+	queue_work(priv->workqueue, &priv->post_associate.work);
++	iwl_release_restricted_access(priv);
++}
 +
-+	mutex_unlock(&priv->mutex);
++#define EVENT_START_OFFSET  (4 * sizeof(u32))
 +
-+	return 0;
-+}
++/**
++ * iwl_print_event_log - Dump error event log to syslog
++ *
++ * NOTE: Must be called with iwl_grab_restricted_access() already obtained!
++ */
++static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
++				u32 num_events, u32 mode)
++{
++	u32 i;
++	u32 base;       /* SRAM byte address of event log header */
++	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
++	u32 ptr;        /* SRAM byte address of log data */
++	u32 ev, time, data; /* event log data */
 +
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+union ht_cap_info {
-+	struct {
-+		u16 advanced_coding_cap		:1;
-+		u16 supported_chan_width_set	:1;
-+		u16 mimo_power_save_mode	:2;
-+		u16 green_field			:1;
-+		u16 short_GI20			:1;
-+		u16 short_GI40			:1;
-+		u16 tx_stbc			:1;
-+		u16 rx_stbc			:1;
-+		u16 beam_forming		:1;
-+		u16 delayed_ba			:1;
-+		u16 maximal_amsdu_size		:1;
-+		u16 cck_mode_at_40MHz		:1;
-+		u16 psmp_support		:1;
-+		u16 stbc_ctrl_frame_support	:1;
-+		u16 sig_txop_protection_support	:1;
-+	};
-+	u16 val;
-+} __attribute__ ((packed));
++	if (num_events == 0)
++		return;
 +
-+union ht_param_info{
-+	struct {
-+		u8 max_rx_ampdu_factor	:2;
-+		u8 mpdu_density		:3;
-+		u8 reserved		:3;
-+	};
-+	u8 val;
-+} __attribute__ ((packed));
++	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
 +
-+union ht_exra_param_info {
-+	struct {
-+		u8 ext_chan_offset		:2;
-+		u8 tx_chan_width		:1;
-+		u8 rifs_mode			:1;
-+		u8 controlled_access_only	:1;
-+		u8 service_interval_granularity	:3;
-+	};
-+	u8 val;
-+} __attribute__ ((packed));
++	if (mode == 0)
++		event_size = 2 * sizeof(u32);
++	else
++		event_size = 3 * sizeof(u32);
 +
-+union ht_operation_mode{
-+	struct {
-+		u16 op_mode	:2;
-+		u16 non_GF	:1;
-+		u16 reserved	:13;
-+	};
-+	u16 val;
-+} __attribute__ ((packed));
++	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
 +
++	/* "time" is actually "data" for mode 0 (no timestamp).
++	 * place event id # at far right for easier visual parsing. */
++	for (i = 0; i < num_events; i++) {
++		ev = iwl_read_restricted_mem(priv, ptr);
++		ptr += sizeof(u32);
++		time = iwl_read_restricted_mem(priv, ptr);
++		ptr += sizeof(u32);
++		if (mode == 0)
++			IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
++		else {
++			data = iwl_read_restricted_mem(priv, ptr);
++			ptr += sizeof(u32);
++			IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
++		}
++	}
++}
 +
-+static int sta_ht_info_init(struct ieee80211_ht_capability *ht_cap,
-+			    struct ieee80211_ht_additional_info *ht_extra,
-+			    struct sta_ht_info *ht_info_ap,
-+			    struct sta_ht_info *ht_info)
++static void iwl_dump_nic_event_log(struct iwl_priv *priv)
 +{
-+	union ht_cap_info cap;
-+	union ht_operation_mode op_mode;
-+	union ht_param_info param_info;
-+	union ht_exra_param_info extra_param_info;
++	int rc;
++	u32 base;       /* SRAM byte address of event log header */
++	u32 capacity;   /* event log capacity in # entries */
++	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
++	u32 num_wraps;  /* # times uCode wrapped to top of log */
++	u32 next_entry; /* index of next entry to be written by uCode */
++	u32 size;       /* # entries that we'll print */
 +
-+	IWL_DEBUG_MAC80211("enter: \n");
++	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
++	if (!iwl_hw_valid_rtc_data_addr(base)) {
++		IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
++		return;
++	}
 +
-+	if (!ht_info) {
-+		IWL_DEBUG_MAC80211("leave: ht_info is NULL\n");
-+		return -1;
++	rc = iwl_grab_restricted_access(priv);
++	if (rc) {
++		IWL_WARNING("Can not read from adapter at this time.\n");
++		return;
 +	}
 +
-+	if (ht_cap) {
-+		cap.val = (u16) le16_to_cpu(ht_cap->capabilities_info);
-+		param_info.val = ht_cap->mac_ht_params_info;
-+		ht_info->is_ht = 1;
-+		if (cap.short_GI20)
-+			ht_info->sgf |= 0x1;
-+		if (cap.short_GI40)
-+			ht_info->sgf |= 0x2;
-+		ht_info->is_green_field = cap.green_field;
-+		ht_info->max_amsdu_size = cap.maximal_amsdu_size;
-+		ht_info->supported_chan_width = cap.supported_chan_width_set;
-+		ht_info->tx_mimo_ps_mode = cap.mimo_power_save_mode;
-+		memcpy(ht_info->supp_rates, ht_cap->supported_mcs_set, 16);
++	/* event log header */
++	capacity = iwl_read_restricted_mem(priv, base);
++	mode = iwl_read_restricted_mem(priv, base + (1 * sizeof(u32)));
++	num_wraps = iwl_read_restricted_mem(priv, base + (2 * sizeof(u32)));
++	next_entry = iwl_read_restricted_mem(priv, base + (3 * sizeof(u32)));
 +
-+		ht_info->ampdu_factor = param_info.max_rx_ampdu_factor;
-+		ht_info->mpdu_density = param_info.mpdu_density;
++	size = num_wraps ? capacity : next_entry;
 +
-+		IWL_DEBUG_MAC80211("SISO mask 0x%X MIMO mask 0x%X \n",
-+				    ht_cap->supported_mcs_set[0],
-+				    ht_cap->supported_mcs_set[1]);
++	/* bail out if nothing in log */
++	if (size == 0) {
++		IWL_ERROR("Start IPW Event Log Dump: nothing in log\n");
++		iwl_release_restricted_access(priv);
++		return;
++	}
 +
-+		if (ht_info_ap) {
-+			ht_info->control_channel = ht_info_ap->control_channel;
-+			ht_info->extension_chan_offset =
-+				ht_info_ap->extension_chan_offset;
-+			ht_info->tx_chan_width = ht_info_ap->tx_chan_width;
-+			ht_info->operating_mode = ht_info_ap->operating_mode;
-+		}
++	IWL_ERROR("Start IPW Event Log Dump: display count %d, wraps %d\n",
++		  size, num_wraps);
 +
-+		if (ht_extra) {
-+			extra_param_info.val = ht_extra->ht_param;
-+			ht_info->control_channel = ht_extra->control_chan;
-+			ht_info->extension_chan_offset =
-+			    extra_param_info.ext_chan_offset;
-+			ht_info->tx_chan_width = extra_param_info.tx_chan_width;
-+			op_mode.val = (u16)
-+			    le16_to_cpu(ht_extra->operation_mode);
-+			ht_info->operating_mode = op_mode.op_mode;
-+			IWL_DEBUG_MAC80211("control channel %d\n",
-+					    ht_extra->control_chan);
-+		}
-+	} else
-+		ht_info->is_ht = 0;
++	/* if uCode has wrapped back to top of log, start at the oldest entry,
++	 * i.e the next one that uCode would fill. */
++	if (num_wraps)
++		iwl_print_event_log(priv, next_entry,
++				    capacity - next_entry, mode);
++
++	/* (then/else) start at top of log */
++	iwl_print_event_log(priv, 0, next_entry, mode);
 +
-+	IWL_DEBUG_MAC80211("leave\n");
-+	return 0;
++	iwl_release_restricted_access(priv);
 +}
 +
-+static int iwl_mac_conf_ht(struct ieee80211_hw *hw,
-+			   struct ieee80211_ht_capability *ht_cap,
-+			   struct ieee80211_ht_additional_info *ht_extra)
++/**
++ * iwl_irq_handle_error - called for HW or SW error interrupt from card
++ */
++static void iwl_irq_handle_error(struct iwl_priv *priv)
 +{
-+	struct iwl_priv *priv = hw->priv;
-+	int rs;
++	/* Set the FW error flag -- cleared on iwl_down */
++	set_bit(STATUS_FW_ERROR, &priv->status);
 +
-+	IWL_DEBUG_MAC80211("enter: \n");
++	/* Cancel currently queued command. */
++	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
 +
-+	rs = sta_ht_info_init(ht_cap, ht_extra, NULL, &priv->current_assoc_ht);
-+	iwl4965_set_rxon_chain(priv);
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & IWL_DL_FW_ERRORS) {
++		iwl_dump_nic_error_log(priv);
++		iwl_dump_nic_event_log(priv);
++		iwl_print_rx_config_cmd(&priv->staging_rxon);
++	}
++#endif
 +
-+	if (priv && priv->assoc_id &&
-+	    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
-+		unsigned long flags;
++	wake_up_interruptible(&priv->wait_command_queue);
 +
-+		spin_lock_irqsave(&priv->lock, flags);
-+		if (priv->beacon_int)
-+			queue_work(priv->workqueue, &priv->post_associate.work);
-+		else
-+			priv->call_post_assoc_from_beacon = 1;
-+		spin_unlock_irqrestore(&priv->lock, flags);
-+	}
++	/* Keep the restart process from trying to send host
++	 * commands by clearing the INIT status bit */
++	clear_bit(STATUS_READY, &priv->status);
 +
-+	IWL_DEBUG_MAC80211("leave: control channel %d\n",
-+			ht_extra->control_chan);
-+	return rs;
++	if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
++		IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS,
++			  "Restarting adapter due to uCode error.\n");
 +
++		if (iwl_is_associated(priv)) {
++			memcpy(&priv->recovery_rxon, &priv->active_rxon,
++			       sizeof(priv->recovery_rxon));
++			priv->error_recovering = 1;
++		}
++		queue_work(priv->workqueue, &priv->restart);
++	}
 +}
 +
-+static void iwl_set_ht_capab(struct ieee80211_hw *hw,
-+			     struct ieee80211_ht_capability *ht_cap,
-+			     u8 use_wide_chan)
++static void iwl_error_recovery(struct iwl_priv *priv)
 +{
-+	union ht_cap_info cap;
-+	union ht_param_info param_info;
-+
-+	memset(&cap, 0, sizeof(union ht_cap_info));
-+	memset(&param_info, 0, sizeof(union ht_param_info));
++	unsigned long flags;
 +
-+	cap.maximal_amsdu_size = HT_IE_MAX_AMSDU_SIZE_4K;
-+	cap.green_field = 1;
-+	cap.short_GI20 = 1;
-+	cap.short_GI40 = 1;
-+	cap.supported_chan_width_set = use_wide_chan;
-+	cap.mimo_power_save_mode = 0x3;
++	memcpy(&priv->staging_rxon, &priv->recovery_rxon,
++	       sizeof(priv->staging_rxon));
++	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++	iwl_commit_rxon(priv);
 +
-+	param_info.max_rx_ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
-+	param_info.mpdu_density = CFG_HT_MPDU_DENSITY_DEF;
-+	ht_cap->capabilities_info = (__le16) cpu_to_le16(cap.val);
-+	ht_cap->mac_ht_params_info = (u8) param_info.val;
++	iwl_rxon_add_station(priv, priv->bssid, 1);
 +
-+	ht_cap->supported_mcs_set[0] = 0xff;
-+	ht_cap->supported_mcs_set[1] = 0xff;
-+	ht_cap->supported_mcs_set[4] =
-+	    (cap.supported_chan_width_set) ? 0x1: 0x0;
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
++	priv->error_recovering = 0;
++	spin_unlock_irqrestore(&priv->lock, flags);
 +}
 +
-+static void iwl_mac_get_ht_capab(struct ieee80211_hw *hw,
-+				 struct ieee80211_ht_capability *ht_cap)
++static void iwl_irq_tasklet(struct iwl_priv *priv)
 +{
-+	u8 use_wide_channel = 1;
-+	struct iwl_priv *priv = hw->priv;
++	u32 inta, handled = 0;
++	u32 inta_fh;
++	unsigned long flags;
++#ifdef CONFIG_IWLWIFI_DEBUG
++	u32 inta_mask;
++#endif
 +
-+	IWL_DEBUG_MAC80211("enter: \n");
-+	if (priv->channel_width != IWL_CHANNEL_WIDTH_40MHZ)
-+		use_wide_channel = 0;
++	spin_lock_irqsave(&priv->lock, flags);
 +
-+	/* no fat tx allowed on 2.4GHZ */
-+	if (priv->phymode != MODE_IEEE80211A)
-+		use_wide_channel = 0;
++	/* Ack/clear/reset pending uCode interrupts.
++	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
++	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
++	inta = iwl_read32(priv, CSR_INT);
++	iwl_write32(priv, CSR_INT, inta);
 +
-+	iwl_set_ht_capab(hw, ht_cap, use_wide_channel);
-+	IWL_DEBUG_MAC80211("leave: \n");
-+}
-+#endif /*CONFIG_IWLWIFI_HT*/
-+#endif /*IWL == 4965*/
-+/*****************************************************************************
-+ *
-+ * sysfs attributes
-+ *
-+ *****************************************************************************/
++	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
++	 * Any new interrupts that happen after this, either while we're
++	 * in this tasklet, or later, will show up in next ISR/tasklet. */
++	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
++	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
 +
 +#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & IWL_DL_ISR) {
++		inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
++		IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
++			      inta, inta_mask, inta_fh);
++	}
++#endif
 +
-+/*
-+ * The following adds a new attribute to the sysfs representation
-+ * of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/)
-+ * used for controlling the debug level.
-+ *
-+ * See the level definitions in ipw for details.
-+ */
++	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
++	 * atomic, make sure that inta covers all the interrupts that
++	 * we've discovered, even if FH interrupt came in just after
++	 * reading CSR_INT. */
++	if (inta_fh & CSR_FH_INT_RX_MASK)
++		inta |= CSR_INT_BIT_FH_RX;
++	if (inta_fh & CSR_FH_INT_TX_MASK)
++		inta |= CSR_INT_BIT_FH_TX;
 +
-+static ssize_t show_debug_level(struct device_driver *d, char *buf)
-+{
-+	return sprintf(buf, "0x%08X\n", iwl_debug_level);
-+}
-+static ssize_t store_debug_level(struct device_driver *d,
-+				 const char *buf, size_t count)
-+{
-+	char *p = (char *)buf;
-+	u32 val;
++	/* Now service all interrupt bits discovered above. */
++	if (inta & CSR_INT_BIT_HW_ERR) {
++		IWL_ERROR("Microcode HW error detected.  Restarting.\n");
 +
-+	val = simple_strtoul(p, &p, 0);
-+	if (p == buf)
-+		printk(KERN_INFO DRV_NAME
-+		       ": %s is not in hex or decimal form.\n", buf);
-+	else
-+		iwl_debug_level = val;
++		/* Tell the device to stop sending interrupts */
++		iwl_disable_interrupts(priv);
 +
-+	return strnlen(buf, count);
-+}
++		iwl_irq_handle_error(priv);
 +
-+static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
-+		   show_debug_level, store_debug_level);
++		handled |= CSR_INT_BIT_HW_ERR;
 +
-+#endif /* CONFIG_IWLWIFI_DEBUG */
++		spin_unlock_irqrestore(&priv->lock, flags);
 +
-+static ssize_t show_rf_kill(struct device *d,
-+			    struct device_attribute *attr, char *buf)
-+{
-+	/*
-+	 * 0 - RF kill not enabled
-+	 * 1 - SW based RF kill active (sysfs)
-+	 * 2 - HW based RF kill active
-+	 * 3 - Both HW and SW based RF kill active
-+	 */
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-+	int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
-+		  (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
++		return;
++	}
 +
-+	return sprintf(buf, "%i\n", val);
-+}
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & (IWL_DL_ISR)) {
++		/* NIC fires this, but we don't use it, redundant with WAKEUP */
++		if (inta & CSR_INT_BIT_MAC_CLK_ACTV)
++			IWL_DEBUG_ISR("Microcode started or stopped.\n");
 +
-+static ssize_t store_rf_kill(struct device *d,
-+			     struct device_attribute *attr,
-+			     const char *buf, size_t count)
-+{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++		/* Alive notification via Rx interrupt will do the real work */
++		if (inta & CSR_INT_BIT_ALIVE)
++			IWL_DEBUG_ISR("Alive interrupt\n");
++	}
++#endif
++	/* Safely ignore these bits for debug checks below */
++	inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE);
 +
-+	mutex_lock(&priv->mutex);
-+	iwl_radio_kill_sw(priv, buf[0] == '1');
-+	mutex_unlock(&priv->mutex);
++	/* HW RF KILL switch toggled (4965 only) */
++	if (inta & CSR_INT_BIT_RF_KILL) {
++		int hw_rf_kill = 0;
++		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
++				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
++			hw_rf_kill = 1;
 +
-+	return count;
-+}
++		IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR,
++				"RF_KILL bit toggled to %s.\n",
++				hw_rf_kill ? "disable radio":"enable radio");
 +
-+static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
++		/* Queue restart only if RF_KILL switch was set to "kill"
++		 *   when we loaded driver, and is now set to "enable".
++		 * After we're Alive, RF_KILL gets handled by
++		 *   iwl_rx_card_state_notif() */
++		if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status))
++			queue_work(priv->workqueue, &priv->restart);
 +
-+static ssize_t show_temperature(struct device *d,
-+				struct device_attribute *attr, char *buf)
-+{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++		handled |= CSR_INT_BIT_RF_KILL;
++	}
 +
-+	if (!iwl_is_alive(priv))
-+		return -EAGAIN;
++	/* Chip got too hot and stopped itself (4965 only) */
++	if (inta & CSR_INT_BIT_CT_KILL) {
++		IWL_ERROR("Microcode CT kill error detected.\n");
++		handled |= CSR_INT_BIT_CT_KILL;
++	}
 +
-+	return sprintf(buf, "%d\n", iwl_hw_get_temperature(priv));
-+}
++	/* Error detected by uCode */
++	if (inta & CSR_INT_BIT_SW_ERR) {
++		IWL_ERROR("Microcode SW error detected.  Restarting 0x%X.\n",
++			  inta);
++		iwl_irq_handle_error(priv);
++		handled |= CSR_INT_BIT_SW_ERR;
++	}
++
++	/* uCode wakes up after power-down sleep */
++	if (inta & CSR_INT_BIT_WAKEUP) {
++		IWL_DEBUG_ISR("Wakeup interrupt\n");
++		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[0]);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[1]);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[2]);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[3]);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[4]);
++		iwl_tx_queue_update_write_ptr(priv, &priv->txq[5]);
++
++		handled |= CSR_INT_BIT_WAKEUP;
++	}
++
++	/* All uCode command responses, including Tx command responses,
++	 * Rx "responses" (frame-received notification), and other
++	 * notifications from uCode come through here*/
++	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
++		iwl_rx_handle(priv);
++		handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
++	}
++
++	if (inta & CSR_INT_BIT_FH_TX) {
++		IWL_DEBUG_ISR("Tx interrupt\n");
++		handled |= CSR_INT_BIT_FH_TX;
++	}
++
++	if (inta & ~handled)
++		IWL_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
 +
-+static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
++	if (inta & ~CSR_INI_SET_MASK) {
++		IWL_WARNING("Disabled INTA bits 0x%08x were pending\n",
++			 inta & ~CSR_INI_SET_MASK);
++		IWL_WARNING("   with FH_INT = 0x%08x\n", inta_fh);
++	}
 +
-+static ssize_t show_rs_window(struct device *d,
-+			      struct device_attribute *attr,
-+			      char *buf)
-+{
-+	struct iwl_priv *priv = d->driver_data;
-+	return iwl_fill_rs_info(priv->hw, buf, IWL_AP_ID);
-+}
-+static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
++	/* Re-enable all interrupts */
++	iwl_enable_interrupts(priv);
 +
-+static ssize_t show_tx_power(struct device *d,
-+			     struct device_attribute *attr, char *buf)
-+{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-+	return sprintf(buf, "%d\n", priv->user_txpower_limit);
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & (IWL_DL_ISR)) {
++		inta = iwl_read32(priv, CSR_INT);
++		inta_mask = iwl_read32(priv, CSR_INT_MASK);
++		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
++		IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
++			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
++	}
++#endif
++	spin_unlock_irqrestore(&priv->lock, flags);
 +}
 +
-+static ssize_t store_tx_power(struct device *d,
-+			      struct device_attribute *attr,
-+			      const char *buf, size_t count)
++static irqreturn_t iwl_isr(int irq, void *data)
 +{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-+	char *p = (char *)buf;
-+	u32 val;
-+
-+	val = simple_strtoul(p, &p, 10);
-+	if (p == buf)
-+		printk(KERN_INFO DRV_NAME
-+		       ": %s is not in decimal form.\n", buf);
-+	else
-+		iwl_hw_reg_set_txpower(priv, val);
-+
-+	return count;
-+}
++	struct iwl_priv *priv = data;
++	u32 inta, inta_mask;
++	u32 inta_fh;
++	if (!priv)
++		return IRQ_NONE;
 +
-+static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
++	spin_lock(&priv->lock);
 +
-+static ssize_t show_flags(struct device *d,
-+			  struct device_attribute *attr, char *buf)
-+{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	/* Disable (but don't clear!) interrupts here to avoid
++	 *    back-to-back ISRs and sporadic interrupts from our NIC.
++	 * If we have something to service, the tasklet will re-enable ints.
++	 * If we *don't* have something, we'll re-enable before leaving here. */
++	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
++	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
 +
-+	return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
-+}
++	/* Discover which interrupts are active/pending */
++	inta = iwl_read32(priv, CSR_INT);
++	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
 +
-+static ssize_t store_flags(struct device *d,
-+			   struct device_attribute *attr,
-+			   const char *buf, size_t count)
-+{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-+	u32 flags = simple_strtoul(buf, NULL, 0);
++	/* Ignore interrupt if there's nothing in NIC to service.
++	 * This may be due to IRQ shared with another device,
++	 * or due to sporadic interrupts thrown from our NIC. */
++	if (!inta && !inta_fh) {
++		IWL_DEBUG_ISR("Ignore interrupt, inta == 0, inta_fh == 0\n");
++		goto none;
++	}
 +
-+	mutex_lock(&priv->mutex);
-+	if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
-+		/* Cancel any currently running scans... */
-+		if (iwl_scan_cancel_timeout(priv, 100))
-+			IWL_WARNING("Could not cancel scan.\n");
-+		else {
-+			IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n",
-+				       flags);
-+			priv->staging_rxon.flags = cpu_to_le32(flags);
-+			iwl_commit_rxon(priv);
-+		}
++	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
++		/* Hardware disappeared */
++		IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
++		goto none;
 +	}
-+	mutex_unlock(&priv->mutex);
 +
-+	return count;
-+}
++	IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
++		      inta, inta_mask, inta_fh);
 +
-+static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
++	/* iwl_irq_tasklet() will service interrupts and re-enable them */
++	tasklet_schedule(&priv->irq_tasklet);
++	spin_unlock(&priv->lock);
 +
-+static ssize_t show_filter_flags(struct device *d,
-+				 struct device_attribute *attr, char *buf)
-+{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	return IRQ_HANDLED;
 +
-+	return sprintf(buf, "0x%04X\n",
-+		le32_to_cpu(priv->active_rxon.filter_flags));
++ none:
++	/* re-enable interrupts here since we don't have anything to service. */
++	iwl_enable_interrupts(priv);
++	spin_unlock(&priv->lock);
++	return IRQ_NONE;
 +}
 +
-+static ssize_t store_filter_flags(struct device *d,
-+				  struct device_attribute *attr,
-+				  const char *buf, size_t count)
-+{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-+	u32 filter_flags = simple_strtoul(buf, NULL, 0);
++/************************** EEPROM BANDS ****************************
++ *
++ * The iwl_eeprom_band definitions below provide the mapping from the
++ * EEPROM contents to the specific channel number supported for each
++ * band.
++ *
++ * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
++ * definition below maps to physical channel 42 in the 5.2GHz spectrum.
++ * The specific geography and calibration information for that channel
++ * is contained in the eeprom map itself.
++ *
++ * During init, we copy the eeprom information and channel map
++ * information into priv->channel_info_24/52 and priv->channel_map_24/52
++ *
++ * channel_map_24/52 provides the index in the channel_info array for a
++ * given channel.  We have to have two separate maps as there is channel
++ * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
++ * band_2
++ *
++ * A value of 0xff stored in the channel_map indicates that the channel
++ * is not supported by the hardware at all.
++ *
++ * A value of 0xfe in the channel_map indicates that the channel is not
++ * valid for Tx with the current hardware.  This means that
++ * while the system can tune and receive on a given channel, it may not
++ * be able to associate or transmit any frames on that
++ * channel.  There is no corresponding channel information for that
++ * entry.
++ *
++ *********************************************************************/
 +
-+	mutex_lock(&priv->mutex);
-+	if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
-+		/* Cancel any currently running scans... */
-+		if (iwl_scan_cancel_timeout(priv, 100))
-+			IWL_WARNING("Could not cancel scan.\n");
-+		else {
-+			IWL_DEBUG_INFO("Committing rxon.filter_flags = "
-+				       "0x%04X\n", filter_flags);
-+			priv->staging_rxon.filter_flags =
-+				cpu_to_le32(filter_flags);
-+			iwl_commit_rxon(priv);
-+		}
-+	}
-+	mutex_unlock(&priv->mutex);
++/* 2.4 GHz */
++static const u8 iwl_eeprom_band_1[14] = {
++	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
++};
 +
-+	return count;
-+}
++/* 5.2 GHz bands */
++static const u8 iwl_eeprom_band_2[] = {
++	183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
++};
 +
-+static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
-+		   store_filter_flags);
++static const u8 iwl_eeprom_band_3[] = {	/* 5205-5320MHz */
++	34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
++};
 +
-+static ssize_t show_tune(struct device *d,
-+			 struct device_attribute *attr, char *buf)
-+{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++static const u8 iwl_eeprom_band_4[] = {	/* 5500-5700MHz */
++	100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
++};
 +
-+	return sprintf(buf, "0x%04X\n",
-+		       (priv->phymode << 8) |
-+			le16_to_cpu(priv->active_rxon.channel));
-+}
++static const u8 iwl_eeprom_band_5[] = {	/* 5725-5825MHz */
++	145, 149, 153, 157, 161, 165
++};
 +
-+static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode);
++static u8 iwl_eeprom_band_6[] = {       /* 2.4 FAT channel */
++	1, 2, 3, 4, 5, 6, 7
++};
 +
-+static ssize_t store_tune(struct device *d,
-+			  struct device_attribute *attr,
-+			  const char *buf, size_t count)
-+{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-+	char *p = (char *)buf;
-+	u16 tune = simple_strtoul(p, &p, 0);
-+	u8 phymode = (tune >> 8) & 0xff;
-+	u16 channel = tune & 0xff;
++static u8 iwl_eeprom_band_7[] = {       /* 5.2 FAT channel */
++	36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
++};
 +
-+	IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
++static void iwl_init_band_reference(const struct iwl_priv *priv, int band,
++				    int *eeprom_ch_count,
++				    const struct iwl_eeprom_channel
++				    **eeprom_ch_info,
++				    const u8 **eeprom_ch_index)
++{
++	switch (band) {
++	case 1:		/* 2.4GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
++		*eeprom_ch_info = priv->eeprom.band_1_channels;
++		*eeprom_ch_index = iwl_eeprom_band_1;
++		break;
++	case 2:		/* 5.2GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
++		*eeprom_ch_info = priv->eeprom.band_2_channels;
++		*eeprom_ch_index = iwl_eeprom_band_2;
++		break;
++	case 3:		/* 5.2GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
++		*eeprom_ch_info = priv->eeprom.band_3_channels;
++		*eeprom_ch_index = iwl_eeprom_band_3;
++		break;
++	case 4:		/* 5.2GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
++		*eeprom_ch_info = priv->eeprom.band_4_channels;
++		*eeprom_ch_index = iwl_eeprom_band_4;
++		break;
++	case 5:		/* 5.2GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
++		*eeprom_ch_info = priv->eeprom.band_5_channels;
++		*eeprom_ch_index = iwl_eeprom_band_5;
++		break;
++	case 6:
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
++		*eeprom_ch_info = priv->eeprom.band_24_channels;
++		*eeprom_ch_index = iwl_eeprom_band_6;
++		break;
++	case 7:
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
++		*eeprom_ch_info = priv->eeprom.band_52_channels;
++		*eeprom_ch_index = iwl_eeprom_band_7;
++		break;
++	default:
++		BUG();
++		return;
++	}
++}
 +
-+	mutex_lock(&priv->mutex);
-+	if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
-+	    (priv->phymode != phymode)) {
-+		const struct iwl_channel_info *ch_info;
++const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
++						    int phymode, u16 channel)
++{
++	int i;
 +
-+		ch_info = iwl_get_channel_info(priv, phymode, channel);
-+		if (!ch_info) {
-+			IWL_WARNING("Requested invalid phymode/channel "
-+				    "combination: %d %d\n", phymode, channel);
-+			mutex_unlock(&priv->mutex);
-+			return -EINVAL;
++	switch (phymode) {
++	case MODE_IEEE80211A:
++		for (i = 14; i < priv->channel_count; i++) {
++			if (priv->channel_info[i].channel == channel)
++				return &priv->channel_info[i];
 +		}
++		break;
 +
-+		/* Cancel any currently running scans... */
-+		if (iwl_scan_cancel_timeout(priv, 100))
-+			IWL_WARNING("Could not cancel scan.\n");
-+		else {
-+			IWL_DEBUG_INFO("Committing phymode and "
-+				       "rxon.channel = %d %d\n",
-+				       phymode, channel);
-+
-+			iwl_set_rxon_channel(priv, phymode, channel);
-+			iwl_set_flags_for_phymode(priv, phymode);
++	case MODE_IEEE80211B:
++	case MODE_IEEE80211G:
++		if (channel >= 1 && channel <= 14)
++			return &priv->channel_info[channel - 1];
++		break;
 +
-+			iwl_set_rate(priv);
-+			iwl_commit_rxon(priv);
-+		}
 +	}
-+	mutex_unlock(&priv->mutex);
 +
-+	return count;
++	return NULL;
 +}
 +
-+static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
-+
-+#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
++			    ? # x " " : "")
 +
-+static ssize_t show_measurement(struct device *d,
-+				struct device_attribute *attr, char *buf)
++static int iwl_init_channel_map(struct iwl_priv *priv)
 +{
-+	struct iwl_priv *priv = dev_get_drvdata(d);
-+	struct iwl_spectrum_notification measure_report;
-+	u32 size = sizeof(measure_report), len = 0, ofs = 0;
-+	u8 *data = (u8 *) & measure_report;
-+	unsigned long flags;
++	int eeprom_ch_count = 0;
++	const u8 *eeprom_ch_index = NULL;
++	const struct iwl_eeprom_channel *eeprom_ch_info = NULL;
++	int band, ch;
++	struct iwl_channel_info *ch_info;
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	if (!(priv->measurement_status & MEASUREMENT_READY)) {
-+		spin_unlock_irqrestore(&priv->lock, flags);
++	if (priv->channel_count) {
++		IWL_DEBUG_INFO("Channel map already initialized.\n");
 +		return 0;
 +	}
-+	memcpy(&measure_report, &priv->measure_report, size);
-+	priv->measurement_status = 0;
-+	spin_unlock_irqrestore(&priv->lock, flags);
-+
-+	while (size && (PAGE_SIZE - len)) {
-+		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
-+				   PAGE_SIZE - len, 1);
-+		len = strlen(buf);
-+		if (PAGE_SIZE - len)
-+			buf[len++] = '\n';
 +
-+		ofs += 16;
-+		size -= min(size, 16U);
++	if (priv->eeprom.version < 0x2f) {
++		IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
++			    priv->eeprom.version);
++		return -EINVAL;
 +	}
 +
-+	return len;
-+}
++	IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
 +
-+static ssize_t store_measurement(struct device *d,
-+				 struct device_attribute *attr,
-+				 const char *buf, size_t count)
-+{
-+	struct iwl_priv *priv = dev_get_drvdata(d);
-+	struct ieee80211_measurement_params params = {
-+		.channel = le16_to_cpu(priv->active_rxon.channel),
-+		.start_time = cpu_to_le64(priv->last_tsf),
-+		.duration = cpu_to_le16(1),
-+	};
-+	u8 type = IWL_MEASURE_BASIC;
-+	u8 buffer[32];
-+	u8 channel;
++	priv->channel_count =
++	    ARRAY_SIZE(iwl_eeprom_band_1) +
++	    ARRAY_SIZE(iwl_eeprom_band_2) +
++	    ARRAY_SIZE(iwl_eeprom_band_3) +
++	    ARRAY_SIZE(iwl_eeprom_band_4) +
++	    ARRAY_SIZE(iwl_eeprom_band_5);
 +
-+	if (count) {
-+		char *p = buffer;
-+		strncpy(buffer, buf, min(sizeof(buffer), count));
-+		channel = simple_strtoul(p, NULL, 0);
-+		if (channel)
-+			params.channel = channel;
++	IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
 +
-+		p = buffer;
-+		while (*p && *p != ' ')
-+			p++;
-+		if (*p)
-+			type = simple_strtoul(p + 1, NULL, 0);
++	priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
++				     priv->channel_count, GFP_KERNEL);
++	if (!priv->channel_info) {
++		IWL_ERROR("Could not allocate channel_info\n");
++		priv->channel_count = 0;
++		return -ENOMEM;
 +	}
 +
-+	IWL_DEBUG_INFO("Invoking measurement of type %d on "
-+		       "channel %d (for '%s')\n", type, params.channel, buf);
-+	iwl_get_measurement(priv, &params, type);
-+
-+	return count;
-+}
++	ch_info = priv->channel_info;
 +
-+static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
-+		   show_measurement, store_measurement);
-+#endif /* CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT */
-+#if IWL == 3945
-+static ssize_t show_rate(struct device *d,
-+			 struct device_attribute *attr, char *buf)
-+{
-+	struct iwl_priv *priv = dev_get_drvdata(d);
-+	unsigned long flags;
-+	int i;
++	/* Loop through the 5 EEPROM bands adding them in order to the
++	 * channel map we maintain (that contains additional information than
++	 * what just in the EEPROM) */
++	for (band = 1; band <= 5; band++) {
 +
-+	spin_lock_irqsave(&priv->sta_lock, flags);
-+	if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
-+		i = priv->stations[IWL_AP_ID].current_rate.s.rate;
-+	else
-+		i = priv->stations[IWL_STA_ID].current_rate.s.rate;
-+	spin_unlock_irqrestore(&priv->sta_lock, flags);
++		iwl_init_band_reference(priv, band, &eeprom_ch_count,
++					&eeprom_ch_info, &eeprom_ch_index);
 +
-+	i = iwl_rate_index_from_plcp(i);
-+	if (i == -1)
-+		return sprintf(buf, "0\n");
++		/* Loop through each band adding each of the channels */
++		for (ch = 0; ch < eeprom_ch_count; ch++) {
++			ch_info->channel = eeprom_ch_index[ch];
++			ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
++			    MODE_IEEE80211A;
 +
-+	return sprintf(buf, "%d%s\n",
-+		       (iwl_rates[i].ieee >> 1),
-+		       (iwl_rates[i].ieee & 0x1) ? ".5" : "");
-+}
++			/* permanently store EEPROM's channel regulatory flags
++			 *   and max power in channel info database. */
++			ch_info->eeprom = eeprom_ch_info[ch];
 +
-+static DEVICE_ATTR(rate, S_IRUSR, show_rate, NULL);
-+#endif
++			/* Copy the run-time flags so they are there even on
++			 * invalid channels */
++			ch_info->flags = eeprom_ch_info[ch].flags;
 +
-+static ssize_t store_retry_rate(struct device *d,
-+				struct device_attribute *attr,
-+				const char *buf, size_t count)
-+{
-+	struct iwl_priv *priv = dev_get_drvdata(d);
++			if (!(is_channel_valid(ch_info))) {
++				IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - "
++					       "No traffic\n",
++					       ch_info->channel,
++					       ch_info->flags,
++					       is_channel_a_band(ch_info) ?
++					       "5.2" : "2.4");
++				ch_info++;
++				continue;
++			}
 +
-+	priv->retry_rate = simple_strtoul(buf, NULL, 0);
-+	if (priv->retry_rate <= 0)
-+		priv->retry_rate = 1;
++			/* Initialize regulatory-based run-time data */
++			ch_info->max_power_avg = ch_info->curr_txpow =
++			    eeprom_ch_info[ch].max_power_avg;
++			ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
++			ch_info->min_power = 0;
 +
-+	return count;
-+}
++			IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
++				       " %ddBm): Ad-Hoc %ssupported\n",
++				       ch_info->channel,
++				       is_channel_a_band(ch_info) ?
++				       "5.2" : "2.4",
++				       CHECK_AND_PRINT(IBSS),
++				       CHECK_AND_PRINT(ACTIVE),
++				       CHECK_AND_PRINT(RADAR),
++				       CHECK_AND_PRINT(WIDE),
++				       CHECK_AND_PRINT(NARROW),
++				       CHECK_AND_PRINT(DFS),
++				       eeprom_ch_info[ch].flags,
++				       eeprom_ch_info[ch].max_power_avg,
++				       ((eeprom_ch_info[ch].
++					 flags & EEPROM_CHANNEL_IBSS)
++					&& !(eeprom_ch_info[ch].
++					     flags & EEPROM_CHANNEL_RADAR))
++				       ? "" : "not ");
 +
-+static ssize_t show_retry_rate(struct device *d,
-+			       struct device_attribute *attr, char *buf)
-+{
-+	struct iwl_priv *priv = dev_get_drvdata(d);
-+	return sprintf(buf, "%d", priv->retry_rate);
-+}
++			/* Set the user_txpower_limit to the highest power
++			 * supported by any channel */
++			if (eeprom_ch_info[ch].max_power_avg >
++			    priv->user_txpower_limit)
++				priv->user_txpower_limit =
++				    eeprom_ch_info[ch].max_power_avg;
 +
-+static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
-+		   store_retry_rate);
++			ch_info++;
++		}
++	}
 +
-+static ssize_t store_power_level(struct device *d,
-+				 struct device_attribute *attr,
-+				 const char *buf, size_t count)
-+{
-+	struct iwl_priv *priv = dev_get_drvdata(d);
-+	int rc;
-+	int mode;
++	for (band = 6; band <= 7; band++) {
++		int phymode;
++		u8 fat_extension_chan;
 +
-+	mode = simple_strtoul(buf, NULL, 0);
-+	mutex_lock(&priv->mutex);
++		iwl_init_band_reference(priv, band, &eeprom_ch_count,
++					&eeprom_ch_info, &eeprom_ch_index);
 +
-+	if (!iwl_is_ready(priv)) {
-+		rc = -EAGAIN;
-+		goto out;
-+	}
++		phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A;
++		/* Loop through each band adding each of the channels */
++		for (ch = 0; ch < eeprom_ch_count; ch++) {
 +
-+	if ((mode < 1) || (mode > IWL_POWER_LIMIT) || (mode == IWL_POWER_AC))
-+		mode = IWL_POWER_AC;
-+	else
-+		mode |= IWL_POWER_ENABLED;
++			if ((band == 6) &&
++			    ((eeprom_ch_index[ch] == 5) ||
++			    (eeprom_ch_index[ch] == 6) ||
++			    (eeprom_ch_index[ch] == 7)))
++			       fat_extension_chan = HT_IE_EXT_CHANNEL_MAX;
++			else
++				fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;
 +
-+	if (mode != priv->power_mode) {
-+		rc = iwl_send_power_mode(priv, IWL_POWER_LEVEL(mode));
-+		if (rc) {
-+			IWL_DEBUG_MAC80211("failed setting power mode.\n");
-+			goto out;
++			iwl4965_set_fat_chan_info(priv, phymode,
++						  eeprom_ch_index[ch],
++						  &(eeprom_ch_info[ch]),
++						  fat_extension_chan);
++
++			iwl4965_set_fat_chan_info(priv, phymode,
++						  (eeprom_ch_index[ch] + 4),
++						  &(eeprom_ch_info[ch]),
++						  HT_IE_EXT_CHANNEL_BELOW);
 +		}
-+		priv->power_mode = mode;
 +	}
 +
-+	rc = count;
-+
-+ out:
-+	mutex_unlock(&priv->mutex);
-+	return rc;
++	return 0;
 +}
 +
-+#define MAX_WX_STRING 80
++/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
++ * sending probe req.  This should be set long enough to hear probe responses
++ * from more than one AP.  */
++#define IWL_ACTIVE_DWELL_TIME_24    (20)	/* all times in msec */
++#define IWL_ACTIVE_DWELL_TIME_52    (10)
 +
-+/* Values are in microsecond */
-+static const s32 timeout_duration[] = {
-+	350000,
-+	250000,
-+	75000,
-+	37000,
-+	25000,
-+};
-+static const s32 period_duration[] = {
-+	400000,
-+	700000,
-+	1000000,
-+	1000000,
-+	1000000
-+};
++/* For faster active scanning, scan will move to the next channel if fewer than
++ * PLCP_QUIET_THRESH packets are heard on this channel within
++ * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell
++ * time if it's a quiet channel (nothing responded to our probe, and there's
++ * no other traffic).
++ * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
++#define IWL_PLCP_QUIET_THRESH       __constant_cpu_to_le16(1)	/* packets */
++#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(5)	/* msec */
 +
-+static ssize_t show_power_level(struct device *d,
-+				struct device_attribute *attr, char *buf)
++/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
++ * Must be set longer than active dwell time.
++ * For the most reliable scan, set > AP beacon interval (typically 100msec). */
++#define IWL_PASSIVE_DWELL_TIME_24   (20)	/* all times in msec */
++#define IWL_PASSIVE_DWELL_TIME_52   (10)
++#define IWL_PASSIVE_DWELL_BASE      (100)
++#define IWL_CHANNEL_TUNE_TIME       5
++
++static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, int phymode)
 +{
-+	struct iwl_priv *priv = dev_get_drvdata(d);
-+	int level = IWL_POWER_LEVEL(priv->power_mode);
-+	char *p = buf;
++	if (phymode == MODE_IEEE80211A)
++		return IWL_ACTIVE_DWELL_TIME_52;
++	else
++		return IWL_ACTIVE_DWELL_TIME_24;
++}
 +
-+	p += sprintf(p, "%d ", level);
-+	switch (level) {
-+	case IWL_POWER_MODE_CAM:
-+	case IWL_POWER_AC:
-+		p += sprintf(p, "(AC)");
-+		break;
-+	case IWL_POWER_BATTERY:
-+		p += sprintf(p, "(BATTERY)");
-+		break;
-+	default:
-+		p += sprintf(p,
-+			     "(Timeout %dms, Period %dms)",
-+			     timeout_duration[level - 1] / 1000,
-+			     period_duration[level - 1] / 1000);
-+	}
++static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, int phymode)
++{
++	u16 active = iwl_get_active_dwell_time(priv, phymode);
++	u16 passive = (phymode != MODE_IEEE80211A) ?
++	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
++	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
 +
-+	if (!(priv->power_mode & IWL_POWER_ENABLED))
-+		p += sprintf(p, " OFF\n");
-+	else
-+		p += sprintf(p, " \n");
++	if (iwl_is_associated(priv)) {
++		/* If we're associated, we clamp the maximum passive
++		 * dwell time to be 98% of the beacon interval (minus
++		 * 2 * channel tune time) */
++		passive = priv->beacon_int;
++		if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
++			passive = IWL_PASSIVE_DWELL_BASE;
++		passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
++	}
 +
-+	return (p - buf + 1);
++	if (passive <= active)
++		passive = active + 1;
 +
++	return passive;
 +}
 +
-+static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
-+		   store_power_level);
-+
-+static ssize_t show_channels(struct device *d,
-+			     struct device_attribute *attr, char *buf)
++static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
++				     u8 is_active, u8 direct_mask,
++				     struct iwl_scan_channel *scan_ch)
 +{
-+	struct iwl_priv *priv = dev_get_drvdata(d);
-+	int len = 0, i;
-+	struct ieee80211_channel *channels = NULL;
-+	const struct ieee80211_hw_mode *hw_mode = NULL;
-+	int count = 0;
-+
-+	if (!iwl_is_ready(priv))
-+		return -EAGAIN;
++	const struct ieee80211_channel *channels = NULL;
++	const struct ieee80211_hw_mode *hw_mode;
++	const struct iwl_channel_info *ch_info;
++	u16 passive_dwell = 0;
++	u16 active_dwell = 0;
++	int added, i;
 +
-+	hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211G);
++	hw_mode = iwl_get_hw_mode(priv, phymode);
 +	if (!hw_mode)
-+		hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211B);
-+	if (hw_mode) {
-+		channels = hw_mode->channels;
-+		count = hw_mode->num_channels;
-+	}
++		return 0;
 +
-+	len +=
-+	    sprintf(&buf[len],
-+		    "Displaying %d channels in 2.4GHz band "
-+		    "(802.11bg):\n", count);
++	channels = hw_mode->channels;
 +
-+	for (i = 0; i < count; i++)
-+		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-+			       channels[i].chan,
-+			       channels[i].power_level,
-+			       channels[i].
-+			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
-+			       " (IEEE 802.11h required)" : "",
-+			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
-+				|| (channels[i].
-+				    flag &
-+				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
-+			       ", IBSS",
-+			       channels[i].
-+			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
-+			       "active/passive" : "passive only");
++	active_dwell = iwl_get_active_dwell_time(priv, phymode);
++	passive_dwell = iwl_get_passive_dwell_time(priv, phymode);
 +
-+	hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211A);
-+	if (hw_mode) {
-+		channels = hw_mode->channels;
-+		count = hw_mode->num_channels;
-+	} else {
-+		channels = NULL;
-+		count = 0;
-+	}
++	for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
++		if (channels[i].chan ==
++		    le16_to_cpu(priv->active_rxon.channel)) {
++			if (iwl_is_associated(priv)) {
++				IWL_DEBUG_SCAN
++				    ("Skipping current channel %d\n",
++				     le16_to_cpu(priv->active_rxon.channel));
++				continue;
++			}
++		} else if (priv->only_active_channel)
++			continue;
 +
-+	len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
-+		       "(802.11a):\n", count);
++		scan_ch->channel = channels[i].chan;
 +
-+	for (i = 0; i < count; i++)
-+		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-+			       channels[i].chan,
-+			       channels[i].power_level,
-+			       channels[i].
-+			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
-+			       " (IEEE 802.11h required)" : "",
-+			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
-+				|| (channels[i].
-+				    flag &
-+				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
-+			       ", IBSS",
-+			       channels[i].
-+			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
-+			       "active/passive" : "passive only");
++		ch_info = iwl_get_channel_info(priv, phymode, scan_ch->channel);
++		if (!is_channel_valid(ch_info)) {
++			IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
++				       scan_ch->channel);
++			continue;
++		}
 +
-+	return len;
-+}
++		if (!is_active || is_channel_passive(ch_info) ||
++		    !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
++			scan_ch->type = 0;	/* passive */
++		else
++			scan_ch->type = 1;	/* active */
 +
-+static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
++		if (scan_ch->type & 1)
++			scan_ch->type |= (direct_mask << 1);
 +
-+static ssize_t show_statistics(struct device *d,
-+			       struct device_attribute *attr, char *buf)
-+{
-+	struct iwl_priv *priv = dev_get_drvdata(d);
-+	u32 size = sizeof(struct iwl_notif_statistics);
-+	u32 len = 0, ofs = 0;
-+	u8 *data = (u8 *) & priv->statistics;
-+	int rc = 0;
++		if (is_channel_narrow(ch_info))
++			scan_ch->type |= (1 << 7);
 +
-+	if (!iwl_is_alive(priv))
-+		return -EAGAIN;
++		scan_ch->active_dwell = cpu_to_le16(active_dwell);
++		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
 +
-+	mutex_lock(&priv->mutex);
-+	rc = iwl_send_statistics_request(priv);
-+	mutex_unlock(&priv->mutex);
++		/* Set power levels to defaults */
++		scan_ch->tpc.dsp_atten = 110;
++		/* scan_pwr_info->tpc.dsp_atten; */
 +
-+	if (rc) {
-+		len = sprintf(buf,
-+			      "Error sending statistics request: 0x%08X\n", rc);
-+		return len;
-+	}
++		/*scan_pwr_info->tpc.tx_gain; */
++		if (phymode == MODE_IEEE80211A)
++			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
++		else {
++			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
++			/* NOTE: if we were doing 6Mb OFDM for scans we'd use
++			 * power level
++			 scan_ch->tpc.tx_gain = ((1<<5) | (2 << 3)) | 3;
++			 */
++		}
 +
-+	while (size && (PAGE_SIZE - len)) {
-+		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
-+				   PAGE_SIZE - len, 1);
-+		len = strlen(buf);
-+		if (PAGE_SIZE - len)
-+			buf[len++] = '\n';
++		IWL_DEBUG_SCAN("Scanning %d [%s %d]\n",
++			       scan_ch->channel,
++			       (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
++			       (scan_ch->type & 1) ?
++			       active_dwell : passive_dwell);
 +
-+		ofs += 16;
-+		size -= min(size, 16U);
++		scan_ch++;
++		added++;
 +	}
 +
-+	return len;
++	IWL_DEBUG_SCAN("total channels to scan %d \n", added);
++	return added;
 +}
 +
-+static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
-+
-+static ssize_t show_antenna(struct device *d,
-+			    struct device_attribute *attr, char *buf)
++static void iwl_reset_channel_flag(struct iwl_priv *priv)
 +{
-+	struct iwl_priv *priv = dev_get_drvdata(d);
-+
-+	if (!iwl_is_alive(priv))
-+		return -EAGAIN;
-+
-+	return sprintf(buf, "%d\n", priv->antenna);
++	int i, j;
++	for (i = 0; i < 3; i++) {
++		struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
++		for (j = 0; j < hw_mode->num_channels; j++)
++			hw_mode->channels[j].flag = hw_mode->channels[j].val;
++	}
 +}
 +
-+static ssize_t store_antenna(struct device *d,
-+			     struct device_attribute *attr,
-+			     const char *buf, size_t count)
++static void iwl_init_hw_rates(struct iwl_priv *priv,
++			      struct ieee80211_rate *rates)
 +{
-+	int ant;
-+	struct iwl_priv *priv = dev_get_drvdata(d);
++	int i;
 +
-+	if (count == 0)
-+		return 0;
++	for (i = 0; i < IWL_RATE_COUNT; i++) {
++		rates[i].rate = iwl_rates[i].ieee * 5;
++		rates[i].val = i; /* Rate scaling will work on indexes */
++		rates[i].val2 = i;
++		rates[i].flags = IEEE80211_RATE_SUPPORTED;
++		/* Only OFDM have the bits-per-symbol set */
++		if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
++			rates[i].flags |= IEEE80211_RATE_OFDM;
++		else {
++			/*
++			 * If CCK 1M then set rate flag to CCK else CCK_2
++			 * which is CCK | PREAMBLE2
++			 */
++			rates[i].flags |= (iwl_rates[i].plcp == 10) ?
++				IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
++		}
 +
-+	if (sscanf(buf, "%1i", &ant) != 1) {
-+		IWL_DEBUG_INFO("not in hex or decimal form.\n");
-+		return count;
++		/* Set up which ones are basic rates... */
++		if (IWL_BASIC_RATES_MASK & (1 << i))
++			rates[i].flags |= IEEE80211_RATE_BASIC;
 +	}
 +
-+	if ((ant >= 0) && (ant <= 2)) {
-+		IWL_DEBUG_INFO("Setting antenna select to %d.\n", ant);
-+		priv->antenna = (enum iwl_antenna)ant;
-+	} else
-+		IWL_DEBUG_INFO("Bad antenna select value %d.\n", ant);
-+
-+
-+	return count;
-+}
-+
-+static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
-+
-+static ssize_t show_status(struct device *d,
-+			   struct device_attribute *attr, char *buf)
-+{
-+	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-+	if (!iwl_is_alive(priv))
-+		return -EAGAIN;
-+	return sprintf(buf, "0x%08x\n", (int)priv->status);
++	iwl4965_init_hw_rates(priv, rates);
 +}
 +
-+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
-+
-+static ssize_t dump_error_log(struct device *d,
-+			      struct device_attribute *attr,
-+			      const char *buf, size_t count)
++/**
++ * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom
++ */
++static int iwl_init_geos(struct iwl_priv *priv)
 +{
-+	char *p = (char *)buf;
-+
-+	if (p[0] == '1')
-+		iwl_dump_nic_error_log((struct iwl_priv *)d->driver_data);
++	struct iwl_channel_info *ch;
++	struct ieee80211_hw_mode *modes;
++	struct ieee80211_channel *channels;
++	struct ieee80211_channel *geo_ch;
++	struct ieee80211_rate *rates;
++	int i = 0;
++	enum {
++		A = 0,
++		B = 1,
++		G = 2,
++		A_11N = 3,
++		G_11N = 4,
++	};
++	int mode_count = 5;
 +
-+	return strnlen(buf, count);
-+}
++	if (priv->modes) {
++		IWL_DEBUG_INFO("Geography modes already initialized.\n");
++		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
++		return 0;
++	}
 +
-+static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
++	modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
++			GFP_KERNEL);
++	if (!modes)
++		return -ENOMEM;
 +
-+static ssize_t dump_event_log(struct device *d,
-+			      struct device_attribute *attr,
-+			      const char *buf, size_t count)
-+{
-+	char *p = (char *)buf;
++	channels = kzalloc(sizeof(struct ieee80211_channel) *
++			   priv->channel_count, GFP_KERNEL);
++	if (!channels) {
++		kfree(modes);
++		return -ENOMEM;
++	}
 +
-+	if (p[0] == '1')
-+		iwl_dump_nic_event_log((struct iwl_priv *)d->driver_data);
++	rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
++			GFP_KERNEL);
++	if (!rates) {
++		kfree(modes);
++		kfree(channels);
++		return -ENOMEM;
++	}
 +
-+	return strnlen(buf, count);
-+}
++	/* 0 = 802.11a
++	 * 1 = 802.11b
++	 * 2 = 802.11g
++	 */
 +
-+static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
++	/* 5.2GHz channels start after the 2.4GHz channels */
++	modes[A].mode = MODE_IEEE80211A;
++	modes[A].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
++	modes[A].rates = rates;
++	modes[A].num_rates = 8;	/* just OFDM */
++	modes[A].rates = &rates[4];
++	modes[A].num_channels = 0;
 +
-+/*****************************************************************************
-+ *
-+ * driver setup and teardown
-+ *
-+ *****************************************************************************/
++	modes[B].mode = MODE_IEEE80211B;
++	modes[B].channels = channels;
++	modes[B].rates = rates;
++	modes[B].num_rates = 4;	/* just CCK */
++	modes[B].num_channels = 0;
 +
-+static void iwl_setup_deferred_work(struct iwl_priv *priv)
-+{
-+	priv->workqueue = create_workqueue(DRV_NAME);
++	modes[G].mode = MODE_IEEE80211G;
++	modes[G].channels = channels;
++	modes[G].rates = rates;
++	modes[G].num_rates = 12;	/* OFDM & CCK */
++	modes[G].num_channels = 0;
 +
-+	init_waitqueue_head(&priv->wait_command_queue);
++	modes[G_11N].mode = MODE_IEEE80211G;
++	modes[G_11N].channels = channels;
++	modes[G_11N].num_rates = 13;        /* OFDM & CCK */
++	modes[G_11N].rates = rates;
++	modes[G_11N].num_channels = 0;
 +
-+	INIT_WORK(&priv->up, iwl_bg_up);
-+	INIT_WORK(&priv->restart, iwl_bg_restart);
-+	INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
-+	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
-+	INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
-+	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
-+	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
-+	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
-+	INIT_DELAYED_WORK(&priv->post_associate, iwl_bg_post_associate);
-+	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
-+	INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
-+	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
++	modes[A_11N].mode = MODE_IEEE80211A;
++	modes[A_11N].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
++	modes[A_11N].rates = &rates[4];
++	modes[A_11N].num_rates = 9; /* just OFDM */
++	modes[A_11N].num_channels = 0;
 +
-+	iwl_hw_setup_deferred_work(priv);
++	priv->ieee_channels = channels;
++	priv->ieee_rates = rates;
 +
-+	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-+		     iwl_irq_tasklet, (unsigned long)priv);
-+}
++	iwl_init_hw_rates(priv, rates);
 +
-+static void iwl_cancel_deferred_work(struct iwl_priv *priv)
-+{
-+	iwl_hw_cancel_deferred_work(priv);
++	for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
++		ch = &priv->channel_info[i];
 +
-+	cancel_delayed_work(&priv->scan_check);
-+	cancel_delayed_work(&priv->alive_start);
-+	cancel_delayed_work(&priv->post_associate);
-+	cancel_work_sync(&priv->beacon_update);
-+}
++		if (!is_channel_valid(ch)) {
++			IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- "
++				    "skipping.\n",
++				    ch->channel, is_channel_a_band(ch) ?
++				    "5.2" : "2.4");
++			continue;
++		}
 +
-+static struct attribute *iwl_sysfs_entries[] = {
-+	&dev_attr_antenna.attr,
-+	&dev_attr_channels.attr,
-+	&dev_attr_dump_errors.attr,
-+	&dev_attr_dump_events.attr,
-+	&dev_attr_flags.attr,
-+	&dev_attr_filter_flags.attr,
-+#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
-+	&dev_attr_measurement.attr,
-+#endif
-+	&dev_attr_power_level.attr,
-+#if IWL == 3945
-+	&dev_attr_rate.attr,
-+#endif
-+	&dev_attr_retry_rate.attr,
-+	&dev_attr_rf_kill.attr,
-+	&dev_attr_rs_window.attr,
-+	&dev_attr_statistics.attr,
-+	&dev_attr_status.attr,
-+	&dev_attr_temperature.attr,
-+	&dev_attr_tune.attr,
-+	&dev_attr_tx_power.attr,
++		if (is_channel_a_band(ch)) {
++			geo_ch = &modes[A].channels[modes[A].num_channels++];
++			modes[A_11N].num_channels++;
++		} else {
++			geo_ch = &modes[B].channels[modes[B].num_channels++];
++			modes[G].num_channels++;
++			modes[G_11N].num_channels++;
++		}
 +
-+	NULL
-+};
++		geo_ch->freq = ieee80211chan2mhz(ch->channel);
++		geo_ch->chan = ch->channel;
++		geo_ch->power_level = ch->max_power_avg;
++		geo_ch->antenna_max = 0xff;
 +
-+static struct attribute_group iwl_attribute_group = {
-+	.name = NULL,		/* put in device directory */
-+	.attrs = iwl_sysfs_entries,
-+};
++		if (is_channel_valid(ch)) {
++			geo_ch->flag = IEEE80211_CHAN_W_SCAN;
++			if (ch->flags & EEPROM_CHANNEL_IBSS)
++				geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
 +
-+static struct ieee80211_ops iwl_hw_ops = {
-+	.tx = iwl_mac_tx,
-+	.open = iwl_mac_open,
-+	.stop = iwl_mac_stop,
-+	.add_interface = iwl_mac_add_interface,
-+	.remove_interface = iwl_mac_remove_interface,
-+	.config = iwl_mac_config,
-+	.config_interface = iwl_mac_config_interface,
-+	.set_key = iwl_mac_set_key,
-+	.get_stats = iwl_mac_get_stats,
-+	.get_tx_stats = iwl_mac_get_tx_stats,
-+	.conf_tx = iwl_mac_conf_tx,
-+	.get_tsf = iwl_mac_get_tsf,
-+	.reset_tsf = iwl_mac_reset_tsf,
-+	.beacon_update = iwl_mac_beacon_update,
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+	.conf_ht = iwl_mac_conf_ht,
-+	.get_ht_capab = iwl_mac_get_ht_capab,
-+#ifdef CONFIG_IWLWIFI_HT_AGG
-+	.ht_tx_agg_start = iwl_mac_ht_tx_agg_start,
-+	.ht_tx_agg_stop = iwl_mac_ht_tx_agg_stop,
-+	.ht_rx_agg_start = iwl_mac_ht_rx_agg_start,
-+	.ht_rx_agg_stop = iwl_mac_ht_rx_agg_stop,
-+#endif  /* CONFIG_IWLWIFI_HT_AGG */
-+#endif  /* CONFIG_IWLWIFI_HT */
-+#endif
-+	.hw_scan = iwl_mac_hw_scan
-+};
++			if (ch->flags & EEPROM_CHANNEL_ACTIVE)
++				geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
 +
-+static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-+{
-+	int err = 0;
-+	u32 pci_id;
-+	struct iwl_priv *priv;
-+	struct ieee80211_hw *hw;
-+	int i;
++			if (ch->flags & EEPROM_CHANNEL_RADAR)
++				geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
 +
-+	if (iwl_param_disable_hw_scan) {
-+		IWL_DEBUG_INFO("Disabling hw_scan\n");
-+		iwl_hw_ops.hw_scan = NULL;
-+	}
++			if (ch->max_power_avg > priv->max_channel_txpower_limit)
++				priv->max_channel_txpower_limit =
++				    ch->max_power_avg;
++		}
 +
-+	if ((iwl_param_queues_num > IWL_MAX_NUM_QUEUES) ||
-+	    (iwl_param_queues_num < IWL_MIN_NUM_QUEUES)) {
-+		IWL_ERROR("invalid queues_num, should be between %d and %d\n",
-+			  IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
-+		err = -EINVAL;
-+		goto out;
++		geo_ch->val = geo_ch->flag;
 +	}
 +
-+	/* mac80211 allocates memory for this device instance, including
-+	 *   space for this driver's private structure */
-+	hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl_hw_ops);
-+	if (hw == NULL) {
-+		IWL_ERROR("Can not allocate network device\n");
-+		err = -ENOMEM;
-+		goto out;
++	if ((modes[A].num_channels == 0) && priv->is_abg) {
++		printk(KERN_INFO DRV_NAME
++		       ": Incorrectly detected BG card as ABG.  Please send "
++		       "your PCI ID 0x%04X:0x%04X to maintainer.\n",
++		       priv->pci_dev->device, priv->pci_dev->subsystem_device);
++		priv->is_abg = 0;
 +	}
-+	SET_IEEE80211_DEV(hw, &pdev->dev);
-+
-+	IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
-+	priv = hw->priv;
-+	priv->hw = hw;
-+
-+	priv->pci_dev = pdev;
-+	priv->antenna = (enum iwl_antenna)iwl_param_antenna;
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	iwl_debug_level = iwl_param_debug;
-+	atomic_set(&priv->restrict_refcnt, 0);
-+#endif
-+	priv->retry_rate = 1;
-+
-+	priv->ibss_beacon = NULL;
 +
-+	/* Tell mac80211 and its clients (e.g. Wireless Extensions)
-+	 *   the range of signal quality values that we'll provide.
-+	 * Negative values for level/noise indicate that we'll provide dBm.
-+	 * For WE, at least, non-0 values here *enable* display of values
-+	 *   in app (iwconfig). */
-+	hw->max_rssi = -20;	/* signal level, negative indicates dBm */
-+	hw->max_noise = -20;	/* noise level, negative indicates dBm */
-+	hw->max_signal = 100;	/* link quality indication (%) */
++	printk(KERN_INFO DRV_NAME
++	       ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
++	       modes[G].num_channels, modes[A].num_channels);
 +
-+	/* Tell mac80211 our Tx characteristics */
-+	hw->flags = IEEE80211_HW_WEP_INCLUDE_IV |
-+	    IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
++	/*
++	 * NOTE:  We register these in preference of order -- the
++	 * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
++	 * a phymode based on rates or AP capabilities but seems to
++	 * configure it purely on if the channel being configured
++	 * is supported by a mode -- and the first match is taken
++	 */
 +
-+	hw->queues = 4;
-+#if IWL == 4965
-+#ifdef CONFIG_IWLWIFI_HT
-+#ifdef CONFIG_IWLWIFI_HT_AGG
-+	hw->queues = 16;
-+#endif /* CONFIG_IWLWIFI_HT_AGG */
-+#endif /* CONFIG_IWLWIFI_HT */
-+#endif /* 4965 */
++	if (modes[G].num_channels)
++		ieee80211_register_hwmode(priv->hw, &modes[G]);
++	if (modes[B].num_channels)
++		ieee80211_register_hwmode(priv->hw, &modes[B]);
++	if (modes[A].num_channels)
++		ieee80211_register_hwmode(priv->hw, &modes[A]);
 +
-+	spin_lock_init(&priv->lock);
-+	spin_lock_init(&priv->power_data.lock);
-+	spin_lock_init(&priv->sta_lock);
-+	spin_lock_init(&priv->hcmd_lock);
-+#if IWL == 4965
-+	spin_lock_init(&priv->lq_mngr.lock);
-+#endif
++	priv->modes = modes;
++	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
 +
-+	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
-+		INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
++	return 0;
++}
 +
-+	INIT_LIST_HEAD(&priv->free_frames);
++/******************************************************************************
++ *
++ * uCode download functions
++ *
++ ******************************************************************************/
 +
-+	mutex_init(&priv->mutex);
-+	if (pci_enable_device(pdev)) {
-+		err = -ENODEV;
-+		goto out_ieee80211_free_hw;
++static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
++{
++	if (priv->ucode_code.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_code.len,
++				    priv->ucode_code.v_addr,
++				    priv->ucode_code.p_addr);
++		priv->ucode_code.v_addr = NULL;
++	}
++	if (priv->ucode_data.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_data.len,
++				    priv->ucode_data.v_addr,
++				    priv->ucode_data.p_addr);
++		priv->ucode_data.v_addr = NULL;
++	}
++	if (priv->ucode_data_backup.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_data_backup.len,
++				    priv->ucode_data_backup.v_addr,
++				    priv->ucode_data_backup.p_addr);
++		priv->ucode_data_backup.v_addr = NULL;
++	}
++	if (priv->ucode_init.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_init.len,
++				    priv->ucode_init.v_addr,
++				    priv->ucode_init.p_addr);
++		priv->ucode_init.v_addr = NULL;
++	}
++	if (priv->ucode_init_data.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_init_data.len,
++				    priv->ucode_init_data.v_addr,
++				    priv->ucode_init_data.p_addr);
++		priv->ucode_init_data.v_addr = NULL;
++	}
++	if (priv->ucode_boot.v_addr != NULL) {
++		pci_free_consistent(priv->pci_dev,
++				    priv->ucode_boot.len,
++				    priv->ucode_boot.v_addr,
++				    priv->ucode_boot.p_addr);
++		priv->ucode_boot.v_addr = NULL;
 +	}
++}
 +
-+	pci_set_master(pdev);
++/**
++ * iwl_verify_inst_full - verify runtime uCode image in card vs. host,
++ *     looking at all data.
++ */
++static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 * image, u32 len)
++{
++	u32 val;
++	u32 save_len = len;
++	int rc = 0;
++	u32 errcnt;
 +
-+	iwl_clear_stations_table(priv);
++	IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
 +
-+	priv->data_retry_limit = -1;
-+	priv->ieee_channels = NULL;
-+	priv->ieee_rates = NULL;
-+	priv->phymode = -1;
++	rc = iwl_grab_restricted_access(priv);
++	if (rc)
++		return rc;
 +
-+	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-+	if (!err)
-+		err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-+	if (err) {
-+		printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n");
-+		goto out_pci_disable_device;
-+	}
++	iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
 +
-+	pci_set_drvdata(pdev, priv);
-+	err = pci_request_regions(pdev, DRV_NAME);
-+	if (err)
-+		goto out_pci_disable_device;
-+	/* We disable the RETRY_TIMEOUT register (0x41) to keep
-+	 * PCI Tx retries from interfering with C3 CPU state */
-+	pci_write_config_byte(pdev, 0x41, 0x00);
-+	priv->hw_base = pci_iomap(pdev, 0, 0);
-+	if (!priv->hw_base) {
-+		err = -ENODEV;
-+		goto out_pci_release_regions;
++	errcnt = 0;
++	for (; len > 0; len -= sizeof(u32), image++) {
++		/* read data comes through single port, auto-incr addr */
++		/* NOTE: Use the debugless read so we don't flood kernel log
++		 * if IWL_DL_IO is set */
++		val = _iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
++		if (val != le32_to_cpu(*image)) {
++			IWL_ERROR("uCode INST section is invalid at "
++				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
++				  save_len - len, val, le32_to_cpu(*image));
++			rc = -EIO;
++			errcnt++;
++			if (errcnt >= 20)
++				break;
++		}
 +	}
 +
-+	IWL_DEBUG_INFO("pci_resource_len = 0x%08llx\n",
-+			(unsigned long long) pci_resource_len(pdev, 0));
-+	IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
-+
-+	/* Initialize module parameter values here */
-+
-+	if (iwl_param_disable) {
-+		set_bit(STATUS_RF_KILL_SW, &priv->status);
-+		IWL_DEBUG_INFO("Radio disabled.\n");
-+	}
++	iwl_release_restricted_access(priv);
 +
-+	priv->iw_mode = IEEE80211_IF_TYPE_STA;
++	if (!errcnt)
++		IWL_DEBUG_INFO
++		    ("ucode image in INSTRUCTION memory is good\n");
 +
-+	pci_id =
-+	    (priv->pci_dev->device << 16) | priv->pci_dev->subsystem_device;
++	return rc;
++}
 +
-+#if IWL == 4965
-+	priv->ps_mode = 0;
-+	priv->use_ant_b_for_management_frame = 1; /* start with ant B */
-+	priv->is_ht_enabled = 1;
-+	priv->channel_width = IWL_CHANNEL_WIDTH_40MHZ;
-+	priv->valid_antenna = 0x7;	/* assume all 3 connected */
-+	priv->ps_mode = IWL_MIMO_PS_NONE;
-+	priv->cck_power_index_compensation = iwl_read32(
-+		priv, CSR_HW_REV_WA_REG);
 +
-+	iwl4965_set_rxon_chain(priv);
++/**
++ * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
++ *   using sample data 100 bytes apart.  If these sample points are good,
++ *   it's a pretty good bet that everything between them is good, too.
++ */
++static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
++{
++	u32 val;
++	int rc = 0;
++	u32 errcnt = 0;
++	u32 i;
 +
-+	printk(KERN_INFO DRV_NAME
-+	       ": Detected Intel Wireless WiFi Link 4965AGN\n");
-+#else
-+	switch (pci_id) {
-+	case 0x42221005:	/* 0x4222 0x8086 0x1005 is BG SKU */
-+	case 0x42221034:	/* 0x4222 0x8086 0x1034 is BG SKU */
-+	case 0x42271014:	/* 0x4227 0x8086 0x1014 is BG SKU */
-+	case 0x42221044:	/* 0x4222 0x8086 0x1044 is BG SKU */
-+		priv->is_abg = 0;
-+		break;
++	IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
 +
-+	/*
-+	 * Rest are assumed ABG SKU -- if this is not the
-+	 * case then the card will get the wrong 'Detected'
-+	 * line in the kernel log however the code that
-+	 * initializes the GEO table will detect no A-band
-+	 * channels and remove the is_abg mask.
-+	 */
-+	default:
-+		priv->is_abg = 1;
-+		break;
-+	}
++	rc = iwl_grab_restricted_access(priv);
++	if (rc)
++		return rc;
 +
-+	printk(KERN_INFO DRV_NAME
-+	       ": Detected Intel PRO/Wireless 3945%sBG Network Connection\n",
-+	       priv->is_abg ? "A" : "");
++	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
++		/* read data comes through single port, auto-incr addr */
++		/* NOTE: Use the debugless read so we don't flood kernel log
++		 * if IWL_DL_IO is set */
++		iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR,
++			i + RTC_INST_LOWER_BOUND);
++		val = _iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
++		if (val != le32_to_cpu(*image)) {
++#if 0 /* Enable this if you want to see details */
++			IWL_ERROR("uCode INST section is invalid at "
++				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
++				  i, val, *image);
 +#endif
-+
-+	/* Device-specific setup */
-+	if (iwl_hw_set_hw_setting(priv)) {
-+		IWL_ERROR("failed to set hw settings\n");
-+		mutex_unlock(&priv->mutex);
-+		goto out_iounmap;
++			rc = -EIO;
++			errcnt++;
++			if (errcnt >= 3)
++				break;
++		}
 +	}
 +
-+#ifdef CONFIG_IWLWIFI_QOS
-+	if (iwl_param_qos_enable)
-+		priv->qos_data.qos_enable = 1;
-+	priv->qos_data.qos_active = 0;
-+	priv->qos_data.qos_cap.val = 0;
-+#endif /* CONFIG_IWLWIFI_QOS */
++	iwl_release_restricted_access(priv);
 +
-+	iwl_set_rxon_channel(priv, MODE_IEEE80211G, 6);
-+	iwl_setup_deferred_work(priv);
-+	iwl_setup_rx_handlers(priv);
++	return rc;
++}
 +
-+	priv->rates_mask = IWL_RATES_MASK;
-+	/* If power management is turned on, default to AC mode */
-+	priv->power_mode = IWL_POWER_AC;
-+	priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
 +
-+	pci_enable_msi(pdev);
++/**
++ * iwl_verify_ucode - determine which instruction image is in SRAM,
++ *    and verify its contents
++ */
++static int iwl_verify_ucode(struct iwl_priv *priv)
++{
++	__le32 *image;
++	u32 len;
++	int rc = 0;
 +
-+	err = request_irq(pdev->irq, iwl_isr, IRQF_SHARED, DRV_NAME, priv);
-+	if (err) {
-+		IWL_ERROR("Error allocating IRQ %d\n", pdev->irq);
-+		goto out_disable_msi;
++	/* Try bootstrap */
++	image = (__le32 *)priv->ucode_boot.v_addr;
++	len = priv->ucode_boot.len;
++	rc = iwl_verify_inst_sparse(priv, image, len);
++	if (rc == 0) {
++		IWL_DEBUG_INFO("Bootstrap uCode is good in inst SRAM\n");
++		return 0;
 +	}
 +
-+	mutex_lock(&priv->mutex);
-+
-+	err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
-+	if (err) {
-+		IWL_ERROR("failed to create sysfs device attributes\n");
-+		mutex_unlock(&priv->mutex);
-+		goto out_release_irq;
++	/* Try initialize */
++	image = (__le32 *)priv->ucode_init.v_addr;
++	len = priv->ucode_init.len;
++	rc = iwl_verify_inst_sparse(priv, image, len);
++	if (rc == 0) {
++		IWL_DEBUG_INFO("Initialize uCode is good in inst SRAM\n");
++		return 0;
 +	}
 +
-+	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
-+	 * ucode filename and max sizes are card-specific. */
-+	err = iwl_read_ucode(priv);
-+	if (err) {
-+		IWL_ERROR("Could not read microcode: %d\n", err);
-+		mutex_unlock(&priv->mutex);
-+		goto out_pci_alloc;
++	/* Try runtime/protocol */
++	image = (__le32 *)priv->ucode_code.v_addr;
++	len = priv->ucode_code.len;
++	rc = iwl_verify_inst_sparse(priv, image, len);
++	if (rc == 0) {
++		IWL_DEBUG_INFO("Runtime uCode is good in inst SRAM\n");
++		return 0;
 +	}
 +
-+	mutex_unlock(&priv->mutex);
++	IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
 +
-+	IWL_DEBUG_INFO("Queing UP work.\n");
++	/* Show first several data entries in instruction SRAM.
++	 * Selection of bootstrap image is arbitrary. */
++	image = (__le32 *)priv->ucode_boot.v_addr;
++	len = priv->ucode_boot.len;
++	rc = iwl_verify_inst_full(priv, image, len);
 +
-+	queue_work(priv->workqueue, &priv->up);
++	return rc;
++}
 +
-+	return 0;
 +
-+ out_pci_alloc:
-+	iwl_dealloc_ucode_pci(priv);
++/* check contents of special bootstrap uCode SRAM */
++static int iwl_verify_bsm(struct iwl_priv *priv)
++{
++	__le32 *image = priv->ucode_boot.v_addr;
++	u32 len = priv->ucode_boot.len;
++	u32 reg;
++	u32 val;
 +
-+	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
++	IWL_DEBUG_INFO("Begin verify bsm\n");
 +
-+ out_release_irq:
-+	free_irq(pdev->irq, priv);
++	/* verify BSM SRAM contents */
++	val = iwl_read_restricted_reg(priv, BSM_WR_DWCOUNT_REG);
++	for (reg = BSM_SRAM_LOWER_BOUND;
++	     reg < BSM_SRAM_LOWER_BOUND + len;
++	     reg += sizeof(u32), image ++) {
++		val = iwl_read_restricted_reg(priv, reg);
++		if (val != le32_to_cpu(*image)) {
++			IWL_ERROR("BSM uCode verification failed at "
++				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
++				  BSM_SRAM_LOWER_BOUND,
++				  reg - BSM_SRAM_LOWER_BOUND, len,
++				  val, le32_to_cpu(*image));
++			return -EIO;
++		}
++	}
 +
-+ out_disable_msi:
-+	pci_disable_msi(pdev);
-+	destroy_workqueue(priv->workqueue);
-+	priv->workqueue = NULL;
-+	iwl_unset_hw_setting(priv);
++	IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
 +
-+ out_iounmap:
-+	pci_iounmap(pdev, priv->hw_base);
-+ out_pci_release_regions:
-+	pci_release_regions(pdev);
-+ out_pci_disable_device:
-+	pci_disable_device(pdev);
-+	pci_set_drvdata(pdev, NULL);
-+ out_ieee80211_free_hw:
-+	ieee80211_free_hw(priv->hw);
-+ out:
-+	return err;
++	return 0;
 +}
 +
-+static void iwl_pci_remove(struct pci_dev *pdev)
++/**
++ * iwl_load_bsm - Load bootstrap instructions
++ *
++ * BSM operation:
++ *
++ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
++ * in special SRAM that does not power down during RFKILL.  When powering back
++ * up after power-saving sleeps (or during initial uCode load), the BSM loads
++ * the bootstrap program into the on-board processor, and starts it.
++ *
++ * The bootstrap program loads (via DMA) instructions and data for a new
++ * program from host DRAM locations indicated by the host driver in the
++ * BSM_DRAM_* registers.  Once the new program is loaded, it starts
++ * automatically.
++ *
++ * When initializing the NIC, the host driver points the BSM to the
++ * "initialize" uCode image.  This uCode sets up some internal data, then
++ * notifies host via "initialize alive" that it is complete.
++ *
++ * The host then replaces the BSM_DRAM_* pointer values to point to the
++ * normal runtime uCode instructions and a backup uCode data cache buffer
++ * (filled initially with starting data values for the on-board processor),
++ * then triggers the "initialize" uCode to load and launch the runtime uCode,
++ * which begins normal operation.
++ *
++ * When doing a power-save shutdown, runtime uCode saves data SRAM into
++ * the backup data cache in DRAM before SRAM is powered down.
++ *
++ * When powering back up, the BSM loads the bootstrap program.  This reloads
++ * the runtime uCode instructions and the backup data cache into SRAM,
++ * and re-launches the runtime uCode from where it left off.
++ */
++static int iwl_load_bsm(struct iwl_priv *priv)
 +{
-+	struct iwl_priv *priv = pci_get_drvdata(pdev);
-+	struct list_head *p, *q;
++	__le32 *image = priv->ucode_boot.v_addr;
++	u32 len = priv->ucode_boot.len;
++	dma_addr_t pinst;
++	dma_addr_t pdata;
++	u32 inst_len;
++	u32 data_len;
++	int rc;
 +	int i;
++	u32 done;
++	u32 reg_offset;
 +
-+	if (!priv)
-+		return;
-+
-+	IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n");
-+
-+	mutex_lock(&priv->mutex);
-+	set_bit(STATUS_EXIT_PENDING, &priv->status);
-+	__iwl_down(priv);
-+	mutex_unlock(&priv->mutex);
++	IWL_DEBUG_INFO("Begin load bsm\n");
 +
-+	/* Free MAC hash list for ADHOC */
-+	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
-+		list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
-+			list_del(p);
-+			kfree(list_entry(p, struct iwl_ibss_seq, list));
-+		}
-+	}
++	/* make sure bootstrap program is no larger than BSM's SRAM size */
++	if (len > IWL_MAX_BSM_SIZE)
++		return -EINVAL;
 +
-+	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
++	/* Tell bootstrap uCode where to find the "Initialize" uCode
++	 *   in host DRAM ... bits 31:0 for 3945, bits 35:4 for 4965.
++	 * NOTE:  iwl_initialize_alive_start() will replace these values,
++	 *        after the "initialize" uCode has run, to point to
++	 *        runtime/protocol instructions and backup data cache. */
++	pinst = priv->ucode_init.p_addr >> 4;
++	pdata = priv->ucode_init_data.p_addr >> 4;
++	inst_len = priv->ucode_init.len;
++	data_len = priv->ucode_init_data.len;
 +
-+	iwl_dealloc_ucode_pci(priv);
++	rc = iwl_grab_restricted_access(priv);
++	if (rc)
++		return rc;
 +
-+	if (priv->rxq.bd)
-+		iwl_rx_queue_free(priv, &priv->rxq);
-+	iwl_hw_txq_ctx_free(priv);
++	iwl_write_restricted_reg(priv, BSM_DRAM_INST_PTR_REG, pinst);
++	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_PTR_REG, pdata);
++	iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
++	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
 +
-+	iwl_unset_hw_setting(priv);
-+	iwl_clear_stations_table(priv);
++	/* Fill BSM memory with bootstrap instructions */
++	for (reg_offset = BSM_SRAM_LOWER_BOUND;
++	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
++	     reg_offset += sizeof(u32), image++)
++		_iwl_write_restricted_reg(priv, reg_offset,
++					  le32_to_cpu(*image));
 +
-+	if (priv->mac80211_registered) {
-+		ieee80211_unregister_hw(priv->hw);
-+		iwl_rate_control_unregister(priv->hw);
++	rc = iwl_verify_bsm(priv);
++	if (rc) {
++		iwl_release_restricted_access(priv);
++		return rc;
 +	}
 +
-+	/* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
-+	 * priv->workqueue... so we can't take down the workqueue
-+	 * until now... */
-+	destroy_workqueue(priv->workqueue);
-+	priv->workqueue = NULL;
++	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
++	iwl_write_restricted_reg(priv, BSM_WR_MEM_SRC_REG, 0x0);
++	iwl_write_restricted_reg(priv, BSM_WR_MEM_DST_REG,
++				 RTC_INST_LOWER_BOUND);
++	iwl_write_restricted_reg(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
 +
-+	free_irq(pdev->irq, priv);
-+	pci_disable_msi(pdev);
-+	pci_iounmap(pdev, priv->hw_base);
-+	pci_release_regions(pdev);
-+	pci_disable_device(pdev);
-+	pci_set_drvdata(pdev, NULL);
++	/* Load bootstrap code into instruction SRAM now,
++	 *   to prepare to load "initialize" uCode */
++	iwl_write_restricted_reg(priv, BSM_WR_CTRL_REG,
++		BSM_WR_CTRL_REG_BIT_START);
 +
-+	kfree(priv->channel_info);
++	/* Wait for load of bootstrap uCode to finish */
++	for (i = 0; i < 100; i++) {
++		done = iwl_read_restricted_reg(priv, BSM_WR_CTRL_REG);
++		if (!(done & BSM_WR_CTRL_REG_BIT_START))
++			break;
++		udelay(10);
++	}
++	if (i < 100)
++		IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
++	else {
++		IWL_ERROR("BSM write did not complete!\n");
++		return -EIO;
++	}
 +
-+	kfree(priv->ieee_channels);
-+	kfree(priv->ieee_rates);
++	/* Enable future boot loads whenever power management unit triggers it
++	 *   (e.g. when powering back up after power-save shutdown) */
++	iwl_write_restricted_reg(priv, BSM_WR_CTRL_REG,
++		BSM_WR_CTRL_REG_BIT_START_EN);
 +
-+	if (priv->ibss_beacon)
-+		dev_kfree_skb(priv->ibss_beacon);
++	iwl_release_restricted_access(priv);
 +
-+	ieee80211_free_hw(priv->hw);
++	return 0;
 +}
 +
-+#ifdef CONFIG_PM
++static void iwl_nic_start(struct iwl_priv *priv)
++{
++	/* Remove all resets to allow NIC to operate */
++	iwl_write32(priv, CSR_RESET, 0);
++}
 +
-+static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
++/**
++ * iwl_read_ucode - Read uCode images from disk file.
++ *
++ * Copy into buffers for card to fetch via bus-mastering
++ */
++static int iwl_read_ucode(struct iwl_priv *priv)
 +{
-+	struct iwl_priv *priv = pci_get_drvdata(pdev);
++	struct iwl_ucode *ucode;
++	int rc = 0;
++	const struct firmware *ucode_raw;
++	const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode";
++	u8 *src;
++	size_t len;
++	u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
 +
-+	mutex_lock(&priv->mutex);
++	/* Ask kernel firmware_class module to get the boot firmware off disk.
++	 * request_firmware() is synchronous, file is in memory on return. */
++	rc = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
++	if (rc < 0) {
++		IWL_ERROR("%s firmware file req failed: Reason %d\n", name, rc);
++		goto error;
++	}
 +
-+	set_bit(STATUS_IN_SUSPEND, &priv->status);
++	IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
++		       name, ucode_raw->size);
 +
-+	/* Take down the device; powers it off, etc. */
-+	__iwl_down(priv);
++	/* Make sure that we got at least our header! */
++	if (ucode_raw->size < sizeof(*ucode)) {
++		IWL_ERROR("File size way too small!\n");
++		rc = -EINVAL;
++		goto err_release;
++	}
 +
-+	if (priv->mac80211_registered)
-+		ieee80211_stop_queues(priv->hw);
++	/* Data from ucode file:  header followed by uCode images */
++	ucode = (void *)ucode_raw->data;
 +
-+	pci_save_state(pdev);
-+	pci_disable_device(pdev);
-+	pci_set_power_state(pdev, PCI_D3hot);
++	ver = le32_to_cpu(ucode->ver);
++	inst_size = le32_to_cpu(ucode->inst_size);
++	data_size = le32_to_cpu(ucode->data_size);
++	init_size = le32_to_cpu(ucode->init_size);
++	init_data_size = le32_to_cpu(ucode->init_data_size);
++	boot_size = le32_to_cpu(ucode->boot_size);
 +
-+	mutex_unlock(&priv->mutex);
++	IWL_DEBUG_INFO("f/w package hdr ucode version = 0x%x\n", ver);
++	IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n",
++		       inst_size);
++	IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n",
++		       data_size);
++	IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n",
++		       init_size);
++	IWL_DEBUG_INFO("f/w package hdr init data size = %u\n",
++		       init_data_size);
++	IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n",
++		       boot_size);
 +
-+	return 0;
-+}
++	/* Verify size of file vs. image size info in file's header */
++	if (ucode_raw->size < sizeof(*ucode) +
++		inst_size + data_size + init_size +
++		init_data_size + boot_size) {
 +
-+static void iwl_resume(struct iwl_priv *priv)
-+{
-+	unsigned long flags;
++		IWL_DEBUG_INFO("uCode file size %d too small\n",
++			       (int)ucode_raw->size);
++		rc = -EINVAL;
++		goto err_release;
++	}
 +
-+	/* The following it a temporary work around due to the
-+	 * suspend / resume not fully initializing the NIC correctly.
-+	 * Without all of the following, resume will not attempt to take
-+	 * down the NIC (it shouldn't really need to) and will just try
-+	 * and bring the NIC back up.  However that fails during the
-+	 * ucode verification process.  This then causes iwl_down to be
-+	 * called *after* iwl_hw_nic_init() has succeeded -- which
-+	 * then lets the next init sequence succeed.  So, we've
-+	 * replicated all of that NIC init code here... */
++	/* Verify that uCode images will fit in card's SRAM */
++	if (inst_size > IWL_MAX_INST_SIZE) {
++		IWL_DEBUG_INFO("uCode instr len %d too large to fit in card\n",
++			       (int)inst_size);
++		rc = -EINVAL;
++		goto err_release;
++	}
 +
-+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
++	if (data_size > IWL_MAX_DATA_SIZE) {
++		IWL_DEBUG_INFO("uCode data len %d too large to fit in card\n",
++			       (int)data_size);
++		rc = -EINVAL;
++		goto err_release;
++	}
++	if (init_size > IWL_MAX_INST_SIZE) {
++		IWL_DEBUG_INFO
++		    ("uCode init instr len %d too large to fit in card\n",
++		     (int)init_size);
++		rc = -EINVAL;
++		goto err_release;
++	}
++	if (init_data_size > IWL_MAX_DATA_SIZE) {
++		IWL_DEBUG_INFO
++		    ("uCode init data len %d too large to fit in card\n",
++		     (int)init_data_size);
++		rc = -EINVAL;
++		goto err_release;
++	}
++	if (boot_size > IWL_MAX_BSM_SIZE) {
++		IWL_DEBUG_INFO
++		    ("uCode boot instr len %d too large to fit in bsm\n",
++		     (int)boot_size);
++		rc = -EINVAL;
++		goto err_release;
++	}
 +
-+	iwl_hw_nic_init(priv);
++	/* Allocate ucode buffers for card's bus-master loading ... */
 +
-+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-+		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	/* Runtime instructions and 2 copies of data:
++	 * 1) unmodified from disk
++	 * 2) backup cache for save/restore during power-downs */
++	priv->ucode_code.len = inst_size;
++	priv->ucode_code.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_code.len,
++				 &(priv->ucode_code.p_addr));
 +
-+	/* tell the device to stop sending interrupts */
-+	iwl_disable_interrupts(priv);
++	priv->ucode_data.len = data_size;
++	priv->ucode_data.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_data.len,
++				 &(priv->ucode_data.p_addr));
++
++	priv->ucode_data_backup.len = data_size;
++	priv->ucode_data_backup.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_data_backup.len,
++				 &(priv->ucode_data_backup.p_addr));
 +
-+	spin_lock_irqsave(&priv->lock, flags);
-+	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 +
-+	if (!iwl_grab_restricted_access(priv)) {
-+		iwl_write_restricted_reg(priv, ALM_APMG_CLK_DIS,
-+					 APMG_CLK_REG_VAL_DMA_CLK_RQT);
-+		iwl_release_restricted_access(priv);
-+	}
-+	spin_unlock_irqrestore(&priv->lock, flags);
++	/* Initialization instructions and data */
++	priv->ucode_init.len = init_size;
++	priv->ucode_init.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_init.len,
++				 &(priv->ucode_init.p_addr));
 +
-+	udelay(5);
++	priv->ucode_init_data.len = init_data_size;
++	priv->ucode_init_data.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_init_data.len,
++				 &(priv->ucode_init_data.p_addr));
 +
-+	iwl_hw_nic_reset(priv);
++	/* Bootstrap (instructions only, no data) */
++	priv->ucode_boot.len = boot_size;
++	priv->ucode_boot.v_addr =
++	    pci_alloc_consistent(priv->pci_dev,
++				 priv->ucode_boot.len,
++				 &(priv->ucode_boot.p_addr));
 +
-+	/* Bring the device back up */
-+	clear_bit(STATUS_IN_SUSPEND, &priv->status);
-+	queue_work(priv->workqueue, &priv->up);
-+}
++	if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
++	    !priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr ||
++	    !priv->ucode_boot.v_addr || !priv->ucode_data_backup.v_addr)
++		goto err_pci_alloc;
 +
-+static int iwl_pci_resume(struct pci_dev *pdev)
-+{
-+	struct iwl_priv *priv = pci_get_drvdata(pdev);
-+	int err;
++	/* Copy images into buffers for card's bus-master reads ... */
 +
-+	printk(KERN_INFO "Coming out of suspend...\n");
++	/* Runtime instructions (first block of data in file) */
++	src = &ucode->data[0];
++	len = priv->ucode_code.len;
++	IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %d\n",
++		       (int)len);
++	memcpy(priv->ucode_code.v_addr, src, len);
++	IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
++		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
 +
-+	mutex_lock(&priv->mutex);
++	/* Runtime data (2nd block)
++	 * NOTE:  Copy into backup buffer will be done in iwl_up()  */
++	src = &ucode->data[inst_size];
++	len = priv->ucode_data.len;
++	IWL_DEBUG_INFO("Copying (but not loading) uCode data len %d\n",
++		       (int)len);
++	memcpy(priv->ucode_data.v_addr, src, len);
++	memcpy(priv->ucode_data_backup.v_addr, src, len);
 +
-+	pci_set_power_state(pdev, PCI_D0);
-+	err = pci_enable_device(pdev);
-+	pci_restore_state(pdev);
++	/* Initialization instructions (3rd block) */
++	if (init_size) {
++		src = &ucode->data[inst_size + data_size];
++		len = priv->ucode_init.len;
++		IWL_DEBUG_INFO("Copying (but not loading) init instr len %d\n",
++			       (int)len);
++		memcpy(priv->ucode_init.v_addr, src, len);
++	}
 +
-+	/*
-+	 * Suspend/Resume resets the PCI configuration space, so we have to
-+	 * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
-+	 * from interfering with C3 CPU state. pci_restore_state won't help
-+	 * here since it only restores the first 64 bytes pci config header.
-+	 */
-+	pci_write_config_byte(pdev, 0x41, 0x00);
++	/* Initialization data (4th block) */
++	if (init_data_size) {
++		src = &ucode->data[inst_size + data_size + init_size];
++		len = priv->ucode_init_data.len;
++		IWL_DEBUG_INFO("Copying (but not loading) init data len %d\n",
++			       (int)len);
++		memcpy(priv->ucode_init_data.v_addr, src, len);
++	}
 +
-+	iwl_resume(priv);
-+	mutex_unlock(&priv->mutex);
++	/* Bootstrap instructions (5th block) */
++	src = &ucode->data[inst_size + data_size + init_size + init_data_size];
++	len = priv->ucode_boot.len;
++	IWL_DEBUG_INFO("Copying (but not loading) boot instr len %d\n",
++		       (int)len);
++	memcpy(priv->ucode_boot.v_addr, src, len);
 +
++	/* We have our copies now, allow OS release its copies */
++	release_firmware(ucode_raw);
 +	return 0;
++
++ err_pci_alloc:
++	IWL_ERROR("failed to allocate pci memory\n");
++	rc = -ENOMEM;
++	iwl_dealloc_ucode_pci(priv);
++
++ err_release:
++	release_firmware(ucode_raw);
++
++ error:
++	return rc;
 +}
 +
-+#endif /* CONFIG_PM */
 +
-+/*****************************************************************************
++/**
++ * iwl_set_ucode_ptrs - Set uCode address location
 + *
-+ * driver and module entry point
++ * Tell initialization uCode where to find runtime uCode.
 + *
-+ *****************************************************************************/
-+
-+static struct pci_driver iwl_driver = {
-+	.name = DRV_NAME,
-+	.id_table = iwl_hw_card_ids,
-+	.probe = iwl_pci_probe,
-+	.remove = __devexit_p(iwl_pci_remove),
-+#ifdef CONFIG_PM
-+	.suspend = iwl_pci_suspend,
-+	.resume = iwl_pci_resume,
-+#endif
-+};
-+
-+static int __init iwl_init(void)
++ * BSM registers initially contain pointers to initialization uCode.
++ * We need to replace them to load runtime uCode inst and data,
++ * and to save runtime data when powering down.
++ */
++static int iwl_set_ucode_ptrs(struct iwl_priv *priv)
 +{
++	dma_addr_t pinst;
++	dma_addr_t pdata;
++	int rc = 0;
++	unsigned long flags;
 +
-+	int ret;
-+	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
-+	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
-+	ret = pci_register_driver(&iwl_driver);
-+	if (ret) {
-+		IWL_ERROR("Unable to initialize PCI module\n");
-+		return ret;
-+	}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level);
-+	if (ret) {
-+		IWL_ERROR("Unable to create driver sysfs file\n");
-+		pci_unregister_driver(&iwl_driver);
-+		return ret;
++	/* bits 35:4 for 4965 */
++	pinst = priv->ucode_code.p_addr >> 4;
++	pdata = priv->ucode_data_backup.p_addr >> 4;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	rc = iwl_grab_restricted_access(priv);
++	if (rc) {
++		spin_unlock_irqrestore(&priv->lock, flags);
++		return rc;
 +	}
-+#endif
 +
-+	return ret;
-+}
++	/* Tell bootstrap uCode where to find image to load */
++	iwl_write_restricted_reg(priv, BSM_DRAM_INST_PTR_REG, pinst);
++	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_PTR_REG, pdata);
++	iwl_write_restricted_reg(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
++				 priv->ucode_data.len);
 +
-+static void __exit iwl_exit(void)
-+{
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level);
-+#endif
-+	pci_unregister_driver(&iwl_driver);
-+}
++	/* Inst bytecount must be last to set up, bit 31 signals uCode
++	 *   that all new ptr/size info is in place */
++	iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG,
++				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
 +
-+module_param_named(antenna, iwl_param_antenna, int, 0444);
-+MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-+module_param_named(disable, iwl_param_disable, int, 0444);
-+MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
-+module_param_named(hwcrypto, iwl_param_hwcrypto, int, 0444);
-+MODULE_PARM_DESC(hwcrypto,
-+		 "using hardware crypto engine (default 0 [software])\n");
-+module_param_named(debug, iwl_param_debug, int, 0444);
-+MODULE_PARM_DESC(debug, "debug output mask");
-+module_param_named(disable_hw_scan, iwl_param_disable_hw_scan, int, 0444);
-+MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
++	iwl_release_restricted_access(priv);
 +
-+module_param_named(queues_num, iwl_param_queues_num, int, 0444);
-+MODULE_PARM_DESC(queues_num, "number of hw queues.");
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+/* QoS */
-+module_param_named(qos_enable, iwl_param_qos_enable, int, 0444);
-+MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
++	IWL_DEBUG_INFO("Runtime uCode pointers are set.\n");
 +
-+module_exit(iwl_exit);
-+module_init(iwl_init);
-diff --git a/drivers/net/wireless/iwl-channel.h b/drivers/net/wireless/iwl-channel.h
-new file mode 100644
-index 0000000..023c3f2
---- /dev/null
-+++ b/drivers/net/wireless/iwl-channel.h
-@@ -0,0 +1,161 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++	return rc;
++}
++
++/**
++ * iwl_init_alive_start - Called after REPLY_ALIVE notification receieved
 + *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
++ * Called after REPLY_ALIVE notification received from "initialize" uCode.
 + *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ * The 4965 "initialize" ALIVE reply contains calibration data for:
++ *   Voltage, temperature, and MIMO tx gain correction, now stored in priv
++ *   (3945 does not contain this data).
 + *
-+ *****************************************************************************/
-+#ifndef __iwl_channel_h__
-+#define __iwl_channel_h__
-+
-+#define IWL_NUM_SCAN_RATES         (2)
++ * Tell "initialize" uCode to go ahead and load the runtime uCode.
++*/
++static void iwl_init_alive_start(struct iwl_priv *priv)
++{
++	/* Check alive response for "valid" sign from uCode */
++	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
++		/* We had an error bringing up the hardware, so take it
++		 * all the way back down so we can try again */
++		IWL_DEBUG_INFO("Initialize Alive failed.\n");
++		goto restart;
++	}
 +
-+struct iwl_channel_tgd_info {
-+	u8 type;
-+	s8 max_power;
-+};
++	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
++	 * This is a paranoid check, because we would not have gotten the
++	 * "initialize" alive if code weren't properly loaded.  */
++	if (iwl_verify_ucode(priv)) {
++		/* Runtime instruction load was bad;
++		 * take it all the way back down so we can try again */
++		IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
++		goto restart;
++	}
 +
-+struct iwl_channel_tgh_info {
-+	s64 last_radar_time;
-+};
++	/* Calculate temperature */
++	priv->temperature = iwl4965_get_temperature(priv);
 +
-+/* current Tx power values to use, one for each rate for each channel.
-+ * requested power is limited by:
-+ * -- regulatory EEPROM limits for this channel
-+ * -- hardware capabilities (clip-powers)
-+ * -- spectrum management
-+ * -- user preference (e.g. iwconfig)
-+ * when requested power is set, base power index must also be set. */
-+struct iwl_channel_power_info {
-+	struct iwl_tx_power tpc;	/* actual radio and DSP gain settings */
-+	s8 power_table_index;	/* actual (compenst'd) index into gain table */
-+	s8 base_power_index;	/* gain index for power at factory temp. */
-+	s8 requested_power;	/* power (dBm) requested for this chnl/rate */
-+};
++	/* Send pointers to protocol/runtime uCode image ... init code will
++	 * load and launch runtime uCode, which will send us another "Alive"
++	 * notification. */
++	IWL_DEBUG_INFO("Initialization Alive received.\n");
++	if (iwl_set_ucode_ptrs(priv)) {
++		/* Runtime instruction load won't happen;
++		 * take it all the way back down so we can try again */
++		IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n");
++		goto restart;
++	}
++	return;
 +
-+/* current scan Tx power values to use, one for each scan rate for each
-+ * channel. */
-+struct iwl_scan_power_info {
-+	struct iwl_tx_power tpc;	/* actual radio and DSP gain settings */
-+	s8 power_table_index;	/* actual (compenst'd) index into gain table */
-+	s8 requested_power;	/* scan pwr (dBm) requested for chnl/rate */
-+};
++ restart:
++	queue_work(priv->workqueue, &priv->restart);
++}
 +
-+/* Channel unlock period is 15 seconds. If no beacon or probe response
-+ * has been received within 15 seconds on a locked channel then the channel
-+ * remains locked. */
-+#define TX_UNLOCK_PERIOD 15
 +
-+/* CSA lock period is 15 seconds.  If a CSA has been received on a channel in
-+ * the last 15 seconds, the channel is locked */
-+#define CSA_LOCK_PERIOD 15
-+/*
-+ * One for each channel, holds all channel setup data
-+ * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
-+ *     with one another!
++/**
++ * iwl_alive_start - called after REPLY_ALIVE notification received
++ *                   from protocol/runtime uCode (initialization uCode's
++ *                   Alive gets handled by iwl_init_alive_start()).
 + */
-+#define IWL4965_MAX_RATE (33)
++static void iwl_alive_start(struct iwl_priv *priv)
++{
++	int rc = 0;
 +
-+struct iwl_channel_info {
-+	struct iwl_channel_tgd_info tgd;
-+	struct iwl_channel_tgh_info tgh;
-+	struct iwl_eeprom_channel eeprom;	/* EEPROM regulatory limit */
-+	struct iwl_eeprom_channel fat_eeprom;	/* EEPROM regulatory limit for
-+						 * FAT channel */
++	IWL_DEBUG_INFO("Runtime Alive received.\n");
 +
-+	u8 channel;	  /* channel number */
-+	u8 flags;	  /* flags copied from EEPROM */
-+	s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
-+	s8 curr_txpow;	  /* (dBm) regulatory/spectrum/user (not h/w) */
-+	s8 min_power;	  /* always 0 */
-+	s8 scan_power;	  /* (dBm) regul. eeprom, direct scans, any rate */
++	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
++		/* We had an error bringing up the hardware, so take it
++		 * all the way back down so we can try again */
++		IWL_DEBUG_INFO("Alive failed.\n");
++		goto restart;
++	}
 +
-+	u8 group_index;	  /* 0-4, maps channel to group1/2/3/4/5 */
-+	u8 band_index;	  /* 0-4, maps channel to band1/2/3/4/5 */
-+	u8 phymode;	  /* MODE_IEEE80211{A,B,G} */
++	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
++	 * This is a paranoid check, because we would not have gotten the
++	 * "runtime" alive if code weren't properly loaded.  */
++	if (iwl_verify_ucode(priv)) {
++		/* Runtime instruction load was bad;
++		 * take it all the way back down so we can try again */
++		IWL_DEBUG_INFO("Bad runtime uCode load.\n");
++		goto restart;
++	}
 +
-+	/* Radio/DSP gain settings for each "normal" data Tx rate.
-+	 * These include, in addition to RF and DSP gain, a few fields for
-+	 *   remembering/modifying gain settings (indexes). */
-+	struct iwl_channel_power_info power_info[IWL4965_MAX_RATE];
++	iwl_clear_stations_table(priv);
 +
-+#if IWL == 4965
-+	/* FAT channel info */
-+	s8 fat_max_power_avg;	/* (dBm) regul. eeprom, normal Tx, any rate */
-+	s8 fat_curr_txpow;	/* (dBm) regulatory/spectrum/user (not h/w) */
-+	s8 fat_min_power;	/* always 0 */
-+	s8 fat_scan_power;	/* (dBm) eeprom, direct scans, any rate */
-+	u8 fat_flags;		/* flags copied from EEPROM */
-+	u8 fat_extension_channel;
-+#endif
++	rc = iwl4965_alive_notify(priv);
++	if (rc) {
++		IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
++			    rc);
++		goto restart;
++	}
 +
-+	/* Radio/DSP gain settings for each scan rate, for directed scans. */
-+	struct iwl_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
-+};
++	/* After the ALIVE response, we can process host commands */
++	set_bit(STATUS_ALIVE, &priv->status);
 +
-+struct iwl_clip_group {
-+	/* maximum power level to prevent clipping for each rate, derived by
-+	 *   us from this band's saturation power in EEPROM */
-+	const s8 clip_powers[IWL_MAX_RATES];
-+};
++	/* Clear out the uCode error bit if it is set */
++	clear_bit(STATUS_FW_ERROR, &priv->status);
 +
-+static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
-+{
-+	if (ch_info == NULL)
-+		return 0;
-+	return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
-+}
++	rc = iwl_init_channel_map(priv);
++	if (rc) {
++		IWL_ERROR("initializing regulatory failed: %d\n", rc);
++		return;
++	}
 +
-+static inline int is_channel_narrow(const struct iwl_channel_info *ch_info)
-+{
-+	return (ch_info->flags & EEPROM_CHANNEL_NARROW) ? 1 : 0;
-+}
++	iwl_init_geos(priv);
 +
-+static inline int is_channel_radar(const struct iwl_channel_info *ch_info)
-+{
-+	return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
-+}
++	if (iwl_is_rfkill(priv))
++		return;
 +
-+static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info)
-+{
-+	return ch_info->phymode == MODE_IEEE80211A;
-+}
++	if (!priv->mac80211_registered) {
++		/* Unlock so any user space entry points can call back into
++		 * the driver without a deadlock... */
++		mutex_unlock(&priv->mutex);
++		iwl_rate_control_register(priv->hw);
++		rc = ieee80211_register_hw(priv->hw);
++		priv->hw->conf.beacon_int = 100;
++		mutex_lock(&priv->mutex);
 +
-+static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info)
-+{
-+	return ((ch_info->phymode == MODE_IEEE80211B) ||
-+		(ch_info->phymode == MODE_IEEE80211G));
-+}
++		if (rc) {
++			IWL_ERROR("Failed to register network "
++				  "device (error %d)\n", rc);
++			return;
++		}
 +
-+static inline int is_channel_passive(const struct iwl_channel_info *ch)
-+{
-+	return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
-+}
++		priv->mac80211_registered = 1;
 +
-+static inline int is_channel_ibss(const struct iwl_channel_info *ch)
-+{
-+	return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
-+}
++		iwl_reset_channel_flag(priv);
++	} else
++		ieee80211_start_queues(priv->hw);
 +
-+extern const struct iwl_channel_info *iwl_get_channel_info(
-+	const struct iwl_priv *priv, int phymode, u16 channel);
++	priv->active_rate = priv->rates_mask;
++	priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
 +
-+#endif
-diff --git a/drivers/net/wireless/iwl-commands.h b/drivers/net/wireless/iwl-commands.h
-new file mode 100644
-index 0000000..7f39b03
---- /dev/null
-+++ b/drivers/net/wireless/iwl-commands.h
-@@ -0,0 +1,1708 @@
-+/******************************************************************************
-+ *
-+ * This file is provided under a dual BSD/GPLv2 license.  When using or
-+ * redistributing this file, you may do so under either license.
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU Geeral Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ * BSD LICENSE
-+ *
-+ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ *  * Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ *  * Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in
-+ *    the documentation and/or other materials provided with the
-+ *    distribution.
-+ *  * Neither the name Intel Corporation nor the names of its
-+ *    contributors may be used to endorse or promote products derived
-+ *    from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ *****************************************************************************/
++	iwl_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode));
++
++	if (iwl_is_associated(priv)) {
++		struct iwl_rxon_cmd *active_rxon =
++				(struct iwl_rxon_cmd *)(&priv->active_rxon);
 +
-+#ifndef __iwl_commands_h__
-+#define __iwl_commands_h__
++		memcpy(&priv->staging_rxon, &priv->active_rxon,
++		       sizeof(priv->staging_rxon));
++		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++	} else {
++		/* Initialize our rx_config data */
++		iwl_connection_init_rx_config(priv);
++		memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
++	}
 +
-+enum {
-+	REPLY_ALIVE = 0x1,
-+	REPLY_ERROR = 0x2,
++	/* Configure BT coexistence */
++	iwl_send_bt_config(priv);
 +
-+	/* RXON and QOS commands */
-+	REPLY_RXON = 0x10,
-+	REPLY_RXON_ASSOC = 0x11,
-+	REPLY_QOS_PARAM = 0x13,
-+	REPLY_RXON_TIMING = 0x14,
++	/* Configure the adapter for unassociated operation */
++	iwl_commit_rxon(priv);
 +
-+	/* Multi-Station support */
-+	REPLY_ADD_STA = 0x18,
-+	REPLY_REMOVE_STA = 0x19,	/* not used */
-+	REPLY_REMOVE_ALL_STA = 0x1a,	/* not used */
++	/* At this point, the NIC is initialized and operational */
++	priv->notif_missed_beacons = 0;
++	set_bit(STATUS_READY, &priv->status);
 +
-+	/* RX, TX, LEDs */
-+#if IWL == 3945
-+	REPLY_3945_RX = 0x1b,		/* 3945 only */
-+#endif
-+	REPLY_TX = 0x1c,
-+	REPLY_RATE_SCALE = 0x47,	/* 3945 only */
-+	REPLY_LEDS_CMD = 0x48,
-+	REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */
++	iwl4965_rf_kill_ct_config(priv);
++	IWL_DEBUG_INFO("ALIVE processing complete.\n");
 +
-+	/* 802.11h related */
-+	RADAR_NOTIFICATION = 0x70,	/* not used */
-+	REPLY_QUIET_CMD = 0x71,		/* not used */
-+	REPLY_CHANNEL_SWITCH = 0x72,
-+	CHANNEL_SWITCH_NOTIFICATION = 0x73,
-+	REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74,
-+	SPECTRUM_MEASURE_NOTIFICATION = 0x75,
++	if (priv->error_recovering)
++		iwl_error_recovery(priv);
 +
-+	/* Power Management */
-+	POWER_TABLE_CMD = 0x77,
-+	PM_SLEEP_NOTIFICATION = 0x7A,
-+	PM_DEBUG_STATISTIC_NOTIFIC = 0x7B,
++	return;
 +
-+	/* Scan commands and notifications */
-+	REPLY_SCAN_CMD = 0x80,
-+	REPLY_SCAN_ABORT_CMD = 0x81,
-+	SCAN_START_NOTIFICATION = 0x82,
-+	SCAN_RESULTS_NOTIFICATION = 0x83,
-+	SCAN_COMPLETE_NOTIFICATION = 0x84,
++ restart:
++	queue_work(priv->workqueue, &priv->restart);
++}
 +
-+	/* IBSS/AP commands */
-+	BEACON_NOTIFICATION = 0x90,
-+	REPLY_TX_BEACON = 0x91,
-+	WHO_IS_AWAKE_NOTIFICATION = 0x94,	/* not used */
++static void iwl_cancel_deferred_work(struct iwl_priv *priv);
 +
-+	/* Miscellaneous commands */
-+	QUIET_NOTIFICATION = 0x96,		/* not used */
-+	REPLY_TX_PWR_TABLE_CMD = 0x97,
-+	MEASURE_ABORT_NOTIFICATION = 0x99,	/* not used */
++static void __iwl_down(struct iwl_priv *priv)
++{
++	unsigned long flags;
++	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
++	struct ieee80211_conf *conf = NULL;
 +
-+	/* BT config command */
-+	REPLY_BT_CONFIG = 0x9b,
++	IWL_DEBUG_INFO(DRV_NAME " is going down\n");
 +
-+	/* 4965 Statistics */
-+	REPLY_STATISTICS_CMD = 0x9c,
-+	STATISTICS_NOTIFICATION = 0x9d,
++	conf = ieee80211_get_hw_conf(priv->hw);
 +
-+	/* RF-KILL commands and notifications */
-+	REPLY_CARD_STATE_CMD = 0xa0,
-+	CARD_STATE_NOTIFICATION = 0xa1,
++	if (!exit_pending)
++		set_bit(STATUS_EXIT_PENDING, &priv->status);
 +
-+	/* Missed beacons notification */
-+	MISSED_BEACONS_NOTIFICATION = 0xa2,
++	iwl_clear_stations_table(priv);
 +
-+#if IWL == 4965
-+	REPLY_CT_KILL_CONFIG_CMD = 0xa4,
-+	SENSITIVITY_CMD = 0xa8,
-+	REPLY_PHY_CALIBRATION_CMD = 0xb0,
-+	REPLY_RX_PHY_CMD = 0xc0,
-+	REPLY_RX_MPDU_CMD = 0xc1,
-+	REPLY_4965_RX = 0xc3,
-+	REPLY_COMPRESSED_BA = 0xc5,
-+#endif
-+	REPLY_MAX = 0xff
-+};
++	/* Unblock any waiting calls */
++	wake_up_interruptible_all(&priv->wait_command_queue);
 +
-+/******************************************************************************
-+ * (0)
-+ * Header
-+ *
-+ *****************************************************************************/
++	iwl_cancel_deferred_work(priv);
 +
-+#define IWL_CMD_FAILED_MSK 0x40
++	/* Wipe out the EXIT_PENDING status bit if we are not actually
++	 * exiting the module */
++	if (!exit_pending)
++		clear_bit(STATUS_EXIT_PENDING, &priv->status);
 +
-+struct iwl_cmd_header {
-+	u8 cmd;
-+	u8 flags;
-+	/* We have 15 LSB to use as we please (MSB indicates
-+	 * a frame Rx'd from the HW).  We encode the following
-+	 * information into the sequence field:
-+	 *
-+	 *  0:7    index in fifo
-+	 *  8:13   fifo selection
-+	 * 14:14   bit indicating if this packet references the 'extra'
-+	 *         storage at the end of the memory queue
-+	 * 15:15   (Rx indication)
-+	 *
-+	 */
-+	__le16 sequence;
++	/* stop and reset the on-board processor */
++	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 +
-+	/* command data follows immediately */
-+	u8 data[0];
-+} __attribute__ ((packed));
++	/* tell the device to stop sending interrupts */
++	iwl_disable_interrupts(priv);
 +
-+/******************************************************************************
-+ * (0a)
-+ * Alive and Error Commands & Responses:
-+ *
-+ *****************************************************************************/
++	if (priv->mac80211_registered)
++		ieee80211_stop_queues(priv->hw);
 +
-+#define UCODE_VALID_OK	__constant_cpu_to_le32(0x1)
-+#define INITIALIZE_SUBTYPE    (9)
++	/* If we have not previously called iwl_init() then
++	 * clear all bits but the RF Kill and SUSPEND bits and return */
++	if (!iwl_is_init(priv)) {
++		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
++					STATUS_RF_KILL_HW |
++			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
++					STATUS_RF_KILL_SW |
++			       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
++					STATUS_IN_SUSPEND;
++		goto exit;
++	}
 +
-+/*
-+ * REPLY_ALIVE = 0x1 (response only, not a command)
-+ */
-+struct iwl_alive_resp {
-+	u8 ucode_minor;
-+	u8 ucode_major;
-+	__le16 reserved1;
-+	u8 sw_rev[8];
-+	u8 ver_type;
-+	u8 ver_subtype;
-+	__le16 reserved2;
-+	__le32 log_event_table_ptr;
-+	__le32 error_event_table_ptr;
-+	__le32 timestamp;
-+	__le32 is_valid;
-+} __attribute__ ((packed));
++	/* ...otherwise clear out all the status bits but the RF Kill and
++	 * SUSPEND bits and continue taking the NIC down. */
++	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
++				STATUS_RF_KILL_HW |
++			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
++				STATUS_RF_KILL_SW |
++			test_bit(STATUS_IN_SUSPEND, &priv->status) <<
++				STATUS_IN_SUSPEND |
++			test_bit(STATUS_FW_ERROR, &priv->status) <<
++				STATUS_FW_ERROR;
 +
-+struct iwl_init_alive_resp {
-+	u8 ucode_minor;
-+	u8 ucode_major;
-+	__le16 reserved1;
-+	u8 sw_rev[8];
-+	u8 ver_type;
-+	u8 ver_subtype;
-+	__le16 reserved2;
-+	__le32 log_event_table_ptr;
-+	__le32 error_event_table_ptr;
-+	__le32 timestamp;
-+	__le32 is_valid;
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+#if IWL == 4965
-+	/* calibration values from "initialize" uCode */
-+	__le32 voltage;		/* signed */
-+	__le32 therm_r1[2];	/* signed 1st for normal, 2nd for FAT channel */
-+	__le32 therm_r2[2];	/* signed */
-+	__le32 therm_r3[2];	/* signed */
-+	__le32 therm_r4[2];	/* signed */
-+	__le32 tx_atten[5][2];	/* signed MIMO gain comp, 5 freq groups,
-+				 * 2 Tx chains */
-+#endif
-+} __attribute__ ((packed));
++	iwl_hw_txq_ctx_stop(priv);
++	iwl_hw_rxq_stop(priv);
++
++	spin_lock_irqsave(&priv->lock, flags);
++	if (!iwl_grab_restricted_access(priv)) {
++		iwl_write_restricted_reg(priv, APMG_CLK_DIS_REG,
++					 APMG_CLK_VAL_DMA_CLK_RQT);
++		iwl_release_restricted_access(priv);
++	}
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	udelay(5);
++
++	iwl_hw_nic_stop_master(priv);
++	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
++	iwl_hw_nic_reset(priv);
++
++ exit:
++	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
++
++	if (priv->ibss_beacon)
++		dev_kfree_skb(priv->ibss_beacon);
++	priv->ibss_beacon = NULL;
++
++	/* clear out any free frames */
++	iwl_clear_free_frames(priv);
++}
++
++static void iwl_down(struct iwl_priv *priv)
++{
++	mutex_lock(&priv->mutex);
++	__iwl_down(priv);
++	mutex_unlock(&priv->mutex);
++}
++
++#define MAX_HW_RESTARTS 5
++
++static int __iwl_up(struct iwl_priv *priv)
++{
++	int rc, i;
++	u32 hw_rf_kill = 0;
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
++		IWL_WARNING("Exit pending; will not bring the NIC up\n");
++		return -EIO;
++	}
++
++	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
++		IWL_WARNING("Radio disabled by SW RF kill (module "
++			    "parameter)\n");
++		return 0;
++	}
 +
-+union tsf {
-+	u8 byte[8];
-+	__le16 word[4];
-+	__le32 dw[2];
-+};
++	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
 +
-+/*
-+ * REPLY_ERROR = 0x2 (response only, not a command)
-+ */
-+struct iwl_error_resp {
-+	__le32 error_type;
-+	u8 cmd_id;
-+	u8 reserved1;
-+	__le16 bad_cmd_seq_num;
-+#if IWL == 3945
-+	__le16 reserved2;
-+#endif
-+	__le32 error_info;
-+	union tsf timestamp;
-+} __attribute__ ((packed));
++	rc = iwl_hw_nic_init(priv);
++	if (rc) {
++		IWL_ERROR("Unable to int nic\n");
++		return rc;
++	}
 +
-+/******************************************************************************
-+ * (1)
-+ * RXON Commands & Responses:
-+ *
-+ *****************************************************************************/
++	/* make sure rfkill handshake bits are cleared */
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
 +
-+/*
-+ * Rx config defines & structure
-+ */
-+/* rx_config device types  */
-+enum {
-+	RXON_DEV_TYPE_AP = 1,
-+	RXON_DEV_TYPE_ESS = 3,
-+	RXON_DEV_TYPE_IBSS = 4,
-+	RXON_DEV_TYPE_SNIFFER = 6,
-+};
++	/* clear (again), then enable host interrupts */
++	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
++	iwl_enable_interrupts(priv);
 +
-+/* rx_config flags */
-+/* band & modulation selection */
-+#define RXON_FLG_BAND_24G_MSK           __constant_cpu_to_le32(1 << 0)
-+#define RXON_FLG_CCK_MSK                __constant_cpu_to_le32(1 << 1)
-+/* auto detection enable */
-+#define RXON_FLG_AUTO_DETECT_MSK        __constant_cpu_to_le32(1 << 2)
-+/* TGg protection when tx */
-+#define RXON_FLG_TGG_PROTECT_MSK        __constant_cpu_to_le32(1 << 3)
-+/* cck short slot & preamble */
-+#define RXON_FLG_SHORT_SLOT_MSK          __constant_cpu_to_le32(1 << 4)
-+#define RXON_FLG_SHORT_PREAMBLE_MSK     __constant_cpu_to_le32(1 << 5)
-+/* antenna selection */
-+#define RXON_FLG_DIS_DIV_MSK            __constant_cpu_to_le32(1 << 7)
-+#define RXON_FLG_ANT_SEL_MSK            __constant_cpu_to_le32(0x0f00)
-+#define RXON_FLG_ANT_A_MSK              __constant_cpu_to_le32(1 << 8)
-+#define RXON_FLG_ANT_B_MSK              __constant_cpu_to_le32(1 << 9)
-+/* radar detection enable */
-+#define RXON_FLG_RADAR_DETECT_MSK       __constant_cpu_to_le32(1 << 12)
-+#define RXON_FLG_TGJ_NARROW_BAND_MSK    __constant_cpu_to_le32(1 << 13)
-+/* rx response to host with 8-byte TSF
-+* (according to ON_AIR deassertion) */
-+#define RXON_FLG_TSF2HOST_MSK           __constant_cpu_to_le32(1 << 15)
++	/* really make sure rfkill handshake bits are cleared */
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
 +
-+/* rx_config filter flags */
-+/* accept all data frames */
-+#define RXON_FILTER_PROMISC_MSK         __constant_cpu_to_le32(1 << 0)
-+/* pass control & management to host */
-+#define RXON_FILTER_CTL2HOST_MSK        __constant_cpu_to_le32(1 << 1)
-+/* accept multi-cast */
-+#define RXON_FILTER_ACCEPT_GRP_MSK      __constant_cpu_to_le32(1 << 2)
-+/* don't decrypt uni-cast frames */
-+#define RXON_FILTER_DIS_DECRYPT_MSK     __constant_cpu_to_le32(1 << 3)
-+/* don't decrypt multi-cast frames */
-+#define RXON_FILTER_DIS_GRP_DECRYPT_MSK __constant_cpu_to_le32(1 << 4)
-+/* STA is associated */
-+#define RXON_FILTER_ASSOC_MSK           __constant_cpu_to_le32(1 << 5)
-+/* transfer to host non bssid beacons in associated state */
-+#define RXON_FILTER_BCON_AWARE_MSK      __constant_cpu_to_le32(1 << 6)
++	/* Copy original ucode data image from disk into backup cache.
++	 * This will be used to initialize the on-board processor's
++	 * data SRAM for a clean start when the runtime program first loads. */
++	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
++			priv->ucode_data.len);
 +
-+/*
-+ * REPLY_RXON = 0x10 (command, has simple generic response)
-+ */
-+struct iwl_rxon_cmd {
-+	u8 node_addr[6];
-+	__le16 reserved1;
-+	u8 bssid_addr[6];
-+	__le16 reserved2;
-+	u8 wlap_bssid_addr[6];
-+	__le16 reserved3;
-+	u8 dev_type;
-+	u8 air_propagation;
-+#if IWL == 3945
-+	__le16 reserved4;
-+#elif IWL == 4965
-+	__le16 rx_chain;
-+#endif
-+	u8 ofdm_basic_rates;
-+	u8 cck_basic_rates;
-+	__le16 assoc_id;
-+	__le32 flags;
-+	__le32 filter_flags;
-+	__le16 channel;
-+#if IWL == 3945
-+	__le16 reserved5;
-+#elif IWL == 4965
-+	u8 ofdm_ht_single_stream_basic_rates;
-+	u8 ofdm_ht_dual_stream_basic_rates;
-+#endif
-+} __attribute__ ((packed));
++	/* If platform's RF_KILL switch is set to KILL,
++	 * wait for BIT_INT_RF_KILL interrupt before loading uCode
++	 * and getting things started */
++	if (!(iwl_read32(priv, CSR_GP_CNTRL) &
++				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
++		hw_rf_kill = 1;
 +
-+/*
-+ * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
-+ */
-+struct iwl_rxon_assoc_cmd {
-+	__le32 flags;
-+	__le32 filter_flags;
-+	u8 ofdm_basic_rates;
-+	u8 cck_basic_rates;
-+#if IWL == 4965
-+	u8 ofdm_ht_single_stream_basic_rates;
-+	u8 ofdm_ht_dual_stream_basic_rates;
-+	__le16 rx_chain_select_flags;
-+#endif
-+	__le16 reserved;
-+} __attribute__ ((packed));
++	if (test_bit(STATUS_RF_KILL_HW, &priv->status) || hw_rf_kill) {
++		IWL_WARNING("Radio disabled by HW RF Kill switch\n");
++		return 0;
++	}
 +
-+/*
-+ * REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
-+ */
-+struct iwl_rxon_time_cmd {
-+	union tsf timestamp;
-+	__le16 beacon_interval;
-+	__le16 atim_window;
-+	__le32 beacon_init_val;
-+	__le16 listen_interval;
-+	__le16 reserved;
-+} __attribute__ ((packed));
++	for (i = 0; i < MAX_HW_RESTARTS; i++) {
 +
-+struct iwl_tx_power {
-+	u8 tx_gain;		/* gain for analog radio */
-+	u8 dsp_atten;		/* gain for DSP */
-+} __attribute__ ((packed));
++		iwl_clear_stations_table(priv);
 +
-+#if IWL == 3945
-+struct iwl_power_per_rate {
-+	u8 rate;		/* plcp */
-+	struct iwl_tx_power tpc;
-+	u8 reserved;
-+} __attribute__ ((packed));
++		/* load bootstrap state machine,
++		 * load bootstrap program into processor's memory,
++		 * prepare to load the "initialize" uCode */
++		rc = iwl_load_bsm(priv);
 +
-+#elif IWL == 4965
-+#define POWER_TABLE_NUM_ENTRIES			33
-+#define POWER_TABLE_NUM_HT_OFDM_ENTRIES		32
-+#define POWER_TABLE_CCK_ENTRY			32
-+struct tx_power_dual_stream {
-+	__le32 dw;
-+} __attribute__ ((packed));
++		if (rc) {
++			IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc);
++			continue;
++		}
 +
-+struct iwl_tx_power_db {
-+	struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES];
-+} __attribute__ ((packed));
-+#endif
++		/* start card; "initialize" will load runtime ucode */
++		iwl_nic_start(priv);
 +
-+/*
-+ * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
-+ */
-+struct iwl_channel_switch_cmd {
-+	u8 band;
-+	u8 expect_beacon;
-+	__le16 channel;
-+	__le32 rxon_flags;
-+	__le32 rxon_filter_flags;
-+	__le32 switch_time;
-+#if IWL == 3945
-+	struct iwl_power_per_rate power[IWL_MAX_RATES];
-+#elif IWL == 4965
-+	struct iwl_tx_power_db tx_power;
-+#endif
-+} __attribute__ ((packed));
++		/* MAC Address location in EEPROM same for 3945/4965 */
++		get_eeprom_mac(priv, priv->mac_addr);
++		IWL_DEBUG_INFO("MAC address: " MAC_FMT "\n",
++			       MAC_ARG(priv->mac_addr));
 +
-+/*
-+ * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
-+ */
-+struct iwl_csa_notification {
-+	__le16 band;
-+	__le16 channel;
-+	__le32 status;		/* 0 - OK, 1 - fail */
-+} __attribute__ ((packed));
++		SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
 +
-+/******************************************************************************
-+ * (2)
-+ * Quality-of-Service (QOS) Commands & Responses:
-+ *
-+ *****************************************************************************/
-+struct iwl_ac_qos {
-+	__le16 cw_min;
-+	__le16 cw_max;
-+	u8 aifsn;
-+	u8 reserved1;
-+	__le16 edca_txop;
-+} __attribute__ ((packed));
++		IWL_DEBUG_INFO(DRV_NAME " is coming up\n");
 +
-+/* QoS flags defines */
-+#define QOS_PARAM_FLG_UPDATE_EDCA_MSK	__constant_cpu_to_le32(0x01)
-+#define QOS_PARAM_FLG_TGN_MSK		__constant_cpu_to_le32(0x02)
-+#define QOS_PARAM_FLG_TXOP_TYPE_MSK	__constant_cpu_to_le32(0x10)
++		return 0;
++	}
 +
-+/*
-+ *  TXFIFO Queue number defines
-+ */
-+/* number of Access categories (AC) (EDCA), queues 0..3 */
-+#define AC_NUM                4
++	set_bit(STATUS_EXIT_PENDING, &priv->status);
++	__iwl_down(priv);
 +
-+/*
-+ * REPLY_QOS_PARAM = 0x13 (command, has simple generic response)
-+ */
-+struct iwl_qosparam_cmd {
-+	__le32 qos_flags;
-+	struct iwl_ac_qos ac[AC_NUM];
-+} __attribute__ ((packed));
++	/* tried to restart and config the device for as long as our
++	 * patience could withstand */
++	IWL_ERROR("Unable to initialize device after %d attempts.\n", i);
++	return -EIO;
++}
 +
-+/******************************************************************************
-+ * (3)
-+ * Add/Modify Stations Commands & Responses:
++
++/*****************************************************************************
++ *
++ * Workqueue callbacks
 + *
 + *****************************************************************************/
-+/*
-+ * Multi station support
-+ */
-+#if IWL == 3945
-+enum {
-+	IWL_AP_ID = 0,
-+	IWL_MULTICAST_ID,
-+	IWL_STA_ID,
-+	IWL_BROADCAST_ID = 24,
-+	IWL_STATION_COUNT = 25,
-+	IWL_INVALID_STATION
-+};
-+#elif IWL == 4965
-+enum {
-+	IWL_AP_ID = 0,
-+	IWL_MULTICAST_ID,
-+	IWL_STA_ID,
-+	IWL_BROADCAST_ID = 31,
-+	IWL_STATION_COUNT = 32,
-+	IWL_INVALID_STATION
-+};
-+#endif
 +
-+#if IWL == 3945
-+#define STA_FLG_TX_RATE_MSK		__constant_cpu_to_le32(1<<2);
-+#endif
-+#define STA_FLG_PWR_SAVE_MSK		__constant_cpu_to_le32(1<<8);
++static void iwl_bg_init_alive_start(struct work_struct *data)
++{
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, init_alive_start.work);
 +
-+#define STA_CONTROL_MODIFY_MSK		0x01
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
 +
-+/* key flags __le16*/
-+#define STA_KEY_FLG_ENCRYPT_MSK	__constant_cpu_to_le16(0x7)
-+#define STA_KEY_FLG_NO_ENC	__constant_cpu_to_le16(0x0)
-+#define STA_KEY_FLG_WEP		__constant_cpu_to_le16(0x1)
-+#define STA_KEY_FLG_CCMP	__constant_cpu_to_le16(0x2)
-+#define STA_KEY_FLG_TKIP	__constant_cpu_to_le16(0x3)
++	mutex_lock(&priv->mutex);
++	iwl_init_alive_start(priv);
++	mutex_unlock(&priv->mutex);
++}
 +
-+#define STA_KEY_FLG_KEYID_POS	8
-+#define STA_KEY_FLG_INVALID 	__constant_cpu_to_le16(0x0800)
++static void iwl_bg_alive_start(struct work_struct *data)
++{
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, alive_start.work);
 +
-+/* modify flags  */
-+enum {
-+	STA_MODIFY_KEY_MASK = 0x01,
-+	STA_MODIFY_TID_DISABLE_TX = 0x02,
-+	STA_MODIFY_TX_RATE_MSK = 0x04
-+};
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
 +
-+/*
-+ * Antenna masks:
-+ * bit14:15 01 B inactive, A active
-+ *          10 B active, A inactive
-+ *          11 Both active
-+ */
-+#define RATE_MCS_ANT_A_POS	14
-+#define RATE_MCS_ANT_B_POS	15
-+#define RATE_MCS_ANT_A_MSK	0x4000
-+#define RATE_MCS_ANT_B_MSK	0x8000
-+#define RATE_MCS_ANT_AB_MSK	0xc000
++	mutex_lock(&priv->mutex);
++	iwl_alive_start(priv);
++	mutex_unlock(&priv->mutex);
++}
 +
-+struct iwl_keyinfo {
-+	__le16 key_flags;
-+	u8 tkip_rx_tsc_byte2;	/* TSC[2] for key mix ph1 detection */
-+	u8 reserved1;
-+	__le16 tkip_rx_ttak[5];	/* 10-byte unicast TKIP TTAK */
-+	__le16 reserved2;
-+	u8 key[16];		/* 16-byte unicast decryption key */
-+} __attribute__ ((packed));
++static void iwl_bg_rf_kill(struct work_struct *work)
++{
++	struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
 +
-+struct sta_id_modify {
-+	u8 addr[ETH_ALEN];
-+	__le16 reserved1;
-+	u8 sta_id;
-+	u8 modify_mask;
-+	__le16 reserved2;
-+} __attribute__ ((packed));
++	wake_up_interruptible(&priv->wait_command_queue);
 +
-+/*
-+ * REPLY_ADD_STA = 0x18 (command)
-+ */
-+struct iwl_addsta_cmd {
-+	u8 mode;
-+	u8 reserved[3];
-+	struct sta_id_modify sta;
-+	struct iwl_keyinfo key;
-+	__le32 station_flags;
-+	__le32 station_flags_msk;
-+	__le16 tid_disable_tx;
-+#if IWL == 3945
-+	__le16 rate_n_flags;
-+#else
-+	__le16	reserved1;
-+#endif
-+	u8 add_immediate_ba_tid;
-+	u8 remove_immediate_ba_tid;
-+	__le16 add_immediate_ba_ssn;
-+#if IWL == 4965
-+	__le32 reserved2;
-+#endif
-+} __attribute__ ((packed));
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
 +
-+/*
-+ * REPLY_ADD_STA = 0x18 (response)
-+ */
-+struct iwl_add_sta_resp {
-+	u8 status;
-+} __attribute__ ((packed));
++	mutex_lock(&priv->mutex);
 +
-+#define ADD_STA_SUCCESS_MSK              0x1
++	if (!iwl_is_rfkill(priv)) {
++		IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
++			  "HW and/or SW RF Kill no longer active, restarting "
++			  "device\n");
++		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
++			queue_work(priv->workqueue, &priv->restart);
++	} else {
 +
-+/******************************************************************************
-+ * (4)
-+ * Rx Responses:
-+ *
-+ *****************************************************************************/
++		if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
++			IWL_DEBUG_RF_KILL("Can not turn radio back on - "
++					  "disabled by SW switch\n");
++		else
++			IWL_WARNING("Radio Frequency Kill Switch is On:\n"
++				    "Kill switch must be turned off for "
++				    "wireless networking to work.\n");
++	}
++	mutex_unlock(&priv->mutex);
++}
 +
-+struct iwl_rx_frame_stats {
-+	u8 phy_count;
-+	u8 id;
-+	u8 rssi;
-+	u8 agc;
-+	__le16 sig_avg;
-+	__le16 noise_diff;
-+	u8 payload[0];
-+} __attribute__ ((packed));
++#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
 +
-+struct iwl_rx_frame_hdr {
-+	__le16 channel;
-+	__le16 phy_flags;
-+	u8 reserved1;
-+	u8 rate;
-+	__le16 len;
-+	u8 payload[0];
-+} __attribute__ ((packed));
++static void iwl_bg_scan_check(struct work_struct *data)
++{
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, scan_check.work);
 +
-+#define	RX_RES_STATUS_NO_CRC32_ERROR	__constant_cpu_to_le32(1 << 0)
-+#define	RX_RES_STATUS_NO_RXE_OVERFLOW	__constant_cpu_to_le32(1 << 1)
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
 +
-+#define	RX_RES_PHY_FLAGS_BAND_24_MSK	__constant_cpu_to_le16(1 << 0)
-+#define	RX_RES_PHY_FLAGS_MOD_CCK_MSK		__constant_cpu_to_le16(1 << 1)
-+#define	RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK	__constant_cpu_to_le16(1 << 2)
-+#define	RX_RES_PHY_FLAGS_NARROW_BAND_MSK	__constant_cpu_to_le16(1 << 3)
-+#define	RX_RES_PHY_FLAGS_ANTENNA_MSK		__constant_cpu_to_le16(0xf0)
++	mutex_lock(&priv->mutex);
++	if (test_bit(STATUS_SCANNING, &priv->status) ||
++	    test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++		IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN,
++			  "Scan completion watchdog resetting adapter (%dms)\n",
++			  jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
++		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
++			queue_work(priv->workqueue, &priv->restart);
++	}
++	mutex_unlock(&priv->mutex);
++}
 +
-+#define	RX_RES_STATUS_SEC_TYPE_MSK	(0x7 << 8)
-+#define	RX_RES_STATUS_SEC_TYPE_NONE	(0x0 << 8)
-+#define	RX_RES_STATUS_SEC_TYPE_WEP	(0x1 << 8)
-+#define	RX_RES_STATUS_SEC_TYPE_CCMP	(0x2 << 8)
-+#define	RX_RES_STATUS_SEC_TYPE_TKIP	(0x3 << 8)
++static void iwl_bg_request_scan(struct work_struct *data)
++{
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, request_scan);
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_SCAN_CMD,
++		.len = sizeof(struct iwl_scan_cmd),
++		.meta.flags = CMD_SIZE_HUGE,
++	};
++	int rc = 0;
++	struct iwl_scan_cmd *scan;
++	struct ieee80211_conf *conf = NULL;
++	u8 direct_mask;
++	int phymode;
 +
-+#define	RX_RES_STATUS_DECRYPT_TYPE_MSK	(0x3 << 11)
-+#define	RX_RES_STATUS_NOT_DECRYPT	(0x0 << 11)
-+#define	RX_RES_STATUS_DECRYPT_OK	(0x3 << 11)
-+#define	RX_RES_STATUS_BAD_ICV_MIC	(0x1 << 11)
-+#define	RX_RES_STATUS_BAD_KEY_TTAK	(0x2 << 11)
++	conf = ieee80211_get_hw_conf(priv->hw);
 +
-+struct iwl_rx_frame_end {
-+	__le32 status;
-+	__le64 timestamp;
-+	__le32 beacon_timestamp;
-+} __attribute__ ((packed));
++	mutex_lock(&priv->mutex);
 +
-+/*
-+ * REPLY_3945_RX = 0x1b (response only, not a command)
-+ *
-+ * NOTE:  DO NOT dereference from casts to this structure
-+ * It is provided only for calculating minimum data set size.
-+ * The actual offsets of the hdr and end are dynamic based on
-+ * stats.phy_count
-+ */
-+struct iwl_rx_frame {
-+	struct iwl_rx_frame_stats stats;
-+	struct iwl_rx_frame_hdr hdr;
-+	struct iwl_rx_frame_end end;
-+} __attribute__ ((packed));
++	if (!iwl_is_ready(priv)) {
++		IWL_WARNING("request scan called when driver not ready.\n");
++		goto done;
++	}
++
++	/* Make sure the scan wasn't cancelled before this queued work
++	 * was given the chance to run... */
++	if (!test_bit(STATUS_SCANNING, &priv->status))
++		goto done;
++
++	/* This should never be called or scheduled if there is currently
++	 * a scan active in the hardware. */
++	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
++		IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. "
++			       "Ignoring second request.\n");
++		rc = -EIO;
++		goto done;
++	}
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
++		IWL_DEBUG_SCAN("Aborting scan due to device shutdown\n");
++		goto done;
++	}
++
++	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
++		IWL_DEBUG_HC("Scan request while abort pending.  Queuing.\n");
++		goto done;
++	}
 +
-+/*
-+ * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
-+ */
-+struct iwl_compressed_ba_resp {
-+	__le32 sta_addr_lo32;
-+	__le16 sta_addr_hi16;
-+	__le16 reserved;
-+	u8 sta_id;
-+	u8 tid;
-+	__le16 ba_seq_ctl;
-+	__le32 ba_bitmap0;
-+	__le32 ba_bitmap1;
-+	__le16 scd_flow;
-+	__le16 scd_ssn;
-+} __attribute__ ((packed));
++	if (iwl_is_rfkill(priv)) {
++		IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
++		goto done;
++	}
 +
-+/******************************************************************************
-+ * (5)
-+ * Tx Commands & Responses:
-+ *
-+ *****************************************************************************/
++	if (!test_bit(STATUS_READY, &priv->status)) {
++		IWL_DEBUG_HC("Scan request while uninitialized.  Queuing.\n");
++		goto done;
++	}
 +
-+/* Tx flags */
-+#define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1)
-+#define TX_CMD_FLG_CTS_MSK __constant_cpu_to_le32(1 << 2)
-+#define TX_CMD_FLG_ACK_MSK __constant_cpu_to_le32(1 << 3)
-+#define TX_CMD_FLG_STA_RATE_MSK __constant_cpu_to_le32(1 << 4)
-+#define TX_CMD_FLG_IMM_BA_RSP_MASK  __constant_cpu_to_le32(1 << 6)
-+#define TX_CMD_FLG_FULL_TXOP_PROT_MSK __constant_cpu_to_le32(1 << 7)
-+#define TX_CMD_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0xf00)
-+#define TX_CMD_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8)
-+#define TX_CMD_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9)
++	if (!priv->scan_bands) {
++		IWL_DEBUG_HC("Aborting scan due to no requested bands\n");
++		goto done;
++	}
 +
-+/* ucode ignores BT priority for this frame */
-+#define TX_CMD_FLG_BT_DIS_MSK __constant_cpu_to_le32(1 << 12)
++	if (!priv->scan) {
++		priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
++				     IWL_MAX_SCAN_SIZE, GFP_KERNEL);
++		if (!priv->scan) {
++			rc = -ENOMEM;
++			goto done;
++		}
++	}
++	scan = priv->scan;
++	memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
 +
-+/* ucode overrides sequence control */
-+#define TX_CMD_FLG_SEQ_CTL_MSK __constant_cpu_to_le32(1 << 13)
++	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
++	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
 +
-+/* signal that this frame is non-last MPDU */
-+#define TX_CMD_FLG_MORE_FRAG_MSK __constant_cpu_to_le32(1 << 14)
++	if (iwl_is_associated(priv)) {
++		u16 interval = 0;
++		u32 extra;
++		u32 suspend_time = 100;
++		u32 scan_suspend_time = 100;
++		unsigned long flags;
 +
-+/* calculate TSF in outgoing frame */
-+#define TX_CMD_FLG_TSF_MSK __constant_cpu_to_le32(1 << 16)
++		IWL_DEBUG_INFO("Scanning while associated...\n");
 +
-+/* activate TX calibration. */
-+#define TX_CMD_FLG_CALIB_MSK __constant_cpu_to_le32(1 << 17)
++		spin_lock_irqsave(&priv->lock, flags);
++		interval = priv->beacon_int;
++		spin_unlock_irqrestore(&priv->lock, flags);
 +
-+/* signals that 2 bytes pad was inserted
-+   after the MAC header */
-+#define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20)
++		scan->suspend_time = 0;
++		scan->max_out_time = cpu_to_le32(600 * 1024);
++		if (!interval)
++			interval = suspend_time;
 +
-+/* HCCA-AP - disable duration overwriting. */
-+#define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25)
++		extra = (suspend_time / interval) << 22;
++		scan_suspend_time = (extra |
++		    ((suspend_time % interval) * 1024));
++		scan->suspend_time = cpu_to_le32(scan_suspend_time);
++		IWL_DEBUG_SCAN("suspend_time 0x%X beacon interval %d\n",
++			       scan_suspend_time, interval);
++	}
 +
-+/*
-+ * TX command security control
-+ */
-+#define TX_CMD_SEC_CCM  	0x2
-+#define TX_CMD_SEC_TKIP		0x3
++	/* We should add the ability for user to lock to PASSIVE ONLY */
++	if (priv->one_direct_scan) {
++		IWL_DEBUG_SCAN
++		    ("Kicking off one direct scan for '%s'\n",
++		     iwl_escape_essid(priv->direct_ssid,
++				      priv->direct_ssid_len));
++		scan->direct_scan[0].id = WLAN_EID_SSID;
++		scan->direct_scan[0].len = priv->direct_ssid_len;
++		memcpy(scan->direct_scan[0].ssid,
++		       priv->direct_ssid, priv->direct_ssid_len);
++		direct_mask = 1;
++	} else if (!iwl_is_associated(priv)) {
++		scan->direct_scan[0].id = WLAN_EID_SSID;
++		scan->direct_scan[0].len = priv->essid_len;
++		memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
++		direct_mask = 1;
++	} else
++		direct_mask = 0;
 +
-+/*
-+ * TX command Frame life time
-+ */
++	/* We don't build a direct scan probe request; the uCode will do
++	 * that based on the direct_mask added to each channel entry */
++	scan->tx_cmd.len = cpu_to_le16(
++		iwl_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
++			IWL_MAX_SCAN_SIZE - sizeof(scan), 0));
++	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
++	scan->tx_cmd.sta_id = IWL_BROADCAST_ID;
++	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
 +
-+struct iwl_dram_scratch {
-+	u8 try_cnt;
-+	u8 bt_kill_cnt;
-+	__le16 reserved;
-+} __attribute__ ((packed));
++	/* flags + rate selection */
 +
-+/*
-+ * REPLY_TX = 0x1c (command)
-+ */
-+struct iwl_tx_cmd {
-+	__le16 len;
-+	__le16 next_frame_len;
-+	__le32 tx_flags;
-+#if IWL == 3945
-+	u8 rate;
-+	u8 sta_id;
-+	u8 tid_tspec;
-+#elif IWL == 4965
-+	struct iwl_dram_scratch scratch;
-+	__le32 rate_n_flags;
-+	u8 sta_id;
-+#endif
-+	u8 sec_ctl;
-+#if IWL == 4965
-+	u8 initial_rate_index;
-+	u8 reserved;
-+#endif
-+	u8 key[16];
-+#if IWL == 3945
-+	union {
-+		u8 byte[8];
-+		__le16 word[4];
-+		__le32 dw[2];
-+	} tkip_mic;
-+	__le32 next_frame_info;
-+#elif IWL == 4965
-+	__le16 next_frame_flags;
-+	__le16 reserved2;
-+#endif
-+	union {
-+		__le32 life_time;
-+		__le32 attempt;
-+	} stop_time;
-+#if IWL == 3945
-+	u8 supp_rates[2];
-+#elif IWL == 4965
-+	__le32 dram_lsb_ptr;
-+	u8 dram_msb_ptr;
-+#endif
-+	u8 rts_retry_limit;	/*byte 50 */
-+	u8 data_retry_limit;	/*byte 51 */
-+#if IWL == 4965
-+	u8 tid_tspec;
-+#endif
-+	union {
-+		__le16 pm_frame_timeout;
-+		__le16 attempt_duration;
-+	} timeout;
-+	__le16 driver_txop;
-+	u8 payload[0];
-+	struct ieee80211_hdr hdr[0];
-+} __attribute__ ((packed));
++	scan->tx_cmd.tx_flags |= cpu_to_le32(0x200);
 +
-+/* TX command response is sent after *all* transmission attempts.
-+ *
-+ * NOTES:
-+ *
-+ * TX_STATUS_FAIL_NEXT_FRAG
-+ *
-+ * If the fragment flag in the MAC header for the frame being transmitted
-+ * is set and there is insufficient time to transmit the next frame, the
-+ * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'.
-+ *
-+ * TX_STATUS_FIFO_UNDERRUN
-+ *
-+ * Indicates the host did not provide bytes to the FIFO fast enough while
-+ * a TX was in progress.
-+ *
-+ * TX_STATUS_FAIL_MGMNT_ABORT
-+ *
-+ * This status is only possible if the ABORT ON MGMT RX parameter was
-+ * set to true with the TX command.
-+ *
-+ * If the MSB of the status parameter is set then an abort sequence is
-+ * required.  This sequence consists of the host activating the TX Abort
-+ * control line, and then waiting for the TX Abort command response.  This
-+ * indicates that a the device is no longer in a transmit state, and that the
-+ * command FIFO has been cleared.  The host must then deactivate the TX Abort
-+ * control line.  Receiving is still allowed in this case.
-+ */
-+enum {
-+	TX_STATUS_SUCCESS = 0x01,
-+	TX_STATUS_DIRECT_DONE = 0x02,
-+	TX_STATUS_FAIL_SHORT_LIMIT = 0x82,
-+	TX_STATUS_FAIL_LONG_LIMIT = 0x83,
-+	TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84,
-+	TX_STATUS_FAIL_MGMNT_ABORT = 0x85,
-+	TX_STATUS_FAIL_NEXT_FRAG = 0x86,
-+	TX_STATUS_FAIL_LIFE_EXPIRE = 0x87,
-+	TX_STATUS_FAIL_DEST_PS = 0x88,
-+	TX_STATUS_FAIL_ABORTED = 0x89,
-+	TX_STATUS_FAIL_BT_RETRY = 0x8a,
-+	TX_STATUS_FAIL_STA_INVALID = 0x8b,
-+	TX_STATUS_FAIL_FRAG_DROPPED = 0x8c,
-+	TX_STATUS_FAIL_TID_DISABLE = 0x8d,
-+	TX_STATUS_FAIL_FRAME_FLUSHED = 0x8e,
-+	TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f,
-+	TX_STATUS_FAIL_TX_LOCKED = 0x90,
-+	TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91,
-+};
++	switch (priv->scan_bands) {
++	case 2:
++		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
++		scan->tx_cmd.rate_n_flags =
++				iwl_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
++				RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);
++
++		scan->good_CRC_th = 0;
++		phymode = MODE_IEEE80211G;
++		break;
++
++	case 1:
++		scan->tx_cmd.rate_n_flags =
++				iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
++				RATE_MCS_ANT_B_MSK);
++		scan->good_CRC_th = IWL_GOOD_CRC_TH;
++		phymode = MODE_IEEE80211A;
++		break;
 +
-+#define	TX_PACKET_MODE_REGULAR		0x0000
-+#define	TX_PACKET_MODE_BURST_SEQ	0x0100
-+#define	TX_PACKET_MODE_BURST_FIRST	0x0200
++	default:
++		IWL_WARNING("Invalid scan band count\n");
++		goto done;
++	}
 +
-+enum {
-+	TX_POWER_PA_NOT_ACTIVE = 0x0,
-+};
++	/* select Rx chains */
 +
-+enum {
-+	TX_STATUS_MSK = 0x000000ff,	/* bits 0:7 */
-+	TX_STATUS_DELAY_MSK = 0x00000040,
-+	TX_STATUS_ABORT_MSK = 0x00000080,
-+	TX_PACKET_MODE_MSK = 0x0000ff00,	/* bits 8:15 */
-+	TX_FIFO_NUMBER_MSK = 0x00070000,	/* bits 16:18 */
-+	TX_RESERVED = 0x00780000,	/* bits 19:22 */
-+	TX_POWER_PA_DETECT_MSK = 0x7f800000,	/* bits 23:30 */
-+	TX_ABORT_REQUIRED_MSK = 0x80000000,	/* bits 31:31 */
-+};
++	/* Force use of chains B and C (0x6) for scan Rx.
++	 * Avoid A (0x1) because of its off-channel reception on A-band.
++	 * MIMO is not used here, but value is required to make uCode happy. */
++	scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
++			cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
++			(0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
++			(0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
 +
-+/* *******************************
-+ * TX aggregation state
-+ ******************************* */
++	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
++		scan->filter_flags = RXON_FILTER_PROMISC_MSK;
 +
-+enum {
-+	AGG_TX_STATE_TRANSMITTED = 0x00,
-+	AGG_TX_STATE_UNDERRUN_MSK = 0x01,
-+	AGG_TX_STATE_BT_PRIO_MSK = 0x02,
-+	AGG_TX_STATE_FEW_BYTES_MSK = 0x04,
-+	AGG_TX_STATE_ABORT_MSK = 0x08,
-+	AGG_TX_STATE_LAST_SENT_TTL_MSK = 0x10,
-+	AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK = 0x20,
-+	AGG_TX_STATE_LAST_SENT_BT_KILL_MSK = 0x40,
-+	AGG_TX_STATE_SCD_QUERY_MSK = 0x80,
-+	AGG_TX_STATE_TEST_BAD_CRC32_MSK = 0x100,
-+	AGG_TX_STATE_RESPONSE_MSK = 0x1ff,
-+	AGG_TX_STATE_DUMP_TX_MSK = 0x200,
-+	AGG_TX_STATE_DELAY_TX_MSK = 0x400
-+};
++	if (direct_mask)
++		IWL_DEBUG_SCAN
++		    ("Initiating direct scan for %s.\n",
++		     iwl_escape_essid(priv->essid, priv->essid_len));
++	else
++		IWL_DEBUG_SCAN("Initiating indirect scan.\n");
 +
-+#define AGG_TX_STATE_LAST_SENT_MSK \
-+(AGG_TX_STATE_LAST_SENT_TTL_MSK | \
-+ AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \
-+ AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
++	scan->channel_count =
++		iwl_get_channels_for_scan(
++			priv, phymode, 1, /* active */
++			direct_mask,
++			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
 +
-+#define AGG_TX_STATE_TRY_CNT_POS 12
-+#define AGG_TX_STATE_TRY_CNT_MSK 0xf000
++	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
++	    scan->channel_count * sizeof(struct iwl_scan_channel);
++	cmd.data = scan;
++	scan->len = cpu_to_le16(cmd.len);
 +
-+#define AGG_TX_STATE_SEQ_NUM_POS 16
-+#define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000
++	set_bit(STATUS_SCAN_HW, &priv->status);
++	rc = iwl_send_cmd_sync(priv, &cmd);
++	if (rc)
++		goto done;
 +
-+/*
-+ * REPLY_TX = 0x1c (response)
-+ */
-+#if IWL == 4965
-+struct iwl_tx_resp {
-+	u8 frame_count;		/* 1 no aggregation, >1 aggregation */
-+	u8 bt_kill_count;
-+	u8 failure_rts;
-+	u8 failure_frame;
-+	__le32 rate_n_flags;
-+	__le16 wireless_media_time;
-+	__le16 reserved;
-+	__le32 pa_power1;
-+	__le32 pa_power2;
-+	__le32 status;	/* TX status (for aggregation status of 1st frame) */
-+} __attribute__ ((packed));
++	queue_delayed_work(priv->workqueue, &priv->scan_check,
++			   IWL_SCAN_CHECK_WATCHDOG);
 +
-+#elif IWL == 3945
-+struct iwl_tx_resp {
-+	u8 failure_rts;
-+	u8 failure_frame;
-+	u8 bt_kill_count;
-+	u8 rate;
-+	__le32 wireless_media_time;
-+	__le32 status;	/* TX status (for aggregation status of 1st frame) */
-+} __attribute__ ((packed));
-+#endif
++	mutex_unlock(&priv->mutex);
++	return;
 +
-+#if IWL == 3945
-+/*
-+ * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response)
-+ * 3945 Tx Power Table Command
-+ */
-+struct iwl_txpowertable_cmd {
-+	u8 band;
-+	u8 reserved;
-+	__le16 channel;
-+	struct iwl_power_per_rate power[IWL_MAX_RATES];
-+} __attribute__ ((packed));
++ done:
++	/* inform mac80211 sacn aborted */
++	queue_work(priv->workqueue, &priv->scan_completed);
++	mutex_unlock(&priv->mutex);
++}
 +
-+#elif IWL == 4965
-+/*
-+ * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response)
-+ * 4965 Tx Power Table Command
-+ */
-+struct iwl_tx_power_table_cmd {
-+	u8 band;
-+	u8 channel_normal_width;
-+	__le16 channel;
-+	struct iwl_tx_power_db tx_power;
-+} __attribute__ ((packed));
++static void iwl_bg_up(struct work_struct *data)
++{
++	struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
 +
-+#endif
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
 +
++	mutex_lock(&priv->mutex);
++	__iwl_up(priv);
++	mutex_unlock(&priv->mutex);
++}
 +
-+#if IWL == 3945
-+struct iwl_rate_scaling_info {
-+	__le16 rate_n_flags;
-+	u8 try_cnt;
-+	u8 next_rate_index;
-+} __attribute__ ((packed));
++static void iwl_bg_restart(struct work_struct *data)
++{
++	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
 +
-+/**
-+ * struct iwl_rate_scaling_cmd - Rate Scaling Command & Response
-+ *
-+ * REPLY_RATE_SCALE = 0x47 (command, has simple generic response)
-+ *
-+ * NOTE: The table of rates passed to the uCode via the
-+ * RATE_SCALE command sets up the corresponding order of
-+ * rates used for all related commands, including rate
-+ * masks, etc.
-+ *
-+ * For example, if you set 9MB (PLCP 0x0f) as the first
-+ * rate in the rate table, the bit mask for that rate
-+ * when passed through ofdm_basic_rates on the REPLY_RXON
-+ * command would be bit 0 (1<<0)
-+ */
-+struct iwl_rate_scaling_cmd {
-+	u8 table_id;
-+	u8 reserved[3];
-+	struct iwl_rate_scaling_info table[IWL_MAX_RATES];
-+} __attribute__ ((packed));
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
 +
-+#elif IWL == 4965
++	iwl_down(priv);
++	queue_work(priv->workqueue, &priv->up);
++}
 +
-+/*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */
-+#define  LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK	(1<<0)
++static void iwl_bg_rx_replenish(struct work_struct *data)
++{
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, rx_replenish);
 +
-+#define  LINK_QUAL_AC_NUM AC_NUM
-+#define  LINK_QUAL_MAX_RETRY_NUM 16
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
 +
-+#define  LINK_QUAL_ANT_A_MSK (1<<0)
-+#define  LINK_QUAL_ANT_B_MSK (1<<1)
-+#define  LINK_QUAL_ANT_MSK   (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK)
++	mutex_lock(&priv->mutex);
++	iwl_rx_replenish(priv);
++	mutex_unlock(&priv->mutex);
++}
 +
-+struct iwl_link_qual_general_params {
-+	u8 flags;
-+	u8 mimo_delimiter;
-+	u8 single_stream_ant_msk;
-+	u8 dual_stream_ant_msk;
-+	u8 start_rate_index[LINK_QUAL_AC_NUM];
-+} __attribute__ ((packed));
++static void iwl_bg_post_associate(struct work_struct *data)
++{
++	struct iwl_priv *priv = container_of(data, struct iwl_priv,
++					     post_associate.work);
 +
-+struct iwl_link_qual_agg_params {
-+	__le16 agg_time_limit;
-+	u8 agg_dis_start_th;
-+	u8 agg_frame_cnt_limit;
-+	__le32 reserved;
-+} __attribute__ ((packed));
++	int rc = 0;
++	struct ieee80211_conf *conf = NULL;
 +
-+/*
-+ * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
-+ */
-+struct iwl_link_quality_cmd {
-+	u8 sta_id;
-+	u8 reserved1;
-+	__le16 control;
-+	struct iwl_link_qual_general_params general_params;
-+	struct iwl_link_qual_agg_params agg_params;
-+	struct {
-+		__le32 rate_n_flags;
-+	} rs_table[LINK_QUAL_MAX_RETRY_NUM];
-+	__le32 reserved2;
-+} __attribute__ ((packed));
-+#endif
++	IWL_DEBUG_ASSOC("Associated as %d to: " MAC_FMT "\n",
++			priv->assoc_id, MAC_ARG(priv->active_rxon.bssid_addr));
 +
-+/*
-+ * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
-+ */
-+struct iwl_bt_cmd {
-+	u8 flags;
-+	u8 lead_time;
-+	u8 max_kill;
-+	u8 reserved;
-+	__le32 kill_ack_mask;
-+	__le32 kill_cts_mask;
-+} __attribute__ ((packed));
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	mutex_lock(&priv->mutex);
++
++	conf = ieee80211_get_hw_conf(priv->hw);
++
++	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++	iwl_commit_rxon(priv);
++
++	memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
++	iwl_setup_rxon_timing(priv);
++	rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
++			      sizeof(priv->rxon_timing), &priv->rxon_timing);
++	if (rc)
++		IWL_WARNING("REPLY_RXON_TIMING failed - "
++			    "Attempting to continue.\n");
++
++	priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
++
++#ifdef CONFIG_IWLWIFI_HT
++	if (priv->is_ht_enabled && priv->current_assoc_ht.is_ht)
++		iwl4965_set_rxon_ht(priv, &priv->current_assoc_ht);
++	else {
++		priv->active_rate_ht[0] = 0;
++		priv->active_rate_ht[1] = 0;
++		priv->current_channel_width = IWL_CHANNEL_WIDTH_20MHZ;
++	}
++#endif /* CONFIG_IWLWIFI_HT*/
++	iwl4965_set_rxon_chain(priv);
++	priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
 +
-+/******************************************************************************
-+ * (6)
-+ * Spectrum Management (802.11h) Commands, Responses, Notifications:
-+ *
-+ *****************************************************************************/
++	IWL_DEBUG_ASSOC("assoc id %d beacon interval %d\n",
++			priv->assoc_id, priv->beacon_int);
 +
-+/*
-+ * Spectrum Management
-+ */
-+#define MEASUREMENT_FILTER_FLAG (RXON_FILTER_PROMISC_MSK         | \
-+				 RXON_FILTER_CTL2HOST_MSK        | \
-+				 RXON_FILTER_ACCEPT_GRP_MSK      | \
-+				 RXON_FILTER_DIS_DECRYPT_MSK     | \
-+				 RXON_FILTER_DIS_GRP_DECRYPT_MSK | \
-+				 RXON_FILTER_ASSOC_MSK           | \
-+				 RXON_FILTER_BCON_AWARE_MSK)
++	if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
++		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
++	else
++		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 +
-+struct iwl_measure_channel {
-+	__le32 duration;	/* measurement duration in extended beacon
-+				 * format */
-+	u8 channel;		/* channel to measure */
-+	u8 type;		/* see enum iwl_measure_type */
-+	__le16 reserved;
-+} __attribute__ ((packed));
++	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
++		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
++			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
++		else
++			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 +
-+/*
-+ * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command)
-+ */
-+struct iwl_spectrum_cmd {
-+	__le16 len;		/* number of bytes starting from token */
-+	u8 token;		/* token id */
-+	u8 id;			/* measurement id -- 0 or 1 */
-+	u8 origin;		/* 0 = TGh, 1 = other, 2 = TGk */
-+	u8 periodic;		/* 1 = periodic */
-+	__le16 path_loss_timeout;
-+	__le32 start_time;	/* start time in extended beacon format */
-+	__le32 reserved2;
-+	__le32 flags;		/* rxon flags */
-+	__le32 filter_flags;	/* rxon filter flags */
-+	__le16 channel_count;	/* minimum 1, maximum 10 */
-+	__le16 reserved3;
-+	struct iwl_measure_channel channels[10];
-+} __attribute__ ((packed));
++		if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
++			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 +
-+/*
-+ * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response)
-+ */
-+struct iwl_spectrum_resp {
-+	u8 token;
-+	u8 id;			/* id of the prior command replaced, or 0xff */
-+	__le16 status;		/* 0 - command will be handled
-+				 * 1 - cannot handle (conflicts with another
-+				 *     measurement) */
-+} __attribute__ ((packed));
++	}
 +
-+enum iwl_measurement_state {
-+	IWL_MEASUREMENT_START = 0,
-+	IWL_MEASUREMENT_STOP = 1,
-+};
++	iwl_commit_rxon(priv);
 +
-+enum iwl_measurement_status {
-+	IWL_MEASUREMENT_OK = 0,
-+	IWL_MEASUREMENT_CONCURRENT = 1,
-+	IWL_MEASUREMENT_CSA_CONFLICT = 2,
-+	IWL_MEASUREMENT_TGH_CONFLICT = 3,
-+	/* 4-5 reserved */
-+	IWL_MEASUREMENT_STOPPED = 6,
-+	IWL_MEASUREMENT_TIMEOUT = 7,
-+	IWL_MEASUREMENT_PERIODIC_FAILED = 8,
-+};
++	switch (priv->iw_mode) {
++	case IEEE80211_IF_TYPE_STA:
++		iwl_rate_scale_init(priv->hw, IWL_AP_ID);
++		break;
 +
-+#define NUM_ELEMENTS_IN_HISTOGRAM 8
++	case IEEE80211_IF_TYPE_IBSS:
 +
-+struct iwl_measurement_histogram {
-+	__le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM];	/* in 0.8usec counts */
-+	__le32 cck[NUM_ELEMENTS_IN_HISTOGRAM];	/* in 1usec counts */
-+} __attribute__ ((packed));
++		/* clear out the station table */
++		iwl_clear_stations_table(priv);
 +
-+/* clear channel availability counters */
-+struct iwl_measurement_cca_counters {
-+	__le32 ofdm;
-+	__le32 cck;
-+} __attribute__ ((packed));
++		iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
++		iwl_rxon_add_station(priv, priv->bssid, 0);
++		iwl_rate_scale_init(priv->hw, IWL_STA_ID);
++		iwl_send_beacon_cmd(priv);
 +
-+enum iwl_measure_type {
-+	IWL_MEASURE_BASIC = (1 << 0),
-+	IWL_MEASURE_CHANNEL_LOAD = (1 << 1),
-+	IWL_MEASURE_HISTOGRAM_RPI = (1 << 2),
-+	IWL_MEASURE_HISTOGRAM_NOISE = (1 << 3),
-+	IWL_MEASURE_FRAME = (1 << 4),
-+	/* bits 5:6 are reserved */
-+	IWL_MEASURE_IDLE = (1 << 7),
-+};
++		break;
 +
-+/*
-+ * SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command)
-+ */
-+struct iwl_spectrum_notification {
-+	u8 id;			/* measurement id -- 0 or 1 */
-+	u8 token;
-+	u8 channel_index;	/* index in measurement channel list */
-+	u8 state;		/* 0 - start, 1 - stop */
-+	__le32 start_time;	/* lower 32-bits of TSF */
-+	u8 band;		/* 0 - 5.2GHz, 1 - 2.4GHz */
-+	u8 channel;
-+	u8 type;		/* see enum iwl_measurement_type */
-+	u8 reserved1;
-+	/* NOTE:  cca_ofdm, cca_cck, basic_type, and histogram are only only
-+	 * valid if applicable for measurement type requested. */
-+	__le32 cca_ofdm;	/* cca fraction time in 40Mhz clock periods */
-+	__le32 cca_cck;		/* cca fraction time in 44Mhz clock periods */
-+	__le32 cca_time;	/* channel load time in usecs */
-+	u8 basic_type;		/* 0 - bss, 1 - ofdm preamble, 2 -
-+				 * unidentified */
-+	u8 reserved2[3];
-+	struct iwl_measurement_histogram histogram;
-+	__le32 stop_time;	/* lower 32-bits of TSF */
-+	__le32 status;		/* see iwl_measurement_status */
-+} __attribute__ ((packed));
++	case IEEE80211_IF_TYPE_AP:
 +
-+/******************************************************************************
-+ * (7)
-+ * Power Management Commands, Responses, Notifications:
-+ *
-+ *****************************************************************************/
++		/* clear out the station table */
++		iwl_clear_stations_table(priv);
 +
-+/**
-+ * struct iwl_powertable_cmd - Power Table Command
-+ * @flags: See below:
-+ *
-+ * POWER_TABLE_CMD = 0x77 (command, has simple generic response)
-+ *
-+ * PM allow:
-+ *   bit 0 - '0' Driver not allow power management
-+ *           '1' Driver allow PM (use rest of parameters)
-+ * uCode send sleep notifications:
-+ *   bit 1 - '0' Don't send sleep notification
-+ *           '1' send sleep notification (SEND_PM_NOTIFICATION)
-+ * Sleep over DTIM
-+ *   bit 2 - '0' PM have to walk up every DTIM
-+ *           '1' PM could sleep over DTIM till listen Interval.
-+ * PCI power managed
-+ *   bit 3 - '0' (PCI_LINK_CTRL & 0x1)
-+ *           '1' !(PCI_LINK_CTRL & 0x1)
-+ * Force sleep Modes
-+ *   bit 31/30- '00' use both mac/xtal sleeps
-+ *              '01' force Mac sleep
-+ *              '10' force xtal sleep
-+ *              '11' Illegal set
-+ *
-+ * NOTE: if sleep_interval[SLEEP_INTRVL_TABLE_SIZE-1] > DTIM period then
-+ * ucode assume sleep over DTIM is allowed and we don't need to wakeup
-+ * for every DTIM.
-+ */
-+#define IWL_POWER_VEC_SIZE 5
++		iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
++		iwl_send_beacon_cmd(priv);
 +
++		break;
++	}
 +
-+#if IWL == 3945
++	/* FIXME: not sure why this doesn't work in AP mode */
++	if (priv->iw_mode != IEEE80211_IF_TYPE_AP)
++		iwl_sequence_reset(priv);
 +
-+#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK	__constant_cpu_to_le32(1<<0)
-+#define IWL_POWER_SLEEP_OVER_DTIM_MSK		__constant_cpu_to_le32(1<<2)
-+#define IWL_POWER_PCI_PM_MSK			__constant_cpu_to_le32(1<<3)
-+struct iwl_powertable_cmd {
-+	__le32 flags;
-+	__le32 rx_data_timeout;
-+	__le32 tx_data_timeout;
-+	__le32 sleep_interval[IWL_POWER_VEC_SIZE];
-+} __attribute__((packed));
++#ifdef CONFIG_IWLWIFI_SENSITIVITY
++	/* Enable Rx differential gain and sensitivity calibrations */
++	iwl4965_chain_noise_reset(priv);
++	priv->start_calib = 1;
++#endif /* CONFIG_IWLWIFI_SENSITIVITY */
 +
-+#elif IWL == 4965
++	if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
++		priv->assoc_station_added = 1;
 +
-+#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK	__constant_cpu_to_le16(1<<0)
-+#define IWL_POWER_SLEEP_OVER_DTIM_MSK		__constant_cpu_to_le16(1<<2)
-+#define IWL_POWER_PCI_PM_MSK			__constant_cpu_to_le16(1<<3)
++#ifdef CONFIG_IWLWIFI_QOS
++	iwl_activate_qos(priv, 0);
++#endif /* CONFIG_IWLWIFI_QOS */
++	mutex_unlock(&priv->mutex);
++}
 +
-+struct iwl_powertable_cmd {
-+	__le16 flags;
-+	u8 keep_alive_seconds;
-+	u8 debug_flags;
-+	__le32 rx_data_timeout;
-+	__le32 tx_data_timeout;
-+	__le32 sleep_interval[IWL_POWER_VEC_SIZE];
-+	__le32 keep_alive_beacons;
-+} __attribute__ ((packed));
-+#endif
++static void iwl_bg_abort_scan(struct work_struct *work)
++{
++	struct iwl_priv *priv = container_of(work, struct iwl_priv,
++					     abort_scan);
 +
-+/*
-+ * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
-+ * 3945 and 4965 identical.
-+ */
-+struct iwl_sleep_notification {
-+	u8 pm_sleep_mode;
-+	u8 pm_wakeup_src;
-+	__le16 reserved;
-+	__le32 sleep_time;
-+	__le32 tsf_low;
-+	__le32 bcon_timer;
-+} __attribute__ ((packed));
++	if (!iwl_is_ready(priv))
++		return;
 +
-+/* Sleep states.  3945 and 4965 identical. */
-+enum {
-+	IWL_PM_NO_SLEEP = 0,
-+	IWL_PM_SLP_MAC = 1,
-+	IWL_PM_SLP_FULL_MAC_UNASSOCIATE = 2,
-+	IWL_PM_SLP_FULL_MAC_CARD_STATE = 3,
-+	IWL_PM_SLP_PHY = 4,
-+	IWL_PM_SLP_REPENT = 5,
-+	IWL_PM_WAKEUP_BY_TIMER = 6,
-+	IWL_PM_WAKEUP_BY_DRIVER = 7,
-+	IWL_PM_WAKEUP_BY_RFKILL = 8,
-+	/* 3 reserved */
-+	IWL_PM_NUM_OF_MODES = 12,
-+};
++	mutex_lock(&priv->mutex);
 +
-+/*
-+ * REPLY_CARD_STATE_CMD = 0xa0 (command, has simple generic response)
-+ */
-+#define CARD_STATE_CMD_DISABLE 0x00	/* Put card to sleep */
-+#define CARD_STATE_CMD_ENABLE  0x01	/* Wake up card */
-+#define CARD_STATE_CMD_HALT    0x02	/* Power down permanently */
-+struct iwl_card_state_cmd {
-+	__le32 status;		/* CARD_STATE_CMD_* request new power state */
-+} __attribute__ ((packed));
++	set_bit(STATUS_SCAN_ABORTING, &priv->status);
++	iwl_send_scan_abort(priv);
 +
-+/*
-+ * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command)
-+ */
-+struct iwl_card_state_notif {
-+	__le32 flags;
-+} __attribute__ ((packed));
++	mutex_unlock(&priv->mutex);
++}
 +
-+#define HW_CARD_DISABLED   0x01
-+#define SW_CARD_DISABLED   0x02
-+#define RF_CARD_DISABLED   0x04
-+#define RXON_CARD_DISABLED 0x10
++static void iwl_bg_scan_completed(struct work_struct *work)
++{
++	struct iwl_priv *priv =
++	    container_of(work, struct iwl_priv, scan_completed);
 +
-+struct iwl_ct_kill_config {
-+	__le32   reserved;
-+	__le32   critical_temperature_M;
-+	__le32   critical_temperature_R;
-+}  __attribute__ ((packed));
++	IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
 +
-+/******************************************************************************
-+ * (8)
-+ * Scan Commands, Responses, Notifications:
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	ieee80211_scan_completed(priv->hw);
++
++	/* Since setting the TXPOWER may have been deferred while
++	 * performing the scan, fire one off */
++	mutex_lock(&priv->mutex);
++	iwl_hw_reg_send_txpower(priv);
++	mutex_unlock(&priv->mutex);
++}
++
++/*****************************************************************************
++ *
++ * mac80211 entry point functions
 + *
 + *****************************************************************************/
 +
-+struct iwl_scan_channel {
-+	/* type is defined as:
-+	 * 0:0 active (0 - passive)
-+	 * 1:4 SSID direct
-+	 *     If 1 is set then corresponding SSID IE is transmitted in probe
-+	 * 5:7 reserved
-+	 */
-+	u8 type;
-+	u8 channel;
-+	struct iwl_tx_power tpc;
-+	__le16 active_dwell;
-+	__le16 passive_dwell;
-+} __attribute__ ((packed));
++static int iwl_mac_open(struct ieee80211_hw *hw)
++{
++	struct iwl_priv *priv = hw->priv;
 +
-+struct iwl_ssid_ie {
-+	u8 id;
-+	u8 len;
-+	u8 ssid[32];
-+} __attribute__ ((packed));
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+#define PROBE_OPTION_MAX        0x4
-+#define TX_CMD_LIFE_TIME_INFINITE	__constant_cpu_to_le32(0xFFFFFFFF)
-+#define IWL_GOOD_CRC_TH		__constant_cpu_to_le16(1)
-+#define IWL_MAX_SCAN_SIZE 1024
++	/* we should be verifying the device is ready to be opened */
++	mutex_lock(&priv->mutex);
 +
-+/*
-+ * REPLY_SCAN_CMD = 0x80 (command)
-+ */
-+struct iwl_scan_cmd {
-+	__le16 len;
-+	u8 reserved0;
-+	u8 channel_count;
-+	__le16 quiet_time;     /* dwell only this long on quiet chnl
-+				* (active scan) */
-+	__le16 quiet_plcp_th;  /* quiet chnl is < this # pkts (typ. 1) */
-+	__le16 good_CRC_th;    /* passive -> active promotion threshold */
-+#if IWL == 3945
-+	__le16 reserved1;
-+#elif IWL == 4965
-+	__le16 rx_chain;
-+#endif
-+	__le32 max_out_time;   /* max usec to be out of associated (service)
-+				* chnl */
-+	__le32 suspend_time;   /* pause scan this long when returning to svc
-+				* chnl.
-+				* 3945 -- 31:24 # beacons, 19:0 additional usec,
-+				* 4965 -- 31:22 # beacons, 21:0 additional usec.
-+				*/
-+	__le32 flags;
-+	__le32 filter_flags;
++	priv->is_open = 1;
 +
-+	struct iwl_tx_cmd tx_cmd;
-+	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
++	if (!iwl_is_rfkill(priv))
++		ieee80211_start_queues(priv->hw);
 +
-+	u8 data[0];
-+	/*
-+	 * The channels start after the probe request payload and are of type:
-+	 *
-+	 * struct iwl_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));
++	mutex_unlock(&priv->mutex);
++	IWL_DEBUG_MAC80211("leave\n");
++	return 0;
++}
 +
-+/* Can abort will notify by complete notification with abort status. */
-+#define CAN_ABORT_STATUS	__constant_cpu_to_le32(0x1)
-+/* complete notification statuses */
-+#define ABORT_STATUS            0x2
++static int iwl_mac_stop(struct ieee80211_hw *hw)
++{
++	struct iwl_priv *priv = hw->priv;
 +
-+/*
-+ * REPLY_SCAN_CMD = 0x80 (response)
-+ */
-+struct iwl_scanreq_notification {
-+	__le32 status;		/* 1: okay, 2: cannot fulfill request */
-+} __attribute__ ((packed));
++	IWL_DEBUG_MAC80211("enter\n");
++	priv->is_open = 0;
++	/*netif_stop_queue(dev); */
++	flush_workqueue(priv->workqueue);
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+/*
-+ * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command)
-+ */
-+struct iwl_scanstart_notification {
-+	__le32 tsf_low;
-+	__le32 tsf_high;
-+	__le32 beacon_timer;
-+	u8 channel;
-+	u8 band;
-+	u8 reserved[2];
-+	__le32 status;
-+} __attribute__ ((packed));
++	return 0;
++}
 +
-+#define  SCAN_OWNER_STATUS 0x1;
-+#define  MEASURE_OWNER_STATUS 0x2;
++static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
++		      struct ieee80211_tx_control *ctl)
++{
++	struct iwl_priv *priv = hw->priv;
 +
-+#define NUMBER_OF_STATISTICS 1	/* first __le32 is good CRC */
-+/*
-+ * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command)
-+ */
-+struct iwl_scanresults_notification {
-+	u8 channel;
-+	u8 band;
-+	u8 reserved[2];
-+	__le32 tsf_low;
-+	__le32 tsf_high;
-+	__le32 statistics[NUMBER_OF_STATISTICS];
-+} __attribute__ ((packed));
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+/*
-+ * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command)
-+ */
-+struct iwl_scancomplete_notification {
-+	u8 scanned_channels;
-+	u8 status;
-+	u8 reserved;
-+	u8 last_channel;
-+	__le32 tsf_low;
-+	__le32 tsf_high;
-+} __attribute__ ((packed));
++	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
++		IWL_DEBUG_MAC80211("leave - monitor\n");
++		return -1;
++	}
 +
++	IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
++		     ctl->tx_rate);
 +
-+/******************************************************************************
-+ * (9)
-+ * IBSS/AP Commands and Notifications:
-+ *
-+ *****************************************************************************/
++	if (iwl_tx_skb(priv, skb, ctl))
++		dev_kfree_skb_any(skb);
 +
-+/*
-+ * BEACON_NOTIFICATION = 0x90 (notification only, not a command)
-+ */
-+struct iwl_beacon_notif {
-+	struct iwl_tx_resp beacon_notify_hdr;
-+	__le32 low_tsf;
-+	__le32 high_tsf;
-+	__le32 ibss_mgr_status;
-+} __attribute__ ((packed));
++	IWL_DEBUG_MAC80211("leave\n");
++	return 0;
++}
 +
-+/*
-+ * REPLY_TX_BEACON = 0x91 (command, has simple generic response)
-+ */
-+struct iwl_tx_beacon_cmd {
-+	struct iwl_tx_cmd tx;
-+	__le16 tim_idx;
-+	u8 tim_size;
-+	u8 reserved1;
-+	struct ieee80211_hdr frame[0];	/* beacon frame */
-+} __attribute__ ((packed));
++static int iwl_mac_add_interface(struct ieee80211_hw *hw,
++				 struct ieee80211_if_init_conf *conf)
++{
++	struct iwl_priv *priv = hw->priv;
++	unsigned long flags;
 +
-+/******************************************************************************
-+ * (10)
-+ * Statistics Commands and Notifications:
-+ *
-+ *****************************************************************************/
++	IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type);
++	if (conf->mac_addr)
++		IWL_DEBUG_MAC80211("enter: MAC " MAC_FMT "\n",
++				   MAC_ARG(conf->mac_addr));
 +
-+#define IWL_TEMP_CONVERT 260
++	if (priv->interface_id) {
++		IWL_DEBUG_MAC80211("leave - interface_id != 0\n");
++		return 0;
++	}
 +
-+#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
-+#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
-+#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->interface_id = conf->if_id;
 +
-+/* Used for passing to driver number of successes and failures per rate */
-+struct rate_histogram {
-+	union {
-+		__le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
-+		__le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
-+		__le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
-+	} success;
-+	union {
-+		__le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
-+		__le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
-+		__le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
-+	} failed;
-+} __attribute__ ((packed));
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+/* statistics command response */
++	mutex_lock(&priv->mutex);
++	iwl_set_mode(priv, conf->type);
 +
-+struct statistics_rx_phy {
-+	__le32 ina_cnt;
-+	__le32 fina_cnt;
-+	__le32 plcp_err;
-+	__le32 crc32_err;
-+	__le32 overrun_err;
-+	__le32 early_overrun_err;
-+	__le32 crc32_good;
-+	__le32 false_alarm_cnt;
-+	__le32 fina_sync_err_cnt;
-+	__le32 sfd_timeout;
-+	__le32 fina_timeout;
-+	__le32 unresponded_rts;
-+	__le32 rxe_frame_limit_overrun;
-+	__le32 sent_ack_cnt;
-+	__le32 sent_cts_cnt;
-+#if IWL == 4965
-+	__le32 sent_ba_rsp_cnt;
-+	__le32 dsp_self_kill;
-+	__le32 mh_format_err;
-+	__le32 re_acq_main_rssi_sum;
-+	__le32 reserved3;
-+#endif
-+} __attribute__ ((packed));
++	IWL_DEBUG_MAC80211("leave\n");
++	mutex_unlock(&priv->mutex);
 +
-+#if IWL == 4965
-+struct statistics_rx_ht_phy {
-+	__le32 plcp_err;
-+	__le32 overrun_err;
-+	__le32 early_overrun_err;
-+	__le32 crc32_good;
-+	__le32 crc32_err;
-+	__le32 mh_format_err;
-+	__le32 agg_crc32_good;
-+	__le32 agg_mpdu_cnt;
-+	__le32 agg_cnt;
-+	__le32 reserved2;
-+} __attribute__ ((packed));
-+#endif
++	return 0;
++}
 +
-+struct statistics_rx_non_phy {
-+	__le32 bogus_cts;	/* CTS received when not expecting CTS */
-+	__le32 bogus_ack;	/* ACK received when not expecting ACK */
-+	__le32 non_bssid_frames;	/* number of frames with BSSID that
-+					 * doesn't belong to the STA BSSID */
-+	__le32 filtered_frames;	/* count frames that were dumped in the
-+				 * filtering process */
-+	__le32 non_channel_beacons;	/* beacons with our bss id but not on
-+					 * our serving channel */
-+#if IWL == 4965
-+	__le32 channel_beacons;	/* beacons with our bss id and in our
-+				 * serving channel */
-+	__le32 num_missed_bcon;	/* number of missed beacons */
-+	__le32 adc_rx_saturation_time;	/* count in 0.8us units the time the
-+					 * ADC was in saturation */
-+	__le32 ina_detection_search_time;/* total time (in 0.8us) searched
-+					  * for INA */
-+	__le32 beacon_silence_rssi_a;	/* RSSI silence after beacon frame */
-+	__le32 beacon_silence_rssi_b;	/* RSSI silence after beacon frame */
-+	__le32 beacon_silence_rssi_c;	/* RSSI silence after beacon frame */
-+	__le32 interference_data_flag;	/* flag for interference data
-+					 * availability. 1 when data is
-+					 * available. */
-+	__le32 channel_load;	/* counts RX Enable time */
-+	__le32 dsp_false_alarms;	/* DSP false alarm (both OFDM
-+					 * and CCK) counter */
-+	__le32 beacon_rssi_a;
-+	__le32 beacon_rssi_b;
-+	__le32 beacon_rssi_c;
-+	__le32 beacon_energy_a;
-+	__le32 beacon_energy_b;
-+	__le32 beacon_energy_c;
-+#endif
-+} __attribute__ ((packed));
++/**
++ * iwl_mac_config - mac80211 config callback
++ *
++ * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
++ * be set inappropriately and the driver currently sets the hardware up to
++ * use it whenever needed.
++ */
++static int iwl_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
++{
++	struct iwl_priv *priv = hw->priv;
++	const struct iwl_channel_info *ch_info;
++	unsigned long flags;
 +
-+struct statistics_rx {
-+	struct statistics_rx_phy ofdm;
-+	struct statistics_rx_phy cck;
-+	struct statistics_rx_non_phy general;
-+#if IWL == 4965
-+	struct statistics_rx_ht_phy ofdm_ht;
-+#endif
-+} __attribute__ ((packed));
++	mutex_lock(&priv->mutex);
++	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
 +
-+#if IWL == 4965
-+struct statistics_tx_non_phy_agg {
-+	__le32 ba_timeout;
-+	__le32 ba_reschedule_frames;
-+	__le32 scd_query_agg_frame_cnt;
-+	__le32 scd_query_no_agg;
-+	__le32 scd_query_agg;
-+	__le32 scd_query_mismatch;
-+	__le32 frame_not_ready;
-+	__le32 underrun;
-+	__le32 bt_prio_kill;
-+	__le32 rx_ba_rsp_cnt;
-+	__le32 reserved2;
-+	__le32 reserved3;
-+} __attribute__ ((packed));
-+#endif
++	if (!iwl_is_ready(priv)) {
++		IWL_DEBUG_MAC80211("leave - not ready\n");
++		mutex_unlock(&priv->mutex);
++		return -EIO;
++	}
 +
-+struct statistics_tx {
-+	__le32 preamble_cnt;
-+	__le32 rx_detected_cnt;
-+	__le32 bt_prio_defer_cnt;
-+	__le32 bt_prio_kill_cnt;
-+	__le32 few_bytes_cnt;
-+	__le32 cts_timeout;
-+	__le32 ack_timeout;
-+	__le32 expected_ack_cnt;
-+	__le32 actual_ack_cnt;
-+#if IWL == 4965
-+	__le32 dump_msdu_cnt;
-+	__le32 burst_abort_next_frame_mismatch_cnt;
-+	__le32 burst_abort_missing_next_frame_cnt;
-+	__le32 cts_timeout_collision;
-+	__le32 ack_or_ba_timeout_collision;
-+	struct statistics_tx_non_phy_agg agg;
-+#endif
-+} __attribute__ ((packed));
++	/* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only
++	 * what is exposed through include/ declrations */
++	if (unlikely(!iwl_param_disable_hw_scan &&
++		     test_bit(STATUS_SCANNING, &priv->status))) {
++		IWL_DEBUG_MAC80211("leave - scanning\n");
++		mutex_unlock(&priv->mutex);
++		return 0;
++	}
 +
-+struct statistics_dbg {
-+	__le32 burst_check;
-+	__le32 burst_count;
-+	__le32 reserved[4];
-+} __attribute__ ((packed));
++	spin_lock_irqsave(&priv->lock, flags);
 +
-+struct statistics_div {
-+	__le32 tx_on_a;
-+	__le32 tx_on_b;
-+	__le32 exec_time;
-+	__le32 probe_time;
-+#if IWL == 4965
-+	__le32 reserved1;
-+	__le32 reserved2;
-+#endif
-+} __attribute__ ((packed));
++	ch_info = iwl_get_channel_info(priv, conf->phymode, conf->channel);
++	if (!is_channel_valid(ch_info)) {
++		IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
++			       conf->channel, conf->phymode);
++		IWL_DEBUG_MAC80211("leave - invalid channel\n");
++		spin_unlock_irqrestore(&priv->lock, flags);
++		mutex_unlock(&priv->mutex);
++		return -EINVAL;
++	}
 +
-+struct statistics_general {
-+	__le32 temperature;
-+#if IWL == 4965
-+	__le32 temperature_m;
-+#endif
-+	struct statistics_dbg dbg;
-+	__le32 sleep_time;
-+	__le32 slots_out;
-+	__le32 slots_idle;
-+	__le32 ttl_timestamp;
-+	struct statistics_div div;
-+#if IWL == 4965
-+	__le32 rx_enable_counter;
-+	__le32 reserved1;
-+	__le32 reserved2;
-+	__le32 reserved3;
++#ifdef CONFIG_IWLWIFI_HT
++	/* if we are switching fron ht to 2.4 clear flags
++	 * from any ht related info since 2.4 does not
++	 * support ht */
++	if ((le16_to_cpu(priv->staging_rxon.channel) != conf->channel)
++#ifdef IEEE80211_CONF_CHANNEL_SWITCH
++	    && !(conf->flags & IEEE80211_CONF_CHANNEL_SWITCH)
 +#endif
-+} __attribute__ ((packed));
++	)
++		priv->staging_rxon.flags = 0;
++#endif /* CONFIG_IWLWIFI_HT */
 +
-+/*
-+ * REPLY_STATISTICS_CMD = 0x9c,
-+ * 3945 and 4965 identical.
-+ *
-+ * This command triggers an immediate response containing uCode statistics.
-+ * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below.
-+ *
-+ * If the CLEAR_STATS configuration flag is set, uCode will clear its
-+ * internal copy of the statistics (counters) after issuing the response.
-+ * This flag does not affect STATISTICS_NOTIFICATIONs after beacons (see below).
-+ *
-+ * If the DISABLE_NOTIF configuration flag is set, uCode will not issue
-+ * STATISTICS_NOTIFICATIONs after received beacons (see below).  This flag
-+ * does not affect the response to the REPLY_STATISTICS_CMD 0x9c itself.
-+ */
-+#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1)	/* see above */
-+#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */
-+struct iwl_statistics_cmd {
-+	__le32 configuration_flags;	/* IWL_STATS_CONF_* */
-+} __attribute__ ((packed));
++	iwl_set_rxon_channel(priv, conf->phymode, conf->channel);
 +
-+/*
-+ * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)
-+ *
-+ * By default, uCode issues this notification after receiving a beacon
-+ * while associated.  To disable this behavior, set DISABLE_NOTIF flag in the
-+ * REPLY_STATISTICS_CMD 0x9c, above.
-+ *
-+ * Statistics counters continue to increment beacon after beacon, but are
-+ * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD
-+ * 0x9c with CLEAR_STATS bit set (see above).
-+ *
-+ * uCode also issues this notification during scans.  uCode clears statistics
-+ * appropriately so that each notification contains statistics for only the
-+ * one channel that has just been scanned.
-+ */
-+struct iwl_notif_statistics {
-+	__le32 flag;
-+	struct statistics_rx rx;
-+	struct statistics_tx tx;
-+	struct statistics_general general;
-+} __attribute__ ((packed));
++	iwl_set_flags_for_phymode(priv, conf->phymode);
++
++	/* The list of supported rates and rate mask can be different
++	 * for each phymode; since the phymode may have changed, reset
++	 * the rate mask to what mac80211 lists */
++	iwl_set_rate(priv);
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++#ifdef IEEE80211_CONF_CHANNEL_SWITCH
++	if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
++		iwl_hw_channel_switch(priv, conf->channel);
++		mutex_unlock(&priv->mutex);
++		return 0;
++	}
++#endif
 +
++	iwl_radio_kill_sw(priv, !conf->radio_enabled);
 +
-+/*
-+ * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command)
-+ */
-+/* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row,
-+ * then this notification will be sent. */
-+#define CONSECUTIVE_MISSED_BCONS_TH 20
++	if (!conf->radio_enabled) {
++		IWL_DEBUG_MAC80211("leave - radio disabled\n");
++		mutex_unlock(&priv->mutex);
++		return 0;
++	}
 +
-+struct iwl_missed_beacon_notif {
-+	__le32 consequtive_missed_beacons;
-+	__le32 total_missed_becons;
-+	__le32 num_expected_beacons;
-+	__le32 num_recvd_beacons;
-+} __attribute__ ((packed));
++	if (iwl_is_rfkill(priv)) {
++		IWL_DEBUG_MAC80211("leave - RF kill\n");
++		mutex_unlock(&priv->mutex);
++		return -EIO;
++	}
 +
-+/******************************************************************************
-+ * (11)
-+ * Rx Calibration Commands:
-+ *
-+ *****************************************************************************/
++	iwl_set_rate(priv);
 +
-+#define PHY_CALIBRATE_DIFF_GAIN_CMD (7)
-+#define HD_TABLE_SIZE  (11)
++	if (memcmp(&priv->active_rxon,
++		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
++		iwl_commit_rxon(priv);
++	else
++		IWL_DEBUG_INFO("No re-sending same RXON configuration.\n");
 +
-+struct iwl_sensitivity_cmd {
-+	__le16 control;
-+	__le16 table[HD_TABLE_SIZE];
-+} __attribute__ ((packed));
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+struct iwl_calibration_cmd {
-+	u8 opCode;
-+	u8 flags;
-+	__le16 reserved;
-+	s8 diff_gain_a;
-+	s8 diff_gain_b;
-+	s8 diff_gain_c;
-+	u8 reserved1;
-+} __attribute__ ((packed));
++	mutex_unlock(&priv->mutex);
 +
-+/******************************************************************************
-+ * (12)
-+ * Miscellaneous Commands:
-+ *
-+ *****************************************************************************/
++	return 0;
++}
 +
-+/*
-+ * LEDs Command & Response
-+ * REPLY_LEDS_CMD = 0x48 (command, has simple generic response)
-+ *
-+ * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field),
-+ * this command turns it on or off, or sets up a periodic blinking cycle.
-+ */
-+struct iwl_led_cmd {
-+	__le32 interval;	/* "interval" in uSec */
-+	u8 id;			/* 1: Activity, 2: Link, 3: Tech */
-+	u8 off;			/* # intervals off while blinking;
-+				 * "0", with >0 "on" value, turns LED on */
-+	u8 on;			/* # intervals on while blinking;
-+				 * "0", regardless of "off", turns LED off */
-+	u8 reserved;
-+} __attribute__ ((packed));
++static void iwl_config_ap(struct iwl_priv *priv)
++{
++	int rc = 0;
 +
-+/******************************************************************************
-+ * (13)
-+ * Union of all expected notifications/responses:
-+ *
-+ *****************************************************************************/
++	if (priv->status & STATUS_EXIT_PENDING)
++		return;
 +
-+struct iwl_rx_packet {
-+	__le32 len;
-+	struct iwl_cmd_header hdr;
-+	union {
-+		struct iwl_alive_resp alive_frame;
-+		struct iwl_rx_frame rx_frame;
-+		struct iwl_tx_resp tx_resp;
-+		struct iwl_spectrum_notification spectrum_notif;
-+		struct iwl_csa_notification csa_notif;
-+		struct iwl_error_resp err_resp;
-+		struct iwl_card_state_notif card_state_notif;
-+		struct iwl_beacon_notif beacon_status;
-+		struct iwl_add_sta_resp add_sta;
-+		struct iwl_sleep_notification sleep_notif;
-+		struct iwl_spectrum_resp spectrum;
-+		struct iwl_notif_statistics stats;
-+#if IWL == 4965
-+		struct iwl_compressed_ba_resp compressed_ba;
-+		struct iwl_missed_beacon_notif missed_beacon;
-+#endif
-+		__le32 status;
-+		u8 raw[0];
-+	} u;
-+} __attribute__ ((packed));
++	/* The following should be done only at AP bring up */
++	if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) {
 +
-+#define IWL_RX_FRAME_SIZE        (4 + sizeof(struct iwl_rx_frame))
++		/* RXON - unassoc (to set timing command) */
++		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++		iwl_commit_rxon(priv);
 +
-+#endif				/* __iwl_commands_h__ */
-diff --git a/drivers/net/wireless/iwl-debug.h b/drivers/net/wireless/iwl-debug.h
-new file mode 100644
-index 0000000..0ebc4f7
---- /dev/null
-+++ b/drivers/net/wireless/iwl-debug.h
-@@ -0,0 +1,149 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ipw3945 project.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
++		/* RXON Timing */
++		memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
++		iwl_setup_rxon_timing(priv);
++		rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
++				sizeof(priv->rxon_timing), &priv->rxon_timing);
++		if (rc)
++			IWL_WARNING("REPLY_RXON_TIMING failed - "
++					"Attempting to continue.\n");
 +
-+#ifndef __iwl_debug_h__
-+#define __iwl_debug_h__
++		iwl4965_set_rxon_chain(priv);
++#ifdef CONFIG_IWL_QOS
++		iwl_reset_qos(priv);
++#endif /* CONFIG_IWL_QOS */
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+extern u32 iwl_debug_level;
-+#define IWL_DEBUG(level, fmt, args...) \
-+do { if (iwl_debug_level & (level)) \
-+  printk(KERN_ERR DRV_NAME": %c %s " fmt, \
-+	 in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
++		/* FIXME: what should be the assoc_id for AP? */
++		priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
++		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
++			priv->staging_rxon.flags |=
++				RXON_FLG_SHORT_PREAMBLE_MSK;
++		else
++			priv->staging_rxon.flags &=
++				~RXON_FLG_SHORT_PREAMBLE_MSK;
 +
-+#define IWL_DEBUG_LIMIT(level, fmt, args...) \
-+do { if ((iwl_debug_level & (level)) && net_ratelimit()) \
-+  printk(KERN_ERR DRV_NAME": %c %s " fmt, \
-+	 in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
-+#else
-+static inline void IWL_DEBUG(int level, const char *fmt, ...)
-+{
++		if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
++			if (priv->assoc_capability &
++				WLAN_CAPABILITY_SHORT_SLOT_TIME)
++				priv->staging_rxon.flags |=
++					RXON_FLG_SHORT_SLOT_MSK;
++			else
++				priv->staging_rxon.flags &=
++					~RXON_FLG_SHORT_SLOT_MSK;
++
++			if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
++				priv->staging_rxon.flags &=
++					~RXON_FLG_SHORT_SLOT_MSK;
++		}
++		/* restore RXON assoc */
++		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
++		iwl_commit_rxon(priv);
++		iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
++		iwl_send_beacon_cmd(priv);
++	} else
++		iwl_send_beacon_cmd(priv);
++
++	/* FIXME - we need to add code here to detect a totally new
++	 * configuration, reset the AP, unassoc, rxon timing, assoc,
++	 * clear sta table, add BCAST sta... */
 +}
-+static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
++
++static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
++				    struct ieee80211_if_conf *conf)
 +{
-+}
-+#endif				/* CONFIG_IWLWIFI_DEBUG */
++	struct iwl_priv *priv = hw->priv;
++	unsigned long flags;
++	int rc;
 +
-+/*
-+ * To use the debug system;
-+ *
-+ * If you are defining a new debug classification, simply add it to the #define
-+ * list here in the form of:
-+ *
-+ * #define IWL_DL_xxxx VALUE
-+ *
-+ * shifting value to the left one bit from the previous entry.  xxxx should be
-+ * the name of the classification (for example, WEP)
-+ *
-+ * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
-+ * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
-+ * to send output to that classification.
-+ *
-+ * To add your debug level to the list of levels seen when you perform
-+ *
-+ * % cat /proc/net/ipw/debug_level
-+ *
-+ * you simply need to add your entry to the iwl_debug_levels array.
-+ *
-+ * If you do not see debug_level in /proc/net/ipw then you do not have
-+ * CONFIG_IWLWIFI_DEBUG defined in your kernel configuration
-+ *
-+ */
++	if (conf == NULL)
++		return -EIO;
++
++	if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
++	    (!conf->beacon || !conf->ssid_len)) {
++		IWL_DEBUG_MAC80211
++		    ("Leaving in AP mode because HostAPD is not ready.\n");
++		return 0;
++	}
++
++	mutex_lock(&priv->mutex);
++
++	IWL_DEBUG_MAC80211("enter: interface id %d\n", if_id);
++	if (conf->bssid)
++		IWL_DEBUG_MAC80211("bssid: " MAC_FMT "\n",
++				   MAC_ARG(conf->bssid));
 +
-+#define IWL_DL_INFO          (1<<0)
-+#define IWL_DL_MAC80211      (1<<1)
-+#define IWL_DL_HOST_COMMAND  (1<<2)
-+#define IWL_DL_STATE         (1<<3)
++	if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
++	    !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
++		IWL_DEBUG_MAC80211("leave - scanning\n");
++		mutex_unlock(&priv->mutex);
++		return 0;
++	}
 +
-+#define IWL_DL_RADIO         (1<<7)
-+#define IWL_DL_POWER         (1<<8)
-+#define IWL_DL_TEMP          (1<<9)
++	if (priv->interface_id != if_id) {
++		IWL_DEBUG_MAC80211("leave - interface_id != if_id\n");
++		mutex_unlock(&priv->mutex);
++		return 0;
++	}
 +
-+#define IWL_DL_NOTIF         (1<<10)
-+#define IWL_DL_SCAN          (1<<11)
-+#define IWL_DL_ASSOC         (1<<12)
-+#define IWL_DL_DROP          (1<<13)
++	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
++		if (!conf->bssid) {
++			conf->bssid = priv->mac_addr;
++			memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
++			IWL_DEBUG_MAC80211("bssid was set to: " MAC_FMT "\n",
++					   MAC_ARG(conf->bssid));
++		}
++		if (priv->ibss_beacon)
++			dev_kfree_skb(priv->ibss_beacon);
 +
-+#define IWL_DL_TXPOWER       (1<<14)
++		priv->ibss_beacon = conf->beacon;
++	}
 +
-+#define IWL_DL_AP            (1<<15)
++	if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
++	    !is_multicast_ether_addr(conf->bssid)) {
++		/* If there is currently a HW scan going on in the background
++		 * then we need to cancel it else the RXON below will fail. */
++		if (iwl_scan_cancel_timeout(priv, 100)) {
++			IWL_WARNING("Aborted scan still in progress "
++				    "after 100ms\n");
++			IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
++			mutex_unlock(&priv->mutex);
++			return -EAGAIN;
++		}
++		memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);
 +
-+#define IWL_DL_FW            (1<<16)
-+#define IWL_DL_RF_KILL       (1<<17)
-+#define IWL_DL_FW_ERRORS     (1<<18)
++		/* TODO: Audit driver for usage of these members and see
++		 * if mac80211 deprecates them (priv->bssid looks like it
++		 * shouldn't be there, but I haven't scanned the IBSS code
++		 * to verify) - jpk */
++		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
 +
-+#define IWL_DL_LED           (1<<19)
++		if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
++			iwl_config_ap(priv);
++		else {
++			priv->staging_rxon.filter_flags |=
++						RXON_FILTER_ASSOC_MSK;
++			rc = iwl_commit_rxon(priv);
++			if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
++				iwl_rxon_add_station(
++					priv, priv->active_rxon.bssid_addr, 1);
++		}
 +
-+#define IWL_DL_RATE          (1<<20)
++	} else {
++		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
++		iwl_commit_rxon(priv);
++	}
 +
-+#define IWL_DL_CALIB         (1<<21)
-+#define IWL_DL_WEP           (1<<22)
-+#define IWL_DL_TX            (1<<23)
-+#define IWL_DL_RX            (1<<24)
-+#define IWL_DL_ISR           (1<<25)
-+#define IWL_DL_HT            (1<<26)
-+#define IWL_DL_IO            (1<<27)
-+#define IWL_DL_11H           (1<<28)
++	spin_lock_irqsave(&priv->lock, flags);
++	if (!conf->ssid_len)
++		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
++	else
++		memcpy(priv->essid, conf->ssid, conf->ssid_len);
 +
-+#define IWL_DL_STATS         (1<<29)
-+#define IWL_DL_TX_REPLY      (1<<30)
-+#define IWL_DL_QOS           (1<<31)
++	priv->essid_len = conf->ssid_len;
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
-+#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
-+#define IWL_DEBUG_INFO(f, a...)    IWL_DEBUG(IWL_DL_INFO, f, ## a)
++	IWL_DEBUG_MAC80211("leave\n");
++	mutex_unlock(&priv->mutex);
 +
-+#define IWL_DEBUG_MAC80211(f, a...)     IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
-+#define IWL_DEBUG_TEMP(f, a...)   IWL_DEBUG(IWL_DL_TEMP, f, ## a)
-+#define IWL_DEBUG_SCAN(f, a...)   IWL_DEBUG(IWL_DL_SCAN, f, ## a)
-+#define IWL_DEBUG_RX(f, a...)     IWL_DEBUG(IWL_DL_RX, f, ## a)
-+#define IWL_DEBUG_TX(f, a...)     IWL_DEBUG(IWL_DL_TX, f, ## a)
-+#define IWL_DEBUG_ISR(f, a...)    IWL_DEBUG(IWL_DL_ISR, f, ## a)
-+#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
-+#define IWL_DEBUG_WEP(f, a...)    IWL_DEBUG(IWL_DL_WEP, f, ## a)
-+#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
-+#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
-+#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
-+#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
-+#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
-+#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
-+#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
-+#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
-+#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
-+#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
-+#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
-+#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
-+#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
-+#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
-+#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
-+#define IWL_DEBUG_QOS(f, a...)   IWL_DEBUG(IWL_DL_QOS, f, ## a)
-+#define IWL_DEBUG_RADIO(f, a...)  IWL_DEBUG(IWL_DL_RADIO, f, ## a)
-+#define IWL_DEBUG_POWER(f, a...)  IWL_DEBUG(IWL_DL_POWER, f, ## a)
-+#define IWL_DEBUG_11H(f, a...)  IWL_DEBUG(IWL_DL_11H, f, ## a)
++	return 0;
++}
 +
-+#endif
-diff --git a/drivers/net/wireless/iwl-eeprom.h b/drivers/net/wireless/iwl-eeprom.h
-new file mode 100644
-index 0000000..e473c97
---- /dev/null
-+++ b/drivers/net/wireless/iwl-eeprom.h
-@@ -0,0 +1,336 @@
-+/******************************************************************************
-+ *
-+ * This file is provided under a dual BSD/GPLv2 license.  When using or
-+ * redistributing this file, you may do so under either license.
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU Geeral Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ * BSD LICENSE
-+ *
-+ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ *  * Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ *  * Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in
-+ *    the documentation and/or other materials provided with the
-+ *    distribution.
-+ *  * Neither the name Intel Corporation nor the names of its
-+ *    contributors may be used to endorse or promote products derived
-+ *    from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ *****************************************************************************/
++static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
++				     struct ieee80211_if_init_conf *conf)
++{
++	struct iwl_priv *priv = hw->priv;
 +
-+#ifndef __iwl_eeprom_h__
-+#define __iwl_eeprom_h__
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+/*
-+ * This file defines EEPROM related constants, enums, and inline functions.
-+ *
-+ */
++	mutex_lock(&priv->mutex);
++	if (priv->interface_id == conf->if_id) {
++		priv->interface_id = 0;
++		memset(priv->bssid, 0, ETH_ALEN);
++		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
++		priv->essid_len = 0;
++	}
++	mutex_unlock(&priv->mutex);
 +
-+#define IWL_EEPROM_ACCESS_TIMEOUT	5000 /* uSec */
-+#define IWL_EEPROM_ACCESS_DELAY		10   /* uSec */
-+/* EEPROM field values */
-+#define ANTENNA_SWITCH_NORMAL     0
-+#define ANTENNA_SWITCH_INVERSE    1
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+enum {
-+	EEPROM_CHANNEL_VALID = (1 << 0),	/* usable for this SKU/geo */
-+	EEPROM_CHANNEL_IBSS = (1 << 1),	/* usable as an IBSS channel */
-+	/* Bit 2 Reserved */
-+	EEPROM_CHANNEL_ACTIVE = (1 << 3),	/* active scanning allowed */
-+	EEPROM_CHANNEL_RADAR = (1 << 4),	/* radar detection required */
-+	EEPROM_CHANNEL_WIDE = (1 << 5),
-+	EEPROM_CHANNEL_NARROW = (1 << 6),
-+	EEPROM_CHANNEL_DFS = (1 << 7),	/* dynamic freq selection candidate */
-+};
++}
 +
-+/* EEPROM field lengths */
-+#define EEPROM_BOARD_PBA_NUMBER_LENGTH                  11
++#define IWL_DELAY_NEXT_SCAN (HZ*2)
++static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
++{
++	int rc = 0;
++	unsigned long flags;
++	struct iwl_priv *priv = hw->priv;
 +
-+/* EEPROM field lengths */
-+#define EEPROM_BOARD_PBA_NUMBER_LENGTH                  11
-+#define EEPROM_REGULATORY_SKU_ID_LENGTH                 4
-+#define EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH         14
-+#define EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH         13
-+#define EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH         12
-+#define EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH         11
-+#define EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH         6
++	IWL_DEBUG_MAC80211("enter\n");
++
++	spin_lock_irqsave(&priv->lock, flags);
++
++	if (!iwl_is_ready_rf(priv)) {
++		rc = -EIO;
++		IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
++		goto out_unlock;
++	}
 +
-+#if IWL == 3945
-+#define EEPROM_REGULATORY_CHANNELS_LENGTH ( \
-+	EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH + \
-+	EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH + \
-+	EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH + \
-+	EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH + \
-+	EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH)
-+#elif IWL == 4965
-+#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS_LENGTH 7
-+#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS_LENGTH 11
-+#define EEPROM_REGULATORY_CHANNELS_LENGTH ( \
-+	EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH + \
-+	EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH + \
-+	EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH + \
-+	EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH + \
-+	EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH + \
-+	EEPROM_REGULATORY_BAND_24_FAT_CHANNELS_LENGTH + \
-+	EEPROM_REGULATORY_BAND_52_FAT_CHANNELS_LENGTH)
-+#endif
++	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {	/* APs don't scan */
++		rc = -EIO;
++		IWL_ERROR("ERROR: APs don't scan\n");
++		goto out_unlock;
++	}
 +
-+#define EEPROM_REGULATORY_NUMBER_OF_BANDS               5
++	/* if we just finished scan ask for delay */
++	if (priv->last_scan_jiffies &&
++	    time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
++		       jiffies)) {
++		rc = -EAGAIN;
++		goto out_unlock;
++	}
++	if (len) {
++		IWL_DEBUG_SCAN("direct scan for  "
++			       "%s [%d]\n ",
++			       iwl_escape_essid(ssid, len), (int)len);
 +
-+/* SKU Capabilities */
-+#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE                (1 << 0)
-+#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
-+#define EEPROM_SKU_CAP_OP_MODE_MRC                      (1 << 7)
++		priv->one_direct_scan = 1;
++		priv->direct_ssid_len = (u8)
++		    min((u8) len, (u8) IW_ESSID_MAX_SIZE);
++		memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
++	}
 +
-+/* *regulatory* channel data from eeprom, one for each channel */
-+struct iwl_eeprom_channel {
-+	u8 flags;		/* flags copied from EEPROM */
-+	s8 max_power_avg;	/* max power (dBm) on this chnl, limit 31 */
-+} __attribute__ ((packed));
++	rc = iwl_scan_initiate(priv);
 +
-+/*
-+ * Mapping of a Tx power level, at factory calibration temperature,
-+ *   to a radio/DSP gain table index.
-+ * One for each of 5 "sample" power levels in each band.
-+ * v_det is measured at the factory, using the 3945's built-in power amplifier
-+ *   (PA) output voltage detector.  This same detector is used during Tx of
-+ *   long packets in normal operation to provide feedback as to proper output
-+ *   level.
-+ * Data copied from EEPROM.
-+ */
-+struct iwl_eeprom_txpower_sample {
-+	u8 gain_index;		/* index into power (gain) setup table ... */
-+	s8 power;		/* ... for this pwr level for this chnl group */
-+	u16 v_det;		/* PA output voltage */
-+} __attribute__ ((packed));
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+/*
-+ * Mappings of Tx power levels -> nominal radio/DSP gain table indexes.
-+ * One for each channel group (a.k.a. "band") (1 for BG, 4 for A).
-+ * Tx power setup code interpolates between the 5 "sample" power levels
-+ *    to determine the nominal setup for a requested power level.
-+ * Data copied from EEPROM.
-+ * DO NOT ALTER THIS STRUCTURE!!!
-+ */
-+struct iwl_eeprom_txpower_group {
-+	struct iwl_eeprom_txpower_sample samples[5];	/* 5 power levels */
-+	s32 a, b, c, d, e;	/* coefficients for voltage->power
-+				 * formula (signed) */
-+	s32 Fa, Fb, Fc, Fd, Fe;	/* these modify coeffs based on
-+					 * frequency (signed) */
-+	s8 saturation_power;	/* highest power possible by h/w in this
-+				 * band */
-+	u8 group_channel;	/* "representative" channel # in this band */
-+	s16 temperature;	/* h/w temperature at factory calib this band
-+				 * (signed) */
-+} __attribute__ ((packed));
++out_unlock:
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+/*
-+ * Temperature-based Tx-power compensation data, not band-specific.
-+ * These coefficients are use to modify a/b/c/d/e coeffs based on
-+ *   difference between current temperature and factory calib temperature.
-+ * Data copied from EEPROM.
-+ */
-+struct iwl_eeprom_temperature_corr {
-+	u32 Ta;
-+	u32 Tb;
-+	u32 Tc;
-+	u32 Td;
-+	u32 Te;
-+} __attribute__ ((packed));
++	return rc;
++}
 +
-+#if IWL == 4965
-+#define EEPROM_TX_POWER_TX_CHAINS      (2)
-+#define EEPROM_TX_POWER_BANDS          (8)
-+#define EEPROM_TX_POWER_MEASUREMENTS   (3)
-+#define EEPROM_TX_POWER_VERSION        (2)
-+#define EEPROM_TX_POWER_VERSION_NEW    (5)
++static int iwl_mac_set_key(struct ieee80211_hw *hw, set_key_cmd cmd, u8 *addr,
++			   struct ieee80211_key_conf *key, int aid)
++{
++	struct iwl_priv *priv = hw->priv;
++	int rc = 0;
++	u8 sta_id;
 +
-+struct iwl_eeprom_calib_measure {
-+	u8 temperature;
-+	u8 gain_idx;
-+	u8 actual_pow;
-+	s8 pa_det;
-+} __attribute__ ((packed));
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+struct iwl_eeprom_calib_ch_info {
-+	u8 ch_num;
-+	struct iwl_eeprom_calib_measure measurements[EEPROM_TX_POWER_TX_CHAINS]
-+		[EEPROM_TX_POWER_MEASUREMENTS];
-+} __attribute__ ((packed));
++	if (!iwl_param_hwcrypto) {
++		IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
++		return -EOPNOTSUPP;
++	}
 +
-+struct iwl_eeprom_calib_subband_info {
-+	u8 ch_from;
-+	u8 ch_to;
-+	struct iwl_eeprom_calib_ch_info ch1;
-+	struct iwl_eeprom_calib_ch_info ch2;
-+} __attribute__ ((packed));
++	sta_id = iwl_hw_find_station(priv, addr);
++	if (sta_id == IWL_INVALID_STATION) {
++		IWL_DEBUG_MAC80211("leave - " MAC_FMT " not in station map.\n",
++				   MAC_ARG(addr));
++		return -EINVAL;
++	}
 +
-+struct iwl_eeprom_calib_info {
-+	u8 saturation_power24;
-+	u8 saturation_power52;
-+	s16 voltage;		/* signed */
-+	struct iwl_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS];
-+} __attribute__ ((packed));
++	mutex_lock(&priv->mutex);
 +
-+#endif
++	if (cmd == SET_KEY)
++		rc = iwl_update_sta_key_info(priv, key, sta_id);
++	else
++		rc = -EINVAL;
 +
-+struct iwl_eeprom {
-+	u8 reserved0[16];
-+#define EEPROM_DEVICE_ID                    (2*0x08)	/* 2 bytes */
-+	u16 device_id;	/* abs.ofs: 16 */
-+	u8 reserved1[2];
-+#define EEPROM_PMC                          (2*0x0A)	/* 2 bytes */
-+	u16 pmc;		/* abs.ofs: 20 */
-+	u8 reserved2[20];
-+#define EEPROM_MAC_ADDRESS                  (2*0x15)	/* 6  bytes */
-+	u8 mac_address[6];	/* abs.ofs: 42 */
-+	u8 reserved3[58];
-+#define EEPROM_BOARD_REVISION               (2*0x35)	/* 2  bytes */
-+	u16 board_revision;	/* abs.ofs: 106 */
-+	u8 reserved4[11];
-+#define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1)	/* 9  bytes */
-+	u8 board_pba_number[9];	/* abs.ofs: 119 */
-+	u8 reserved5[8];
-+#define EEPROM_VERSION                      (2*0x44)	/* 2  bytes */
-+	u16 version;		/* abs.ofs: 136 */
-+#define EEPROM_SKU_CAP                      (2*0x45)	/* 1  bytes */
-+	u8 sku_cap;		/* abs.ofs: 138 */
-+#define EEPROM_LEDS_MODE                    (2*0x45+1)	/* 1  bytes */
-+	u8 leds_mode;		/* abs.ofs: 139 */
-+#define EEPROM_OEM_MODE                     (2*0x46)	/* 2  bytes */
-+	u16 oem_mode;
-+#define EEPROM_WOWLAN_MODE                  (2*0x47)	/* 2  bytes */
-+	u16 wowlan_mode;	/* abs.ofs: 142 */
-+#define EEPROM_LEDS_TIME_INTERVAL           (2*0x48)	/* 2  bytes */
-+	u16 leds_time_interval;	/* abs.ofs: 144 */
-+#define EEPROM_LEDS_OFF_TIME                (2*0x49)	/* 1  bytes */
-+	u8 leds_off_time;	/* abs.ofs: 146 */
-+#define EEPROM_LEDS_ON_TIME                 (2*0x49+1)	/* 1  bytes */
-+	u8 leds_on_time;	/* abs.ofs: 147 */
-+#define EEPROM_ALMGOR_M_VERSION             (2*0x4A)	/* 1  bytes */
-+	u8 almgor_m_version;	/* abs.ofs: 148 */
-+#define EEPROM_ANTENNA_SWITCH_TYPE          (2*0x4A+1)	/* 1  bytes */
-+	u8 antenna_switch_type;	/* abs.ofs: 149 */
-+#if IWL == 3945
-+	u8 reserved6[42];
-+#else
-+	u8 reserved6[8];
-+#define EEPROM_4965_BOARD_REVISION          (2*0x4F)	/* 2 bytes */
-+	u16 board_revision_4965;	/* abs.ofs: 158 */
-+	u8 reserved7[13];
-+#define EEPROM_4965_BOARD_PBA               (2*0x56+1)	/* 9 bytes */
-+	u8 board_pba_number_4965[9];	/* abs.ofs: 173 */
-+	u8 reserved8[10];
-+#endif
-+#define EEPROM_REGULATORY_SKU_ID            (2*0x60)	/* 4  bytes */
-+	u8 sku_id[4];		/* abs.ofs: 192 */
-+#define EEPROM_REGULATORY_BAND_1            (2*0x62)	/* 2  bytes */
-+	u16 band_1_count;	/* abs.ofs: 196 */
-+#define EEPROM_REGULATORY_BAND_1_CHANNELS   (2*0x63)	/* 28 bytes */
-+	struct iwl_eeprom_channel band_1_channels[14];	/* abs.ofs: 196 */
-+#define EEPROM_REGULATORY_BAND_2            (2*0x71)	/* 2  bytes */
-+	u16 band_2_count;	/* abs.ofs: 226 */
-+#define EEPROM_REGULATORY_BAND_2_CHANNELS   (2*0x72)	/* 26 bytes */
-+	struct iwl_eeprom_channel band_2_channels[13];	/* abs.ofs: 228 */
-+#define EEPROM_REGULATORY_BAND_3            (2*0x7F)	/* 2  bytes */
-+	u16 band_3_count;	/* abs.ofs: 254 */
-+#define EEPROM_REGULATORY_BAND_3_CHANNELS   (2*0x80)	/* 24 bytes */
-+	struct iwl_eeprom_channel band_3_channels[12];	/* abs.ofs: 256 */
-+#define EEPROM_REGULATORY_BAND_4            (2*0x8C)	/* 2  bytes */
-+	u16 band_4_count;	/* abs.ofs: 280 */
-+#define EEPROM_REGULATORY_BAND_4_CHANNELS   (2*0x8D)	/* 22 bytes */
-+	struct iwl_eeprom_channel band_4_channels[11];	/* abs.ofs: 282 */
-+#define EEPROM_REGULATORY_BAND_5            (2*0x98)	/* 2  bytes */
-+	u16 band_5_count;	/* abs.ofs: 304 */
-+#define EEPROM_REGULATORY_BAND_5_CHANNELS   (2*0x99)	/* 12 bytes */
-+	struct iwl_eeprom_channel band_5_channels[6];	/* abs.ofs: 306 */
++	if (!rc) {
++		iwl_set_rxon_hwcrypto(priv, 1);
++		iwl_commit_rxon(priv);
++		key->flags &= ~IEEE80211_KEY_FORCE_SW_ENCRYPT;
++		key->hw_key_idx = sta_id;
++		IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n");
++	}
 +
-+/* From here on out the EEPROM diverges between the 4965 and the 3945 */
-+#if IWL == 3945
++	IWL_DEBUG_MAC80211("leave\n");
++	mutex_unlock(&priv->mutex);
 +
-+	u8 reserved9[194];
++	return rc;
++}
 +
-+#define EEPROM_TXPOWER_CALIB_GROUP0 0x200
-+#define EEPROM_TXPOWER_CALIB_GROUP1 0x240
-+#define EEPROM_TXPOWER_CALIB_GROUP2 0x280
-+#define EEPROM_TXPOWER_CALIB_GROUP3 0x2c0
-+#define EEPROM_TXPOWER_CALIB_GROUP4 0x300
-+#define IWL_NUM_TX_CALIB_GROUPS 5
-+	struct iwl_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
-+/* abs.ofs: 512 */
-+#define EEPROM_CALIB_TEMPERATURE_CORRECT 0x340
-+	struct iwl_eeprom_temperature_corr corrections;	/* abs.ofs: 832 */
-+	u8 reserved16[172];	/* fill out to full 1024 byte block */
++static int iwl_mac_conf_tx(struct ieee80211_hw *hw, int queue,
++			   const struct ieee80211_tx_queue_params *params)
++{
++	struct iwl_priv *priv = hw->priv;
++#ifdef CONFIG_IWLWIFI_QOS
++	unsigned long flags;
++	int q;
++#endif /* CONFIG_IWL_QOS */
 +
-+/* 4965AGN adds fat channel support */
-+#elif IWL == 4965
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+	u8 reserved10[2];
-+#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0)	/* 14 bytes */
-+	struct iwl_eeprom_channel band_24_channels[7];	/* abs.ofs: 320 */
-+	u8 reserved11[2];
-+#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8)	/* 22 bytes */
-+	struct iwl_eeprom_channel band_52_channels[11];	/* abs.ofs: 336 */
-+	u8 reserved12[6];
-+#define EEPROM_CALIB_VERSION_OFFSET            (2*0xB6)	/* 2 bytes */
-+	u16 calib_version;	/* abs.ofs: 364 */
-+	u8 reserved13[2];
-+#define EEPROM_SATURATION_POWER_OFFSET         (2*0xB8)	/* 2 bytes */
-+	u16 satruation_power;	/* abs.ofs: 368 */
-+	u8 reserved14[94];
-+#define EEPROM_IWL_CALIB_TXPOWER_OFFSET        (2*0xE8)	/* 48  bytes */
-+	struct iwl_eeprom_calib_info calib_info;	/* abs.ofs: 464 */
++	if (!iwl_is_ready_rf(priv)) {
++		IWL_DEBUG_MAC80211("leave - RF not ready\n");
++		return -EIO;
++	}
 +
-+	u8 reserved16[140];	/* fill out to full 1024 byte block */
++	if (queue >= AC_NUM) {
++		IWL_DEBUG_MAC80211("leave - queue >= AC_NUM %d\n", queue);
++		return 0;
++	}
 +
-+#endif
++#ifdef CONFIG_IWLWIFI_QOS
++	if (!priv->qos_data.qos_enable) {
++		priv->qos_data.qos_active = 0;
++		IWL_DEBUG_MAC80211("leave - qos not enabled\n");
++		return 0;
++	}
++	q = AC_NUM - 1 - queue;
 +
-+} __attribute__ ((packed));
++	spin_lock_irqsave(&priv->lock, flags);
 +
-+#define IWL_EEPROM_IMAGE_SIZE 1024
++	priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
++	priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
++	priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
++	priv->qos_data.def_qos_parm.ac[q].edca_txop =
++			cpu_to_le16((params->burst_time * 100));
 +
-+#endif
-diff --git a/drivers/net/wireless/iwl-helpers.h b/drivers/net/wireless/iwl-helpers.h
-new file mode 100644
-index 0000000..e2a8d95
---- /dev/null
-+++ b/drivers/net/wireless/iwl-helpers.h
-@@ -0,0 +1,255 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ipw3945 project, as well
-+ * as portions of the ieee80211 subsystem header files.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
++	priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
++	priv->qos_data.qos_active = 1;
 +
-+#ifndef __iwl_helpers_h__
-+#define __iwl_helpers_h__
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+#include <linux/ctype.h>
++	mutex_lock(&priv->mutex);
++	if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
++		iwl_activate_qos(priv, 1);
++	else if (priv->assoc_id && iwl_is_associated(priv))
++		iwl_activate_qos(priv, 0);
 +
-+/*
-+ * The structures defined by the hardware/uCode interface
-+ * have bit-wise operations.  For each bit-field there is
-+ * a data symbol in the structure, the start bit position
-+ * and the length of the bit-field.
-+ *
-+ * iwl_get_bits and iwl_set_bits will return or set the
-+ * appropriate bits on a 32-bit value.
-+ *
-+ * IWL_GET_BITS and IWL_SET_BITS use symbol expansion to
-+ * expand out to the appropriate call to iwl_get_bits
-+ * and iwl_set_bits without having to reference all of the
-+ * numerical constants and defines provided in the hardware
-+ * definition
-+ */
++	mutex_unlock(&priv->mutex);
 +
-+/**
-+ * iwl_get_bits - Extract a hardware bit-field value
-+ * @src: source hardware value (__le32)
-+ * @pos: bit-position (0-based) of first bit of value
-+ * @len: length of bit-field
-+ *
-+ * iwl_get_bits will return the bit-field in cpu endian ordering.
-+ *
-+ * NOTE:  If used from IWL_GET_BITS then pos and len are compile-constants and
-+ *        will collapse to minimal code by the compiler.
-+ */
-+static inline u32 iwl_get_bits(__le32 src, u8 pos, u8 len)
-+{
-+	u32 tmp = le32_to_cpu(src);
++#endif /*CONFIG_IWLWIFI_QOS */
 +
-+	tmp >>= pos;
-+	tmp &= (1UL << len) - 1;
-+	return tmp;
++	IWL_DEBUG_MAC80211("leave\n");
++	return 0;
 +}
 +
-+/**
-+ * iwl_set_bits - Set a hardware bit-field value
-+ * @dst: Address of __le32 hardware value
-+ * @pos: bit-position (0-based) of first bit of value
-+ * @len: length of bit-field
-+ * @val: cpu endian value to encode into the bit-field
-+ *
-+ * iwl_set_bits will encode val into dst, masked to be len bits long at bit
-+ * position pos.
-+ *
-+ * NOTE:  If used IWL_SET_BITS pos and len will be compile-constants and
-+ *        will collapse to minimal code by the compiler.
-+ */
-+static inline void iwl_set_bits(__le32 *dst, u8 pos, u8 len, int val)
++static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
++				struct ieee80211_tx_queue_stats *stats)
 +{
-+	u32 tmp = le32_to_cpu(*dst);
++	struct iwl_priv *priv = hw->priv;
++	int i, avail;
++	struct iwl_tx_queue *txq;
++	struct iwl_queue *q;
++	unsigned long flags;
 +
-+	tmp &= ~(((1UL << len) - 1) << pos);
-+	tmp |= (val & ((1UL << len) - 1)) << pos;
-+	*dst = cpu_to_le32(tmp);
-+}
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+static inline void iwl_set_bits16(__le16 *dst, u8 pos, u8 len, int val)
-+{
-+	u16 tmp = le16_to_cpu(*dst);
++	if (!iwl_is_ready_rf(priv)) {
++		IWL_DEBUG_MAC80211("leave - RF not ready\n");
++		return -EIO;
++	}
 +
-+	tmp &= ~((1UL << (pos + len)) - (1UL << pos));
-+	tmp |= (val & ((1UL << len) - 1)) << pos;
-+	*dst = cpu_to_le16(tmp);
-+}
++	spin_lock_irqsave(&priv->lock, flags);
 +
-+/*
-+ * The bit-field definitions in iwl-xxxx-hw.h are in the form of:
-+ *
-+ * struct example {
-+ *         __le32 val1;
-+ * #define IWL_name_POS 8
-+ * #define IWL_name_LEN 4
-+ * #define IWL_name_SYM val1
-+ * };
-+ *
-+ * The IWL_SET_BITS and IWL_GET_BITS macros are provided to allow the driver
-+ * to call:
-+ *
-+ * struct example bar;
-+ * u32 val = IWL_GET_BITS(bar, name);
-+ * val = val * 2;
-+ * IWL_SET_BITS(bar, name, val);
-+ *
-+ * All cpu / host ordering, masking, and shifts are performed by the macros
-+ * and iwl_{get,set}_bits.
-+ *
-+ */
-+#define IWL_SET_BITS(s, sym, v) \
-+	iwl_set_bits(&(s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
-+		     IWL_ ## sym ## _LEN, (v))
++	for (i = 0; i < AC_NUM; i++) {
++		txq = &priv->txq[i];
++		q = &txq->q;
++		avail = iwl_queue_space(q);
 +
-+#define IWL_SET_BITS16(s, sym, v) \
-+	iwl_set_bits16(&(s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
-+		       IWL_ ## sym ## _LEN, (v))
++		stats->data[i].len = q->n_window - avail;
++		stats->data[i].limit = q->n_window - q->high_mark;
++		stats->data[i].count = q->n_window;
 +
-+#define IWL_GET_BITS(s, sym) \
-+	iwl_get_bits((s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
-+		      IWL_ ## sym ## _LEN)
++	}
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+#define KELVIN_TO_CELSIUS(x) ((x)-273)
-+#define CELSIUS_TO_KELVIN(x) ((x)+273)
++	return 0;
++}
 +
-+#define IEEE80211_CHAN_W_RADAR_DETECT 0x00000010
++static int iwl_mac_get_stats(struct ieee80211_hw *hw,
++			     struct ieee80211_low_level_stats *stats)
++{
++	IWL_DEBUG_MAC80211("enter\n");
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+static inline struct ieee80211_conf *ieee80211_get_hw_conf(
-+	struct ieee80211_hw *hw)
++	return 0;
++}
++
++static u64 iwl_mac_get_tsf(struct ieee80211_hw *hw)
 +{
-+	return &hw->conf;
++	IWL_DEBUG_MAC80211("enter\n");
++	IWL_DEBUG_MAC80211("leave\n");
++
++	return 0;
 +}
 +
-+#define QOS_CONTROL_LEN 2
++static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
++{
++	struct iwl_priv *priv = hw->priv;
++	unsigned long flags;
 +
-+#define IEEE80211_STYPE_BACK_REQ	0x0080
-+#define IEEE80211_STYPE_BACK		0x0090
++	mutex_lock(&priv->mutex);
++	IWL_DEBUG_MAC80211("enter\n");
 +
++	priv->lq_mngr.lq_ready = 0;
++#ifdef CONFIG_IWLWIFI_HT
++	spin_lock_irqsave(&priv->lock, flags);
++	memset(&priv->current_assoc_ht, 0, sizeof(struct sta_ht_info));
++	spin_unlock_irqrestore(&priv->lock, flags);
++#ifdef CONFIG_IWLWIFI_HT_AGG
++/*	if (priv->lq_mngr.agg_ctrl.granted_ba)
++		iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);*/
 +
-+static inline int ieee80211_is_management(u16 fc)
-+{
-+	return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT;
-+}
++	memset(&(priv->lq_mngr.agg_ctrl), 0, sizeof(struct iwl_agg_control));
++	priv->lq_mngr.agg_ctrl.tid_traffic_load_threshold = 10;
++	priv->lq_mngr.agg_ctrl.ba_timeout = 5000;
++	priv->lq_mngr.agg_ctrl.auto_agg = 1;
 +
-+static inline int ieee80211_is_control(u16 fc)
-+{
-+	return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL;
-+}
++	if (priv->lq_mngr.agg_ctrl.auto_agg)
++		priv->lq_mngr.agg_ctrl.requested_ba = TID_ALL_ENABLED;
++#endif /*CONFIG_IWLWIFI_HT_AGG */
++#endif /* CONFIG_IWLWIFI_HT */
 +
-+static inline int ieee80211_is_data(u16 fc)
-+{
-+	return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA;
-+}
++#ifdef CONFIG_IWLWIFI_QOS
++	iwl_reset_qos(priv);
++#endif
 +
-+static inline int ieee80211_is_back_request(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ);
-+}
++	cancel_delayed_work(&priv->post_associate);
 +
-+static inline int ieee80211_is_probe_response(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP);
-+}
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->assoc_id = 0;
++	priv->assoc_capability = 0;
++	priv->call_post_assoc_from_beacon = 0;
++	priv->assoc_station_added = 0;
 +
-+static inline int ieee80211_is_probe_request(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_REQ);
-+}
++	/* new association get rid of ibss beacon skb */
++	if (priv->ibss_beacon)
++		dev_kfree_skb(priv->ibss_beacon);
 +
-+static inline int ieee80211_is_beacon(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON);
-+}
++	priv->ibss_beacon = NULL;
 +
-+static inline int ieee80211_is_atim(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ATIM);
-+}
++	priv->beacon_int = priv->hw->conf.beacon_int;
++	priv->timestamp1 = 0;
++	priv->timestamp0 = 0;
++	if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
++		priv->beacon_int = 0;
 +
-+static inline int ieee80211_is_assoc_request(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ);
-+}
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+static inline int ieee80211_is_assoc_response(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_RESP);
-+}
++	/* Per mac80211.h: This is only used in IBSS mode... */
++	if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
++		IWL_DEBUG_MAC80211("leave - not in IBSS\n");
++		mutex_unlock(&priv->mutex);
++		return;
++	}
 +
-+static inline int ieee80211_is_auth(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ);
-+}
++	if (!iwl_is_ready_rf(priv)) {
++		IWL_DEBUG_MAC80211("leave - not ready\n");
++		mutex_unlock(&priv->mutex);
++		return;
++	}
 +
-+static inline int ieee80211_is_deauth(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ);
-+}
++	priv->only_active_channel = 0;
 +
-+static inline int ieee80211_is_disassoc(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ);
-+}
++	iwl_set_rate(priv);
 +
-+static inline int ieee80211_is_reassoc_request(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ);
-+}
++	mutex_unlock(&priv->mutex);
 +
-+static inline int ieee80211_is_reassoc_response(u16 fc)
-+{
-+	return ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
-+	       ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_RESP);
-+}
++	IWL_DEBUG_MAC80211("leave\n");
 +
-+static inline int iwl_check_bits(unsigned long field, unsigned long mask)
-+{
-+	return ((field & mask) == mask) ? 1 : 0;
 +}
 +
-+static inline unsigned long elapsed_jiffies(unsigned long start,
-+					    unsigned long end)
++static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
++				 struct ieee80211_tx_control *control)
 +{
-+	if (end > start)
-+		return end - start;
-+
-+	return end + (MAX_JIFFY_OFFSET - start);
-+}
++	struct iwl_priv *priv = hw->priv;
++	unsigned long flags;
 +
-+#endif				/* __iwl_helpers_h__ */
-diff --git a/drivers/net/wireless/iwl-hw.h b/drivers/net/wireless/iwl-hw.h
-new file mode 100644
-index 0000000..3743cdb
---- /dev/null
-+++ b/drivers/net/wireless/iwl-hw.h
-@@ -0,0 +1,717 @@
-+/******************************************************************************
-+ *
-+ * This file is provided under a dual BSD/GPLv2 license.  When using or
-+ * redistributing this file, you may do so under either license.
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU Geeral Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ * BSD LICENSE
-+ *
-+ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ *  * Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ *  * Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in
-+ *    the documentation and/or other materials provided with the
-+ *    distribution.
-+ *  * Neither the name Intel Corporation nor the names of its
-+ *    contributors may be used to endorse or promote products derived
-+ *    from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *****************************************************************************/
++	mutex_lock(&priv->mutex);
++	IWL_DEBUG_MAC80211("enter\n");
 +
-+#ifndef	__iwlwifi_hw_h__
-+#define __iwlwifi_hw_h__
++	if (!iwl_is_ready_rf(priv)) {
++		IWL_DEBUG_MAC80211("leave - RF not ready\n");
++		mutex_unlock(&priv->mutex);
++		return -EIO;
++	}
 +
-+/*
-+ * This file defines hardware constants common to 3945 and 4965.
-+ *
-+ * Device-specific constants are defined in iwl-3945-hw.h and iwl-4965-hw.h,
-+ * although this file contains a few definitions for which the .c
-+ * implementation is the same for 3945 and 4965, except for the value of
-+ * a constant.
-+ *
-+ * uCode API constants are defined in iwl-commands.h.
-+ *
-+ * NOTE:  DO NOT PUT OS IMPLEMENTATION-SPECIFIC DECLARATIONS HERE
-+ *
-+ * The iwl-*hw.h (and files they include) files should remain OS/driver
-+ * implementation independent, declaring only the hardware interface.
-+ */
++	if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
++		IWL_DEBUG_MAC80211("leave - not IBSS\n");
++		mutex_unlock(&priv->mutex);
++		return -EIO;
++	}
 +
-+/* uCode queue management definitions */
-+#define IWL_CMD_QUEUE_NUM       4
-+#define IWL_CMD_FIFO_NUM        4
-+#define IWL_BACK_QUEUE_FIRST_ID 7
++	spin_lock_irqsave(&priv->lock, flags);
 +
-+/* Tx rates */
-+#define IWL_CCK_RATES 4
-+#define IWL_OFDM_RATES 8
++	if (priv->ibss_beacon)
++		dev_kfree_skb(priv->ibss_beacon);
 +
-+#if IWL == 3945
-+#define IWL_HT_RATES 0
-+#elif IWL == 4965
-+#define IWL_HT_RATES 16
-+#endif
++	priv->ibss_beacon = skb;
 +
-+#define IWL_MAX_RATES  (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES)
++	priv->assoc_id = 0;
 +
-+/* Time constants */
-+#define SHORT_SLOT_TIME 9
-+#define LONG_SLOT_TIME 20
++	IWL_DEBUG_MAC80211("leave\n");
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+/* RSSI to dBm */
-+#if IWL == 3945
-+#define IWL_RSSI_OFFSET	95
-+#elif IWL == 4965
-+#define IWL_RSSI_OFFSET	44
++#ifdef CONFIG_IWLWIFI_QOS
++	iwl_reset_qos(priv);
 +#endif
 +
-+#include "iwl-eeprom.h"
-+#include "iwl-commands.h"
-+
-+#define PCI_LINK_CTRL      0x0F0
-+#define PCI_POWER_SOURCE   0x0C8
-+#define PCI_REG_WUM8       0x0E8
++	queue_work(priv->workqueue, &priv->post_associate.work);
 +
-+/* register and values */
-+/* base */
-+#define CSR_BASE    (0x0)
-+#define HBUS_BASE   (0x400)
-+#define FH_BASE     (0x800)
++	mutex_unlock(&priv->mutex);
 +
-+#define HBUS_TARG_MBX_C         (HBUS_BASE+0x030)
++	return 0;
++}
 +
-+/*=== CSR (control and status registers) ===*/
++#ifdef CONFIG_IWLWIFI_HT
++union ht_cap_info {
++	struct {
++		u16 advanced_coding_cap		:1;
++		u16 supported_chan_width_set	:1;
++		u16 mimo_power_save_mode	:2;
++		u16 green_field			:1;
++		u16 short_GI20			:1;
++		u16 short_GI40			:1;
++		u16 tx_stbc			:1;
++		u16 rx_stbc			:1;
++		u16 beam_forming		:1;
++		u16 delayed_ba			:1;
++		u16 maximal_amsdu_size		:1;
++		u16 cck_mode_at_40MHz		:1;
++		u16 psmp_support		:1;
++		u16 stbc_ctrl_frame_support	:1;
++		u16 sig_txop_protection_support	:1;
++	};
++	u16 val;
++} __attribute__ ((packed));
 +
-+#define CSR_SW_VER              (CSR_BASE+0x000)
-+#define CSR_HW_IF_CONFIG_REG    (CSR_BASE+0x000) /* hardware interface config */
-+#define CSR_INT_COALESCING      (CSR_BASE+0x004) /* accum ints, 32-usec units */
-+#define CSR_INT                 (CSR_BASE+0x008) /* host interrupt status/ack */
-+#define CSR_INT_MASK            (CSR_BASE+0x00c) /* host interrupt enable */
-+#define CSR_FH_INT_STATUS       (CSR_BASE+0x010) /* busmaster int status/ack*/
-+#define CSR_GPIO_IN             (CSR_BASE+0x018) /* read external chip pins */
-+#define CSR_RESET               (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
-+#define CSR_GP_CNTRL            (CSR_BASE+0x024)
-+/* 0x028 - reserved */
-+#define CSR_EEPROM_REG          (CSR_BASE+0x02c)
-+#define CSR_EEPROM_REG_READ_VALID_MSK	0x00000001
-+#define CSR_EEPROM_REG_BIT_CMD		0x00000002
++union ht_param_info{
++	struct {
++		u8 max_rx_ampdu_factor	:2;
++		u8 mpdu_density		:3;
++		u8 reserved		:3;
++	};
++	u8 val;
++} __attribute__ ((packed));
 +
-+#define CSR_EEPROM_GP           (CSR_BASE+0x030)
-+#define CSR_EEPROM_GP_VALID_MSK		0x00000006
-+#define CSR_EEPROM_GP_BAD_SIGNATURE	0x00000000
-+#define CSR_EEPROM_GP_IF_OWNER_MSK	0x00000180
++union ht_exra_param_info {
++	struct {
++		u8 ext_chan_offset		:2;
++		u8 tx_chan_width		:1;
++		u8 rifs_mode			:1;
++		u8 controlled_access_only	:1;
++		u8 service_interval_granularity	:3;
++	};
++	u8 val;
++} __attribute__ ((packed));
 +
-+#define CSR_UCODE_DRV_GP1       (CSR_BASE+0x054)
-+#define CSR_UCODE_DRV_GP1_SET   (CSR_BASE+0x058)
-+#define CSR_UCODE_DRV_GP1_CLR   (CSR_BASE+0x05c)
-+#define CSR_UCODE_DRV_GP2       (CSR_BASE+0x060)
-+#define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
-+#define CSR_ANA_PLL_CFG         (CSR_BASE+0x20c)
-+#define CSR_HW_REV_WA_REG	(CSR_BASE+0x22C)
++union ht_operation_mode{
++	struct {
++		u16 op_mode	:2;
++		u16 non_GF	:1;
++		u16 reserved	:13;
++	};
++	u16 val;
++} __attribute__ ((packed));
 +
-+/**
-+ * BSM (Bootstrap State Machine)
-+ *
-+ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
-+ * in special SRAM that does not power down when the embedded control
-+ * processor is sleeping (e.g. for periodic power-saving shutdowns of radio).
-+ *
-+ * When powering back up after sleeps (or during initial uCode load), the BSM
-+ * internally loads the short bootstrap program from the special SRAM into the
-+ * embedded processor's instruction SRAM, and starts the processor so it runs
-+ * the bootstrap program.
-+ *
-+ * This bootstrap program loads (via PCI busmaster DMA) instructions and data
-+ * images for a uCode program from host DRAM locations.  The host driver
-+ * indicates DRAM locations and sizes for instruction and data images via the
-+ * four BSM_DRAM_* registers.  Once the bootstrap program loads the new program,
-+ * the new program starts automatically.
-+ *
-+ * The uCode used for open-source drivers includes two programs:
-+ *
-+ * 1)  Initialization -- performs hardware calibration and sets up some
-+ *     internal data, then notifies host via "initialize alive" notification
-+ *     (struct iwl_init_alive_resp) that it has completed all of its work.
-+ *     After signal from host, it then loads and starts the runtime program.
-+ *     The initialization program must be used when initially setting up the
-+ *     NIC after loading the driver.
-+ *
-+ * 2)  Runtime/Protocol -- performs all normal runtime operations.  This
-+ *     notifies host via "alive" notification (struct iwl_alive_resp) that it
-+ *     is ready to be used.
-+ *
-+ * When initializing the NIC, the host driver does the following procedure:
-+ *
-+ * 1)  Load bootstrap program (instructions only, no data image for bootstrap)
-+ *     into bootstrap memory.  Use dword writes starting at BSM_SRAM_LOWER_BOUND
-+ *
-+ * 2)  Point (via BSM_DRAM_*) to the "initialize" uCode data and instruction
-+ *     images in host DRAM.
-+ *
-+ * 3)  Set up BSM to copy from BSM SRAM into uCode instruction SRAM when asked:
-+ *     BSM_WR_MEM_SRC_REG = 0
-+ *     BSM_WR_MEM_DST_REG = RTC_INST_LOWER_BOUND
-+ *     BSM_WR_MEM_DWCOUNT_REG = # dwords in bootstrap instruction image
-+ *
-+ * 4)  Load bootstrap into instruction SRAM:
-+ *     BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START
-+ *
-+ * 5)  Wait for load completion:
-+ *     Poll BSM_WR_CTRL_REG for BSM_WR_CTRL_REG_BIT_START = 0
-+ *
-+ * 6)  Enable future boot loads whenever NIC's power management triggers it:
-+ *     BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START_EN
-+ *
-+ * 7)  Start the NIC by removing all reset bits:
-+ *     CSR_RESET = 0
-+ *
-+ *     The bootstrap uCode (already in instruction SRAM) loads initialization
-+ *     uCode.  Initialization uCode performs data initialization, sends
-+ *     "initialize alive" notification to host, and waits for a signal from
-+ *     host to load runtime code.
-+ *
-+ * 4)  Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction
-+ *     images in host DRAM.  The last register loaded must be the instruction
-+ *     bytecount register ("1" in MSbit tells initialization uCode to load
-+ *     the runtime uCode):
-+ *     BSM_DRAM_INST_BYTECOUNT_REG = bytecount | BSM_DRAM_INST_LOAD
-+ *
-+ * 5)  Wait for "alive" notification, then issue normal runtime commands.
-+ *
-+ * Data caching during power-downs:
-+ *
-+ * Just before the embedded controller powers down (e.g for automatic
-+ * power-saving modes, or for RFKILL), uCode stores (via PCI busmaster DMA)
-+ * a current snapshot of the embedded processor's data SRAM into host DRAM.
-+ * This caches the data while the embedded processor's memory is powered down.
-+ * Location and size are controlled by BSM_DRAM_DATA_* registers.
-+ *
-+ * NOTE:  Instruction SRAM does not need to be saved, since that doesn't
-+ *        change during operation; the original image (from uCode distribution
-+ *        file) can be used for reload.
-+ *
-+ * When powering back up, the BSM loads the bootstrap program.  Bootstrap looks
-+ * at the BSM_DRAM_* registers, which now point to the runtime instruction
-+ * image and the cached (modified) runtime data (*not* the initialization
-+ * uCode).  Bootstrap reloads these runtime images into SRAM, and restarts the
-+ * uCode from where it left off before the power-down.
-+ *
-+ * NOTE:  Initialization uCode does *not* run as part of the save/restore
-+ *        procedure.
-+ *
-+ * This save/restore method is mostly for autonomous power management during
-+ * normal operation (result of POWER_TABLE_CMD).  Platform suspend/resume and
-+ * RFKILL should use complete restarts (with total re-initialization) of uCode,
-+ * allowing total shutdown (including BSM memory).
-+ *
-+ * Note that, during normal operation, the host DRAM that held the initial
-+ * startup data for the runtime code is now being used as a backup data cache
-+ * for modified data!  If you need to completely re-initialize the NIC, make
-+ * sure that you use the runtime data image from the uCode distribution file,
-+ * not the modified/saved runtime data.  You may want to store a separate
-+ * "clean" runtime data image in DRAM to avoid disk reads of distribution file.
-+ */
 +
-+/* BSM bit fields */
-+#define BSM_WR_CTRL_REG_BIT_START     (0x80000000) /* start boot load now */
-+#define BSM_WR_CTRL_REG_BIT_START_EN  (0x40000000) /* enable boot after pwrup*/
-+#define BSM_DRAM_INST_LOAD            (0x80000000) /* start program load now */
++static int sta_ht_info_init(struct ieee80211_ht_capability *ht_cap,
++			    struct ieee80211_ht_additional_info *ht_extra,
++			    struct sta_ht_info *ht_info_ap,
++			    struct sta_ht_info *ht_info)
++{
++	union ht_cap_info cap;
++	union ht_operation_mode op_mode;
++	union ht_param_info param_info;
++	union ht_exra_param_info extra_param_info;
 +
-+/* BSM addresses */
-+#define BSM_BASE                     (CSR_BASE + 0x3400)
++	IWL_DEBUG_MAC80211("enter: \n");
 +
-+#define BSM_WR_CTRL_REG              (BSM_BASE + 0x000) /* ctl and status */
-+#define BSM_WR_MEM_SRC_REG           (BSM_BASE + 0x004) /* source in BSM mem */
-+#define BSM_WR_MEM_DST_REG           (BSM_BASE + 0x008) /* dest in SRAM mem */
-+#define BSM_WR_DWCOUNT_REG           (BSM_BASE + 0x00C) /* bytes */
-+#define BSM_WR_STATUS_REG            (BSM_BASE + 0x010) /* bit 0:  1 == done */
++	if (!ht_info) {
++		IWL_DEBUG_MAC80211("leave: ht_info is NULL\n");
++		return -1;
++	}
 +
-+/*
-+ * Pointers and size regs for bootstrap load and data SRAM save/restore.
-+ * NOTE:  3945 pointers use bits 31:0 of DRAM address.
-+ *        4965 pointers use bits 35:4 of DRAM address.
-+ */
-+#define BSM_DRAM_INST_PTR_REG        (BSM_BASE + 0x090)
-+#define BSM_DRAM_INST_BYTECOUNT_REG  (BSM_BASE + 0x094)
-+#define BSM_DRAM_DATA_PTR_REG        (BSM_BASE + 0x098)
-+#define BSM_DRAM_DATA_BYTECOUNT_REG  (BSM_BASE + 0x09C)
++	if (ht_cap) {
++		cap.val = (u16) le16_to_cpu(ht_cap->capabilities_info);
++		param_info.val = ht_cap->mac_ht_params_info;
++		ht_info->is_ht = 1;
++		if (cap.short_GI20)
++			ht_info->sgf |= 0x1;
++		if (cap.short_GI40)
++			ht_info->sgf |= 0x2;
++		ht_info->is_green_field = cap.green_field;
++		ht_info->max_amsdu_size = cap.maximal_amsdu_size;
++		ht_info->supported_chan_width = cap.supported_chan_width_set;
++		ht_info->tx_mimo_ps_mode = cap.mimo_power_save_mode;
++		memcpy(ht_info->supp_rates, ht_cap->supported_mcs_set, 16);
 +
-+/*
-+ * BSM special memory, stays powered on during power-save sleeps.
-+ * Read/write, address range from LOWER_BOUND to (LOWER_BOUND + SIZE -1)
-+ */
-+#define BSM_SRAM_LOWER_BOUND         (CSR_BASE + 0x3800)
-+#define BSM_SRAM_SIZE			(1024) /* bytes */
++		ht_info->ampdu_factor = param_info.max_rx_ampdu_factor;
++		ht_info->mpdu_density = param_info.mpdu_density;
 +
++		IWL_DEBUG_MAC80211("SISO mask 0x%X MIMO mask 0x%X \n",
++				    ht_cap->supported_mcs_set[0],
++				    ht_cap->supported_mcs_set[1]);
 +
-+/* SCD (Scheduler) */
-+#define SCD_BASE                        (CSR_BASE + 0x2E00)
++		if (ht_info_ap) {
++			ht_info->control_channel = ht_info_ap->control_channel;
++			ht_info->extension_chan_offset =
++				ht_info_ap->extension_chan_offset;
++			ht_info->tx_chan_width = ht_info_ap->tx_chan_width;
++			ht_info->operating_mode = ht_info_ap->operating_mode;
++		}
 +
-+#define SCD_MODE_REG                    (SCD_BASE + 0x000)
-+#define SCD_ARASTAT_REG                 (SCD_BASE + 0x004)
-+#define SCD_TXFACT_REG                  (SCD_BASE + 0x010)
-+#define SCD_TXF4MF_REG                  (SCD_BASE + 0x014)
-+#define SCD_TXF5MF_REG                  (SCD_BASE + 0x020)
-+#define SCD_SBYP_MODE_1_REG             (SCD_BASE + 0x02C)
-+#define SCD_SBYP_MODE_2_REG             (SCD_BASE + 0x030)
++		if (ht_extra) {
++			extra_param_info.val = ht_extra->ht_param;
++			ht_info->control_channel = ht_extra->control_chan;
++			ht_info->extension_chan_offset =
++			    extra_param_info.ext_chan_offset;
++			ht_info->tx_chan_width = extra_param_info.tx_chan_width;
++			op_mode.val = (u16)
++			    le16_to_cpu(ht_extra->operation_mode);
++			ht_info->operating_mode = op_mode.op_mode;
++			IWL_DEBUG_MAC80211("control channel %d\n",
++					    ht_extra->control_chan);
++		}
++	} else
++		ht_info->is_ht = 0;
 +
-+/*=== HBUS (Host-side Bus) ===*/
++	IWL_DEBUG_MAC80211("leave\n");
++	return 0;
++}
 +
-+#define HBUS_TARG_MEM_RADDR     (HBUS_BASE+0x00c)
-+#define HBUS_TARG_MEM_WADDR     (HBUS_BASE+0x010)
-+#define HBUS_TARG_MEM_WDAT      (HBUS_BASE+0x018)
-+#define HBUS_TARG_MEM_RDAT      (HBUS_BASE+0x01c)
-+#define HBUS_TARG_PRPH_WADDR    (HBUS_BASE+0x044)
-+#define HBUS_TARG_PRPH_RADDR    (HBUS_BASE+0x048)
-+#define HBUS_TARG_PRPH_WDAT     (HBUS_BASE+0x04c)
-+#define HBUS_TARG_PRPH_RDAT     (HBUS_BASE+0x050)
-+#define HBUS_TARG_WRPTR         (HBUS_BASE+0x060)
++static int iwl_mac_conf_ht(struct ieee80211_hw *hw,
++			   struct ieee80211_ht_capability *ht_cap,
++			   struct ieee80211_ht_additional_info *ht_extra)
++{
++	struct iwl_priv *priv = hw->priv;
++	int rs;
 +
-+/*=== FH (data Flow Handler) ===*/
++	IWL_DEBUG_MAC80211("enter: \n");
 +
-+#define FH_CBCC_TABLE           (FH_BASE+0x140)
-+#define FH_TFDB_TABLE           (FH_BASE+0x180)
-+#define FH_RCSR_TABLE           (FH_BASE+0x400)
-+#define FH_RSSR_TABLE           (FH_BASE+0x4c0)
-+#define FH_TCSR_TABLE           (FH_BASE+0x500)
-+#define FH_TSSR_TABLE           (FH_BASE+0x680)
++	rs = sta_ht_info_init(ht_cap, ht_extra, NULL, &priv->current_assoc_ht);
++	iwl4965_set_rxon_chain(priv);
 +
-+/* TFDB (Transmit Frame Buffer Descriptor) */
-+#define FH_TFDB(_channel, buf) \
-+	(FH_TFDB_TABLE+((_channel)*2+(buf))*0x28)
-+#define ALM_FH_TFDB_CHNL_BUF_CTRL_REG(_channel) \
-+	(FH_TFDB_TABLE + 0x50 * _channel)
-+/* CBCC _channel is [0,2] */
-+#define FH_CBCC(_channel)           (FH_CBCC_TABLE+(_channel)*0x8)
-+#define FH_CBCC_CTRL(_channel)      (FH_CBCC(_channel)+0x00)
-+#define FH_CBCC_BASE(_channel)      (FH_CBCC(_channel)+0x04)
++	if (priv && priv->assoc_id &&
++	    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
++		unsigned long flags;
 +
-+/* RCSR _channel is [0,2] */
-+#define FH_RCSR(_channel)           (FH_RCSR_TABLE+(_channel)*0x40)
-+#define FH_RCSR_CONFIG(_channel)    (FH_RCSR(_channel)+0x00)
-+#define FH_RCSR_RBD_BASE(_channel)  (FH_RCSR(_channel)+0x04)
-+#define FH_RCSR_WPTR(_channel)      (FH_RCSR(_channel)+0x20)
-+#define FH_RCSR_RPTR_ADDR(_channel) (FH_RCSR(_channel)+0x24)
++		spin_lock_irqsave(&priv->lock, flags);
++		if (priv->beacon_int)
++			queue_work(priv->workqueue, &priv->post_associate.work);
++		else
++			priv->call_post_assoc_from_beacon = 1;
++		spin_unlock_irqrestore(&priv->lock, flags);
++	}
 +
-+#if IWL == 3945
-+#define FH_RSCSR_CHNL0_WPTR        (FH_RCSR_WPTR(0))
-+#elif IWL == 4965
-+#define FH_RSCSR_CHNL0_WPTR        (FH_RSCSR_CHNL0_RBDCB_WPTR_REG)
-+#endif
++	IWL_DEBUG_MAC80211("leave: control channel %d\n",
++			ht_extra->control_chan);
++	return rs;
 +
-+/* RSSR */
-+#define FH_RSSR_CTRL            (FH_RSSR_TABLE+0x000)
-+#define FH_RSSR_STATUS          (FH_RSSR_TABLE+0x004)
-+/* TCSR */
-+#define FH_TCSR(_channel)           (FH_TCSR_TABLE+(_channel)*0x20)
-+#define FH_TCSR_CONFIG(_channel)    (FH_TCSR(_channel)+0x00)
-+#define FH_TCSR_CREDIT(_channel)    (FH_TCSR(_channel)+0x04)
-+#define FH_TCSR_BUFF_STTS(_channel) (FH_TCSR(_channel)+0x08)
-+/* TSSR */
-+#define FH_TSSR_CBB_BASE        (FH_TSSR_TABLE+0x000)
-+#define FH_TSSR_MSG_CONFIG      (FH_TSSR_TABLE+0x008)
-+#define FH_TSSR_TX_STATUS       (FH_TSSR_TABLE+0x010)
-+/* 18 - reserved */
++}
 +
-+/* card static random access memory (SRAM) for processor data and instructs */
-+#define RTC_INST_LOWER_BOUND			(0x000000)
-+#define RTC_DATA_LOWER_BOUND			(0x800000)
++static void iwl_set_ht_capab(struct ieee80211_hw *hw,
++			     struct ieee80211_ht_capability *ht_cap,
++			     u8 use_wide_chan)
++{
++	union ht_cap_info cap;
++	union ht_param_info param_info;
 +
-+/* HW I/F configuration */
-+#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB         (0x00000100)
-+#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM         (0x00000200)
-+#define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC            (0x00000400)
-+#define CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE         (0x00000800)
-+#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A    (0x00000000)
-+#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B    (0x00001000)
-+#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM     (0x00200000)
++	memset(&cap, 0, sizeof(union ht_cap_info));
++	memset(&param_info, 0, sizeof(union ht_param_info));
 +
-+#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP             (0x00000001)
-+#define CSR_UCODE_SW_BIT_RFKILL                     (0x00000002)
-+#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED           (0x00000004)
-+#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT      (0x00000008)
++	cap.maximal_amsdu_size = HT_IE_MAX_AMSDU_SIZE_4K;
++	cap.green_field = 1;
++	cap.short_GI20 = 1;
++	cap.short_GI40 = 1;
++	cap.supported_chan_width_set = use_wide_chan;
++	cap.mimo_power_save_mode = 0x3;
 +
-+#define CSR_GPIO_IN_BIT_AUX_POWER                   (0x00000200)
-+#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC                (0x00000000)
-+#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)
-+#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)
-+#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC               CSR_GPIO_IN_BIT_AUX_POWER
++	param_info.max_rx_ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
++	param_info.mpdu_density = CFG_HT_MPDU_DENSITY_DEF;
++	ht_cap->capabilities_info = (__le16) cpu_to_le16(cap.val);
++	ht_cap->mac_ht_params_info = (u8) param_info.val;
 +
-+#define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT         (0x80000000)
++	ht_cap->supported_mcs_set[0] = 0xff;
++	ht_cap->supported_mcs_set[1] = 0xff;
++	ht_cap->supported_mcs_set[4] =
++	    (cap.supported_chan_width_set) ? 0x1: 0x0;
++}
 +
-+/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
-+ * acknowledged (reset) by host writing "1" to flagged bits. */
-+#define BIT_INT_FH_RX        (1<<31) /* Rx DMA, cmd responses, FH_INT[17:16] */
-+#define BIT_INT_ERR          (1<<29) /* DMA hardware error FH_INT[31] */
-+#define BIT_INT_FH_TX        (1<<27) /* Tx DMA FH_INT[1:0] */
-+#define BIT_INT_MAC_CLK_ACTV (1<<26) /* NIC controller's clock toggled on/off */
-+#define BIT_INT_SWERROR      (1<<25) /* uCode error */
-+#define BIT_INT_RF_KILL      (1<<7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
-+#define BIT_INT_CT_KILL      (1<<6)  /* Critical temp (chip too hot) rfkill */
-+#define BIT_INT_SW_RX        (1<<3)  /* Rx, command responses, 3945 */
-+#define BIT_INT_WAKEUP       (1<<1)  /* NIC controller waking up (pwr mgmt) */
-+#define BIT_INT_ALIVE        (1<<0)  /* uCode interrupts once it initializes */
-+
-+#define CSR_INI_SET_MASK	(BIT_INT_FH_RX   | \
-+				 BIT_INT_ERR     | \
-+				 BIT_INT_FH_TX   | \
-+				 BIT_INT_SWERROR | \
-+				 BIT_INT_RF_KILL | \
-+				 BIT_INT_SW_RX   | \
-+				 BIT_INT_WAKEUP  | \
-+				 BIT_INT_ALIVE)
++static void iwl_mac_get_ht_capab(struct ieee80211_hw *hw,
++				 struct ieee80211_ht_capability *ht_cap)
++{
++	u8 use_wide_channel = 1;
++	struct iwl_priv *priv = hw->priv;
 +
-+/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
-+#define BIT_FH_INT_ERR       (1<<31) /* Error */
-+#define BIT_FH_INT_HI_PRIOR  (1<<30) /* High priority Rx, bypass coalescing */
-+#define BIT_FH_INT_RX_CHNL2  (1<<18) /* Rx channel 2 (3945 only) */
-+#define BIT_FH_INT_RX_CHNL1  (1<<17) /* Rx channel 1 */
-+#define BIT_FH_INT_RX_CHNL0  (1<<16) /* Rx channel 0 */
-+#define BIT_FH_INT_TX_CHNL6  (1<<6)  /* Tx channel 6 (3945 only) */
-+#define BIT_FH_INT_TX_CHNL1  (1<<1)  /* Tx channel 1 */
-+#define BIT_FH_INT_TX_CHNL0  (1<<0)  /* Tx channel 0 */
-+
-+#define FH_INT_RX_MASK		(BIT_FH_INT_HI_PRIOR | \
-+				 BIT_FH_INT_RX_CHNL2 | \
-+				 BIT_FH_INT_RX_CHNL1 | \
-+				 BIT_FH_INT_RX_CHNL0)
-+
-+#define FH_INT_TX_MASK		(BIT_FH_INT_TX_CHNL6 | \
-+				 BIT_FH_INT_TX_CHNL1 | \
-+				 BIT_FH_INT_TX_CHNL0 )
++	IWL_DEBUG_MAC80211("enter: \n");
++	if (priv->channel_width != IWL_CHANNEL_WIDTH_40MHZ)
++		use_wide_channel = 0;
 +
-+/* RESET */
-+#define CSR_RESET_REG_FLAG_NEVO_RESET                (0x00000001)
-+#define CSR_RESET_REG_FLAG_FORCE_NMI                 (0x00000002)
-+#define CSR_RESET_REG_FLAG_SW_RESET                  (0x00000080)
-+#define CSR_RESET_REG_FLAG_MASTER_DISABLED           (0x00000100)
-+#define CSR_RESET_REG_FLAG_STOP_MASTER               (0x00000200)
++	/* no fat tx allowed on 2.4GHZ */
++	if (priv->phymode != MODE_IEEE80211A)
++		use_wide_channel = 0;
 +
-+/* GP (general purpose) CONTROL */
-+#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY        (0x00000001)
-+#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE              (0x00000004)
-+#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ         (0x00000008)
-+#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP         (0x00000010)
++	iwl_set_ht_capab(hw, ht_cap, use_wide_channel);
++	IWL_DEBUG_MAC80211("leave: \n");
++}
++#endif /*CONFIG_IWLWIFI_HT*/
 +
-+#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN          (0x00000001)
++/*****************************************************************************
++ *
++ * sysfs attributes
++ *
++ *****************************************************************************/
 +
-+#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE        (0x07000000)
-+#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE         (0x04000000)
-+#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW          (0x08000000)
++#ifdef CONFIG_IWLWIFI_DEBUG
 +
-+/* APMG (power management) constants */
-+#define APMG_CLK_CTRL_REG                        (0x003000)
-+#define ALM_APMG_CLK_EN                          (0x003004)
-+#define ALM_APMG_CLK_DIS                         (0x003008)
-+#define ALM_APMG_PS_CTL                          (0x00300c)
-+#define ALM_APMG_PCIDEV_STT                      (0x003010)
-+#define ALM_APMG_RFKILL				 (0x003014)
-+#define ALM_APMG_LARC_INT                        (0x00301c)
-+#define ALM_APMG_LARC_INT_MSK                    (0x003020)
-+
-+#define APMG_CLK_REG_VAL_DMA_CLK_RQT                (0x00000200)
-+#define APMG_CLK_REG_VAL_BSM_CLK_RQT                (0x00000800)
-+
-+#define APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ        (0x04000000)
-+
-+#define APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE    (0x00000800)
-+
-+#define APMG_PS_CTRL_REG_MSK_POWER_SRC              (0x03000000)
-+#define APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN        (0x00000000)
-+#define APMG_PS_CTRL_REG_VAL_POWER_SRC_VAUX         (0x01000000)
++/*
++ * The following adds a new attribute to the sysfs representation
++ * of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/)
++ * used for controlling the debug level.
++ *
++ * See the level definitions in ipw for details.
++ */
 +
-+/* DBM */
++static ssize_t show_debug_level(struct device_driver *d, char *buf)
++{
++	return sprintf(buf, "0x%08X\n", iwl_debug_level);
++}
++static ssize_t store_debug_level(struct device_driver *d,
++				 const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++	u32 val;
 +
-+#define ALM_FH_SRVC_CHNL                            (6)
++	val = simple_strtoul(p, &p, 0);
++	if (p == buf)
++		printk(KERN_INFO DRV_NAME
++		       ": %s is not in hex or decimal form.\n", buf);
++	else
++		iwl_debug_level = val;
 +
-+#define ALM_FH_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE     (20)
-+#define ALM_FH_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH      (4)
++	return strnlen(buf, count);
++}
 +
-+#define ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN    (0x08000000)
++static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
++		   show_debug_level, store_debug_level);
 +
-+#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE        (0x80000000)
++#endif /* CONFIG_IWLWIFI_DEBUG */
 +
-+#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE           (0x20000000)
++static ssize_t show_rf_kill(struct device *d,
++			    struct device_attribute *attr, char *buf)
++{
++	/*
++	 * 0 - RF kill not enabled
++	 * 1 - SW based RF kill active (sysfs)
++	 * 2 - HW based RF kill active
++	 * 3 - Both HW and SW based RF kill active
++	 */
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
++		  (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
 +
-+#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128         (0x01000000)
++	return sprintf(buf, "%i\n", val);
++}
 +
-+#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST         (0x00001000)
++static ssize_t store_rf_kill(struct device *d,
++			     struct device_attribute *attr,
++			     const char *buf, size_t count)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 +
-+#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH               (0x00000000)
++	mutex_lock(&priv->mutex);
++	iwl_radio_kill_sw(priv, buf[0] == '1');
++	mutex_unlock(&priv->mutex);
 +
-+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF              (0x00000000)
-+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER           (0x00000001)
++	return count;
++}
 +
-+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL    (0x00000000)
-+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL     (0x00000008)
++static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
 +
-+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD           (0x00200000)
++static ssize_t show_temperature(struct device *d,
++				struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 +
-+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT            (0x00000000)
++	if (!iwl_is_alive(priv))
++		return -EAGAIN;
 +
-+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE            (0x00000000)
-+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE           (0x80000000)
++	return sprintf(buf, "%d\n", iwl_hw_get_temperature(priv));
++}
 +
-+#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID          (0x00004000)
++static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
 +
-+#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR           (0x00000001)
++static ssize_t show_rs_window(struct device *d,
++			      struct device_attribute *attr,
++			      char *buf)
++{
++	struct iwl_priv *priv = d->driver_data;
++	return iwl_fill_rs_info(priv->hw, buf, IWL_AP_ID);
++}
++static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
 +
-+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON      (0xFF000000)
-+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON      (0x00FF0000)
++static ssize_t show_tx_power(struct device *d,
++			     struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	return sprintf(buf, "%d\n", priv->user_txpower_limit);
++}
 +
-+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B    (0x00000400)
++static ssize_t store_tx_power(struct device *d,
++			      struct device_attribute *attr,
++			      const char *buf, size_t count)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	char *p = (char *)buf;
++	u32 val;
 +
-+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON       (0x00000100)
-+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON       (0x00000080)
++	val = simple_strtoul(p, &p, 10);
++	if (p == buf)
++		printk(KERN_INFO DRV_NAME
++		       ": %s is not in decimal form.\n", buf);
++	else
++		iwl_hw_reg_set_txpower(priv, val);
++
++	return count;
++}
 +
-+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH     (0x00000020)
-+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH           (0x00000005)
++static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
 +
-+#define ALM_TB_MAX_BYTES_COUNT      (0xFFF0)
++static ssize_t show_flags(struct device *d,
++			  struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 +
-+#define ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) \
-+	((1LU << _channel) << 24)
-+#define ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel) \
-+	((1LU << _channel) << 16)
++	return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
++}
 +
-+#define ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_channel) \
-+	(ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) | \
-+	 ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel))
-+#define PCI_CFG_REV_ID_BIT_BASIC_SKU                (0x40)	/* bit 6    */
-+#define PCI_CFG_REV_ID_BIT_RTP                      (0x80)	/* bit 7    */
++static ssize_t store_flags(struct device *d,
++			   struct device_attribute *attr,
++			   const char *buf, size_t count)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	u32 flags = simple_strtoul(buf, NULL, 0);
 +
-+#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED         (0x00000004)
++	mutex_lock(&priv->mutex);
++	if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
++		/* Cancel any currently running scans... */
++		if (iwl_scan_cancel_timeout(priv, 100))
++			IWL_WARNING("Could not cancel scan.\n");
++		else {
++			IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n",
++				       flags);
++			priv->staging_rxon.flags = cpu_to_le32(flags);
++			iwl_commit_rxon(priv);
++		}
++	}
++	mutex_unlock(&priv->mutex);
 +
-+#define TFD_QUEUE_MIN           0
-+#define TFD_QUEUE_MAX           6
-+#define TFD_QUEUE_SIZE_MAX      (256)
++	return count;
++}
 +
-+/* spectrum and channel data structures */
-+#define IWL_NUM_SCAN_RATES         (2)
++static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
 +
-+#define IWL_SCAN_FLAG_24GHZ  (1<<0)
-+#define IWL_SCAN_FLAG_52GHZ  (1<<1)
-+#define IWL_SCAN_FLAG_ACTIVE (1<<2)
-+#define IWL_SCAN_FLAG_DIRECT (1<<3)
++static ssize_t show_filter_flags(struct device *d,
++				 struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 +
-+#define IWL_MAX_CMD_SIZE 1024
++	return sprintf(buf, "0x%04X\n",
++		le32_to_cpu(priv->active_rxon.filter_flags));
++}
 +
-+/* LEDs mode */
++static ssize_t store_filter_flags(struct device *d,
++				  struct device_attribute *attr,
++				  const char *buf, size_t count)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	u32 filter_flags = simple_strtoul(buf, NULL, 0);
 +
-+#define IWL_DEFAULT_TX_RETRY  15
-+#define IWL_MAX_TX_RETRY      16
++	mutex_lock(&priv->mutex);
++	if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
++		/* Cancel any currently running scans... */
++		if (iwl_scan_cancel_timeout(priv, 100))
++			IWL_WARNING("Could not cancel scan.\n");
++		else {
++			IWL_DEBUG_INFO("Committing rxon.filter_flags = "
++				       "0x%04X\n", filter_flags);
++			priv->staging_rxon.filter_flags =
++				cpu_to_le32(filter_flags);
++			iwl_commit_rxon(priv);
++		}
++	}
++	mutex_unlock(&priv->mutex);
 +
-+/*********************************************/
++	return count;
++}
 +
-+#define RFD_SIZE                              4
-+#define NUM_TFD_CHUNKS                        4
++static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
++		   store_filter_flags);
 +
-+#define RX_QUEUE_SIZE                         256
-+#define RX_QUEUE_MASK                         255
-+#define RX_QUEUE_SIZE_LOG                     8
++static ssize_t show_tune(struct device *d,
++			 struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
 +
-+/*
-+ * TX Queue Flag Definitions
-+ */
++	return sprintf(buf, "0x%04X\n",
++		       (priv->phymode << 8) |
++			le16_to_cpu(priv->active_rxon.channel));
++}
 +
-+/* abort attempt if mgmt frame is rx'd */
++static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode);
 +
-+/* require CTS */
++static ssize_t store_tune(struct device *d,
++			  struct device_attribute *attr,
++			  const char *buf, size_t count)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	char *p = (char *)buf;
++	u16 tune = simple_strtoul(p, &p, 0);
++	u8 phymode = (tune >> 8) & 0xff;
++	u16 channel = tune & 0xff;
 +
-+/* use short preamble */
-+#define DCT_FLAG_LONG_PREAMBLE             0x00
-+#define DCT_FLAG_SHORT_PREAMBLE            0x04
++	IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
 +
-+/* RTS/CTS first */
++	mutex_lock(&priv->mutex);
++	if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
++	    (priv->phymode != phymode)) {
++		const struct iwl_channel_info *ch_info;
 +
-+/* don't calculate duration field */
++		ch_info = iwl_get_channel_info(priv, phymode, channel);
++		if (!ch_info) {
++			IWL_WARNING("Requested invalid phymode/channel "
++				    "combination: %d %d\n", phymode, channel);
++			mutex_unlock(&priv->mutex);
++			return -EINVAL;
++		}
 +
-+/* even if MAC WEP set (allows pre-encrypt) */
-+#define IWL_
-+/* overwrite TSF field */
++		/* Cancel any currently running scans... */
++		if (iwl_scan_cancel_timeout(priv, 100))
++			IWL_WARNING("Could not cancel scan.\n");
++		else {
++			IWL_DEBUG_INFO("Committing phymode and "
++				       "rxon.channel = %d %d\n",
++				       phymode, channel);
 +
-+/* ACK rx is expected to follow */
-+#define DCT_FLAG_ACK_REQD                  0x80
++			iwl_set_rxon_channel(priv, phymode, channel);
++			iwl_set_flags_for_phymode(priv, phymode);
 +
-+#define IWL_MB_DISASSOCIATE_THRESHOLD_DEFAULT           24
-+#define IWL_MB_ROAMING_THRESHOLD_DEFAULT                8
-+#define IWL_REAL_RATE_RX_PACKET_THRESHOLD               300
++			iwl_set_rate(priv);
++			iwl_commit_rxon(priv);
++		}
++	}
++	mutex_unlock(&priv->mutex);
 +
-+/* QoS  definitions */
++	return count;
++}
 +
-+#define CW_MIN_OFDM          15
-+#define CW_MAX_OFDM          1023
-+#define CW_MIN_CCK           31
-+#define CW_MAX_CCK           1023
++static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
 +
-+#define QOS_TX0_CW_MIN_OFDM      CW_MIN_OFDM
-+#define QOS_TX1_CW_MIN_OFDM      CW_MIN_OFDM
-+#define QOS_TX2_CW_MIN_OFDM      ((CW_MIN_OFDM + 1) / 2 - 1)
-+#define QOS_TX3_CW_MIN_OFDM      ((CW_MIN_OFDM + 1) / 4 - 1)
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
 +
-+#define QOS_TX0_CW_MIN_CCK       CW_MIN_CCK
-+#define QOS_TX1_CW_MIN_CCK       CW_MIN_CCK
-+#define QOS_TX2_CW_MIN_CCK       ((CW_MIN_CCK + 1) / 2 - 1)
-+#define QOS_TX3_CW_MIN_CCK       ((CW_MIN_CCK + 1) / 4 - 1)
++static ssize_t show_measurement(struct device *d,
++				struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	struct iwl_spectrum_notification measure_report;
++	u32 size = sizeof(measure_report), len = 0, ofs = 0;
++	u8 *data = (u8 *) & measure_report;
++	unsigned long flags;
 +
-+#define QOS_TX0_CW_MAX_OFDM      CW_MAX_OFDM
-+#define QOS_TX1_CW_MAX_OFDM      CW_MAX_OFDM
-+#define QOS_TX2_CW_MAX_OFDM      CW_MIN_OFDM
-+#define QOS_TX3_CW_MAX_OFDM      ((CW_MIN_OFDM + 1) / 2 - 1)
++	spin_lock_irqsave(&priv->lock, flags);
++	if (!(priv->measurement_status & MEASUREMENT_READY)) {
++		spin_unlock_irqrestore(&priv->lock, flags);
++		return 0;
++	}
++	memcpy(&measure_report, &priv->measure_report, size);
++	priv->measurement_status = 0;
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+#define QOS_TX0_CW_MAX_CCK       CW_MAX_CCK
-+#define QOS_TX1_CW_MAX_CCK       CW_MAX_CCK
-+#define QOS_TX2_CW_MAX_CCK       CW_MIN_CCK
-+#define QOS_TX3_CW_MAX_CCK       ((CW_MIN_CCK + 1) / 2 - 1)
++	while (size && (PAGE_SIZE - len)) {
++		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
++				   PAGE_SIZE - len, 1);
++		len = strlen(buf);
++		if (PAGE_SIZE - len)
++			buf[len++] = '\n';
 +
-+#define QOS_TX0_AIFS            3
-+#define QOS_TX1_AIFS            7
-+#define QOS_TX2_AIFS            2
-+#define QOS_TX3_AIFS            2
++		ofs += 16;
++		size -= min(size, 16U);
++	}
 +
-+#define QOS_TX0_ACM             0
-+#define QOS_TX1_ACM             0
-+#define QOS_TX2_ACM             0
-+#define QOS_TX3_ACM             0
++	return len;
++}
 +
-+#define QOS_TX0_TXOP_LIMIT_CCK          0
-+#define QOS_TX1_TXOP_LIMIT_CCK          0
-+#define QOS_TX2_TXOP_LIMIT_CCK          6016
-+#define QOS_TX3_TXOP_LIMIT_CCK          3264
++static ssize_t store_measurement(struct device *d,
++				 struct device_attribute *attr,
++				 const char *buf, size_t count)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	struct ieee80211_measurement_params params = {
++		.channel = le16_to_cpu(priv->active_rxon.channel),
++		.start_time = cpu_to_le64(priv->last_tsf),
++		.duration = cpu_to_le16(1),
++	};
++	u8 type = IWL_MEASURE_BASIC;
++	u8 buffer[32];
++	u8 channel;
 +
-+#define QOS_TX0_TXOP_LIMIT_OFDM      0
-+#define QOS_TX1_TXOP_LIMIT_OFDM      0
-+#define QOS_TX2_TXOP_LIMIT_OFDM      3008
-+#define QOS_TX3_TXOP_LIMIT_OFDM      1504
++	if (count) {
++		char *p = buffer;
++		strncpy(buffer, buf, min(sizeof(buffer), count));
++		channel = simple_strtoul(p, NULL, 0);
++		if (channel)
++			params.channel = channel;
 +
-+#define DEF_TX0_CW_MIN_OFDM      CW_MIN_OFDM
-+#define DEF_TX1_CW_MIN_OFDM      CW_MIN_OFDM
-+#define DEF_TX2_CW_MIN_OFDM      CW_MIN_OFDM
-+#define DEF_TX3_CW_MIN_OFDM      CW_MIN_OFDM
++		p = buffer;
++		while (*p && *p != ' ')
++			p++;
++		if (*p)
++			type = simple_strtoul(p + 1, NULL, 0);
++	}
 +
-+#define DEF_TX0_CW_MIN_CCK       CW_MIN_CCK
-+#define DEF_TX1_CW_MIN_CCK       CW_MIN_CCK
-+#define DEF_TX2_CW_MIN_CCK       CW_MIN_CCK
-+#define DEF_TX3_CW_MIN_CCK       CW_MIN_CCK
++	IWL_DEBUG_INFO("Invoking measurement of type %d on "
++		       "channel %d (for '%s')\n", type, params.channel, buf);
++	iwl_get_measurement(priv, &params, type);
 +
-+#define DEF_TX0_CW_MAX_OFDM      CW_MAX_OFDM
-+#define DEF_TX1_CW_MAX_OFDM      CW_MAX_OFDM
-+#define DEF_TX2_CW_MAX_OFDM      CW_MAX_OFDM
-+#define DEF_TX3_CW_MAX_OFDM      CW_MAX_OFDM
++	return count;
++}
 +
-+#define DEF_TX0_CW_MAX_CCK       CW_MAX_CCK
-+#define DEF_TX1_CW_MAX_CCK       CW_MAX_CCK
-+#define DEF_TX2_CW_MAX_CCK       CW_MAX_CCK
-+#define DEF_TX3_CW_MAX_CCK       CW_MAX_CCK
++static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
++		   show_measurement, store_measurement);
++#endif /* CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT */
 +
-+#define DEF_TX0_AIFS            (2)
-+#define DEF_TX1_AIFS            (2)
-+#define DEF_TX2_AIFS            (2)
-+#define DEF_TX3_AIFS            (2)
++static ssize_t store_retry_rate(struct device *d,
++				struct device_attribute *attr,
++				const char *buf, size_t count)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
 +
-+#define DEF_TX0_ACM             0
-+#define DEF_TX1_ACM             0
-+#define DEF_TX2_ACM             0
-+#define DEF_TX3_ACM             0
++	priv->retry_rate = simple_strtoul(buf, NULL, 0);
++	if (priv->retry_rate <= 0)
++		priv->retry_rate = 1;
 +
-+#define DEF_TX0_TXOP_LIMIT_CCK        0
-+#define DEF_TX1_TXOP_LIMIT_CCK        0
-+#define DEF_TX2_TXOP_LIMIT_CCK        0
-+#define DEF_TX3_TXOP_LIMIT_CCK        0
++	return count;
++}
 +
-+#define DEF_TX0_TXOP_LIMIT_OFDM       0
-+#define DEF_TX1_TXOP_LIMIT_OFDM       0
-+#define DEF_TX2_TXOP_LIMIT_OFDM       0
-+#define DEF_TX3_TXOP_LIMIT_OFDM       0
++static ssize_t show_retry_rate(struct device *d,
++			       struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	return sprintf(buf, "%d", priv->retry_rate);
++}
 +
-+#define QOS_QOS_SETS                  3
-+#define QOS_PARAM_SET_ACTIVE          0
-+#define QOS_PARAM_SET_DEF_CCK         1
-+#define QOS_PARAM_SET_DEF_OFDM        2
++static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
++		   store_retry_rate);
 +
-+#define CTRL_QOS_NO_ACK               (0x0020)
-+#define DCT_FLAG_EXT_QOS_ENABLED      (0x10)
++static ssize_t store_power_level(struct device *d,
++				 struct device_attribute *attr,
++				 const char *buf, size_t count)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	int rc;
++	int mode;
 +
-+#define IWL_TX_QUEUE_AC0        0
-+#define IWL_TX_QUEUE_AC1        1
-+#define IWL_TX_QUEUE_AC2        2
-+#define IWL_TX_QUEUE_AC3        3
-+#define IWL_TX_QUEUE_HCCA_1     5
-+#define IWL_TX_QUEUE_HCCA_2     6
++	mode = simple_strtoul(buf, NULL, 0);
++	mutex_lock(&priv->mutex);
 +
-+#define U32_PAD(n)		((4-(n))&0x3)
++	if (!iwl_is_ready(priv)) {
++		rc = -EAGAIN;
++		goto out;
++	}
 +
-+#define AC_BE_TID_MASK 0x9	/* TID 0 and 3 */
-+#define AC_BK_TID_MASK 0x6	/* TID 1 and 2 */
++	if ((mode < 1) || (mode > IWL_POWER_LIMIT) || (mode == IWL_POWER_AC))
++		mode = IWL_POWER_AC;
++	else
++		mode |= IWL_POWER_ENABLED;
 +
-+/*
-+ * Generic queue structure
-+ *
-+ * Contains common data for Rx and Tx queues
-+ */
-+#define TFD_CTL_COUNT_SET(n)       (n<<24)
-+#define TFD_CTL_COUNT_GET(ctl)     ((ctl>>24) & 7)
-+#define TFD_CTL_PAD_SET(n)         (n<<28)
-+#define TFD_CTL_PAD_GET(ctl)       (ctl>>28)
++	if (mode != priv->power_mode) {
++		rc = iwl_send_power_mode(priv, IWL_POWER_LEVEL(mode));
++		if (rc) {
++			IWL_DEBUG_MAC80211("failed setting power mode.\n");
++			goto out;
++		}
++		priv->power_mode = mode;
++	}
 +
-+#define TFD_TX_CMD_SLOTS 256
-+#define TFD_CMD_SLOTS 32
++	rc = count;
 +
-+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \
-+			      sizeof(struct iwl_cmd_meta))
++ out:
++	mutex_unlock(&priv->mutex);
++	return rc;
++}
 +
-+/*
-+ * RX related structures and functions
-+ */
-+#define RX_FREE_BUFFERS 64
-+#define RX_LOW_WATERMARK 8
++#define MAX_WX_STRING 80
 +
-+#if IWL == 3945
-+#include "iwl-3945-hw.h"
-+#elif IWL == 4965
-+#include "iwl-4965-hw.h"
-+#endif
++/* Values are in microsecond */
++static const s32 timeout_duration[] = {
++	350000,
++	250000,
++	75000,
++	37000,
++	25000,
++};
++static const s32 period_duration[] = {
++	400000,
++	700000,
++	1000000,
++	1000000,
++	1000000
++};
 +
-+#endif				/* __iwlwifi_hw_h__ */
-diff --git a/drivers/net/wireless/iwl-io.h b/drivers/net/wireless/iwl-io.h
-new file mode 100644
-index 0000000..f293702
---- /dev/null
-+++ b/drivers/net/wireless/iwl-io.h
-@@ -0,0 +1,485 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ipw3945 project.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
++static ssize_t show_power_level(struct device *d,
++				struct device_attribute *attr, char *buf)
++{
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	int level = IWL_POWER_LEVEL(priv->power_mode);
++	char *p = buf;
 +
-+#ifndef __iwl_io_h__
-+#define __iwl_io_h__
++	p += sprintf(p, "%d ", level);
++	switch (level) {
++	case IWL_POWER_MODE_CAM:
++	case IWL_POWER_AC:
++		p += sprintf(p, "(AC)");
++		break;
++	case IWL_POWER_BATTERY:
++		p += sprintf(p, "(BATTERY)");
++		break;
++	default:
++		p += sprintf(p,
++			     "(Timeout %dms, Period %dms)",
++			     timeout_duration[level - 1] / 1000,
++			     period_duration[level - 1] / 1000);
++	}
 +
-+#include <linux/io.h>
++	if (!(priv->power_mode & IWL_POWER_ENABLED))
++		p += sprintf(p, " OFF\n");
++	else
++		p += sprintf(p, " \n");
 +
-+#include "iwl-debug.h"
++	return (p - buf + 1);
 +
-+/*
-+ * IO, register, and NIC memory access functions
-+ *
-+ * NOTE on naming convention and macro usage for these
-+ *
-+ * A single _ prefix before a an access function means that no state
-+ * check or debug information is printed when that function is called.
-+ *
-+ * A double __ prefix before an access function means that state is checked
-+ * (in the case of *restricted calls) and the current line number is printed
-+ * in addition to any other debug output.
-+ *
-+ * The non-prefixed name is the #define that maps the caller into a
-+ * #define that provides the caller's __LINE__ to the double prefix version.
-+ *
-+ * If you wish to call the function without any debug or state checking,
-+ * you should use the single _ prefix version (as is used by dependent IO
-+ * routines, for example _iwl_read_restricted calls the non-check version of
-+ * _iwl_read32.)
-+ *
-+ * These declarations are *extremely* useful in quickly isolating code deltas
-+ * which result in misconfiguring of the hardware I/O.  In combination with
-+ * git-bisect and the IO debug level you can quickly determine the specific
-+ * commit which breaks the IO sequence to the hardware.
-+ *
-+ */
++}
 +
-+#define _iwl_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs))
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *ipw,
-+				 u32 ofs, u32 val)
++static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
++		   store_power_level);
++
++static ssize_t show_channels(struct device *d,
++			     struct device_attribute *attr, char *buf)
 +{
-+	IWL_DEBUG_IO("write_direct32(0x%08X, 0x%08X) - %s %d\n",
-+		     (u32) (ofs), (u32) (val), f, l);
-+	_iwl_write32(ipw, ofs, val);
-+}
-+#define iwl_write32(ipw, ofs, val) \
-+	__iwl_write32(__FILE__, __LINE__, ipw, ofs, val)
-+#else
-+#define iwl_write32(ipw, ofs, val) _iwl_write32(ipw, ofs, val)
-+#endif
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	int len = 0, i;
++	struct ieee80211_channel *channels = NULL;
++	const struct ieee80211_hw_mode *hw_mode = NULL;
++	int count = 0;
++
++	if (!iwl_is_ready(priv))
++		return -EAGAIN;
++
++	hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211G);
++	if (!hw_mode)
++		hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211B);
++	if (hw_mode) {
++		channels = hw_mode->channels;
++		count = hw_mode->num_channels;
++	}
 +
-+#define _iwl_read32(ipw, ofs) readl((ipw)->hw_base + (ofs))
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *ipw, u32 ofs)
-+{
-+	IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
-+	return _iwl_read32(ipw, ofs);
-+}
-+#define iwl_read32(ipw, ofs) __iwl_read32(__FILE__, __LINE__, ipw, ofs)
-+#else
-+#define iwl_read32(p, o) _iwl_read32(p, o)
-+#endif
++	len +=
++	    sprintf(&buf[len],
++		    "Displaying %d channels in 2.4GHz band "
++		    "(802.11bg):\n", count);
 +
-+static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr,
-+				u32 bits, u32 mask, int timeout)
-+{
-+	int i = 0;
++	for (i = 0; i < count; i++)
++		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
++			       channels[i].chan,
++			       channels[i].power_level,
++			       channels[i].
++			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
++			       " (IEEE 802.11h required)" : "",
++			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
++				|| (channels[i].
++				    flag &
++				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
++			       ", IBSS",
++			       channels[i].
++			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
++			       "active/passive" : "passive only");
 +
-+	do {
-+		if ((_iwl_read32(priv, addr) & mask) == (bits & mask))
-+			return i;
-+		mdelay(10);
-+		i += 10;
-+	} while (i < timeout);
++	hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211A);
++	if (hw_mode) {
++		channels = hw_mode->channels;
++		count = hw_mode->num_channels;
++	} else {
++		channels = NULL;
++		count = 0;
++	}
 +
-+	return -ETIMEDOUT;
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline int __iwl_poll_bit(const char *f, u32 l,
-+				 struct iwl_priv *priv, u32 addr,
-+				 u32 bits, u32 mask, int timeout)
-+{
-+	int rc = _iwl_poll_bit(priv, addr, bits, mask, timeout);
-+	if (unlikely(rc == -ETIMEDOUT))
-+		IWL_DEBUG_IO
-+		    ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
-+		     addr, bits, mask, f, l);
-+	else
-+		IWL_DEBUG_IO
-+		    ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
-+		     addr, bits, mask, rc, f, l);
-+	return rc;
-+}
-+#define iwl_poll_bit(ipw, addr, bits, mask, timeout) \
-+	__iwl_poll_bit(__FILE__, __LINE__, ipw, addr, bits, mask, timeout)
-+#else
-+#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t)
-+#endif
++	len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
++		       "(802.11a):\n", count);
 +
-+static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
-+{
-+	_iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_set_bit(const char *f, u32 l,
-+				 struct iwl_priv *priv, u32 reg, u32 mask)
-+{
-+	u32 val = _iwl_read32(priv, reg) | mask;
-+	IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
-+	_iwl_write32(priv, reg, val);
-+}
-+#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m)
-+#else
-+#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m)
-+#endif
++	for (i = 0; i < count; i++)
++		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
++			       channels[i].chan,
++			       channels[i].power_level,
++			       channels[i].
++			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
++			       " (IEEE 802.11h required)" : "",
++			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
++				|| (channels[i].
++				    flag &
++				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
++			       ", IBSS",
++			       channels[i].
++			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
++			       "active/passive" : "passive only");
 +
-+static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
-+{
-+	_iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_clear_bit(const char *f, u32 l,
-+				   struct iwl_priv *priv, u32 reg, u32 mask)
-+{
-+	u32 val = _iwl_read32(priv, reg) & ~mask;
-+	IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
-+	_iwl_write32(priv, reg, val);
++	return len;
 +}
-+#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m)
-+#else
-+#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m)
-+#endif
 +
-+static inline int _iwl_grab_restricted_access(struct iwl_priv *priv)
++static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
++
++static ssize_t show_statistics(struct device *d,
++			       struct device_attribute *attr, char *buf)
 +{
-+	int rc;
-+	u32 gp_ctl;
++	struct iwl_priv *priv = dev_get_drvdata(d);
++	u32 size = sizeof(struct iwl_notif_statistics);
++	u32 len = 0, ofs = 0;
++	u8 *data = (u8 *) & priv->statistics;
++	int rc = 0;
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	if (atomic_read(&priv->restrict_refcnt))
-+		return 0;
-+#endif
-+	if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
-+	    test_bit(STATUS_RF_KILL_SW, &priv->status)) {
-+		IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
-+			"wakes up NIC\n");
++	if (!iwl_is_alive(priv))
++		return -EAGAIN;
 +
-+		/* 10 msec allows time for NIC to complete its data save */
-+		gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL);
-+		if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
-+			IWL_DEBUG_RF_KILL("Wait for complete power-down, "
-+				"gpctl = 0x%08x\n", gp_ctl);
-+			mdelay(10);
-+		} else
-+			IWL_DEBUG_RF_KILL("power-down complete, "
-+					  "gpctl = 0x%08x\n", gp_ctl);
++	mutex_lock(&priv->mutex);
++	rc = iwl_send_statistics_request(priv);
++	mutex_unlock(&priv->mutex);
++
++	if (rc) {
++		len = sprintf(buf,
++			      "Error sending statistics request: 0x%08X\n", rc);
++		return len;
 +	}
 +
-+	/* this bit wakes up the NIC */
-+	_iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-+	rc = _iwl_poll_bit(priv, CSR_GP_CNTRL,
-+			   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
-+			   (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
-+			    CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
-+	if (rc < 0) {
-+		IWL_ERROR("MAC is in deep sleep!\n");
-+		return -EIO;
++	while (size && (PAGE_SIZE - len)) {
++		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
++				   PAGE_SIZE - len, 1);
++		len = strlen(buf);
++		if (PAGE_SIZE - len)
++			buf[len++] = '\n';
++
++		ofs += 16;
++		size -= min(size, 16U);
 +	}
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	atomic_inc(&priv->restrict_refcnt);
-+#endif
-+	return 0;
++	return len;
 +}
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline int __iwl_grab_restricted_access(const char *f, u32 l,
-+					       struct iwl_priv *priv)
++static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
++
++static ssize_t show_antenna(struct device *d,
++			    struct device_attribute *attr, char *buf)
 +{
-+	if (atomic_read(&priv->restrict_refcnt))
-+		IWL_DEBUG_INFO("Grabbing access while already held at "
-+			       "line %d.\n", l);
++	struct iwl_priv *priv = dev_get_drvdata(d);
 +
-+	IWL_DEBUG_IO("grabbing restricted access - %s %d\n", f, l);
++	if (!iwl_is_alive(priv))
++		return -EAGAIN;
 +
-+	return _iwl_grab_restricted_access(priv);
++	return sprintf(buf, "%d\n", priv->antenna);
 +}
-+#define iwl_grab_restricted_access(priv) \
-+	__iwl_grab_restricted_access(__FILE__, __LINE__, priv)
-+#else
-+#define iwl_grab_restricted_access(priv) \
-+	_iwl_grab_restricted_access(priv)
-+#endif
 +
-+static inline void _iwl_release_restricted_access(struct iwl_priv *priv)
-+{
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	if (atomic_dec_and_test(&priv->restrict_refcnt))
-+#endif
-+		_iwl_clear_bit(priv, CSR_GP_CNTRL,
-+			       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_release_restricted_access(const char *f, u32 l,
-+						   struct iwl_priv *priv)
++static ssize_t store_antenna(struct device *d,
++			     struct device_attribute *attr,
++			     const char *buf, size_t count)
 +{
-+	if (atomic_read(&priv->restrict_refcnt) <= 0)
-+		IWL_ERROR("Release unheld restricted access at line %d.\n", l);
++	int ant;
++	struct iwl_priv *priv = dev_get_drvdata(d);
 +
-+	IWL_DEBUG_IO("releasing restricted access - %s %d\n", f, l);
-+	_iwl_release_restricted_access(priv);
-+}
-+#define iwl_release_restricted_access(priv) \
-+	__iwl_release_restricted_access(__FILE__, __LINE__, priv)
-+#else
-+#define iwl_release_restricted_access(priv) \
-+	_iwl_release_restricted_access(priv)
-+#endif
++	if (count == 0)
++		return 0;
 +
-+static inline u32 _iwl_read_restricted(struct iwl_priv *priv, u32 reg)
-+{
-+	return _iwl_read32(priv, reg);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline u32 __iwl_read_restricted(const char *f, u32 l,
-+					struct iwl_priv *priv, u32 reg)
-+{
-+	u32 value = _iwl_read_restricted(priv, reg);
-+	if (!atomic_read(&priv->restrict_refcnt))
-+		IWL_ERROR("Unrestricted access from %s %d\n", f, l);
-+	IWL_DEBUG_IO("read_restricted(0x%4X) = 0x%08x - %s %d \n", reg, value,
-+		     f, l);
-+	return value;
-+}
-+#define iwl_read_restricted(priv, reg) \
-+	__iwl_read_restricted(__FILE__, __LINE__, priv, reg)
-+#else
-+#define iwl_read_restricted _iwl_read_restricted
-+#endif
++	if (sscanf(buf, "%1i", &ant) != 1) {
++		IWL_DEBUG_INFO("not in hex or decimal form.\n");
++		return count;
++	}
 +
-+static inline void _iwl_write_restricted(struct iwl_priv *priv,
-+					 u32 reg, u32 value)
-+{
-+	_iwl_write32(priv, reg, value);
++	if ((ant >= 0) && (ant <= 2)) {
++		IWL_DEBUG_INFO("Setting antenna select to %d.\n", ant);
++		priv->antenna = (enum iwl_antenna)ant;
++	} else
++		IWL_DEBUG_INFO("Bad antenna select value %d.\n", ant);
++
++
++	return count;
 +}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static void __iwl_write_restricted(u32 line,
-+				   struct iwl_priv *priv, u32 reg, u32 value)
++
++static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
++
++static ssize_t show_status(struct device *d,
++			   struct device_attribute *attr, char *buf)
 +{
-+	if (!atomic_read(&priv->restrict_refcnt))
-+		IWL_ERROR("Unrestricted access from line %d\n", line);
-+	_iwl_write_restricted(priv, reg, value);
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	if (!iwl_is_alive(priv))
++		return -EAGAIN;
++	return sprintf(buf, "0x%08x\n", (int)priv->status);
 +}
-+#define iwl_write_restricted(priv, reg, value) \
-+	__iwl_write_restricted(__LINE__, priv, reg, value)
-+#else
-+#define iwl_write_restricted _iwl_write_restricted
-+#endif
 +
-+static inline void iwl_write_buffer_restricted(struct iwl_priv *priv,
-+					       u32 reg, u32 len, u32 *values)
++static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
++
++static ssize_t dump_error_log(struct device *d,
++			      struct device_attribute *attr,
++			      const char *buf, size_t count)
 +{
-+	u32 count = sizeof(u32);
++	char *p = (char *)buf;
 +
-+	if ((priv != NULL) && (values != NULL)) {
-+		for (; 0 < len; len -= count, reg += count, values++)
-+			_iwl_write_restricted(priv, reg, *values);
-+	}
++	if (p[0] == '1')
++		iwl_dump_nic_error_log((struct iwl_priv *)d->driver_data);
++
++	return strnlen(buf, count);
 +}
 +
-+static inline int _iwl_poll_restricted_bit(struct iwl_priv *priv,
-+					   u32 addr, u32 mask, int timeout)
++static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
++
++static ssize_t dump_event_log(struct device *d,
++			      struct device_attribute *attr,
++			      const char *buf, size_t count)
 +{
-+	int i = 0;
++	char *p = (char *)buf;
 +
-+	do {
-+		if ((_iwl_read_restricted(priv, addr) & mask) == mask)
-+			return i;
-+		mdelay(10);
-+		i += 10;
-+	} while (i < timeout);
++	if (p[0] == '1')
++		iwl_dump_nic_event_log((struct iwl_priv *)d->driver_data);
 +
-+	return -ETIMEDOUT;
++	return strnlen(buf, count);
 +}
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline int __iwl_poll_restricted_bit(const char *f, u32 l,
-+					    struct iwl_priv *priv,
-+					    u32 addr, u32 mask, int timeout)
-+{
-+	int rc = _iwl_poll_restricted_bit(priv, addr, mask, timeout);
++static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
 +
-+	if (unlikely(rc == -ETIMEDOUT))
-+		IWL_DEBUG_IO("poll_restricted_bit(0x%08X, 0x%08X) - "
-+			     "timedout - %s %d\n", addr, mask, f, l);
-+	else
-+		IWL_DEBUG_IO("poll_restricted_bit(0x%08X, 0x%08X) = 0x%08X "
-+			     "- %s %d\n", addr, mask, rc, f, l);
-+	return rc;
-+}
-+#define iwl_poll_restricted_bit(ipw, addr, mask, timeout) \
-+	__iwl_poll_restricted_bit(__FILE__, __LINE__, ipw, addr, mask, timeout)
-+#else
-+#define iwl_poll_restricted_bit _iwl_poll_restricted_bit
-+#endif
++/*****************************************************************************
++ *
++ * driver setup and teardown
++ *
++ *****************************************************************************/
 +
-+static inline u32 _iwl_read_restricted_reg(struct iwl_priv *priv, u32 reg)
++static void iwl_setup_deferred_work(struct iwl_priv *priv)
 +{
-+	_iwl_write_restricted(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
-+	return _iwl_read_restricted(priv, HBUS_TARG_PRPH_RDAT);
++	priv->workqueue = create_workqueue(DRV_NAME);
++
++	init_waitqueue_head(&priv->wait_command_queue);
++
++	INIT_WORK(&priv->up, iwl_bg_up);
++	INIT_WORK(&priv->restart, iwl_bg_restart);
++	INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
++	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
++	INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
++	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
++	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
++	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
++	INIT_DELAYED_WORK(&priv->post_associate, iwl_bg_post_associate);
++	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
++	INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
++	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
++
++	iwl_hw_setup_deferred_work(priv);
++
++	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
++		     iwl_irq_tasklet, (unsigned long)priv);
 +}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline u32 __iwl_read_restricted_reg(u32 line,
-+					    struct iwl_priv *priv, u32 reg)
++
++static void iwl_cancel_deferred_work(struct iwl_priv *priv)
 +{
-+	if (!atomic_read(&priv->restrict_refcnt))
-+		IWL_ERROR("Unrestricted access from line %d\n", line);
-+	return _iwl_read_restricted_reg(priv, reg);
++	iwl_hw_cancel_deferred_work(priv);
++
++	cancel_delayed_work(&priv->scan_check);
++	cancel_delayed_work(&priv->alive_start);
++	cancel_delayed_work(&priv->post_associate);
++	cancel_work_sync(&priv->beacon_update);
 +}
 +
-+#define iwl_read_restricted_reg(priv, reg) \
-+	__iwl_read_restricted_reg(__LINE__, priv, reg)
-+#else
-+#define iwl_read_restricted_reg _iwl_read_restricted_reg
++static struct attribute *iwl_sysfs_entries[] = {
++	&dev_attr_antenna.attr,
++	&dev_attr_channels.attr,
++	&dev_attr_dump_errors.attr,
++	&dev_attr_dump_events.attr,
++	&dev_attr_flags.attr,
++	&dev_attr_filter_flags.attr,
++#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++	&dev_attr_measurement.attr,
 +#endif
++	&dev_attr_power_level.attr,
++	&dev_attr_retry_rate.attr,
++	&dev_attr_rf_kill.attr,
++	&dev_attr_rs_window.attr,
++	&dev_attr_statistics.attr,
++	&dev_attr_status.attr,
++	&dev_attr_temperature.attr,
++	&dev_attr_tune.attr,
++	&dev_attr_tx_power.attr,
 +
-+static inline void _iwl_write_restricted_reg(struct iwl_priv *priv,
-+					     u32 addr, u32 val)
++	NULL
++};
++
++static struct attribute_group iwl_attribute_group = {
++	.name = NULL,		/* put in device directory */
++	.attrs = iwl_sysfs_entries,
++};
++
++static struct ieee80211_ops iwl_hw_ops = {
++	.tx = iwl_mac_tx,
++	.open = iwl_mac_open,
++	.stop = iwl_mac_stop,
++	.add_interface = iwl_mac_add_interface,
++	.remove_interface = iwl_mac_remove_interface,
++	.config = iwl_mac_config,
++	.config_interface = iwl_mac_config_interface,
++	.set_key = iwl_mac_set_key,
++	.get_stats = iwl_mac_get_stats,
++	.get_tx_stats = iwl_mac_get_tx_stats,
++	.conf_tx = iwl_mac_conf_tx,
++	.get_tsf = iwl_mac_get_tsf,
++	.reset_tsf = iwl_mac_reset_tsf,
++	.beacon_update = iwl_mac_beacon_update,
++#ifdef CONFIG_IWLWIFI_HT
++	.conf_ht = iwl_mac_conf_ht,
++	.get_ht_capab = iwl_mac_get_ht_capab,
++#ifdef CONFIG_IWLWIFI_HT_AGG
++	.ht_tx_agg_start = iwl_mac_ht_tx_agg_start,
++	.ht_tx_agg_stop = iwl_mac_ht_tx_agg_stop,
++	.ht_rx_agg_start = iwl_mac_ht_rx_agg_start,
++	.ht_rx_agg_stop = iwl_mac_ht_rx_agg_stop,
++#endif  /* CONFIG_IWLWIFI_HT_AGG */
++#endif  /* CONFIG_IWLWIFI_HT */
++	.hw_scan = iwl_mac_hw_scan
++};
++
++static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 +{
-+	_iwl_write_restricted(priv, HBUS_TARG_PRPH_WADDR,
-+			      ((addr & 0x0000FFFF) | (3 << 24)));
-+	_iwl_write_restricted(priv, HBUS_TARG_PRPH_WDAT, val);
-+}
++	int err = 0;
++	u32 pci_id;
++	struct iwl_priv *priv;
++	struct ieee80211_hw *hw;
++	int i;
++
++	if (iwl_param_disable_hw_scan) {
++		IWL_DEBUG_INFO("Disabling hw_scan\n");
++		iwl_hw_ops.hw_scan = NULL;
++	}
++
++	if ((iwl_param_queues_num > IWL_MAX_NUM_QUEUES) ||
++	    (iwl_param_queues_num < IWL_MIN_NUM_QUEUES)) {
++		IWL_ERROR("invalid queues_num, should be between %d and %d\n",
++			  IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
++		err = -EINVAL;
++		goto out;
++	}
++
++	/* mac80211 allocates memory for this device instance, including
++	 *   space for this driver's private structure */
++	hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl_hw_ops);
++	if (hw == NULL) {
++		IWL_ERROR("Can not allocate network device\n");
++		err = -ENOMEM;
++		goto out;
++	}
++	SET_IEEE80211_DEV(hw, &pdev->dev);
++
++	IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
++	priv = hw->priv;
++	priv->hw = hw;
++
++	priv->pci_dev = pdev;
++	priv->antenna = (enum iwl_antenna)iwl_param_antenna;
 +#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_write_restricted_reg(u32 line,
-+					      struct iwl_priv *priv,
-+					      u32 addr, u32 val)
-+{
-+	if (!atomic_read(&priv->restrict_refcnt))
-+		IWL_ERROR("Unrestricted access from line %d\n", line);
-+	_iwl_write_restricted_reg(priv, addr, val);
-+}
++	iwl_debug_level = iwl_param_debug;
++	atomic_set(&priv->restrict_refcnt, 0);
++#endif
++	priv->retry_rate = 1;
++
++	priv->ibss_beacon = NULL;
++
++	/* Tell mac80211 and its clients (e.g. Wireless Extensions)
++	 *   the range of signal quality values that we'll provide.
++	 * Negative values for level/noise indicate that we'll provide dBm.
++	 * For WE, at least, non-0 values here *enable* display of values
++	 *   in app (iwconfig). */
++	hw->max_rssi = -20;	/* signal level, negative indicates dBm */
++	hw->max_noise = -20;	/* noise level, negative indicates dBm */
++	hw->max_signal = 100;	/* link quality indication (%) */
 +
-+#define iwl_write_restricted_reg(priv, addr, val) \
-+	__iwl_write_restricted_reg(__LINE__, priv, addr, val);
-+#else
-+#define iwl_write_restricted_reg _iwl_write_restricted_reg
-+#endif
++	/* Tell mac80211 our Tx characteristics */
++	hw->flags = IEEE80211_HW_WEP_INCLUDE_IV |
++	    IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
 +
-+#define _iwl_set_bits_restricted_reg(priv, reg, mask) \
-+	_iwl_write_restricted_reg(priv, reg, \
-+				  (_iwl_read_restricted_reg(priv, reg) | mask))
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_set_bits_restricted_reg(u32 line, struct iwl_priv
-+						 *priv, u32 reg, u32 mask)
-+{
-+	if (!atomic_read(&priv->restrict_refcnt))
-+		IWL_ERROR("Unrestricted access from line %d\n", line);
-+	_iwl_set_bits_restricted_reg(priv, reg, mask);
-+}
-+#define iwl_set_bits_restricted_reg(priv, reg, mask) \
-+	__iwl_set_bits_restricted_reg(__LINE__, priv, reg, mask)
-+#else
-+#define iwl_set_bits_restricted_reg _iwl_set_bits_restricted_reg
-+#endif
++	hw->queues = 4;
++#ifdef CONFIG_IWLWIFI_HT
++#ifdef CONFIG_IWLWIFI_HT_AGG
++	hw->queues = 16;
++#endif /* CONFIG_IWLWIFI_HT_AGG */
++#endif /* CONFIG_IWLWIFI_HT */
 +
-+#define _iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask) \
-+	_iwl_write_restricted_reg( \
-+	    priv, reg, ((_iwl_read_restricted_reg(priv, reg) & mask) | bits))
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_set_bits_mask_restricted_reg(u32 line,
-+		struct iwl_priv *priv, u32 reg, u32 bits, u32 mask)
-+{
-+	if (!atomic_read(&priv->restrict_refcnt))
-+		IWL_ERROR("Unrestricted access from line %d\n", line);
-+	_iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask);
-+}
++	spin_lock_init(&priv->lock);
++	spin_lock_init(&priv->power_data.lock);
++	spin_lock_init(&priv->sta_lock);
++	spin_lock_init(&priv->hcmd_lock);
++	spin_lock_init(&priv->lq_mngr.lock);
 +
-+#define iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask) \
-+	__iwl_set_bits_mask_restricted_reg(__LINE__, priv, reg, bits, mask)
-+#else
-+#define iwl_set_bits_mask_restricted_reg _iwl_set_bits_mask_restricted_reg
-+#endif
++	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
++		INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
 +
-+static inline void iwl_clear_bits_restricted_reg(struct iwl_priv
-+						 *priv, u32 reg, u32 mask)
-+{
-+	u32 val = _iwl_read_restricted_reg(priv, reg);
-+	_iwl_write_restricted_reg(priv, reg, (val & ~mask));
-+}
++	INIT_LIST_HEAD(&priv->free_frames);
 +
-+static inline u32 iwl_read_restricted_mem(struct iwl_priv *priv, u32 addr)
-+{
-+	iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR, addr);
-+	return iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
-+}
++	mutex_init(&priv->mutex);
++	if (pci_enable_device(pdev)) {
++		err = -ENODEV;
++		goto out_ieee80211_free_hw;
++	}
 +
-+static inline void iwl_write_restricted_mem(struct iwl_priv *priv, u32 addr,
-+					    u32 val)
-+{
-+	iwl_write_restricted(priv, HBUS_TARG_MEM_WADDR, addr);
-+	iwl_write_restricted(priv, HBUS_TARG_MEM_WDAT, val);
-+}
++	pci_set_master(pdev);
 +
-+static inline void iwl_write_restricted_mems(struct iwl_priv *priv, u32 addr,
-+					     u32 len, u32 *values)
-+{
-+	iwl_write_restricted(priv, HBUS_TARG_MEM_WADDR, addr);
-+	for (; 0 < len; len -= sizeof(u32), values++)
-+		iwl_write_restricted(priv, HBUS_TARG_MEM_WDAT, *values);
-+}
++	iwl_clear_stations_table(priv);
 +
-+static inline void iwl_write_restricted_regs(struct iwl_priv *priv, u32 reg,
-+					     u32 len, u8 *values)
-+{
-+	u32 reg_offset = reg;
-+	u32 aligment = reg & 0x3;
++	priv->data_retry_limit = -1;
++	priv->ieee_channels = NULL;
++	priv->ieee_rates = NULL;
++	priv->phymode = -1;
 +
-+	/* write any non-dword-aligned stuff at the beginning */
-+	if (len < sizeof(u32)) {
-+		if ((aligment + len) <= sizeof(u32)) {
-+			u8 size;
-+			u32 value = 0;
-+			size = len - 1;
-+			memcpy(&value, values, len);
-+			reg_offset = (reg_offset & 0x0000FFFF);
++	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
++	if (!err)
++		err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
++	if (err) {
++		printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n");
++		goto out_pci_disable_device;
++	}
 +
-+			_iwl_write_restricted(priv,
-+					      HBUS_TARG_PRPH_WADDR,
-+					      (reg_offset | (size << 24)));
-+			_iwl_write_restricted(priv, HBUS_TARG_PRPH_WDAT,
-+					      value);
-+		}
++	pci_set_drvdata(pdev, priv);
++	err = pci_request_regions(pdev, DRV_NAME);
++	if (err)
++		goto out_pci_disable_device;
++	/* We disable the RETRY_TIMEOUT register (0x41) to keep
++	 * PCI Tx retries from interfering with C3 CPU state */
++	pci_write_config_byte(pdev, 0x41, 0x00);
++	priv->hw_base = pci_iomap(pdev, 0, 0);
++	if (!priv->hw_base) {
++		err = -ENODEV;
++		goto out_pci_release_regions;
++	}
 +
-+		return;
++	IWL_DEBUG_INFO("pci_resource_len = 0x%08llx\n",
++			(unsigned long long) pci_resource_len(pdev, 0));
++	IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
++
++	/* Initialize module parameter values here */
++
++	if (iwl_param_disable) {
++		set_bit(STATUS_RF_KILL_SW, &priv->status);
++		IWL_DEBUG_INFO("Radio disabled.\n");
 +	}
 +
-+	/* now write all the dword-aligned stuff */
-+	for (; reg_offset < (reg + len);
-+	     reg_offset += sizeof(u32), values += sizeof(u32))
-+		_iwl_write_restricted_reg(priv, reg_offset, *((u32 *) values));
-+}
++	priv->iw_mode = IEEE80211_IF_TYPE_STA;
 +
-+/**
-+ * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer pointer.
-+ *
-+ * NOTE: This function has 3945 and 4965 specific code paths in it.
-+ */
-+static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
-+				       dma_addr_t dma_addr)
-+{
-+#if IWL == 3945
-+	return cpu_to_le32((u32)dma_addr);
-+#elif IWL == 4965
-+	return cpu_to_le32((u32)(dma_addr >> 8));
-+#endif
-+}
++	pci_id =
++	    (priv->pci_dev->device << 16) | priv->pci_dev->subsystem_device;
 +
-+#endif
-diff --git a/drivers/net/wireless/iwl-priv.h b/drivers/net/wireless/iwl-priv.h
-new file mode 100644
-index 0000000..c9cb11e
---- /dev/null
-+++ b/drivers/net/wireless/iwl-priv.h
-@@ -0,0 +1,307 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
++	priv->ps_mode = 0;
++	priv->use_ant_b_for_management_frame = 1; /* start with ant B */
++	priv->is_ht_enabled = 1;
++	priv->channel_width = IWL_CHANNEL_WIDTH_40MHZ;
++	priv->valid_antenna = 0x7;	/* assume all 3 connected */
++	priv->ps_mode = IWL_MIMO_PS_NONE;
++	priv->cck_power_index_compensation = iwl_read32(
++		priv, CSR_HW_REV_WA_REG);
 +
-+#ifndef __iwl_priv_h__
-+#define __iwl_priv_h__
++	iwl4965_set_rxon_chain(priv);
 +
-+#include <linux/workqueue.h>
++	printk(KERN_INFO DRV_NAME
++	       ": Detected Intel Wireless WiFi Link 4965AGN\n");
 +
-+#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
++	/* Device-specific setup */
++	if (iwl_hw_set_hw_setting(priv)) {
++		IWL_ERROR("failed to set hw settings\n");
++		mutex_unlock(&priv->mutex);
++		goto out_iounmap;
++	}
 +
-+enum {
-+	MEASUREMENT_READY = (1 << 0),
-+	MEASUREMENT_ACTIVE = (1 << 1),
-+};
++#ifdef CONFIG_IWLWIFI_QOS
++	if (iwl_param_qos_enable)
++		priv->qos_data.qos_enable = 1;
 +
-+#endif
++	iwl_reset_qos(priv);
 +
-+struct iwl_priv {
++	priv->qos_data.qos_active = 0;
++	priv->qos_data.qos_cap.val = 0;
++#endif /* CONFIG_IWLWIFI_QOS */
 +
-+	/* ieee device used by generic ieee processing code */
-+	struct ieee80211_hw *hw;
-+	struct ieee80211_channel *ieee_channels;
-+	struct ieee80211_rate *ieee_rates;
++	iwl_set_rxon_channel(priv, MODE_IEEE80211G, 6);
++	iwl_setup_deferred_work(priv);
++	iwl_setup_rx_handlers(priv);
 +
-+	/* temporary frame storage list */
-+	struct list_head free_frames;
-+	int frames_count;
++	priv->rates_mask = IWL_RATES_MASK;
++	/* If power management is turned on, default to AC mode */
++	priv->power_mode = IWL_POWER_AC;
++	priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
 +
-+	u8 phymode;
-+	int alloc_rxb_skb;
++	pci_enable_msi(pdev);
++
++	err = request_irq(pdev->irq, iwl_isr, IRQF_SHARED, DRV_NAME, priv);
++	if (err) {
++		IWL_ERROR("Error allocating IRQ %d\n", pdev->irq);
++		goto out_disable_msi;
++	}
++
++	mutex_lock(&priv->mutex);
++
++	err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
++	if (err) {
++		IWL_ERROR("failed to create sysfs device attributes\n");
++		mutex_unlock(&priv->mutex);
++		goto out_release_irq;
++	}
++
++	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
++	 * ucode filename and max sizes are card-specific. */
++	err = iwl_read_ucode(priv);
++	if (err) {
++		IWL_ERROR("Could not read microcode: %d\n", err);
++		mutex_unlock(&priv->mutex);
++		goto out_pci_alloc;
++	}
 +
-+	void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
-+				       struct iwl_rx_mem_buffer *rxb);
++	mutex_unlock(&priv->mutex);
 +
-+	const struct ieee80211_hw_mode *modes;
++	IWL_DEBUG_INFO("Queing UP work.\n");
 +
-+#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
-+	/* spectrum measurement report caching */
-+	struct iwl_spectrum_notification measure_report;
-+	u8 measurement_status;
-+#endif
-+	/* ucode beacon time */
-+	u32 ucode_beacon_time;
++	queue_work(priv->workqueue, &priv->up);
 +
-+	/* we allocate array of iwl_channel_info for NIC's valid channels.
-+	 *    Access via channel # using indirect index array */
-+	struct iwl_channel_info *channel_info;	/* channel info array */
-+	u8 channel_count;	/* # of channels */
++	return 0;
 +
-+	/* each calibration channel group in the EEPROM has a derived
-+	 * clip setting for each rate. */
-+	const struct iwl_clip_group clip_groups[5];
++ out_pci_alloc:
++	iwl_dealloc_ucode_pci(priv);
 +
-+	/* thermal calibration */
-+	s32 temperature;	/* degrees Kelvin */
-+	s32 last_temperature;
++	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
 +
-+	/* Scan related variables */
-+	unsigned long last_scan_jiffies;
-+	unsigned long scan_start;
-+	unsigned long scan_pass_start;
-+	unsigned long scan_start_tsf;
-+	int scan_bands;
-+	int one_direct_scan;
-+	u8 direct_ssid_len;
-+	u8 direct_ssid[IW_ESSID_MAX_SIZE];
-+	struct iwl_scan_cmd *scan;
-+	u8 only_active_channel;
++ out_release_irq:
++	free_irq(pdev->irq, priv);
 +
-+	/* spinlock */
-+	spinlock_t lock;	/* protect general shared data */
-+	spinlock_t hcmd_lock;	/* protect hcmd */
-+	struct mutex mutex;
++ out_disable_msi:
++	pci_disable_msi(pdev);
++	destroy_workqueue(priv->workqueue);
++	priv->workqueue = NULL;
++	iwl_unset_hw_setting(priv);
 +
-+	/* basic pci-network driver stuff */
-+	struct pci_dev *pci_dev;
++ out_iounmap:
++	pci_iounmap(pdev, priv->hw_base);
++ out_pci_release_regions:
++	pci_release_regions(pdev);
++ out_pci_disable_device:
++	pci_disable_device(pdev);
++	pci_set_drvdata(pdev, NULL);
++ out_ieee80211_free_hw:
++	ieee80211_free_hw(priv->hw);
++ out:
++	return err;
++}
 +
-+	/* pci hardware address support */
-+	void __iomem *hw_base;
++static void iwl_pci_remove(struct pci_dev *pdev)
++{
++	struct iwl_priv *priv = pci_get_drvdata(pdev);
++	struct list_head *p, *q;
++	int i;
 +
-+	/* uCode images, save to reload in case of failure */
-+	struct fw_image_desc ucode_code;	/* runtime inst */
-+	struct fw_image_desc ucode_data;	/* runtime data original */
-+	struct fw_image_desc ucode_data_backup;	/* runtime data save/restore */
-+	struct fw_image_desc ucode_init;	/* initialization inst */
-+	struct fw_image_desc ucode_init_data;	/* initialization data */
-+	struct fw_image_desc ucode_boot;	/* bootstrap inst */
++	if (!priv)
++		return;
 +
++	IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n");
 +
-+	struct iwl_rxon_time_cmd rxon_timing;
++	mutex_lock(&priv->mutex);
++	set_bit(STATUS_EXIT_PENDING, &priv->status);
++	__iwl_down(priv);
++	mutex_unlock(&priv->mutex);
 +
-+	/* We declare this const so it can only be
-+	 * changed via explicit cast within the
-+	 * routines that actually update the physical
-+	 * hardware */
-+	const struct iwl_rxon_cmd active_rxon;
-+	struct iwl_rxon_cmd staging_rxon;
++	/* Free MAC hash list for ADHOC */
++	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
++		list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
++			list_del(p);
++			kfree(list_entry(p, struct iwl_ibss_seq, list));
++		}
++	}
 +
-+	int error_recovering;
-+	struct iwl_rxon_cmd recovery_rxon;
++	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
 +
-+	/* 1st responses from initialize and runtime uCode images.
-+	 * 4965's initialize alive response contains some calibration data. */
-+	struct iwl_init_alive_resp card_alive_init;
-+	struct iwl_alive_resp card_alive;
++	iwl_dealloc_ucode_pci(priv);
 +
-+#ifdef LED
-+	/* LED related variables */
-+	struct iwl_activity_blink activity;
-+	unsigned long led_packets;
-+	int led_state;
-+#endif
++	if (priv->rxq.bd)
++		iwl_rx_queue_free(priv, &priv->rxq);
++	iwl_hw_txq_ctx_free(priv);
 +
-+	u16 active_rate;
-+	u16 active_rate_basic;
++	iwl_unset_hw_setting(priv);
++	iwl_clear_stations_table(priv);
 +
-+	u8 call_post_assoc_from_beacon;
-+#if IWL == 4965
-+	u8 use_ant_b_for_management_frame;	/* Tx antenna selection */
-+	/* HT variables */
-+	u8 is_dup;
-+	u8 is_ht_enabled;
-+	u8 channel_width;	/* 0=20MHZ, 1=40MHZ */
-+	u8 current_channel_width;
-+	u8 valid_antenna;	/* Bit mask of antennas actually connected */
-+#ifdef CONFIG_IWLWIFI_SENSITIVITY
-+	struct iwl_sensitivity_data sensitivity_data;
-+	struct iwl_chain_noise_data chain_noise_data;
-+	u8 start_calib;
-+	__le16 sensitivity_tbl[HD_TABLE_SIZE];
-+#endif /*CONFIG_IWLWIFI_SENSITIVITY*/
++	if (priv->mac80211_registered) {
++		ieee80211_unregister_hw(priv->hw);
++		iwl_rate_control_unregister(priv->hw);
++	}
 +
-+#ifdef CONFIG_IWLWIFI_HT
-+	struct sta_ht_info current_assoc_ht;
-+#endif
-+	u8 active_rate_ht[2];
-+	u8 last_phy_res[100];
++	/* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
++	 * priv->workqueue... so we can't take down the workqueue
++	 * until now... */
++	destroy_workqueue(priv->workqueue);
++	priv->workqueue = NULL;
 +
-+	/* Rate scaling data */
-+	struct iwl_lq_mngr lq_mngr;
-+#endif
++	free_irq(pdev->irq, priv);
++	pci_disable_msi(pdev);
++	pci_iounmap(pdev, priv->hw_base);
++	pci_release_regions(pdev);
++	pci_disable_device(pdev);
++	pci_set_drvdata(pdev, NULL);
 +
-+	/* Rate scaling data */
-+	s8 data_retry_limit;
-+	u8 retry_rate;
++	kfree(priv->channel_info);
 +
-+	wait_queue_head_t wait_command_queue;
++	kfree(priv->ieee_channels);
++	kfree(priv->ieee_rates);
 +
-+	int activity_timer_active;
++	if (priv->ibss_beacon)
++		dev_kfree_skb(priv->ibss_beacon);
 +
-+	/* Rx and Tx DMA processing queues */
-+	struct iwl_rx_queue rxq;
-+	struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES];
-+#if IWL == 4965
-+	unsigned long txq_ctx_active_msk;
-+	struct iwl_kw kw;	/* keep warm address */
-+	u32 scd_base_addr;	/* scheduler sram base address */
-+#endif
++	ieee80211_free_hw(priv->hw);
++}
 +
-+	unsigned long status;
-+	u32 config;
++#ifdef CONFIG_PM
 +
-+	int last_rx_rssi;	/* From Rx packet statisitics */
-+	int last_rx_noise;	/* From beacon statistics */
++static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++	struct iwl_priv *priv = pci_get_drvdata(pdev);
 +
-+	struct iwl_power_mgr power_data;
++	mutex_lock(&priv->mutex);
 +
-+	struct iwl_notif_statistics statistics;
-+	unsigned long last_statistics_time;
++	set_bit(STATUS_IN_SUSPEND, &priv->status);
 +
-+	/* context information */
-+	u8 essid[IW_ESSID_MAX_SIZE];
-+	u8 essid_len;
-+	u16 rates_mask;
++	/* Take down the device; powers it off, etc. */
++	__iwl_down(priv);
 +
-+	u32 power_mode;
-+	u32 antenna;
-+	u8 bssid[ETH_ALEN];
-+	u16 rts_threshold;
-+	u8 mac_addr[ETH_ALEN];
++	if (priv->mac80211_registered)
++		ieee80211_stop_queues(priv->hw);
 +
-+	/*station table variables */
-+	spinlock_t sta_lock;
-+	u8 num_stations;
-+	struct iwl_station_entry stations[IWL_STATION_COUNT];
++	pci_save_state(pdev);
++	pci_disable_device(pdev);
++	pci_set_power_state(pdev, PCI_D3hot);
 +
-+	/* Indication if ieee80211_ops->open has been called */
-+	int is_open;
++	mutex_unlock(&priv->mutex);
 +
-+	u8 mac80211_registered;
-+	int is_abg;
++	return 0;
++}
 +
-+	u32 notif_missed_beacons;
++static void iwl_resume(struct iwl_priv *priv)
++{
++	unsigned long flags;
 +
-+	/* Rx'd packet timing information */
-+	u32 last_beacon_time;
-+	u64 last_tsf;
++	/* The following it a temporary work around due to the
++	 * suspend / resume not fully initializing the NIC correctly.
++	 * Without all of the following, resume will not attempt to take
++	 * down the NIC (it shouldn't really need to) and will just try
++	 * and bring the NIC back up.  However that fails during the
++	 * ucode verification process.  This then causes iwl_down to be
++	 * called *after* iwl_hw_nic_init() has succeeded -- which
++	 * then lets the next init sequence succeed.  So, we've
++	 * replicated all of that NIC init code here... */
 +
-+	/* Duplicate packet detection */
-+	u16 last_seq_num;
-+	u16 last_frag_num;
-+	unsigned long last_packet_time;
-+	struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE];
++	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
 +
-+	/* eeprom */
-+	struct iwl_eeprom eeprom;
++	iwl_hw_nic_init(priv);
 +
-+	int iw_mode;
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
++	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
 +
-+	struct sk_buff *ibss_beacon;
++	/* tell the device to stop sending interrupts */
++	iwl_disable_interrupts(priv);
 +
-+	/* Last Rx'd beacon timestamp */
-+	u32 timestamp0;
-+	u32 timestamp1;
-+	u16 beacon_int;
-+	struct iwl_driver_hw_info hw_setting;
-+	int interface_id;
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 +
-+	/* Current association information needed to configure the
-+	 * hardware */
-+	u16 assoc_id;
-+	u16 assoc_capability;
-+	u8 ps_mode;
++	if (!iwl_grab_restricted_access(priv)) {
++		iwl_write_restricted_reg(priv, APMG_CLK_DIS_REG,
++					 APMG_CLK_VAL_DMA_CLK_RQT);
++		iwl_release_restricted_access(priv);
++	}
++	spin_unlock_irqrestore(&priv->lock, flags);
 +
-+#ifdef CONFIG_IWLWIFI_QOS
-+	struct iwl_qos_info qos_data;
-+#endif /*CONFIG_IWLWIFI_QOS */
++	udelay(5);
 +
-+	struct workqueue_struct *workqueue;
++	iwl_hw_nic_reset(priv);
 +
-+	struct work_struct up;
-+	struct work_struct restart;
-+	struct work_struct calibrated_work;
-+	struct work_struct scan_completed;
-+	struct work_struct rx_replenish;
-+	struct work_struct rf_kill;
-+	struct work_struct abort_scan;
-+	struct work_struct update_link_led;
-+	struct work_struct auth_work;
-+	struct work_struct report_work;
-+	struct work_struct request_scan;
-+	struct work_struct beacon_update;
++	/* Bring the device back up */
++	clear_bit(STATUS_IN_SUSPEND, &priv->status);
++	queue_work(priv->workqueue, &priv->up);
++}
 +
-+	struct tasklet_struct irq_tasklet;
++static int iwl_pci_resume(struct pci_dev *pdev)
++{
++	struct iwl_priv *priv = pci_get_drvdata(pdev);
++	int err;
 +
-+	struct delayed_work init_alive_start;
-+	struct delayed_work alive_start;
-+	struct delayed_work activity_timer;
-+	struct delayed_work thermal_periodic;
-+	struct delayed_work gather_stats;
-+	struct delayed_work scan_check;
-+	struct delayed_work post_associate;
++	printk(KERN_INFO "Coming out of suspend...\n");
 +
-+#define IWL_DEFAULT_TX_POWER 0x0F
-+	s8 user_txpower_limit;
-+	s8 max_channel_txpower_limit;
-+	u32 cck_power_index_compensation;
++	mutex_lock(&priv->mutex);
 +
-+#ifdef CONFIG_PM
-+	u32 pm_state[16];
-+#endif
++	pci_set_power_state(pdev, PCI_D0);
++	err = pci_enable_device(pdev);
++	pci_restore_state(pdev);
 +
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+	/* debugging info */
-+	u32 framecnt_to_us;
-+	atomic_t restrict_refcnt;
-+#endif
++	/*
++	 * Suspend/Resume resets the PCI configuration space, so we have to
++	 * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
++	 * from interfering with C3 CPU state. pci_restore_state won't help
++	 * here since it only restores the first 64 bytes pci config header.
++	 */
++	pci_write_config_byte(pdev, 0x41, 0x00);
 +
-+#if IWL == 4965
-+	struct work_struct txpower_work;
-+#ifdef CONFIG_IWLWIFI_SENSITIVITY
-+	struct work_struct sensitivity_work;
-+#endif
-+	struct work_struct statistics_work;
-+	struct timer_list statistics_periodic;
++	iwl_resume(priv);
++	mutex_unlock(&priv->mutex);
 +
-+#ifdef CONFIG_IWLWIFI_HT_AGG
-+	struct work_struct agg_work;
-+#endif
++	return 0;
++}
 +
-+#endif /* 4965 */
-+};				/*iwl_priv */
++#endif /* CONFIG_PM */
 +
-+#endif /* __iwl_priv_h__ */
-diff --git a/drivers/net/wireless/iwl-spectrum.h b/drivers/net/wireless/iwl-spectrum.h
-new file mode 100644
-index 0000000..b576ff2
---- /dev/null
-+++ b/drivers/net/wireless/iwl-spectrum.h
-@@ -0,0 +1,91 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ieee80211 subsystem header files.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
++/*****************************************************************************
 + *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ * driver and module entry point
 + *
 + *****************************************************************************/
 +
-+#ifndef __iwl_spectrum_h__
-+#define __iwl_spectrum_h__
-+enum {				/* ieee80211_basic_report.map */
-+	IEEE80211_BASIC_MAP_BSS = (1 << 0),
-+	IEEE80211_BASIC_MAP_OFDM = (1 << 1),
-+	IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2),
-+	IEEE80211_BASIC_MAP_RADAR = (1 << 3),
-+	IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4),
-+	/* Bits 5-7 are reserved */
-+
++static struct pci_driver iwl_driver = {
++	.name = DRV_NAME,
++	.id_table = iwl_hw_card_ids,
++	.probe = iwl_pci_probe,
++	.remove = __devexit_p(iwl_pci_remove),
++#ifdef CONFIG_PM
++	.suspend = iwl_pci_suspend,
++	.resume = iwl_pci_resume,
++#endif
 +};
-+struct ieee80211_basic_report {
-+	u8 channel;
-+	__le64 start_time;
-+	__le16 duration;
-+	u8 map;
-+} __attribute__ ((packed));
 +
-+enum {				/* ieee80211_measurement_request.mode */
-+	/* Bit 0 is reserved */
-+	IEEE80211_MEASUREMENT_ENABLE = (1 << 1),
-+	IEEE80211_MEASUREMENT_REQUEST = (1 << 2),
-+	IEEE80211_MEASUREMENT_REPORT = (1 << 3),
-+	/* Bits 4-7 are reserved */
-+};
++static int __init iwl_init(void)
++{
 +
-+enum {
-+	IEEE80211_REPORT_BASIC = 0,	/* required */
-+	IEEE80211_REPORT_CCA = 1,	/* optional */
-+	IEEE80211_REPORT_RPI = 2,	/* optional */
-+	/* 3-255 reserved */
-+};
++	int ret;
++	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
++	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
++	ret = pci_register_driver(&iwl_driver);
++	if (ret) {
++		IWL_ERROR("Unable to initialize PCI module\n");
++		return ret;
++	}
++#ifdef CONFIG_IWLWIFI_DEBUG
++	ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level);
++	if (ret) {
++		IWL_ERROR("Unable to create driver sysfs file\n");
++		pci_unregister_driver(&iwl_driver);
++		return ret;
++	}
++#endif
 +
-+struct ieee80211_measurement_params {
-+	u8 channel;
-+	__le64 start_time;
-+	__le16 duration;
-+} __attribute__ ((packed));
++	return ret;
++}
 +
-+struct ieee80211_info_element {
-+	u8 id;
-+	u8 len;
-+	u8 data[0];
-+} __attribute__ ((packed));
++static void __exit iwl_exit(void)
++{
++#ifdef CONFIG_IWLWIFI_DEBUG
++	driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level);
++#endif
++	pci_unregister_driver(&iwl_driver);
++}
 +
-+struct ieee80211_measurement_request {
-+	struct ieee80211_info_element ie;
-+	u8 token;
-+	u8 mode;
-+	u8 type;
-+	struct ieee80211_measurement_params params[0];
-+} __attribute__ ((packed));
++module_param_named(antenna, iwl_param_antenna, int, 0444);
++MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
++module_param_named(disable, iwl_param_disable, int, 0444);
++MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
++module_param_named(hwcrypto, iwl_param_hwcrypto, int, 0444);
++MODULE_PARM_DESC(hwcrypto,
++		 "using hardware crypto engine (default 0 [software])\n");
++module_param_named(debug, iwl_param_debug, int, 0444);
++MODULE_PARM_DESC(debug, "debug output mask");
++module_param_named(disable_hw_scan, iwl_param_disable_hw_scan, int, 0444);
++MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
 +
-+struct ieee80211_measurement_report {
-+	struct ieee80211_info_element ie;
-+	u8 token;
-+	u8 mode;
-+	u8 type;
-+	union {
-+		struct ieee80211_basic_report basic[0];
-+	} u;
-+} __attribute__ ((packed));
-+#endif
++module_param_named(queues_num, iwl_param_queues_num, int, 0444);
++MODULE_PARM_DESC(queues_num, "number of hw queues.");
++
++/* QoS */
++module_param_named(qos_enable, iwl_param_qos_enable, int, 0444);
++MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
++
++module_exit(iwl_exit);
++module_init(iwl_init);
 diff --git a/drivers/net/wireless/iwlwifi.h b/drivers/net/wireless/iwlwifi.h
 new file mode 100644
-index 0000000..fcf0197
+index 0000000..f4f42f5
 --- /dev/null
 +++ b/drivers/net/wireless/iwlwifi.h
-@@ -0,0 +1,714 @@
+@@ -0,0 +1,712 @@
 +/******************************************************************************
 + *
 + * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
@@ -26277,12 +34424,20 @@
 +extern struct pci_device_id iwl_hw_card_ids[];
 +
 +#if IWL == 3945
++
 +#define DRV_NAME	"iwl3945"
++#include "iwl-hw.h"
++#include "iwl-3945-hw.h"
++
 +#elif IWL == 4965
++
 +#define DRV_NAME        "iwl4965"
++#include "iwl-hw.h"
++#include "iwl-4965-hw.h"
++
 +#endif
 +
-+#include "iwl-hw.h"
++#include "iwl-prph.h"
 +
 +/*
 + * Driver implementation data structures, constants, inline
@@ -26503,13 +34658,10 @@
 +				struct iwl_cmd *cmd, struct sk_buff *skb);
 +	} __attribute__ ((packed)) u;
 +
-+	u16 len;
-+
 +	/* The CMD_SIZE_HUGE flag bit indicates that the command
 +	 * structure is stored at the end of the shared queue memory. */
-+	u8 flags;
++	u32 flags;
 +
-+	u8 token;
 +} __attribute__ ((packed));
 +
 +struct iwl_cmd {
@@ -26685,10 +34837,6 @@
 +
 +#ifdef CONFIG_IWLWIFI_QOS
 +
-+#define IPW_QOS_NONE      0
-+#define IPW_QOS_11H       1
-+#define IPW_QOS_WMM       2
-+
 +union iwl_qos_capabity {
 +	struct {
 +		u8 edca_count:4;	/* bit 0-3 */
@@ -26790,8 +34938,6 @@
 +#define HT_SHORT_GI_20MHZ_ONLY          (1 << 0)
 +#define HT_SHORT_GI_40MHZ_ONLY          (1 << 1)
 +
-+#include "iwl-3945.h"
-+#include "iwl-4965.h"
 +
 +#include "iwl-priv.h"
 +
@@ -26884,8 +35030,7 @@
 +
 +static inline int iwl_is_associated(struct iwl_priv *priv)
 +{
-+	return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ?
-+		1 : 0;
++	return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
 +}
 +
 +/******************************************************************************

Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	(original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	Tue Sep  4 18:52:03 2007
@@ -39,4 +39,4 @@
 + bugfix/arm/disable-netxen_nic.patch
 + bugfix/arm/disable-chelsio_t3.patch
 + bugfix/arm/disable-video_bt848.patch
-+ features/all/v5-Add-iwlwifi-wireless-drivers.patch
++ features/all/v6-Add-iwlwifi-wireless-drivers.patch



More information about the Kernel-svn-changes mailing list