]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
authorDavid S. Miller <davem@davemloft.net>
Tue, 29 Nov 2011 00:21:10 +0000 (19:21 -0500)
committerDavid S. Miller <davem@davemloft.net>
Tue, 29 Nov 2011 00:21:10 +0000 (19:21 -0500)
167 files changed:
drivers/net/wireless/Makefile
drivers/net/wireless/ath/ath6kl/Makefile
drivers/net/wireless/ath/ath6kl/bmi.c
drivers/net/wireless/ath/ath6kl/bmi.h
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/cfg80211.h
drivers/net/wireless/ath/ath6kl/common.h
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/debug.c
drivers/net/wireless/ath/ath6kl/debug.h
drivers/net/wireless/ath/ath6kl/hif-ops.h
drivers/net/wireless/ath/ath6kl/hif.c [moved from drivers/net/wireless/ath/ath6kl/htc_hif.c with 80% similarity]
drivers/net/wireless/ath/ath6kl/hif.h
drivers/net/wireless/ath/ath6kl/htc.c
drivers/net/wireless/ath/ath6kl/htc.h
drivers/net/wireless/ath/ath6kl/htc_hif.h [deleted file]
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/ath6kl/sdio.c
drivers/net/wireless/ath/ath6kl/target.h
drivers/net/wireless/ath/ath6kl/txrx.c
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.h
drivers/net/wireless/ath/ath9k/btcoex.c
drivers/net/wireless/ath/ath9k/btcoex.h
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/carl9170/tx.c
drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
drivers/net/wireless/brcm80211/brcmsmac/dma.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlegacy/3945-debug.c [new file with mode: 0644]
drivers/net/wireless/iwlegacy/3945-mac.c [new file with mode: 0644]
drivers/net/wireless/iwlegacy/3945-rs.c [new file with mode: 0644]
drivers/net/wireless/iwlegacy/3945.c [new file with mode: 0644]
drivers/net/wireless/iwlegacy/3945.h [new file with mode: 0644]
drivers/net/wireless/iwlegacy/4965-calib.c [moved from drivers/net/wireless/iwlegacy/iwl-4965-calib.c with 55% similarity]
drivers/net/wireless/iwlegacy/4965-debug.c [new file with mode: 0644]
drivers/net/wireless/iwlegacy/4965-mac.c [new file with mode: 0644]
drivers/net/wireless/iwlegacy/4965-rs.c [new file with mode: 0644]
drivers/net/wireless/iwlegacy/4965.c [new file with mode: 0644]
drivers/net/wireless/iwlegacy/4965.h [new file with mode: 0644]
drivers/net/wireless/iwlegacy/Kconfig
drivers/net/wireless/iwlegacy/Makefile
drivers/net/wireless/iwlegacy/commands.h [moved from drivers/net/wireless/iwlegacy/iwl-commands.h with 79% similarity]
drivers/net/wireless/iwlegacy/common.c [new file with mode: 0644]
drivers/net/wireless/iwlegacy/common.h [new file with mode: 0644]
drivers/net/wireless/iwlegacy/csr.h [moved from drivers/net/wireless/iwlegacy/iwl-csr.h with 84% similarity]
drivers/net/wireless/iwlegacy/debug.c [new file with mode: 0644]
drivers/net/wireless/iwlegacy/iwl-3945-debugfs.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-3945-debugfs.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-3945-fh.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-3945-hw.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-3945-led.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-3945-led.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-3945-rs.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-3945.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-3945.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-calib.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-debugfs.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-debugfs.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-eeprom.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-hw.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-led.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-led.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-lib.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-rs.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-rx.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-sta.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-tx.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965-ucode.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-4965.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-core.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-core.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-debug.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-debugfs.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-dev.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-devtrace.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-devtrace.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-eeprom.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-eeprom.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-fh.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-hcmd.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-helpers.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-io.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-led.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-led.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-legacy-rs.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-power.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-power.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-rx.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-scan.c [deleted file]
drivers/net/wireless/iwlegacy/iwl-spectrum.h
drivers/net/wireless/iwlegacy/iwl-sta.c
drivers/net/wireless/iwlegacy/iwl-sta.h [deleted file]
drivers/net/wireless/iwlegacy/iwl-tx.c [deleted file]
drivers/net/wireless/iwlegacy/iwl3945-base.c [deleted file]
drivers/net/wireless/iwlegacy/iwl4965-base.c [deleted file]
drivers/net/wireless/iwlegacy/prph.h [moved from drivers/net/wireless/iwlegacy/iwl-prph.h with 83% similarity]
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-debug.h
drivers/net/wireless/iwlwifi/iwl-io.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
drivers/net/wireless/libertas/ethtool.c
drivers/net/wireless/mwifiex/Kconfig
drivers/net/wireless/mwifiex/cfp.c
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/sdio.c
drivers/net/wireless/mwifiex/sdio.h
drivers/net/wireless/mwifiex/sta_cmdresp.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/p54/p54spi.c
drivers/net/wireless/p54/txrx.c
drivers/net/wireless/prism54/islpci_dev.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/base.h
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/wireless/rtlwifi/wifi.h
include/linux/nl80211.h
include/net/cfg80211.h
include/net/mac80211.h
include/net/nfc/nci.h
include/net/regulatory.h
net/mac80211/cfg.c
net/mac80211/debugfs_sta.c
net/mac80211/driver-ops.h
net/mac80211/ht.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_pathtbl.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/sta_info.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wep.c
net/mac80211/work.c
net/mac80211/wpa.c
net/wireless/core.h
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/reg.h
net/wireless/sme.c
net/wireless/util.c

index c1c0678b1fb64a8b6e9b56757b48700f095473fa..98db76196b59d448ae7d11ba33e46cc8f9339d74 100644 (file)
@@ -42,7 +42,7 @@ obj-$(CONFIG_ADM8211) += adm8211.o
 obj-$(CONFIG_MWL8K)    += mwl8k.o
 
 obj-$(CONFIG_IWLWIFI)  += iwlwifi/
-obj-$(CONFIG_IWLWIFI_LEGACY)   += iwlegacy/
+obj-$(CONFIG_IWLEGACY) += iwlegacy/
 obj-$(CONFIG_RT2X00)   += rt2x00/
 
 obj-$(CONFIG_P54_COMMON)       += p54/
index 8f7a0d1c290c67b2c1783c5dba172689c76e3bb0..707069303550e9eae103f533875eb72b3376d9fb 100644 (file)
@@ -23,7 +23,7 @@
 
 obj-$(CONFIG_ATH6KL) := ath6kl.o
 ath6kl-y += debug.o
-ath6kl-y += htc_hif.o
+ath6kl-y += hif.o
 ath6kl-y += htc.o
 ath6kl-y += bmi.o
 ath6kl-y += cfg80211.o
index c5d11cc536e04791d75050f4fd356fde2ec4a16f..a962fe4c6b7e43d612b8cda710df01239a55305d 100644 (file)
@@ -196,8 +196,6 @@ int ath6kl_bmi_done(struct ath6kl *ar)
                return ret;
        }
 
-       ath6kl_bmi_cleanup(ar);
-
        return 0;
 }
 
@@ -672,6 +670,11 @@ int ath6kl_bmi_fast_download(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
        return ret;
 }
 
+void ath6kl_bmi_reset(struct ath6kl *ar)
+{
+       ar->bmi.done_sent = false;
+}
+
 int ath6kl_bmi_init(struct ath6kl *ar)
 {
        ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC);
index 96851d5df24b604e6f6079728012a8c0dc7ef1cb..009e8f650ab1dc7f2f5de82c78fd9930074d846d 100644 (file)
@@ -230,6 +230,8 @@ struct ath6kl_bmi_target_info {
 
 int ath6kl_bmi_init(struct ath6kl *ar);
 void ath6kl_bmi_cleanup(struct ath6kl *ar);
+void ath6kl_bmi_reset(struct ath6kl *ar);
+
 int ath6kl_bmi_done(struct ath6kl *ar);
 int ath6kl_bmi_get_target_info(struct ath6kl *ar,
                               struct ath6kl_bmi_target_info *targ_info);
index 5ac2bc2ebee6e64fe2013fa72ada50884d3132a0..02526044acb925d4f360d2e6504e6326087f0c2a 100644 (file)
 #include "testmode.h"
 
 static unsigned int ath6kl_p2p;
+static unsigned int multi_norm_if_support;
 
 module_param(ath6kl_p2p, uint, 0644);
+module_param(multi_norm_if_support, uint, 0644);
 
 #define RATETAB_ENT(_rate, _rateid, _flags) {   \
        .bitrate    = (_rate),                  \
@@ -123,17 +125,19 @@ static struct ieee80211_supported_band ath6kl_band_5ghz = {
        .bitrates = ath6kl_a_rates,
 };
 
-static int ath6kl_set_wpa_version(struct ath6kl *ar,
+#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
+
+static int ath6kl_set_wpa_version(struct ath6kl_vif *vif,
                                  enum nl80211_wpa_versions wpa_version)
 {
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: %u\n", __func__, wpa_version);
 
        if (!wpa_version) {
-               ar->auth_mode = NONE_AUTH;
+               vif->auth_mode = NONE_AUTH;
        } else if (wpa_version & NL80211_WPA_VERSION_2) {
-               ar->auth_mode = WPA2_AUTH;
+               vif->auth_mode = WPA2_AUTH;
        } else if (wpa_version & NL80211_WPA_VERSION_1) {
-               ar->auth_mode = WPA_AUTH;
+               vif->auth_mode = WPA_AUTH;
        } else {
                ath6kl_err("%s: %u not supported\n", __func__, wpa_version);
                return -ENOTSUPP;
@@ -142,25 +146,24 @@ static int ath6kl_set_wpa_version(struct ath6kl *ar,
        return 0;
 }
 
-static int ath6kl_set_auth_type(struct ath6kl *ar,
+static int ath6kl_set_auth_type(struct ath6kl_vif *vif,
                                enum nl80211_auth_type auth_type)
 {
-
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, auth_type);
 
        switch (auth_type) {
        case NL80211_AUTHTYPE_OPEN_SYSTEM:
-               ar->dot11_auth_mode = OPEN_AUTH;
+               vif->dot11_auth_mode = OPEN_AUTH;
                break;
        case NL80211_AUTHTYPE_SHARED_KEY:
-               ar->dot11_auth_mode = SHARED_AUTH;
+               vif->dot11_auth_mode = SHARED_AUTH;
                break;
        case NL80211_AUTHTYPE_NETWORK_EAP:
-               ar->dot11_auth_mode = LEAP_AUTH;
+               vif->dot11_auth_mode = LEAP_AUTH;
                break;
 
        case NL80211_AUTHTYPE_AUTOMATIC:
-               ar->dot11_auth_mode = OPEN_AUTH | SHARED_AUTH;
+               vif->dot11_auth_mode = OPEN_AUTH | SHARED_AUTH;
                break;
 
        default:
@@ -171,11 +174,11 @@ static int ath6kl_set_auth_type(struct ath6kl *ar,
        return 0;
 }
 
-static int ath6kl_set_cipher(struct ath6kl *ar, u32 cipher, bool ucast)
+static int ath6kl_set_cipher(struct ath6kl_vif *vif, u32 cipher, bool ucast)
 {
-       u8 *ar_cipher = ucast ? &ar->prwise_crypto : &ar->grp_crypto;
-       u8 *ar_cipher_len = ucast ? &ar->prwise_crypto_len :
-               &ar->grp_crypto_len;
+       u8 *ar_cipher = ucast ? &vif->prwise_crypto : &vif->grp_crypto;
+       u8 *ar_cipher_len = ucast ? &vif->prwise_crypto_len :
+               &vif->grp_crypto_len;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n",
                   __func__, cipher, ucast);
@@ -210,28 +213,35 @@ static int ath6kl_set_cipher(struct ath6kl *ar, u32 cipher, bool ucast)
        return 0;
 }
 
-static void ath6kl_set_key_mgmt(struct ath6kl *ar, u32 key_mgmt)
+static void ath6kl_set_key_mgmt(struct ath6kl_vif *vif, u32 key_mgmt)
 {
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, key_mgmt);
 
        if (key_mgmt == WLAN_AKM_SUITE_PSK) {
-               if (ar->auth_mode == WPA_AUTH)
-                       ar->auth_mode = WPA_PSK_AUTH;
-               else if (ar->auth_mode == WPA2_AUTH)
-                       ar->auth_mode = WPA2_PSK_AUTH;
+               if (vif->auth_mode == WPA_AUTH)
+                       vif->auth_mode = WPA_PSK_AUTH;
+               else if (vif->auth_mode == WPA2_AUTH)
+                       vif->auth_mode = WPA2_PSK_AUTH;
+       } else if (key_mgmt == 0x00409600) {
+               if (vif->auth_mode == WPA_AUTH)
+                       vif->auth_mode = WPA_AUTH_CCKM;
+               else if (vif->auth_mode == WPA2_AUTH)
+                       vif->auth_mode = WPA2_AUTH_CCKM;
        } else if (key_mgmt != WLAN_AKM_SUITE_8021X) {
-               ar->auth_mode = NONE_AUTH;
+               vif->auth_mode = NONE_AUTH;
        }
 }
 
-static bool ath6kl_cfg80211_ready(struct ath6kl *ar)
+static bool ath6kl_cfg80211_ready(struct ath6kl_vif *vif)
 {
+       struct ath6kl *ar = vif->ar;
+
        if (!test_bit(WMI_READY, &ar->flag)) {
                ath6kl_err("wmi is not ready\n");
                return false;
        }
 
-       if (!test_bit(WLAN_ENABLED, &ar->flag)) {
+       if (!test_bit(WLAN_ENABLED, &vif->flags)) {
                ath6kl_err("wlan disabled\n");
                return false;
        }
@@ -239,15 +249,143 @@ static bool ath6kl_cfg80211_ready(struct ath6kl *ar)
        return true;
 }
 
+static bool ath6kl_is_wpa_ie(const u8 *pos)
+{
+       return pos[0] == WLAN_EID_WPA && pos[1] >= 4 &&
+               pos[2] == 0x00 && pos[3] == 0x50 &&
+               pos[4] == 0xf2 && pos[5] == 0x01;
+}
+
+static bool ath6kl_is_rsn_ie(const u8 *pos)
+{
+       return pos[0] == WLAN_EID_RSN;
+}
+
+static bool ath6kl_is_wps_ie(const u8 *pos)
+{
+       return (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
+               pos[1] >= 4 &&
+               pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xf2 &&
+               pos[5] == 0x04);
+}
+
+static int ath6kl_set_assoc_req_ies(struct ath6kl_vif *vif, const u8 *ies,
+                                   size_t ies_len)
+{
+       struct ath6kl *ar = vif->ar;
+       const u8 *pos;
+       u8 *buf = NULL;
+       size_t len = 0;
+       int ret;
+
+       /*
+        * Clear previously set flag
+        */
+
+       ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG;
+
+       /*
+        * Filter out RSN/WPA IE(s)
+        */
+
+       if (ies && ies_len) {
+               buf = kmalloc(ies_len, GFP_KERNEL);
+               if (buf == NULL)
+                       return -ENOMEM;
+               pos = ies;
+
+               while (pos + 1 < ies + ies_len) {
+                       if (pos + 2 + pos[1] > ies + ies_len)
+                               break;
+                       if (!(ath6kl_is_wpa_ie(pos) || ath6kl_is_rsn_ie(pos))) {
+                               memcpy(buf + len, pos, 2 + pos[1]);
+                               len += 2 + pos[1];
+                       }
+
+                       if (ath6kl_is_wps_ie(pos))
+                               ar->connect_ctrl_flags |= CONNECT_WPS_FLAG;
+
+                       pos += 2 + pos[1];
+               }
+       }
+
+       ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
+                                      WMI_FRAME_ASSOC_REQ, buf, len);
+       kfree(buf);
+       return ret;
+}
+
+static int ath6kl_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type)
+{
+       switch (type) {
+       case NL80211_IFTYPE_STATION:
+               *nw_type = INFRA_NETWORK;
+               break;
+       case NL80211_IFTYPE_ADHOC:
+               *nw_type = ADHOC_NETWORK;
+               break;
+       case NL80211_IFTYPE_AP:
+               *nw_type = AP_NETWORK;
+               break;
+       case NL80211_IFTYPE_P2P_CLIENT:
+               *nw_type = INFRA_NETWORK;
+               break;
+       case NL80211_IFTYPE_P2P_GO:
+               *nw_type = AP_NETWORK;
+               break;
+       default:
+               ath6kl_err("invalid interface type %u\n", type);
+               return -ENOTSUPP;
+       }
+
+       return 0;
+}
+
+static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
+                                  u8 *if_idx, u8 *nw_type)
+{
+       int i;
+
+       if (ath6kl_nliftype_to_drv_iftype(type, nw_type))
+               return false;
+
+       if (ar->ibss_if_active || ((type == NL80211_IFTYPE_ADHOC) &&
+           ar->num_vif))
+               return false;
+
+       if (type == NL80211_IFTYPE_STATION ||
+           type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) {
+               for (i = 0; i < MAX_NUM_VIF; i++) {
+                       if ((ar->avail_idx_map >> i) & BIT(0)) {
+                               *if_idx = i;
+                               return true;
+                       }
+               }
+       }
+
+       if (type == NL80211_IFTYPE_P2P_CLIENT ||
+           type == NL80211_IFTYPE_P2P_GO) {
+               for (i = ar->max_norm_iface; i < MAX_NUM_VIF; i++) {
+                       if ((ar->avail_idx_map >> i) & BIT(0)) {
+                               *if_idx = i;
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
 static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                                   struct cfg80211_connect_params *sme)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
        int status;
 
-       ar->sme_state = SME_CONNECTING;
+       vif->sme_state = SME_CONNECTING;
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
@@ -287,12 +425,19 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                }
        }
 
-       if (test_bit(CONNECTED, &ar->flag) &&
-           ar->ssid_len == sme->ssid_len &&
-           !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
-               ar->reconnect_flag = true;
-               status = ath6kl_wmi_reconnect_cmd(ar->wmi, ar->req_bssid,
-                                                 ar->ch_hint);
+       if (sme->ie && (sme->ie_len > 0)) {
+               status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len);
+               if (status)
+                       return status;
+       }
+
+       if (test_bit(CONNECTED, &vif->flags) &&
+           vif->ssid_len == sme->ssid_len &&
+           !memcmp(vif->ssid, sme->ssid, vif->ssid_len)) {
+               vif->reconnect_flag = true;
+               status = ath6kl_wmi_reconnect_cmd(ar->wmi, vif->fw_vif_idx,
+                                                 vif->req_bssid,
+                                                 vif->ch_hint);
 
                up(&ar->sem);
                if (status) {
@@ -300,42 +445,43 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                        return -EIO;
                }
                return 0;
-       } else if (ar->ssid_len == sme->ssid_len &&
-                  !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
-               ath6kl_disconnect(ar);
+       } else if (vif->ssid_len == sme->ssid_len &&
+                  !memcmp(vif->ssid, sme->ssid, vif->ssid_len)) {
+               ath6kl_disconnect(vif);
        }
 
-       memset(ar->ssid, 0, sizeof(ar->ssid));
-       ar->ssid_len = sme->ssid_len;
-       memcpy(ar->ssid, sme->ssid, sme->ssid_len);
+       memset(vif->ssid, 0, sizeof(vif->ssid));
+       vif->ssid_len = sme->ssid_len;
+       memcpy(vif->ssid, sme->ssid, sme->ssid_len);
 
        if (sme->channel)
-               ar->ch_hint = sme->channel->center_freq;
+               vif->ch_hint = sme->channel->center_freq;
 
-       memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
+       memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
        if (sme->bssid && !is_broadcast_ether_addr(sme->bssid))
-               memcpy(ar->req_bssid, sme->bssid, sizeof(ar->req_bssid));
+               memcpy(vif->req_bssid, sme->bssid, sizeof(vif->req_bssid));
 
-       ath6kl_set_wpa_version(ar, sme->crypto.wpa_versions);
+       ath6kl_set_wpa_version(vif, sme->crypto.wpa_versions);
 
-       status = ath6kl_set_auth_type(ar, sme->auth_type);
+       status = ath6kl_set_auth_type(vif, sme->auth_type);
        if (status) {
                up(&ar->sem);
                return status;
        }
 
        if (sme->crypto.n_ciphers_pairwise)
-               ath6kl_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true);
+               ath6kl_set_cipher(vif, sme->crypto.ciphers_pairwise[0], true);
        else
-               ath6kl_set_cipher(ar, 0, true);
+               ath6kl_set_cipher(vif, 0, true);
 
-       ath6kl_set_cipher(ar, sme->crypto.cipher_group, false);
+       ath6kl_set_cipher(vif, sme->crypto.cipher_group, false);
 
        if (sme->crypto.n_akm_suites)
-               ath6kl_set_key_mgmt(ar, sme->crypto.akm_suites[0]);
+               ath6kl_set_key_mgmt(vif, sme->crypto.akm_suites[0]);
 
        if ((sme->key_len) &&
-           (ar->auth_mode == NONE_AUTH) && (ar->prwise_crypto == WEP_CRYPT)) {
+           (vif->auth_mode == NONE_AUTH) &&
+           (vif->prwise_crypto == WEP_CRYPT)) {
                struct ath6kl_key *key = NULL;
 
                if (sme->key_idx < WMI_MIN_KEY_INDEX ||
@@ -346,56 +492,57 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                        return -ENOENT;
                }
 
-               key = &ar->keys[sme->key_idx];
+               key = &vif->keys[sme->key_idx];
                key->key_len = sme->key_len;
                memcpy(key->key, sme->key, key->key_len);
-               key->cipher = ar->prwise_crypto;
-               ar->def_txkey_index = sme->key_idx;
+               key->cipher = vif->prwise_crypto;
+               vif->def_txkey_index = sme->key_idx;
 
-               ath6kl_wmi_addkey_cmd(ar->wmi, sme->key_idx,
-                                     ar->prwise_crypto,
+               ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, sme->key_idx,
+                                     vif->prwise_crypto,
                                      GROUP_USAGE | TX_USAGE,
                                      key->key_len,
-                                     NULL,
+                                     NULL, 0,
                                      key->key, KEY_OP_INIT_VAL, NULL,
                                      NO_SYNC_WMIFLAG);
        }
 
        if (!ar->usr_bss_filter) {
-               clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
-               if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) {
+               clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
+               if (ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
+                   ALL_BSS_FILTER, 0) != 0) {
                        ath6kl_err("couldn't set bss filtering\n");
                        up(&ar->sem);
                        return -EIO;
                }
        }
 
-       ar->nw_type = ar->next_mode;
+       vif->nw_type = vif->next_mode;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                   "%s: connect called with authmode %d dot11 auth %d"
                   " PW crypto %d PW crypto len %d GRP crypto %d"
                   " GRP crypto len %d channel hint %u\n",
                   __func__,
-                  ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto,
-                  ar->prwise_crypto_len, ar->grp_crypto,
-                  ar->grp_crypto_len, ar->ch_hint);
-
-       ar->reconnect_flag = 0;
-       status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type,
-                                       ar->dot11_auth_mode, ar->auth_mode,
-                                       ar->prwise_crypto,
-                                       ar->prwise_crypto_len,
-                                       ar->grp_crypto, ar->grp_crypto_len,
-                                       ar->ssid_len, ar->ssid,
-                                       ar->req_bssid, ar->ch_hint,
+                  vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
+                  vif->prwise_crypto_len, vif->grp_crypto,
+                  vif->grp_crypto_len, vif->ch_hint);
+
+       vif->reconnect_flag = 0;
+       status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
+                                       vif->dot11_auth_mode, vif->auth_mode,
+                                       vif->prwise_crypto,
+                                       vif->prwise_crypto_len,
+                                       vif->grp_crypto, vif->grp_crypto_len,
+                                       vif->ssid_len, vif->ssid,
+                                       vif->req_bssid, vif->ch_hint,
                                        ar->connect_ctrl_flags);
 
        up(&ar->sem);
 
        if (status == -EINVAL) {
-               memset(ar->ssid, 0, sizeof(ar->ssid));
-               ar->ssid_len = 0;
+               memset(vif->ssid, 0, sizeof(vif->ssid));
+               vif->ssid_len = 0;
                ath6kl_err("invalid request\n");
                return -ENOENT;
        } else if (status) {
@@ -404,27 +551,28 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        }
 
        if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
-           ((ar->auth_mode == WPA_PSK_AUTH)
-            || (ar->auth_mode == WPA2_PSK_AUTH))) {
-               mod_timer(&ar->disconnect_timer,
+           ((vif->auth_mode == WPA_PSK_AUTH)
+            || (vif->auth_mode == WPA2_PSK_AUTH))) {
+               mod_timer(&vif->disconnect_timer,
                          jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
        }
 
        ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD;
-       set_bit(CONNECT_PEND, &ar->flag);
+       set_bit(CONNECT_PEND, &vif->flags);
 
        return 0;
 }
 
-static int ath6kl_add_bss_if_needed(struct ath6kl *ar, const u8 *bssid,
+static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, const u8 *bssid,
                                    struct ieee80211_channel *chan,
                                    const u8 *beacon_ie, size_t beacon_ie_len)
 {
+       struct ath6kl *ar = vif->ar;
        struct cfg80211_bss *bss;
        u8 *ie;
 
-       bss = cfg80211_get_bss(ar->wdev->wiphy, chan, bssid,
-                              ar->ssid, ar->ssid_len, WLAN_CAPABILITY_ESS,
+       bss = cfg80211_get_bss(ar->wiphy, chan, bssid,
+                              vif->ssid, vif->ssid_len, WLAN_CAPABILITY_ESS,
                               WLAN_CAPABILITY_ESS);
        if (bss == NULL) {
                /*
@@ -435,16 +583,16 @@ static int ath6kl_add_bss_if_needed(struct ath6kl *ar, const u8 *bssid,
                 * Prepend SSID element since it is not included in the Beacon
                 * IEs from the target.
                 */
-               ie = kmalloc(2 + ar->ssid_len + beacon_ie_len, GFP_KERNEL);
+               ie = kmalloc(2 + vif->ssid_len + beacon_ie_len, GFP_KERNEL);
                if (ie == NULL)
                        return -ENOMEM;
                ie[0] = WLAN_EID_SSID;
-               ie[1] = ar->ssid_len;
-               memcpy(ie + 2, ar->ssid, ar->ssid_len);
-               memcpy(ie + 2 + ar->ssid_len, beacon_ie, beacon_ie_len);
-               bss = cfg80211_inform_bss(ar->wdev->wiphy, chan,
+               ie[1] = vif->ssid_len;
+               memcpy(ie + 2, vif->ssid, vif->ssid_len);
+               memcpy(ie + 2 + vif->ssid_len, beacon_ie, beacon_ie_len);
+               bss = cfg80211_inform_bss(ar->wiphy, chan,
                                          bssid, 0, WLAN_CAPABILITY_ESS, 100,
-                                         ie, 2 + ar->ssid_len + beacon_ie_len,
+                                         ie, 2 + vif->ssid_len + beacon_ie_len,
                                          0, GFP_KERNEL);
                if (bss)
                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added dummy bss for "
@@ -463,7 +611,7 @@ static int ath6kl_add_bss_if_needed(struct ath6kl *ar, const u8 *bssid,
        return 0;
 }
 
-void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
+void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
                                   u8 *bssid, u16 listen_intvl,
                                   u16 beacon_intvl,
                                   enum network_type nw_type,
@@ -471,6 +619,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
                                   u8 assoc_resp_len, u8 *assoc_info)
 {
        struct ieee80211_channel *chan;
+       struct ath6kl *ar = vif->ar;
 
        /* capinfo + listen interval */
        u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16);
@@ -489,11 +638,11 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
         * Store Beacon interval here; DTIM period will be available only once
         * a Beacon frame from the AP is seen.
         */
-       ar->assoc_bss_beacon_int = beacon_intvl;
-       clear_bit(DTIM_PERIOD_AVAIL, &ar->flag);
+       vif->assoc_bss_beacon_int = beacon_intvl;
+       clear_bit(DTIM_PERIOD_AVAIL, &vif->flags);
 
        if (nw_type & ADHOC_NETWORK) {
-               if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) {
+               if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                                   "%s: ath6k not in ibss mode\n", __func__);
                        return;
@@ -501,39 +650,39 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
        }
 
        if (nw_type & INFRA_NETWORK) {
-               if (ar->wdev->iftype != NL80211_IFTYPE_STATION &&
-                   ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) {
+               if (vif->wdev.iftype != NL80211_IFTYPE_STATION &&
+                   vif->wdev.iftype != NL80211_IFTYPE_P2P_CLIENT) {
                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                                   "%s: ath6k not in station mode\n", __func__);
                        return;
                }
        }
 
-       chan = ieee80211_get_channel(ar->wdev->wiphy, (int) channel);
+       chan = ieee80211_get_channel(ar->wiphy, (int) channel);
 
 
        if (nw_type & ADHOC_NETWORK) {
-               cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL);
+               cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
                return;
        }
 
-       if (ath6kl_add_bss_if_needed(ar, bssid, chan, assoc_info,
+       if (ath6kl_add_bss_if_needed(vif, bssid, chan, assoc_info,
                                     beacon_ie_len) < 0) {
                ath6kl_err("could not add cfg80211 bss entry for "
                           "connect/roamed notification\n");
                return;
        }
 
-       if (ar->sme_state == SME_CONNECTING) {
+       if (vif->sme_state == SME_CONNECTING) {
                /* inform connect result to cfg80211 */
-               ar->sme_state = SME_CONNECTED;
-               cfg80211_connect_result(ar->net_dev, bssid,
+               vif->sme_state = SME_CONNECTED;
+               cfg80211_connect_result(vif->ndev, bssid,
                                        assoc_req_ie, assoc_req_len,
                                        assoc_resp_ie, assoc_resp_len,
                                        WLAN_STATUS_SUCCESS, GFP_KERNEL);
-       } else if (ar->sme_state == SME_CONNECTED) {
+       } else if (vif->sme_state == SME_CONNECTED) {
                /* inform roam event to cfg80211 */
-               cfg80211_roamed(ar->net_dev, chan, bssid,
+               cfg80211_roamed(vif->ndev, chan, bssid,
                                assoc_req_ie, assoc_req_len,
                                assoc_resp_ie, assoc_resp_len, GFP_KERNEL);
        }
@@ -543,11 +692,12 @@ static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
                                      struct net_device *dev, u16 reason_code)
 {
        struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__,
                   reason_code);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
@@ -560,44 +710,46 @@ static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
                return -ERESTARTSYS;
        }
 
-       ar->reconnect_flag = 0;
-       ath6kl_disconnect(ar);
-       memset(ar->ssid, 0, sizeof(ar->ssid));
-       ar->ssid_len = 0;
+       vif->reconnect_flag = 0;
+       ath6kl_disconnect(vif);
+       memset(vif->ssid, 0, sizeof(vif->ssid));
+       vif->ssid_len = 0;
 
        if (!test_bit(SKIP_SCAN, &ar->flag))
-               memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
+               memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
 
        up(&ar->sem);
 
-       ar->sme_state = SME_DISCONNECTED;
+       vif->sme_state = SME_DISCONNECTED;
 
        return 0;
 }
 
-void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
+void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
                                      u8 *bssid, u8 assoc_resp_len,
                                      u8 *assoc_info, u16 proto_reason)
 {
-       if (ar->scan_req) {
-               cfg80211_scan_done(ar->scan_req, true);
-               ar->scan_req = NULL;
+       struct ath6kl *ar = vif->ar;
+
+       if (vif->scan_req) {
+               cfg80211_scan_done(vif->scan_req, true);
+               vif->scan_req = NULL;
        }
 
-       if (ar->nw_type & ADHOC_NETWORK) {
-               if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) {
+       if (vif->nw_type & ADHOC_NETWORK) {
+               if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                                   "%s: ath6k not in ibss mode\n", __func__);
                        return;
                }
                memset(bssid, 0, ETH_ALEN);
-               cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL);
+               cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
                return;
        }
 
-       if (ar->nw_type & INFRA_NETWORK) {
-               if (ar->wdev->iftype != NL80211_IFTYPE_STATION &&
-                   ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) {
+       if (vif->nw_type & INFRA_NETWORK) {
+               if (vif->wdev.iftype != NL80211_IFTYPE_STATION &&
+                   vif->wdev.iftype != NL80211_IFTYPE_P2P_CLIENT) {
                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                                   "%s: ath6k not in station mode\n", __func__);
                        return;
@@ -614,42 +766,44 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
         */
 
        if (reason != DISCONNECT_CMD) {
-               ath6kl_wmi_disconnect_cmd(ar->wmi);
+               ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
                return;
        }
 
-       clear_bit(CONNECT_PEND, &ar->flag);
+       clear_bit(CONNECT_PEND, &vif->flags);
 
-       if (ar->sme_state == SME_CONNECTING) {
-               cfg80211_connect_result(ar->net_dev,
+       if (vif->sme_state == SME_CONNECTING) {
+               cfg80211_connect_result(vif->ndev,
                                bssid, NULL, 0,
                                NULL, 0,
                                WLAN_STATUS_UNSPECIFIED_FAILURE,
                                GFP_KERNEL);
-       } else if (ar->sme_state == SME_CONNECTED) {
-               cfg80211_disconnected(ar->net_dev, reason,
+       } else if (vif->sme_state == SME_CONNECTED) {
+               cfg80211_disconnected(vif->ndev, reason,
                                NULL, 0, GFP_KERNEL);
        }
 
-       ar->sme_state = SME_DISCONNECTED;
+       vif->sme_state = SME_DISCONNECTED;
 }
 
 static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                                struct cfg80211_scan_request *request)
 {
        struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+       struct ath6kl_vif *vif = netdev_priv(ndev);
        s8 n_channels = 0;
        u16 *channels = NULL;
        int ret = 0;
+       u32 force_fg_scan = 0;
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        if (!ar->usr_bss_filter) {
-               clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
+               clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
                ret = ath6kl_wmi_bssfilter_cmd(
-                       ar->wmi,
-                       (test_bit(CONNECTED, &ar->flag) ?
+                       ar->wmi, vif->fw_vif_idx,
+                       (test_bit(CONNECTED, &vif->flags) ?
                         ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0);
                if (ret) {
                        ath6kl_err("couldn't set bss filtering\n");
@@ -664,14 +818,15 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                        request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
 
                for (i = 0; i < request->n_ssids; i++)
-                       ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1,
-                                                 SPECIFIC_SSID_FLAG,
+                       ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
+                                                 i + 1, SPECIFIC_SSID_FLAG,
                                                  request->ssids[i].ssid_len,
                                                  request->ssids[i].ssid);
        }
 
        if (request->ie) {
-               ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_REQ,
+               ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
+                                              WMI_FRAME_PROBE_REQ,
                                               request->ie, request->ie_len);
                if (ret) {
                        ath6kl_err("failed to set Probe Request appie for "
@@ -702,44 +857,47 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                        channels[i] = request->channels[i]->center_freq;
        }
 
-       ret = ath6kl_wmi_startscan_cmd(ar->wmi, WMI_LONG_SCAN, 0,
-                                      false, 0, 0, n_channels, channels);
+       if (test_bit(CONNECTED, &vif->flags))
+               force_fg_scan = 1;
+
+       ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx, WMI_LONG_SCAN,
+                                      force_fg_scan, false, 0, 0, n_channels,
+                                      channels);
        if (ret)
                ath6kl_err("wmi_startscan_cmd failed\n");
        else
-               ar->scan_req = request;
+               vif->scan_req = request;
 
        kfree(channels);
 
        return ret;
 }
 
-void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status)
+void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
 {
+       struct ath6kl *ar = vif->ar;
        int i;
 
-       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status %d\n", __func__, status);
+       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__,
+                  aborted ? " aborted" : "");
 
-       if (!ar->scan_req)
+       if (!vif->scan_req)
                return;
 
-       if ((status == -ECANCELED) || (status == -EBUSY)) {
-               cfg80211_scan_done(ar->scan_req, true);
+       if (aborted)
                goto out;
-       }
-
-       cfg80211_scan_done(ar->scan_req, false);
 
-       if (ar->scan_req->n_ssids && ar->scan_req->ssids[0].ssid_len) {
-               for (i = 0; i < ar->scan_req->n_ssids; i++) {
-                       ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1,
-                                                 DISABLE_SSID_FLAG,
+       if (vif->scan_req->n_ssids && vif->scan_req->ssids[0].ssid_len) {
+               for (i = 0; i < vif->scan_req->n_ssids; i++) {
+                       ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
+                                                 i + 1, DISABLE_SSID_FLAG,
                                                  0, NULL);
                }
        }
 
 out:
-       ar->scan_req = NULL;
+       cfg80211_scan_done(vif->scan_req, aborted);
+       vif->scan_req = NULL;
 }
 
 static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
@@ -748,14 +906,21 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                                   struct key_params *params)
 {
        struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+       struct ath6kl_vif *vif = netdev_priv(ndev);
        struct ath6kl_key *key = NULL;
        u8 key_usage;
        u8 key_type;
-       int status = 0;
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
+       if (params->cipher == CCKM_KRK_CIPHER_SUITE) {
+               if (params->key_len != WMI_KRK_LEN)
+                       return -EINVAL;
+               return ath6kl_wmi_add_krk_cmd(ar->wmi, vif->fw_vif_idx,
+                                             params->key);
+       }
+
        if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                           "%s: key index %d out of bounds\n", __func__,
@@ -763,7 +928,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                return -ENOENT;
        }
 
-       key = &ar->keys[key_index];
+       key = &vif->keys[key_index];
        memset(key, 0, sizeof(struct ath6kl_key));
 
        if (pairwise)
@@ -801,26 +966,26 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                return -ENOTSUPP;
        }
 
-       if (((ar->auth_mode == WPA_PSK_AUTH)
-            || (ar->auth_mode == WPA2_PSK_AUTH))
+       if (((vif->auth_mode == WPA_PSK_AUTH)
+            || (vif->auth_mode == WPA2_PSK_AUTH))
            && (key_usage & GROUP_USAGE))
-               del_timer(&ar->disconnect_timer);
+               del_timer(&vif->disconnect_timer);
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                   "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n",
                   __func__, key_index, key->key_len, key_type,
                   key_usage, key->seq_len);
 
-       ar->def_txkey_index = key_index;
+       vif->def_txkey_index = key_index;
 
-       if (ar->nw_type == AP_NETWORK && !pairwise &&
+       if (vif->nw_type == AP_NETWORK && !pairwise &&
            (key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) {
                ar->ap_mode_bkey.valid = true;
                ar->ap_mode_bkey.key_index = key_index;
                ar->ap_mode_bkey.key_type = key_type;
                ar->ap_mode_bkey.key_len = key->key_len;
                memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
-               if (!test_bit(CONNECTED, &ar->flag)) {
+               if (!test_bit(CONNECTED, &vif->flags)) {
                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
                                   "key configuration until AP mode has been "
                                   "started\n");
@@ -832,8 +997,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                }
        }
 
-       if (ar->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
-           !test_bit(CONNECTED, &ar->flag)) {
+       if (vif->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
+           !test_bit(CONNECTED, &vif->flags)) {
                /*
                 * Store the key locally so that it can be re-configured after
                 * the AP mode has properly started
@@ -841,20 +1006,18 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                 */
                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
                           "until AP mode has been started\n");
-               ar->wep_key_list[key_index].key_len = key->key_len;
-               memcpy(ar->wep_key_list[key_index].key, key->key, key->key_len);
+               vif->wep_key_list[key_index].key_len = key->key_len;
+               memcpy(vif->wep_key_list[key_index].key, key->key,
+                      key->key_len);
                return 0;
        }
 
-       status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
-                                      key_type, key_usage, key->key_len,
-                                      key->seq, key->key, KEY_OP_INIT_VAL,
-                                      (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
-
-       if (status)
-               return -EIO;
-
-       return 0;
+       return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx,
+                                    vif->def_txkey_index,
+                                    key_type, key_usage, key->key_len,
+                                    key->seq, key->seq_len, key->key,
+                                    KEY_OP_INIT_VAL,
+                                    (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
 }
 
 static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
@@ -862,10 +1025,11 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
                                   const u8 *mac_addr)
 {
        struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+       struct ath6kl_vif *vif = netdev_priv(ndev);
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
@@ -875,15 +1039,15 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
                return -ENOENT;
        }
 
-       if (!ar->keys[key_index].key_len) {
+       if (!vif->keys[key_index].key_len) {
                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                           "%s: index %d is empty\n", __func__, key_index);
                return 0;
        }
 
-       ar->keys[key_index].key_len = 0;
+       vif->keys[key_index].key_len = 0;
 
-       return ath6kl_wmi_deletekey_cmd(ar->wmi, key_index);
+       return ath6kl_wmi_deletekey_cmd(ar->wmi, vif->fw_vif_idx, key_index);
 }
 
 static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
@@ -892,13 +1056,13 @@ static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
                                   void (*callback) (void *cookie,
                                                     struct key_params *))
 {
-       struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+       struct ath6kl_vif *vif = netdev_priv(ndev);
        struct ath6kl_key *key = NULL;
        struct key_params params;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
@@ -908,7 +1072,7 @@ static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
                return -ENOENT;
        }
 
-       key = &ar->keys[key_index];
+       key = &vif->keys[key_index];
        memset(&params, 0, sizeof(params));
        params.cipher = key->cipher;
        params.key_len = key->key_len;
@@ -927,14 +1091,14 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
                                           bool multicast)
 {
        struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+       struct ath6kl_vif *vif = netdev_priv(ndev);
        struct ath6kl_key *key = NULL;
-       int status = 0;
        u8 key_usage;
        enum crypto_type key_type = NONE_CRYPT;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
@@ -944,43 +1108,41 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
                return -ENOENT;
        }
 
-       if (!ar->keys[key_index].key_len) {
+       if (!vif->keys[key_index].key_len) {
                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
                           __func__, key_index);
                return -EINVAL;
        }
 
-       ar->def_txkey_index = key_index;
-       key = &ar->keys[ar->def_txkey_index];
+       vif->def_txkey_index = key_index;
+       key = &vif->keys[vif->def_txkey_index];
        key_usage = GROUP_USAGE;
-       if (ar->prwise_crypto == WEP_CRYPT)
+       if (vif->prwise_crypto == WEP_CRYPT)
                key_usage |= TX_USAGE;
        if (unicast)
-               key_type = ar->prwise_crypto;
+               key_type = vif->prwise_crypto;
        if (multicast)
-               key_type = ar->grp_crypto;
+               key_type = vif->grp_crypto;
 
-       if (ar->next_mode == AP_NETWORK && !test_bit(CONNECTED, &ar->flag))
+       if (vif->next_mode == AP_NETWORK && !test_bit(CONNECTED, &vif->flags))
                return 0; /* Delay until AP mode has been started */
 
-       status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
-                                      key_type, key_usage,
-                                      key->key_len, key->seq, key->key,
-                                      KEY_OP_INIT_VAL, NULL,
-                                      SYNC_BOTH_WMIFLAG);
-       if (status)
-               return -EIO;
-
-       return 0;
+       return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx,
+                                    vif->def_txkey_index,
+                                    key_type, key_usage,
+                                    key->key_len, key->seq, key->seq_len,
+                                    key->key,
+                                    KEY_OP_INIT_VAL, NULL,
+                                    SYNC_BOTH_WMIFLAG);
 }
 
-void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid,
+void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
                                       bool ismcast)
 {
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                   "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast);
 
-       cfg80211_michael_mic_failure(ar->net_dev, ar->bssid,
+       cfg80211_michael_mic_failure(vif->ndev, vif->bssid,
                                     (ismcast ? NL80211_KEYTYPE_GROUP :
                                      NL80211_KEYTYPE_PAIRWISE), keyid, NULL,
                                     GFP_KERNEL);
@@ -989,12 +1151,17 @@ void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid,
 static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 {
        struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
+       struct ath6kl_vif *vif;
        int ret;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
                   changed);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       vif = ath6kl_vif_first(ar);
+       if (!vif)
+               return -EIO;
+
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
@@ -1017,12 +1184,17 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
                                       int dbm)
 {
        struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
+       struct ath6kl_vif *vif;
        u8 ath6kl_dbm;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
                   type, dbm);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       vif = ath6kl_vif_first(ar);
+       if (!vif)
+               return -EIO;
+
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        switch (type) {
@@ -1037,7 +1209,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
                return -EOPNOTSUPP;
        }
 
-       ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, ath6kl_dbm);
+       ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, ath6kl_dbm);
 
        return 0;
 }
@@ -1045,14 +1217,19 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
 static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
 {
        struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
+       struct ath6kl_vif *vif;
 
-       if (!ath6kl_cfg80211_ready(ar))
+       vif = ath6kl_vif_first(ar);
+       if (!vif)
                return -EIO;
 
-       if (test_bit(CONNECTED, &ar->flag)) {
+       if (!ath6kl_cfg80211_ready(vif))
+               return -EIO;
+
+       if (test_bit(CONNECTED, &vif->flags)) {
                ar->tx_pwr = 0;
 
-               if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi) != 0) {
+               if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx) != 0) {
                        ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
                        return -EIO;
                }
@@ -1076,11 +1253,12 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
 {
        struct ath6kl *ar = ath6kl_priv(dev);
        struct wmi_power_mode_cmd mode;
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
                   __func__, pmgmt, timeout);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        if (pmgmt) {
@@ -1091,7 +1269,8 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
                mode.pwr_mode = MAX_PERF_POWER;
        }
 
-       if (ath6kl_wmi_powermode_cmd(ar->wmi, mode.pwr_mode) != 0) {
+       if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx,
+            mode.pwr_mode) != 0) {
                ath6kl_err("wmi_powermode_cmd failed\n");
                return -EIO;
        }
@@ -1099,41 +1278,86 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
        return 0;
 }
 
+static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
+                                                   char *name,
+                                                   enum nl80211_iftype type,
+                                                   u32 *flags,
+                                                   struct vif_params *params)
+{
+       struct ath6kl *ar = wiphy_priv(wiphy);
+       struct net_device *ndev;
+       u8 if_idx, nw_type;
+
+       if (ar->num_vif == MAX_NUM_VIF) {
+               ath6kl_err("Reached maximum number of supported vif\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (!ath6kl_is_valid_iftype(ar, type, &if_idx, &nw_type)) {
+               ath6kl_err("Not a supported interface type\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       ndev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
+       if (!ndev)
+               return ERR_PTR(-ENOMEM);
+
+       ar->num_vif++;
+
+       return ndev;
+}
+
+static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
+                                    struct net_device *ndev)
+{
+       struct ath6kl *ar = wiphy_priv(wiphy);
+       struct ath6kl_vif *vif = netdev_priv(ndev);
+
+       spin_lock_bh(&ar->list_lock);
+       list_del(&vif->list);
+       spin_unlock_bh(&ar->list_lock);
+
+       ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
+
+       ath6kl_deinit_if_data(vif);
+
+       return 0;
+}
+
 static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
                                        struct net_device *ndev,
                                        enum nl80211_iftype type, u32 *flags,
                                        struct vif_params *params)
 {
-       struct ath6kl *ar = ath6kl_priv(ndev);
-       struct wireless_dev *wdev = ar->wdev;
+       struct ath6kl_vif *vif = netdev_priv(ndev);
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        switch (type) {
        case NL80211_IFTYPE_STATION:
-               ar->next_mode = INFRA_NETWORK;
+               vif->next_mode = INFRA_NETWORK;
                break;
        case NL80211_IFTYPE_ADHOC:
-               ar->next_mode = ADHOC_NETWORK;
+               vif->next_mode = ADHOC_NETWORK;
                break;
        case NL80211_IFTYPE_AP:
-               ar->next_mode = AP_NETWORK;
+               vif->next_mode = AP_NETWORK;
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
-               ar->next_mode = INFRA_NETWORK;
+               vif->next_mode = INFRA_NETWORK;
                break;
        case NL80211_IFTYPE_P2P_GO:
-               ar->next_mode = AP_NETWORK;
+               vif->next_mode = AP_NETWORK;
                break;
        default:
                ath6kl_err("invalid interface type %u\n", type);
                return -EOPNOTSUPP;
        }
 
-       wdev->iftype = type;
+       vif->wdev.iftype = type;
 
        return 0;
 }
@@ -1143,16 +1367,17 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
                                     struct cfg80211_ibss_params *ibss_param)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
        int status;
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
-       ar->ssid_len = ibss_param->ssid_len;
-       memcpy(ar->ssid, ibss_param->ssid, ar->ssid_len);
+       vif->ssid_len = ibss_param->ssid_len;
+       memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
 
        if (ibss_param->channel)
-               ar->ch_hint = ibss_param->channel->center_freq;
+               vif->ch_hint = ibss_param->channel->center_freq;
 
        if (ibss_param->channel_fixed) {
                /*
@@ -1164,44 +1389,45 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
                return -EOPNOTSUPP;
        }
 
-       memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
+       memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
        if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid))
-               memcpy(ar->req_bssid, ibss_param->bssid, sizeof(ar->req_bssid));
+               memcpy(vif->req_bssid, ibss_param->bssid,
+                      sizeof(vif->req_bssid));
 
-       ath6kl_set_wpa_version(ar, 0);
+       ath6kl_set_wpa_version(vif, 0);
 
-       status = ath6kl_set_auth_type(ar, NL80211_AUTHTYPE_OPEN_SYSTEM);
+       status = ath6kl_set_auth_type(vif, NL80211_AUTHTYPE_OPEN_SYSTEM);
        if (status)
                return status;
 
        if (ibss_param->privacy) {
-               ath6kl_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, true);
-               ath6kl_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, false);
+               ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, true);
+               ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, false);
        } else {
-               ath6kl_set_cipher(ar, 0, true);
-               ath6kl_set_cipher(ar, 0, false);
+               ath6kl_set_cipher(vif, 0, true);
+               ath6kl_set_cipher(vif, 0, false);
        }
 
-       ar->nw_type = ar->next_mode;
+       vif->nw_type = vif->next_mode;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                   "%s: connect called with authmode %d dot11 auth %d"
                   " PW crypto %d PW crypto len %d GRP crypto %d"
                   " GRP crypto len %d channel hint %u\n",
                   __func__,
-                  ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto,
-                  ar->prwise_crypto_len, ar->grp_crypto,
-                  ar->grp_crypto_len, ar->ch_hint);
-
-       status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type,
-                                       ar->dot11_auth_mode, ar->auth_mode,
-                                       ar->prwise_crypto,
-                                       ar->prwise_crypto_len,
-                                       ar->grp_crypto, ar->grp_crypto_len,
-                                       ar->ssid_len, ar->ssid,
-                                       ar->req_bssid, ar->ch_hint,
+                  vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
+                  vif->prwise_crypto_len, vif->grp_crypto,
+                  vif->grp_crypto_len, vif->ch_hint);
+
+       status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
+                                       vif->dot11_auth_mode, vif->auth_mode,
+                                       vif->prwise_crypto,
+                                       vif->prwise_crypto_len,
+                                       vif->grp_crypto, vif->grp_crypto_len,
+                                       vif->ssid_len, vif->ssid,
+                                       vif->req_bssid, vif->ch_hint,
                                        ar->connect_ctrl_flags);
-       set_bit(CONNECT_PEND, &ar->flag);
+       set_bit(CONNECT_PEND, &vif->flags);
 
        return 0;
 }
@@ -1209,14 +1435,14 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
 static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
                                      struct net_device *dev)
 {
-       struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
-       ath6kl_disconnect(ar);
-       memset(ar->ssid, 0, sizeof(ar->ssid));
-       ar->ssid_len = 0;
+       ath6kl_disconnect(vif);
+       memset(vif->ssid, 0, sizeof(vif->ssid));
+       vif->ssid_len = 0;
 
        return 0;
 }
@@ -1226,6 +1452,7 @@ static const u32 cipher_suites[] = {
        WLAN_CIPHER_SUITE_WEP104,
        WLAN_CIPHER_SUITE_TKIP,
        WLAN_CIPHER_SUITE_CCMP,
+       CCKM_KRK_CIPHER_SUITE,
 };
 
 static bool is_rate_legacy(s32 rate)
@@ -1293,21 +1520,22 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
                              u8 *mac, struct station_info *sinfo)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
        long left;
        bool sgi;
        s32 rate;
        int ret;
        u8 mcs;
 
-       if (memcmp(mac, ar->bssid, ETH_ALEN) != 0)
+       if (memcmp(mac, vif->bssid, ETH_ALEN) != 0)
                return -ENOENT;
 
        if (down_interruptible(&ar->sem))
                return -EBUSY;
 
-       set_bit(STATS_UPDATE_PEND, &ar->flag);
+       set_bit(STATS_UPDATE_PEND, &vif->flags);
 
-       ret = ath6kl_wmi_get_stats_cmd(ar->wmi);
+       ret = ath6kl_wmi_get_stats_cmd(ar->wmi, vif->fw_vif_idx);
 
        if (ret != 0) {
                up(&ar->sem);
@@ -1316,7 +1544,7 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
 
        left = wait_event_interruptible_timeout(ar->event_wq,
                                                !test_bit(STATS_UPDATE_PEND,
-                                                         &ar->flag),
+                                                         &vif->flags),
                                                WMI_TIMEOUT);
 
        up(&ar->sem);
@@ -1326,24 +1554,24 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
        else if (left < 0)
                return left;
 
-       if (ar->target_stats.rx_byte) {
-               sinfo->rx_bytes = ar->target_stats.rx_byte;
+       if (vif->target_stats.rx_byte) {
+               sinfo->rx_bytes = vif->target_stats.rx_byte;
                sinfo->filled |= STATION_INFO_RX_BYTES;
-               sinfo->rx_packets = ar->target_stats.rx_pkt;
+               sinfo->rx_packets = vif->target_stats.rx_pkt;
                sinfo->filled |= STATION_INFO_RX_PACKETS;
        }
 
-       if (ar->target_stats.tx_byte) {
-               sinfo->tx_bytes = ar->target_stats.tx_byte;
+       if (vif->target_stats.tx_byte) {
+               sinfo->tx_bytes = vif->target_stats.tx_byte;
                sinfo->filled |= STATION_INFO_TX_BYTES;
-               sinfo->tx_packets = ar->target_stats.tx_pkt;
+               sinfo->tx_packets = vif->target_stats.tx_pkt;
                sinfo->filled |= STATION_INFO_TX_PACKETS;
        }
 
-       sinfo->signal = ar->target_stats.cs_rssi;
+       sinfo->signal = vif->target_stats.cs_rssi;
        sinfo->filled |= STATION_INFO_SIGNAL;
 
-       rate = ar->target_stats.tx_ucast_rate;
+       rate = vif->target_stats.tx_ucast_rate;
 
        if (is_rate_legacy(rate)) {
                sinfo->txrate.legacy = rate / 100;
@@ -1375,13 +1603,13 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
 
        sinfo->filled |= STATION_INFO_TX_BITRATE;
 
-       if (test_bit(CONNECTED, &ar->flag) &&
-           test_bit(DTIM_PERIOD_AVAIL, &ar->flag) &&
-           ar->nw_type == INFRA_NETWORK) {
+       if (test_bit(CONNECTED, &vif->flags) &&
+           test_bit(DTIM_PERIOD_AVAIL, &vif->flags) &&
+           vif->nw_type == INFRA_NETWORK) {
                sinfo->filled |= STATION_INFO_BSS_PARAM;
                sinfo->bss_param.flags = 0;
-               sinfo->bss_param.dtim_period = ar->assoc_bss_dtim_period;
-               sinfo->bss_param.beacon_interval = ar->assoc_bss_beacon_int;
+               sinfo->bss_param.dtim_period = vif->assoc_bss_dtim_period;
+               sinfo->bss_param.beacon_interval = vif->assoc_bss_beacon_int;
        }
 
        return 0;
@@ -1391,7 +1619,9 @@ static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
                            struct cfg80211_pmksa *pmksa)
 {
        struct ath6kl *ar = ath6kl_priv(netdev);
-       return ath6kl_wmi_setpmkid_cmd(ar->wmi, pmksa->bssid,
+       struct ath6kl_vif *vif = netdev_priv(netdev);
+
+       return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
                                       pmksa->pmkid, true);
 }
 
@@ -1399,25 +1629,292 @@ static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
                            struct cfg80211_pmksa *pmksa)
 {
        struct ath6kl *ar = ath6kl_priv(netdev);
-       return ath6kl_wmi_setpmkid_cmd(ar->wmi, pmksa->bssid,
+       struct ath6kl_vif *vif = netdev_priv(netdev);
+
+       return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
                                       pmksa->pmkid, false);
 }
 
 static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
 {
        struct ath6kl *ar = ath6kl_priv(netdev);
-       if (test_bit(CONNECTED, &ar->flag))
-               return ath6kl_wmi_setpmkid_cmd(ar->wmi, ar->bssid, NULL, false);
+       struct ath6kl_vif *vif = netdev_priv(netdev);
+
+       if (test_bit(CONNECTED, &vif->flags))
+               return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx,
+                                              vif->bssid, NULL, false);
+       return 0;
+}
+
+static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
+{
+       struct ath6kl_vif *vif;
+       int ret, pos, left;
+       u32 filter = 0;
+       u16 i;
+       u8 mask[WOW_MASK_SIZE];
+
+       vif = ath6kl_vif_first(ar);
+       if (!vif)
+               return -EIO;
+
+       if (!ath6kl_cfg80211_ready(vif))
+               return -EIO;
+
+       if (!test_bit(CONNECTED, &vif->flags))
+               return -EINVAL;
+
+       /* Clear existing WOW patterns */
+       for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
+               ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
+                                              WOW_LIST_ID, i);
+       /* Configure new WOW patterns */
+       for (i = 0; i < wow->n_patterns; i++) {
+
+               /*
+                * Convert given nl80211 specific mask value to equivalent
+                * driver specific mask value and send it to the chip along
+                * with patterns. For example, If the mask value defined in
+                * struct cfg80211_wowlan is 0xA (equivalent binary is 1010),
+                * then equivalent driver specific mask value is
+                * "0xFF 0x00 0xFF 0x00".
+                */
+               memset(&mask, 0, sizeof(mask));
+               for (pos = 0; pos < wow->patterns[i].pattern_len; pos++) {
+                       if (wow->patterns[i].mask[pos / 8] & (0x1 << (pos % 8)))
+                               mask[pos] = 0xFF;
+               }
+               /*
+                * Note: Pattern's offset is not passed as part of wowlan
+                * parameter from CFG layer. So it's always passed as ZERO
+                * to the firmware. It means, given WOW patterns are always
+                * matched from the first byte of received pkt in the firmware.
+                */
+               ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
+                                       vif->fw_vif_idx, WOW_LIST_ID,
+                                       wow->patterns[i].pattern_len,
+                                       0 /* pattern offset */,
+                                       wow->patterns[i].pattern, mask);
+               if (ret)
+                       return ret;
+       }
+
+       if (wow->disconnect)
+               filter |= WOW_FILTER_OPTION_NWK_DISASSOC;
+
+       if (wow->magic_pkt)
+               filter |= WOW_FILTER_OPTION_MAGIC_PACKET;
+
+       if (wow->gtk_rekey_failure)
+               filter |= WOW_FILTER_OPTION_GTK_ERROR;
+
+       if (wow->eap_identity_req)
+               filter |= WOW_FILTER_OPTION_EAP_REQ;
+
+       if (wow->four_way_handshake)
+               filter |= WOW_FILTER_OPTION_8021X_4WAYHS;
+
+       ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
+                                         ATH6KL_WOW_MODE_ENABLE,
+                                         filter,
+                                         WOW_HOST_REQ_DELAY);
+       if (ret)
+               return ret;
+
+       ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
+                                                ATH6KL_HOST_MODE_ASLEEP);
+       if (ret)
+               return ret;
+
+       if (ar->tx_pending[ar->ctrl_ep]) {
+               left = wait_event_interruptible_timeout(ar->event_wq,
+                               ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT);
+               if (left == 0) {
+                       ath6kl_warn("clear wmi ctrl data timeout\n");
+                       ret = -ETIMEDOUT;
+               } else if (left < 0) {
+                       ath6kl_warn("clear wmi ctrl data failed: %d\n", left);
+                       ret = left;
+               }
+       }
+
+       return ret;
+}
+
+static int ath6kl_wow_resume(struct ath6kl *ar)
+{
+       struct ath6kl_vif *vif;
+       int ret;
+
+       vif = ath6kl_vif_first(ar);
+       if (!vif)
+               return -EIO;
+
+       ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
+                                                ATH6KL_HOST_MODE_AWAKE);
+       return ret;
+}
+
+int ath6kl_cfg80211_suspend(struct ath6kl *ar,
+                           enum ath6kl_cfg_suspend_mode mode,
+                           struct cfg80211_wowlan *wow)
+{
+       int ret;
+
+       switch (mode) {
+       case ATH6KL_CFG_SUSPEND_WOW:
+
+               ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode suspend\n");
+
+               /* Flush all non control pkts in TX path */
+               ath6kl_tx_data_cleanup(ar);
+
+               ret = ath6kl_wow_suspend(ar, wow);
+               if (ret) {
+                       ath6kl_err("wow suspend failed: %d\n", ret);
+                       return ret;
+               }
+               ar->state = ATH6KL_STATE_WOW;
+               break;
+
+       case ATH6KL_CFG_SUSPEND_DEEPSLEEP:
+
+               ath6kl_cfg80211_stop(ar);
+
+               /* save the current power mode before enabling power save */
+               ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
+
+               ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
+               if (ret) {
+                       ath6kl_warn("wmi powermode command failed during suspend: %d\n",
+                                   ret);
+               }
+
+               ar->state = ATH6KL_STATE_DEEPSLEEP;
+
+               break;
+
+       case ATH6KL_CFG_SUSPEND_CUTPOWER:
+
+               ath6kl_cfg80211_stop(ar);
+
+               if (ar->state == ATH6KL_STATE_OFF) {
+                       ath6kl_dbg(ATH6KL_DBG_SUSPEND,
+                                  "suspend hw off, no action for cutpower\n");
+                       break;
+               }
+
+               ath6kl_dbg(ATH6KL_DBG_SUSPEND, "suspend cutting power\n");
+
+               ret = ath6kl_init_hw_stop(ar);
+               if (ret) {
+                       ath6kl_warn("failed to stop hw during suspend: %d\n",
+                                   ret);
+               }
+
+               ar->state = ATH6KL_STATE_CUTPOWER;
+
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+int ath6kl_cfg80211_resume(struct ath6kl *ar)
+{
+       int ret;
+
+       switch (ar->state) {
+       case  ATH6KL_STATE_WOW:
+               ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode resume\n");
+
+               ret = ath6kl_wow_resume(ar);
+               if (ret) {
+                       ath6kl_warn("wow mode resume failed: %d\n", ret);
+                       return ret;
+               }
+
+               ar->state = ATH6KL_STATE_ON;
+               break;
+
+       case ATH6KL_STATE_DEEPSLEEP:
+               if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
+                       ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
+                                                      ar->wmi->saved_pwr_mode);
+                       if (ret) {
+                               ath6kl_warn("wmi powermode command failed during resume: %d\n",
+                                           ret);
+                       }
+               }
+
+               ar->state = ATH6KL_STATE_ON;
+
+               break;
+
+       case ATH6KL_STATE_CUTPOWER:
+               ath6kl_dbg(ATH6KL_DBG_SUSPEND, "resume restoring power\n");
+
+               ret = ath6kl_init_hw_start(ar);
+               if (ret) {
+                       ath6kl_warn("Failed to boot hw in resume: %d\n", ret);
+                       return ret;
+               }
+               break;
+
+       default:
+               break;
+       }
+
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int ar6k_cfg80211_suspend(struct wiphy *wiphy,
+
+/* hif layer decides what suspend mode to use */
+static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
                                 struct cfg80211_wowlan *wow)
 {
        struct ath6kl *ar = wiphy_priv(wiphy);
 
-       return ath6kl_hif_suspend(ar);
+       return ath6kl_hif_suspend(ar, wow);
+}
+
+static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
+{
+       struct ath6kl *ar = wiphy_priv(wiphy);
+
+       return ath6kl_hif_resume(ar);
+}
+
+/*
+ * FIXME: WOW suspend mode is selected if the host sdio controller supports
+ * both sdio irq wake up and keep power. The target pulls sdio data line to
+ * wake up the host when WOW pattern matches. This causes sdio irq handler
+ * is being called in the host side which internally hits ath6kl's RX path.
+ *
+ * Since sdio interrupt is not disabled, RX path executes even before
+ * the host executes the actual resume operation from PM module.
+ *
+ * In the current scenario, WOW resume should happen before start processing
+ * any data from the target. So It's required to perform WOW resume in RX path.
+ * Ideally we should perform WOW resume only in the actual platform
+ * resume path. This area needs bit rework to avoid WOW resume in RX path.
+ *
+ * ath6kl_check_wow_status() is called from ath6kl_rx().
+ */
+void ath6kl_check_wow_status(struct ath6kl *ar)
+{
+       if (ar->state == ATH6KL_STATE_WOW)
+               ath6kl_cfg80211_resume(ar);
+}
+
+#else
+
+void ath6kl_check_wow_status(struct ath6kl *ar)
+{
 }
 #endif
 
@@ -1425,14 +1922,14 @@ static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
                              struct ieee80211_channel *chan,
                              enum nl80211_channel_type channel_type)
 {
-       struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
                   __func__, chan->center_freq, chan->hw_value);
-       ar->next_chan = chan->center_freq;
+       vif->next_chan = chan->center_freq;
 
        return 0;
 }
@@ -1444,9 +1941,10 @@ static bool ath6kl_is_p2p_ie(const u8 *pos)
                pos[4] == 0x9a && pos[5] == 0x09;
 }
 
-static int ath6kl_set_ap_probe_resp_ies(struct ath6kl *ar, const u8 *ies,
-                                       size_t ies_len)
+static int ath6kl_set_ap_probe_resp_ies(struct ath6kl_vif *vif,
+                                       const u8 *ies, size_t ies_len)
 {
+       struct ath6kl *ar = vif->ar;
        const u8 *pos;
        u8 *buf = NULL;
        size_t len = 0;
@@ -1473,8 +1971,8 @@ static int ath6kl_set_ap_probe_resp_ies(struct ath6kl *ar, const u8 *ies,
                }
        }
 
-       ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_RESP,
-                                      buf, len);
+       ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
+                                      WMI_FRAME_PROBE_RESP, buf, len);
        kfree(buf);
        return ret;
 }
@@ -1483,6 +1981,7 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
                            struct beacon_parameters *info, bool add)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
        struct ieee80211_mgmt *mgmt;
        u8 *ies;
        int ies_len;
@@ -1492,27 +1991,29 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add);
 
-       if (!ath6kl_cfg80211_ready(ar))
+       if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
-       if (ar->next_mode != AP_NETWORK)
+       if (vif->next_mode != AP_NETWORK)
                return -EOPNOTSUPP;
 
        if (info->beacon_ies) {
-               res = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_BEACON,
+               res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
+                                              WMI_FRAME_BEACON,
                                               info->beacon_ies,
                                               info->beacon_ies_len);
                if (res)
                        return res;
        }
        if (info->proberesp_ies) {
-               res = ath6kl_set_ap_probe_resp_ies(ar, info->proberesp_ies,
+               res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
                                                   info->proberesp_ies_len);
                if (res)
                        return res;
        }
        if (info->assocresp_ies) {
-               res = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_ASSOC_RESP,
+               res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
+                                              WMI_FRAME_ASSOC_RESP,
                                               info->assocresp_ies,
                                               info->assocresp_ies_len);
                if (res)
@@ -1539,12 +2040,12 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
 
        if (info->ssid == NULL)
                return -EINVAL;
-       memcpy(ar->ssid, info->ssid, info->ssid_len);
-       ar->ssid_len = info->ssid_len;
+       memcpy(vif->ssid, info->ssid, info->ssid_len);
+       vif->ssid_len = info->ssid_len;
        if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
                return -EOPNOTSUPP; /* TODO */
 
-       ar->dot11_auth_mode = OPEN_AUTH;
+       vif->dot11_auth_mode = OPEN_AUTH;
 
        memset(&p, 0, sizeof(p));
 
@@ -1566,7 +2067,7 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
        }
        if (p.auth_mode == 0)
                p.auth_mode = NONE_AUTH;
-       ar->auth_mode = p.auth_mode;
+       vif->auth_mode = p.auth_mode;
 
        for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) {
                switch (info->crypto.ciphers_pairwise[i]) {
@@ -1584,9 +2085,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
        }
        if (p.prwise_crypto_type == 0) {
                p.prwise_crypto_type = NONE_CRYPT;
-               ath6kl_set_cipher(ar, 0, true);
+               ath6kl_set_cipher(vif, 0, true);
        } else if (info->crypto.n_ciphers_pairwise == 1)
-               ath6kl_set_cipher(ar, info->crypto.ciphers_pairwise[0], true);
+               ath6kl_set_cipher(vif, info->crypto.ciphers_pairwise[0], true);
 
        switch (info->crypto.cipher_group) {
        case WLAN_CIPHER_SUITE_WEP40:
@@ -1603,17 +2104,17 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
                p.grp_crypto_type = NONE_CRYPT;
                break;
        }
-       ath6kl_set_cipher(ar, info->crypto.cipher_group, false);
+       ath6kl_set_cipher(vif, info->crypto.cipher_group, false);
 
        p.nw_type = AP_NETWORK;
-       ar->nw_type = ar->next_mode;
+       vif->nw_type = vif->next_mode;
 
-       p.ssid_len = ar->ssid_len;
-       memcpy(p.ssid, ar->ssid, ar->ssid_len);
-       p.dot11_auth_mode = ar->dot11_auth_mode;
-       p.ch = cpu_to_le16(ar->next_chan);
+       p.ssid_len = vif->ssid_len;
+       memcpy(p.ssid, vif->ssid, vif->ssid_len);
+       p.dot11_auth_mode = vif->dot11_auth_mode;
+       p.ch = cpu_to_le16(vif->next_chan);
 
-       res = ath6kl_wmi_ap_profile_commit(ar->wmi, &p);
+       res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
        if (res < 0)
                return res;
 
@@ -1635,14 +2136,15 @@ static int ath6kl_set_beacon(struct wiphy *wiphy, struct net_device *dev,
 static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
-       if (ar->nw_type != AP_NETWORK)
+       if (vif->nw_type != AP_NETWORK)
                return -EOPNOTSUPP;
-       if (!test_bit(CONNECTED, &ar->flag))
+       if (!test_bit(CONNECTED, &vif->flags))
                return -ENOTCONN;
 
-       ath6kl_wmi_disconnect_cmd(ar->wmi);
-       clear_bit(CONNECTED, &ar->flag);
+       ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
+       clear_bit(CONNECTED, &vif->flags);
 
        return 0;
 }
@@ -1651,8 +2153,9 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
                                 u8 *mac, struct station_parameters *params)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
-       if (ar->nw_type != AP_NETWORK)
+       if (vif->nw_type != AP_NETWORK)
                return -EOPNOTSUPP;
 
        /* Use this only for authorizing/unauthorizing a station */
@@ -1660,10 +2163,10 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
                return -EOPNOTSUPP;
 
        if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
-               return ath6kl_wmi_ap_set_mlme(ar->wmi, WMI_AP_MLME_AUTHORIZE,
-                                             mac, 0);
-       return ath6kl_wmi_ap_set_mlme(ar->wmi, WMI_AP_MLME_UNAUTHORIZE, mac,
-                                     0);
+               return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
+                                             WMI_AP_MLME_AUTHORIZE, mac, 0);
+       return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
+                                     WMI_AP_MLME_UNAUTHORIZE, mac, 0);
 }
 
 static int ath6kl_remain_on_channel(struct wiphy *wiphy,
@@ -1674,13 +2177,20 @@ static int ath6kl_remain_on_channel(struct wiphy *wiphy,
                                    u64 *cookie)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
+       u32 id;
 
        /* TODO: if already pending or ongoing remain-on-channel,
         * return -EBUSY */
-       *cookie = 1; /* only a single pending request is supported */
+       id = ++vif->last_roc_id;
+       if (id == 0) {
+               /* Do not use 0 as the cookie value */
+               id = ++vif->last_roc_id;
+       }
+       *cookie = id;
 
-       return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, chan->center_freq,
-                                            duration);
+       return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx,
+                                            chan->center_freq, duration);
 }
 
 static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
@@ -1688,16 +2198,20 @@ static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
                                           u64 cookie)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
-       if (cookie != 1)
+       if (cookie != vif->last_roc_id)
                return -ENOENT;
+       vif->last_cancel_roc_id = cookie;
 
-       return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi);
+       return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx);
 }
 
-static int ath6kl_send_go_probe_resp(struct ath6kl *ar, const u8 *buf,
-                                    size_t len, unsigned int freq)
+static int ath6kl_send_go_probe_resp(struct ath6kl_vif *vif,
+                                    const u8 *buf, size_t len,
+                                    unsigned int freq)
 {
+       struct ath6kl *ar = vif->ar;
        const u8 *pos;
        u8 *p2p;
        int p2p_len;
@@ -1724,8 +2238,8 @@ static int ath6kl_send_go_probe_resp(struct ath6kl *ar, const u8 *buf,
                pos += 2 + pos[1];
        }
 
-       ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, freq, mgmt->da,
-                                                p2p, p2p_len);
+       ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, vif->fw_vif_idx, freq,
+                                                mgmt->da, p2p, p2p_len);
        kfree(p2p);
        return ret;
 }
@@ -1738,33 +2252,35 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
                          bool dont_wait_for_ack, u64 *cookie)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
        u32 id;
        const struct ieee80211_mgmt *mgmt;
 
        mgmt = (const struct ieee80211_mgmt *) buf;
        if (buf + len >= mgmt->u.probe_resp.variable &&
-           ar->nw_type == AP_NETWORK && test_bit(CONNECTED, &ar->flag) &&
+           vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) &&
            ieee80211_is_probe_resp(mgmt->frame_control)) {
                /*
                 * Send Probe Response frame in AP mode using a separate WMI
                 * command to allow the target to fill in the generic IEs.
                 */
                *cookie = 0; /* TX status not supported */
-               return ath6kl_send_go_probe_resp(ar, buf, len,
+               return ath6kl_send_go_probe_resp(vif, buf, len,
                                                 chan->center_freq);
        }
 
-       id = ar->send_action_id++;
+       id = vif->send_action_id++;
        if (id == 0) {
                /*
                 * 0 is a reserved value in the WMI command and shall not be
                 * used for the command.
                 */
-               id = ar->send_action_id++;
+               id = vif->send_action_id++;
        }
 
        *cookie = id;
-       return ath6kl_wmi_send_action_cmd(ar->wmi, id, chan->center_freq, wait,
+       return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id,
+                                         chan->center_freq, wait,
                                          buf, len);
 }
 
@@ -1772,7 +2288,7 @@ static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
                                       struct net_device *dev,
                                       u16 frame_type, bool reg)
 {
-       struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
                   __func__, frame_type, reg);
@@ -1782,7 +2298,7 @@ static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
                 * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
                 * hardcode target to report Probe Request frames all the time.
                 */
-               ar->probe_req_report = reg;
+               vif->probe_req_report = reg;
        }
 }
 
@@ -1809,6 +2325,8 @@ ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
 };
 
 static struct cfg80211_ops ath6kl_cfg80211_ops = {
+       .add_virtual_intf = ath6kl_cfg80211_add_iface,
+       .del_virtual_intf = ath6kl_cfg80211_del_iface,
        .change_virtual_intf = ath6kl_cfg80211_change_iface,
        .scan = ath6kl_cfg80211_scan,
        .connect = ath6kl_cfg80211_connect,
@@ -1829,7 +2347,8 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
        .flush_pmksa = ath6kl_flush_pmksa,
        CFG80211_TESTMODE_CMD(ath6kl_tm_cmd)
 #ifdef CONFIG_PM
-       .suspend = ar6k_cfg80211_suspend,
+       .suspend = __ath6kl_cfg80211_suspend,
+       .resume = __ath6kl_cfg80211_resume,
 #endif
        .set_channel = ath6kl_set_channel,
        .add_beacon = ath6kl_add_beacon,
@@ -1842,76 +2361,269 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
        .mgmt_frame_register = ath6kl_mgmt_frame_register,
 };
 
-struct wireless_dev *ath6kl_cfg80211_init(struct device *dev)
+void ath6kl_cfg80211_stop(struct ath6kl *ar)
 {
-       int ret = 0;
-       struct wireless_dev *wdev;
-       struct ath6kl *ar;
+       struct ath6kl_vif *vif;
 
-       wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
-       if (!wdev) {
-               ath6kl_err("couldn't allocate wireless device\n");
-               return NULL;
+       /* FIXME: for multi vif */
+       vif = ath6kl_vif_first(ar);
+       if (!vif) {
+               /* save the current power mode before enabling power save */
+               ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
+
+               if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
+                       ath6kl_warn("ath6kl_deep_sleep_enable: "
+                                   "wmi_powermode_cmd failed\n");
+               return;
        }
 
+       switch (vif->sme_state) {
+       case SME_CONNECTING:
+               cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0,
+                                       NULL, 0,
+                                       WLAN_STATUS_UNSPECIFIED_FAILURE,
+                                       GFP_KERNEL);
+               break;
+       case SME_CONNECTED:
+       default:
+               /*
+                * FIXME: oddly enough smeState is in DISCONNECTED during
+                * suspend, why? Need to send disconnected event in that
+                * state.
+                */
+               cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL);
+               break;
+       }
+
+       if (test_bit(CONNECTED, &vif->flags) ||
+           test_bit(CONNECT_PEND, &vif->flags))
+               ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
+
+       vif->sme_state = SME_DISCONNECTED;
+       clear_bit(CONNECTED, &vif->flags);
+       clear_bit(CONNECT_PEND, &vif->flags);
+
+       /* disable scanning */
+       if (ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0xFFFF, 0, 0,
+                                     0, 0, 0, 0, 0, 0, 0) != 0)
+               printk(KERN_WARNING "ath6kl: failed to disable scan "
+                      "during suspend\n");
+
+       ath6kl_cfg80211_scan_complete_event(vif, true);
+}
+
+struct ath6kl *ath6kl_core_alloc(struct device *dev)
+{
+       struct ath6kl *ar;
+       struct wiphy *wiphy;
+       u8 ctr;
+
        /* create a new wiphy for use with cfg80211 */
-       wdev->wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
-       if (!wdev->wiphy) {
+       wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
+
+       if (!wiphy) {
                ath6kl_err("couldn't allocate wiphy device\n");
-               kfree(wdev);
                return NULL;
        }
 
-       ar = wiphy_priv(wdev->wiphy);
-       ar->p2p = !!ath6kl_p2p;
+       ar = wiphy_priv(wiphy);
+       if (!multi_norm_if_support)
+               ar->p2p = !!ath6kl_p2p;
+       ar->wiphy = wiphy;
+       ar->dev = dev;
+
+       if (multi_norm_if_support)
+               ar->max_norm_iface = 2;
+       else
+               ar->max_norm_iface = 1;
+
+       /* FIXME: Remove this once the multivif support is enabled */
+       ar->max_norm_iface = 1;
+
+       spin_lock_init(&ar->lock);
+       spin_lock_init(&ar->mcastpsq_lock);
+       spin_lock_init(&ar->list_lock);
 
-       wdev->wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
+       init_waitqueue_head(&ar->event_wq);
+       sema_init(&ar->sem, 1);
 
-       wdev->wiphy->max_remain_on_channel_duration = 5000;
+       INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);
+       INIT_LIST_HEAD(&ar->vif_list);
+
+       clear_bit(WMI_ENABLED, &ar->flag);
+       clear_bit(SKIP_SCAN, &ar->flag);
+       clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
+
+       ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL;
+       ar->listen_intvl_b = 0;
+       ar->tx_pwr = 0;
+
+       ar->intra_bss = 1;
+       memset(&ar->sc_params, 0, sizeof(ar->sc_params));
+       ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT;
+       ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS;
+       ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
+
+       ar->state = ATH6KL_STATE_OFF;
+
+       memset((u8 *)ar->sta_list, 0,
+              AP_MAX_NUM_STA * sizeof(struct ath6kl_sta));
+
+       /* Init the PS queues */
+       for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
+               spin_lock_init(&ar->sta_list[ctr].psq_lock);
+               skb_queue_head_init(&ar->sta_list[ctr].psq);
+       }
+
+       skb_queue_head_init(&ar->mcastpsq);
+
+       memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
+
+       return ar;
+}
+
+int ath6kl_register_ieee80211_hw(struct ath6kl *ar)
+{
+       struct wiphy *wiphy = ar->wiphy;
+       int ret;
+
+       wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
+
+       wiphy->max_remain_on_channel_duration = 5000;
 
        /* set device pointer for wiphy */
-       set_wiphy_dev(wdev->wiphy, dev);
+       set_wiphy_dev(wiphy, ar->dev);
 
-       wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-               BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
+       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+                                BIT(NL80211_IFTYPE_ADHOC) |
+                                BIT(NL80211_IFTYPE_AP);
        if (ar->p2p) {
-               wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) |
-                       BIT(NL80211_IFTYPE_P2P_CLIENT);
+               wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) |
+                                         BIT(NL80211_IFTYPE_P2P_CLIENT);
        }
-       /* max num of ssids that can be probed during scanning */
-       wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
-       wdev->wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
-       wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
-       wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
-       wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
-
-       wdev->wiphy->cipher_suites = cipher_suites;
-       wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 
-       ret = wiphy_register(wdev->wiphy);
+       /* max num of ssids that can be probed during scanning */
+       wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
+       wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
+       wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
+       wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
+       wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+       wiphy->cipher_suites = cipher_suites;
+       wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+
+       wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
+                             WIPHY_WOWLAN_DISCONNECT |
+                             WIPHY_WOWLAN_GTK_REKEY_FAILURE  |
+                             WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
+                             WIPHY_WOWLAN_EAP_IDENTITY_REQ   |
+                             WIPHY_WOWLAN_4WAY_HANDSHAKE;
+       wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST;
+       wiphy->wowlan.pattern_min_len = 1;
+       wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
+
+       ret = wiphy_register(wiphy);
        if (ret < 0) {
                ath6kl_err("couldn't register wiphy device\n");
-               wiphy_free(wdev->wiphy);
-               kfree(wdev);
-               return NULL;
+               return ret;
        }
 
-       return wdev;
+       return 0;
 }
 
-void ath6kl_cfg80211_deinit(struct ath6kl *ar)
+static int ath6kl_init_if_data(struct ath6kl_vif *vif)
 {
-       struct wireless_dev *wdev = ar->wdev;
-
-       if (ar->scan_req) {
-               cfg80211_scan_done(ar->scan_req, true);
-               ar->scan_req = NULL;
+       vif->aggr_cntxt = aggr_init(vif->ndev);
+       if (!vif->aggr_cntxt) {
+               ath6kl_err("failed to initialize aggr\n");
+               return -ENOMEM;
        }
 
-       if (!wdev)
-               return;
+       setup_timer(&vif->disconnect_timer, disconnect_timer_handler,
+                   (unsigned long) vif->ndev);
+       set_bit(WMM_ENABLED, &vif->flags);
+       spin_lock_init(&vif->if_lock);
+
+       return 0;
+}
+
+void ath6kl_deinit_if_data(struct ath6kl_vif *vif)
+{
+       struct ath6kl *ar = vif->ar;
+
+       aggr_module_destroy(vif->aggr_cntxt);
+
+       ar->avail_idx_map |= BIT(vif->fw_vif_idx);
 
-       wiphy_unregister(wdev->wiphy);
-       wiphy_free(wdev->wiphy);
-       kfree(wdev);
+       if (vif->nw_type == ADHOC_NETWORK)
+               ar->ibss_if_active = false;
+
+       unregister_netdevice(vif->ndev);
+
+       ar->num_vif--;
+}
+
+struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
+                                       enum nl80211_iftype type, u8 fw_vif_idx,
+                                       u8 nw_type)
+{
+       struct net_device *ndev;
+       struct ath6kl_vif *vif;
+
+       ndev = alloc_netdev(sizeof(*vif), name, ether_setup);
+       if (!ndev)
+               return NULL;
+
+       vif = netdev_priv(ndev);
+       ndev->ieee80211_ptr = &vif->wdev;
+       vif->wdev.wiphy = ar->wiphy;
+       vif->ar = ar;
+       vif->ndev = ndev;
+       SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy));
+       vif->wdev.netdev = ndev;
+       vif->wdev.iftype = type;
+       vif->fw_vif_idx = fw_vif_idx;
+       vif->nw_type = vif->next_mode = nw_type;
+
+       memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
+       if (fw_vif_idx != 0)
+               ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
+                                    0x2;
+
+       init_netdev(ndev);
+
+       ath6kl_init_control_info(vif);
+
+       /* TODO: Pass interface specific pointer instead of ar */
+       if (ath6kl_init_if_data(vif))
+               goto err;
+
+       if (register_netdevice(ndev))
+               goto err;
+
+       ar->avail_idx_map &= ~BIT(fw_vif_idx);
+       vif->sme_state = SME_DISCONNECTED;
+       set_bit(WLAN_ENABLED, &vif->flags);
+       ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
+       set_bit(NETDEV_REGISTERED, &vif->flags);
+
+       if (type == NL80211_IFTYPE_ADHOC)
+               ar->ibss_if_active = true;
+
+       spin_lock_bh(&ar->list_lock);
+       list_add_tail(&vif->list, &ar->vif_list);
+       spin_unlock_bh(&ar->list_lock);
+
+       return ndev;
+
+err:
+       aggr_module_destroy(vif->aggr_cntxt);
+       free_netdev(ndev);
+       return NULL;
+}
+
+void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar)
+{
+       wiphy_unregister(ar->wiphy);
+       wiphy_free(ar->wiphy);
 }
index a84adc249c61cfeabbaa60d1e45bbd4af58b5c6e..59fa9d859def609a97d6f3ecb5760a9a25f5ee15 100644 (file)
 #ifndef ATH6KL_CFG80211_H
 #define ATH6KL_CFG80211_H
 
-struct wireless_dev *ath6kl_cfg80211_init(struct device *dev);
-void ath6kl_cfg80211_deinit(struct ath6kl *ar);
+enum ath6kl_cfg_suspend_mode {
+       ATH6KL_CFG_SUSPEND_DEEPSLEEP,
+       ATH6KL_CFG_SUSPEND_CUTPOWER,
+       ATH6KL_CFG_SUSPEND_WOW
+};
 
-void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status);
+struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
+                                       enum nl80211_iftype type,
+                                       u8 fw_vif_idx, u8 nw_type);
+int ath6kl_register_ieee80211_hw(struct ath6kl *ar);
+struct ath6kl *ath6kl_core_alloc(struct device *dev);
+void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar);
 
-void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
+void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted);
+
+void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
                                   u8 *bssid, u16 listen_intvl,
                                   u16 beacon_intvl,
                                   enum network_type nw_type,
                                   u8 beacon_ie_len, u8 assoc_req_len,
                                   u8 assoc_resp_len, u8 *assoc_info);
 
-void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
+void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
                                      u8 *bssid, u8 assoc_resp_len,
                                      u8 *assoc_info, u16 proto_reason);
 
-void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid,
+void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
                                     bool ismcast);
 
+int ath6kl_cfg80211_suspend(struct ath6kl *ar,
+                           enum ath6kl_cfg_suspend_mode mode,
+                           struct cfg80211_wowlan *wow);
+
+int ath6kl_cfg80211_resume(struct ath6kl *ar);
+
+void ath6kl_cfg80211_stop(struct ath6kl *ar);
+
 #endif /* ATH6KL_CFG80211_H */
index b92f0e5d233631290cb262ca99a375827d4dc452..41e465f29e6312afdde51bea46d39c84960abf2f 100644 (file)
@@ -23,8 +23,6 @@
 
 extern int ath6kl_printk(const char *level, const char *fmt, ...);
 
-#define A_CACHE_LINE_PAD            128
-
 /*
  * Reflects the version of binary interface exposed by ATH6KL target
  * firmware. Needs to be incremented by 1 for any change in the firmware
@@ -78,20 +76,10 @@ enum crypto_type {
 struct htc_endpoint_credit_dist;
 struct ath6kl;
 enum htc_credit_dist_reason;
-struct htc_credit_state_info;
+struct ath6kl_htc_credit_info;
 
-int ath6k_setup_credit_dist(void *htc_handle,
-                           struct htc_credit_state_info *cred_info);
-void ath6k_credit_distribute(struct htc_credit_state_info *cred_inf,
-                            struct list_head *epdist_list,
-                            enum htc_credit_dist_reason reason);
-void ath6k_credit_init(struct htc_credit_state_info *cred_inf,
-                      struct list_head *ep_list,
-                      int tot_credits);
-void ath6k_seek_credits(struct htc_credit_state_info *cred_inf,
-                       struct htc_endpoint_credit_dist *ep_dist);
 struct ath6kl *ath6kl_core_alloc(struct device *sdev);
 int ath6kl_core_init(struct ath6kl *ar);
-int ath6kl_unavail_ev(struct ath6kl *ar);
+void ath6kl_core_cleanup(struct ath6kl *ar);
 struct sk_buff *ath6kl_buf_alloc(int size);
 #endif /* COMMON_H */
index 6d8a4845baafe48b0ac3fa6dcb3dac7a4a63dbfb..e7e095e536a7e0bb34d81e4a63d1a87b159a2a14 100644 (file)
@@ -166,6 +166,7 @@ struct ath6kl_fw_ie {
 #define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN  BIT(1)
 #define ATH6KL_CONF_ENABLE_11N                 BIT(2)
 #define ATH6KL_CONF_ENABLE_TX_BURST            BIT(3)
+#define ATH6KL_CONF_SUSPEND_CUTPOWER           BIT(4)
 
 enum wlan_low_pwr_state {
        WLAN_POWER_STATE_ON,
@@ -380,40 +381,33 @@ struct ath6kl_req_key {
        u8 key_len;
 };
 
-/* Flag info */
-#define WMI_ENABLED    0
-#define WMI_READY      1
-#define CONNECTED      2
-#define STATS_UPDATE_PEND 3
-#define CONNECT_PEND     4
-#define WMM_ENABLED      5
-#define NETQ_STOPPED     6
-#define WMI_CTRL_EP_FULL  7
-#define DTIM_EXPIRED     8
-#define DESTROY_IN_PROGRESS  9
-#define NETDEV_REGISTERED    10
-#define SKIP_SCAN           11
-#define WLAN_ENABLED        12
-#define TESTMODE            13
-#define CLEAR_BSSFILTER_ON_BEACON 14
-#define DTIM_PERIOD_AVAIL    15
+#define MAX_NUM_VIF    1
+
+/* vif flags info */
+enum ath6kl_vif_state {
+       CONNECTED,
+       CONNECT_PEND,
+       WMM_ENABLED,
+       NETQ_STOPPED,
+       DTIM_EXPIRED,
+       NETDEV_REGISTERED,
+       CLEAR_BSSFILTER_ON_BEACON,
+       DTIM_PERIOD_AVAIL,
+       WLAN_ENABLED,
+       STATS_UPDATE_PEND,
+};
 
-struct ath6kl {
-       struct device *dev;
-       struct net_device *net_dev;
-       struct ath6kl_bmi bmi;
-       const struct ath6kl_hif_ops *hif_ops;
-       struct wmi *wmi;
-       int tx_pending[ENDPOINT_MAX];
-       int total_tx_data_pend;
-       struct htc_target *htc_target;
-       void *hif_priv;
-       spinlock_t lock;
-       struct semaphore sem;
+struct ath6kl_vif {
+       struct list_head list;
+       struct wireless_dev wdev;
+       struct net_device *ndev;
+       struct ath6kl *ar;
+       /* Lock to protect vif specific net_stats and flags */
+       spinlock_t if_lock;
+       u8 fw_vif_idx;
+       unsigned long flags;
        int ssid_len;
        u8 ssid[IEEE80211_MAX_SSID_LEN];
-       u8 next_mode;
-       u8 nw_type;
        u8 dot11_auth_mode;
        u8 auth_mode;
        u8 prwise_crypto;
@@ -421,21 +415,83 @@ struct ath6kl {
        u8 grp_crypto;
        u8 grp_crypto_len;
        u8 def_txkey_index;
-       struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
+       u8 next_mode;
+       u8 nw_type;
        u8 bssid[ETH_ALEN];
        u8 req_bssid[ETH_ALEN];
        u16 ch_hint;
        u16 bss_ch;
+       struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
+       struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
+       struct aggr_info *aggr_cntxt;
+       struct timer_list disconnect_timer;
+       struct cfg80211_scan_request *scan_req;
+       enum sme_state sme_state;
+       int reconnect_flag;
+       u32 last_roc_id;
+       u32 last_cancel_roc_id;
+       u32 send_action_id;
+       bool probe_req_report;
+       u16 next_chan;
+       u16 assoc_bss_beacon_int;
+       u8 assoc_bss_dtim_period;
+       struct net_device_stats net_stats;
+       struct target_stats target_stats;
+};
+
+#define WOW_LIST_ID            0
+#define WOW_HOST_REQ_DELAY     500 /* ms */
+
+/* Flag info */
+enum ath6kl_dev_state {
+       WMI_ENABLED,
+       WMI_READY,
+       WMI_CTRL_EP_FULL,
+       TESTMODE,
+       DESTROY_IN_PROGRESS,
+       SKIP_SCAN,
+       ROAM_TBL_PEND,
+       FIRST_BOOT,
+};
+
+enum ath6kl_state {
+       ATH6KL_STATE_OFF,
+       ATH6KL_STATE_ON,
+       ATH6KL_STATE_DEEPSLEEP,
+       ATH6KL_STATE_CUTPOWER,
+       ATH6KL_STATE_WOW,
+};
+
+struct ath6kl {
+       struct device *dev;
+       struct wiphy *wiphy;
+
+       enum ath6kl_state state;
+
+       struct ath6kl_bmi bmi;
+       const struct ath6kl_hif_ops *hif_ops;
+       struct wmi *wmi;
+       int tx_pending[ENDPOINT_MAX];
+       int total_tx_data_pend;
+       struct htc_target *htc_target;
+       void *hif_priv;
+       struct list_head vif_list;
+       /* Lock to avoid race in vif_list entries among add/del/traverse */
+       spinlock_t list_lock;
+       u8 num_vif;
+       u8 max_norm_iface;
+       u8 avail_idx_map;
+       spinlock_t lock;
+       struct semaphore sem;
        u16 listen_intvl_b;
        u16 listen_intvl_t;
        u8 lrssi_roam_threshold;
        struct ath6kl_version version;
        u32 target_type;
        u8 tx_pwr;
-       struct net_device_stats net_stats;
-       struct target_stats target_stats;
        struct ath6kl_node_mapping node_map[MAX_NODE_NUM];
        u8 ibss_ps_enable;
+       bool ibss_if_active;
        u8 node_num;
        u8 next_ep_id;
        struct ath6kl_cookie *cookie_list;
@@ -446,7 +502,7 @@ struct ath6kl {
        u8 hiac_stream_active_pri;
        u8 ep2ac_map[ENDPOINT_MAX];
        enum htc_endpoint_id ctrl_ep;
-       struct htc_credit_state_info credit_state_info;
+       struct ath6kl_htc_credit_info credit_state_info;
        u32 connect_ctrl_flags;
        u32 user_key_ctrl;
        u8 usr_bss_filter;
@@ -456,18 +512,13 @@ struct ath6kl {
        struct sk_buff_head mcastpsq;
        spinlock_t mcastpsq_lock;
        u8 intra_bss;
-       struct aggr_info *aggr_cntxt;
        struct wmi_ap_mode_stat ap_stats;
        u8 ap_country_code[3];
        struct list_head amsdu_rx_buffer_queue;
-       struct timer_list disconnect_timer;
        u8 rx_meta_ver;
-       struct wireless_dev *wdev;
-       struct cfg80211_scan_request *scan_req;
-       struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
-       enum sme_state sme_state;
        enum wlan_low_pwr_state wlan_pwr_state;
        struct wmi_scan_params_cmd sc_params;
+       u8 mac_addr[ETH_ALEN];
 #define AR_MCAST_FILTER_MAC_ADDR_SIZE  4
        struct {
                void *rx_report;
@@ -487,7 +538,6 @@ struct ath6kl {
        struct ath6kl_mbox_info mbox_info;
 
        struct ath6kl_cookie cookie_mem[MAX_COOKIE_NUM];
-       int reconnect_flag;
        unsigned long flag;
 
        u8 *fw_board;
@@ -508,13 +558,7 @@ struct ath6kl {
 
        struct dentry *debugfs_phy;
 
-       u32 send_action_id;
-       bool probe_req_report;
-       u16 next_chan;
-
        bool p2p;
-       u16 assoc_bss_beacon_int;
-       u8 assoc_bss_dtim_period;
 
 #ifdef CONFIG_ATH6KL_DEBUG
        struct {
@@ -529,23 +573,19 @@ struct ath6kl {
                struct {
                        unsigned int invalid_rate;
                } war_stats;
+
+               u8 *roam_tbl;
+               unsigned int roam_tbl_len;
+
+               u8 keepalive;
+               u8 disc_timeout;
        } debug;
 #endif /* CONFIG_ATH6KL_DEBUG */
 };
 
 static inline void *ath6kl_priv(struct net_device *dev)
 {
-       return wdev_priv(dev->ieee80211_ptr);
-}
-
-static inline void ath6kl_deposit_credit_to_ep(struct htc_credit_state_info
-                                              *cred_info,
-                                              struct htc_endpoint_credit_dist
-                                              *ep_dist, int credits)
-{
-       ep_dist->credits += credits;
-       ep_dist->cred_assngd += credits;
-       cred_info->cur_free_credits -= credits;
+       return ((struct ath6kl_vif *) netdev_priv(dev))->ar;
 }
 
 static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar,
@@ -561,7 +601,6 @@ static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar,
        return addr;
 }
 
-void ath6kl_destroy(struct net_device *dev, unsigned int unregister);
 int ath6kl_configure_target(struct ath6kl *ar);
 void ath6kl_detect_error(unsigned long ptr);
 void disconnect_timer_handler(unsigned long ptr);
@@ -579,10 +618,8 @@ int ath6kl_diag_write(struct ath6kl *ar, u32 address, void *data, u32 length);
 int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value);
 int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length);
 int ath6kl_read_fwlogs(struct ath6kl *ar);
-void ath6kl_init_profile_info(struct ath6kl *ar);
+void ath6kl_init_profile_info(struct ath6kl_vif *vif);
 void ath6kl_tx_data_cleanup(struct ath6kl *ar);
-void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile,
-                         bool get_dbglogs);
 
 struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar);
 void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie);
@@ -598,40 +635,49 @@ struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target,
 void aggr_module_destroy(struct aggr_info *aggr_info);
 void aggr_reset_state(struct aggr_info *aggr_info);
 
-struct ath6kl_sta *ath6kl_find_sta(struct ath6kl *ar, u8 * node_addr);
+struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 * node_addr);
 struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid);
 
 void ath6kl_ready_event(void *devt, u8 * datap, u32 sw_ver, u32 abi_ver);
 int ath6kl_control_tx(void *devt, struct sk_buff *skb,
                      enum htc_endpoint_id eid);
-void ath6kl_connect_event(struct ath6kl *ar, u16 channel,
+void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel,
                          u8 *bssid, u16 listen_int,
                          u16 beacon_int, enum network_type net_type,
                          u8 beacon_ie_len, u8 assoc_req_len,
                          u8 assoc_resp_len, u8 *assoc_info);
-void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel);
-void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
+void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel);
+void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
                                u8 keymgmt, u8 ucipher, u8 auth,
                                u8 assoc_req_len, u8 *assoc_info);
-void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason,
+void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason,
                             u8 *bssid, u8 assoc_resp_len,
                             u8 *assoc_info, u16 prot_reason_status);
-void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast);
+void ath6kl_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid, bool ismcast);
 void ath6kl_txpwr_rx_evt(void *devt, u8 tx_pwr);
-void ath6kl_scan_complete_evt(struct ath6kl *ar, int status);
-void ath6kl_tgt_stats_event(struct ath6kl *ar, u8 *ptr, u32 len);
+void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status);
+void ath6kl_tgt_stats_event(struct ath6kl_vif *vif, u8 *ptr, u32 len);
 void ath6kl_indicate_tx_activity(void *devt, u8 traffic_class, bool active);
 enum htc_endpoint_id ath6kl_ac2_endpoint_id(void *devt, u8 ac);
 
-void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid);
+void ath6kl_pspoll_event(struct ath6kl_vif *vif, u8 aid);
 
-void ath6kl_dtimexpiry_event(struct ath6kl *ar);
-void ath6kl_disconnect(struct ath6kl *ar);
-void ath6kl_deep_sleep_enable(struct ath6kl *ar);
-void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid);
-void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no,
+void ath6kl_dtimexpiry_event(struct ath6kl_vif *vif);
+void ath6kl_disconnect(struct ath6kl_vif *vif);
+void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid);
+void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no,
                             u8 win_sz);
 void ath6kl_wakeup_event(void *dev);
-void ath6kl_target_failure(struct ath6kl *ar);
+
+void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
+                        bool wait_fot_compltn, bool cold_reset);
+void ath6kl_init_control_info(struct ath6kl_vif *vif);
+void ath6kl_deinit_if_data(struct ath6kl_vif *vif);
+void ath6kl_core_free(struct ath6kl *ar);
+struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar);
+void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready);
+int ath6kl_init_hw_start(struct ath6kl *ar);
+int ath6kl_init_hw_stop(struct ath6kl *ar);
+void ath6kl_check_wow_status(struct ath6kl *ar);
 
 #endif /* CORE_H */
index 7879b5314285492dc0ccbffd61098bf5d909af65..9eff0d010bb161812f70712bd51e9c7700acc2f9 100644 (file)
@@ -143,49 +143,48 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
 
 static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist)
 {
-       ath6kl_dbg(ATH6KL_DBG_ANY,
+       ath6kl_dbg(ATH6KL_DBG_CREDIT,
                   "--- endpoint: %d  svc_id: 0x%X ---\n",
                   ep_dist->endpoint, ep_dist->svc_id);
-       ath6kl_dbg(ATH6KL_DBG_ANY, " dist_flags     : 0x%X\n",
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, " dist_flags     : 0x%X\n",
                   ep_dist->dist_flags);
-       ath6kl_dbg(ATH6KL_DBG_ANY, " cred_norm      : %d\n",
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_norm      : %d\n",
                   ep_dist->cred_norm);
-       ath6kl_dbg(ATH6KL_DBG_ANY, " cred_min       : %d\n",
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_min       : %d\n",
                   ep_dist->cred_min);
-       ath6kl_dbg(ATH6KL_DBG_ANY, " credits        : %d\n",
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, " credits        : %d\n",
                   ep_dist->credits);
-       ath6kl_dbg(ATH6KL_DBG_ANY, " cred_assngd    : %d\n",
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_assngd    : %d\n",
                   ep_dist->cred_assngd);
-       ath6kl_dbg(ATH6KL_DBG_ANY, " seek_cred      : %d\n",
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, " seek_cred      : %d\n",
                   ep_dist->seek_cred);
-       ath6kl_dbg(ATH6KL_DBG_ANY, " cred_sz        : %d\n",
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_sz        : %d\n",
                   ep_dist->cred_sz);
-       ath6kl_dbg(ATH6KL_DBG_ANY, " cred_per_msg   : %d\n",
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_per_msg   : %d\n",
                   ep_dist->cred_per_msg);
-       ath6kl_dbg(ATH6KL_DBG_ANY, " cred_to_dist   : %d\n",
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_to_dist   : %d\n",
                   ep_dist->cred_to_dist);
-       ath6kl_dbg(ATH6KL_DBG_ANY, " txq_depth      : %d\n",
-                  get_queue_depth(&((struct htc_endpoint *)
-                                    ep_dist->htc_rsvd)->txq));
-       ath6kl_dbg(ATH6KL_DBG_ANY,
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, " txq_depth      : %d\n",
+                  get_queue_depth(&ep_dist->htc_ep->txq));
+       ath6kl_dbg(ATH6KL_DBG_CREDIT,
                   "----------------------------------\n");
 }
 
+/* FIXME: move to htc.c */
 void dump_cred_dist_stats(struct htc_target *target)
 {
        struct htc_endpoint_credit_dist *ep_list;
 
-       if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_TRC))
+       if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_CREDIT))
                return;
 
        list_for_each_entry(ep_list, &target->cred_dist_list, list)
                dump_cred_dist(ep_list);
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:%p dist:%p\n",
-                  target->cred_dist_cntxt, NULL);
-       ath6kl_dbg(ATH6KL_DBG_TRC, "credit distribution, total : %d, free : %d\n",
-                  target->cred_dist_cntxt->total_avail_credits,
-                  target->cred_dist_cntxt->cur_free_credits);
+       ath6kl_dbg(ATH6KL_DBG_CREDIT,
+                  "credit distribution total %d free %d\n",
+                  target->credit_info->total_avail_credits,
+                  target->credit_info->cur_free_credits);
 }
 
 static int ath6kl_debugfs_open(struct inode *inode, struct file *file)
@@ -397,13 +396,20 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
                                   size_t count, loff_t *ppos)
 {
        struct ath6kl *ar = file->private_data;
-       struct target_stats *tgt_stats = &ar->target_stats;
+       struct ath6kl_vif *vif;
+       struct target_stats *tgt_stats;
        char *buf;
        unsigned int len = 0, buf_len = 1500;
        int i;
        long left;
        ssize_t ret_cnt;
 
+       vif = ath6kl_vif_first(ar);
+       if (!vif)
+               return -EIO;
+
+       tgt_stats = &vif->target_stats;
+
        buf = kzalloc(buf_len, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
@@ -413,9 +419,9 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
                return -EBUSY;
        }
 
-       set_bit(STATS_UPDATE_PEND, &ar->flag);
+       set_bit(STATS_UPDATE_PEND, &vif->flags);
 
-       if (ath6kl_wmi_get_stats_cmd(ar->wmi)) {
+       if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) {
                up(&ar->sem);
                kfree(buf);
                return -EIO;
@@ -423,7 +429,7 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
 
        left = wait_event_interruptible_timeout(ar->event_wq,
                                                !test_bit(STATS_UPDATE_PEND,
-                                               &ar->flag), WMI_TIMEOUT);
+                                               &vif->flags), WMI_TIMEOUT);
 
        up(&ar->sem);
 
@@ -555,10 +561,10 @@ static ssize_t read_file_credit_dist_stats(struct file *file,
 
        len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
                         "Total Avail Credits: ",
-                        target->cred_dist_cntxt->total_avail_credits);
+                        target->credit_info->total_avail_credits);
        len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
                         "Free credits :",
-                        target->cred_dist_cntxt->cur_free_credits);
+                        target->credit_info->cur_free_credits);
 
        len += scnprintf(buf + len, buf_len - len,
                         " Epid  Flags    Cred_norm  Cred_min  Credits  Cred_assngd"
@@ -577,8 +583,7 @@ static ssize_t read_file_credit_dist_stats(struct file *file,
                print_credit_info("%9d", cred_per_msg);
                print_credit_info("%14d", cred_to_dist);
                len += scnprintf(buf + len, buf_len - len, "%12d\n",
-                                get_queue_depth(&((struct htc_endpoint *)
-                                                ep_list->htc_rsvd)->txq));
+                                get_queue_depth(&ep_list->htc_ep->txq));
        }
 
        if (len > buf_len)
@@ -596,6 +601,107 @@ static const struct file_operations fops_credit_dist_stats = {
        .llseek = default_llseek,
 };
 
+static unsigned int print_endpoint_stat(struct htc_target *target, char *buf,
+                                       unsigned int buf_len, unsigned int len,
+                                       int offset, const char *name)
+{
+       int i;
+       struct htc_endpoint_stats *ep_st;
+       u32 *counter;
+
+       len += scnprintf(buf + len, buf_len - len, "%s:", name);
+       for (i = 0; i < ENDPOINT_MAX; i++) {
+               ep_st = &target->endpoint[i].ep_st;
+               counter = ((u32 *) ep_st) + (offset / 4);
+               len += scnprintf(buf + len, buf_len - len, " %u", *counter);
+       }
+       len += scnprintf(buf + len, buf_len - len, "\n");
+
+       return len;
+}
+
+static ssize_t ath6kl_endpoint_stats_read(struct file *file,
+                                         char __user *user_buf,
+                                         size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       struct htc_target *target = ar->htc_target;
+       char *buf;
+       unsigned int buf_len, len = 0;
+       ssize_t ret_cnt;
+
+       buf_len = sizeof(struct htc_endpoint_stats) / sizeof(u32) *
+               (25 + ENDPOINT_MAX * 11);
+       buf = kmalloc(buf_len, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+#define EPSTAT(name)                                                   \
+       len = print_endpoint_stat(target, buf, buf_len, len,            \
+                                 offsetof(struct htc_endpoint_stats, name), \
+                                 #name)
+       EPSTAT(cred_low_indicate);
+       EPSTAT(tx_issued);
+       EPSTAT(tx_pkt_bundled);
+       EPSTAT(tx_bundles);
+       EPSTAT(tx_dropped);
+       EPSTAT(tx_cred_rpt);
+       EPSTAT(cred_rpt_from_rx);
+       EPSTAT(cred_rpt_from_other);
+       EPSTAT(cred_rpt_ep0);
+       EPSTAT(cred_from_rx);
+       EPSTAT(cred_from_other);
+       EPSTAT(cred_from_ep0);
+       EPSTAT(cred_cosumd);
+       EPSTAT(cred_retnd);
+       EPSTAT(rx_pkts);
+       EPSTAT(rx_lkahds);
+       EPSTAT(rx_bundl);
+       EPSTAT(rx_bundle_lkahd);
+       EPSTAT(rx_bundle_from_hdr);
+       EPSTAT(rx_alloc_thresh_hit);
+       EPSTAT(rxalloc_thresh_byte);
+#undef EPSTAT
+
+       if (len > buf_len)
+               len = buf_len;
+
+       ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+       return ret_cnt;
+}
+
+static ssize_t ath6kl_endpoint_stats_write(struct file *file,
+                                          const char __user *user_buf,
+                                          size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       struct htc_target *target = ar->htc_target;
+       int ret, i;
+       u32 val;
+       struct htc_endpoint_stats *ep_st;
+
+       ret = kstrtou32_from_user(user_buf, count, 0, &val);
+       if (ret)
+               return ret;
+       if (val == 0) {
+               for (i = 0; i < ENDPOINT_MAX; i++) {
+                       ep_st = &target->endpoint[i].ep_st;
+                       memset(ep_st, 0, sizeof(*ep_st));
+               }
+       }
+
+       return count;
+}
+
+static const struct file_operations fops_endpoint_stats = {
+       .open = ath6kl_debugfs_open,
+       .read = ath6kl_endpoint_stats_read,
+       .write = ath6kl_endpoint_stats_write,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
 static unsigned long ath6kl_get_num_reg(void)
 {
        int i;
@@ -868,6 +974,660 @@ static const struct file_operations fops_diag_reg_write = {
        .llseek = default_llseek,
 };
 
+int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf,
+                               size_t len)
+{
+       const struct wmi_target_roam_tbl *tbl;
+       u16 num_entries;
+
+       if (len < sizeof(*tbl))
+               return -EINVAL;
+
+       tbl = (const struct wmi_target_roam_tbl *) buf;
+       num_entries = le16_to_cpu(tbl->num_entries);
+       if (sizeof(*tbl) + num_entries * sizeof(struct wmi_bss_roam_info) >
+           len)
+               return -EINVAL;
+
+       if (ar->debug.roam_tbl == NULL ||
+           ar->debug.roam_tbl_len < (unsigned int) len) {
+               kfree(ar->debug.roam_tbl);
+               ar->debug.roam_tbl = kmalloc(len, GFP_ATOMIC);
+               if (ar->debug.roam_tbl == NULL)
+                       return -ENOMEM;
+       }
+
+       memcpy(ar->debug.roam_tbl, buf, len);
+       ar->debug.roam_tbl_len = len;
+
+       if (test_bit(ROAM_TBL_PEND, &ar->flag)) {
+               clear_bit(ROAM_TBL_PEND, &ar->flag);
+               wake_up(&ar->event_wq);
+       }
+
+       return 0;
+}
+
+static ssize_t ath6kl_roam_table_read(struct file *file, char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       int ret;
+       long left;
+       struct wmi_target_roam_tbl *tbl;
+       u16 num_entries, i;
+       char *buf;
+       unsigned int len, buf_len;
+       ssize_t ret_cnt;
+
+       if (down_interruptible(&ar->sem))
+               return -EBUSY;
+
+       set_bit(ROAM_TBL_PEND, &ar->flag);
+
+       ret = ath6kl_wmi_get_roam_tbl_cmd(ar->wmi);
+       if (ret) {
+               up(&ar->sem);
+               return ret;
+       }
+
+       left = wait_event_interruptible_timeout(
+               ar->event_wq, !test_bit(ROAM_TBL_PEND, &ar->flag), WMI_TIMEOUT);
+       up(&ar->sem);
+
+       if (left <= 0)
+               return -ETIMEDOUT;
+
+       if (ar->debug.roam_tbl == NULL)
+               return -ENOMEM;
+
+       tbl = (struct wmi_target_roam_tbl *) ar->debug.roam_tbl;
+       num_entries = le16_to_cpu(tbl->num_entries);
+
+       buf_len = 100 + num_entries * 100;
+       buf = kzalloc(buf_len, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+       len = 0;
+       len += scnprintf(buf + len, buf_len - len,
+                        "roam_mode=%u\n\n"
+                        "# roam_util bssid rssi rssidt last_rssi util bias\n",
+                        le16_to_cpu(tbl->roam_mode));
+
+       for (i = 0; i < num_entries; i++) {
+               struct wmi_bss_roam_info *info = &tbl->info[i];
+               len += scnprintf(buf + len, buf_len - len,
+                                "%d %pM %d %d %d %d %d\n",
+                                a_sle32_to_cpu(info->roam_util), info->bssid,
+                                info->rssi, info->rssidt, info->last_rssi,
+                                info->util, info->bias);
+       }
+
+       if (len > buf_len)
+               len = buf_len;
+
+       ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+       kfree(buf);
+       return ret_cnt;
+}
+
+static const struct file_operations fops_roam_table = {
+       .read = ath6kl_roam_table_read,
+       .open = ath6kl_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_force_roam_write(struct file *file,
+                                      const char __user *user_buf,
+                                      size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       int ret;
+       char buf[20];
+       size_t len;
+       u8 bssid[ETH_ALEN];
+       int i;
+       int addr[ETH_ALEN];
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+       buf[len] = '\0';
+
+       if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+                  &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5])
+           != ETH_ALEN)
+               return -EINVAL;
+       for (i = 0; i < ETH_ALEN; i++)
+               bssid[i] = addr[i];
+
+       ret = ath6kl_wmi_force_roam_cmd(ar->wmi, bssid);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
+static const struct file_operations fops_force_roam = {
+       .write = ath6kl_force_roam_write,
+       .open = ath6kl_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_roam_mode_write(struct file *file,
+                                     const char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       int ret;
+       char buf[20];
+       size_t len;
+       enum wmi_roam_mode mode;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+       buf[len] = '\0';
+       if (len > 0 && buf[len - 1] == '\n')
+               buf[len - 1] = '\0';
+
+       if (strcasecmp(buf, "default") == 0)
+               mode = WMI_DEFAULT_ROAM_MODE;
+       else if (strcasecmp(buf, "bssbias") == 0)
+               mode = WMI_HOST_BIAS_ROAM_MODE;
+       else if (strcasecmp(buf, "lock") == 0)
+               mode = WMI_LOCK_BSS_MODE;
+       else
+               return -EINVAL;
+
+       ret = ath6kl_wmi_set_roam_mode_cmd(ar->wmi, mode);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
+static const struct file_operations fops_roam_mode = {
+       .write = ath6kl_roam_mode_write,
+       .open = ath6kl_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive)
+{
+       ar->debug.keepalive = keepalive;
+}
+
+static ssize_t ath6kl_keepalive_read(struct file *file, char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       char buf[16];
+       int len;
+
+       len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.keepalive);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath6kl_keepalive_write(struct file *file,
+                                     const char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       int ret;
+       u8 val;
+
+       ret = kstrtou8_from_user(user_buf, count, 0, &val);
+       if (ret)
+               return ret;
+
+       ret = ath6kl_wmi_set_keepalive_cmd(ar->wmi, 0, val);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
+static const struct file_operations fops_keepalive = {
+       .open = ath6kl_debugfs_open,
+       .read = ath6kl_keepalive_read,
+       .write = ath6kl_keepalive_write,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout)
+{
+       ar->debug.disc_timeout = timeout;
+}
+
+static ssize_t ath6kl_disconnect_timeout_read(struct file *file,
+                                             char __user *user_buf,
+                                             size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       char buf[16];
+       int len;
+
+       len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.disc_timeout);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath6kl_disconnect_timeout_write(struct file *file,
+                                              const char __user *user_buf,
+                                              size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       int ret;
+       u8 val;
+
+       ret = kstrtou8_from_user(user_buf, count, 0, &val);
+       if (ret)
+               return ret;
+
+       ret = ath6kl_wmi_disctimeout_cmd(ar->wmi, 0, val);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
+static const struct file_operations fops_disconnect_timeout = {
+       .open = ath6kl_debugfs_open,
+       .read = ath6kl_disconnect_timeout_read,
+       .write = ath6kl_disconnect_timeout_write,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_create_qos_write(struct file *file,
+                                               const char __user *user_buf,
+                                               size_t count, loff_t *ppos)
+{
+
+       struct ath6kl *ar = file->private_data;
+       struct ath6kl_vif *vif;
+       char buf[200];
+       ssize_t len;
+       char *sptr, *token;
+       struct wmi_create_pstream_cmd pstream;
+       u32 val32;
+       u16 val16;
+
+       vif = ath6kl_vif_first(ar);
+       if (!vif)
+               return -EIO;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+       buf[len] = '\0';
+       sptr = buf;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou8(token, 0, &pstream.user_pri))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou8(token, 0, &pstream.traffic_direc))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou8(token, 0, &pstream.traffic_class))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou8(token, 0, &pstream.traffic_type))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou8(token, 0, &pstream.voice_psc_cap))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.min_service_int = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.max_service_int = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.inactivity_int = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.suspension_int = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.service_start_time = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou8(token, 0, &pstream.tsid))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou16(token, 0, &val16))
+               return -EINVAL;
+       pstream.nominal_msdu = cpu_to_le16(val16);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou16(token, 0, &val16))
+               return -EINVAL;
+       pstream.max_msdu = cpu_to_le16(val16);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.min_data_rate = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.mean_data_rate = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.peak_data_rate = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.max_burst_size = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.delay_bound = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.min_phy_rate = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.sba = cpu_to_le32(val32);
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou32(token, 0, &val32))
+               return -EINVAL;
+       pstream.medium_time = cpu_to_le32(val32);
+
+       ath6kl_wmi_create_pstream_cmd(ar->wmi, vif->fw_vif_idx, &pstream);
+
+       return count;
+}
+
+static const struct file_operations fops_create_qos = {
+       .write = ath6kl_create_qos_write,
+       .open = ath6kl_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_delete_qos_write(struct file *file,
+                               const char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+
+       struct ath6kl *ar = file->private_data;
+       struct ath6kl_vif *vif;
+       char buf[100];
+       ssize_t len;
+       char *sptr, *token;
+       u8 traffic_class;
+       u8 tsid;
+
+       vif = ath6kl_vif_first(ar);
+       if (!vif)
+               return -EIO;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+       buf[len] = '\0';
+       sptr = buf;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou8(token, 0, &traffic_class))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou8(token, 0, &tsid))
+               return -EINVAL;
+
+       ath6kl_wmi_delete_pstream_cmd(ar->wmi, vif->fw_vif_idx,
+                                     traffic_class, tsid);
+
+       return count;
+}
+
+static const struct file_operations fops_delete_qos = {
+       .write = ath6kl_delete_qos_write,
+       .open = ath6kl_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_bgscan_int_write(struct file *file,
+                               const char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       u16 bgscan_int;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (kstrtou16(buf, 0, &bgscan_int))
+               return -EINVAL;
+
+       if (bgscan_int == 0)
+               bgscan_int = 0xffff;
+
+       ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3,
+                                 0, 0, 0);
+
+       return count;
+}
+
+static const struct file_operations fops_bgscan_int = {
+       .write = ath6kl_bgscan_int_write,
+       .open = ath6kl_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_listen_int_write(struct file *file,
+                                               const char __user *user_buf,
+                                               size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       u16 listen_int_t, listen_int_b;
+       char buf[32];
+       char *sptr, *token;
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       sptr = buf;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+
+       if (kstrtou16(token, 0, &listen_int_t))
+               return -EINVAL;
+
+       if (kstrtou16(sptr, 0, &listen_int_b))
+               return -EINVAL;
+
+       if ((listen_int_t < 15) || (listen_int_t > 5000))
+               return -EINVAL;
+
+       if ((listen_int_b < 1) || (listen_int_b > 50))
+               return -EINVAL;
+
+       ar->listen_intvl_t = listen_int_t;
+       ar->listen_intvl_b = listen_int_b;
+
+       ath6kl_wmi_listeninterval_cmd(ar->wmi, 0, ar->listen_intvl_t,
+                                     ar->listen_intvl_b);
+
+       return count;
+}
+
+static ssize_t ath6kl_listen_int_read(struct file *file,
+                                               char __user *user_buf,
+                                               size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       char buf[16];
+       int len;
+
+       len = snprintf(buf, sizeof(buf), "%u %u\n", ar->listen_intvl_t,
+                                       ar->listen_intvl_b);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_listen_int = {
+       .read = ath6kl_listen_int_read,
+       .write = ath6kl_listen_int_write,
+       .open = ath6kl_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t ath6kl_power_params_write(struct file *file,
+                                               const char __user *user_buf,
+                                               size_t count, loff_t *ppos)
+{
+       struct ath6kl *ar = file->private_data;
+       u8 buf[100];
+       unsigned int len = 0;
+       char *sptr, *token;
+       u16 idle_period, ps_poll_num, dtim,
+               tx_wakeup, num_tx;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+       buf[len] = '\0';
+       sptr = buf;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou16(token, 0, &idle_period))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou16(token, 0, &ps_poll_num))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou16(token, 0, &dtim))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou16(token, 0, &tx_wakeup))
+               return -EINVAL;
+
+       token = strsep(&sptr, " ");
+       if (!token)
+               return -EINVAL;
+       if (kstrtou16(token, 0, &num_tx))
+               return -EINVAL;
+
+       ath6kl_wmi_pmparams_cmd(ar->wmi, 0, idle_period, ps_poll_num,
+                               dtim, tx_wakeup, num_tx, 0);
+
+       return count;
+}
+
+static const struct file_operations fops_power_params = {
+       .write = ath6kl_power_params_write,
+       .open = ath6kl_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
 int ath6kl_debug_init(struct ath6kl *ar)
 {
        ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
@@ -889,7 +1649,7 @@ int ath6kl_debug_init(struct ath6kl *ar)
        ar->debug.fwlog_mask = 0;
 
        ar->debugfs_phy = debugfs_create_dir("ath6kl",
-                                            ar->wdev->wiphy->debugfsdir);
+                                            ar->wiphy->debugfsdir);
        if (!ar->debugfs_phy) {
                vfree(ar->debug.fwlog_buf.buf);
                kfree(ar->debug.fwlog_tmp);
@@ -902,6 +1662,9 @@ int ath6kl_debug_init(struct ath6kl *ar)
        debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
                            &fops_credit_dist_stats);
 
+       debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR,
+                           ar->debugfs_phy, ar, &fops_endpoint_stats);
+
        debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
                            &fops_fwlog);
 
@@ -923,6 +1686,33 @@ int ath6kl_debug_init(struct ath6kl *ar)
        debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar,
                            &fops_war_stats);
 
+       debugfs_create_file("roam_table", S_IRUSR, ar->debugfs_phy, ar,
+                           &fops_roam_table);
+
+       debugfs_create_file("force_roam", S_IWUSR, ar->debugfs_phy, ar,
+                           &fops_force_roam);
+
+       debugfs_create_file("roam_mode", S_IWUSR, ar->debugfs_phy, ar,
+                           &fops_roam_mode);
+
+       debugfs_create_file("keepalive", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar,
+                           &fops_keepalive);
+
+       debugfs_create_file("disconnect_timeout", S_IRUSR | S_IWUSR,
+                           ar->debugfs_phy, ar, &fops_disconnect_timeout);
+
+       debugfs_create_file("create_qos", S_IWUSR, ar->debugfs_phy, ar,
+                               &fops_create_qos);
+
+       debugfs_create_file("delete_qos", S_IWUSR, ar->debugfs_phy, ar,
+                               &fops_delete_qos);
+
+       debugfs_create_file("bgscan_interval", S_IWUSR,
+                               ar->debugfs_phy, ar, &fops_bgscan_int);
+
+       debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar,
+                                               &fops_power_params);
+
        return 0;
 }
 
@@ -930,6 +1720,7 @@ void ath6kl_debug_cleanup(struct ath6kl *ar)
 {
        vfree(ar->debug.fwlog_buf.buf);
        kfree(ar->debug.fwlog_tmp);
+       kfree(ar->debug.roam_tbl);
 }
 
 #endif
index 7b7675f70a102a585a6fc1be257242b1c63d496b..9853c9c125c1417c9ab87de1afc6aea8b8fe3160 100644 (file)
 #ifndef DEBUG_H
 #define DEBUG_H
 
-#include "htc_hif.h"
+#include "hif.h"
 
 enum ATH6K_DEBUG_MASK {
-       ATH6KL_DBG_WLAN_CONNECT = BIT(0),     /* wlan connect */
-       ATH6KL_DBG_WLAN_SCAN    = BIT(1),     /* wlan scan */
+       ATH6KL_DBG_CREDIT       = BIT(0),
+       /* hole */
        ATH6KL_DBG_WLAN_TX      = BIT(2),     /* wlan tx */
        ATH6KL_DBG_WLAN_RX      = BIT(3),     /* wlan rx */
        ATH6KL_DBG_BMI          = BIT(4),     /* bmi tracing */
-       ATH6KL_DBG_HTC_SEND     = BIT(5),     /* htc send */
-       ATH6KL_DBG_HTC_RECV     = BIT(6),     /* htc recv */
+       ATH6KL_DBG_HTC          = BIT(5),
+       ATH6KL_DBG_HIF          = BIT(6),
        ATH6KL_DBG_IRQ          = BIT(7),     /* interrupt processing */
-       ATH6KL_DBG_PM           = BIT(8),     /* power management */
-       ATH6KL_DBG_WLAN_NODE    = BIT(9),     /* general wlan node tracing */
+       /* hole */
+       /* hole */
        ATH6KL_DBG_WMI          = BIT(10),    /* wmi tracing */
        ATH6KL_DBG_TRC          = BIT(11),    /* generic func tracing */
        ATH6KL_DBG_SCATTER      = BIT(12),    /* hif scatter tracing */
@@ -40,6 +40,7 @@ enum ATH6K_DEBUG_MASK {
        ATH6KL_DBG_SDIO_DUMP    = BIT(17),
        ATH6KL_DBG_BOOT         = BIT(18),    /* driver init and fw boot */
        ATH6KL_DBG_WMI_DUMP     = BIT(19),
+       ATH6KL_DBG_SUSPEND      = BIT(20),
        ATH6KL_DBG_ANY          = 0xffffffff  /* enable all logs */
 };
 
@@ -90,6 +91,10 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
 void dump_cred_dist_stats(struct htc_target *target);
 void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len);
 void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war);
+int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf,
+                               size_t len);
+void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive);
+void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout);
 int ath6kl_debug_init(struct ath6kl *ar);
 void ath6kl_debug_cleanup(struct ath6kl *ar);
 
@@ -125,6 +130,21 @@ static inline void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
 {
 }
 
+static inline int ath6kl_debug_roam_tbl_event(struct ath6kl *ar,
+                                             const void *buf, size_t len)
+{
+       return 0;
+}
+
+static inline void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive)
+{
+}
+
+static inline void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar,
+                                                      u8 timeout)
+{
+}
+
 static inline int ath6kl_debug_init(struct ath6kl *ar)
 {
        return 0;
index d6c898f3d0b325a79ed968897f6cec9bdfd968a2..eed22870448bd2f68b0cc2c9897ecbc50cb2fdd4 100644 (file)
 #define HIF_OPS_H
 
 #include "hif.h"
+#include "debug.h"
 
 static inline int hif_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
                                      u32 len, u32 request)
 {
+       ath6kl_dbg(ATH6KL_DBG_HIF,
+                  "hif %s sync addr 0x%x buf 0x%p len %d request 0x%x\n",
+                  (request & HIF_WRITE) ? "write" : "read",
+                  addr, buf, len, request);
+
        return ar->hif_ops->read_write_sync(ar, addr, buf, len, request);
 }
 
@@ -29,16 +35,24 @@ static inline int hif_write_async(struct ath6kl *ar, u32 address, u8 *buffer,
                                  u32 length, u32 request,
                                  struct htc_packet *packet)
 {
+       ath6kl_dbg(ATH6KL_DBG_HIF,
+                  "hif write async addr 0x%x buf 0x%p len %d request 0x%x\n",
+                  address, buffer, length, request);
+
        return ar->hif_ops->write_async(ar, address, buffer, length,
                                        request, packet);
 }
 static inline void ath6kl_hif_irq_enable(struct ath6kl *ar)
 {
+       ath6kl_dbg(ATH6KL_DBG_HIF, "hif irq enable\n");
+
        return ar->hif_ops->irq_enable(ar);
 }
 
 static inline void ath6kl_hif_irq_disable(struct ath6kl *ar)
 {
+       ath6kl_dbg(ATH6KL_DBG_HIF, "hif irq disable\n");
+
        return ar->hif_ops->irq_disable(ar);
 }
 
@@ -69,9 +83,40 @@ static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar)
        return ar->hif_ops->cleanup_scatter(ar);
 }
 
-static inline int ath6kl_hif_suspend(struct ath6kl *ar)
+static inline int ath6kl_hif_suspend(struct ath6kl *ar,
+                                    struct cfg80211_wowlan *wow)
 {
-       return ar->hif_ops->suspend(ar);
+       ath6kl_dbg(ATH6KL_DBG_HIF, "hif suspend\n");
+
+       return ar->hif_ops->suspend(ar, wow);
+}
+
+static inline int ath6kl_hif_resume(struct ath6kl *ar)
+{
+       ath6kl_dbg(ATH6KL_DBG_HIF, "hif resume\n");
+
+       return ar->hif_ops->resume(ar);
+}
+
+static inline int ath6kl_hif_power_on(struct ath6kl *ar)
+{
+       ath6kl_dbg(ATH6KL_DBG_HIF, "hif power on\n");
+
+       return ar->hif_ops->power_on(ar);
+}
+
+static inline int ath6kl_hif_power_off(struct ath6kl *ar)
+{
+       ath6kl_dbg(ATH6KL_DBG_HIF, "hif power off\n");
+
+       return ar->hif_ops->power_off(ar);
+}
+
+static inline void ath6kl_hif_stop(struct ath6kl *ar)
+{
+       ath6kl_dbg(ATH6KL_DBG_HIF, "hif stop\n");
+
+       ar->hif_ops->stop(ar);
 }
 
 #endif
similarity index 80%
rename from drivers/net/wireless/ath/ath6kl/htc_hif.c
rename to drivers/net/wireless/ath/ath6kl/hif.c
index 86b1cc7409c2afe3e80d062141eda61498ceb7e3..e57da35e59fa78d66566841765a803f2f36e1637 100644 (file)
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+#include "hif.h"
 
 #include "core.h"
 #include "target.h"
 #include "hif-ops.h"
-#include "htc_hif.h"
 #include "debug.h"
 
 #define MAILBOX_FOR_BLOCK_SIZE          1
 
 #define ATH6KL_TIME_QUANTUM    10  /* in ms */
 
-static int ath6kldev_cp_scat_dma_buf(struct hif_scatter_req *req, bool from_dma)
+static int ath6kl_hif_cp_scat_dma_buf(struct hif_scatter_req *req,
+                                     bool from_dma)
 {
        u8 *buf;
        int i;
@@ -46,12 +47,11 @@ static int ath6kldev_cp_scat_dma_buf(struct hif_scatter_req *req, bool from_dma)
        return 0;
 }
 
-int ath6kldev_rw_comp_handler(void *context, int status)
+int ath6kl_hif_rw_comp_handler(void *context, int status)
 {
        struct htc_packet *packet = context;
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-                  "ath6kldev_rw_comp_handler (pkt:0x%p , status: %d\n",
+       ath6kl_dbg(ATH6KL_DBG_HIF, "hif rw completion pkt 0x%p status %d\n",
                   packet, status);
 
        packet->status = status;
@@ -59,30 +59,83 @@ int ath6kldev_rw_comp_handler(void *context, int status)
 
        return 0;
 }
+#define REG_DUMP_COUNT_AR6003   60
+#define REGISTER_DUMP_LEN_MAX   60
 
-static int ath6kldev_proc_dbg_intr(struct ath6kl_device *dev)
+static void ath6kl_hif_dump_fw_crash(struct ath6kl *ar)
 {
-       u32 dummy;
-       int status;
+       __le32 regdump_val[REGISTER_DUMP_LEN_MAX];
+       u32 i, address, regdump_addr = 0;
+       int ret;
+
+       if (ar->target_type != TARGET_TYPE_AR6003)
+               return;
+
+       /* the reg dump pointer is copied to the host interest area */
+       address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
+       address = TARG_VTOP(ar->target_type, address);
+
+       /* read RAM location through diagnostic window */
+       ret = ath6kl_diag_read32(ar, address, &regdump_addr);
+
+       if (ret || !regdump_addr) {
+               ath6kl_warn("failed to get ptr to register dump area: %d\n",
+                           ret);
+               return;
+       }
+
+       ath6kl_dbg(ATH6KL_DBG_IRQ, "register dump data address 0x%x\n",
+               regdump_addr);
+       regdump_addr = TARG_VTOP(ar->target_type, regdump_addr);
+
+       /* fetch register dump data */
+       ret = ath6kl_diag_read(ar, regdump_addr, (u8 *)&regdump_val[0],
+                                 REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
+       if (ret) {
+               ath6kl_warn("failed to get register dump: %d\n", ret);
+               return;
+       }
+
+       ath6kl_info("crash dump:\n");
+       ath6kl_info("hw 0x%x fw %s\n", ar->wiphy->hw_version,
+                   ar->wiphy->fw_version);
+
+       BUILD_BUG_ON(REG_DUMP_COUNT_AR6003 % 4);
 
-       ath6kl_err("target debug interrupt\n");
+       for (i = 0; i < REG_DUMP_COUNT_AR6003 / 4; i++) {
+               ath6kl_info("%d: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
+                           4 * i,
+                           le32_to_cpu(regdump_val[i]),
+                           le32_to_cpu(regdump_val[i + 1]),
+                           le32_to_cpu(regdump_val[i + 2]),
+                           le32_to_cpu(regdump_val[i + 3]));
+       }
+
+}
+
+static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
+{
+       u32 dummy;
+       int ret;
 
-       ath6kl_target_failure(dev->ar);
+       ath6kl_warn("firmware crashed\n");
 
        /*
         * read counter to clear the interrupt, the debug error interrupt is
         * counter 0.
         */
-       status = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS,
+       ret = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS,
                                     (u8 *)&dummy, 4, HIF_RD_SYNC_BYTE_INC);
-       if (status)
-               WARN_ON(1);
+       if (ret)
+               ath6kl_warn("Failed to clear debug interrupt: %d\n", ret);
 
-       return status;
+       ath6kl_hif_dump_fw_crash(dev->ar);
+
+       return ret;
 }
 
 /* mailbox recv message polling */
-int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
+int ath6kl_hif_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
                              int timeout)
 {
        struct ath6kl_irq_proc_registers *rg;
@@ -118,7 +171,7 @@ int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
 
                /* delay a little  */
                mdelay(ATH6KL_TIME_QUANTUM);
-               ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "retry mbox poll : %d\n", i);
+               ath6kl_dbg(ATH6KL_DBG_HIF, "hif retry mbox poll try %d\n", i);
        }
 
        if (i == 0) {
@@ -131,7 +184,7 @@ int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
                         * Target failure handler will be called in case of
                         * an assert.
                         */
-                       ath6kldev_proc_dbg_intr(dev);
+                       ath6kl_hif_proc_dbg_intr(dev);
        }
 
        return status;
@@ -141,11 +194,14 @@ int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
  * Disable packet reception (used in case the host runs out of buffers)
  * using the interrupt enable registers through the host I/F
  */
-int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx)
+int ath6kl_hif_rx_control(struct ath6kl_device *dev, bool enable_rx)
 {
        struct ath6kl_irq_enable_reg regs;
        int status = 0;
 
+       ath6kl_dbg(ATH6KL_DBG_HIF, "hif rx %s\n",
+                  enable_rx ? "enable" : "disable");
+
        /* take the lock to protect interrupt enable shadows */
        spin_lock_bh(&dev->lock);
 
@@ -168,7 +224,7 @@ int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx)
        return status;
 }
 
-int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
+int ath6kl_hif_submit_scat_req(struct ath6kl_device *dev,
                              struct hif_scatter_req *scat_req, bool read)
 {
        int status = 0;
@@ -185,14 +241,14 @@ int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
                        dev->ar->mbox_info.htc_addr;
        }
 
-       ath6kl_dbg((ATH6KL_DBG_HTC_RECV | ATH6KL_DBG_HTC_SEND),
-                  "ath6kldev_submit_scat_req, entries: %d, total len: %d mbox:0x%X (mode: %s : %s)\n",
+       ath6kl_dbg(ATH6KL_DBG_HIF,
+                  "hif submit scatter request entries %d len %d mbox 0x%x %s %s\n",
                   scat_req->scat_entries, scat_req->len,
                   scat_req->addr, !read ? "async" : "sync",
                   (read) ? "rd" : "wr");
 
        if (!read && scat_req->virt_scat) {
-               status = ath6kldev_cp_scat_dma_buf(scat_req, false);
+               status = ath6kl_hif_cp_scat_dma_buf(scat_req, false);
                if (status) {
                        scat_req->status = status;
                        scat_req->complete(dev->ar->htc_target, scat_req);
@@ -207,13 +263,13 @@ int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
                scat_req->status = status;
                if (!status && scat_req->virt_scat)
                        scat_req->status =
-                               ath6kldev_cp_scat_dma_buf(scat_req, true);
+                               ath6kl_hif_cp_scat_dma_buf(scat_req, true);
        }
 
        return status;
 }
 
-static int ath6kldev_proc_counter_intr(struct ath6kl_device *dev)
+static int ath6kl_hif_proc_counter_intr(struct ath6kl_device *dev)
 {
        u8 counter_int_status;
 
@@ -232,12 +288,12 @@ static int ath6kldev_proc_counter_intr(struct ath6kl_device *dev)
         * the debug assertion counter interrupt.
         */
        if (counter_int_status & ATH6KL_TARGET_DEBUG_INTR_MASK)
-               return ath6kldev_proc_dbg_intr(dev);
+               return ath6kl_hif_proc_dbg_intr(dev);
 
        return 0;
 }
 
-static int ath6kldev_proc_err_intr(struct ath6kl_device *dev)
+static int ath6kl_hif_proc_err_intr(struct ath6kl_device *dev)
 {
        int status;
        u8 error_int_status;
@@ -282,7 +338,7 @@ static int ath6kldev_proc_err_intr(struct ath6kl_device *dev)
        return status;
 }
 
-static int ath6kldev_proc_cpu_intr(struct ath6kl_device *dev)
+static int ath6kl_hif_proc_cpu_intr(struct ath6kl_device *dev)
 {
        int status;
        u8 cpu_int_status;
@@ -417,7 +473,7 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done)
                 * we rapidly pull packets.
                 */
                status = ath6kl_htc_rxmsg_pending_handler(dev->htc_cnxt,
-                                                         &lk_ahd, &fetched);
+                                                         lk_ahd, &fetched);
                if (status)
                        goto out;
 
@@ -436,21 +492,21 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done)
 
        if (MS(HOST_INT_STATUS_CPU, host_int_status)) {
                /* CPU Interrupt */
-               status = ath6kldev_proc_cpu_intr(dev);
+               status = ath6kl_hif_proc_cpu_intr(dev);
                if (status)
                        goto out;
        }
 
        if (MS(HOST_INT_STATUS_ERROR, host_int_status)) {
                /* Error Interrupt */
-               status = ath6kldev_proc_err_intr(dev);
+               status = ath6kl_hif_proc_err_intr(dev);
                if (status)
                        goto out;
        }
 
        if (MS(HOST_INT_STATUS_COUNTER, host_int_status))
                /* Counter Interrupt */
-               status = ath6kldev_proc_counter_intr(dev);
+               status = ath6kl_hif_proc_counter_intr(dev);
 
 out:
        /*
@@ -479,9 +535,10 @@ out:
 }
 
 /* interrupt handler, kicks off all interrupt processing */
-int ath6kldev_intr_bh_handler(struct ath6kl *ar)
+int ath6kl_hif_intr_bh_handler(struct ath6kl *ar)
 {
        struct ath6kl_device *dev = ar->htc_target->dev;
+       unsigned long timeout;
        int status = 0;
        bool done = false;
 
@@ -495,7 +552,8 @@ int ath6kldev_intr_bh_handler(struct ath6kl *ar)
         * IRQ processing is synchronous, interrupt status registers can be
         * re-read.
         */
-       while (!done) {
+       timeout = jiffies + msecs_to_jiffies(ATH6KL_HIF_COMMUNICATION_TIMEOUT);
+       while (time_before(jiffies, timeout) && !done) {
                status = proc_pending_irqs(dev, &done);
                if (status)
                        break;
@@ -504,7 +562,7 @@ int ath6kldev_intr_bh_handler(struct ath6kl *ar)
        return status;
 }
 
-static int ath6kldev_enable_intrs(struct ath6kl_device *dev)
+static int ath6kl_hif_enable_intrs(struct ath6kl_device *dev)
 {
        struct ath6kl_irq_enable_reg regs;
        int status;
@@ -552,7 +610,7 @@ static int ath6kldev_enable_intrs(struct ath6kl_device *dev)
        return status;
 }
 
-int ath6kldev_disable_intrs(struct ath6kl_device *dev)
+int ath6kl_hif_disable_intrs(struct ath6kl_device *dev)
 {
        struct ath6kl_irq_enable_reg regs;
 
@@ -571,7 +629,7 @@ int ath6kldev_disable_intrs(struct ath6kl_device *dev)
 }
 
 /* enable device interrupts */
-int ath6kldev_unmask_intrs(struct ath6kl_device *dev)
+int ath6kl_hif_unmask_intrs(struct ath6kl_device *dev)
 {
        int status = 0;
 
@@ -583,29 +641,29 @@ int ath6kldev_unmask_intrs(struct ath6kl_device *dev)
         * target "soft" resets. The ATH6KL interrupt enables reset back to an
         * "enabled" state when this happens.
         */
-       ath6kldev_disable_intrs(dev);
+       ath6kl_hif_disable_intrs(dev);
 
        /* unmask the host controller interrupts */
        ath6kl_hif_irq_enable(dev->ar);
-       status = ath6kldev_enable_intrs(dev);
+       status = ath6kl_hif_enable_intrs(dev);
 
        return status;
 }
 
 /* disable all device interrupts */
-int ath6kldev_mask_intrs(struct ath6kl_device *dev)
+int ath6kl_hif_mask_intrs(struct ath6kl_device *dev)
 {
        /*
         * Mask the interrupt at the HIF layer to avoid any stray interrupt
         * taken while we zero out our shadow registers in
-        * ath6kldev_disable_intrs().
+        * ath6kl_hif_disable_intrs().
         */
        ath6kl_hif_irq_disable(dev->ar);
 
-       return ath6kldev_disable_intrs(dev);
+       return ath6kl_hif_disable_intrs(dev);
 }
 
-int ath6kldev_setup(struct ath6kl_device *dev)
+int ath6kl_hif_setup(struct ath6kl_device *dev)
 {
        int status = 0;
 
@@ -621,19 +679,17 @@ int ath6kldev_setup(struct ath6kl_device *dev)
        /* must be a power of 2 */
        if ((dev->htc_cnxt->block_sz & (dev->htc_cnxt->block_sz - 1)) != 0) {
                WARN_ON(1);
+               status = -EINVAL;
                goto fail_setup;
        }
 
        /* assemble mask, used for padding to a block */
        dev->htc_cnxt->block_mask = dev->htc_cnxt->block_sz - 1;
 
-       ath6kl_dbg(ATH6KL_DBG_TRC, "block size: %d, mbox addr:0x%X\n",
+       ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n",
                   dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr);
 
-       ath6kl_dbg(ATH6KL_DBG_TRC,
-                  "hif interrupt processing is sync only\n");
-
-       status = ath6kldev_disable_intrs(dev);
+       status = ath6kl_hif_disable_intrs(dev);
 
 fail_setup:
        return status;
index 797e2d1d9bf9f41ede26891e1ac1eef0f673be5c..f2dc3bcdae4ae6661fdf191e93181855f685b597 100644 (file)
 /* mode to enable special 4-bit interrupt assertion without clock */
 #define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ   (1 << 0)
 
+/* HTC runs over mailbox 0 */
+#define HTC_MAILBOX    0
+
+#define ATH6KL_TARGET_DEBUG_INTR_MASK     0x01
+
+/* FIXME: are these duplicates with MAX_SCATTER_ values in hif.h? */
+#define ATH6KL_SCATTER_ENTRIES_PER_REQ            16
+#define ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER      (16 * 1024)
+#define ATH6KL_SCATTER_REQS                       4
+
+#define ATH6KL_HIF_COMMUNICATION_TIMEOUT       1000
+
 struct bus_request {
        struct list_head list;
 
@@ -186,6 +198,34 @@ struct hif_scatter_req {
        struct hif_scatter_item scat_list[1];
 };
 
+struct ath6kl_irq_proc_registers {
+       u8 host_int_status;
+       u8 cpu_int_status;
+       u8 error_int_status;
+       u8 counter_int_status;
+       u8 mbox_frame;
+       u8 rx_lkahd_valid;
+       u8 host_int_status2;
+       u8 gmbox_rx_avail;
+       __le32 rx_lkahd[2];
+       __le32 rx_gmbox_lkahd_alias[2];
+} __packed;
+
+struct ath6kl_irq_enable_reg {
+       u8 int_status_en;
+       u8 cpu_int_status_en;
+       u8 err_int_status_en;
+       u8 cntr_int_status_en;
+} __packed;
+
+struct ath6kl_device {
+       spinlock_t lock;
+       struct ath6kl_irq_proc_registers irq_proc_reg;
+       struct ath6kl_irq_enable_reg irq_en_reg;
+       struct htc_target *htc_cnxt;
+       struct ath6kl *ar;
+};
+
 struct ath6kl_hif_ops {
        int (*read_write_sync)(struct ath6kl *ar, u32 addr, u8 *buf,
                               u32 len, u32 request);
@@ -202,7 +242,26 @@ struct ath6kl_hif_ops {
        int (*scat_req_rw) (struct ath6kl *ar,
                            struct hif_scatter_req *scat_req);
        void (*cleanup_scatter)(struct ath6kl *ar);
-       int (*suspend)(struct ath6kl *ar);
+       int (*suspend)(struct ath6kl *ar, struct cfg80211_wowlan *wow);
+       int (*resume)(struct ath6kl *ar);
+       int (*power_on)(struct ath6kl *ar);
+       int (*power_off)(struct ath6kl *ar);
+       void (*stop)(struct ath6kl *ar);
 };
 
+int ath6kl_hif_setup(struct ath6kl_device *dev);
+int ath6kl_hif_unmask_intrs(struct ath6kl_device *dev);
+int ath6kl_hif_mask_intrs(struct ath6kl_device *dev);
+int ath6kl_hif_poll_mboxmsg_rx(struct ath6kl_device *dev,
+                              u32 *lk_ahd, int timeout);
+int ath6kl_hif_rx_control(struct ath6kl_device *dev, bool enable_rx);
+int ath6kl_hif_disable_intrs(struct ath6kl_device *dev);
+
+int ath6kl_hif_rw_comp_handler(void *context, int status);
+int ath6kl_hif_intr_bh_handler(struct ath6kl *ar);
+
+/* Scatter Function and Definitions */
+int ath6kl_hif_submit_scat_req(struct ath6kl_device *dev,
+                              struct hif_scatter_req *scat_req, bool read);
+
 #endif
index f88a7c9e41485d6cb1806110c359e4d8cddce241..f3b63ca25c7e02b469feb800f8294fe1c3d195b5 100644 (file)
  */
 
 #include "core.h"
-#include "htc_hif.h"
+#include "hif.h"
 #include "debug.h"
 #include "hif-ops.h"
 #include <asm/unaligned.h>
 
 #define CALC_TXRX_PADDED_LEN(dev, len)  (__ALIGN_MASK((len), (dev)->block_mask))
 
+/* Functions for Tx credit handling */
+static void ath6kl_credit_deposit(struct ath6kl_htc_credit_info *cred_info,
+                                 struct htc_endpoint_credit_dist *ep_dist,
+                                 int credits)
+{
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, "credit deposit ep %d credits %d\n",
+                  ep_dist->endpoint, credits);
+
+       ep_dist->credits += credits;
+       ep_dist->cred_assngd += credits;
+       cred_info->cur_free_credits -= credits;
+}
+
+static void ath6kl_credit_init(struct ath6kl_htc_credit_info *cred_info,
+                              struct list_head *ep_list,
+                              int tot_credits)
+{
+       struct htc_endpoint_credit_dist *cur_ep_dist;
+       int count;
+
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, "credit init total %d\n", tot_credits);
+
+       cred_info->cur_free_credits = tot_credits;
+       cred_info->total_avail_credits = tot_credits;
+
+       list_for_each_entry(cur_ep_dist, ep_list, list) {
+               if (cur_ep_dist->endpoint == ENDPOINT_0)
+                       continue;
+
+               cur_ep_dist->cred_min = cur_ep_dist->cred_per_msg;
+
+               if (tot_credits > 4) {
+                       if ((cur_ep_dist->svc_id == WMI_DATA_BK_SVC) ||
+                           (cur_ep_dist->svc_id == WMI_DATA_BE_SVC)) {
+                               ath6kl_credit_deposit(cred_info,
+                                                     cur_ep_dist,
+                                                     cur_ep_dist->cred_min);
+                               cur_ep_dist->dist_flags |= HTC_EP_ACTIVE;
+                       }
+               }
+
+               if (cur_ep_dist->svc_id == WMI_CONTROL_SVC) {
+                       ath6kl_credit_deposit(cred_info, cur_ep_dist,
+                                             cur_ep_dist->cred_min);
+                       /*
+                        * Control service is always marked active, it
+                        * never goes inactive EVER.
+                        */
+                       cur_ep_dist->dist_flags |= HTC_EP_ACTIVE;
+               } else if (cur_ep_dist->svc_id == WMI_DATA_BK_SVC)
+                       /* this is the lowest priority data endpoint */
+                       /* FIXME: this looks fishy, check */
+                       cred_info->lowestpri_ep_dist = cur_ep_dist->list;
+
+               /*
+                * Streams have to be created (explicit | implicit) for all
+                * kinds of traffic. BE endpoints are also inactive in the
+                * beginning. When BE traffic starts it creates implicit
+                * streams that redistributes credits.
+                *
+                * Note: all other endpoints have minimums set but are
+                * initially given NO credits. credits will be distributed
+                * as traffic activity demands
+                */
+       }
+
+       WARN_ON(cred_info->cur_free_credits <= 0);
+
+       list_for_each_entry(cur_ep_dist, ep_list, list) {
+               if (cur_ep_dist->endpoint == ENDPOINT_0)
+                       continue;
+
+               if (cur_ep_dist->svc_id == WMI_CONTROL_SVC)
+                       cur_ep_dist->cred_norm = cur_ep_dist->cred_per_msg;
+               else {
+                       /*
+                        * For the remaining data endpoints, we assume that
+                        * each cred_per_msg are the same. We use a simple
+                        * calculation here, we take the remaining credits
+                        * and determine how many max messages this can
+                        * cover and then set each endpoint's normal value
+                        * equal to 3/4 this amount.
+                        */
+                       count = (cred_info->cur_free_credits /
+                                cur_ep_dist->cred_per_msg)
+                               * cur_ep_dist->cred_per_msg;
+                       count = (count * 3) >> 2;
+                       count = max(count, cur_ep_dist->cred_per_msg);
+                       cur_ep_dist->cred_norm = count;
+
+               }
+
+               ath6kl_dbg(ATH6KL_DBG_CREDIT,
+                          "credit ep %d svc_id %d credits %d per_msg %d norm %d min %d\n",
+                          cur_ep_dist->endpoint,
+                          cur_ep_dist->svc_id,
+                          cur_ep_dist->credits,
+                          cur_ep_dist->cred_per_msg,
+                          cur_ep_dist->cred_norm,
+                          cur_ep_dist->cred_min);
+       }
+}
+
+/* initialize and setup credit distribution */
+int ath6kl_credit_setup(void *htc_handle,
+                       struct ath6kl_htc_credit_info *cred_info)
+{
+       u16 servicepriority[5];
+
+       memset(cred_info, 0, sizeof(struct ath6kl_htc_credit_info));
+
+       servicepriority[0] = WMI_CONTROL_SVC;  /* highest */
+       servicepriority[1] = WMI_DATA_VO_SVC;
+       servicepriority[2] = WMI_DATA_VI_SVC;
+       servicepriority[3] = WMI_DATA_BE_SVC;
+       servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */
+
+       /* set priority list */
+       ath6kl_htc_set_credit_dist(htc_handle, cred_info, servicepriority, 5);
+
+       return 0;
+}
+
+/* reduce an ep's credits back to a set limit */
+static void ath6kl_credit_reduce(struct ath6kl_htc_credit_info *cred_info,
+                                struct htc_endpoint_credit_dist *ep_dist,
+                                int limit)
+{
+       int credits;
+
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, "credit reduce ep %d limit %d\n",
+                  ep_dist->endpoint, limit);
+
+       ep_dist->cred_assngd = limit;
+
+       if (ep_dist->credits <= limit)
+               return;
+
+       credits = ep_dist->credits - limit;
+       ep_dist->credits -= credits;
+       cred_info->cur_free_credits += credits;
+}
+
+static void ath6kl_credit_update(struct ath6kl_htc_credit_info *cred_info,
+                                struct list_head *epdist_list)
+{
+       struct htc_endpoint_credit_dist *cur_dist_list;
+
+       list_for_each_entry(cur_dist_list, epdist_list, list) {
+               if (cur_dist_list->endpoint == ENDPOINT_0)
+                       continue;
+
+               if (cur_dist_list->cred_to_dist > 0) {
+                       cur_dist_list->credits +=
+                                       cur_dist_list->cred_to_dist;
+                       cur_dist_list->cred_to_dist = 0;
+                       if (cur_dist_list->credits >
+                           cur_dist_list->cred_assngd)
+                               ath6kl_credit_reduce(cred_info,
+                                               cur_dist_list,
+                                               cur_dist_list->cred_assngd);
+
+                       if (cur_dist_list->credits >
+                           cur_dist_list->cred_norm)
+                               ath6kl_credit_reduce(cred_info, cur_dist_list,
+                                                    cur_dist_list->cred_norm);
+
+                       if (!(cur_dist_list->dist_flags & HTC_EP_ACTIVE)) {
+                               if (cur_dist_list->txq_depth == 0)
+                                       ath6kl_credit_reduce(cred_info,
+                                                            cur_dist_list, 0);
+                       }
+               }
+       }
+}
+
+/*
+ * HTC has an endpoint that needs credits, ep_dist is the endpoint in
+ * question.
+ */
+static void ath6kl_credit_seek(struct ath6kl_htc_credit_info *cred_info,
+                               struct htc_endpoint_credit_dist *ep_dist)
+{
+       struct htc_endpoint_credit_dist *curdist_list;
+       int credits = 0;
+       int need;
+
+       if (ep_dist->svc_id == WMI_CONTROL_SVC)
+               goto out;
+
+       if ((ep_dist->svc_id == WMI_DATA_VI_SVC) ||
+           (ep_dist->svc_id == WMI_DATA_VO_SVC))
+               if ((ep_dist->cred_assngd >= ep_dist->cred_norm))
+                       goto out;
+
+       /*
+        * For all other services, we follow a simple algorithm of:
+        *
+        * 1. checking the free pool for credits
+        * 2. checking lower priority endpoints for credits to take
+        */
+
+       credits = min(cred_info->cur_free_credits, ep_dist->seek_cred);
+
+       if (credits >= ep_dist->seek_cred)
+               goto out;
+
+       /*
+        * We don't have enough in the free pool, try taking away from
+        * lower priority services The rule for taking away credits:
+        *
+        *   1. Only take from lower priority endpoints
+        *   2. Only take what is allocated above the minimum (never
+        *      starve an endpoint completely)
+        *   3. Only take what you need.
+        */
+
+       list_for_each_entry_reverse(curdist_list,
+                                   &cred_info->lowestpri_ep_dist,
+                                   list) {
+               if (curdist_list == ep_dist)
+                       break;
+
+               need = ep_dist->seek_cred - cred_info->cur_free_credits;
+
+               if ((curdist_list->cred_assngd - need) >=
+                    curdist_list->cred_min) {
+                       /*
+                        * The current one has been allocated more than
+                        * it's minimum and it has enough credits assigned
+                        * above it's minimum to fulfill our need try to
+                        * take away just enough to fulfill our need.
+                        */
+                       ath6kl_credit_reduce(cred_info, curdist_list,
+                                            curdist_list->cred_assngd - need);
+
+                       if (cred_info->cur_free_credits >=
+                           ep_dist->seek_cred)
+                               break;
+               }
+
+               if (curdist_list->endpoint == ENDPOINT_0)
+                       break;
+       }
+
+       credits = min(cred_info->cur_free_credits, ep_dist->seek_cred);
+
+out:
+       /* did we find some credits? */
+       if (credits)
+               ath6kl_credit_deposit(cred_info, ep_dist, credits);
+
+       ep_dist->seek_cred = 0;
+}
+
+/* redistribute credits based on activity change */
+static void ath6kl_credit_redistribute(struct ath6kl_htc_credit_info *info,
+                                      struct list_head *ep_dist_list)
+{
+       struct htc_endpoint_credit_dist *curdist_list;
+
+       list_for_each_entry(curdist_list, ep_dist_list, list) {
+               if (curdist_list->endpoint == ENDPOINT_0)
+                       continue;
+
+               if ((curdist_list->svc_id == WMI_DATA_BK_SVC)  ||
+                   (curdist_list->svc_id == WMI_DATA_BE_SVC))
+                       curdist_list->dist_flags |= HTC_EP_ACTIVE;
+
+               if ((curdist_list->svc_id != WMI_CONTROL_SVC) &&
+                   !(curdist_list->dist_flags & HTC_EP_ACTIVE)) {
+                       if (curdist_list->txq_depth == 0)
+                               ath6kl_credit_reduce(info, curdist_list, 0);
+                       else
+                               ath6kl_credit_reduce(info,
+                                                    curdist_list,
+                                                    curdist_list->cred_min);
+               }
+       }
+}
+
+/*
+ *
+ * This function is invoked whenever endpoints require credit
+ * distributions. A lock is held while this function is invoked, this
+ * function shall NOT block. The ep_dist_list is a list of distribution
+ * structures in prioritized order as defined by the call to the
+ * htc_set_credit_dist() api.
+ */
+static void ath6kl_credit_distribute(struct ath6kl_htc_credit_info *cred_info,
+                                    struct list_head *ep_dist_list,
+                             enum htc_credit_dist_reason reason)
+{
+       switch (reason) {
+       case HTC_CREDIT_DIST_SEND_COMPLETE:
+               ath6kl_credit_update(cred_info, ep_dist_list);
+               break;
+       case HTC_CREDIT_DIST_ACTIVITY_CHANGE:
+               ath6kl_credit_redistribute(cred_info, ep_dist_list);
+               break;
+       default:
+               break;
+       }
+
+       WARN_ON(cred_info->cur_free_credits > cred_info->total_avail_credits);
+       WARN_ON(cred_info->cur_free_credits < 0);
+}
+
 static void ath6kl_htc_tx_buf_align(u8 **buf, unsigned long len)
 {
        u8 *align_addr;
@@ -102,12 +410,12 @@ static void htc_tx_comp_update(struct htc_target *target,
                                packet->info.tx.cred_used;
        endpoint->cred_dist.txq_depth = get_queue_depth(&endpoint->txq);
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
-                  target->cred_dist_cntxt, &target->cred_dist_list);
+       ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx ctxt 0x%p dist 0x%p\n",
+                  target->credit_info, &target->cred_dist_list);
 
-       ath6k_credit_distribute(target->cred_dist_cntxt,
-                               &target->cred_dist_list,
-                               HTC_CREDIT_DIST_SEND_COMPLETE);
+       ath6kl_credit_distribute(target->credit_info,
+                                &target->cred_dist_list,
+                                HTC_CREDIT_DIST_SEND_COMPLETE);
 
        spin_unlock_bh(&target->tx_lock);
 }
@@ -118,8 +426,8 @@ static void htc_tx_complete(struct htc_endpoint *endpoint,
        if (list_empty(txq))
                return;
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                  "send complete ep %d, (%d pkts)\n",
+       ath6kl_dbg(ATH6KL_DBG_HTC,
+                  "htc tx complete ep %d pkts %d\n",
                   endpoint->eid, get_queue_depth(txq));
 
        ath6kl_tx_complete(endpoint->target->dev->ar, txq);
@@ -131,6 +439,9 @@ static void htc_tx_comp_handler(struct htc_target *target,
        struct htc_endpoint *endpoint = &target->endpoint[packet->endpoint];
        struct list_head container;
 
+       ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx complete seqno %d\n",
+                  packet->info.tx.seqno);
+
        htc_tx_comp_update(target, endpoint, packet);
        INIT_LIST_HEAD(&container);
        list_add_tail(&packet->list, &container);
@@ -148,8 +459,8 @@ static void htc_async_tx_scat_complete(struct htc_target *target,
 
        INIT_LIST_HEAD(&tx_compq);
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-               "htc_async_tx_scat_complete  total len: %d  entries: %d\n",
+       ath6kl_dbg(ATH6KL_DBG_HTC,
+               "htc tx scat complete len %d entries %d\n",
                scat_req->len, scat_req->scat_entries);
 
        if (scat_req->status)
@@ -190,16 +501,13 @@ static int ath6kl_htc_tx_issue(struct htc_target *target,
 
        send_len = packet->act_len + HTC_HDR_LENGTH;
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "%s: transmit len : %d (%s)\n",
-                  __func__, send_len, sync ? "sync" : "async");
-
        padded_len = CALC_TXRX_PADDED_LEN(target, send_len);
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-               "DevSendPacket, padded len: %d mbox:0x%X (mode:%s)\n",
-               padded_len,
-               target->dev->ar->mbox_info.htc_addr,
-               sync ? "sync" : "async");
+       ath6kl_dbg(ATH6KL_DBG_HTC,
+                  "htc tx issue len %d seqno %d padded_len %d mbox 0x%X %s\n",
+                  send_len, packet->info.tx.seqno, padded_len,
+                  target->dev->ar->mbox_info.htc_addr,
+                  sync ? "sync" : "async");
 
        if (sync) {
                status = hif_read_write_sync(target->dev->ar,
@@ -227,7 +535,7 @@ static int htc_check_credits(struct htc_target *target,
        *req_cred = (len > target->tgt_cred_sz) ?
                     DIV_ROUND_UP(len, target->tgt_cred_sz) : 1;
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "creds required:%d got:%d\n",
+       ath6kl_dbg(ATH6KL_DBG_CREDIT, "credit check need %d got %d\n",
                   *req_cred, ep->cred_dist.credits);
 
        if (ep->cred_dist.credits < *req_cred) {
@@ -237,16 +545,13 @@ static int htc_check_credits(struct htc_target *target,
                /* Seek more credits */
                ep->cred_dist.seek_cred = *req_cred - ep->cred_dist.credits;
 
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
-                          target->cred_dist_cntxt, &ep->cred_dist);
-
-               ath6k_seek_credits(target->cred_dist_cntxt, &ep->cred_dist);
+               ath6kl_credit_seek(target->credit_info, &ep->cred_dist);
 
                ep->cred_dist.seek_cred = 0;
 
                if (ep->cred_dist.credits < *req_cred) {
-                       ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                                  "not enough credits for ep %d - leaving packet in queue\n",
+                       ath6kl_dbg(ATH6KL_DBG_CREDIT,
+                                  "credit not found for ep %d\n",
                                   eid);
                        return -EINVAL;
                }
@@ -260,17 +565,15 @@ static int htc_check_credits(struct htc_target *target,
                ep->cred_dist.seek_cred =
                ep->cred_dist.cred_per_msg - ep->cred_dist.credits;
 
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
-                          target->cred_dist_cntxt, &ep->cred_dist);
-
-               ath6k_seek_credits(target->cred_dist_cntxt, &ep->cred_dist);
+               ath6kl_credit_seek(target->credit_info, &ep->cred_dist);
 
                /* see if we were successful in getting more */
                if (ep->cred_dist.credits < ep->cred_dist.cred_per_msg) {
                        /* tell the target we need credits ASAP! */
                        *flags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
                        ep->ep_st.cred_low_indicate += 1;
-                       ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "host needs credits\n");
+                       ath6kl_dbg(ATH6KL_DBG_CREDIT,
+                                  "credit we need credits asap\n");
                }
        }
 
@@ -295,8 +598,8 @@ static void ath6kl_htc_tx_pkts_get(struct htc_target *target,
                packet = list_first_entry(&endpoint->txq, struct htc_packet,
                                          list);
 
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                       "got head pkt:0x%p , queue depth: %d\n",
+               ath6kl_dbg(ATH6KL_DBG_HTC,
+                       "htc tx got packet 0x%p queue depth %d\n",
                        packet, get_queue_depth(&endpoint->txq));
 
                len = CALC_TXRX_PADDED_LEN(target,
@@ -404,9 +707,9 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target,
 
                scat_req->len += len;
                scat_req->scat_entries++;
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                          "%d, adding pkt : 0x%p len:%d (remaining space:%d)\n",
-                          i, packet, len, rem_scat);
+               ath6kl_dbg(ATH6KL_DBG_HTC,
+                          "htc tx adding (%d) pkt 0x%p seqno %d len %d remaining %d\n",
+                          i, packet, packet->info.tx.seqno, len, rem_scat);
        }
 
        /* Roll back scatter setup in case of any failure */
@@ -455,12 +758,12 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
 
                if (!scat_req) {
                        /* no scatter resources  */
-                       ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                               "no more scatter resources\n");
+                       ath6kl_dbg(ATH6KL_DBG_HTC,
+                               "htc tx no more scatter resources\n");
                        break;
                }
 
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "pkts to scatter: %d\n",
+               ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n",
                           n_scat);
 
                scat_req->len = 0;
@@ -479,10 +782,10 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
                n_sent_bundle++;
                tot_pkts_bundle += scat_req->scat_entries;
 
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                          "send scatter total bytes: %d , entries: %d\n",
+               ath6kl_dbg(ATH6KL_DBG_HTC,
+                          "htc tx scatter bytes %d entries %d\n",
                           scat_req->len, scat_req->scat_entries);
-               ath6kldev_submit_scat_req(target->dev, scat_req, false);
+               ath6kl_hif_submit_scat_req(target->dev, scat_req, false);
 
                if (status)
                        break;
@@ -490,8 +793,8 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
 
        *sent_bundle = n_sent_bundle;
        *n_bundle_pkts = tot_pkts_bundle;
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "%s (sent:%d)\n",
-                  __func__, n_sent_bundle);
+       ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx bundle sent %d pkts\n",
+                  n_sent_bundle);
 
        return;
 }
@@ -510,7 +813,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
        if (endpoint->tx_proc_cnt > 1) {
                endpoint->tx_proc_cnt--;
                spin_unlock_bh(&target->tx_lock);
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "htc_try_send (busy)\n");
+               ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx busy\n");
                return;
        }
 
@@ -588,15 +891,12 @@ static bool ath6kl_htc_tx_try(struct htc_target *target,
                overflow = true;
 
        if (overflow)
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                          "ep %d, tx queue will overflow :%d , tx depth:%d, max:%d\n",
-                          endpoint->eid, overflow, txq_depth,
+               ath6kl_dbg(ATH6KL_DBG_HTC,
+                          "htc tx overflow ep %d depth %d max %d\n",
+                          endpoint->eid, txq_depth,
                           endpoint->max_txq_depth);
 
        if (overflow && ep_cb.tx_full) {
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                          "indicating overflowed tx packet: 0x%p\n", tx_pkt);
-
                if (ep_cb.tx_full(endpoint->target, tx_pkt) ==
                    HTC_SEND_FULL_DROP) {
                        endpoint->ep_st.tx_dropped += 1;
@@ -625,12 +925,12 @@ static void htc_chk_ep_txq(struct htc_target *target)
         * are not modifying any state.
         */
        list_for_each_entry(cred_dist, &target->cred_dist_list, list) {
-               endpoint = (struct htc_endpoint *)cred_dist->htc_rsvd;
+               endpoint = cred_dist->htc_ep;
 
                spin_lock_bh(&target->tx_lock);
                if (!list_empty(&endpoint->txq)) {
-                       ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                                  "ep %d has %d credits and %d packets in tx queue\n",
+                       ath6kl_dbg(ATH6KL_DBG_HTC,
+                                  "htc creds ep %d credits %d pkts %d\n",
                                   cred_dist->endpoint,
                                   endpoint->cred_dist.credits,
                                   get_queue_depth(&endpoint->txq));
@@ -704,13 +1004,13 @@ static int htc_setup_tx_complete(struct htc_target *target)
 }
 
 void ath6kl_htc_set_credit_dist(struct htc_target *target,
-                               struct htc_credit_state_info *cred_dist_cntxt,
+                               struct ath6kl_htc_credit_info *credit_info,
                                u16 srvc_pri_order[], int list_len)
 {
        struct htc_endpoint *endpoint;
        int i, ep;
 
-       target->cred_dist_cntxt = cred_dist_cntxt;
+       target->credit_info = credit_info;
 
        list_add_tail(&target->endpoint[ENDPOINT_0].cred_dist.list,
                      &target->cred_dist_list);
@@ -736,8 +1036,8 @@ int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet)
        struct htc_endpoint *endpoint;
        struct list_head queue;
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                  "htc_tx: ep id: %d, buf: 0x%p, len: %d\n",
+       ath6kl_dbg(ATH6KL_DBG_HTC,
+                  "htc tx ep id %d buf 0x%p len %d\n",
                   packet->endpoint, packet->buf, packet->act_len);
 
        if (packet->endpoint >= ENDPOINT_MAX) {
@@ -787,8 +1087,8 @@ void ath6kl_htc_flush_txep(struct htc_target *target,
        list_for_each_entry_safe(packet, tmp_pkt, &discard_q, list) {
                packet->status = -ECANCELED;
                list_del(&packet->list);
-               ath6kl_dbg(ATH6KL_DBG_TRC,
-                       "flushing tx pkt:0x%p, len:%d, ep:%d tag:0x%X\n",
+               ath6kl_dbg(ATH6KL_DBG_HTC,
+                       "htc tx flushing pkt 0x%p len %d  ep %d tag 0x%x\n",
                        packet, packet->act_len,
                        packet->endpoint, packet->info.tx.tag);
 
@@ -844,12 +1144,13 @@ void ath6kl_htc_indicate_activity_change(struct htc_target *target,
                endpoint->cred_dist.txq_depth =
                        get_queue_depth(&endpoint->txq);
 
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
-                          target->cred_dist_cntxt, &target->cred_dist_list);
+               ath6kl_dbg(ATH6KL_DBG_HTC,
+                          "htc tx activity ctxt 0x%p dist 0x%p\n",
+                          target->credit_info, &target->cred_dist_list);
 
-               ath6k_credit_distribute(target->cred_dist_cntxt,
-                                       &target->cred_dist_list,
-                                       HTC_CREDIT_DIST_ACTIVITY_CHANGE);
+               ath6kl_credit_distribute(target->credit_info,
+                                        &target->cred_dist_list,
+                                        HTC_CREDIT_DIST_ACTIVITY_CHANGE);
        }
 
        spin_unlock_bh(&target->tx_lock);
@@ -919,15 +1220,15 @@ static int ath6kl_htc_rx_packet(struct htc_target *target,
        padded_len = CALC_TXRX_PADDED_LEN(target, rx_len);
 
        if (padded_len > packet->buf_len) {
-               ath6kl_err("not enough receive space for packet - padlen:%d recvlen:%d bufferlen:%d\n",
+               ath6kl_err("not enough receive space for packet - padlen %d recvlen %d bufferlen %d\n",
                           padded_len, rx_len, packet->buf_len);
                return -ENOMEM;
        }
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-                  "dev_rx_pkt (0x%p : hdr:0x%X) padded len: %d mbox:0x%X (mode:%s)\n",
+       ath6kl_dbg(ATH6KL_DBG_HTC,
+                  "htc rx 0x%p hdr x%x len %d mbox 0x%x\n",
                   packet, packet->info.rx.exp_hdr,
-                  padded_len, dev->ar->mbox_info.htc_addr, "sync");
+                  padded_len, dev->ar->mbox_info.htc_addr);
 
        status = hif_read_write_sync(dev->ar,
                                     dev->ar->mbox_info.htc_addr,
@@ -1137,8 +1438,8 @@ static int ath6kl_htc_rx_alloc(struct htc_target *target,
                        }
 
                        endpoint->ep_st.rx_bundle_from_hdr += 1;
-                       ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-                                  "htc hdr indicates :%d msg can be fetched as a bundle\n",
+                       ath6kl_dbg(ATH6KL_DBG_HTC,
+                                  "htc rx bundle pkts %d\n",
                                   n_msg);
                } else
                        /* HTC header only indicates 1 message to fetch */
@@ -1191,8 +1492,8 @@ static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets)
                ath6kl_err("htc_ctrl_rx, got message with len:%zu\n",
                        packets->act_len + HTC_HDR_LENGTH);
 
-               ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES,
-                               "Unexpected ENDPOINT 0 Message", "",
+               ath6kl_dbg_dump(ATH6KL_DBG_HTC,
+                               "htc rx unexpected endpoint 0 message", "",
                                packets->buf - HTC_HDR_LENGTH,
                                packets->act_len + HTC_HDR_LENGTH);
        }
@@ -1209,9 +1510,6 @@ static void htc_proc_cred_rpt(struct htc_target *target,
        int tot_credits = 0, i;
        bool dist = false;
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                  "htc_proc_cred_rpt, credit report entries:%d\n", n_entries);
-
        spin_lock_bh(&target->tx_lock);
 
        for (i = 0; i < n_entries; i++, rpt++) {
@@ -1223,8 +1521,9 @@ static void htc_proc_cred_rpt(struct htc_target *target,
 
                endpoint = &target->endpoint[rpt->eid];
 
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND, " ep %d got %d credits\n",
-                       rpt->eid, rpt->credits);
+               ath6kl_dbg(ATH6KL_DBG_CREDIT,
+                          "credit report ep %d credits %d\n",
+                          rpt->eid, rpt->credits);
 
                endpoint->ep_st.tx_cred_rpt += 1;
                endpoint->ep_st.cred_retnd += rpt->credits;
@@ -1264,21 +1563,14 @@ static void htc_proc_cred_rpt(struct htc_target *target,
                tot_credits += rpt->credits;
        }
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
-                  "report indicated %d credits to distribute\n",
-                  tot_credits);
-
        if (dist) {
                /*
                 * This was a credit return based on a completed send
                 * operations note, this is done with the lock held
                 */
-               ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
-                          target->cred_dist_cntxt, &target->cred_dist_list);
-
-               ath6k_credit_distribute(target->cred_dist_cntxt,
-                                       &target->cred_dist_list,
-                                       HTC_CREDIT_DIST_SEND_COMPLETE);
+               ath6kl_credit_distribute(target->credit_info,
+                                        &target->cred_dist_list,
+                                        HTC_CREDIT_DIST_SEND_COMPLETE);
        }
 
        spin_unlock_bh(&target->tx_lock);
@@ -1320,14 +1612,15 @@ static int htc_parse_trailer(struct htc_target *target,
                if ((lk_ahd->pre_valid == ((~lk_ahd->post_valid) & 0xFF))
                    && next_lk_ahds) {
 
-                       ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-                                  "lk_ahd report found (pre valid:0x%X, post valid:0x%X)\n",
+                       ath6kl_dbg(ATH6KL_DBG_HTC,
+                                  "htc rx lk_ahd found pre_valid 0x%x post_valid 0x%x\n",
                                   lk_ahd->pre_valid, lk_ahd->post_valid);
 
                        /* look ahead bytes are valid, copy them over */
                        memcpy((u8 *)&next_lk_ahds[0], lk_ahd->lk_ahd, 4);
 
-                       ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Next Look Ahead",
+                       ath6kl_dbg_dump(ATH6KL_DBG_HTC,
+                                       "htc rx next look ahead",
                                        "", next_lk_ahds, 4);
 
                        *n_lk_ahds = 1;
@@ -1346,7 +1639,7 @@ static int htc_parse_trailer(struct htc_target *target,
                        bundle_lkahd_rpt =
                                (struct htc_bundle_lkahd_rpt *) record_buf;
 
-                       ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Bundle lk_ahd",
+                       ath6kl_dbg_dump(ATH6KL_DBG_HTC, "htc rx bundle lk_ahd",
                                        "", record_buf, record->len);
 
                        for (i = 0; i < len; i++) {
@@ -1378,10 +1671,8 @@ static int htc_proc_trailer(struct htc_target *target,
        u8 *record_buf;
        u8 *orig_buf;
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "+htc_proc_trailer (len:%d)\n", len);
-
-       ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Recv Trailer", "",
-                       buf, len);
+       ath6kl_dbg(ATH6KL_DBG_HTC, "htc rx trailer len %d\n", len);
+       ath6kl_dbg_dump(ATH6KL_DBG_HTC, NULL, "", buf, len);
 
        orig_buf = buf;
        orig_len = len;
@@ -1418,7 +1709,7 @@ static int htc_proc_trailer(struct htc_target *target,
        }
 
        if (status)
-               ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD Recv Trailer",
+               ath6kl_dbg_dump(ATH6KL_DBG_HTC, "htc rx bad trailer",
                                "", orig_buf, orig_len);
 
        return status;
@@ -1436,9 +1727,6 @@ static int ath6kl_htc_rx_process_hdr(struct htc_target *target,
        if (n_lkahds != NULL)
                *n_lkahds = 0;
 
-       ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "HTC Recv PKT", "htc ",
-                       packet->buf, packet->act_len);
-
        /*
         * NOTE: we cannot assume the alignment of buf, so we use the safe
         * macros to retrieve 16 bit fields.
@@ -1480,9 +1768,9 @@ static int ath6kl_htc_rx_process_hdr(struct htc_target *target,
        if (lk_ahd != packet->info.rx.exp_hdr) {
                ath6kl_err("%s(): lk_ahd mismatch! (pPkt:0x%p flags:0x%X)\n",
                           __func__, packet, packet->info.rx.rx_flags);
-               ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Expected Message lk_ahd",
+               ath6kl_dbg_dump(ATH6KL_DBG_HTC, "htc rx expected lk_ahd",
                                "", &packet->info.rx.exp_hdr, 4);
-               ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Current Frame Header",
+               ath6kl_dbg_dump(ATH6KL_DBG_HTC, "htc rx current header",
                                "", (u8 *)&lk_ahd, sizeof(lk_ahd));
                status = -ENOMEM;
                goto fail_rx;
@@ -1518,15 +1806,8 @@ static int ath6kl_htc_rx_process_hdr(struct htc_target *target,
 
 fail_rx:
        if (status)
-               ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD HTC Recv PKT",
-                               "", packet->buf,
-                               packet->act_len < 256 ? packet->act_len : 256);
-       else {
-               if (packet->act_len > 0)
-                       ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES,
-                                       "HTC - Application Msg", "",
-                                       packet->buf, packet->act_len);
-       }
+               ath6kl_dbg_dump(ATH6KL_DBG_HTC, "htc rx bad packet",
+                               "", packet->buf, packet->act_len);
 
        return status;
 }
@@ -1534,8 +1815,8 @@ fail_rx:
 static void ath6kl_htc_rx_complete(struct htc_endpoint *endpoint,
                                   struct htc_packet *packet)
 {
-               ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-                          "htc calling ep %d recv callback on packet 0x%p\n",
+               ath6kl_dbg(ATH6KL_DBG_HTC,
+                          "htc rx complete ep %d packet 0x%p\n",
                           endpoint->eid, packet);
                endpoint->ep_cb.rx(endpoint->target, packet);
 }
@@ -1571,9 +1852,9 @@ static int ath6kl_htc_rx_bundle(struct htc_target *target,
 
        len = 0;
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-                  "%s(): (numpackets: %d , actual : %d)\n",
-                  __func__, get_queue_depth(rxq), n_scat_pkt);
+       ath6kl_dbg(ATH6KL_DBG_HTC,
+                  "htc rx bundle depth %d pkts %d\n",
+                  get_queue_depth(rxq), n_scat_pkt);
 
        scat_req = hif_scatter_req_get(target->dev->ar);
 
@@ -1620,7 +1901,7 @@ static int ath6kl_htc_rx_bundle(struct htc_target *target,
        scat_req->len = len;
        scat_req->scat_entries = i;
 
-       status = ath6kldev_submit_scat_req(target->dev, scat_req, true);
+       status = ath6kl_hif_submit_scat_req(target->dev, scat_req, true);
 
        if (!status)
                *n_pkt_fetched = i;
@@ -1643,7 +1924,6 @@ static int ath6kl_htc_rx_process_packets(struct htc_target *target,
        int status = 0;
 
        list_for_each_entry_safe(packet, tmp_pkt, comp_pktq, list) {
-               list_del(&packet->list);
                ep = &target->endpoint[packet->endpoint];
 
                /* process header for each of the recv packet */
@@ -1652,6 +1932,8 @@ static int ath6kl_htc_rx_process_packets(struct htc_target *target,
                if (status)
                        return status;
 
+               list_del(&packet->list);
+
                if (list_empty(comp_pktq)) {
                        /*
                         * Last packet's more packet flag is set
@@ -1686,11 +1968,15 @@ static int ath6kl_htc_rx_fetch(struct htc_target *target,
        int fetched_pkts;
        bool part_bundle = false;
        int status = 0;
+       struct list_head tmp_rxq;
+       struct htc_packet *packet, *tmp_pkt;
 
        /* now go fetch the list of HTC packets */
        while (!list_empty(rx_pktq)) {
                fetched_pkts = 0;
 
+               INIT_LIST_HEAD(&tmp_rxq);
+
                if (target->rx_bndl_enable && (get_queue_depth(rx_pktq) > 1)) {
                        /*
                         * There are enough packets to attempt a
@@ -1698,28 +1984,27 @@ static int ath6kl_htc_rx_fetch(struct htc_target *target,
                         * allowed.
                         */
                        status = ath6kl_htc_rx_bundle(target, rx_pktq,
-                                                     comp_pktq,
+                                                     &tmp_rxq,
                                                      &fetched_pkts,
                                                      part_bundle);
                        if (status)
-                               return status;
+                               goto fail_rx;
 
                        if (!list_empty(rx_pktq))
                                part_bundle = true;
+
+                       list_splice_tail_init(&tmp_rxq, comp_pktq);
                }
 
                if (!fetched_pkts) {
-                       struct htc_packet *packet;
 
                        packet = list_first_entry(rx_pktq, struct htc_packet,
                                                   list);
 
-                       list_del(&packet->list);
-
                        /* fully synchronous */
                        packet->completion = NULL;
 
-                       if (!list_empty(rx_pktq))
+                       if (!list_is_singular(rx_pktq))
                                /*
                                 * look_aheads in all packet
                                 * except the last one in the
@@ -1731,18 +2016,42 @@ static int ath6kl_htc_rx_fetch(struct htc_target *target,
                        /* go fetch the packet */
                        status = ath6kl_htc_rx_packet(target, packet,
                                                      packet->act_len);
+
+                       list_move_tail(&packet->list, &tmp_rxq);
+
                        if (status)
-                               return status;
+                               goto fail_rx;
 
-                       list_add_tail(&packet->list, comp_pktq);
+                       list_splice_tail_init(&tmp_rxq, comp_pktq);
                }
        }
 
+       return 0;
+
+fail_rx:
+
+       /*
+        * Cleanup any packets we allocated but didn't use to
+        * actually fetch any packets.
+        */
+
+       list_for_each_entry_safe(packet, tmp_pkt, rx_pktq, list) {
+               list_del(&packet->list);
+               htc_reclaim_rxbuf(target, packet,
+                               &target->endpoint[packet->endpoint]);
+       }
+
+       list_for_each_entry_safe(packet, tmp_pkt, &tmp_rxq, list) {
+               list_del(&packet->list);
+               htc_reclaim_rxbuf(target, packet,
+                               &target->endpoint[packet->endpoint]);
+       }
+
        return status;
 }
 
 int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
-                                    u32 msg_look_ahead[], int *num_pkts)
+                                    u32 msg_look_ahead, int *num_pkts)
 {
        struct htc_packet *packets, *tmp_pkt;
        struct htc_endpoint *endpoint;
@@ -1759,7 +2068,7 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
         * On first entry copy the look_aheads into our temp array for
         * processing
         */
-       memcpy(look_aheads, msg_look_ahead, sizeof(look_aheads));
+       look_aheads[0] = msg_look_ahead;
 
        while (true) {
 
@@ -1827,15 +2136,6 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
        if (status) {
                ath6kl_err("failed to get pending recv messages: %d\n",
                           status);
-               /*
-                * Cleanup any packets we allocated but didn't use to
-                * actually fetch any packets.
-                */
-               list_for_each_entry_safe(packets, tmp_pkt, &rx_pktq, list) {
-                       list_del(&packets->list);
-                       htc_reclaim_rxbuf(target, packets,
-                                       &target->endpoint[packets->endpoint]);
-               }
 
                /* cleanup any packets in sync completion queue */
                list_for_each_entry_safe(packets, tmp_pkt, &comp_pktq, list) {
@@ -1846,7 +2146,7 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
 
                if (target->htc_flags & HTC_OP_STATE_STOPPING) {
                        ath6kl_warn("host is going to stop blocking receiver for htc_stop\n");
-                       ath6kldev_rx_control(target->dev, false);
+                       ath6kl_hif_rx_control(target->dev, false);
                }
        }
 
@@ -1856,7 +2156,7 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
         */
        if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) {
                ath6kl_warn("host has no rx buffers blocking receiver to prevent overrun\n");
-               ath6kldev_rx_control(target->dev, false);
+               ath6kl_hif_rx_control(target->dev, false);
        }
        *num_pkts = n_fetched;
 
@@ -1874,12 +2174,12 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
        struct htc_frame_hdr *htc_hdr;
        u32 look_ahead;
 
-       if (ath6kldev_poll_mboxmsg_rx(target->dev, &look_ahead,
+       if (ath6kl_hif_poll_mboxmsg_rx(target->dev, &look_ahead,
                               HTC_TARGET_RESPONSE_TIMEOUT))
                return NULL;
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-               "htc_wait_for_ctrl_msg: look_ahead : 0x%X\n", look_ahead);
+       ath6kl_dbg(ATH6KL_DBG_HTC,
+               "htc rx wait ctrl look_ahead 0x%X\n", look_ahead);
 
        htc_hdr = (struct htc_frame_hdr *)&look_ahead;
 
@@ -1943,8 +2243,8 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
 
        depth = get_queue_depth(pkt_queue);
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-               "htc_add_rxbuf_multiple: ep id: %d, cnt:%d, len: %d\n",
+       ath6kl_dbg(ATH6KL_DBG_HTC,
+               "htc rx add multiple ep id %d cnt %d len %d\n",
                first_pkt->endpoint, depth, first_pkt->buf_len);
 
        endpoint = &target->endpoint[first_pkt->endpoint];
@@ -1969,8 +2269,8 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
        /* check if we are blocked waiting for a new buffer */
        if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) {
                if (target->ep_waiting == first_pkt->endpoint) {
-                       ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-                               "receiver was blocked on ep:%d, unblocking.\n",
+                       ath6kl_dbg(ATH6KL_DBG_HTC,
+                               "htc rx blocked on ep %d, unblocking\n",
                                target->ep_waiting);
                        target->rx_st_flags &= ~HTC_RECV_WAIT_BUFFERS;
                        target->ep_waiting = ENDPOINT_MAX;
@@ -1982,7 +2282,7 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
 
        if (rx_unblock && !(target->htc_flags & HTC_OP_STATE_STOPPING))
                /* TODO : implement a buffer threshold count? */
-               ath6kldev_rx_control(target->dev, true);
+               ath6kl_hif_rx_control(target->dev, true);
 
        return status;
 }
@@ -2004,8 +2304,8 @@ void ath6kl_htc_flush_rx_buf(struct htc_target *target)
                                         &endpoint->rx_bufq, list) {
                        list_del(&packet->list);
                        spin_unlock_bh(&target->rx_lock);
-                       ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-                                  "flushing rx pkt:0x%p, len:%d, ep:%d\n",
+                       ath6kl_dbg(ATH6KL_DBG_HTC,
+                                  "htc rx flush pkt 0x%p  len %d  ep %d\n",
                                   packet, packet->buf_len,
                                   packet->endpoint);
                        dev_kfree_skb(packet->pkt_cntxt);
@@ -2028,8 +2328,8 @@ int ath6kl_htc_conn_service(struct htc_target *target,
        unsigned int max_msg_sz = 0;
        int status = 0;
 
-       ath6kl_dbg(ATH6KL_DBG_TRC,
-                  "htc_conn_service, target:0x%p service id:0x%X\n",
+       ath6kl_dbg(ATH6KL_DBG_HTC,
+                  "htc connect service target 0x%p service id 0x%x\n",
                   target, conn_req->svc_id);
 
        if (conn_req->svc_id == HTC_CTRL_RSVD_SVC) {
@@ -2115,7 +2415,7 @@ int ath6kl_htc_conn_service(struct htc_target *target,
        endpoint->len_max = max_msg_sz;
        endpoint->ep_cb = conn_req->ep_cb;
        endpoint->cred_dist.svc_id = conn_req->svc_id;
-       endpoint->cred_dist.htc_rsvd = endpoint;
+       endpoint->cred_dist.htc_ep = endpoint;
        endpoint->cred_dist.endpoint = assigned_ep;
        endpoint->cred_dist.cred_sz = target->tgt_cred_sz;
 
@@ -2172,6 +2472,7 @@ static void reset_ep_state(struct htc_target *target)
        }
 
        /* reset distribution list */
+       /* FIXME: free existing entries */
        INIT_LIST_HEAD(&target->cred_dist_list);
 }
 
@@ -2201,8 +2502,8 @@ static void htc_setup_msg_bndl(struct htc_target *target)
        target->msg_per_bndl_max = min(target->max_scat_entries,
                                       target->msg_per_bndl_max);
 
-       ath6kl_dbg(ATH6KL_DBG_TRC,
-                  "htc bundling allowed. max msg per htc bundle: %d\n",
+       ath6kl_dbg(ATH6KL_DBG_BOOT,
+                  "htc bundling allowed msg_per_bndl_max %d\n",
                   target->msg_per_bndl_max);
 
        /* Max rx bundle size is limited by the max tx bundle size */
@@ -2211,7 +2512,7 @@ static void htc_setup_msg_bndl(struct htc_target *target)
        target->max_tx_bndl_sz = min(HIF_MBOX0_EXT_WIDTH,
                                     target->max_xfer_szper_scatreq);
 
-       ath6kl_dbg(ATH6KL_DBG_ANY, "max recv: %d max send: %d\n",
+       ath6kl_dbg(ATH6KL_DBG_BOOT, "htc max_rx_bndl_sz %d max_tx_bndl_sz %d\n",
                   target->max_rx_bndl_sz, target->max_tx_bndl_sz);
 
        if (target->max_tx_bndl_sz)
@@ -2265,8 +2566,8 @@ int ath6kl_htc_wait_target(struct htc_target *target)
        target->tgt_creds = le16_to_cpu(rdy_msg->ver2_0_info.cred_cnt);
        target->tgt_cred_sz = le16_to_cpu(rdy_msg->ver2_0_info.cred_sz);
 
-       ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
-                  "target ready: credits: %d credit size: %d\n",
+       ath6kl_dbg(ATH6KL_DBG_BOOT,
+                  "htc target ready credits %d size %d\n",
                   target->tgt_creds, target->tgt_cred_sz);
 
        /* check if this is an extended ready message */
@@ -2280,7 +2581,7 @@ int ath6kl_htc_wait_target(struct htc_target *target)
                target->msg_per_bndl_max = 0;
        }
 
-       ath6kl_dbg(ATH6KL_DBG_TRC, "using htc protocol version : %s (%d)\n",
+       ath6kl_dbg(ATH6KL_DBG_BOOT, "htc using protocol %s (%d)\n",
                  (target->htc_tgt_ver == HTC_VERSION_2P0) ? "2.0" : ">= 2.1",
                  target->htc_tgt_ver);
 
@@ -2300,6 +2601,10 @@ int ath6kl_htc_wait_target(struct htc_target *target)
        status = ath6kl_htc_conn_service((void *)target, &connect, &resp);
 
        if (status)
+               /*
+                * FIXME: this call doesn't make sense, the caller should
+                * call ath6kl_htc_cleanup() when it wants remove htc
+                */
                ath6kl_hif_cleanup_scatter(target->dev->ar);
 
 fail_wait_target:
@@ -2320,8 +2625,11 @@ int ath6kl_htc_start(struct htc_target *target)
        struct htc_packet *packet;
        int status;
 
+       memset(&target->dev->irq_proc_reg, 0,
+              sizeof(target->dev->irq_proc_reg));
+
        /* Disable interrupts at the chip level */
-       ath6kldev_disable_intrs(target->dev);
+       ath6kl_hif_disable_intrs(target->dev);
 
        target->htc_flags = 0;
        target->rx_st_flags = 0;
@@ -2334,8 +2642,8 @@ int ath6kl_htc_start(struct htc_target *target)
        }
 
        /* NOTE: the first entry in the distribution list is ENDPOINT_0 */
-       ath6k_credit_init(target->cred_dist_cntxt, &target->cred_dist_list,
-                         target->tgt_creds);
+       ath6kl_credit_init(target->credit_info, &target->cred_dist_list,
+                          target->tgt_creds);
 
        dump_cred_dist_stats(target);
 
@@ -2346,7 +2654,7 @@ int ath6kl_htc_start(struct htc_target *target)
                return status;
 
        /* unmask interrupts */
-       status = ath6kldev_unmask_intrs(target->dev);
+       status = ath6kl_hif_unmask_intrs(target->dev);
 
        if (status)
                ath6kl_htc_stop(target);
@@ -2354,6 +2662,44 @@ int ath6kl_htc_start(struct htc_target *target)
        return status;
 }
 
+static int ath6kl_htc_reset(struct htc_target *target)
+{
+       u32 block_size, ctrl_bufsz;
+       struct htc_packet *packet;
+       int i;
+
+       reset_ep_state(target);
+
+       block_size = target->dev->ar->mbox_info.block_size;
+
+       ctrl_bufsz = (block_size > HTC_MAX_CTRL_MSG_LEN) ?
+                     (block_size + HTC_HDR_LENGTH) :
+                     (HTC_MAX_CTRL_MSG_LEN + HTC_HDR_LENGTH);
+
+       for (i = 0; i < NUM_CONTROL_BUFFERS; i++) {
+               packet = kzalloc(sizeof(*packet), GFP_KERNEL);
+               if (!packet)
+                       return -ENOMEM;
+
+               packet->buf_start = kzalloc(ctrl_bufsz, GFP_KERNEL);
+               if (!packet->buf_start) {
+                       kfree(packet);
+                       return -ENOMEM;
+               }
+
+               packet->buf_len = ctrl_bufsz;
+               if (i < NUM_CONTROL_RX_BUFFERS) {
+                       packet->act_len = 0;
+                       packet->buf = packet->buf_start;
+                       packet->endpoint = ENDPOINT_0;
+                       list_add_tail(&packet->list, &target->free_ctrl_rxbuf);
+               } else
+                       list_add_tail(&packet->list, &target->free_ctrl_txbuf);
+       }
+
+       return 0;
+}
+
 /* htc_stop: stop interrupt reception, and flush all queued buffers */
 void ath6kl_htc_stop(struct htc_target *target)
 {
@@ -2366,21 +2712,19 @@ void ath6kl_htc_stop(struct htc_target *target)
         * function returns all pending HIF I/O has completed, we can
         * safely flush the queues.
         */
-       ath6kldev_mask_intrs(target->dev);
+       ath6kl_hif_mask_intrs(target->dev);
 
        ath6kl_htc_flush_txep_all(target);
 
        ath6kl_htc_flush_rx_buf(target);
 
-       reset_ep_state(target);
+       ath6kl_htc_reset(target);
 }
 
 void *ath6kl_htc_create(struct ath6kl *ar)
 {
        struct htc_target *target = NULL;
-       struct htc_packet *packet;
-       int status = 0, i = 0;
-       u32 block_size, ctrl_bufsz;
+       int status = 0;
 
        target = kzalloc(sizeof(*target), GFP_KERNEL);
        if (!target) {
@@ -2392,7 +2736,7 @@ void *ath6kl_htc_create(struct ath6kl *ar)
        if (!target->dev) {
                ath6kl_err("unable to allocate memory\n");
                status = -ENOMEM;
-               goto fail_create_htc;
+               goto err_htc_cleanup;
        }
 
        spin_lock_init(&target->htc_lock);
@@ -2407,49 +2751,20 @@ void *ath6kl_htc_create(struct ath6kl *ar)
        target->dev->htc_cnxt = target;
        target->ep_waiting = ENDPOINT_MAX;
 
-       reset_ep_state(target);
-
-       status = ath6kldev_setup(target->dev);
-
+       status = ath6kl_hif_setup(target->dev);
        if (status)
-               goto fail_create_htc;
-
-       block_size = ar->mbox_info.block_size;
-
-       ctrl_bufsz = (block_size > HTC_MAX_CTRL_MSG_LEN) ?
-                     (block_size + HTC_HDR_LENGTH) :
-                     (HTC_MAX_CTRL_MSG_LEN + HTC_HDR_LENGTH);
-
-       for (i = 0; i < NUM_CONTROL_BUFFERS; i++) {
-               packet = kzalloc(sizeof(*packet), GFP_KERNEL);
-               if (!packet)
-                       break;
+               goto err_htc_cleanup;
 
-               packet->buf_start = kzalloc(ctrl_bufsz, GFP_KERNEL);
-               if (!packet->buf_start) {
-                       kfree(packet);
-                       break;
-               }
+       status = ath6kl_htc_reset(target);
+       if (status)
+               goto err_htc_cleanup;
 
-               packet->buf_len = ctrl_bufsz;
-               if (i < NUM_CONTROL_RX_BUFFERS) {
-                       packet->act_len = 0;
-                       packet->buf = packet->buf_start;
-                       packet->endpoint = ENDPOINT_0;
-                       list_add_tail(&packet->list, &target->free_ctrl_rxbuf);
-               } else
-                       list_add_tail(&packet->list, &target->free_ctrl_txbuf);
-       }
+       return target;
 
-fail_create_htc:
-       if (i != NUM_CONTROL_BUFFERS || status) {
-               if (target) {
-                       ath6kl_htc_cleanup(target);
-                       target = NULL;
-               }
-       }
+err_htc_cleanup:
+       ath6kl_htc_cleanup(target);
 
-       return target;
+       return NULL;
 }
 
 /* cleanup the HTC instance */
index 8ce0c2c07ded8b14398cddf9af42a2aff2b3e74b..57672e1ed1a68480fd18ee6cf174766007ef4dd8 100644 (file)
@@ -393,7 +393,7 @@ struct htc_endpoint_credit_dist {
        int cred_per_msg;
 
        /* reserved for HTC use */
-       void *htc_rsvd;
+       struct htc_endpoint *htc_ep;
 
        /*
         * current depth of TX queue , i.e. messages waiting for credits
@@ -414,9 +414,11 @@ enum htc_credit_dist_reason {
        HTC_CREDIT_DIST_SEEK_CREDITS,
 };
 
-struct htc_credit_state_info {
+struct ath6kl_htc_credit_info {
        int total_avail_credits;
        int cur_free_credits;
+
+       /* list of lowest priority endpoints */
        struct list_head lowestpri_ep_dist;
 };
 
@@ -508,10 +510,13 @@ struct ath6kl_device;
 /* our HTC target state */
 struct htc_target {
        struct htc_endpoint endpoint[ENDPOINT_MAX];
+
+       /* contains struct htc_endpoint_credit_dist */
        struct list_head cred_dist_list;
+
        struct list_head free_ctrl_txbuf;
        struct list_head free_ctrl_rxbuf;
-       struct htc_credit_state_info *cred_dist_cntxt;
+       struct ath6kl_htc_credit_info *credit_info;
        int tgt_creds;
        unsigned int tgt_cred_sz;
        spinlock_t htc_lock;
@@ -542,7 +547,7 @@ struct htc_target {
 
 void *ath6kl_htc_create(struct ath6kl *ar);
 void ath6kl_htc_set_credit_dist(struct htc_target *target,
-                               struct htc_credit_state_info *cred_info,
+                               struct ath6kl_htc_credit_info *cred_info,
                                u16 svc_pri_order[], int len);
 int ath6kl_htc_wait_target(struct htc_target *target);
 int ath6kl_htc_start(struct htc_target *target);
@@ -563,7 +568,10 @@ int ath6kl_htc_get_rxbuf_num(struct htc_target *target,
 int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
                                  struct list_head *pktq);
 int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
-                                    u32 msg_look_ahead[], int *n_pkts);
+                                    u32 msg_look_ahead, int *n_pkts);
+
+int ath6kl_credit_setup(void *htc_handle,
+                       struct ath6kl_htc_credit_info *cred_info);
 
 static inline void set_htc_pkt_info(struct htc_packet *packet, void *context,
                                    u8 *buf, unsigned int len,
diff --git a/drivers/net/wireless/ath/ath6kl/htc_hif.h b/drivers/net/wireless/ath/ath6kl/htc_hif.h
deleted file mode 100644 (file)
index 171ad63..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2007-2011 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef HTC_HIF_H
-#define HTC_HIF_H
-
-#include "htc.h"
-#include "hif.h"
-
-#define ATH6KL_MAILBOXES       4
-
-/* HTC runs over mailbox 0 */
-#define HTC_MAILBOX    0
-
-#define ATH6KL_TARGET_DEBUG_INTR_MASK     0x01
-
-#define OTHER_INTS_ENABLED             (INT_STATUS_ENABLE_ERROR_MASK | \
-                                       INT_STATUS_ENABLE_CPU_MASK   |  \
-                                       INT_STATUS_ENABLE_COUNTER_MASK)
-
-#define ATH6KL_REG_IO_BUFFER_SIZE                      32
-#define ATH6KL_MAX_REG_IO_BUFFERS                      8
-#define ATH6KL_SCATTER_ENTRIES_PER_REQ            16
-#define ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER      (16 * 1024)
-#define ATH6KL_SCATTER_REQS                       4
-
-#ifndef A_CACHE_LINE_PAD
-#define A_CACHE_LINE_PAD                        128
-#endif
-#define ATH6KL_MIN_SCATTER_ENTRIES_PER_REQ        2
-#define ATH6KL_MIN_TRANSFER_SIZE_PER_SCATTER      (4 * 1024)
-
-struct ath6kl_irq_proc_registers {
-       u8 host_int_status;
-       u8 cpu_int_status;
-       u8 error_int_status;
-       u8 counter_int_status;
-       u8 mbox_frame;
-       u8 rx_lkahd_valid;
-       u8 host_int_status2;
-       u8 gmbox_rx_avail;
-       __le32 rx_lkahd[2];
-       __le32 rx_gmbox_lkahd_alias[2];
-} __packed;
-
-struct ath6kl_irq_enable_reg {
-       u8 int_status_en;
-       u8 cpu_int_status_en;
-       u8 err_int_status_en;
-       u8 cntr_int_status_en;
-} __packed;
-
-struct ath6kl_device {
-       spinlock_t lock;
-       u8 pad1[A_CACHE_LINE_PAD];
-       struct ath6kl_irq_proc_registers irq_proc_reg;
-       u8 pad2[A_CACHE_LINE_PAD];
-       struct ath6kl_irq_enable_reg irq_en_reg;
-       u8 pad3[A_CACHE_LINE_PAD];
-       struct htc_target *htc_cnxt;
-       struct ath6kl *ar;
-};
-
-int ath6kldev_setup(struct ath6kl_device *dev);
-int ath6kldev_unmask_intrs(struct ath6kl_device *dev);
-int ath6kldev_mask_intrs(struct ath6kl_device *dev);
-int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev,
-                             u32 *lk_ahd, int timeout);
-int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx);
-int ath6kldev_disable_intrs(struct ath6kl_device *dev);
-
-int ath6kldev_rw_comp_handler(void *context, int status);
-int ath6kldev_intr_bh_handler(struct ath6kl *ar);
-
-/* Scatter Function and Definitions */
-int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
-                           struct hif_scatter_req *scat_req, bool read);
-
-#endif /*ATH6KL_H_ */
index 81e0031012caa0c7f8ef7033102abe2ec5348d75..30050af9d4c67a4bb1a774e040ea045d5e3c1d7f 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/moduleparam.h>
+#include <linux/errno.h>
 #include <linux/of.h>
 #include <linux/mmc/sdio_func.h>
 #include "core.h"
 
 unsigned int debug_mask;
 static unsigned int testmode;
+static bool suspend_cutpower;
 
 module_param(debug_mask, uint, 0644);
 module_param(testmode, uint, 0644);
+module_param(suspend_cutpower, bool, 0444);
 
 /*
  * Include definitions here that can be used to tune the WLAN module
@@ -73,37 +76,21 @@ struct sk_buff *ath6kl_buf_alloc(int size)
        return skb;
 }
 
-void ath6kl_init_profile_info(struct ath6kl *ar)
+void ath6kl_init_profile_info(struct ath6kl_vif *vif)
 {
-       ar->ssid_len = 0;
-       memset(ar->ssid, 0, sizeof(ar->ssid));
-
-       ar->dot11_auth_mode = OPEN_AUTH;
-       ar->auth_mode = NONE_AUTH;
-       ar->prwise_crypto = NONE_CRYPT;
-       ar->prwise_crypto_len = 0;
-       ar->grp_crypto = NONE_CRYPT;
-       ar->grp_crypto_len = 0;
-       memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
-       memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
-       memset(ar->bssid, 0, sizeof(ar->bssid));
-       ar->bss_ch = 0;
-       ar->nw_type = ar->next_mode = INFRA_NETWORK;
-}
-
-static u8 ath6kl_get_fw_iftype(struct ath6kl *ar)
-{
-       switch (ar->nw_type) {
-       case INFRA_NETWORK:
-               return HI_OPTION_FW_MODE_BSS_STA;
-       case ADHOC_NETWORK:
-               return HI_OPTION_FW_MODE_IBSS;
-       case AP_NETWORK:
-               return HI_OPTION_FW_MODE_AP;
-       default:
-               ath6kl_err("Unsupported interface type :%d\n", ar->nw_type);
-               return 0xff;
-       }
+       vif->ssid_len = 0;
+       memset(vif->ssid, 0, sizeof(vif->ssid));
+
+       vif->dot11_auth_mode = OPEN_AUTH;
+       vif->auth_mode = NONE_AUTH;
+       vif->prwise_crypto = NONE_CRYPT;
+       vif->prwise_crypto_len = 0;
+       vif->grp_crypto = NONE_CRYPT;
+       vif->grp_crypto_len = 0;
+       memset(vif->wep_key_list, 0, sizeof(vif->wep_key_list));
+       memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
+       memset(vif->bssid, 0, sizeof(vif->bssid));
+       vif->bss_ch = 0;
 }
 
 static int ath6kl_set_host_app_area(struct ath6kl *ar)
@@ -120,7 +107,7 @@ static int ath6kl_set_host_app_area(struct ath6kl *ar)
                return -EIO;
 
        address = TARG_VTOP(ar->target_type, data);
-       host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
+       host_app_area.wmi_protocol_ver = cpu_to_le32(WMI_PROTOCOL_VERSION);
        if (ath6kl_diag_write(ar, address, (u8 *) &host_app_area,
                              sizeof(struct host_app_area)))
                return -EIO;
@@ -258,40 +245,12 @@ static int ath6kl_init_service_ep(struct ath6kl *ar)
        return 0;
 }
 
-static void ath6kl_init_control_info(struct ath6kl *ar)
+void ath6kl_init_control_info(struct ath6kl_vif *vif)
 {
-       u8 ctr;
-
-       clear_bit(WMI_ENABLED, &ar->flag);
-       ath6kl_init_profile_info(ar);
-       ar->def_txkey_index = 0;
-       memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
-       ar->ch_hint = 0;
-       ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL;
-       ar->listen_intvl_b = 0;
-       ar->tx_pwr = 0;
-       clear_bit(SKIP_SCAN, &ar->flag);
-       set_bit(WMM_ENABLED, &ar->flag);
-       ar->intra_bss = 1;
-       memset(&ar->sc_params, 0, sizeof(ar->sc_params));
-       ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT;
-       ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS;
-       ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
-
-       memset((u8 *)ar->sta_list, 0,
-              AP_MAX_NUM_STA * sizeof(struct ath6kl_sta));
-
-       spin_lock_init(&ar->mcastpsq_lock);
-
-       /* Init the PS queues */
-       for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
-               spin_lock_init(&ar->sta_list[ctr].psq_lock);
-               skb_queue_head_init(&ar->sta_list[ctr].psq);
-       }
-
-       skb_queue_head_init(&ar->mcastpsq);
-
-       memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
+       ath6kl_init_profile_info(vif);
+       vif->def_txkey_index = 0;
+       memset(vif->wep_key_list, 0, sizeof(vif->wep_key_list));
+       vif->ch_hint = 0;
 }
 
 /*
@@ -341,62 +300,7 @@ out:
        return status;
 }
 
-#define REG_DUMP_COUNT_AR6003   60
-#define REGISTER_DUMP_LEN_MAX   60
-
-static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
-{
-       u32 address;
-       u32 regdump_loc = 0;
-       int status;
-       u32 regdump_val[REGISTER_DUMP_LEN_MAX];
-       u32 i;
-
-       if (ar->target_type != TARGET_TYPE_AR6003)
-               return;
-
-       /* the reg dump pointer is copied to the host interest area */
-       address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
-       address = TARG_VTOP(ar->target_type, address);
-
-       /* read RAM location through diagnostic window */
-       status = ath6kl_diag_read32(ar, address, &regdump_loc);
-
-       if (status || !regdump_loc) {
-               ath6kl_err("failed to get ptr to register dump area\n");
-               return;
-       }
-
-       ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n",
-               regdump_loc);
-       regdump_loc = TARG_VTOP(ar->target_type, regdump_loc);
-
-       /* fetch register dump data */
-       status = ath6kl_diag_read(ar, regdump_loc, (u8 *)&regdump_val[0],
-                                 REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
-
-       if (status) {
-               ath6kl_err("failed to get register dump\n");
-               return;
-       }
-       ath6kl_dbg(ATH6KL_DBG_TRC, "Register Dump:\n");
-
-       for (i = 0; i < REG_DUMP_COUNT_AR6003; i++)
-               ath6kl_dbg(ATH6KL_DBG_TRC, " %d :  0x%8.8X\n",
-                          i, regdump_val[i]);
-
-}
-
-void ath6kl_target_failure(struct ath6kl *ar)
-{
-       ath6kl_err("target asserted\n");
-
-       /* try dumping target assertion information (if any) */
-       ath6kl_dump_target_assert_info(ar);
-
-}
-
-static int ath6kl_target_config_wlan_params(struct ath6kl *ar)
+static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
 {
        int status = 0;
        int ret;
@@ -406,46 +310,50 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar)
         * default values. Required if checksum offload is needed. Set
         * RxMetaVersion to 2.
         */
-       if (ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi,
+       if (ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, idx,
                                               ar->rx_meta_ver, 0, 0)) {
                ath6kl_err("unable to set the rx frame format\n");
                status = -EIO;
        }
 
        if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN)
-               if ((ath6kl_wmi_pmparams_cmd(ar->wmi, 0, 1, 0, 0, 1,
+               if ((ath6kl_wmi_pmparams_cmd(ar->wmi, idx, 0, 1, 0, 0, 1,
                     IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) {
                        ath6kl_err("unable to set power save fail event policy\n");
                        status = -EIO;
                }
 
        if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER))
-               if ((ath6kl_wmi_set_lpreamble_cmd(ar->wmi, 0,
+               if ((ath6kl_wmi_set_lpreamble_cmd(ar->wmi, idx, 0,
                     WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) {
                        ath6kl_err("unable to set barker preamble policy\n");
                        status = -EIO;
                }
 
-       if (ath6kl_wmi_set_keepalive_cmd(ar->wmi,
+       if (ath6kl_wmi_set_keepalive_cmd(ar->wmi, idx,
                        WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) {
                ath6kl_err("unable to set keep alive interval\n");
                status = -EIO;
        }
 
-       if (ath6kl_wmi_disctimeout_cmd(ar->wmi,
+       if (ath6kl_wmi_disctimeout_cmd(ar->wmi, idx,
                        WLAN_CONFIG_DISCONNECT_TIMEOUT)) {
                ath6kl_err("unable to set disconnect timeout\n");
                status = -EIO;
        }
 
        if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST))
-               if (ath6kl_wmi_set_wmm_txop(ar->wmi, WMI_TXOP_DISABLED)) {
+               if (ath6kl_wmi_set_wmm_txop(ar->wmi, idx, WMI_TXOP_DISABLED)) {
                        ath6kl_err("unable to set txop bursting\n");
                        status = -EIO;
                }
 
+       /*
+        * FIXME: Make sure p2p configurations are not applied to
+        * non-p2p capable interfaces when multivif support is enabled.
+        */
        if (ar->p2p) {
-               ret = ath6kl_wmi_info_req_cmd(ar->wmi,
+               ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx,
                                              P2P_FLAG_CAPABILITIES_REQ |
                                              P2P_FLAG_MACADDR_REQ |
                                              P2P_FLAG_HMODEL_REQ);
@@ -457,9 +365,13 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar)
                }
        }
 
+       /*
+        * FIXME: Make sure p2p configurations are not applied to
+        * non-p2p capable interfaces when multivif support is enabled.
+        */
        if (ar->p2p) {
                /* Enable Probe Request reporting for P2P */
-               ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, true);
+               ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true);
                if (ret) {
                        ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe "
                                   "Request reporting (%d)\n", ret);
@@ -472,13 +384,44 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar)
 int ath6kl_configure_target(struct ath6kl *ar)
 {
        u32 param, ram_reserved_size;
-       u8 fw_iftype;
+       u8 fw_iftype, fw_mode = 0, fw_submode = 0;
+       int i;
 
-       fw_iftype = ath6kl_get_fw_iftype(ar);
-       if (fw_iftype == 0xff)
-               return -EINVAL;
+       /*
+        * Note: Even though the firmware interface type is
+        * chosen as BSS_STA for all three interfaces, can
+        * be configured to IBSS/AP as long as the fw submode
+        * remains normal mode (0 - AP, STA and IBSS). But
+        * due to an target assert in firmware only one interface is
+        * configured for now.
+        */
+       fw_iftype = HI_OPTION_FW_MODE_BSS_STA;
+
+       for (i = 0; i < MAX_NUM_VIF; i++)
+               fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS);
+
+       /*
+        * By default, submodes :
+        *              vif[0] - AP/STA/IBSS
+        *              vif[1] - "P2P dev"/"P2P GO"/"P2P Client"
+        *              vif[2] - "P2P dev"/"P2P GO"/"P2P Client"
+        */
+
+       for (i = 0; i < ar->max_norm_iface; i++)
+               fw_submode |= HI_OPTION_FW_SUBMODE_NONE <<
+                             (i * HI_OPTION_FW_SUBMODE_BITS);
+
+       for (i = ar->max_norm_iface; i < MAX_NUM_VIF; i++)
+               fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV <<
+                             (i * HI_OPTION_FW_SUBMODE_BITS);
+
+       /*
+        * FIXME: This needs to be removed once the multivif
+        * support is enabled.
+        */
+       if (ar->p2p)
+               fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV;
 
-       /* Tell target which HTC version it is used*/
        param = HTC_PROTOCOL_VERSION;
        if (ath6kl_bmi_write(ar,
                             ath6kl_get_hi_item_addr(ar,
@@ -499,12 +442,10 @@ int ath6kl_configure_target(struct ath6kl *ar)
                return -EIO;
        }
 
-       param |= (1 << HI_OPTION_NUM_DEV_SHIFT);
-       param |= (fw_iftype << HI_OPTION_FW_MODE_SHIFT);
-       if (ar->p2p && fw_iftype == HI_OPTION_FW_MODE_BSS_STA) {
-               param |= HI_OPTION_FW_SUBMODE_P2PDEV <<
-                       HI_OPTION_FW_SUBMODE_SHIFT;
-       }
+       param |= (MAX_NUM_VIF << HI_OPTION_NUM_DEV_SHIFT);
+       param |= fw_mode << HI_OPTION_FW_MODE_SHIFT;
+       param |= fw_submode << HI_OPTION_FW_SUBMODE_SHIFT;
+
        param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
        param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
 
@@ -553,68 +494,34 @@ int ath6kl_configure_target(struct ath6kl *ar)
        return 0;
 }
 
-struct ath6kl *ath6kl_core_alloc(struct device *sdev)
+void ath6kl_core_free(struct ath6kl *ar)
 {
-       struct net_device *dev;
-       struct ath6kl *ar;
-       struct wireless_dev *wdev;
-
-       wdev = ath6kl_cfg80211_init(sdev);
-       if (!wdev) {
-               ath6kl_err("ath6kl_cfg80211_init failed\n");
-               return NULL;
-       }
-
-       ar = wdev_priv(wdev);
-       ar->dev = sdev;
-       ar->wdev = wdev;
-       wdev->iftype = NL80211_IFTYPE_STATION;
-
-       if (ath6kl_debug_init(ar)) {
-               ath6kl_err("Failed to initialize debugfs\n");
-               ath6kl_cfg80211_deinit(ar);
-               return NULL;
-       }
-
-       dev = alloc_netdev(0, "wlan%d", ether_setup);
-       if (!dev) {
-               ath6kl_err("no memory for network device instance\n");
-               ath6kl_cfg80211_deinit(ar);
-               return NULL;
-       }
-
-       dev->ieee80211_ptr = wdev;
-       SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
-       wdev->netdev = dev;
-       ar->sme_state = SME_DISCONNECTED;
-
-       init_netdev(dev);
+       wiphy_free(ar->wiphy);
+}
 
-       ar->net_dev = dev;
-       set_bit(WLAN_ENABLED, &ar->flag);
+void ath6kl_core_cleanup(struct ath6kl *ar)
+{
+       ath6kl_hif_power_off(ar);
 
-       ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
+       destroy_workqueue(ar->ath6kl_wq);
 
-       spin_lock_init(&ar->lock);
+       if (ar->htc_target)
+               ath6kl_htc_cleanup(ar->htc_target);
 
-       ath6kl_init_control_info(ar);
-       init_waitqueue_head(&ar->event_wq);
-       sema_init(&ar->sem, 1);
-       clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
+       ath6kl_cookie_cleanup(ar);
 
-       INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);
+       ath6kl_cleanup_amsdu_rxbufs(ar);
 
-       setup_timer(&ar->disconnect_timer, disconnect_timer_handler,
-                   (unsigned long) dev);
+       ath6kl_bmi_cleanup(ar);
 
-       return ar;
-}
+       ath6kl_debug_cleanup(ar);
 
-int ath6kl_unavail_ev(struct ath6kl *ar)
-{
-       ath6kl_destroy(ar->net_dev, 1);
+       kfree(ar->fw_board);
+       kfree(ar->fw_otp);
+       kfree(ar->fw);
+       kfree(ar->fw_patch);
 
-       return 0;
+       ath6kl_deinit_ieee80211_hw(ar);
 }
 
 /* firmware upload */
@@ -1182,6 +1089,7 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
 static int ath6kl_upload_otp(struct ath6kl *ar)
 {
        u32 address, param;
+       bool from_hw = false;
        int ret;
 
        if (WARN_ON(ar->fw_otp == NULL))
@@ -1210,15 +1118,20 @@ static int ath6kl_upload_otp(struct ath6kl *ar)
                return ret;
        }
 
-       ar->hw.app_start_override_addr = address;
+       if (ar->hw.app_start_override_addr == 0) {
+               ar->hw.app_start_override_addr = address;
+               from_hw = true;
+       }
 
-       ath6kl_dbg(ATH6KL_DBG_BOOT, "app_start_override_addr 0x%x\n",
+       ath6kl_dbg(ATH6KL_DBG_BOOT, "app_start_override_addr%s 0x%x\n",
+                  from_hw ? " (from hw)" : "",
                   ar->hw.app_start_override_addr);
 
        /* execute the OTP code */
-       ath6kl_dbg(ATH6KL_DBG_BOOT, "executing OTP at 0x%x\n", address);
+       ath6kl_dbg(ATH6KL_DBG_BOOT, "executing OTP at 0x%x\n",
+                  ar->hw.app_start_override_addr);
        param = 0;
-       ath6kl_bmi_execute(ar, address, &param);
+       ath6kl_bmi_execute(ar, ar->hw.app_start_override_addr, &param);
 
        return ret;
 }
@@ -1420,6 +1333,10 @@ static int ath6kl_init_hw_params(struct ath6kl *ar)
                ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS;
                ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS;
                ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE;
+
+               /* hw2.0 needs override address hardcoded */
+               ar->hw.app_start_override_addr = 0x944C00;
+
                break;
        case AR6003_REV3_VERSION:
                ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS;
@@ -1451,71 +1368,56 @@ static int ath6kl_init_hw_params(struct ath6kl *ar)
        return 0;
 }
 
-static int ath6kl_init(struct net_device *dev)
+int ath6kl_init_hw_start(struct ath6kl *ar)
 {
-       struct ath6kl *ar = ath6kl_priv(dev);
-       int status = 0;
-       s32 timeleft;
+       long timeleft;
+       int ret, i;
 
-       if (!ar)
-               return -EIO;
+       ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n");
+
+       ret = ath6kl_hif_power_on(ar);
+       if (ret)
+               return ret;
+
+       ret = ath6kl_configure_target(ar);
+       if (ret)
+               goto err_power_off;
+
+       ret = ath6kl_init_upload(ar);
+       if (ret)
+               goto err_power_off;
 
        /* Do we need to finish the BMI phase */
+       /* FIXME: return error from ath6kl_bmi_done() */
        if (ath6kl_bmi_done(ar)) {
-               status = -EIO;
-               goto ath6kl_init_done;
+               ret = -EIO;
+               goto err_power_off;
        }
 
-       /* Indicate that WMI is enabled (although not ready yet) */
-       set_bit(WMI_ENABLED, &ar->flag);
-       ar->wmi = ath6kl_wmi_init(ar);
-       if (!ar->wmi) {
-               ath6kl_err("failed to initialize wmi\n");
-               status = -EIO;
-               goto ath6kl_init_done;
-       }
-
-       ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
-
        /*
         * The reason we have to wait for the target here is that the
         * driver layer has to init BMI in order to set the host block
         * size.
         */
        if (ath6kl_htc_wait_target(ar->htc_target)) {
-               status = -EIO;
-               goto err_node_cleanup;
+               ret = -EIO;
+               goto err_power_off;
        }
 
        if (ath6kl_init_service_ep(ar)) {
-               status = -EIO;
+               ret = -EIO;
                goto err_cleanup_scatter;
        }
 
-       /* setup access class priority mappings */
-       ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest  */
-       ar->ac_stream_pri_map[WMM_AC_BE] = 1;
-       ar->ac_stream_pri_map[WMM_AC_VI] = 2;
-       ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
-
-       /* give our connected endpoints some buffers */
-       ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
-       ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
-
-       /* allocate some buffers that handle larger AMSDU frames */
-       ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
-
        /* setup credit distribution */
-       ath6k_setup_credit_dist(ar->htc_target, &ar->credit_state_info);
-
-       ath6kl_cookie_init(ar);
+       ath6kl_credit_setup(ar->htc_target, &ar->credit_state_info);
 
        /* start HTC */
-       status = ath6kl_htc_start(ar->htc_target);
-
-       if (status) {
+       ret = ath6kl_htc_start(ar->htc_target);
+       if (ret) {
+               /* FIXME: call this */
                ath6kl_cookie_cleanup(ar);
-               goto err_rxbuf_cleanup;
+               goto err_cleanup_scatter;
        }
 
        /* Wait for Wmi event to be ready */
@@ -1529,52 +1431,69 @@ static int ath6kl_init(struct net_device *dev)
        if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
                ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
                           ATH6KL_ABI_VERSION, ar->version.abi_ver);
-               status = -EIO;
+               ret = -EIO;
                goto err_htc_stop;
        }
 
        if (!timeleft || signal_pending(current)) {
                ath6kl_err("wmi is not ready or wait was interrupted\n");
-               status = -EIO;
+               ret = -EIO;
                goto err_htc_stop;
        }
 
        ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__);
 
        /* communicate the wmi protocol verision to the target */
+       /* FIXME: return error */
        if ((ath6kl_set_host_app_area(ar)) != 0)
                ath6kl_err("unable to set the host app area\n");
 
-       ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
-                        ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
+       for (i = 0; i < MAX_NUM_VIF; i++) {
+               ret = ath6kl_target_config_wlan_params(ar, i);
+               if (ret)
+                       goto err_htc_stop;
+       }
 
-       ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
-                                 WIPHY_FLAG_HAVE_AP_SME;
+       ar->state = ATH6KL_STATE_ON;
 
-       status = ath6kl_target_config_wlan_params(ar);
-       if (!status)
-               goto ath6kl_init_done;
+       return 0;
 
 err_htc_stop:
        ath6kl_htc_stop(ar->htc_target);
-err_rxbuf_cleanup:
-       ath6kl_htc_flush_rx_buf(ar->htc_target);
-       ath6kl_cleanup_amsdu_rxbufs(ar);
 err_cleanup_scatter:
        ath6kl_hif_cleanup_scatter(ar);
-err_node_cleanup:
-       ath6kl_wmi_shutdown(ar->wmi);
-       clear_bit(WMI_ENABLED, &ar->flag);
-       ar->wmi = NULL;
+err_power_off:
+       ath6kl_hif_power_off(ar);
 
-ath6kl_init_done:
-       return status;
+       return ret;
+}
+
+int ath6kl_init_hw_stop(struct ath6kl *ar)
+{
+       int ret;
+
+       ath6kl_dbg(ATH6KL_DBG_BOOT, "hw stop\n");
+
+       ath6kl_htc_stop(ar->htc_target);
+
+       ath6kl_hif_stop(ar);
+
+       ath6kl_bmi_reset(ar);
+
+       ret = ath6kl_hif_power_off(ar);
+       if (ret)
+               ath6kl_warn("failed to power off hif: %d\n", ret);
+
+       ar->state = ATH6KL_STATE_OFF;
+
+       return 0;
 }
 
 int ath6kl_core_init(struct ath6kl *ar)
 {
-       int ret = 0;
        struct ath6kl_bmi_target_info targ_info;
+       struct net_device *ndev;
+       int ret = 0, i;
 
        ar->ath6kl_wq = create_singlethread_workqueue("ath6kl");
        if (!ar->ath6kl_wq)
@@ -1584,145 +1503,226 @@ int ath6kl_core_init(struct ath6kl *ar)
        if (ret)
                goto err_wq;
 
-       ret = ath6kl_bmi_get_target_info(ar, &targ_info);
+       /*
+        * Turn on power to get hardware (target) version and leave power
+        * on delibrately as we will boot the hardware anyway within few
+        * seconds.
+        */
+       ret = ath6kl_hif_power_on(ar);
        if (ret)
                goto err_bmi_cleanup;
 
+       ret = ath6kl_bmi_get_target_info(ar, &targ_info);
+       if (ret)
+               goto err_power_off;
+
        ar->version.target_ver = le32_to_cpu(targ_info.version);
        ar->target_type = le32_to_cpu(targ_info.type);
-       ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version);
+       ar->wiphy->hw_version = le32_to_cpu(targ_info.version);
 
        ret = ath6kl_init_hw_params(ar);
        if (ret)
-               goto err_bmi_cleanup;
-
-       ret = ath6kl_configure_target(ar);
-       if (ret)
-               goto err_bmi_cleanup;
+               goto err_power_off;
 
        ar->htc_target = ath6kl_htc_create(ar);
 
        if (!ar->htc_target) {
                ret = -ENOMEM;
-               goto err_bmi_cleanup;
-       }
-
-       ar->aggr_cntxt = aggr_init(ar->net_dev);
-       if (!ar->aggr_cntxt) {
-               ath6kl_err("failed to initialize aggr\n");
-               ret = -ENOMEM;
-               goto err_htc_cleanup;
+               goto err_power_off;
        }
 
        ret = ath6kl_fetch_firmwares(ar);
        if (ret)
                goto err_htc_cleanup;
 
-       ret = ath6kl_init_upload(ar);
-       if (ret)
+       /* FIXME: we should free all firmwares in the error cases below */
+
+       /* Indicate that WMI is enabled (although not ready yet) */
+       set_bit(WMI_ENABLED, &ar->flag);
+       ar->wmi = ath6kl_wmi_init(ar);
+       if (!ar->wmi) {
+               ath6kl_err("failed to initialize wmi\n");
+               ret = -EIO;
                goto err_htc_cleanup;
+       }
 
-       ret = ath6kl_init(ar->net_dev);
+       ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
+
+       ret = ath6kl_register_ieee80211_hw(ar);
        if (ret)
-               goto err_htc_cleanup;
+               goto err_node_cleanup;
 
-       /* This runs the init function if registered */
-       ret = register_netdev(ar->net_dev);
+       ret = ath6kl_debug_init(ar);
        if (ret) {
-               ath6kl_err("register_netdev failed\n");
-               ath6kl_destroy(ar->net_dev, 0);
-               return ret;
+               wiphy_unregister(ar->wiphy);
+               goto err_node_cleanup;
+       }
+
+       for (i = 0; i < MAX_NUM_VIF; i++)
+               ar->avail_idx_map |= BIT(i);
+
+       rtnl_lock();
+
+       /* Add an initial station interface */
+       ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
+                                   INFRA_NETWORK);
+
+       rtnl_unlock();
+
+       if (!ndev) {
+               ath6kl_err("Failed to instantiate a network device\n");
+               ret = -ENOMEM;
+               wiphy_unregister(ar->wiphy);
+               goto err_debug_init;
        }
 
-       set_bit(NETDEV_REGISTERED, &ar->flag);
 
        ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
-                       __func__, ar->net_dev->name, ar->net_dev, ar);
+                       __func__, ndev->name, ndev, ar);
+
+       /* setup access class priority mappings */
+       ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest  */
+       ar->ac_stream_pri_map[WMM_AC_BE] = 1;
+       ar->ac_stream_pri_map[WMM_AC_VI] = 2;
+       ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
+
+       /* give our connected endpoints some buffers */
+       ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
+       ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
+
+       /* allocate some buffers that handle larger AMSDU frames */
+       ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
+
+       ath6kl_cookie_init(ar);
+
+       ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
+                        ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
+
+       if (suspend_cutpower)
+               ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER;
+
+       ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
+                           WIPHY_FLAG_HAVE_AP_SME |
+                           WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+
+       set_bit(FIRST_BOOT, &ar->flag);
+
+       ret = ath6kl_init_hw_start(ar);
+       if (ret) {
+               ath6kl_err("Failed to start hardware: %d\n", ret);
+               goto err_rxbuf_cleanup;
+       }
+
+       /*
+        * Set mac address which is received in ready event
+        * FIXME: Move to ath6kl_interface_add()
+        */
+       memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
 
        return ret;
 
+err_rxbuf_cleanup:
+       ath6kl_htc_flush_rx_buf(ar->htc_target);
+       ath6kl_cleanup_amsdu_rxbufs(ar);
+       rtnl_lock();
+       ath6kl_deinit_if_data(netdev_priv(ndev));
+       rtnl_unlock();
+       wiphy_unregister(ar->wiphy);
+err_debug_init:
+       ath6kl_debug_cleanup(ar);
+err_node_cleanup:
+       ath6kl_wmi_shutdown(ar->wmi);
+       clear_bit(WMI_ENABLED, &ar->flag);
+       ar->wmi = NULL;
 err_htc_cleanup:
        ath6kl_htc_cleanup(ar->htc_target);
+err_power_off:
+       ath6kl_hif_power_off(ar);
 err_bmi_cleanup:
        ath6kl_bmi_cleanup(ar);
 err_wq:
        destroy_workqueue(ar->ath6kl_wq);
+
        return ret;
 }
 
-void ath6kl_stop_txrx(struct ath6kl *ar)
+void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
 {
-       struct net_device *ndev = ar->net_dev;
+       static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+       bool discon_issued;
 
-       if (!ndev)
-               return;
+       netif_stop_queue(vif->ndev);
 
-       set_bit(DESTROY_IN_PROGRESS, &ar->flag);
+       clear_bit(WLAN_ENABLED, &vif->flags);
 
-       if (down_interruptible(&ar->sem)) {
-               ath6kl_err("down_interruptible failed\n");
-               return;
-       }
+       if (wmi_ready) {
+               discon_issued = test_bit(CONNECTED, &vif->flags) ||
+                               test_bit(CONNECT_PEND, &vif->flags);
+               ath6kl_disconnect(vif);
+               del_timer(&vif->disconnect_timer);
 
-       if (ar->wlan_pwr_state != WLAN_POWER_STATE_CUT_PWR)
-               ath6kl_stop_endpoint(ndev, false, true);
+               if (discon_issued)
+                       ath6kl_disconnect_event(vif, DISCONNECT_CMD,
+                                               (vif->nw_type & AP_NETWORK) ?
+                                               bcast_mac : vif->bssid,
+                                               0, NULL, 0);
+       }
 
-       clear_bit(WLAN_ENABLED, &ar->flag);
+       if (vif->scan_req) {
+               cfg80211_scan_done(vif->scan_req, true);
+               vif->scan_req = NULL;
+       }
 }
 
-/*
- * We need to differentiate between the surprise and planned removal of the
- * device because of the following consideration:
- *
- * - In case of surprise removal, the hcd already frees up the pending
- *   for the device and hence there is no need to unregister the function
- *   driver inorder to get these requests. For planned removal, the function
- *   driver has to explicitly unregister itself to have the hcd return all the
- *   pending requests before the data structures for the devices are freed up.
- *   Note that as per the current implementation, the function driver will
- *   end up releasing all the devices since there is no API to selectively
- *   release a particular device.
- *
- * - Certain commands issued to the target can be skipped for surprise
- *   removal since they will anyway not go through.
- */
-void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
+void ath6kl_stop_txrx(struct ath6kl *ar)
 {
-       struct ath6kl *ar;
+       struct ath6kl_vif *vif, *tmp_vif;
 
-       if (!dev || !ath6kl_priv(dev)) {
-               ath6kl_err("failed to get device structure\n");
+       set_bit(DESTROY_IN_PROGRESS, &ar->flag);
+
+       if (down_interruptible(&ar->sem)) {
+               ath6kl_err("down_interruptible failed\n");
                return;
        }
 
-       ar = ath6kl_priv(dev);
-
-       destroy_workqueue(ar->ath6kl_wq);
-
-       if (ar->htc_target)
-               ath6kl_htc_cleanup(ar->htc_target);
-
-       aggr_module_destroy(ar->aggr_cntxt);
-
-       ath6kl_cookie_cleanup(ar);
-
-       ath6kl_cleanup_amsdu_rxbufs(ar);
+       spin_lock_bh(&ar->list_lock);
+       list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) {
+               list_del(&vif->list);
+               spin_unlock_bh(&ar->list_lock);
+               ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
+               rtnl_lock();
+               ath6kl_deinit_if_data(vif);
+               rtnl_unlock();
+               spin_lock_bh(&ar->list_lock);
+       }
+       spin_unlock_bh(&ar->list_lock);
 
-       ath6kl_bmi_cleanup(ar);
+       clear_bit(WMI_READY, &ar->flag);
 
-       ath6kl_debug_cleanup(ar);
+       /*
+        * After wmi_shudown all WMI events will be dropped. We
+        * need to cleanup the buffers allocated in AP mode and
+        * give disconnect notification to stack, which usually
+        * happens in the disconnect_event. Simulate the disconnect
+        * event by calling the function directly. Sometimes
+        * disconnect_event will be received when the debug logs
+        * are collected.
+        */
+       ath6kl_wmi_shutdown(ar->wmi);
 
-       if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) {
-               unregister_netdev(dev);
-               clear_bit(NETDEV_REGISTERED, &ar->flag);
+       clear_bit(WMI_ENABLED, &ar->flag);
+       if (ar->htc_target) {
+               ath6kl_dbg(ATH6KL_DBG_TRC, "%s: shut down htc\n", __func__);
+               ath6kl_htc_stop(ar->htc_target);
        }
 
-       free_netdev(dev);
-
-       kfree(ar->fw_board);
-       kfree(ar->fw_otp);
-       kfree(ar->fw);
-       kfree(ar->fw_patch);
+       /*
+        * Try to reset the device if we can. The driver may have been
+        * configure NOT to reset the target during a debug session.
+        */
+       ath6kl_dbg(ATH6KL_DBG_TRC,
+                       "attempting to reset target on instance destroy\n");
+       ath6kl_reset_device(ar, ar->target_type, true, true);
 
-       ath6kl_cfg80211_deinit(ar);
+       clear_bit(WLAN_ENABLED, &ar->flag);
 }
index 30b5a53db9ed061dd6ba60a790a7ccde0ba8fc23..5e5f4ca8f3f079488391bf902897991e3ba3e03d 100644 (file)
 #include "target.h"
 #include "debug.h"
 
-struct ath6kl_sta *ath6kl_find_sta(struct ath6kl *ar, u8 *node_addr)
+struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 *node_addr)
 {
+       struct ath6kl *ar = vif->ar;
        struct ath6kl_sta *conn = NULL;
        u8 i, max_conn;
 
-       max_conn = (ar->nw_type == AP_NETWORK) ? AP_MAX_NUM_STA : 0;
+       max_conn = (vif->nw_type == AP_NETWORK) ? AP_MAX_NUM_STA : 0;
 
        for (i = 0; i < max_conn; i++) {
                if (memcmp(node_addr, ar->sta_list[i].mac, ETH_ALEN) == 0) {
@@ -393,8 +394,8 @@ out:
 #define AR6003_RESET_CONTROL_ADDRESS 0x00004000
 #define AR6004_RESET_CONTROL_ADDRESS 0x00004000
 
-static void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
-                               bool wait_fot_compltn, bool cold_reset)
+void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
+                        bool wait_fot_compltn, bool cold_reset)
 {
        int status = 0;
        u32 address;
@@ -425,102 +426,33 @@ static void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
                ath6kl_err("failed to reset target\n");
 }
 
-void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile,
-                         bool get_dbglogs)
-{
-       struct ath6kl *ar = ath6kl_priv(dev);
-       static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-       bool discon_issued;
-
-       netif_stop_queue(dev);
-
-       /* disable the target and the interrupts associated with it */
-       if (test_bit(WMI_READY, &ar->flag)) {
-               discon_issued = (test_bit(CONNECTED, &ar->flag) ||
-                                test_bit(CONNECT_PEND, &ar->flag));
-               ath6kl_disconnect(ar);
-               if (!keep_profile)
-                       ath6kl_init_profile_info(ar);
-
-               del_timer(&ar->disconnect_timer);
-
-               clear_bit(WMI_READY, &ar->flag);
-               ath6kl_wmi_shutdown(ar->wmi);
-               clear_bit(WMI_ENABLED, &ar->flag);
-               ar->wmi = NULL;
-
-               /*
-                * After wmi_shudown all WMI events will be dropped. We
-                * need to cleanup the buffers allocated in AP mode and
-                * give disconnect notification to stack, which usually
-                * happens in the disconnect_event. Simulate the disconnect
-                * event by calling the function directly. Sometimes
-                * disconnect_event will be received when the debug logs
-                * are collected.
-                */
-               if (discon_issued)
-                       ath6kl_disconnect_event(ar, DISCONNECT_CMD,
-                                               (ar->nw_type & AP_NETWORK) ?
-                                               bcast_mac : ar->bssid,
-                                               0, NULL, 0);
-
-               ar->user_key_ctrl = 0;
-
-       } else {
-               ath6kl_dbg(ATH6KL_DBG_TRC,
-                          "%s: wmi is not ready 0x%p 0x%p\n",
-                          __func__, ar, ar->wmi);
-
-               /* Shut down WMI if we have started it */
-               if (test_bit(WMI_ENABLED, &ar->flag)) {
-                       ath6kl_dbg(ATH6KL_DBG_TRC,
-                                  "%s: shut down wmi\n", __func__);
-                       ath6kl_wmi_shutdown(ar->wmi);
-                       clear_bit(WMI_ENABLED, &ar->flag);
-                       ar->wmi = NULL;
-               }
-       }
-
-       if (ar->htc_target) {
-               ath6kl_dbg(ATH6KL_DBG_TRC, "%s: shut down htc\n", __func__);
-               ath6kl_htc_stop(ar->htc_target);
-       }
-
-       /*
-        * Try to reset the device if we can. The driver may have been
-        * configure NOT to reset the target during a debug session.
-        */
-       ath6kl_dbg(ATH6KL_DBG_TRC,
-                  "attempting to reset target on instance destroy\n");
-       ath6kl_reset_device(ar, ar->target_type, true, true);
-}
-
-static void ath6kl_install_static_wep_keys(struct ath6kl *ar)
+static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif)
 {
        u8 index;
        u8 keyusage;
 
        for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
-               if (ar->wep_key_list[index].key_len) {
+               if (vif->wep_key_list[index].key_len) {
                        keyusage = GROUP_USAGE;
-                       if (index == ar->def_txkey_index)
+                       if (index == vif->def_txkey_index)
                                keyusage |= TX_USAGE;
 
-                       ath6kl_wmi_addkey_cmd(ar->wmi,
+                       ath6kl_wmi_addkey_cmd(vif->ar->wmi, vif->fw_vif_idx,
                                              index,
                                              WEP_CRYPT,
                                              keyusage,
-                                             ar->wep_key_list[index].key_len,
-                                             NULL,
-                                             ar->wep_key_list[index].key,
+                                             vif->wep_key_list[index].key_len,
+                                             NULL, 0,
+                                             vif->wep_key_list[index].key,
                                              KEY_OP_INIT_VAL, NULL,
                                              NO_SYNC_WMIFLAG);
                }
        }
 }
 
-void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel)
+void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
 {
+       struct ath6kl *ar = vif->ar;
        struct ath6kl_req_key *ik;
        int res;
        u8 key_rsc[ATH6KL_KEY_SEQ_LEN];
@@ -529,10 +461,10 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel)
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", channel);
 
-       switch (ar->auth_mode) {
+       switch (vif->auth_mode) {
        case NONE_AUTH:
-               if (ar->prwise_crypto == WEP_CRYPT)
-                       ath6kl_install_static_wep_keys(ar);
+               if (vif->prwise_crypto == WEP_CRYPT)
+                       ath6kl_install_static_wep_keys(vif);
                break;
        case WPA_PSK_AUTH:
        case WPA2_PSK_AUTH:
@@ -544,8 +476,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel)
                           "the initial group key for AP mode\n");
                memset(key_rsc, 0, sizeof(key_rsc));
                res = ath6kl_wmi_addkey_cmd(
-                       ar->wmi, ik->key_index, ik->key_type,
-                       GROUP_USAGE, ik->key_len, key_rsc, ik->key,
+                       ar->wmi, vif->fw_vif_idx, ik->key_index, ik->key_type,
+                       GROUP_USAGE, ik->key_len, key_rsc, ATH6KL_KEY_SEQ_LEN,
+                       ik->key,
                        KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);
                if (res) {
                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed "
@@ -554,15 +487,16 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel)
                break;
        }
 
-       ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
-       set_bit(CONNECTED, &ar->flag);
-       netif_carrier_on(ar->net_dev);
+       ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0);
+       set_bit(CONNECTED, &vif->flags);
+       netif_carrier_on(vif->ndev);
 }
 
-void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
+void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
                                u8 keymgmt, u8 ucipher, u8 auth,
                                u8 assoc_req_len, u8 *assoc_info)
 {
+       struct ath6kl *ar = vif->ar;
        u8 *ies = NULL, *wpa_ie = NULL, *pos;
        size_t ies_len = 0;
        struct station_info sinfo;
@@ -617,348 +551,32 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
        sinfo.assoc_req_ies_len = ies_len;
        sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
 
-       cfg80211_new_sta(ar->net_dev, mac_addr, &sinfo, GFP_KERNEL);
+       cfg80211_new_sta(vif->ndev, mac_addr, &sinfo, GFP_KERNEL);
 
-       netif_wake_queue(ar->net_dev);
-}
-
-/* Functions for Tx credit handling */
-void ath6k_credit_init(struct htc_credit_state_info *cred_info,
-                      struct list_head *ep_list,
-                      int tot_credits)
-{
-       struct htc_endpoint_credit_dist *cur_ep_dist;
-       int count;
-
-       cred_info->cur_free_credits = tot_credits;
-       cred_info->total_avail_credits = tot_credits;
-
-       list_for_each_entry(cur_ep_dist, ep_list, list) {
-               if (cur_ep_dist->endpoint == ENDPOINT_0)
-                       continue;
-
-               cur_ep_dist->cred_min = cur_ep_dist->cred_per_msg;
-
-               if (tot_credits > 4)
-                       if ((cur_ep_dist->svc_id == WMI_DATA_BK_SVC) ||
-                           (cur_ep_dist->svc_id == WMI_DATA_BE_SVC)) {
-                               ath6kl_deposit_credit_to_ep(cred_info,
-                                               cur_ep_dist,
-                                               cur_ep_dist->cred_min);
-                               cur_ep_dist->dist_flags |= HTC_EP_ACTIVE;
-                       }
-
-               if (cur_ep_dist->svc_id == WMI_CONTROL_SVC) {
-                       ath6kl_deposit_credit_to_ep(cred_info, cur_ep_dist,
-                                                   cur_ep_dist->cred_min);
-                       /*
-                        * Control service is always marked active, it
-                        * never goes inactive EVER.
-                        */
-                       cur_ep_dist->dist_flags |= HTC_EP_ACTIVE;
-               } else if (cur_ep_dist->svc_id == WMI_DATA_BK_SVC)
-                       /* this is the lowest priority data endpoint */
-                       cred_info->lowestpri_ep_dist = cur_ep_dist->list;
-
-               /*
-                * Streams have to be created (explicit | implicit) for all
-                * kinds of traffic. BE endpoints are also inactive in the
-                * beginning. When BE traffic starts it creates implicit
-                * streams that redistributes credits.
-                *
-                * Note: all other endpoints have minimums set but are
-                * initially given NO credits. credits will be distributed
-                * as traffic activity demands
-                */
-       }
-
-       WARN_ON(cred_info->cur_free_credits <= 0);
-
-       list_for_each_entry(cur_ep_dist, ep_list, list) {
-               if (cur_ep_dist->endpoint == ENDPOINT_0)
-                       continue;
-
-               if (cur_ep_dist->svc_id == WMI_CONTROL_SVC)
-                       cur_ep_dist->cred_norm = cur_ep_dist->cred_per_msg;
-               else {
-                       /*
-                        * For the remaining data endpoints, we assume that
-                        * each cred_per_msg are the same. We use a simple
-                        * calculation here, we take the remaining credits
-                        * and determine how many max messages this can
-                        * cover and then set each endpoint's normal value
-                        * equal to 3/4 this amount.
-                        */
-                       count = (cred_info->cur_free_credits /
-                                cur_ep_dist->cred_per_msg)
-                               * cur_ep_dist->cred_per_msg;
-                       count = (count * 3) >> 2;
-                       count = max(count, cur_ep_dist->cred_per_msg);
-                       cur_ep_dist->cred_norm = count;
-
-               }
-       }
-}
-
-/* initialize and setup credit distribution */
-int ath6k_setup_credit_dist(void *htc_handle,
-                           struct htc_credit_state_info *cred_info)
-{
-       u16 servicepriority[5];
-
-       memset(cred_info, 0, sizeof(struct htc_credit_state_info));
-
-       servicepriority[0] = WMI_CONTROL_SVC;  /* highest */
-       servicepriority[1] = WMI_DATA_VO_SVC;
-       servicepriority[2] = WMI_DATA_VI_SVC;
-       servicepriority[3] = WMI_DATA_BE_SVC;
-       servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */
-
-       /* set priority list */
-       ath6kl_htc_set_credit_dist(htc_handle, cred_info, servicepriority, 5);
-
-       return 0;
-}
-
-/* reduce an ep's credits back to a set limit */
-static void ath6k_reduce_credits(struct htc_credit_state_info *cred_info,
-                                struct htc_endpoint_credit_dist  *ep_dist,
-                                int limit)
-{
-       int credits;
-
-       ep_dist->cred_assngd = limit;
-
-       if (ep_dist->credits <= limit)
-               return;
-
-       credits = ep_dist->credits - limit;
-       ep_dist->credits -= credits;
-       cred_info->cur_free_credits += credits;
-}
-
-static void ath6k_credit_update(struct htc_credit_state_info *cred_info,
-                               struct list_head *epdist_list)
-{
-       struct htc_endpoint_credit_dist *cur_dist_list;
-
-       list_for_each_entry(cur_dist_list, epdist_list, list) {
-               if (cur_dist_list->endpoint == ENDPOINT_0)
-                       continue;
-
-               if (cur_dist_list->cred_to_dist > 0) {
-                       cur_dist_list->credits +=
-                                       cur_dist_list->cred_to_dist;
-                       cur_dist_list->cred_to_dist = 0;
-                       if (cur_dist_list->credits >
-                           cur_dist_list->cred_assngd)
-                               ath6k_reduce_credits(cred_info,
-                                               cur_dist_list,
-                                               cur_dist_list->cred_assngd);
-
-                       if (cur_dist_list->credits >
-                           cur_dist_list->cred_norm)
-                               ath6k_reduce_credits(cred_info, cur_dist_list,
-                                                    cur_dist_list->cred_norm);
-
-                       if (!(cur_dist_list->dist_flags & HTC_EP_ACTIVE)) {
-                               if (cur_dist_list->txq_depth == 0)
-                                       ath6k_reduce_credits(cred_info,
-                                                            cur_dist_list, 0);
-                       }
-               }
-       }
-}
-
-/*
- * HTC has an endpoint that needs credits, ep_dist is the endpoint in
- * question.
- */
-void ath6k_seek_credits(struct htc_credit_state_info *cred_info,
-                       struct htc_endpoint_credit_dist *ep_dist)
-{
-       struct htc_endpoint_credit_dist *curdist_list;
-       int credits = 0;
-       int need;
-
-       if (ep_dist->svc_id == WMI_CONTROL_SVC)
-               goto out;
-
-       if ((ep_dist->svc_id == WMI_DATA_VI_SVC) ||
-           (ep_dist->svc_id == WMI_DATA_VO_SVC))
-               if ((ep_dist->cred_assngd >= ep_dist->cred_norm))
-                       goto out;
-
-       /*
-        * For all other services, we follow a simple algorithm of:
-        *
-        * 1. checking the free pool for credits
-        * 2. checking lower priority endpoints for credits to take
-        */
-
-       credits = min(cred_info->cur_free_credits, ep_dist->seek_cred);
-
-       if (credits >= ep_dist->seek_cred)
-               goto out;
-
-       /*
-        * We don't have enough in the free pool, try taking away from
-        * lower priority services The rule for taking away credits:
-        *
-        *   1. Only take from lower priority endpoints
-        *   2. Only take what is allocated above the minimum (never
-        *      starve an endpoint completely)
-        *   3. Only take what you need.
-        */
-
-       list_for_each_entry_reverse(curdist_list,
-                                   &cred_info->lowestpri_ep_dist,
-                                   list) {
-               if (curdist_list == ep_dist)
-                       break;
-
-               need = ep_dist->seek_cred - cred_info->cur_free_credits;
-
-               if ((curdist_list->cred_assngd - need) >=
-                    curdist_list->cred_min) {
-                       /*
-                        * The current one has been allocated more than
-                        * it's minimum and it has enough credits assigned
-                        * above it's minimum to fulfill our need try to
-                        * take away just enough to fulfill our need.
-                        */
-                       ath6k_reduce_credits(cred_info, curdist_list,
-                                       curdist_list->cred_assngd - need);
-
-                       if (cred_info->cur_free_credits >=
-                           ep_dist->seek_cred)
-                               break;
-               }
-
-               if (curdist_list->endpoint == ENDPOINT_0)
-                       break;
-       }
-
-       credits = min(cred_info->cur_free_credits, ep_dist->seek_cred);
-
-out:
-       /* did we find some credits? */
-       if (credits)
-               ath6kl_deposit_credit_to_ep(cred_info, ep_dist, credits);
-
-       ep_dist->seek_cred = 0;
-}
-
-/* redistribute credits based on activity change */
-static void ath6k_redistribute_credits(struct htc_credit_state_info *info,
-                                      struct list_head *ep_dist_list)
-{
-       struct htc_endpoint_credit_dist *curdist_list;
-
-       list_for_each_entry(curdist_list, ep_dist_list, list) {
-               if (curdist_list->endpoint == ENDPOINT_0)
-                       continue;
-
-               if ((curdist_list->svc_id == WMI_DATA_BK_SVC)  ||
-                   (curdist_list->svc_id == WMI_DATA_BE_SVC))
-                       curdist_list->dist_flags |= HTC_EP_ACTIVE;
-
-               if ((curdist_list->svc_id != WMI_CONTROL_SVC) &&
-                   !(curdist_list->dist_flags & HTC_EP_ACTIVE)) {
-                       if (curdist_list->txq_depth == 0)
-                               ath6k_reduce_credits(info,
-                                               curdist_list, 0);
-                       else
-                               ath6k_reduce_credits(info,
-                                               curdist_list,
-                                               curdist_list->cred_min);
-               }
-       }
-}
-
-/*
- *
- * This function is invoked whenever endpoints require credit
- * distributions. A lock is held while this function is invoked, this
- * function shall NOT block. The ep_dist_list is a list of distribution
- * structures in prioritized order as defined by the call to the
- * htc_set_credit_dist() api.
- */
-void ath6k_credit_distribute(struct htc_credit_state_info *cred_info,
-                            struct list_head *ep_dist_list,
-                            enum htc_credit_dist_reason reason)
-{
-       switch (reason) {
-       case HTC_CREDIT_DIST_SEND_COMPLETE:
-               ath6k_credit_update(cred_info, ep_dist_list);
-               break;
-       case HTC_CREDIT_DIST_ACTIVITY_CHANGE:
-               ath6k_redistribute_credits(cred_info, ep_dist_list);
-               break;
-       default:
-               break;
-       }
-
-       WARN_ON(cred_info->cur_free_credits > cred_info->total_avail_credits);
-       WARN_ON(cred_info->cur_free_credits < 0);
+       netif_wake_queue(vif->ndev);
 }
 
 void disconnect_timer_handler(unsigned long ptr)
 {
        struct net_device *dev = (struct net_device *)ptr;
-       struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
-       ath6kl_init_profile_info(ar);
-       ath6kl_disconnect(ar);
+       ath6kl_init_profile_info(vif);
+       ath6kl_disconnect(vif);
 }
 
-void ath6kl_disconnect(struct ath6kl *ar)
+void ath6kl_disconnect(struct ath6kl_vif *vif)
 {
-       if (test_bit(CONNECTED, &ar->flag) ||
-           test_bit(CONNECT_PEND, &ar->flag)) {
-               ath6kl_wmi_disconnect_cmd(ar->wmi);
+       if (test_bit(CONNECTED, &vif->flags) ||
+           test_bit(CONNECT_PEND, &vif->flags)) {
+               ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx);
                /*
                 * Disconnect command is issued, clear the connect pending
                 * flag. The connected flag will be cleared in
                 * disconnect event notification.
                 */
-               clear_bit(CONNECT_PEND, &ar->flag);
-       }
-}
-
-void ath6kl_deep_sleep_enable(struct ath6kl *ar)
-{
-       switch (ar->sme_state) {
-       case SME_CONNECTING:
-               cfg80211_connect_result(ar->net_dev, ar->bssid, NULL, 0,
-                                       NULL, 0,
-                                       WLAN_STATUS_UNSPECIFIED_FAILURE,
-                                       GFP_KERNEL);
-               break;
-       case SME_CONNECTED:
-       default:
-               /*
-                * FIXME: oddly enough smeState is in DISCONNECTED during
-                * suspend, why? Need to send disconnected event in that
-                * state.
-                */
-               cfg80211_disconnected(ar->net_dev, 0, NULL, 0, GFP_KERNEL);
-               break;
+               clear_bit(CONNECT_PEND, &vif->flags);
        }
-
-       if (test_bit(CONNECTED, &ar->flag) ||
-           test_bit(CONNECT_PEND, &ar->flag))
-               ath6kl_wmi_disconnect_cmd(ar->wmi);
-
-       ar->sme_state = SME_DISCONNECTED;
-
-       /* disable scanning */
-       if (ath6kl_wmi_scanparams_cmd(ar->wmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0,
-                                     0, 0) != 0)
-               printk(KERN_WARNING "ath6kl: failed to disable scan "
-                      "during suspend\n");
-
-       ath6kl_cfg80211_scan_complete_event(ar, -ECANCELED);
 }
 
 /* WMI Event handlers */
@@ -980,17 +598,16 @@ static const char *get_hw_id_string(u32 id)
 void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
 {
        struct ath6kl *ar = devt;
-       struct net_device *dev = ar->net_dev;
 
-       memcpy(dev->dev_addr, datap, ETH_ALEN);
+       memcpy(ar->mac_addr, datap, ETH_ALEN);
        ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n",
-                  __func__, dev->dev_addr);
+                  __func__, ar->mac_addr);
 
        ar->version.wlan_ver = sw_ver;
        ar->version.abi_ver = abi_ver;
 
-       snprintf(ar->wdev->wiphy->fw_version,
-                sizeof(ar->wdev->wiphy->fw_version),
+       snprintf(ar->wiphy->fw_version,
+                sizeof(ar->wiphy->fw_version),
                 "%u.%u.%u.%u",
                 (ar->version.wlan_ver & 0xf0000000) >> 28,
                 (ar->version.wlan_ver & 0x0f000000) >> 24,
@@ -1001,78 +618,91 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
        set_bit(WMI_READY, &ar->flag);
        wake_up(&ar->event_wq);
 
-       ath6kl_info("hw %s fw %s%s\n",
-                   get_hw_id_string(ar->wdev->wiphy->hw_version),
-                   ar->wdev->wiphy->fw_version,
-                   test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
+       if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) {
+               ath6kl_info("hw %s fw %s%s\n",
+                           get_hw_id_string(ar->wiphy->hw_version),
+                           ar->wiphy->fw_version,
+                           test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
+       }
 }
 
-void ath6kl_scan_complete_evt(struct ath6kl *ar, int status)
+void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status)
 {
-       ath6kl_cfg80211_scan_complete_event(ar, status);
+       struct ath6kl *ar = vif->ar;
+       bool aborted = false;
+
+       if (status != WMI_SCAN_STATUS_SUCCESS)
+               aborted = true;
+
+       ath6kl_cfg80211_scan_complete_event(vif, aborted);
 
        if (!ar->usr_bss_filter) {
-               clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
-               ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
+               clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
+               ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
+                                        NONE_BSS_FILTER, 0);
        }
 
-       ath6kl_dbg(ATH6KL_DBG_WLAN_SCAN, "scan complete: %d\n", status);
+       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "scan complete: %d\n", status);
 }
 
-void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
+void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
                          u16 listen_int, u16 beacon_int,
                          enum network_type net_type, u8 beacon_ie_len,
                          u8 assoc_req_len, u8 assoc_resp_len,
                          u8 *assoc_info)
 {
-       unsigned long flags;
+       struct ath6kl *ar = vif->ar;
 
-       ath6kl_cfg80211_connect_event(ar, channel, bssid,
+       ath6kl_cfg80211_connect_event(vif, channel, bssid,
                                      listen_int, beacon_int,
                                      net_type, beacon_ie_len,
                                      assoc_req_len, assoc_resp_len,
                                      assoc_info);
 
-       memcpy(ar->bssid, bssid, sizeof(ar->bssid));
-       ar->bss_ch = channel;
+       memcpy(vif->bssid, bssid, sizeof(vif->bssid));
+       vif->bss_ch = channel;
 
-       if ((ar->nw_type == INFRA_NETWORK))
-               ath6kl_wmi_listeninterval_cmd(ar->wmi, ar->listen_intvl_t,
+       if ((vif->nw_type == INFRA_NETWORK))
+               ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
+                                             ar->listen_intvl_t,
                                              ar->listen_intvl_b);
 
-       netif_wake_queue(ar->net_dev);
+       netif_wake_queue(vif->ndev);
 
        /* Update connect & link status atomically */
-       spin_lock_irqsave(&ar->lock, flags);
-       set_bit(CONNECTED, &ar->flag);
-       clear_bit(CONNECT_PEND, &ar->flag);
-       netif_carrier_on(ar->net_dev);
-       spin_unlock_irqrestore(&ar->lock, flags);
+       spin_lock_bh(&vif->if_lock);
+       set_bit(CONNECTED, &vif->flags);
+       clear_bit(CONNECT_PEND, &vif->flags);
+       netif_carrier_on(vif->ndev);
+       spin_unlock_bh(&vif->if_lock);
 
-       aggr_reset_state(ar->aggr_cntxt);
-       ar->reconnect_flag = 0;
+       aggr_reset_state(vif->aggr_cntxt);
+       vif->reconnect_flag = 0;
 
-       if ((ar->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) {
+       if ((vif->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) {
                memset(ar->node_map, 0, sizeof(ar->node_map));
                ar->node_num = 0;
                ar->next_ep_id = ENDPOINT_2;
        }
 
        if (!ar->usr_bss_filter) {
-               set_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
-               ath6kl_wmi_bssfilter_cmd(ar->wmi, CURRENT_BSS_FILTER, 0);
+               set_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
+               ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
+                                        CURRENT_BSS_FILTER, 0);
        }
 }
 
-void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast)
+void ath6kl_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid, bool ismcast)
 {
        struct ath6kl_sta *sta;
+       struct ath6kl *ar = vif->ar;
        u8 tsc[6];
+
        /*
         * For AP case, keyid will have aid of STA which sent pkt with
         * MIC error. Use this aid to get MAC & send it to hostapd.
         */
-       if (ar->nw_type == AP_NETWORK) {
+       if (vif->nw_type == AP_NETWORK) {
                sta = ath6kl_find_sta_by_aid(ar, (keyid >> 2));
                if (!sta)
                        return;
@@ -1081,19 +711,20 @@ void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast)
                           "ap tkip mic error received from aid=%d\n", keyid);
 
                memset(tsc, 0, sizeof(tsc)); /* FIX: get correct TSC */
-               cfg80211_michael_mic_failure(ar->net_dev, sta->mac,
+               cfg80211_michael_mic_failure(vif->ndev, sta->mac,
                                             NL80211_KEYTYPE_PAIRWISE, keyid,
                                             tsc, GFP_KERNEL);
        } else
-               ath6kl_cfg80211_tkip_micerr_event(ar, keyid, ismcast);
+               ath6kl_cfg80211_tkip_micerr_event(vif, keyid, ismcast);
 
 }
 
-static void ath6kl_update_target_stats(struct ath6kl *ar, u8 *ptr, u32 len)
+static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
 {
        struct wmi_target_stats *tgt_stats =
                (struct wmi_target_stats *) ptr;
-       struct target_stats *stats = &ar->target_stats;
+       struct ath6kl *ar = vif->ar;
+       struct target_stats *stats = &vif->target_stats;
        struct tkip_ccmp_stats *ccmp_stats;
        u8 ac;
 
@@ -1189,8 +820,8 @@ static void ath6kl_update_target_stats(struct ath6kl *ar, u8 *ptr, u32 len)
        stats->wow_evt_discarded +=
                le16_to_cpu(tgt_stats->wow_stats.wow_evt_discarded);
 
-       if (test_bit(STATS_UPDATE_PEND, &ar->flag)) {
-               clear_bit(STATS_UPDATE_PEND, &ar->flag);
+       if (test_bit(STATS_UPDATE_PEND, &vif->flags)) {
+               clear_bit(STATS_UPDATE_PEND, &vif->flags);
                wake_up(&ar->event_wq);
        }
 }
@@ -1200,14 +831,15 @@ static void ath6kl_add_le32(__le32 *var, __le32 val)
        *var = cpu_to_le32(le32_to_cpu(*var) + le32_to_cpu(val));
 }
 
-void ath6kl_tgt_stats_event(struct ath6kl *ar, u8 *ptr, u32 len)
+void ath6kl_tgt_stats_event(struct ath6kl_vif *vif, u8 *ptr, u32 len)
 {
        struct wmi_ap_mode_stat *p = (struct wmi_ap_mode_stat *) ptr;
+       struct ath6kl *ar = vif->ar;
        struct wmi_ap_mode_stat *ap = &ar->ap_stats;
        struct wmi_per_sta_stat *st_ap, *st_p;
        u8 ac;
 
-       if (ar->nw_type == AP_NETWORK) {
+       if (vif->nw_type == AP_NETWORK) {
                if (len < sizeof(*p))
                        return;
 
@@ -1226,7 +858,7 @@ void ath6kl_tgt_stats_event(struct ath6kl *ar, u8 *ptr, u32 len)
                }
 
        } else {
-               ath6kl_update_target_stats(ar, ptr, len);
+               ath6kl_update_target_stats(vif, ptr, len);
        }
 }
 
@@ -1245,11 +877,12 @@ void ath6kl_txpwr_rx_evt(void *devt, u8 tx_pwr)
        wake_up(&ar->event_wq);
 }
 
-void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid)
+void ath6kl_pspoll_event(struct ath6kl_vif *vif, u8 aid)
 {
        struct ath6kl_sta *conn;
        struct sk_buff *skb;
        bool psq_empty = false;
+       struct ath6kl *ar = vif->ar;
 
        conn = ath6kl_find_sta_by_aid(ar, aid);
 
@@ -1272,7 +905,7 @@ void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid)
        spin_unlock_bh(&conn->psq_lock);
 
        conn->sta_flags |= STA_PS_POLLED;
-       ath6kl_data_tx(skb, ar->net_dev);
+       ath6kl_data_tx(skb, vif->ndev);
        conn->sta_flags &= ~STA_PS_POLLED;
 
        spin_lock_bh(&conn->psq_lock);
@@ -1280,13 +913,14 @@ void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid)
        spin_unlock_bh(&conn->psq_lock);
 
        if (psq_empty)
-               ath6kl_wmi_set_pvb_cmd(ar->wmi, conn->aid, 0);
+               ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx, conn->aid, 0);
 }
 
-void ath6kl_dtimexpiry_event(struct ath6kl *ar)
+void ath6kl_dtimexpiry_event(struct ath6kl_vif *vif)
 {
        bool mcastq_empty = false;
        struct sk_buff *skb;
+       struct ath6kl *ar = vif->ar;
 
        /*
         * If there are no associated STAs, ignore the DTIM expiry event.
@@ -1308,31 +942,31 @@ void ath6kl_dtimexpiry_event(struct ath6kl *ar)
                return;
 
        /* set the STA flag to dtim_expired for the frame to go out */
-       set_bit(DTIM_EXPIRED, &ar->flag);
+       set_bit(DTIM_EXPIRED, &vif->flags);
 
        spin_lock_bh(&ar->mcastpsq_lock);
        while ((skb = skb_dequeue(&ar->mcastpsq)) != NULL) {
                spin_unlock_bh(&ar->mcastpsq_lock);
 
-               ath6kl_data_tx(skb, ar->net_dev);
+               ath6kl_data_tx(skb, vif->ndev);
 
                spin_lock_bh(&ar->mcastpsq_lock);
        }
        spin_unlock_bh(&ar->mcastpsq_lock);
 
-       clear_bit(DTIM_EXPIRED, &ar->flag);
+       clear_bit(DTIM_EXPIRED, &vif->flags);
 
        /* clear the LSB of the BitMapCtl field of the TIM IE */
-       ath6kl_wmi_set_pvb_cmd(ar->wmi, MCAST_AID, 0);
+       ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx, MCAST_AID, 0);
 }
 
-void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
+void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
                             u8 assoc_resp_len, u8 *assoc_info,
                             u16 prot_reason_status)
 {
-       unsigned long flags;
+       struct ath6kl *ar = vif->ar;
 
-       if (ar->nw_type == AP_NETWORK) {
+       if (vif->nw_type == AP_NETWORK) {
                if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))
                        return;
 
@@ -1344,31 +978,31 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
 
                        /* clear the LSB of the TIM IE's BitMapCtl field */
                        if (test_bit(WMI_READY, &ar->flag))
-                               ath6kl_wmi_set_pvb_cmd(ar->wmi, MCAST_AID, 0);
+                               ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx,
+                                                      MCAST_AID, 0);
                }
 
                if (!is_broadcast_ether_addr(bssid)) {
                        /* send event to application */
-                       cfg80211_del_sta(ar->net_dev, bssid, GFP_KERNEL);
+                       cfg80211_del_sta(vif->ndev, bssid, GFP_KERNEL);
                }
 
-               if (memcmp(ar->net_dev->dev_addr, bssid, ETH_ALEN) == 0) {
-                       memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
-                       clear_bit(CONNECTED, &ar->flag);
+               if (memcmp(vif->ndev->dev_addr, bssid, ETH_ALEN) == 0) {
+                       memset(vif->wep_key_list, 0, sizeof(vif->wep_key_list));
+                       clear_bit(CONNECTED, &vif->flags);
                }
                return;
        }
 
-       ath6kl_cfg80211_disconnect_event(ar, reason, bssid,
+       ath6kl_cfg80211_disconnect_event(vif, reason, bssid,
                                       assoc_resp_len, assoc_info,
                                       prot_reason_status);
 
-       aggr_reset_state(ar->aggr_cntxt);
+       aggr_reset_state(vif->aggr_cntxt);
 
-       del_timer(&ar->disconnect_timer);
+       del_timer(&vif->disconnect_timer);
 
-       ath6kl_dbg(ATH6KL_DBG_WLAN_CONNECT,
-                  "disconnect reason is %d\n", reason);
+       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "disconnect reason is %d\n", reason);
 
        /*
         * If the event is due to disconnect cmd from the host, only they
@@ -1377,83 +1011,98 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
         */
        if (reason == DISCONNECT_CMD) {
                if (!ar->usr_bss_filter && test_bit(WMI_READY, &ar->flag))
-                       ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
+                       ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
+                                                NONE_BSS_FILTER, 0);
        } else {
-               set_bit(CONNECT_PEND, &ar->flag);
+               set_bit(CONNECT_PEND, &vif->flags);
                if (((reason == ASSOC_FAILED) &&
                    (prot_reason_status == 0x11)) ||
                    ((reason == ASSOC_FAILED) && (prot_reason_status == 0x0)
-                    && (ar->reconnect_flag == 1))) {
-                       set_bit(CONNECTED, &ar->flag);
+                    && (vif->reconnect_flag == 1))) {
+                       set_bit(CONNECTED, &vif->flags);
                        return;
                }
        }
 
        /* update connect & link status atomically */
-       spin_lock_irqsave(&ar->lock, flags);
-       clear_bit(CONNECTED, &ar->flag);
-       netif_carrier_off(ar->net_dev);
-       spin_unlock_irqrestore(&ar->lock, flags);
+       spin_lock_bh(&vif->if_lock);
+       clear_bit(CONNECTED, &vif->flags);
+       netif_carrier_off(vif->ndev);
+       spin_unlock_bh(&vif->if_lock);
 
-       if ((reason != CSERV_DISCONNECT) || (ar->reconnect_flag != 1))
-               ar->reconnect_flag = 0;
+       if ((reason != CSERV_DISCONNECT) || (vif->reconnect_flag != 1))
+               vif->reconnect_flag = 0;
 
        if (reason != CSERV_DISCONNECT)
                ar->user_key_ctrl = 0;
 
-       netif_stop_queue(ar->net_dev);
-       memset(ar->bssid, 0, sizeof(ar->bssid));
-       ar->bss_ch = 0;
+       netif_stop_queue(vif->ndev);
+       memset(vif->bssid, 0, sizeof(vif->bssid));
+       vif->bss_ch = 0;
 
        ath6kl_tx_data_cleanup(ar);
 }
 
-static int ath6kl_open(struct net_device *dev)
+struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar)
 {
-       struct ath6kl *ar = ath6kl_priv(dev);
-       unsigned long flags;
+       struct ath6kl_vif *vif;
+
+       spin_lock_bh(&ar->list_lock);
+       if (list_empty(&ar->vif_list)) {
+               spin_unlock_bh(&ar->list_lock);
+               return NULL;
+       }
 
-       spin_lock_irqsave(&ar->lock, flags);
+       vif = list_first_entry(&ar->vif_list, struct ath6kl_vif, list);
 
-       set_bit(WLAN_ENABLED, &ar->flag);
+       spin_unlock_bh(&ar->list_lock);
 
-       if (test_bit(CONNECTED, &ar->flag)) {
+       return vif;
+}
+
+static int ath6kl_open(struct net_device *dev)
+{
+       struct ath6kl_vif *vif = netdev_priv(dev);
+
+       set_bit(WLAN_ENABLED, &vif->flags);
+
+       if (test_bit(CONNECTED, &vif->flags)) {
                netif_carrier_on(dev);
                netif_wake_queue(dev);
        } else
                netif_carrier_off(dev);
 
-       spin_unlock_irqrestore(&ar->lock, flags);
-
        return 0;
 }
 
 static int ath6kl_close(struct net_device *dev)
 {
        struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
        netif_stop_queue(dev);
 
-       ath6kl_disconnect(ar);
+       ath6kl_disconnect(vif);
 
        if (test_bit(WMI_READY, &ar->flag)) {
-               if (ath6kl_wmi_scanparams_cmd(ar->wmi, 0xFFFF, 0, 0, 0, 0, 0, 0,
-                                             0, 0, 0))
+               if (ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0xFFFF,
+                                             0, 0, 0, 0, 0, 0, 0, 0, 0))
                        return -EIO;
 
-               clear_bit(WLAN_ENABLED, &ar->flag);
        }
 
-       ath6kl_cfg80211_scan_complete_event(ar, -ECANCELED);
+       ath6kl_cfg80211_scan_complete_event(vif, true);
+
+       clear_bit(WLAN_ENABLED, &vif->flags);
 
        return 0;
 }
 
 static struct net_device_stats *ath6kl_get_stats(struct net_device *dev)
 {
-       struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
 
-       return &ar->net_stats;
+       return &vif->net_stats;
 }
 
 static struct net_device_ops ath6kl_netdev_ops = {
@@ -1466,6 +1115,7 @@ static struct net_device_ops ath6kl_netdev_ops = {
 void init_netdev(struct net_device *dev)
 {
        dev->netdev_ops = &ath6kl_netdev_ops;
+       dev->destructor = free_netdev;
        dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
 
        dev->needed_headroom = ETH_HLEN;
index 066d4f88807faf6d4af8f3fae753901b3df9f92f..e69ca5ee5bb193e1e1e5d1f3c5f47fe8f1ee981e 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/sd.h>
-#include "htc_hif.h"
+#include "hif.h"
 #include "hif-ops.h"
 #include "target.h"
 #include "debug.h"
@@ -46,6 +46,8 @@ struct ath6kl_sdio {
        struct list_head scat_req;
 
        spinlock_t scat_lock;
+       bool scatter_enabled;
+
        bool is_disabled;
        atomic_t irq_handling;
        const struct sdio_device_id *id;
@@ -135,6 +137,8 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
 {
        int ret = 0;
 
+       sdio_claim_host(func);
+
        if (request & HIF_WRITE) {
                /* FIXME: looks like ugly workaround for something */
                if (addr >= HIF_MBOX_BASE_ADDR &&
@@ -156,6 +160,8 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
                        ret = sdio_memcpy_fromio(func, buf, addr, len);
        }
 
+       sdio_release_host(func);
+
        ath6kl_dbg(ATH6KL_DBG_SDIO, "%s addr 0x%x%s buf 0x%p len %d\n",
                   request & HIF_WRITE ? "wr" : "rd", addr,
                   request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len);
@@ -167,12 +173,11 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
 static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio)
 {
        struct bus_request *bus_req;
-       unsigned long flag;
 
-       spin_lock_irqsave(&ar_sdio->lock, flag);
+       spin_lock_bh(&ar_sdio->lock);
 
        if (list_empty(&ar_sdio->bus_req_freeq)) {
-               spin_unlock_irqrestore(&ar_sdio->lock, flag);
+               spin_unlock_bh(&ar_sdio->lock);
                return NULL;
        }
 
@@ -180,7 +185,7 @@ static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio)
                                   struct bus_request, list);
        list_del(&bus_req->list);
 
-       spin_unlock_irqrestore(&ar_sdio->lock, flag);
+       spin_unlock_bh(&ar_sdio->lock);
        ath6kl_dbg(ATH6KL_DBG_SCATTER, "%s: bus request 0x%p\n",
                   __func__, bus_req);
 
@@ -190,14 +195,12 @@ static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio)
 static void ath6kl_sdio_free_bus_req(struct ath6kl_sdio *ar_sdio,
                                     struct bus_request *bus_req)
 {
-       unsigned long flag;
-
        ath6kl_dbg(ATH6KL_DBG_SCATTER, "%s: bus request 0x%p\n",
                   __func__, bus_req);
 
-       spin_lock_irqsave(&ar_sdio->lock, flag);
+       spin_lock_bh(&ar_sdio->lock);
        list_add_tail(&bus_req->list, &ar_sdio->bus_req_freeq);
-       spin_unlock_irqrestore(&ar_sdio->lock, flag);
+       spin_unlock_bh(&ar_sdio->lock);
 }
 
 static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req,
@@ -291,10 +294,14 @@ static int ath6kl_sdio_scat_rw(struct ath6kl_sdio *ar_sdio,
        mmc_req.cmd = &cmd;
        mmc_req.data = &data;
 
+       sdio_claim_host(ar_sdio->func);
+
        mmc_set_data_timeout(&data, ar_sdio->func->card);
        /* synchronous call to process request */
        mmc_wait_for_req(ar_sdio->func->card->host, &mmc_req);
 
+       sdio_release_host(ar_sdio->func);
+
        status = cmd.error ? cmd.error : data.error;
 
 scat_complete:
@@ -395,11 +402,9 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
        } else
                tbuf = buf;
 
-       sdio_claim_host(ar_sdio->func);
        ret = ath6kl_sdio_io(ar_sdio->func, request, addr, tbuf, len);
        if ((request & HIF_READ) && bounced)
                memcpy(buf, tbuf, len);
-       sdio_release_host(ar_sdio->func);
 
        return ret;
 }
@@ -418,29 +423,25 @@ static void __ath6kl_sdio_write_async(struct ath6kl_sdio *ar_sdio,
                                                     req->request);
                context = req->packet;
                ath6kl_sdio_free_bus_req(ar_sdio, req);
-               ath6kldev_rw_comp_handler(context, status);
+               ath6kl_hif_rw_comp_handler(context, status);
        }
 }
 
 static void ath6kl_sdio_write_async_work(struct work_struct *work)
 {
        struct ath6kl_sdio *ar_sdio;
-       unsigned long flags;
        struct bus_request *req, *tmp_req;
 
        ar_sdio = container_of(work, struct ath6kl_sdio, wr_async_work);
-       sdio_claim_host(ar_sdio->func);
 
-       spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
+       spin_lock_bh(&ar_sdio->wr_async_lock);
        list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) {
                list_del(&req->list);
-               spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
+               spin_unlock_bh(&ar_sdio->wr_async_lock);
                __ath6kl_sdio_write_async(ar_sdio, req);
-               spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
+               spin_lock_bh(&ar_sdio->wr_async_lock);
        }
-       spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
-
-       sdio_release_host(ar_sdio->func);
+       spin_unlock_bh(&ar_sdio->wr_async_lock);
 }
 
 static void ath6kl_sdio_irq_handler(struct sdio_func *func)
@@ -459,20 +460,23 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
         */
        sdio_release_host(ar_sdio->func);
 
-       status = ath6kldev_intr_bh_handler(ar_sdio->ar);
+       status = ath6kl_hif_intr_bh_handler(ar_sdio->ar);
        sdio_claim_host(ar_sdio->func);
        atomic_set(&ar_sdio->irq_handling, 0);
        WARN_ON(status && status != -ECANCELED);
 }
 
-static int ath6kl_sdio_power_on(struct ath6kl_sdio *ar_sdio)
+static int ath6kl_sdio_power_on(struct ath6kl *ar)
 {
+       struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
        struct sdio_func *func = ar_sdio->func;
        int ret = 0;
 
        if (!ar_sdio->is_disabled)
                return 0;
 
+       ath6kl_dbg(ATH6KL_DBG_BOOT, "sdio power on\n");
+
        sdio_claim_host(func);
 
        ret = sdio_enable_func(func);
@@ -495,13 +499,16 @@ static int ath6kl_sdio_power_on(struct ath6kl_sdio *ar_sdio)
        return ret;
 }
 
-static int ath6kl_sdio_power_off(struct ath6kl_sdio *ar_sdio)
+static int ath6kl_sdio_power_off(struct ath6kl *ar)
 {
+       struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
        int ret;
 
        if (ar_sdio->is_disabled)
                return 0;
 
+       ath6kl_dbg(ATH6KL_DBG_BOOT, "sdio power off\n");
+
        /* Disable the card */
        sdio_claim_host(ar_sdio->func);
        ret = sdio_disable_func(ar_sdio->func);
@@ -521,7 +528,6 @@ static int ath6kl_sdio_write_async(struct ath6kl *ar, u32 address, u8 *buffer,
 {
        struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
        struct bus_request *bus_req;
-       unsigned long flags;
 
        bus_req = ath6kl_sdio_alloc_busreq(ar_sdio);
 
@@ -534,9 +540,9 @@ static int ath6kl_sdio_write_async(struct ath6kl *ar, u32 address, u8 *buffer,
        bus_req->request = request;
        bus_req->packet = packet;
 
-       spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
+       spin_lock_bh(&ar_sdio->wr_async_lock);
        list_add_tail(&bus_req->list, &ar_sdio->wr_asyncq);
-       spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
+       spin_unlock_bh(&ar_sdio->wr_async_lock);
        queue_work(ar->ath6kl_wq, &ar_sdio->wr_async_work);
 
        return 0;
@@ -582,9 +588,8 @@ static struct hif_scatter_req *ath6kl_sdio_scatter_req_get(struct ath6kl *ar)
 {
        struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
        struct hif_scatter_req *node = NULL;
-       unsigned long flag;
 
-       spin_lock_irqsave(&ar_sdio->scat_lock, flag);
+       spin_lock_bh(&ar_sdio->scat_lock);
 
        if (!list_empty(&ar_sdio->scat_req)) {
                node = list_first_entry(&ar_sdio->scat_req,
@@ -592,7 +597,7 @@ static struct hif_scatter_req *ath6kl_sdio_scatter_req_get(struct ath6kl *ar)
                list_del(&node->list);
        }
 
-       spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
+       spin_unlock_bh(&ar_sdio->scat_lock);
 
        return node;
 }
@@ -601,13 +606,12 @@ static void ath6kl_sdio_scatter_req_add(struct ath6kl *ar,
                                        struct hif_scatter_req *s_req)
 {
        struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
-       unsigned long flag;
 
-       spin_lock_irqsave(&ar_sdio->scat_lock, flag);
+       spin_lock_bh(&ar_sdio->scat_lock);
 
        list_add_tail(&s_req->list, &ar_sdio->scat_req);
 
-       spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
+       spin_unlock_bh(&ar_sdio->scat_lock);
 
 }
 
@@ -618,7 +622,6 @@ static int ath6kl_sdio_async_rw_scatter(struct ath6kl *ar,
        struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
        u32 request = scat_req->req;
        int status = 0;
-       unsigned long flags;
 
        if (!scat_req->len)
                return -EINVAL;
@@ -627,14 +630,12 @@ static int ath6kl_sdio_async_rw_scatter(struct ath6kl *ar,
                "hif-scatter: total len: %d scatter entries: %d\n",
                scat_req->len, scat_req->scat_entries);
 
-       if (request & HIF_SYNCHRONOUS) {
-               sdio_claim_host(ar_sdio->func);
+       if (request & HIF_SYNCHRONOUS)
                status = ath6kl_sdio_scat_rw(ar_sdio, scat_req->busrequest);
-               sdio_release_host(ar_sdio->func);
-       } else {
-               spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
+       else {
+               spin_lock_bh(&ar_sdio->wr_async_lock);
                list_add_tail(&scat_req->busrequest->list, &ar_sdio->wr_asyncq);
-               spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
+               spin_unlock_bh(&ar_sdio->wr_async_lock);
                queue_work(ar->ath6kl_wq, &ar_sdio->wr_async_work);
        }
 
@@ -646,23 +647,27 @@ static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar)
 {
        struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
        struct hif_scatter_req *s_req, *tmp_req;
-       unsigned long flag;
 
        /* empty the free list */
-       spin_lock_irqsave(&ar_sdio->scat_lock, flag);
+       spin_lock_bh(&ar_sdio->scat_lock);
        list_for_each_entry_safe(s_req, tmp_req, &ar_sdio->scat_req, list) {
                list_del(&s_req->list);
-               spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
+               spin_unlock_bh(&ar_sdio->scat_lock);
 
+               /*
+                * FIXME: should we also call completion handler with
+                * ath6kl_hif_rw_comp_handler() with status -ECANCELED so
+                * that the packet is properly freed?
+                */
                if (s_req->busrequest)
                        ath6kl_sdio_free_bus_req(ar_sdio, s_req->busrequest);
                kfree(s_req->virt_dma_buf);
                kfree(s_req->sgentries);
                kfree(s_req);
 
-               spin_lock_irqsave(&ar_sdio->scat_lock, flag);
+               spin_lock_bh(&ar_sdio->scat_lock);
        }
-       spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
+       spin_unlock_bh(&ar_sdio->scat_lock);
 }
 
 /* setup of HIF scatter resources */
@@ -673,6 +678,11 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
        int ret;
        bool virt_scat = false;
 
+       if (ar_sdio->scatter_enabled)
+               return 0;
+
+       ar_sdio->scatter_enabled = true;
+
        /* check if host supports scatter and it meets our requirements */
        if (ar_sdio->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) {
                ath6kl_err("host only supports scatter of :%d entries, need: %d\n",
@@ -687,8 +697,8 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
                                MAX_SCATTER_REQUESTS, virt_scat);
 
                if (!ret) {
-                       ath6kl_dbg(ATH6KL_DBG_SCATTER,
-                                  "hif-scatter enabled: max scatter req : %d entries: %d\n",
+                       ath6kl_dbg(ATH6KL_DBG_BOOT,
+                                  "hif-scatter enabled requests %d entries %d\n",
                                   MAX_SCATTER_REQUESTS,
                                   MAX_SCATTER_ENTRIES_PER_REQ);
 
@@ -712,8 +722,8 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
                        return ret;
                }
 
-               ath6kl_dbg(ATH6KL_DBG_SCATTER,
-                          "Vitual scatter enabled, max_scat_req:%d, entries:%d\n",
+               ath6kl_dbg(ATH6KL_DBG_BOOT,
+                          "virtual scatter enabled requests %d entries %d\n",
                           ATH6KL_SCATTER_REQS, ATH6KL_SCATTER_ENTRIES_PER_REQ);
 
                target->max_scat_entries = ATH6KL_SCATTER_ENTRIES_PER_REQ;
@@ -724,7 +734,47 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
        return 0;
 }
 
-static int ath6kl_sdio_suspend(struct ath6kl *ar)
+static int ath6kl_sdio_config(struct ath6kl *ar)
+{
+       struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+       struct sdio_func *func = ar_sdio->func;
+       int ret;
+
+       sdio_claim_host(func);
+
+       if ((ar_sdio->id->device & MANUFACTURER_ID_ATH6KL_BASE_MASK) >=
+           MANUFACTURER_ID_AR6003_BASE) {
+               /* enable 4-bit ASYNC interrupt on AR6003 or later */
+               ret = ath6kl_sdio_func0_cmd52_wr_byte(func->card,
+                                               CCCR_SDIO_IRQ_MODE_REG,
+                                               SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
+               if (ret) {
+                       ath6kl_err("Failed to enable 4-bit async irq mode %d\n",
+                                  ret);
+                       goto out;
+               }
+
+               ath6kl_dbg(ATH6KL_DBG_BOOT, "4-bit async irq mode enabled\n");
+       }
+
+       /* give us some time to enable, in ms */
+       func->enable_timeout = 100;
+
+       ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
+       if (ret) {
+               ath6kl_err("Set sdio block size %d failed: %d)\n",
+                          HIF_MBOX_BLOCK_SIZE, ret);
+               sdio_release_host(func);
+               goto out;
+       }
+
+out:
+       sdio_release_host(func);
+
+       return ret;
+}
+
+static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
 {
        struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
        struct sdio_func *func = ar_sdio->func;
@@ -733,12 +783,14 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar)
 
        flags = sdio_get_host_pm_caps(func);
 
-       if (!(flags & MMC_PM_KEEP_POWER))
-               /* as host doesn't support keep power we need to bail out */
-               ath6kl_dbg(ATH6KL_DBG_SDIO,
-                          "func %d doesn't support MMC_PM_KEEP_POWER\n",
-                          func->num);
-               return -EINVAL;
+       ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio suspend pm_caps 0x%x\n", flags);
+
+       if (!(flags & MMC_PM_KEEP_POWER) ||
+           (ar->conf_flags & ATH6KL_CONF_SUSPEND_CUTPOWER)) {
+               /* as host doesn't support keep power we need to cut power */
+               return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER,
+                                              NULL);
+       }
 
        ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
        if (ret) {
@@ -747,11 +799,85 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar)
                return ret;
        }
 
-       ath6kl_deep_sleep_enable(ar);
+       if ((flags & MMC_PM_WAKE_SDIO_IRQ) && wow) {
+               /*
+                * The host sdio controller is capable of keep power and
+                * sdio irq wake up at this point. It's fine to continue
+                * wow suspend operation.
+                */
+               ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow);
+               if (ret)
+                       return ret;
+
+               ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
+               if (ret)
+                       ath6kl_err("set sdio wake irq flag failed: %d\n", ret);
+
+               return ret;
+       }
+
+       return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, NULL);
+}
+
+static int ath6kl_sdio_resume(struct ath6kl *ar)
+{
+       switch (ar->state) {
+       case ATH6KL_STATE_OFF:
+       case ATH6KL_STATE_CUTPOWER:
+               ath6kl_dbg(ATH6KL_DBG_SUSPEND,
+                          "sdio resume configuring sdio\n");
+
+               /* need to set sdio settings after power is cut from sdio */
+               ath6kl_sdio_config(ar);
+               break;
+
+       case ATH6KL_STATE_ON:
+               break;
+
+       case ATH6KL_STATE_DEEPSLEEP:
+               break;
+
+       case ATH6KL_STATE_WOW:
+               break;
+       }
+
+       ath6kl_cfg80211_resume(ar);
 
        return 0;
 }
 
+static void ath6kl_sdio_stop(struct ath6kl *ar)
+{
+       struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+       struct bus_request *req, *tmp_req;
+       void *context;
+
+       /* FIXME: make sure that wq is not queued again */
+
+       cancel_work_sync(&ar_sdio->wr_async_work);
+
+       spin_lock_bh(&ar_sdio->wr_async_lock);
+
+       list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) {
+               list_del(&req->list);
+
+               if (req->scat_req) {
+                       /* this is a scatter gather request */
+                       req->scat_req->status = -ECANCELED;
+                       req->scat_req->complete(ar_sdio->ar->htc_target,
+                                               req->scat_req);
+               } else {
+                       context = req->packet;
+                       ath6kl_sdio_free_bus_req(ar_sdio, req);
+                       ath6kl_hif_rw_comp_handler(context, -ECANCELED);
+               }
+       }
+
+       spin_unlock_bh(&ar_sdio->wr_async_lock);
+
+       WARN_ON(get_queue_depth(&ar_sdio->scat_req) != 4);
+}
+
 static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
        .read_write_sync = ath6kl_sdio_read_write_sync,
        .write_async = ath6kl_sdio_write_async,
@@ -763,8 +889,43 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
        .scat_req_rw = ath6kl_sdio_async_rw_scatter,
        .cleanup_scatter = ath6kl_sdio_cleanup_scatter,
        .suspend = ath6kl_sdio_suspend,
+       .resume = ath6kl_sdio_resume,
+       .power_on = ath6kl_sdio_power_on,
+       .power_off = ath6kl_sdio_power_off,
+       .stop = ath6kl_sdio_stop,
 };
 
+#ifdef CONFIG_PM_SLEEP
+
+/*
+ * Empty handlers so that mmc subsystem doesn't remove us entirely during
+ * suspend. We instead follow cfg80211 suspend/resume handlers.
+ */
+static int ath6kl_sdio_pm_suspend(struct device *device)
+{
+       ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio pm suspend\n");
+
+       return 0;
+}
+
+static int ath6kl_sdio_pm_resume(struct device *device)
+{
+       ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio pm resume\n");
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ath6kl_sdio_pm_ops, ath6kl_sdio_pm_suspend,
+                        ath6kl_sdio_pm_resume);
+
+#define ATH6KL_SDIO_PM_OPS (&ath6kl_sdio_pm_ops)
+
+#else
+
+#define ATH6KL_SDIO_PM_OPS NULL
+
+#endif /* CONFIG_PM_SLEEP */
+
 static int ath6kl_sdio_probe(struct sdio_func *func,
                             const struct sdio_device_id *id)
 {
@@ -773,8 +934,8 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
        struct ath6kl *ar;
        int count;
 
-       ath6kl_dbg(ATH6KL_DBG_SDIO,
-                  "new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n",
+       ath6kl_dbg(ATH6KL_DBG_BOOT,
+                  "sdio new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n",
                   func->num, func->vendor, func->device,
                   func->max_blksize, func->cur_blksize);
 
@@ -820,57 +981,22 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
 
        ath6kl_sdio_set_mbox_info(ar);
 
-       sdio_claim_host(func);
-
-       if ((ar_sdio->id->device & MANUFACTURER_ID_ATH6KL_BASE_MASK) >=
-           MANUFACTURER_ID_AR6003_BASE) {
-               /* enable 4-bit ASYNC interrupt on AR6003 or later */
-               ret = ath6kl_sdio_func0_cmd52_wr_byte(func->card,
-                                               CCCR_SDIO_IRQ_MODE_REG,
-                                               SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
-               if (ret) {
-                       ath6kl_err("Failed to enable 4-bit async irq mode %d\n",
-                                  ret);
-                       sdio_release_host(func);
-                       goto err_cfg80211;
-               }
-
-               ath6kl_dbg(ATH6KL_DBG_SDIO, "4-bit async irq mode enabled\n");
-       }
-
-       /* give us some time to enable, in ms */
-       func->enable_timeout = 100;
-
-       sdio_release_host(func);
-
-       ret = ath6kl_sdio_power_on(ar_sdio);
-       if (ret)
-               goto err_cfg80211;
-
-       sdio_claim_host(func);
-
-       ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
+       ret = ath6kl_sdio_config(ar);
        if (ret) {
-               ath6kl_err("Set sdio block size %d failed: %d)\n",
-                          HIF_MBOX_BLOCK_SIZE, ret);
-               sdio_release_host(func);
-               goto err_off;
+               ath6kl_err("Failed to config sdio: %d\n", ret);
+               goto err_core_alloc;
        }
 
-       sdio_release_host(func);
-
        ret = ath6kl_core_init(ar);
        if (ret) {
                ath6kl_err("Failed to init ath6kl core\n");
-               goto err_off;
+               goto err_core_alloc;
        }
 
        return ret;
 
-err_off:
-       ath6kl_sdio_power_off(ar_sdio);
-err_cfg80211:
-       ath6kl_cfg80211_deinit(ar_sdio->ar);
+err_core_alloc:
+       ath6kl_core_free(ar_sdio->ar);
 err_dma:
        kfree(ar_sdio->dma_buffer);
 err_hif:
@@ -883,8 +1009,8 @@ static void ath6kl_sdio_remove(struct sdio_func *func)
 {
        struct ath6kl_sdio *ar_sdio;
 
-       ath6kl_dbg(ATH6KL_DBG_SDIO,
-                  "removed func %d vendor 0x%x device 0x%x\n",
+       ath6kl_dbg(ATH6KL_DBG_BOOT,
+                  "sdio removed func %d vendor 0x%x device 0x%x\n",
                   func->num, func->vendor, func->device);
 
        ar_sdio = sdio_get_drvdata(func);
@@ -892,9 +1018,7 @@ static void ath6kl_sdio_remove(struct sdio_func *func)
        ath6kl_stop_txrx(ar_sdio->ar);
        cancel_work_sync(&ar_sdio->wr_async_work);
 
-       ath6kl_unavail_ev(ar_sdio->ar);
-
-       ath6kl_sdio_power_off(ar_sdio);
+       ath6kl_core_cleanup(ar_sdio->ar);
 
        kfree(ar_sdio->dma_buffer);
        kfree(ar_sdio);
@@ -909,10 +1033,11 @@ static const struct sdio_device_id ath6kl_sdio_devices[] = {
 MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices);
 
 static struct sdio_driver ath6kl_sdio_driver = {
-       .name = "ath6kl_sdio",
+       .name = "ath6kl",
        .id_table = ath6kl_sdio_devices,
        .probe = ath6kl_sdio_probe,
        .remove = ath6kl_sdio_remove,
+       .drv.pm = ATH6KL_SDIO_PM_OPS,
 };
 
 static int __init ath6kl_sdio_init(void)
index c9a76051f0424fd6f9a139a6a15b1776fe63a768..687e2b350e8fb20ea081ea3eb355de5dc727e040 100644 (file)
@@ -320,7 +320,10 @@ struct host_interest {
 |   (2)   |   (2)   |   (2)   |   (2)   |   (2)   |   (2)   |   (2)   |   (2)
 |------------------------------------------------------------------------------|
 */
+#define HI_OPTION_FW_MODE_BITS        0x2
 #define HI_OPTION_FW_MODE_SHIFT        0xC
+
+#define HI_OPTION_FW_SUBMODE_BITS      0x2
 #define HI_OPTION_FW_SUBMODE_SHIFT     0x14
 
 /* Convert a Target virtual address into a Target physical address */
index a7117074f81c033776bc89808c8897e1146c4953..d9cff2b950b1e2248a340a3a7f4b496cf025b8e2 100644 (file)
@@ -77,12 +77,13 @@ static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev,
        return ar->node_map[ep_map].ep_id;
 }
 
-static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
+static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb,
                                bool *more_data)
 {
        struct ethhdr *datap = (struct ethhdr *) skb->data;
        struct ath6kl_sta *conn = NULL;
        bool ps_queued = false, is_psq_empty = false;
+       struct ath6kl *ar = vif->ar;
 
        if (is_multicast_ether_addr(datap->h_dest)) {
                u8 ctr = 0;
@@ -100,7 +101,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
                         * If this transmit is not because of a Dtim Expiry
                         * q it.
                         */
-                       if (!test_bit(DTIM_EXPIRED, &ar->flag)) {
+                       if (!test_bit(DTIM_EXPIRED, &vif->flags)) {
                                bool is_mcastq_empty = false;
 
                                spin_lock_bh(&ar->mcastpsq_lock);
@@ -116,6 +117,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
                                 */
                                if (is_mcastq_empty)
                                        ath6kl_wmi_set_pvb_cmd(ar->wmi,
+                                                              vif->fw_vif_idx,
                                                               MCAST_AID, 1);
 
                                ps_queued = true;
@@ -131,7 +133,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
                        }
                }
        } else {
-               conn = ath6kl_find_sta(ar, datap->h_dest);
+               conn = ath6kl_find_sta(vif, datap->h_dest);
                if (!conn) {
                        dev_kfree_skb(skb);
 
@@ -154,6 +156,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
                                 */
                                if (is_psq_empty)
                                        ath6kl_wmi_set_pvb_cmd(ar->wmi,
+                                                              vif->fw_vif_idx,
                                                               conn->aid, 1);
 
                                ps_queued = true;
@@ -235,6 +238,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
        struct ath6kl *ar = ath6kl_priv(dev);
        struct ath6kl_cookie *cookie = NULL;
        enum htc_endpoint_id eid = ENDPOINT_UNUSED;
+       struct ath6kl_vif *vif = netdev_priv(dev);
        u32 map_no = 0;
        u16 htc_tag = ATH6KL_DATA_PKT_TAG;
        u8 ac = 99 ; /* initialize to unmapped ac */
@@ -246,7 +250,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
                   skb, skb->data, skb->len);
 
        /* If target is not associated */
-       if (!test_bit(CONNECTED, &ar->flag)) {
+       if (!test_bit(CONNECTED, &vif->flags)) {
                dev_kfree_skb(skb);
                return 0;
        }
@@ -255,15 +259,21 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
                goto fail_tx;
 
        /* AP mode Power saving processing */
-       if (ar->nw_type == AP_NETWORK) {
-               if (ath6kl_powersave_ap(ar, skb, &more_data))
+       if (vif->nw_type == AP_NETWORK) {
+               if (ath6kl_powersave_ap(vif, skb, &more_data))
                        return 0;
        }
 
        if (test_bit(WMI_ENABLED, &ar->flag)) {
                if (skb_headroom(skb) < dev->needed_headroom) {
-                       WARN_ON(1);
-                       goto fail_tx;
+                       struct sk_buff *tmp_skb = skb;
+
+                       skb = skb_realloc_headroom(skb, dev->needed_headroom);
+                       kfree_skb(tmp_skb);
+                       if (skb == NULL) {
+                               vif->net_stats.tx_dropped++;
+                               return 0;
+                       }
                }
 
                if (ath6kl_wmi_dix_2_dot3(ar->wmi, skb)) {
@@ -272,18 +282,20 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
                }
 
                if (ath6kl_wmi_data_hdr_add(ar->wmi, skb, DATA_MSGTYPE,
-                                           more_data, 0, 0, NULL)) {
+                                           more_data, 0, 0, NULL,
+                                           vif->fw_vif_idx)) {
                        ath6kl_err("wmi_data_hdr_add failed\n");
                        goto fail_tx;
                }
 
-               if ((ar->nw_type == ADHOC_NETWORK) &&
-                    ar->ibss_ps_enable && test_bit(CONNECTED, &ar->flag))
+               if ((vif->nw_type == ADHOC_NETWORK) &&
+                    ar->ibss_ps_enable && test_bit(CONNECTED, &vif->flags))
                        chk_adhoc_ps_mapping = true;
                else {
                        /* get the stream mapping */
-                       ret = ath6kl_wmi_implicit_create_pstream(ar->wmi, skb,
-                                   0, test_bit(WMM_ENABLED, &ar->flag), &ac);
+                       ret = ath6kl_wmi_implicit_create_pstream(ar->wmi,
+                                   vif->fw_vif_idx, skb,
+                                   0, test_bit(WMM_ENABLED, &vif->flags), &ac);
                        if (ret)
                                goto fail_tx;
                }
@@ -354,8 +366,8 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
 fail_tx:
        dev_kfree_skb(skb);
 
-       ar->net_stats.tx_dropped++;
-       ar->net_stats.tx_aborted_errors++;
+       vif->net_stats.tx_dropped++;
+       vif->net_stats.tx_aborted_errors++;
 
        return 0;
 }
@@ -426,7 +438,9 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
                                               struct htc_packet *packet)
 {
        struct ath6kl *ar = target->dev->ar;
+       struct ath6kl_vif *vif;
        enum htc_endpoint_id endpoint = packet->endpoint;
+       enum htc_send_full_action action = HTC_SEND_FULL_KEEP;
 
        if (endpoint == ar->ctrl_ep) {
                /*
@@ -439,19 +453,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
                set_bit(WMI_CTRL_EP_FULL, &ar->flag);
                spin_unlock_bh(&ar->lock);
                ath6kl_err("wmi ctrl ep is full\n");
-               return HTC_SEND_FULL_KEEP;
+               goto stop_adhoc_netq;
        }
 
        if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG)
-               return HTC_SEND_FULL_KEEP;
-
-       if (ar->nw_type == ADHOC_NETWORK)
-               /*
-                * In adhoc mode, we cannot differentiate traffic
-                * priorities so there is no need to continue, however we
-                * should stop the network.
-                */
-               goto stop_net_queues;
+               goto stop_adhoc_netq;
 
        /*
         * The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for
@@ -459,29 +465,43 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
         */
        if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] <
            ar->hiac_stream_active_pri &&
-           ar->cookie_count <= MAX_HI_COOKIE_NUM)
+           ar->cookie_count <= MAX_HI_COOKIE_NUM) {
                /*
                 * Give preference to the highest priority stream by
                 * dropping the packets which overflowed.
                 */
-               return HTC_SEND_FULL_DROP;
+               action = HTC_SEND_FULL_DROP;
+               goto stop_adhoc_netq;
+       }
 
-stop_net_queues:
-       spin_lock_bh(&ar->lock);
-       set_bit(NETQ_STOPPED, &ar->flag);
-       spin_unlock_bh(&ar->lock);
-       netif_stop_queue(ar->net_dev);
+stop_adhoc_netq:
+       /* FIXME: Locking */
+       spin_lock_bh(&ar->list_lock);
+       list_for_each_entry(vif, &ar->vif_list, list) {
+               if (vif->nw_type == ADHOC_NETWORK) {
+                       spin_unlock_bh(&ar->list_lock);
 
-       return HTC_SEND_FULL_KEEP;
+                       spin_lock_bh(&vif->if_lock);
+                       set_bit(NETQ_STOPPED, &vif->flags);
+                       spin_unlock_bh(&vif->if_lock);
+                       netif_stop_queue(vif->ndev);
+
+                       return action;
+               }
+       }
+       spin_unlock_bh(&ar->list_lock);
+
+       return action;
 }
 
 /* TODO this needs to be looked at */
-static void ath6kl_tx_clear_node_map(struct ath6kl *ar,
+static void ath6kl_tx_clear_node_map(struct ath6kl_vif *vif,
                                     enum htc_endpoint_id eid, u32 map_no)
 {
+       struct ath6kl *ar = vif->ar;
        u32 i;
 
-       if (ar->nw_type != ADHOC_NETWORK)
+       if (vif->nw_type != ADHOC_NETWORK)
                return;
 
        if (!ar->ibss_ps_enable)
@@ -523,7 +543,9 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
        int status;
        enum htc_endpoint_id eid;
        bool wake_event = false;
-       bool flushing = false;
+       bool flushing[MAX_NUM_VIF] = {false};
+       u8 if_idx;
+       struct ath6kl_vif *vif;
 
        skb_queue_head_init(&skb_queue);
 
@@ -569,15 +591,30 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
                                wake_event = true;
                }
 
+               if (eid == ar->ctrl_ep) {
+                       if_idx = wmi_cmd_hdr_get_if_idx(
+                               (struct wmi_cmd_hdr *) skb->data);
+               } else {
+                       if_idx = wmi_data_hdr_get_if_idx(
+                               (struct wmi_data_hdr *) skb->data);
+               }
+
+               vif = ath6kl_get_vif_by_index(ar, if_idx);
+               if (!vif) {
+                       ath6kl_free_cookie(ar, ath6kl_cookie);
+                       continue;
+               }
+
                if (status) {
                        if (status == -ECANCELED)
                                /* a packet was flushed  */
-                               flushing = true;
+                               flushing[if_idx] = true;
+
+                       vif->net_stats.tx_errors++;
 
-                       ar->net_stats.tx_errors++;
+                       if (status != -ENOSPC && status != -ECANCELED)
+                               ath6kl_warn("tx complete error: %d\n", status);
 
-                       if (status != -ENOSPC)
-                               ath6kl_err("tx error, status: 0x%x\n", status);
                        ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
                                   "%s: skb=0x%p data=0x%p len=0x%x eid=%d %s\n",
                                   __func__, skb, packet->buf, packet->act_len,
@@ -588,27 +625,34 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
                                   __func__, skb, packet->buf, packet->act_len,
                                   eid, "OK");
 
-                       flushing = false;
-                       ar->net_stats.tx_packets++;
-                       ar->net_stats.tx_bytes += skb->len;
+                       flushing[if_idx] = false;
+                       vif->net_stats.tx_packets++;
+                       vif->net_stats.tx_bytes += skb->len;
                }
 
-               ath6kl_tx_clear_node_map(ar, eid, map_no);
+               ath6kl_tx_clear_node_map(vif, eid, map_no);
 
                ath6kl_free_cookie(ar, ath6kl_cookie);
 
-               if (test_bit(NETQ_STOPPED, &ar->flag))
-                       clear_bit(NETQ_STOPPED, &ar->flag);
+               if (test_bit(NETQ_STOPPED, &vif->flags))
+                       clear_bit(NETQ_STOPPED, &vif->flags);
        }
 
        spin_unlock_bh(&ar->lock);
 
        __skb_queue_purge(&skb_queue);
 
-       if (test_bit(CONNECTED, &ar->flag)) {
-               if (!flushing)
-                       netif_wake_queue(ar->net_dev);
+       /* FIXME: Locking */
+       spin_lock_bh(&ar->list_lock);
+       list_for_each_entry(vif, &ar->vif_list, list) {
+               if (test_bit(CONNECTED, &vif->flags) &&
+                   !flushing[vif->fw_vif_idx]) {
+                       spin_unlock_bh(&ar->list_lock);
+                       netif_wake_queue(vif->ndev);
+                       spin_lock_bh(&ar->list_lock);
+               }
        }
+       spin_unlock_bh(&ar->list_lock);
 
        if (wake_event)
                wake_up(&ar->event_wq);
@@ -1041,8 +1085,9 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
        struct ath6kl_sta *conn = NULL;
        struct sk_buff *skb1 = NULL;
        struct ethhdr *datap = NULL;
+       struct ath6kl_vif *vif;
        u16 seq_no, offset;
-       u8 tid;
+       u8 tid, if_idx;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_RX,
                   "%s: ar=0x%p eid=%d, skb=0x%p, data=0x%p, len=0x%x status:%d",
@@ -1050,7 +1095,23 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
                   packet->act_len, status);
 
        if (status || !(skb->data + HTC_HDR_LENGTH)) {
-               ar->net_stats.rx_errors++;
+               dev_kfree_skb(skb);
+               return;
+       }
+
+       skb_put(skb, packet->act_len + HTC_HDR_LENGTH);
+       skb_pull(skb, HTC_HDR_LENGTH);
+
+       if (ept == ar->ctrl_ep) {
+               if_idx =
+               wmi_cmd_hdr_get_if_idx((struct wmi_cmd_hdr *) skb->data);
+       } else {
+               if_idx =
+               wmi_data_hdr_get_if_idx((struct wmi_data_hdr *) skb->data);
+       }
+
+       vif = ath6kl_get_vif_by_index(ar, if_idx);
+       if (!vif) {
                dev_kfree_skb(skb);
                return;
        }
@@ -1059,28 +1120,28 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
         * Take lock to protect buffer counts and adaptive power throughput
         * state.
         */
-       spin_lock_bh(&ar->lock);
+       spin_lock_bh(&vif->if_lock);
 
-       ar->net_stats.rx_packets++;
-       ar->net_stats.rx_bytes += packet->act_len;
+       vif->net_stats.rx_packets++;
+       vif->net_stats.rx_bytes += packet->act_len;
 
-       spin_unlock_bh(&ar->lock);
+       spin_unlock_bh(&vif->if_lock);
 
-       skb_put(skb, packet->act_len + HTC_HDR_LENGTH);
-       skb_pull(skb, HTC_HDR_LENGTH);
 
        ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ",
                        skb->data, skb->len);
 
-       skb->dev = ar->net_dev;
+       skb->dev = vif->ndev;
 
        if (!test_bit(WMI_ENABLED, &ar->flag)) {
                if (EPPING_ALIGNMENT_PAD > 0)
                        skb_pull(skb, EPPING_ALIGNMENT_PAD);
-               ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb);
+               ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb);
                return;
        }
 
+       ath6kl_check_wow_status(ar);
+
        if (ept == ar->ctrl_ep) {
                ath6kl_wmi_control_rx(ar->wmi, skb);
                return;
@@ -1096,18 +1157,18 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
         * that do not have LLC hdr. They are 16 bytes in size.
         * Allow these frames in the AP mode.
         */
-       if (ar->nw_type != AP_NETWORK &&
+       if (vif->nw_type != AP_NETWORK &&
            ((packet->act_len < min_hdr_len) ||
             (packet->act_len > WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH))) {
                ath6kl_info("frame len is too short or too long\n");
-               ar->net_stats.rx_errors++;
-               ar->net_stats.rx_length_errors++;
+               vif->net_stats.rx_errors++;
+               vif->net_stats.rx_length_errors++;
                dev_kfree_skb(skb);
                return;
        }
 
        /* Get the Power save state of the STA */
-       if (ar->nw_type == AP_NETWORK) {
+       if (vif->nw_type == AP_NETWORK) {
                meta_type = wmi_data_hdr_get_meta(dhdr);
 
                ps_state = !!((dhdr->info >> WMI_DATA_HDR_PS_SHIFT) &
@@ -1129,7 +1190,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
                }
 
                datap = (struct ethhdr *) (skb->data + offset);
-               conn = ath6kl_find_sta(ar, datap->h_source);
+               conn = ath6kl_find_sta(vif, datap->h_source);
 
                if (!conn) {
                        dev_kfree_skb(skb);
@@ -1160,12 +1221,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
                                while ((skbuff = skb_dequeue(&conn->psq))
                                       != NULL) {
                                        spin_unlock_bh(&conn->psq_lock);
-                                       ath6kl_data_tx(skbuff, ar->net_dev);
+                                       ath6kl_data_tx(skbuff, vif->ndev);
                                        spin_lock_bh(&conn->psq_lock);
                                }
                                spin_unlock_bh(&conn->psq_lock);
                                /* Clear the PVB for this STA */
-                               ath6kl_wmi_set_pvb_cmd(ar->wmi, conn->aid, 0);
+                               ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx,
+                                                      conn->aid, 0);
                        }
                }
 
@@ -1215,12 +1277,12 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
                return;
        }
 
-       if (!(ar->net_dev->flags & IFF_UP)) {
+       if (!(vif->ndev->flags & IFF_UP)) {
                dev_kfree_skb(skb);
                return;
        }
 
-       if (ar->nw_type == AP_NETWORK) {
+       if (vif->nw_type == AP_NETWORK) {
                datap = (struct ethhdr *) skb->data;
                if (is_multicast_ether_addr(datap->h_dest))
                        /*
@@ -1235,8 +1297,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
                         * frame to it on the air else send the
                         * frame up the stack.
                         */
-                       struct ath6kl_sta *conn = NULL;
-                       conn = ath6kl_find_sta(ar, datap->h_dest);
+                       conn = ath6kl_find_sta(vif, datap->h_dest);
 
                        if (conn && ar->intra_bss) {
                                skb1 = skb;
@@ -1247,18 +1308,23 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
                        }
                }
                if (skb1)
-                       ath6kl_data_tx(skb1, ar->net_dev);
+                       ath6kl_data_tx(skb1, vif->ndev);
+
+               if (skb == NULL) {
+                       /* nothing to deliver up the stack */
+                       return;
+               }
        }
 
        datap = (struct ethhdr *) skb->data;
 
        if (is_unicast_ether_addr(datap->h_dest) &&
-           aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no,
+           aggr_process_recv_frm(vif->aggr_cntxt, tid, seq_no,
                                  is_amsdu, skb))
                /* aggregation code will handle the skb */
                return;
 
-       ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb);
+       ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb);
 }
 
 static void aggr_timeout(unsigned long arg)
@@ -1336,9 +1402,10 @@ static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid)
        memset(stats, 0, sizeof(struct rxtid_stats));
 }
 
-void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, u8 win_sz)
+void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no,
+                            u8 win_sz)
 {
-       struct aggr_info *p_aggr = ar->aggr_cntxt;
+       struct aggr_info *p_aggr = vif->aggr_cntxt;
        struct rxtid *rxtid;
        struct rxtid_stats *stats;
        u16 hold_q_size;
@@ -1405,9 +1472,9 @@ struct aggr_info *aggr_init(struct net_device *dev)
        return p_aggr;
 }
 
-void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid)
+void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid)
 {
-       struct aggr_info *p_aggr = ar->aggr_cntxt;
+       struct aggr_info *p_aggr = vif->aggr_cntxt;
        struct rxtid *rxtid;
 
        if (!p_aggr)
index a7de23cbd2c74db92a5a3348efe847cb88374c14..922344d3b26259b040dd8c7ec9f642d8a692f7e4 100644 (file)
@@ -21,7 +21,7 @@
 #include "../regd.h"
 #include "../regd_common.h"
 
-static int ath6kl_wmi_sync_point(struct wmi *wmi);
+static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx);
 
 static const s32 wmi_rate_tbl[][2] = {
        /* {W/O SGI, with SGI} */
@@ -81,6 +81,26 @@ enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi)
        return wmi->ep_id;
 }
 
+struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx)
+{
+       struct ath6kl_vif *vif, *found = NULL;
+
+       if (WARN_ON(if_idx > (MAX_NUM_VIF - 1)))
+               return NULL;
+
+       /* FIXME: Locking */
+       spin_lock_bh(&ar->list_lock);
+       list_for_each_entry(vif, &ar->vif_list, list) {
+               if (vif->fw_vif_idx == if_idx) {
+                       found = vif;
+                       break;
+               }
+       }
+       spin_unlock_bh(&ar->list_lock);
+
+       return found;
+}
+
 /*  Performs DIX to 802.3 encapsulation for transmit packets.
  *  Assumes the entire DIX header is contigous and that there is
  *  enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
@@ -162,12 +182,12 @@ static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb,
 int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
                            u8 msg_type, bool more_data,
                            enum wmi_data_hdr_data_type data_type,
-                           u8 meta_ver, void *tx_meta_info)
+                           u8 meta_ver, void *tx_meta_info, u8 if_idx)
 {
        struct wmi_data_hdr *data_hdr;
        int ret;
 
-       if (WARN_ON(skb == NULL))
+       if (WARN_ON(skb == NULL || (if_idx > MAX_NUM_VIF - 1)))
                return -EINVAL;
 
        if (tx_meta_info) {
@@ -189,7 +209,7 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
                    WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT;
 
        data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT);
-       data_hdr->info3 = 0;
+       data_hdr->info3 = cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK);
 
        return 0;
 }
@@ -216,7 +236,8 @@ static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri)
                return ip_pri;
 }
 
-int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb,
+int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx,
+                                      struct sk_buff *skb,
                                       u32 layer2_priority, bool wmm_enabled,
                                       u8 *ac)
 {
@@ -262,7 +283,12 @@ int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb,
                        usr_pri = layer2_priority & 0x7;
        }
 
-       /* workaround for WMM S5 */
+       /*
+        * workaround for WMM S5
+        *
+        * FIXME: wmi->traffic_class is always 100 so this test doesn't
+        * make sense
+        */
        if ((wmi->traffic_class == WMM_AC_VI) &&
            ((usr_pri == 5) || (usr_pri == 4)))
                usr_pri = 1;
@@ -284,7 +310,7 @@ int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb,
                        cpu_to_le32(WMI_IMPLICIT_PSTREAM_INACTIVITY_INT);
                /* Implicit streams are created with TSID 0xFF */
                cmd.tsid = WMI_IMPLICIT_PSTREAM;
-               ath6kl_wmi_create_pstream_cmd(wmi, &cmd);
+               ath6kl_wmi_create_pstream_cmd(wmi, if_idx, &cmd);
        }
 
        *ac = traffic_class;
@@ -410,13 +436,14 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len)
 }
 
 static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
-                                             int len)
+                                             int len, struct ath6kl_vif *vif)
 {
        struct wmi_remain_on_chnl_event *ev;
        u32 freq;
        u32 dur;
        struct ieee80211_channel *chan;
        struct ath6kl *ar = wmi->parent_dev;
+       u32 id;
 
        if (len < sizeof(*ev))
                return -EINVAL;
@@ -426,26 +453,29 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
        dur = le32_to_cpu(ev->duration);
        ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: freq=%u dur=%u\n",
                   freq, dur);
-       chan = ieee80211_get_channel(ar->wdev->wiphy, freq);
+       chan = ieee80211_get_channel(ar->wiphy, freq);
        if (!chan) {
                ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: Unknown channel "
                           "(freq=%u)\n", freq);
                return -EINVAL;
        }
-       cfg80211_ready_on_channel(ar->net_dev, 1, chan, NL80211_CHAN_NO_HT,
+       id = vif->last_roc_id;
+       cfg80211_ready_on_channel(vif->ndev, id, chan, NL80211_CHAN_NO_HT,
                                  dur, GFP_ATOMIC);
 
        return 0;
 }
 
 static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
-                                                    u8 *datap, int len)
+                                                    u8 *datap, int len,
+                                                    struct ath6kl_vif *vif)
 {
        struct wmi_cancel_remain_on_chnl_event *ev;
        u32 freq;
        u32 dur;
        struct ieee80211_channel *chan;
        struct ath6kl *ar = wmi->parent_dev;
+       u32 id;
 
        if (len < sizeof(*ev))
                return -EINVAL;
@@ -455,23 +485,29 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
        dur = le32_to_cpu(ev->duration);
        ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: freq=%u dur=%u "
                   "status=%u\n", freq, dur, ev->status);
-       chan = ieee80211_get_channel(ar->wdev->wiphy, freq);
+       chan = ieee80211_get_channel(ar->wiphy, freq);
        if (!chan) {
                ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: Unknown "
                           "channel (freq=%u)\n", freq);
                return -EINVAL;
        }
-       cfg80211_remain_on_channel_expired(ar->net_dev, 1, chan,
+       if (vif->last_cancel_roc_id &&
+           vif->last_cancel_roc_id + 1 == vif->last_roc_id)
+               id = vif->last_cancel_roc_id; /* event for cancel command */
+       else
+               id = vif->last_roc_id; /* timeout on uncanceled r-o-c */
+       vif->last_cancel_roc_id = 0;
+       cfg80211_remain_on_channel_expired(vif->ndev, id, chan,
                                           NL80211_CHAN_NO_HT, GFP_ATOMIC);
 
        return 0;
 }
 
-static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                        struct ath6kl_vif *vif)
 {
        struct wmi_tx_status_event *ev;
        u32 id;
-       struct ath6kl *ar = wmi->parent_dev;
 
        if (len < sizeof(*ev))
                return -EINVAL;
@@ -481,7 +517,7 @@ static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len)
        ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n",
                   id, ev->ack_status);
        if (wmi->last_mgmt_tx_frame) {
-               cfg80211_mgmt_tx_status(ar->net_dev, id,
+               cfg80211_mgmt_tx_status(vif->ndev, id,
                                        wmi->last_mgmt_tx_frame,
                                        wmi->last_mgmt_tx_frame_len,
                                        !!ev->ack_status, GFP_ATOMIC);
@@ -493,12 +529,12 @@ static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len)
        return 0;
 }
 
-static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                           struct ath6kl_vif *vif)
 {
        struct wmi_p2p_rx_probe_req_event *ev;
        u32 freq;
        u16 dlen;
-       struct ath6kl *ar = wmi->parent_dev;
 
        if (len < sizeof(*ev))
                return -EINVAL;
@@ -513,10 +549,10 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len)
        }
        ath6kl_dbg(ATH6KL_DBG_WMI, "rx_probe_req: len=%u freq=%u "
                   "probe_req_report=%d\n",
-                  dlen, freq, ar->probe_req_report);
+                  dlen, freq, vif->probe_req_report);
 
-       if (ar->probe_req_report || ar->nw_type == AP_NETWORK)
-               cfg80211_rx_mgmt(ar->net_dev, freq, ev->data, dlen, GFP_ATOMIC);
+       if (vif->probe_req_report || vif->nw_type == AP_NETWORK)
+               cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC);
 
        return 0;
 }
@@ -536,12 +572,12 @@ static int ath6kl_wmi_p2p_capabilities_event_rx(u8 *datap, int len)
        return 0;
 }
 
-static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                        struct ath6kl_vif *vif)
 {
        struct wmi_rx_action_event *ev;
        u32 freq;
        u16 dlen;
-       struct ath6kl *ar = wmi->parent_dev;
 
        if (len < sizeof(*ev))
                return -EINVAL;
@@ -555,7 +591,7 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len)
                return -EINVAL;
        }
        ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
-       cfg80211_rx_mgmt(ar->net_dev, freq, ev->data, dlen, GFP_ATOMIC);
+       cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC);
 
        return 0;
 }
@@ -620,7 +656,8 @@ static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size)
 }
 
 /* Send a "simple" wmi command -- one with no arguments */
-static int ath6kl_wmi_simple_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id)
+static int ath6kl_wmi_simple_cmd(struct wmi *wmi, u8 if_idx,
+                                enum wmi_cmd_id cmd_id)
 {
        struct sk_buff *skb;
        int ret;
@@ -629,7 +666,7 @@ static int ath6kl_wmi_simple_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id)
        if (!skb)
                return -ENOMEM;
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, cmd_id, NO_SYNC_WMIFLAG);
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, cmd_id, NO_SYNC_WMIFLAG);
 
        return ret;
 }
@@ -641,7 +678,6 @@ static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len)
        if (len < sizeof(struct wmi_ready_event_2))
                return -EINVAL;
 
-       wmi->ready = true;
        ath6kl_ready_event(wmi->parent_dev, ev->mac_addr,
                           le32_to_cpu(ev->sw_version),
                           le32_to_cpu(ev->abi_version));
@@ -673,32 +709,73 @@ int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi)
        cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR;
        cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS;
 
-       ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_ROAM_CTRL_CMDID, NO_SYNC_WMIFLAG);
+       ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID,
+                           NO_SYNC_WMIFLAG);
 
        return 0;
 }
 
-static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
+int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
+{
+       struct sk_buff *skb;
+       struct roam_ctrl_cmd *cmd;
+
+       skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+       if (!skb)
+               return -ENOMEM;
+
+       cmd = (struct roam_ctrl_cmd *) skb->data;
+       memset(cmd, 0, sizeof(*cmd));
+
+       memcpy(cmd->info.bssid, bssid, ETH_ALEN);
+       cmd->roam_ctrl = WMI_FORCE_ROAM;
+
+       ath6kl_dbg(ATH6KL_DBG_WMI, "force roam to %pM\n", bssid);
+       return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID,
+                                  NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
+{
+       struct sk_buff *skb;
+       struct roam_ctrl_cmd *cmd;
+
+       skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+       if (!skb)
+               return -ENOMEM;
+
+       cmd = (struct roam_ctrl_cmd *) skb->data;
+       memset(cmd, 0, sizeof(*cmd));
+
+       cmd->info.roam_mode = mode;
+       cmd->roam_ctrl = WMI_SET_ROAM_MODE;
+
+       ath6kl_dbg(ATH6KL_DBG_WMI, "set roam mode %d\n", mode);
+       return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID,
+                                  NO_SYNC_WMIFLAG);
+}
+
+static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                      struct ath6kl_vif *vif)
 {
        struct wmi_connect_event *ev;
        u8 *pie, *peie;
-       struct ath6kl *ar = wmi->parent_dev;
 
        if (len < sizeof(struct wmi_connect_event))
                return -EINVAL;
 
        ev = (struct wmi_connect_event *) datap;
 
-       if (ar->nw_type == AP_NETWORK) {
+       if (vif->nw_type == AP_NETWORK) {
                /* AP mode start/STA connected event */
-               struct net_device *dev = ar->net_dev;
+               struct net_device *dev = vif->ndev;
                if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) {
                        ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM "
                                   "(AP started)\n",
                                   __func__, le16_to_cpu(ev->u.ap_bss.ch),
                                   ev->u.ap_bss.bssid);
                        ath6kl_connect_ap_mode_bss(
-                               ar, le16_to_cpu(ev->u.ap_bss.ch));
+                               vif, le16_to_cpu(ev->u.ap_bss.ch));
                } else {
                        ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM "
                                   "auth=%u keymgmt=%u cipher=%u apsd_info=%u "
@@ -710,7 +787,7 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
                                   le16_to_cpu(ev->u.ap_sta.cipher),
                                   ev->u.ap_sta.apsd_info);
                        ath6kl_connect_ap_mode_sta(
-                               ar, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr,
+                               vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr,
                                ev->u.ap_sta.keymgmt,
                                le16_to_cpu(ev->u.ap_sta.cipher),
                                ev->u.ap_sta.auth, ev->assoc_req_len,
@@ -755,7 +832,7 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
                pie += pie[1] + 2;
        }
 
-       ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->u.sta.ch),
+       ath6kl_connect_event(vif, le16_to_cpu(ev->u.sta.ch),
                             ev->u.sta.bssid,
                             le16_to_cpu(ev->u.sta.listen_intvl),
                             le16_to_cpu(ev->u.sta.beacon_intvl),
@@ -834,14 +911,15 @@ static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
                alpha2[0] = country->isoName[0];
                alpha2[1] = country->isoName[1];
 
-               regulatory_hint(wmi->parent_dev->wdev->wiphy, alpha2);
+               regulatory_hint(wmi->parent_dev->wiphy, alpha2);
 
                ath6kl_dbg(ATH6KL_DBG_WMI, "Country alpha2 being used: %c%c\n",
                                alpha2[0], alpha2[1]);
        }
 }
 
-static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                         struct ath6kl_vif *vif)
 {
        struct wmi_disconnect_event *ev;
        wmi->traffic_class = 100;
@@ -857,10 +935,8 @@ static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len)
                   ev->disconn_reason, ev->assoc_resp_len);
 
        wmi->is_wmm_enabled = false;
-       wmi->pair_crypto_type = NONE_CRYPT;
-       wmi->grp_crypto_type = NONE_CRYPT;
 
-       ath6kl_disconnect_event(wmi->parent_dev, ev->disconn_reason,
+       ath6kl_disconnect_event(vif, ev->disconn_reason,
                                ev->bssid, ev->assoc_resp_len, ev->assoc_info,
                                le16_to_cpu(ev->proto_reason_status));
 
@@ -886,7 +962,8 @@ static int ath6kl_wmi_peer_node_event_rx(struct wmi *wmi, u8 *datap, int len)
        return 0;
 }
 
-static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                          struct ath6kl_vif *vif)
 {
        struct wmi_tkip_micerr_event *ev;
 
@@ -895,12 +972,13 @@ static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len)
 
        ev = (struct wmi_tkip_micerr_event *) datap;
 
-       ath6kl_tkip_micerr_event(wmi->parent_dev, ev->key_id, ev->is_mcast);
+       ath6kl_tkip_micerr_event(vif, ev->key_id, ev->is_mcast);
 
        return 0;
 }
 
-static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                      struct ath6kl_vif *vif)
 {
        struct wmi_bss_info_hdr2 *bih;
        u8 *buf;
@@ -927,26 +1005,27 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len)
                return 0; /* Only update BSS table for now */
 
        if (bih->frame_type == BEACON_FTYPE &&
-           test_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag)) {
-               clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
-               ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
+           test_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags)) {
+               clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
+               ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
+                                        NONE_BSS_FILTER, 0);
        }
 
-       channel = ieee80211_get_channel(ar->wdev->wiphy, le16_to_cpu(bih->ch));
+       channel = ieee80211_get_channel(ar->wiphy, le16_to_cpu(bih->ch));
        if (channel == NULL)
                return -EINVAL;
 
        if (len < 8 + 2 + 2)
                return -EINVAL;
 
-       if (bih->frame_type == BEACON_FTYPE && test_bit(CONNECTED, &ar->flag) &&
-           memcmp(bih->bssid, ar->bssid, ETH_ALEN) == 0) {
+       if (bih->frame_type == BEACON_FTYPE && test_bit(CONNECTED, &vif->flags)
+           && memcmp(bih->bssid, vif->bssid, ETH_ALEN) == 0) {
                const u8 *tim;
                tim = cfg80211_find_ie(WLAN_EID_TIM, buf + 8 + 2 + 2,
                                       len - 8 - 2 - 2);
                if (tim && tim[1] >= 2) {
-                       ar->assoc_bss_dtim_period = tim[3];
-                       set_bit(DTIM_PERIOD_AVAIL, &ar->flag);
+                       vif->assoc_bss_dtim_period = tim[3];
+                       set_bit(DTIM_PERIOD_AVAIL, &vif->flags);
                }
        }
 
@@ -966,7 +1045,7 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len)
                                                  IEEE80211_STYPE_BEACON);
                memset(mgmt->da, 0xff, ETH_ALEN);
        } else {
-               struct net_device *dev = ar->net_dev;
+               struct net_device *dev = vif->ndev;
 
                mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                                  IEEE80211_STYPE_PROBE_RESP);
@@ -979,7 +1058,7 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len)
 
        memcpy(&mgmt->u.beacon, buf, len);
 
-       bss = cfg80211_inform_bss_frame(ar->wdev->wiphy, channel, mgmt,
+       bss = cfg80211_inform_bss_frame(ar->wiphy, channel, mgmt,
                                        24 + len, (bih->snr - 95) * 100,
                                        GFP_ATOMIC);
        kfree(mgmt);
@@ -1094,20 +1173,21 @@ static int ath6kl_wmi_keepalive_reply_rx(struct wmi *wmi, u8 *datap, int len)
        return 0;
 }
 
-static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len,
+                                      struct ath6kl_vif *vif)
 {
        struct wmi_scan_complete_event *ev;
 
        ev = (struct wmi_scan_complete_event *) datap;
 
-       ath6kl_scan_complete_evt(wmi->parent_dev, a_sle32_to_cpu(ev->status));
+       ath6kl_scan_complete_evt(vif, a_sle32_to_cpu(ev->status));
        wmi->is_probe_ssid = false;
 
        return 0;
 }
 
 static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap,
-                                              int len)
+                                              int len, struct ath6kl_vif *vif)
 {
        struct wmi_neighbor_report_event *ev;
        u8 i;
@@ -1125,7 +1205,7 @@ static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap,
                ath6kl_dbg(ATH6KL_DBG_WMI, "neighbor %d/%d - %pM 0x%x\n",
                           i + 1, ev->num_neighbors, ev->neighbor[i].bssid,
                           ev->neighbor[i].bss_flags);
-               cfg80211_pmksa_candidate_notify(wmi->parent_dev->net_dev, i,
+               cfg80211_pmksa_candidate_notify(vif->ndev, i,
                                                ev->neighbor[i].bssid,
                                                !!(ev->neighbor[i].bss_flags &
                                                   WMI_PREAUTH_CAPABLE_BSS),
@@ -1166,9 +1246,10 @@ static int ath6kl_wmi_error_event_rx(struct wmi *wmi, u8 *datap, int len)
        return 0;
 }
 
-static int ath6kl_wmi_stats_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_stats_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                    struct ath6kl_vif *vif)
 {
-       ath6kl_tgt_stats_event(wmi->parent_dev, datap, len);
+       ath6kl_tgt_stats_event(vif, datap, len);
 
        return 0;
 }
@@ -1222,7 +1303,7 @@ static int ath6kl_wmi_send_rssi_threshold_params(struct wmi *wmi,
        cmd = (struct wmi_rssi_threshold_params_cmd *) skb->data;
        memcpy(cmd, rssi_cmd, sizeof(struct wmi_rssi_threshold_params_cmd));
 
-       return ath6kl_wmi_cmd_send(wmi, skb, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
+       return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
 
@@ -1322,7 +1403,8 @@ static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap,
        return 0;
 }
 
-static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                  struct ath6kl_vif *vif)
 {
        struct wmi_cac_event *reply;
        struct ieee80211_tspec_ie *ts;
@@ -1343,7 +1425,8 @@ static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len)
                tsid = (tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
                        IEEE80211_WMM_IE_TSPEC_TID_MASK;
 
-               ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, tsid);
+               ath6kl_wmi_delete_pstream_cmd(wmi, vif->fw_vif_idx,
+                                             reply->ac, tsid);
        } else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
                /*
                 * Following assumes that there is only one outstanding
@@ -1358,7 +1441,8 @@ static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len)
                                break;
                }
                if (index < (sizeof(active_tsids) * 8))
-                       ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, index);
+                       ath6kl_wmi_delete_pstream_cmd(wmi, vif->fw_vif_idx,
+                                                     reply->ac, index);
        }
 
        /*
@@ -1403,7 +1487,7 @@ static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi,
        cmd = (struct wmi_snr_threshold_params_cmd *) skb->data;
        memcpy(cmd, snr_cmd, sizeof(struct wmi_snr_threshold_params_cmd));
 
-       return ath6kl_wmi_cmd_send(wmi, skb, WMI_SNR_THRESHOLD_PARAMS_CMDID,
+       return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SNR_THRESHOLD_PARAMS_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
 
@@ -1528,14 +1612,15 @@ static int ath6kl_wmi_aplist_event_rx(struct wmi *wmi, u8 *datap, int len)
        return 0;
 }
 
-int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
+int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
                        enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag)
 {
        struct wmi_cmd_hdr *cmd_hdr;
        enum htc_endpoint_id ep_id = wmi->ep_id;
        int ret;
+       u16 info1;
 
-       if (WARN_ON(skb == NULL))
+       if (WARN_ON(skb == NULL || (if_idx > (MAX_NUM_VIF - 1))))
                return -EINVAL;
 
        ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n",
@@ -1554,19 +1639,20 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
                 * Make sure all data currently queued is transmitted before
                 * the cmd execution.  Establish a new sync point.
                 */
-               ath6kl_wmi_sync_point(wmi);
+               ath6kl_wmi_sync_point(wmi, if_idx);
        }
 
        skb_push(skb, sizeof(struct wmi_cmd_hdr));
 
        cmd_hdr = (struct wmi_cmd_hdr *) skb->data;
        cmd_hdr->cmd_id = cpu_to_le16(cmd_id);
-       cmd_hdr->info1 = 0;     /* added for virtual interface */
+       info1 = if_idx & WMI_CMD_HDR_IF_ID_MASK;
+       cmd_hdr->info1 = cpu_to_le16(info1);
 
        /* Only for OPT_TX_CMD, use BE endpoint. */
        if (cmd_id == WMI_OPT_TX_FRAME_CMDID) {
                ret = ath6kl_wmi_data_hdr_add(wmi, skb, OPT_MSGTYPE,
-                                             false, false, 0, NULL);
+                                             false, false, 0, NULL, if_idx);
                if (ret) {
                        dev_kfree_skb(skb);
                        return ret;
@@ -1582,13 +1668,14 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
                 * Make sure all new data queued waits for the command to
                 * execute. Establish a new sync point.
                 */
-               ath6kl_wmi_sync_point(wmi);
+               ath6kl_wmi_sync_point(wmi, if_idx);
        }
 
        return 0;
 }
 
-int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
+int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
+                          enum network_type nw_type,
                           enum dot11_auth_mode dot11_auth_mode,
                           enum auth_mode auth_mode,
                           enum crypto_type pairwise_crypto,
@@ -1639,15 +1726,14 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
        if (bssid != NULL)
                memcpy(cc->bssid, bssid, ETH_ALEN);
 
-       wmi->pair_crypto_type = pairwise_crypto;
-       wmi->grp_crypto_type = group_crypto;
-
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG);
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_CONNECT_CMDID,
+                                 NO_SYNC_WMIFLAG);
 
        return ret;
 }
 
-int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel)
+int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid,
+                            u16 channel)
 {
        struct sk_buff *skb;
        struct wmi_reconnect_cmd *cc;
@@ -1668,13 +1754,13 @@ int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel)
        if (bssid != NULL)
                memcpy(cc->bssid, bssid, ETH_ALEN);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RECONNECT_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_RECONNECT_CMDID,
                                  NO_SYNC_WMIFLAG);
 
        return ret;
 }
 
-int ath6kl_wmi_disconnect_cmd(struct wmi *wmi)
+int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx)
 {
        int ret;
 
@@ -1683,12 +1769,13 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi)
        wmi->traffic_class = 100;
 
        /* Disconnect command does not need to do a SYNC before. */
-       ret = ath6kl_wmi_simple_cmd(wmi, WMI_DISCONNECT_CMDID);
+       ret = ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_DISCONNECT_CMDID);
 
        return ret;
 }
 
-int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type,
+int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
+                            enum wmi_scan_type scan_type,
                             u32 force_fgscan, u32 is_legacy,
                             u32 home_dwell_time, u32 force_scan_interval,
                             s8 num_chan, u16 *ch_list)
@@ -1724,13 +1811,14 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type,
        for (i = 0; i < num_chan; i++)
                sc->ch_list[i] = cpu_to_le16(ch_list[i]);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_START_SCAN_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID,
                                  NO_SYNC_WMIFLAG);
 
        return ret;
 }
 
-int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec,
+int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx,
+                             u16 fg_start_sec,
                              u16 fg_end_sec, u16 bg_sec,
                              u16 minact_chdw_msec, u16 maxact_chdw_msec,
                              u16 pas_chdw_msec, u8 short_scan_ratio,
@@ -1757,12 +1845,12 @@ int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec,
        sc->max_dfsch_act_time = cpu_to_le32(max_dfsch_act_time);
        sc->maxact_scan_per_ssid = cpu_to_le16(maxact_scan_per_ssid);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_SCAN_PARAMS_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_SCAN_PARAMS_CMDID,
                                  NO_SYNC_WMIFLAG);
        return ret;
 }
 
-int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask)
+int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 if_idx, u8 filter, u32 ie_mask)
 {
        struct sk_buff *skb;
        struct wmi_bss_filter_cmd *cmd;
@@ -1779,12 +1867,12 @@ int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask)
        cmd->bss_filter = filter;
        cmd->ie_mask = cpu_to_le32(ie_mask);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_BSS_FILTER_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_BSS_FILTER_CMDID,
                                  NO_SYNC_WMIFLAG);
        return ret;
 }
 
-int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag,
+int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
                              u8 ssid_len, u8 *ssid)
 {
        struct sk_buff *skb;
@@ -1816,12 +1904,13 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag,
        cmd->ssid_len = ssid_len;
        memcpy(cmd->ssid, ssid, ssid_len);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PROBED_SSID_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_PROBED_SSID_CMDID,
                                  NO_SYNC_WMIFLAG);
        return ret;
 }
 
-int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval,
+int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
+                                 u16 listen_interval,
                                  u16 listen_beacons)
 {
        struct sk_buff *skb;
@@ -1836,12 +1925,12 @@ int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval,
        cmd->listen_intvl = cpu_to_le16(listen_interval);
        cmd->num_beacons = cpu_to_le16(listen_beacons);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LISTEN_INT_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_LISTEN_INT_CMDID,
                                  NO_SYNC_WMIFLAG);
        return ret;
 }
 
-int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode)
+int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode)
 {
        struct sk_buff *skb;
        struct wmi_power_mode_cmd *cmd;
@@ -1855,12 +1944,12 @@ int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode)
        cmd->pwr_mode = pwr_mode;
        wmi->pwr_mode = pwr_mode;
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_MODE_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_POWER_MODE_CMDID,
                                  NO_SYNC_WMIFLAG);
        return ret;
 }
 
-int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period,
+int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u8 if_idx, u16 idle_period,
                            u16 ps_poll_num, u16 dtim_policy,
                            u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
                            u16 ps_fail_event_policy)
@@ -1881,12 +1970,12 @@ int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period,
        pm->num_tx_to_wakeup = cpu_to_le16(num_tx_to_wakeup);
        pm->ps_fail_event_policy = cpu_to_le16(ps_fail_event_policy);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_PARAMS_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_POWER_PARAMS_CMDID,
                                  NO_SYNC_WMIFLAG);
        return ret;
 }
 
-int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout)
+int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 if_idx, u8 timeout)
 {
        struct sk_buff *skb;
        struct wmi_disc_timeout_cmd *cmd;
@@ -1899,15 +1988,20 @@ int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout)
        cmd = (struct wmi_disc_timeout_cmd *) skb->data;
        cmd->discon_timeout = timeout;
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_DISC_TIMEOUT_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_DISC_TIMEOUT_CMDID,
                                  NO_SYNC_WMIFLAG);
+
+       if (ret == 0)
+               ath6kl_debug_set_disconnect_timeout(wmi->parent_dev, timeout);
+
        return ret;
 }
 
-int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
+int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index,
                          enum crypto_type key_type,
                          u8 key_usage, u8 key_len,
-                         u8 *key_rsc, u8 *key_material,
+                         u8 *key_rsc, unsigned int key_rsc_len,
+                         u8 *key_material,
                          u8 key_op_ctrl, u8 *mac_addr,
                          enum wmi_sync_flag sync_flag)
 {
@@ -1920,7 +2014,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
                   key_index, key_type, key_usage, key_len, key_op_ctrl);
 
        if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) ||
-           (key_material == NULL))
+           (key_material == NULL) || key_rsc_len > 8)
                return -EINVAL;
 
        if ((WEP_CRYPT != key_type) && (NULL == key_rsc))
@@ -1938,20 +2032,20 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
        memcpy(cmd->key, key_material, key_len);
 
        if (key_rsc != NULL)
-               memcpy(cmd->key_rsc, key_rsc, sizeof(cmd->key_rsc));
+               memcpy(cmd->key_rsc, key_rsc, key_rsc_len);
 
        cmd->key_op_ctrl = key_op_ctrl;
 
        if (mac_addr)
                memcpy(cmd->key_mac_addr, mac_addr, ETH_ALEN);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_CIPHER_KEY_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_ADD_CIPHER_KEY_CMDID,
                                  sync_flag);
 
        return ret;
 }
 
-int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk)
+int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk)
 {
        struct sk_buff *skb;
        struct wmi_add_krk_cmd *cmd;
@@ -1964,12 +2058,13 @@ int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk)
        cmd = (struct wmi_add_krk_cmd *) skb->data;
        memcpy(cmd->krk, krk, WMI_KRK_LEN);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG);
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_ADD_KRK_CMDID,
+                                 NO_SYNC_WMIFLAG);
 
        return ret;
 }
 
-int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index)
+int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index)
 {
        struct sk_buff *skb;
        struct wmi_delete_cipher_key_cmd *cmd;
@@ -1985,13 +2080,13 @@ int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index)
        cmd = (struct wmi_delete_cipher_key_cmd *) skb->data;
        cmd->key_index = key_index;
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_CIPHER_KEY_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_DELETE_CIPHER_KEY_CMDID,
                                  NO_SYNC_WMIFLAG);
 
        return ret;
 }
 
-int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid,
+int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid,
                            const u8 *pmkid, bool set)
 {
        struct sk_buff *skb;
@@ -2018,14 +2113,14 @@ int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid,
                cmd->enable = PMKID_DISABLE;
        }
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PMKID_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_PMKID_CMDID,
                                  NO_SYNC_WMIFLAG);
 
        return ret;
 }
 
 static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
-                             enum htc_endpoint_id ep_id)
+                             enum htc_endpoint_id ep_id, u8 if_idx)
 {
        struct wmi_data_hdr *data_hdr;
        int ret;
@@ -2037,14 +2132,14 @@ static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
 
        data_hdr = (struct wmi_data_hdr *) skb->data;
        data_hdr->info = SYNC_MSGTYPE << WMI_DATA_HDR_MSG_TYPE_SHIFT;
-       data_hdr->info3 = 0;
+       data_hdr->info3 = cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK);
 
        ret = ath6kl_control_tx(wmi->parent_dev, skb, ep_id);
 
        return ret;
 }
 
-static int ath6kl_wmi_sync_point(struct wmi *wmi)
+static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
 {
        struct sk_buff *skb;
        struct wmi_sync_cmd *cmd;
@@ -2100,7 +2195,7 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi)
         * Send sync cmd followed by sync data messages on all
         * endpoints being used
         */
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SYNCHRONIZE_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SYNCHRONIZE_CMDID,
                                  NO_SYNC_WMIFLAG);
 
        if (ret)
@@ -2119,7 +2214,7 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi)
                                               traffic_class);
                ret =
                    ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb,
-                                             ep_id);
+                                             ep_id, if_idx);
 
                if (ret)
                        break;
@@ -2142,7 +2237,7 @@ free_skb:
        return ret;
 }
 
-int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi,
+int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi, u8 if_idx,
                                  struct wmi_create_pstream_cmd *params)
 {
        struct sk_buff *skb;
@@ -2231,12 +2326,13 @@ int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi,
                ath6kl_indicate_tx_activity(wmi->parent_dev,
                                            params->traffic_class, true);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CREATE_PSTREAM_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_CREATE_PSTREAM_CMDID,
                                  NO_SYNC_WMIFLAG);
        return ret;
 }
 
-int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid)
+int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class,
+                                 u8 tsid)
 {
        struct sk_buff *skb;
        struct wmi_delete_pstream_cmd *cmd;
@@ -2272,7 +2368,7 @@ int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid)
                   "sending delete_pstream_cmd: traffic class: %d tsid=%d\n",
                   traffic_class, tsid);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_PSTREAM_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_DELETE_PSTREAM_CMDID,
                                  SYNC_BEFORE_WMIFLAG);
 
        spin_lock_bh(&wmi->lock);
@@ -2311,17 +2407,173 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd)
        cmd = (struct wmi_set_ip_cmd *) skb->data;
        memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd));
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_IP_CMDID, NO_SYNC_WMIFLAG);
+       ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_IP_CMDID,
+                                 NO_SYNC_WMIFLAG);
+       return ret;
+}
+
+static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
+{
+       u16 active_tsids;
+       u8 stream_exist;
+       int i;
+
+       /*
+        * Relinquish credits from all implicitly created pstreams
+        * since when we go to sleep. If user created explicit
+        * thinstreams exists with in a fatpipe leave them intact
+        * for the user to delete.
+        */
+       spin_lock_bh(&wmi->lock);
+       stream_exist = wmi->fat_pipe_exist;
+       spin_unlock_bh(&wmi->lock);
+
+       for (i = 0; i < WMM_NUM_AC; i++) {
+               if (stream_exist & (1 << i)) {
+
+                       /*
+                        * FIXME: Is this lock & unlock inside
+                        * for loop correct? may need rework.
+                        */
+                       spin_lock_bh(&wmi->lock);
+                       active_tsids = wmi->stream_exist_for_ac[i];
+                       spin_unlock_bh(&wmi->lock);
+
+                       /*
+                        * If there are no user created thin streams
+                        * delete the fatpipe
+                        */
+                       if (!active_tsids) {
+                               stream_exist &= ~(1 << i);
+                               /*
+                                * Indicate inactivity to driver layer for
+                                * this fatpipe (pstream)
+                                */
+                               ath6kl_indicate_tx_activity(wmi->parent_dev,
+                                                           i, false);
+                       }
+               }
+       }
+
+       /* FIXME: Can we do this assignment without locking ? */
+       spin_lock_bh(&wmi->lock);
+       wmi->fat_pipe_exist = stream_exist;
+       spin_unlock_bh(&wmi->lock);
+}
+
+int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
+                                      enum ath6kl_host_mode host_mode)
+{
+       struct sk_buff *skb;
+       struct wmi_set_host_sleep_mode_cmd *cmd;
+       int ret;
+
+       if ((host_mode != ATH6KL_HOST_MODE_ASLEEP) &&
+           (host_mode != ATH6KL_HOST_MODE_AWAKE)) {
+               ath6kl_err("invalid host sleep mode: %d\n", host_mode);
+               return -EINVAL;
+       }
+
+       skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+       if (!skb)
+               return -ENOMEM;
+
+       cmd = (struct wmi_set_host_sleep_mode_cmd *) skb->data;
+
+       if (host_mode == ATH6KL_HOST_MODE_ASLEEP) {
+               ath6kl_wmi_relinquish_implicit_pstream_credits(wmi);
+               cmd->asleep = cpu_to_le32(1);
+       } else
+               cmd->awake = cpu_to_le32(1);
+
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+                                 WMI_SET_HOST_SLEEP_MODE_CMDID,
+                                 NO_SYNC_WMIFLAG);
        return ret;
 }
 
-static int ath6kl_wmi_get_wow_list_event_rx(struct wmi *wmi, u8 * datap,
-                                           int len)
+int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
+                               enum ath6kl_wow_mode wow_mode,
+                               u32 filter, u16 host_req_delay)
 {
-       if (len < sizeof(struct wmi_get_wow_list_reply))
+       struct sk_buff *skb;
+       struct wmi_set_wow_mode_cmd *cmd;
+       int ret;
+
+       if ((wow_mode != ATH6KL_WOW_MODE_ENABLE) &&
+            wow_mode != ATH6KL_WOW_MODE_DISABLE) {
+               ath6kl_err("invalid wow mode: %d\n", wow_mode);
                return -EINVAL;
+       }
 
-       return 0;
+       skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+       if (!skb)
+               return -ENOMEM;
+
+       cmd = (struct wmi_set_wow_mode_cmd *) skb->data;
+       cmd->enable_wow = cpu_to_le32(wow_mode);
+       cmd->filter = cpu_to_le32(filter);
+       cmd->host_req_delay = cpu_to_le16(host_req_delay);
+
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_WOW_MODE_CMDID,
+                                 NO_SYNC_WMIFLAG);
+       return ret;
+}
+
+int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
+                                  u8 list_id, u8 filter_size,
+                                  u8 filter_offset, u8 *filter, u8 *mask)
+{
+       struct sk_buff *skb;
+       struct wmi_add_wow_pattern_cmd *cmd;
+       u16 size;
+       u8 *filter_mask;
+       int ret;
+
+       /*
+        * Allocate additional memory in the buffer to hold
+        * filter and mask value, which is twice of filter_size.
+        */
+       size = sizeof(*cmd) + (2 * filter_size);
+
+       skb = ath6kl_wmi_get_new_buf(size);
+       if (!skb)
+               return -ENOMEM;
+
+       cmd = (struct wmi_add_wow_pattern_cmd *) skb->data;
+       cmd->filter_list_id = list_id;
+       cmd->filter_size = filter_size;
+       cmd->filter_offset = filter_offset;
+
+       memcpy(cmd->filter, filter, filter_size);
+
+       filter_mask = (u8 *) (cmd->filter + filter_size);
+       memcpy(filter_mask, mask, filter_size);
+
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_ADD_WOW_PATTERN_CMDID,
+                                 NO_SYNC_WMIFLAG);
+
+       return ret;
+}
+
+int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
+                                  u16 list_id, u16 filter_id)
+{
+       struct sk_buff *skb;
+       struct wmi_del_wow_pattern_cmd *cmd;
+       int ret;
+
+       skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+       if (!skb)
+               return -ENOMEM;
+
+       cmd = (struct wmi_del_wow_pattern_cmd *) skb->data;
+       cmd->filter_list_id = cpu_to_le16(list_id);
+       cmd->filter_id = cpu_to_le16(filter_id);
+
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_DEL_WOW_PATTERN_CMDID,
+                                 NO_SYNC_WMIFLAG);
+       return ret;
 }
 
 static int ath6kl_wmi_cmd_send_xtnd(struct wmi *wmi, struct sk_buff *skb,
@@ -2336,7 +2588,7 @@ static int ath6kl_wmi_cmd_send_xtnd(struct wmi *wmi, struct sk_buff *skb,
        cmd_hdr = (struct wmix_cmd_hdr *) skb->data;
        cmd_hdr->cmd_id = cpu_to_le32(cmd_id);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_EXTENSION_CMDID, sync_flag);
+       ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_EXTENSION_CMDID, sync_flag);
 
        return ret;
 }
@@ -2379,12 +2631,12 @@ int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config)
        return ret;
 }
 
-int ath6kl_wmi_get_stats_cmd(struct wmi *wmi)
+int ath6kl_wmi_get_stats_cmd(struct wmi *wmi, u8 if_idx)
 {
-       return ath6kl_wmi_simple_cmd(wmi, WMI_GET_STATISTICS_CMDID);
+       return ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_GET_STATISTICS_CMDID);
 }
 
-int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM)
+int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 if_idx, u8 dbM)
 {
        struct sk_buff *skb;
        struct wmi_set_tx_pwr_cmd *cmd;
@@ -2397,18 +2649,24 @@ int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM)
        cmd = (struct wmi_set_tx_pwr_cmd *) skb->data;
        cmd->dbM = dbM;
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_TX_PWR_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_TX_PWR_CMDID,
                                  NO_SYNC_WMIFLAG);
 
        return ret;
 }
 
-int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi)
+int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi, u8 if_idx)
 {
-       return ath6kl_wmi_simple_cmd(wmi, WMI_GET_TX_PWR_CMDID);
+       return ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_GET_TX_PWR_CMDID);
 }
 
-int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, u8 preamble_policy)
+int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi)
+{
+       return ath6kl_wmi_simple_cmd(wmi, 0, WMI_GET_ROAM_TBL_CMDID);
+}
+
+int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 if_idx, u8 status,
+                                u8 preamble_policy)
 {
        struct sk_buff *skb;
        struct wmi_set_lpreamble_cmd *cmd;
@@ -2422,7 +2680,7 @@ int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, u8 preamble_policy)
        cmd->status = status;
        cmd->preamble_policy = preamble_policy;
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LPREAMBLE_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_LPREAMBLE_CMDID,
                                  NO_SYNC_WMIFLAG);
        return ret;
 }
@@ -2440,11 +2698,12 @@ int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold)
        cmd = (struct wmi_set_rts_cmd *) skb->data;
        cmd->threshold = cpu_to_le16(threshold);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_RTS_CMDID, NO_SYNC_WMIFLAG);
+       ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_RTS_CMDID,
+                                 NO_SYNC_WMIFLAG);
        return ret;
 }
 
-int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg)
+int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg)
 {
        struct sk_buff *skb;
        struct wmi_set_wmm_txop_cmd *cmd;
@@ -2460,12 +2719,13 @@ int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg)
        cmd = (struct wmi_set_wmm_txop_cmd *) skb->data;
        cmd->txop_enable = cfg;
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_WMM_TXOP_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_WMM_TXOP_CMDID,
                                  NO_SYNC_WMIFLAG);
        return ret;
 }
 
-int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl)
+int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx,
+                                u8 keep_alive_intvl)
 {
        struct sk_buff *skb;
        struct wmi_set_keepalive_cmd *cmd;
@@ -2477,10 +2737,13 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl)
 
        cmd = (struct wmi_set_keepalive_cmd *) skb->data;
        cmd->keep_alive_intvl = keep_alive_intvl;
-       wmi->keep_alive_intvl = keep_alive_intvl;
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_KEEPALIVE_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_KEEPALIVE_CMDID,
                                  NO_SYNC_WMIFLAG);
+
+       if (ret == 0)
+               ath6kl_debug_set_keepalive(wmi->parent_dev, keep_alive_intvl);
+
        return ret;
 }
 
@@ -2495,7 +2758,7 @@ int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len)
 
        memcpy(skb->data, buf, len);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_TEST_CMDID, NO_SYNC_WMIFLAG);
+       ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_TEST_CMDID, NO_SYNC_WMIFLAG);
 
        return ret;
 }
@@ -2528,28 +2791,31 @@ static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
        return 0;
 }
 
-static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                        struct ath6kl_vif *vif)
 {
        struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap;
 
-       aggr_recv_addba_req_evt(wmi->parent_dev, cmd->tid,
+       aggr_recv_addba_req_evt(vif, cmd->tid,
                                le16_to_cpu(cmd->st_seq_no), cmd->win_sz);
 
        return 0;
 }
 
-static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                        struct ath6kl_vif *vif)
 {
        struct wmi_delba_event *cmd = (struct wmi_delba_event *) datap;
 
-       aggr_recv_delba_req_evt(wmi->parent_dev, cmd->tid);
+       aggr_recv_delba_req_evt(vif, cmd->tid);
 
        return 0;
 }
 
 /*  AP mode functions */
 
-int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p)
+int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx,
+                                struct wmi_connect_cmd *p)
 {
        struct sk_buff *skb;
        struct wmi_connect_cmd *cm;
@@ -2562,7 +2828,7 @@ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p)
        cm = (struct wmi_connect_cmd *) skb->data;
        memcpy(cm, p, sizeof(*cm));
 
-       res = ath6kl_wmi_cmd_send(wmip, skb, WMI_AP_CONFIG_COMMIT_CMDID,
+       res = ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_CONFIG_COMMIT_CMDID,
                                  NO_SYNC_WMIFLAG);
        ath6kl_dbg(ATH6KL_DBG_WMI, "%s: nw_type=%u auth_mode=%u ch=%u "
                   "ctrl_flags=0x%x-> res=%d\n",
@@ -2571,7 +2837,8 @@ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p)
        return res;
 }
 
-int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason)
+int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac,
+                          u16 reason)
 {
        struct sk_buff *skb;
        struct wmi_ap_set_mlme_cmd *cm;
@@ -2585,11 +2852,12 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason)
        cm->reason = cpu_to_le16(reason);
        cm->cmd = cmd;
 
-       return ath6kl_wmi_cmd_send(wmip, skb, WMI_AP_SET_MLME_CMDID,
+       return ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_SET_MLME_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
 
-static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                     struct ath6kl_vif *vif)
 {
        struct wmi_pspoll_event *ev;
 
@@ -2598,19 +2866,21 @@ static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len)
 
        ev = (struct wmi_pspoll_event *) datap;
 
-       ath6kl_pspoll_event(wmi->parent_dev, le16_to_cpu(ev->aid));
+       ath6kl_pspoll_event(vif, le16_to_cpu(ev->aid));
 
        return 0;
 }
 
-static int ath6kl_wmi_dtimexpiry_event_rx(struct wmi *wmi, u8 *datap, int len)
+static int ath6kl_wmi_dtimexpiry_event_rx(struct wmi *wmi, u8 *datap, int len,
+                                         struct ath6kl_vif *vif)
 {
-       ath6kl_dtimexpiry_event(wmi->parent_dev);
+       ath6kl_dtimexpiry_event(vif);
 
        return 0;
 }
 
-int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag)
+int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u8 if_idx, u16 aid,
+                          bool flag)
 {
        struct sk_buff *skb;
        struct wmi_ap_set_pvb_cmd *cmd;
@@ -2625,13 +2895,14 @@ int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag)
        cmd->rsvd = cpu_to_le16(0);
        cmd->flag = cpu_to_le32(flag);
 
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_AP_SET_PVB_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_SET_PVB_CMDID,
                                  NO_SYNC_WMIFLAG);
 
        return 0;
 }
 
-int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver,
+int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 if_idx,
+                                      u8 rx_meta_ver,
                                       bool rx_dot11_hdr, bool defrag_on_host)
 {
        struct sk_buff *skb;
@@ -2648,14 +2919,14 @@ int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver,
        cmd->meta_ver = rx_meta_ver;
 
        /* Delete the local aggr state, on host */
-       ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RX_FRAME_FORMAT_CMDID,
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_RX_FRAME_FORMAT_CMDID,
                                  NO_SYNC_WMIFLAG);
 
        return ret;
 }
 
-int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie,
-                            u8 ie_len)
+int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
+                            const u8 *ie, u8 ie_len)
 {
        struct sk_buff *skb;
        struct wmi_set_appie_cmd *p;
@@ -2670,7 +2941,7 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie,
        p->mgmt_frm_type = mgmt_frm_type;
        p->ie_len = ie_len;
        memcpy(p->ie_info, ie, ie_len);
-       return ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_APPIE_CMDID,
+       return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_APPIE_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
 
@@ -2688,11 +2959,11 @@ int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable)
        cmd = (struct wmi_disable_11b_rates_cmd *) skb->data;
        cmd->disable = disable ? 1 : 0;
 
-       return ath6kl_wmi_cmd_send(wmi, skb, WMI_DISABLE_11B_RATES_CMDID,
+       return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_DISABLE_11B_RATES_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
 
-int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur)
+int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq, u32 dur)
 {
        struct sk_buff *skb;
        struct wmi_remain_on_chnl_cmd *p;
@@ -2706,12 +2977,12 @@ int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur)
        p = (struct wmi_remain_on_chnl_cmd *) skb->data;
        p->freq = cpu_to_le32(freq);
        p->duration = cpu_to_le32(dur);
-       return ath6kl_wmi_cmd_send(wmi, skb, WMI_REMAIN_ON_CHNL_CMDID,
+       return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_REMAIN_ON_CHNL_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
 
-int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait,
-                              const u8 *data, u16 data_len)
+int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
+                              u32 wait, const u8 *data, u16 data_len)
 {
        struct sk_buff *skb;
        struct wmi_send_action_cmd *p;
@@ -2731,6 +3002,7 @@ int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait,
        }
 
        kfree(wmi->last_mgmt_tx_frame);
+       memcpy(buf, data, data_len);
        wmi->last_mgmt_tx_frame = buf;
        wmi->last_mgmt_tx_frame_len = data_len;
 
@@ -2742,13 +3014,13 @@ int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait,
        p->wait = cpu_to_le32(wait);
        p->len = cpu_to_le16(data_len);
        memcpy(p->data, data, data_len);
-       return ath6kl_wmi_cmd_send(wmi, skb, WMI_SEND_ACTION_CMDID,
+       return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SEND_ACTION_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
 
-int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq,
-                                      const u8 *dst,
-                                      const u8 *data, u16 data_len)
+int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
+                                      const u8 *dst, const u8 *data,
+                                      u16 data_len)
 {
        struct sk_buff *skb;
        struct wmi_p2p_probe_response_cmd *p;
@@ -2764,11 +3036,12 @@ int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq,
        memcpy(p->destination_addr, dst, ETH_ALEN);
        p->len = cpu_to_le16(data_len);
        memcpy(p->data, data, data_len);
-       return ath6kl_wmi_cmd_send(wmi, skb, WMI_SEND_PROBE_RESPONSE_CMDID,
+       return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+                                  WMI_SEND_PROBE_RESPONSE_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
 
-int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable)
+int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, u8 if_idx, bool enable)
 {
        struct sk_buff *skb;
        struct wmi_probe_req_report_cmd *p;
@@ -2781,11 +3054,11 @@ int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable)
                   enable);
        p = (struct wmi_probe_req_report_cmd *) skb->data;
        p->enable = enable ? 1 : 0;
-       return ath6kl_wmi_cmd_send(wmi, skb, WMI_PROBE_REQ_REPORT_CMDID,
+       return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_PROBE_REQ_REPORT_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
 
-int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags)
+int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u8 if_idx, u32 info_req_flags)
 {
        struct sk_buff *skb;
        struct wmi_get_p2p_info *p;
@@ -2798,14 +3071,15 @@ int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags)
                   info_req_flags);
        p = (struct wmi_get_p2p_info *) skb->data;
        p->info_req_flags = cpu_to_le32(info_req_flags);
-       return ath6kl_wmi_cmd_send(wmi, skb, WMI_GET_P2P_INFO_CMDID,
+       return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_GET_P2P_INFO_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
 
-int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi)
+int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx)
 {
        ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl_cmd\n");
-       return ath6kl_wmi_simple_cmd(wmi, WMI_CANCEL_REMAIN_ON_CHNL_CMDID);
+       return ath6kl_wmi_simple_cmd(wmi, if_idx,
+                                    WMI_CANCEL_REMAIN_ON_CHNL_CMDID);
 }
 
 static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
@@ -2818,7 +3092,6 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
 
        if (skb->len < sizeof(struct wmix_cmd_hdr)) {
                ath6kl_err("bad packet 1\n");
-               wmi->stat.cmd_len_err++;
                return -EINVAL;
        }
 
@@ -2840,7 +3113,6 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
                break;
        default:
                ath6kl_warn("unknown cmd id 0x%x\n", id);
-               wmi->stat.cmd_id_err++;
                ret = -EINVAL;
                break;
        }
@@ -2848,12 +3120,19 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
        return ret;
 }
 
+static int ath6kl_wmi_roam_tbl_event_rx(struct wmi *wmi, u8 *datap, int len)
+{
+       return ath6kl_debug_roam_tbl_event(wmi->parent_dev, datap, len);
+}
+
 /* Control Path */
 int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
 {
        struct wmi_cmd_hdr *cmd;
+       struct ath6kl_vif *vif;
        u32 len;
        u16 id;
+       u8 if_idx;
        u8 *datap;
        int ret = 0;
 
@@ -2863,12 +3142,12 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
        if (skb->len < sizeof(struct wmi_cmd_hdr)) {
                ath6kl_err("bad packet 1\n");
                dev_kfree_skb(skb);
-               wmi->stat.cmd_len_err++;
                return -EINVAL;
        }
 
        cmd = (struct wmi_cmd_hdr *) skb->data;
        id = le16_to_cpu(cmd->cmd_id);
+       if_idx = le16_to_cpu(cmd->info1) & WMI_CMD_HDR_IF_ID_MASK;
 
        skb_pull(skb, sizeof(struct wmi_cmd_hdr));
 
@@ -2879,6 +3158,15 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
        ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi rx ",
                        datap, len);
 
+       vif = ath6kl_get_vif_by_index(wmi->parent_dev, if_idx);
+       if (!vif) {
+               ath6kl_dbg(ATH6KL_DBG_WMI,
+                          "Wmi event for unavailable vif, vif_index:%d\n",
+                           if_idx);
+               dev_kfree_skb(skb);
+               return -EINVAL;
+       }
+
        switch (id) {
        case WMI_GET_BITRATE_CMDID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n");
@@ -2898,11 +3186,11 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        case WMI_CONNECT_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n");
-               ret = ath6kl_wmi_connect_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_connect_event_rx(wmi, datap, len, vif);
                break;
        case WMI_DISCONNECT_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n");
-               ret = ath6kl_wmi_disconnect_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_disconnect_event_rx(wmi, datap, len, vif);
                break;
        case WMI_PEER_NODE_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n");
@@ -2910,11 +3198,11 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        case WMI_TKIP_MICERR_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n");
-               ret = ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len, vif);
                break;
        case WMI_BSSINFO_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n");
-               ret = ath6kl_wmi_bssinfo_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_bssinfo_event_rx(wmi, datap, len, vif);
                break;
        case WMI_REGDOMAIN_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n");
@@ -2926,11 +3214,12 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        case WMI_NEIGHBOR_REPORT_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n");
-               ret = ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len,
+                                                         vif);
                break;
        case WMI_SCAN_COMPLETE_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n");
-               ret = ath6kl_wmi_scan_complete_rx(wmi, datap, len);
+               ret = ath6kl_wmi_scan_complete_rx(wmi, datap, len, vif);
                break;
        case WMI_CMDERROR_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n");
@@ -2938,7 +3227,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        case WMI_REPORT_STATISTICS_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n");
-               ret = ath6kl_wmi_stats_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_stats_event_rx(wmi, datap, len, vif);
                break;
        case WMI_RSSI_THRESHOLD_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n");
@@ -2953,6 +3242,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        case WMI_REPORT_ROAM_TBL_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n");
+               ret = ath6kl_wmi_roam_tbl_event_rx(wmi, datap, len);
                break;
        case WMI_EXTENSION_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n");
@@ -2960,7 +3250,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        case WMI_CAC_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n");
-               ret = ath6kl_wmi_cac_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_cac_event_rx(wmi, datap, len, vif);
                break;
        case WMI_CHANNEL_CHANGE_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n");
@@ -2996,7 +3286,6 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        case WMI_GET_WOW_LIST_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_WOW_LIST_EVENTID\n");
-               ret = ath6kl_wmi_get_wow_list_event_rx(wmi, datap, len);
                break;
        case WMI_GET_PMKID_LIST_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n");
@@ -3004,25 +3293,25 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        case WMI_PSPOLL_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n");
-               ret = ath6kl_wmi_pspoll_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_pspoll_event_rx(wmi, datap, len, vif);
                break;
        case WMI_DTIMEXPIRY_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n");
-               ret = ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len, vif);
                break;
        case WMI_SET_PARAMS_REPLY_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n");
                break;
        case WMI_ADDBA_REQ_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n");
-               ret = ath6kl_wmi_addba_req_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_addba_req_event_rx(wmi, datap, len, vif);
                break;
        case WMI_ADDBA_RESP_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n");
                break;
        case WMI_DELBA_REQ_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n");
-               ret = ath6kl_wmi_delba_req_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_delba_req_event_rx(wmi, datap, len, vif);
                break;
        case WMI_REPORT_BTCOEX_CONFIG_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI,
@@ -3038,21 +3327,21 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        case WMI_REMAIN_ON_CHNL_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n");
-               ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif);
                break;
        case WMI_CANCEL_REMAIN_ON_CHNL_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI,
                           "WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n");
                ret = ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap,
-                                                               len);
+                                                               len, vif);
                break;
        case WMI_TX_STATUS_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n");
-               ret = ath6kl_wmi_tx_status_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_tx_status_event_rx(wmi, datap, len, vif);
                break;
        case WMI_RX_PROBE_REQ_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n");
-               ret = ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len, vif);
                break;
        case WMI_P2P_CAPABILITIES_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_CAPABILITIES_EVENTID\n");
@@ -3060,7 +3349,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        case WMI_RX_ACTION_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
-               ret = ath6kl_wmi_rx_action_event_rx(wmi, datap, len);
+               ret = ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif);
                break;
        case WMI_P2P_INFO_EVENTID:
                ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_INFO_EVENTID\n");
@@ -3068,7 +3357,6 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
                break;
        default:
                ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id);
-               wmi->stat.cmd_id_err++;
                ret = -EINVAL;
                break;
        }
@@ -3078,11 +3366,8 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
        return ret;
 }
 
-static void ath6kl_wmi_qos_state_init(struct wmi *wmi)
+void ath6kl_wmi_reset(struct wmi *wmi)
 {
-       if (!wmi)
-               return;
-
        spin_lock_bh(&wmi->lock);
 
        wmi->fat_pipe_exist = 0;
@@ -3103,16 +3388,9 @@ void *ath6kl_wmi_init(struct ath6kl *dev)
 
        wmi->parent_dev = dev;
 
-       ath6kl_wmi_qos_state_init(wmi);
-
        wmi->pwr_mode = REC_POWER;
-       wmi->phy_mode = WMI_11G_MODE;
-
-       wmi->pair_crypto_type = NONE_CRYPT;
-       wmi->grp_crypto_type = NONE_CRYPT;
 
-       wmi->ht_allowed[A_BAND_24GHZ] = 1;
-       wmi->ht_allowed[A_BAND_5GHZ] = 1;
+       ath6kl_wmi_reset(wmi);
 
        return wmi;
 }
index f8e644d54aa78a042fab20328e33001fe7eea560..76342d5a190617ac0cd1012e4f07eddf3d1d1616 100644 (file)
@@ -93,11 +93,6 @@ struct sq_threshold_params {
        u8 last_rssi_poll_event;
 };
 
-struct wmi_stats {
-       u32 cmd_len_err;
-       u32 cmd_id_err;
-};
-
 struct wmi_data_sync_bufs {
        u8 traffic_class;
        struct sk_buff *skb;
@@ -111,32 +106,26 @@ struct wmi_data_sync_bufs {
 #define WMM_AC_VO   3          /* voice */
 
 struct wmi {
-       bool ready;
        u16 stream_exist_for_ac[WMM_NUM_AC];
        u8 fat_pipe_exist;
        struct ath6kl *parent_dev;
-       struct wmi_stats stat;
        u8 pwr_mode;
-       u8 phy_mode;
-       u8 keep_alive_intvl;
        spinlock_t lock;
        enum htc_endpoint_id ep_id;
        struct sq_threshold_params
            sq_threshld[SIGNAL_QUALITY_METRICS_NUM_MAX];
-       enum crypto_type pair_crypto_type;
-       enum crypto_type grp_crypto_type;
        bool is_wmm_enabled;
-       u8 ht_allowed[A_NUM_BANDS];
        u8 traffic_class;
        bool is_probe_ssid;
 
        u8 *last_mgmt_tx_frame;
        size_t last_mgmt_tx_frame_len;
+       u8 saved_pwr_mode;
 };
 
 struct host_app_area {
-       u32 wmi_protocol_ver;
-};
+       __le32 wmi_protocol_ver;
+} __packed;
 
 enum wmi_msg_type {
        DATA_MSGTYPE = 0x0,
@@ -184,6 +173,8 @@ enum wmi_data_hdr_data_type {
 #define WMI_DATA_HDR_META_MASK      0x7
 #define WMI_DATA_HDR_META_SHIFT     13
 
+#define WMI_DATA_HDR_IF_IDX_MASK    0xF
+
 struct wmi_data_hdr {
        s8 rssi;
 
@@ -208,6 +199,12 @@ struct wmi_data_hdr {
         * b15:b13      - META_DATA_VERSION 0 - 7
         */
        __le16 info2;
+
+       /*
+        * usage of info3, 16-bit:
+        * b3:b0        - Interface index
+        * b15:b4       - Reserved
+        */
        __le16 info3;
 } __packed;
 
@@ -250,6 +247,11 @@ static inline u8 wmi_data_hdr_get_meta(struct wmi_data_hdr *dhdr)
                               WMI_DATA_HDR_META_MASK;
 }
 
+static inline u8 wmi_data_hdr_get_if_idx(struct wmi_data_hdr *dhdr)
+{
+       return le16_to_cpu(dhdr->info3) & WMI_DATA_HDR_IF_IDX_MASK;
+}
+
 /* Tx meta version definitions */
 #define WMI_MAX_TX_META_SZ     12
 #define WMI_META_VERSION_1     0x01
@@ -299,6 +301,8 @@ struct wmi_rx_meta_v2 {
        u8 csum_flags;
 } __packed;
 
+#define WMI_CMD_HDR_IF_ID_MASK 0xF
+
 /* Control Path */
 struct wmi_cmd_hdr {
        __le16 cmd_id;
@@ -312,6 +316,11 @@ struct wmi_cmd_hdr {
        __le16 reserved;
 } __packed;
 
+static inline u8 wmi_cmd_hdr_get_if_idx(struct wmi_cmd_hdr *chdr)
+{
+       return le16_to_cpu(chdr->info1) & WMI_CMD_HDR_IF_ID_MASK;
+}
+
 /* List of WMI commands */
 enum wmi_cmd_id {
        WMI_CONNECT_CMDID = 0x0001,
@@ -576,9 +585,6 @@ enum auth_mode {
        WPA2_AUTH_CCKM = 0x40,
 };
 
-#define WMI_MIN_CRYPTO_TYPE NONE_CRYPT
-#define WMI_MAX_CRYPTO_TYPE (AES_CRYPT + 1)
-
 #define WMI_MIN_KEY_INDEX   0
 #define WMI_MAX_KEY_INDEX   3
 
@@ -617,6 +623,7 @@ enum wmi_connect_ctrl_flags_bits {
        CONNECT_CSA_FOLLOW_BSS = 0x0020,
        CONNECT_DO_WPA_OFFLOAD = 0x0040,
        CONNECT_DO_NOT_DEAUTH = 0x0080,
+       CONNECT_WPS_FLAG = 0x0100,
 };
 
 struct wmi_connect_cmd {
@@ -1365,14 +1372,20 @@ enum wmi_roam_ctrl {
        WMI_SET_LRSSI_SCAN_PARAMS,
 };
 
+enum wmi_roam_mode {
+       WMI_DEFAULT_ROAM_MODE = 1, /* RSSI based roam */
+       WMI_HOST_BIAS_ROAM_MODE = 2, /* Host bias based roam */
+       WMI_LOCK_BSS_MODE = 3, /* Lock to the current BSS */
+};
+
 struct bss_bias {
        u8 bssid[ETH_ALEN];
-       u8  bias;
+       s8 bias;
 } __packed;
 
 struct bss_bias_info {
        u8 num_bss;
-       struct bss_bias bss_bias[1];
+       struct bss_bias bss_bias[0];
 } __packed;
 
 struct low_rssi_scan_params {
@@ -1385,10 +1398,11 @@ struct low_rssi_scan_params {
 
 struct roam_ctrl_cmd {
        union {
-               u8 bssid[ETH_ALEN];
-               u8 roam_mode;
-               struct bss_bias_info bss;
-               struct low_rssi_scan_params params;
+               u8 bssid[ETH_ALEN]; /* WMI_FORCE_ROAM */
+               u8 roam_mode; /* WMI_SET_ROAM_MODE */
+               struct bss_bias_info bss; /* WMI_SET_HOST_BIAS */
+               struct low_rssi_scan_params params; /* WMI_SET_LRSSI_SCAN_PARAMS
+                                                    */
        } __packed info;
        u8 roam_ctrl;
 } __packed;
@@ -1455,6 +1469,10 @@ struct wmi_tkip_micerr_event {
        u8 is_mcast;
 } __packed;
 
+enum wmi_scan_status {
+       WMI_SCAN_STATUS_SUCCESS = 0,
+};
+
 /* WMI_SCAN_COMPLETE_EVENTID */
 struct wmi_scan_complete_event {
        a_sle32 status;
@@ -1635,6 +1653,12 @@ struct wmi_bss_roam_info {
        u8 reserved;
 } __packed;
 
+struct wmi_target_roam_tbl {
+       __le16 roam_mode;
+       __le16 num_entries;
+       struct wmi_bss_roam_info info[];
+} __packed;
+
 /* WMI_CAC_EVENTID */
 enum cac_indication {
        CAC_INDICATION_ADMISSION = 0x00,
@@ -1771,7 +1795,6 @@ struct wmi_set_appie_cmd {
 #define WSC_REG_ACTIVE     1
 #define WSC_REG_INACTIVE   0
 
-#define WOW_MAX_FILTER_LISTS    1
 #define WOW_MAX_FILTERS_PER_LIST 4
 #define WOW_PATTERN_SIZE        64
 #define WOW_MASK_SIZE           64
@@ -1794,17 +1817,52 @@ struct wmi_set_ip_cmd {
        __le32 ips[MAX_IP_ADDRS];
 } __packed;
 
-/* WMI_GET_WOW_LIST_CMD reply  */
-struct wmi_get_wow_list_reply {
-       /* number of patterns in reply */
-       u8 num_filters;
+enum ath6kl_wow_filters {
+       WOW_FILTER_SSID                 = BIT(0),
+       WOW_FILTER_OPTION_MAGIC_PACKET  = BIT(2),
+       WOW_FILTER_OPTION_EAP_REQ       = BIT(3),
+       WOW_FILTER_OPTION_PATTERNS      = BIT(4),
+       WOW_FILTER_OPTION_OFFLOAD_ARP   = BIT(5),
+       WOW_FILTER_OPTION_OFFLOAD_NS    = BIT(6),
+       WOW_FILTER_OPTION_OFFLOAD_GTK   = BIT(7),
+       WOW_FILTER_OPTION_8021X_4WAYHS  = BIT(8),
+       WOW_FILTER_OPTION_NLO_DISCVRY   = BIT(9),
+       WOW_FILTER_OPTION_NWK_DISASSOC  = BIT(10),
+       WOW_FILTER_OPTION_GTK_ERROR     = BIT(11),
+       WOW_FILTER_OPTION_TEST_MODE     = BIT(15),
+};
 
-       /* this is filter # x of total num_filters */
-       u8 this_filter_num;
+enum ath6kl_host_mode {
+       ATH6KL_HOST_MODE_AWAKE,
+       ATH6KL_HOST_MODE_ASLEEP,
+};
+
+struct wmi_set_host_sleep_mode_cmd {
+       __le32 awake;
+       __le32 asleep;
+} __packed;
+
+enum ath6kl_wow_mode {
+       ATH6KL_WOW_MODE_DISABLE,
+       ATH6KL_WOW_MODE_ENABLE,
+};
+
+struct wmi_set_wow_mode_cmd {
+       __le32 enable_wow;
+       __le32 filter;
+       __le16 host_req_delay;
+} __packed;
+
+struct wmi_add_wow_pattern_cmd {
+       u8 filter_list_id;
+       u8 filter_size;
+       u8 filter_offset;
+       u8 filter[0];
+} __packed;
 
-       u8 wow_mode;
-       u8 host_mode;
-       struct wow_filter wow_filters[1];
+struct wmi_del_wow_pattern_cmd {
+       __le16 filter_list_id;
+       __le16 filter_id;
 } __packed;
 
 /* WMI_SET_AKMP_PARAMS_CMD */
@@ -2163,20 +2221,21 @@ int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb);
 int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
                            u8 msg_type, bool more_data,
                            enum wmi_data_hdr_data_type data_type,
-                           u8 meta_ver, void *tx_meta_info);
+                           u8 meta_ver, void *tx_meta_info, u8 if_idx);
 
 int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb);
 int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb);
-int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb,
-                                      u32 layer2_priority, bool wmm_enabled,
-                                      u8 *ac);
+int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx,
+                                      struct sk_buff *skb, u32 layer2_priority,
+                                      bool wmm_enabled, u8 *ac);
 
 int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb);
 
-int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
+int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
                        enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag);
 
-int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
+int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
+                          enum network_type nw_type,
                           enum dot11_auth_mode dot11_auth_mode,
                           enum auth_mode auth_mode,
                           enum crypto_type pairwise_crypto,
@@ -2185,98 +2244,124 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
                           u8 group_crypto_len, int ssid_len, u8 *ssid,
                           u8 *bssid, u16 channel, u32 ctrl_flags);
 
-int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel);
-int ath6kl_wmi_disconnect_cmd(struct wmi *wmi);
-int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type,
+int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid,
+                            u16 channel);
+int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx);
+int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
+                            enum wmi_scan_type scan_type,
                             u32 force_fgscan, u32 is_legacy,
                             u32 home_dwell_time, u32 force_scan_interval,
                             s8 num_chan, u16 *ch_list);
-int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec,
+int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx, u16 fg_start_sec,
                              u16 fg_end_sec, u16 bg_sec,
                              u16 minact_chdw_msec, u16 maxact_chdw_msec,
                              u16 pas_chdw_msec, u8 short_scan_ratio,
                              u8 scan_ctrl_flag, u32 max_dfsch_act_time,
                              u16 maxact_scan_per_ssid);
-int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask);
-int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag,
+int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 if_idx, u8 filter,
+                            u32 ie_mask);
+int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
                              u8 ssid_len, u8 *ssid);
-int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval,
+int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
+                                 u16 listen_interval,
                                  u16 listen_beacons);
-int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode);
-int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period,
+int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode);
+int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u8 if_idx, u16 idle_period,
                            u16 ps_poll_num, u16 dtim_policy,
                            u16 tx_wakup_policy, u16 num_tx_to_wakeup,
                            u16 ps_fail_event_policy);
-int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout);
-int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi,
+int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi, u8 if_idx,
                                  struct wmi_create_pstream_cmd *pstream);
-int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid);
+int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class,
+                                 u8 tsid);
+int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 if_idx, u8 timeout);
 
 int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold);
-int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status,
+int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 if_idx, u8 status,
                                 u8 preamble_policy);
 
 int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source);
 int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config);
 
-int ath6kl_wmi_get_stats_cmd(struct wmi *wmi);
-int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
+int ath6kl_wmi_get_stats_cmd(struct wmi *wmi, u8 if_idx);
+int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index,
                          enum crypto_type key_type,
                          u8 key_usage, u8 key_len,
-                         u8 *key_rsc, u8 *key_material,
+                         u8 *key_rsc, unsigned int key_rsc_len,
+                         u8 *key_material,
                          u8 key_op_ctrl, u8 *mac_addr,
                          enum wmi_sync_flag sync_flag);
-int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk);
-int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index);
-int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid,
+int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk);
+int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index);
+int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid,
                            const u8 *pmkid, bool set);
-int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM);
-int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi);
+int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 if_idx, u8 dbM);
+int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi, u8 if_idx);
+int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi);
 
-int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg);
-int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl);
+int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg);
+int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx,
+                                u8 keep_alive_intvl);
 int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
 
 s32 ath6kl_wmi_get_rate(s8 rate_index);
 
 int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd);
+int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
+                                      enum ath6kl_host_mode host_mode);
+int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
+                               enum ath6kl_wow_mode wow_mode,
+                               u32 filter, u16 host_req_delay);
+int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
+                                  u8 list_id, u8 filter_size,
+                                  u8 filter_offset, u8 *filter, u8 *mask);
+int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
+                                  u16 list_id, u16 filter_id);
 int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
+int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
+int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode);
 
 /* AP mode */
-int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p);
+int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx,
+                                struct wmi_connect_cmd *p);
 
-int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason);
+int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd,
+                          const u8 *mac, u16 reason);
 
-int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag);
+int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u8 if_idx, u16 aid, bool flag);
 
-int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_version,
+int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 if_idx,
+                                      u8 rx_meta_version,
                                       bool rx_dot11_hdr, bool defrag_on_host);
 
-int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie,
-                            u8 ie_len);
+int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
+                            const u8 *ie, u8 ie_len);
 
 /* P2P */
 int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable);
 
-int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur);
+int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
+                                 u32 dur);
 
-int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait,
-                              const u8 *data, u16 data_len);
+int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
+                              u32 wait, const u8 *data, u16 data_len);
 
-int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq,
-                                      const u8 *dst,
-                                      const u8 *data, u16 data_len);
+int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
+                                      const u8 *dst, const u8 *data,
+                                      u16 data_len);
 
-int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable);
+int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, u8 if_idx, bool enable);
 
-int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags);
+int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u8 if_idx, u32 info_req_flags);
 
-int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi);
+int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx);
 
-int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie,
-                            u8 ie_len);
+int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
+                            const u8 *ie, u8 ie_len);
 
+struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx);
 void *ath6kl_wmi_init(struct ath6kl *devt);
 void ath6kl_wmi_shutdown(struct wmi *wmi);
+void ath6kl_wmi_reset(struct wmi *wmi);
 
 #endif /* WMI_H */
index 012263968d64f75245e5f993a0b37c9123e08874..9ac28d9de597d17c5d39b82551cb54356cbd648d 100644 (file)
@@ -36,6 +36,20 @@ struct ath_btcoex_config {
        bool bt_hold_rx_clear;
 };
 
+static const u32 ar9003_wlan_weights[ATH_BTCOEX_STOMP_MAX]
+                                   [AR9300_NUM_WLAN_WEIGHTS] = {
+       { 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0 }, /* STOMP_ALL */
+       { 0x88888880, 0x88888880, 0x88888880, 0x88888880 }, /* STOMP_LOW */
+       { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* STOMP_NONE */
+};
+
+static const u32 ar9462_wlan_weights[ATH_BTCOEX_STOMP_MAX]
+                                   [AR9300_NUM_WLAN_WEIGHTS] = {
+       { 0x01017d01, 0x41414101, 0x41414101, 0x41414141 }, /* STOMP_ALL */
+       { 0x01017d01, 0x3b3b3b01, 0x3b3b3b01, 0x3b3b3b3b }, /* STOMP_LOW */
+       { 0x01017d01, 0x01010101, 0x01010101, 0x01010101 }, /* STOMP_NONE */
+       { 0x01017d01, 0x013b0101, 0x3b3b0101, 0x3b3b013b }, /* STOMP_LOW_FTP */
+};
 
 void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
 {
@@ -152,27 +166,26 @@ EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
 
 static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
 {
-       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+       struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
        u32  val;
+       int i;
 
        /*
         * Program coex mode and weight registers to
         * enable coex 3-wire
         */
-       REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_hw->bt_coex_mode);
-       REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2);
+       REG_WRITE(ah, AR_BT_COEX_MODE, btcoex->bt_coex_mode);
+       REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2);
 
 
        if (AR_SREV_9300_20_OR_LATER(ah)) {
-               REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, ah->bt_coex_wlan_weight[0]);
-               REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, ah->bt_coex_wlan_weight[1]);
-               REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, ah->bt_coex_bt_weight[0]);
-               REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, ah->bt_coex_bt_weight[1]);
-               REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, ah->bt_coex_bt_weight[2]);
-               REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, ah->bt_coex_bt_weight[3]);
-
+               REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, btcoex->wlan_weight[0]);
+               REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, btcoex->wlan_weight[1]);
+               for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+                       REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS(i),
+                                 btcoex->bt_weight[i]);
        } else
-               REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights);
+               REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex->bt_coex_weights);
 
 
 
@@ -185,10 +198,23 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
        REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
        REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
 
-       ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
+       ath9k_hw_cfg_output(ah, btcoex->wlanactive_gpio,
                            AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
 }
 
+static void ath9k_hw_btcoex_enable_mci(struct ath_hw *ah)
+{
+       struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
+       int i;
+
+       for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+               REG_WRITE(ah, AR_MCI_COEX_WL_WEIGHTS(i),
+                         btcoex->wlan_weight[i]);
+
+       REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
+       btcoex->enabled = true;
+}
+
 void ath9k_hw_btcoex_enable(struct ath_hw *ah)
 {
        struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
@@ -202,6 +228,9 @@ void ath9k_hw_btcoex_enable(struct ath_hw *ah)
        case ATH_BTCOEX_CFG_3WIRE:
                ath9k_hw_btcoex_enable_3wire(ah);
                break;
+       case ATH_BTCOEX_CFG_MCI:
+               ath9k_hw_btcoex_enable_mci(ah);
+               return;
        }
 
        REG_RMW(ah, AR_GPIO_PDPU,
@@ -215,7 +244,15 @@ EXPORT_SYMBOL(ath9k_hw_btcoex_enable);
 void ath9k_hw_btcoex_disable(struct ath_hw *ah)
 {
        struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
-
+       int i;
+
+       btcoex_hw->enabled = false;
+       if (btcoex_hw->scheme == ATH_BTCOEX_CFG_MCI) {
+               ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
+               for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+                       REG_WRITE(ah, AR_MCI_COEX_WL_WEIGHTS(i),
+                                 btcoex_hw->wlan_weight[i]);
+       }
        ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0);
 
        ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
@@ -228,49 +265,27 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah)
                if (AR_SREV_9300_20_OR_LATER(ah)) {
                        REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, 0);
                        REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, 0);
-                       REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, 0);
-                       REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, 0);
-                       REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, 0);
-                       REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, 0);
+                       for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+                               REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS(i), 0);
                } else
                        REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);
 
        }
-
-       ah->btcoex_hw.enabled = false;
 }
 EXPORT_SYMBOL(ath9k_hw_btcoex_disable);
 
 static void ar9003_btcoex_bt_stomp(struct ath_hw *ah,
                         enum ath_stomp_type stomp_type)
 {
-       ah->bt_coex_bt_weight[0] = AR9300_BT_WGHT;
-       ah->bt_coex_bt_weight[1] = AR9300_BT_WGHT;
-       ah->bt_coex_bt_weight[2] = AR9300_BT_WGHT;
-       ah->bt_coex_bt_weight[3] = AR9300_BT_WGHT;
-
-
-       switch (stomp_type) {
-       case ATH_BTCOEX_STOMP_ALL:
-               ah->bt_coex_wlan_weight[0] = AR9300_STOMP_ALL_WLAN_WGHT0;
-               ah->bt_coex_wlan_weight[1] = AR9300_STOMP_ALL_WLAN_WGHT1;
-               break;
-       case ATH_BTCOEX_STOMP_LOW:
-               ah->bt_coex_wlan_weight[0] = AR9300_STOMP_LOW_WLAN_WGHT0;
-               ah->bt_coex_wlan_weight[1] = AR9300_STOMP_LOW_WLAN_WGHT1;
-               break;
-       case ATH_BTCOEX_STOMP_NONE:
-               ah->bt_coex_wlan_weight[0] = AR9300_STOMP_NONE_WLAN_WGHT0;
-               ah->bt_coex_wlan_weight[1] = AR9300_STOMP_NONE_WLAN_WGHT1;
-               break;
-
-       default:
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
-                               "Invalid Stomptype\n");
-               break;
+       struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
+       const u32 *weight = AR_SREV_9462(ah) ? ar9003_wlan_weights[stomp_type] :
+                                              ar9462_wlan_weights[stomp_type];
+       int i;
+
+       for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
+               btcoex->bt_weight[i] = AR9300_BT_WGHT;
+               btcoex->wlan_weight[i] = weight[i];
        }
-
-       ath9k_hw_btcoex_enable(ah);
 }
 
 /*
@@ -302,7 +317,5 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
                                "Invalid Stomptype\n");
                break;
        }
-
-       ath9k_hw_btcoex_enable(ah);
 }
 EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp);
index 234f77689b144715d51372d6da5e1f038b37e78a..d5e5db1faad9eb446e8f985ec461fe1d8ad8b832 100644 (file)
 #define ATH_BT_CNT_THRESHOLD          3
 #define ATH_BT_CNT_SCAN_THRESHOLD      15
 
+#define AR9300_NUM_BT_WEIGHTS   4
+#define AR9300_NUM_WLAN_WEIGHTS 4
 /* Defines the BT AR_BT_COEX_WGHT used */
 enum ath_stomp_type {
-       ATH_BTCOEX_NO_STOMP,
        ATH_BTCOEX_STOMP_ALL,
        ATH_BTCOEX_STOMP_LOW,
-       ATH_BTCOEX_STOMP_NONE
+       ATH_BTCOEX_STOMP_NONE,
+       ATH_BTCOEX_STOMP_LOW_FTP,
+       ATH_BTCOEX_STOMP_MAX
 };
 
 enum ath_btcoex_scheme {
        ATH_BTCOEX_CFG_NONE,
        ATH_BTCOEX_CFG_2WIRE,
        ATH_BTCOEX_CFG_3WIRE,
+       ATH_BTCOEX_CFG_MCI,
 };
 
 struct ath_btcoex_hw {
@@ -59,6 +63,8 @@ struct ath_btcoex_hw {
        u32 bt_coex_mode;       /* Register setting for AR_BT_COEX_MODE */
        u32 bt_coex_weights;    /* Register setting for AR_BT_COEX_WEIGHT */
        u32 bt_coex_mode2;      /* Register setting for AR_BT_COEX_MODE2 */
+       u32 bt_weight[AR9300_NUM_BT_WEIGHTS];
+       u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
 };
 
 void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah);
index 2c279dcaf4ba8cb8813997c39472bb4ac869dc7d..e4ae08e07719e2f4e3f1a545b6ac653cf8d29cb5 100644 (file)
@@ -198,6 +198,7 @@ static void ath_btcoex_period_timer(unsigned long data)
        ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
                              btcoex->bt_stomp_type);
 
+       ath9k_hw_btcoex_enable(ah);
        spin_unlock_bh(&btcoex->btcoex_lock);
 
        if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) {
@@ -240,6 +241,7 @@ static void ath_btcoex_no_stomp_timer(void *arg)
         else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
                ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
 
+       ath9k_hw_btcoex_enable(ah);
        spin_unlock_bh(&btcoex->btcoex_lock);
        ath9k_ps_restore(sc);
 }
index e3a02eb8e0cc768dd44f2b49db655ed9d705c02f..ce606b618e0b7c4813235b221c2bf9fa096887c6 100644 (file)
@@ -80,6 +80,7 @@ static void ath_btcoex_period_work(struct work_struct *work)
        ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
                        btcoex->bt_stomp_type);
 
+       ath9k_hw_btcoex_enable(priv->ah);
        timer_period = is_btscan ? btcoex->btscan_no_stomp :
                btcoex->btcoex_no_stomp;
        ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work,
@@ -108,6 +109,7 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work)
                ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
        else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
                ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
+       ath9k_hw_btcoex_enable(priv->ah);
 }
 
 void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv)
index 33e8f2f9d4256605e539b5be58eabef6fc850315..3cb878c28ccf0a21ee01a554ec982800989c71c3 100644 (file)
@@ -59,9 +59,6 @@
 #define AT9285_COEX3WIRE_SA_SUBSYSID   0x30aa
 #define AT9285_COEX3WIRE_DA_SUBSYSID   0x30ab
 
-#define AR9300_NUM_BT_WEIGHTS   4
-#define AR9300_NUM_WLAN_WEIGHTS 4
-
 #define ATH_AMPDU_LIMIT_MAX        (64 * 1024 - 1)
 
 #define        ATH_DEFAULT_NOISE_FLOOR -95
@@ -802,8 +799,6 @@ struct ath_hw {
 
        /* Bluetooth coexistance */
        struct ath_btcoex_hw btcoex_hw;
-       u32 bt_coex_bt_weight[AR9300_NUM_BT_WEIGHTS];
-       u32 bt_coex_wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
 
        u32 intr_txqs;
        u8 txchainmask;
index 67b862cdae6d2b3b95f53a46160c56b3fa122724..4c8e296f663b7189fd8f172b287cebc99a870141 100644 (file)
@@ -1838,11 +1838,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                if (sc->sc_flags & SC_OP_RXFLUSH)
                        goto requeue_drop_frag;
 
-               retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
-                                                rxs, &decrypt_error);
-               if (retval)
-                       goto requeue_drop_frag;
-
                rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
                if (rs.rs_tstamp > tsf_lower &&
                    unlikely(rs.rs_tstamp - tsf_lower > 0x10000000))
@@ -1852,6 +1847,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                    unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
                        rxs->mactime += 0x100000000ULL;
 
+               retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
+                                                rxs, &decrypt_error);
+               if (retval)
+                       goto requeue_drop_frag;
+
                /* Ensure we always have an skb to requeue once we are done
                 * processing the current buffer's skb */
                requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC);
index 8fcb7e9e8399de3d82c86405797c3775bf55f7ba..45910975d853e262e0c4884d132e2f58420f9f38 100644 (file)
@@ -1752,19 +1752,10 @@ enum {
 
 #define AR_BT_COEX_WL_WEIGHTS0     0x8174
 #define AR_BT_COEX_WL_WEIGHTS1     0x81c4
+#define AR_MCI_COEX_WL_WEIGHTS(_i) (0x18b0 + (_i << 2))
+#define AR_BT_COEX_BT_WEIGHTS(_i)  (0x83ac + (_i << 2))
 
-#define AR_BT_COEX_BT_WEIGHTS0     0x83ac
-#define AR_BT_COEX_BT_WEIGHTS1     0x83b0
-#define AR_BT_COEX_BT_WEIGHTS2     0x83b4
-#define AR_BT_COEX_BT_WEIGHTS3     0x83b8
-
-#define AR9300_BT_WGHT                     0xcccc4444
-#define AR9300_STOMP_ALL_WLAN_WGHT0        0xfffffff0
-#define AR9300_STOMP_ALL_WLAN_WGHT1        0xfffffff0
-#define AR9300_STOMP_LOW_WLAN_WGHT0        0x88888880
-#define AR9300_STOMP_LOW_WLAN_WGHT1        0x88888880
-#define AR9300_STOMP_NONE_WLAN_WGHT0       0x00000000
-#define AR9300_STOMP_NONE_WLAN_WGHT1       0x00000000
+#define AR9300_BT_WGHT             0xcccc4444
 
 #define AR_BT_COEX_MODE2           0x817c
 #define AR_BT_BCN_MISS_THRESH      0x000000ff
index 59472e1605cd89779e06c299937ba950968b3daf..d19a9ee9d057a904577d9497435911bc2867e978 100644 (file)
@@ -314,7 +314,7 @@ static void carl9170_tx_release(struct kref *ref)
                         *    feedback either [CTL_REQ_TX_STATUS not set]
                         */
 
-                       dev_kfree_skb_any(skb);
+                       ieee80211_free_txskb(ar->hw, skb);
                        return;
                } else {
                        /*
@@ -1432,7 +1432,7 @@ void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 
 err_free:
        ar->tx_dropped++;
-       dev_kfree_skb_any(skb);
+       ieee80211_free_txskb(ar->hw, skb);
 }
 
 void carl9170_tx_scheduler(struct ar9170 *ar)
index 025fa0eb6f473e2b30316fce4c78af4262b823bd..39e305443d7ee7db1081e9cef69d26ab83b9bb9b 100644 (file)
@@ -16,6 +16,8 @@
  * File contents: support functions for PCI/PCIe
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/delay.h>
 #include <linux/pci.h>
 
 #define PCI_FORCEHT(si)        (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID))
 
 #ifdef BCMDBG
-#define        SI_MSG(args)    printk args
+#define        SI_MSG(fmt, ...)        pr_debug(fmt, ##__VA_ARGS__)
 #else
-#define        SI_MSG(args)
+#define        SI_MSG(fmt, ...)        no_printk(fmt, ##__VA_ARGS__)
 #endif                         /* BCMDBG */
 
 #define        GOODCOREADDR(x, b) \
@@ -1073,7 +1075,7 @@ static struct si_info *ai_doattach(struct si_info *sii,
 
        /* scan for cores */
        if (socitype == SOCI_AI) {
-               SI_MSG(("Found chip type AI (0x%08x)\n", w));
+               SI_MSG("Found chip type AI (0x%08x)\n", w);
                /* pass chipc address instead of original core base */
                ai_scan(&sii->pub, cc);
        } else {
@@ -1129,7 +1131,7 @@ static struct si_info *ai_doattach(struct si_info *sii,
                 * set chipControl register bit 15
                 */
                if (sih->chiprev == 0) {
-                       SI_MSG(("Applying 43224A0 WARs\n"));
+                       SI_MSG("Applying 43224A0 WARs\n");
                        ai_corereg(sih, SI_CC_IDX,
                                   offsetof(struct chipcregs, chipcontrol),
                                   CCTRL43224_GPIO_TOGGLE,
@@ -1138,7 +1140,7 @@ static struct si_info *ai_doattach(struct si_info *sii,
                                           CCTRL_43224A0_12MA_LED_DRIVE);
                }
                if (sih->chiprev >= 1) {
-                       SI_MSG(("Applying 43224B0+ WARs\n"));
+                       SI_MSG("Applying 43224B0+ WARs\n");
                        si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
                                           CCTRL_43224B0_12MA_LED_DRIVE);
                }
@@ -1149,7 +1151,7 @@ static struct si_info *ai_doattach(struct si_info *sii,
                 * enable 12 mA drive strenth for 4313 and
                 * set chipControl register bit 1
                 */
-               SI_MSG(("Applying 4313 WARs\n"));
+               SI_MSG("Applying 4313 WARs\n");
                si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE,
                                   CCTRL_4313_12MA_LED_DRIVE);
        }
index e286fb4d48135eab824546b420be9439c232d5a9..0bb8c37e979e863cd50f4a980d796b58d30c26db 100644 (file)
@@ -13,6 +13,9 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 
 /* debug/trace */
 #ifdef BCMDBG
-#define        DMA_ERROR(args) \
-       do { \
-               if (!(*di->msg_level & 1)) \
-                       ; \
-               else \
-                       printk args; \
-       } while (0)
-#define        DMA_TRACE(args) \
-       do { \
-               if (!(*di->msg_level & 2)) \
-                       ; \
-               else \
-                       printk args; \
-       } while (0)
+#define        DMA_ERROR(fmt, ...)                                     \
+do {                                                           \
+       if (*di->msg_level & 1)                                 \
+               pr_debug("%s: " fmt, __func__, ##__VA_ARGS__);  \
+} while (0)
+#define        DMA_TRACE(fmt, ...)                                     \
+do {                                                           \
+       if (*di->msg_level & 2)                                 \
+               pr_debug("%s: " fmt, __func__, ##__VA_ARGS__);  \
+} while (0)
 #else
-#define        DMA_ERROR(args)
-#define        DMA_TRACE(args)
+#define        DMA_ERROR(fmt, ...)                     \
+       no_printk(fmt, ##__VA_ARGS__)
+#define        DMA_TRACE(fmt, ...)                     \
+       no_printk(fmt, ##__VA_ARGS__)
 #endif                         /* BCMDBG */
 
-#define        DMA_NONE(args)
+#define        DMA_NONE(fmt, ...)                      \
+       no_printk(fmt, ##__VA_ARGS__)
 
 #define        MAXNAMEL        8       /* 8 char names */
 
@@ -361,7 +363,7 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
        uint dmactrlflags;
 
        if (di == NULL) {
-               DMA_ERROR(("_dma_ctrlflags: NULL dma handle\n"));
+               DMA_ERROR("NULL dma handle\n");
                return 0;
        }
 
@@ -412,13 +414,13 @@ static bool _dma_isaddrext(struct dma_info *di)
        /* not all tx or rx channel are available */
        if (di->d64txregs != NULL) {
                if (!_dma64_addrext(di->d64txregs))
-                       DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have "
-                                  "AE set\n", di->name));
+                       DMA_ERROR("%s: DMA64 tx doesn't have AE set\n",
+                                 di->name);
                return true;
        } else if (di->d64rxregs != NULL) {
                if (!_dma64_addrext(di->d64rxregs))
-                       DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have "
-                                  "AE set\n", di->name));
+                       DMA_ERROR("%s: DMA64 rx doesn't have AE set\n",
+                                 di->name);
                return true;
        }
 
@@ -519,8 +521,8 @@ static bool dma64_alloc(struct dma_info *di, uint direction)
                va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
                        &alloced, &di->txdpaorig);
                if (va == NULL) {
-                       DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd)"
-                                  " failed\n", di->name));
+                       DMA_ERROR("%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n",
+                                 di->name);
                        return false;
                }
                align = (1 << align_bits);
@@ -533,8 +535,8 @@ static bool dma64_alloc(struct dma_info *di, uint direction)
                va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
                        &alloced, &di->rxdpaorig);
                if (va == NULL) {
-                       DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd)"
-                                  " failed\n", di->name));
+                       DMA_ERROR("%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n",
+                                 di->name);
                        return false;
                }
                align = (1 << align_bits);
@@ -583,11 +585,10 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
         */
        _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0);
 
-       DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d "
-                  "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
-                  "dmaregstx %p dmaregsrx %p\n", name, "DMA64",
-                  di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
-                  rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx));
+       DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d dmaregstx %p dmaregsrx %p\n",
+                 name, "DMA64",
+                 di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
+                 rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx);
 
        /* make a private copy of our callers name */
        strncpy(di->name, name, MAXNAMEL);
@@ -645,8 +646,8 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
                di->dmadesc_align = 4;  /* 16 byte alignment */
        }
 
-       DMA_NONE(("DMA descriptor align_needed %d, align %d\n",
-                 di->aligndesc_4k, di->dmadesc_align));
+       DMA_NONE("DMA descriptor align_needed %d, align %d\n",
+                di->aligndesc_4k, di->dmadesc_align);
 
        /* allocate tx packet pointer vector */
        if (ntxd) {
@@ -684,21 +685,21 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
 
        if ((di->ddoffsetlow != 0) && !di->addrext) {
                if (di->txdpa > SI_PCI_DMA_SZ) {
-                       DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not "
-                                  "supported\n", di->name, (u32)di->txdpa));
+                       DMA_ERROR("%s: txdpa 0x%x: addrext not supported\n",
+                                 di->name, (u32)di->txdpa);
                        goto fail;
                }
                if (di->rxdpa > SI_PCI_DMA_SZ) {
-                       DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not "
-                                  "supported\n", di->name, (u32)di->rxdpa));
+                       DMA_ERROR("%s: rxdpa 0x%x: addrext not supported\n",
+                                 di->name, (u32)di->rxdpa);
                        goto fail;
                }
        }
 
-       DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x "
-                  "dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow,
-                  di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh,
-                  di->addrext));
+       DMA_TRACE("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n",
+                 di->ddoffsetlow, di->ddoffsethigh,
+                 di->dataoffsetlow, di->dataoffsethigh,
+                 di->addrext);
 
        return (struct dma_pub *) di;
 
@@ -744,7 +745,7 @@ void dma_detach(struct dma_pub *pub)
 {
        struct dma_info *di = (struct dma_info *)pub;
 
-       DMA_TRACE(("%s: dma_detach\n", di->name));
+       DMA_TRACE("%s:\n", di->name);
 
        /* free dma descriptor rings */
        if (di->txd64)
@@ -812,7 +813,7 @@ static void _dma_rxenable(struct dma_info *di)
        uint dmactrlflags = di->dma.dmactrlflags;
        u32 control;
 
-       DMA_TRACE(("%s: dma_rxenable\n", di->name));
+       DMA_TRACE("%s:\n", di->name);
 
        control =
            (R_REG(&di->d64rxregs->control) & D64_RC_AE) |
@@ -832,7 +833,7 @@ void dma_rxinit(struct dma_pub *pub)
 {
        struct dma_info *di = (struct dma_info *)pub;
 
-       DMA_TRACE(("%s: dma_rxinit\n", di->name));
+       DMA_TRACE("%s:\n", di->name);
 
        if (di->nrxd == 0)
                return;
@@ -926,7 +927,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
                return 0;
 
        len = le16_to_cpu(*(__le16 *) (p->data));
-       DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
+       DMA_TRACE("%s: dma_rx len %d\n", di->name, len);
        dma_spin_for_len(len, p);
 
        /* set actual length */
@@ -953,14 +954,14 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
                                  D64_RS0_CD_MASK) -
                                 di->rcvptrbase) & D64_RS0_CD_MASK,
                                struct dma64desc);
-                       DMA_ERROR(("dma_rx, rxin %d rxout %d, hw_curr %d\n",
-                                  di->rxin, di->rxout, cur));
+                       DMA_ERROR("rxin %d rxout %d, hw_curr %d\n",
+                                 di->rxin, di->rxout, cur);
                }
 #endif                         /* BCMDBG */
 
                if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
-                       DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n",
-                                  di->name, len));
+                       DMA_ERROR("%s: bad frame length (%d)\n",
+                                 di->name, len);
                        skb_queue_walk_safe(&dma_frames, p, next) {
                                skb_unlink(p, &dma_frames);
                                brcmu_pkt_buf_free_skb(p);
@@ -977,7 +978,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
 
 static bool dma64_rxidle(struct dma_info *di)
 {
-       DMA_TRACE(("%s: dma_rxidle\n", di->name));
+       DMA_TRACE("%s:\n", di->name);
 
        if (di->nrxd == 0)
                return true;
@@ -1017,7 +1018,7 @@ bool dma_rxfill(struct dma_pub *pub)
 
        n = di->nrxpost - nrxdactive(di, rxin, rxout);
 
-       DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n));
+       DMA_TRACE("%s: post %d\n", di->name, n);
 
        if (di->rxbufsize > BCMEXTRAHDROOM)
                extra_offset = di->rxextrahdrroom;
@@ -1030,11 +1031,9 @@ bool dma_rxfill(struct dma_pub *pub)
                p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset);
 
                if (p == NULL) {
-                       DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n",
-                                  di->name));
+                       DMA_ERROR("%s: out of rxbufs\n", di->name);
                        if (i == 0 && dma64_rxidle(di)) {
-                               DMA_ERROR(("%s: rxfill64: ring is empty !\n",
-                                          di->name));
+                               DMA_ERROR("%s: ring is empty !\n", di->name);
                                ring_empty = true;
                        }
                        di->dma.rxnobuf++;
@@ -1079,7 +1078,7 @@ void dma_rxreclaim(struct dma_pub *pub)
        struct dma_info *di = (struct dma_info *)pub;
        struct sk_buff *p;
 
-       DMA_TRACE(("%s: dma_rxreclaim\n", di->name));
+       DMA_TRACE("%s:\n", di->name);
 
        while ((p = _dma_getnextrxp(di, true)))
                brcmu_pkt_buf_free_skb(p);
@@ -1110,7 +1109,7 @@ void dma_txinit(struct dma_pub *pub)
        struct dma_info *di = (struct dma_info *)pub;
        u32 control = D64_XC_XE;
 
-       DMA_TRACE(("%s: dma_txinit\n", di->name));
+       DMA_TRACE("%s:\n", di->name);
 
        if (di->ntxd == 0)
                return;
@@ -1142,7 +1141,7 @@ void dma_txsuspend(struct dma_pub *pub)
 {
        struct dma_info *di = (struct dma_info *)pub;
 
-       DMA_TRACE(("%s: dma_txsuspend\n", di->name));
+       DMA_TRACE("%s:\n", di->name);
 
        if (di->ntxd == 0)
                return;
@@ -1154,7 +1153,7 @@ void dma_txresume(struct dma_pub *pub)
 {
        struct dma_info *di = (struct dma_info *)pub;
 
-       DMA_TRACE(("%s: dma_txresume\n", di->name));
+       DMA_TRACE("%s:\n", di->name);
 
        if (di->ntxd == 0)
                return;
@@ -1176,11 +1175,11 @@ void dma_txreclaim(struct dma_pub *pub, enum txd_range range)
        struct dma_info *di = (struct dma_info *)pub;
        struct sk_buff *p;
 
-       DMA_TRACE(("%s: dma_txreclaim %s\n", di->name,
-                  (range == DMA_RANGE_ALL) ? "all" :
-                  ((range ==
-                    DMA_RANGE_TRANSMITTED) ? "transmitted" :
-                   "transferred")));
+       DMA_TRACE("%s: %s\n",
+                 di->name,
+                 range == DMA_RANGE_ALL ? "all" :
+                 range == DMA_RANGE_TRANSMITTED ? "transmitted" :
+                 "transferred");
 
        if (di->txin == di->txout)
                return;
@@ -1250,7 +1249,7 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit)
        u32 flags = 0;
        dma_addr_t pa;
 
-       DMA_TRACE(("%s: dma_txfast\n", di->name));
+       DMA_TRACE("%s:\n", di->name);
 
        txout = di->txout;
 
@@ -1314,7 +1313,7 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit)
        return 0;
 
  outoftxd:
-       DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name));
+       DMA_ERROR("%s: out of txds !!!\n", di->name);
        brcmu_pkt_buf_free_skb(p0);
        di->dma.txavail = 0;
        di->dma.txnobuf++;
@@ -1338,11 +1337,11 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
        u16 active_desc;
        struct sk_buff *txp;
 
-       DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name,
-                  (range == DMA_RANGE_ALL) ? "all" :
-                  ((range ==
-                    DMA_RANGE_TRANSMITTED) ? "transmitted" :
-                   "transferred")));
+       DMA_TRACE("%s: %s\n",
+                 di->name,
+                 range == DMA_RANGE_ALL ? "all" :
+                 range == DMA_RANGE_TRANSMITTED ? "transmitted" :
+                 "transferred");
 
        if (di->ntxd == 0)
                return NULL;
@@ -1402,8 +1401,8 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
        return txp;
 
  bogus:
-       DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d "
-                 "force %d\n", start, end, di->txout, forceall));
+       DMA_NONE("bogus curr: start %d end %d txout %d\n",
+                start, end, di->txout);
        return NULL;
 }
 
index 8457e969eb4fe418178362ac5f0556772f8b5d2b..ba3e4b5cba71ef95c8b608a720d338f51fe44bc1 100644 (file)
@@ -1550,11 +1550,10 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
                        if (le32_to_cpu(hdr->idx) == idx) {
                                pdata = wl->fw.fw_bin[i]->data +
                                        le32_to_cpu(hdr->offset);
-                               *pbuf = kmalloc(len, GFP_ATOMIC);
+                               *pbuf = kmemdup(pdata, len, GFP_ATOMIC);
                                if (*pbuf == NULL)
                                        goto fail;
 
-                               memcpy(*pbuf, pdata, len);
                                return 0;
                        }
                }
index 045a93645a3dede213af0a68855bf0889a5be26b..18054d9c66887363cc7d028279c04e89732481ba 100644 (file)
@@ -3872,8 +3872,8 @@ static void prism2_get_drvinfo(struct net_device *dev,
        iface = netdev_priv(dev);
        local = iface->local;
 
-       strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
-       snprintf(info->fw_version, sizeof(info->fw_version) - 1,
+       strlcpy(info->driver, "hostap", sizeof(info->driver));
+       snprintf(info->fw_version, sizeof(info->fw_version),
                 "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
                 (local->sta_fw_ver >> 8) & 0xff,
                 local->sta_fw_ver & 0xff);
index 127e9c63beaf9be7737ccd104b72debf62f749df..a0e5c21d36576c74c1c402984a7392869926bdea 100644 (file)
@@ -5981,8 +5981,8 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
        struct ipw2100_priv *priv = libipw_priv(dev);
        char fw_ver[64], ucode_ver[64];
 
-       strcpy(info->driver, DRV_NAME);
-       strcpy(info->version, DRV_VERSION);
+       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
 
        ipw2100_get_fwversion(priv, fw_ver, sizeof(fw_ver));
        ipw2100_get_ucodeversion(priv, ucode_ver, sizeof(ucode_ver));
@@ -5990,7 +5990,8 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
        snprintf(info->fw_version, sizeof(info->fw_version), "%s:%d:%s",
                 fw_ver, priv->eeprom_version, ucode_ver);
 
-       strcpy(info->bus_info, pci_name(priv->pci_dev));
+       strlcpy(info->bus_info, pci_name(priv->pci_dev),
+               sizeof(info->bus_info));
 }
 
 static u32 ipw2100_ethtool_get_link(struct net_device *dev)
index 99575884ff525af70d69186ad625b55fb7d6dbdf..018a8deb88a83b5b2ab2febcc2487b89eeb4ba4f 100644 (file)
@@ -10548,8 +10548,8 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
        char date[32];
        u32 len;
 
-       strcpy(info->driver, DRV_NAME);
-       strcpy(info->version, DRV_VERSION);
+       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
 
        len = sizeof(vers);
        ipw_get_ordinal(p, IPW_ORD_STAT_FW_VERSION, vers, &len);
@@ -10558,7 +10558,8 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
 
        snprintf(info->fw_version, sizeof(info->fw_version), "%s (%s)",
                 vers, date);
-       strcpy(info->bus_info, pci_name(p->pci_dev));
+       strlcpy(info->bus_info, pci_name(p->pci_dev),
+               sizeof(info->bus_info));
        info->eedump_len = IPW_EEPROM_IMAGE_SIZE;
 }
 
diff --git a/drivers/net/wireless/iwlegacy/3945-debug.c b/drivers/net/wireless/iwlegacy/3945-debug.c
new file mode 100644 (file)
index 0000000..5e1a19f
--- /dev/null
@@ -0,0 +1,505 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include "common.h"
+#include "3945.h"
+
+static int
+il3945_stats_flag(struct il_priv *il, char *buf, int bufsz)
+{
+       int p = 0;
+
+       p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
+                      le32_to_cpu(il->_3945.stats.flag));
+       if (le32_to_cpu(il->_3945.stats.flag) & UCODE_STATS_CLEAR_MSK)
+               p += scnprintf(buf + p, bufsz - p,
+                              "\tStatistics have been cleared\n");
+       p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
+                      (le32_to_cpu(il->_3945.stats.flag) &
+                       UCODE_STATS_FREQUENCY_MSK) ? "2.4 GHz" : "5.2 GHz");
+       p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
+                      (le32_to_cpu(il->_3945.stats.flag) &
+                       UCODE_STATS_NARROW_BAND_MSK) ? "enabled" : "disabled");
+       return p;
+}
+
+ssize_t
+il3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+                          size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       char *buf;
+       int bufsz =
+           sizeof(struct iwl39_stats_rx_phy) * 40 +
+           sizeof(struct iwl39_stats_rx_non_phy) * 40 + 400;
+       ssize_t ret;
+       struct iwl39_stats_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
+       struct iwl39_stats_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
+       struct iwl39_stats_rx_non_phy *general, *accum_general;
+       struct iwl39_stats_rx_non_phy *delta_general, *max_general;
+
+       if (!il_is_alive(il))
+               return -EAGAIN;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       /*
+        * The statistic information display here is based on
+        * the last stats notification from uCode
+        * might not reflect the current uCode activity
+        */
+       ofdm = &il->_3945.stats.rx.ofdm;
+       cck = &il->_3945.stats.rx.cck;
+       general = &il->_3945.stats.rx.general;
+       accum_ofdm = &il->_3945.accum_stats.rx.ofdm;
+       accum_cck = &il->_3945.accum_stats.rx.cck;
+       accum_general = &il->_3945.accum_stats.rx.general;
+       delta_ofdm = &il->_3945.delta_stats.rx.ofdm;
+       delta_cck = &il->_3945.delta_stats.rx.cck;
+       delta_general = &il->_3945.delta_stats.rx.general;
+       max_ofdm = &il->_3945.max_delta.rx.ofdm;
+       max_cck = &il->_3945.max_delta.rx.cck;
+       max_general = &il->_3945.max_delta.rx.general;
+
+       pos += il3945_stats_flag(il, buf, bufsz);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "%-32s     current"
+                     "acumulative       delta         max\n",
+                     "Statistics_Rx - OFDM:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "ina_cnt:",
+                     le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt,
+                     delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "fina_cnt:",
+                     le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
+                     delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "plcp_err:",
+                     le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
+                     delta_ofdm->plcp_err, max_ofdm->plcp_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "crc32_err:",
+                     le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
+                     delta_ofdm->crc32_err, max_ofdm->crc32_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:",
+                     le32_to_cpu(ofdm->overrun_err), accum_ofdm->overrun_err,
+                     delta_ofdm->overrun_err, max_ofdm->overrun_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "early_overrun_err:",
+                     le32_to_cpu(ofdm->early_overrun_err),
+                     accum_ofdm->early_overrun_err,
+                     delta_ofdm->early_overrun_err,
+                     max_ofdm->early_overrun_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "crc32_good:",
+                     le32_to_cpu(ofdm->crc32_good), accum_ofdm->crc32_good,
+                     delta_ofdm->crc32_good, max_ofdm->crc32_good);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:",
+                     le32_to_cpu(ofdm->false_alarm_cnt),
+                     accum_ofdm->false_alarm_cnt, delta_ofdm->false_alarm_cnt,
+                     max_ofdm->false_alarm_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "fina_sync_err_cnt:",
+                     le32_to_cpu(ofdm->fina_sync_err_cnt),
+                     accum_ofdm->fina_sync_err_cnt,
+                     delta_ofdm->fina_sync_err_cnt,
+                     max_ofdm->fina_sync_err_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "sfd_timeout:",
+                     le32_to_cpu(ofdm->sfd_timeout), accum_ofdm->sfd_timeout,
+                     delta_ofdm->sfd_timeout, max_ofdm->sfd_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "fina_timeout:",
+                     le32_to_cpu(ofdm->fina_timeout), accum_ofdm->fina_timeout,
+                     delta_ofdm->fina_timeout, max_ofdm->fina_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "unresponded_rts:",
+                     le32_to_cpu(ofdm->unresponded_rts),
+                     accum_ofdm->unresponded_rts, delta_ofdm->unresponded_rts,
+                     max_ofdm->unresponded_rts);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n",
+                     "rxe_frame_lmt_ovrun:",
+                     le32_to_cpu(ofdm->rxe_frame_limit_overrun),
+                     accum_ofdm->rxe_frame_limit_overrun,
+                     delta_ofdm->rxe_frame_limit_overrun,
+                     max_ofdm->rxe_frame_limit_overrun);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "sent_ack_cnt:",
+                     le32_to_cpu(ofdm->sent_ack_cnt), accum_ofdm->sent_ack_cnt,
+                     delta_ofdm->sent_ack_cnt, max_ofdm->sent_ack_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "sent_cts_cnt:",
+                     le32_to_cpu(ofdm->sent_cts_cnt), accum_ofdm->sent_cts_cnt,
+                     delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "%-32s     current"
+                     "acumulative       delta         max\n",
+                     "Statistics_Rx - CCK:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "ina_cnt:",
+                     le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
+                     delta_cck->ina_cnt, max_cck->ina_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "fina_cnt:",
+                     le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
+                     delta_cck->fina_cnt, max_cck->fina_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "plcp_err:",
+                     le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
+                     delta_cck->plcp_err, max_cck->plcp_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "crc32_err:",
+                     le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
+                     delta_cck->crc32_err, max_cck->crc32_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:",
+                     le32_to_cpu(cck->overrun_err), accum_cck->overrun_err,
+                     delta_cck->overrun_err, max_cck->overrun_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "early_overrun_err:",
+                     le32_to_cpu(cck->early_overrun_err),
+                     accum_cck->early_overrun_err,
+                     delta_cck->early_overrun_err, max_cck->early_overrun_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "crc32_good:",
+                     le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
+                     delta_cck->crc32_good, max_cck->crc32_good);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:",
+                     le32_to_cpu(cck->false_alarm_cnt),
+                     accum_cck->false_alarm_cnt, delta_cck->false_alarm_cnt,
+                     max_cck->false_alarm_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "fina_sync_err_cnt:",
+                     le32_to_cpu(cck->fina_sync_err_cnt),
+                     accum_cck->fina_sync_err_cnt,
+                     delta_cck->fina_sync_err_cnt, max_cck->fina_sync_err_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "sfd_timeout:",
+                     le32_to_cpu(cck->sfd_timeout), accum_cck->sfd_timeout,
+                     delta_cck->sfd_timeout, max_cck->sfd_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "fina_timeout:",
+                     le32_to_cpu(cck->fina_timeout), accum_cck->fina_timeout,
+                     delta_cck->fina_timeout, max_cck->fina_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "unresponded_rts:",
+                     le32_to_cpu(cck->unresponded_rts),
+                     accum_cck->unresponded_rts, delta_cck->unresponded_rts,
+                     max_cck->unresponded_rts);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n",
+                     "rxe_frame_lmt_ovrun:",
+                     le32_to_cpu(cck->rxe_frame_limit_overrun),
+                     accum_cck->rxe_frame_limit_overrun,
+                     delta_cck->rxe_frame_limit_overrun,
+                     max_cck->rxe_frame_limit_overrun);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "sent_ack_cnt:",
+                     le32_to_cpu(cck->sent_ack_cnt), accum_cck->sent_ack_cnt,
+                     delta_cck->sent_ack_cnt, max_cck->sent_ack_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "sent_cts_cnt:",
+                     le32_to_cpu(cck->sent_cts_cnt), accum_cck->sent_cts_cnt,
+                     delta_cck->sent_cts_cnt, max_cck->sent_cts_cnt);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "%-32s     current"
+                     "acumulative       delta         max\n",
+                     "Statistics_Rx - GENERAL:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "bogus_cts:",
+                     le32_to_cpu(general->bogus_cts), accum_general->bogus_cts,
+                     delta_general->bogus_cts, max_general->bogus_cts);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "bogus_ack:",
+                     le32_to_cpu(general->bogus_ack), accum_general->bogus_ack,
+                     delta_general->bogus_ack, max_general->bogus_ack);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "non_bssid_frames:",
+                     le32_to_cpu(general->non_bssid_frames),
+                     accum_general->non_bssid_frames,
+                     delta_general->non_bssid_frames,
+                     max_general->non_bssid_frames);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "filtered_frames:",
+                     le32_to_cpu(general->filtered_frames),
+                     accum_general->filtered_frames,
+                     delta_general->filtered_frames,
+                     max_general->filtered_frames);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n",
+                     "non_channel_beacons:",
+                     le32_to_cpu(general->non_channel_beacons),
+                     accum_general->non_channel_beacons,
+                     delta_general->non_channel_beacons,
+                     max_general->non_channel_beacons);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+ssize_t
+il3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+                          size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       char *buf;
+       int bufsz = (sizeof(struct iwl39_stats_tx) * 48) + 250;
+       ssize_t ret;
+       struct iwl39_stats_tx *tx, *accum_tx, *delta_tx, *max_tx;
+
+       if (!il_is_alive(il))
+               return -EAGAIN;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       /*
+        * The statistic information display here is based on
+        * the last stats notification from uCode
+        * might not reflect the current uCode activity
+        */
+       tx = &il->_3945.stats.tx;
+       accum_tx = &il->_3945.accum_stats.tx;
+       delta_tx = &il->_3945.delta_stats.tx;
+       max_tx = &il->_3945.max_delta.tx;
+       pos += il3945_stats_flag(il, buf, bufsz);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "%-32s     current"
+                     "acumulative       delta         max\n",
+                     "Statistics_Tx:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "preamble:",
+                     le32_to_cpu(tx->preamble_cnt), accum_tx->preamble_cnt,
+                     delta_tx->preamble_cnt, max_tx->preamble_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "rx_detected_cnt:",
+                     le32_to_cpu(tx->rx_detected_cnt),
+                     accum_tx->rx_detected_cnt, delta_tx->rx_detected_cnt,
+                     max_tx->rx_detected_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "bt_prio_defer_cnt:",
+                     le32_to_cpu(tx->bt_prio_defer_cnt),
+                     accum_tx->bt_prio_defer_cnt, delta_tx->bt_prio_defer_cnt,
+                     max_tx->bt_prio_defer_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "bt_prio_kill_cnt:",
+                     le32_to_cpu(tx->bt_prio_kill_cnt),
+                     accum_tx->bt_prio_kill_cnt, delta_tx->bt_prio_kill_cnt,
+                     max_tx->bt_prio_kill_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "few_bytes_cnt:",
+                     le32_to_cpu(tx->few_bytes_cnt), accum_tx->few_bytes_cnt,
+                     delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "cts_timeout:",
+                     le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
+                     delta_tx->cts_timeout, max_tx->cts_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "ack_timeout:",
+                     le32_to_cpu(tx->ack_timeout), accum_tx->ack_timeout,
+                     delta_tx->ack_timeout, max_tx->ack_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "expected_ack_cnt:",
+                     le32_to_cpu(tx->expected_ack_cnt),
+                     accum_tx->expected_ack_cnt, delta_tx->expected_ack_cnt,
+                     max_tx->expected_ack_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "actual_ack_cnt:",
+                     le32_to_cpu(tx->actual_ack_cnt), accum_tx->actual_ack_cnt,
+                     delta_tx->actual_ack_cnt, max_tx->actual_ack_cnt);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+ssize_t
+il3945_ucode_general_stats_read(struct file *file, char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       char *buf;
+       int bufsz = sizeof(struct iwl39_stats_general) * 10 + 300;
+       ssize_t ret;
+       struct iwl39_stats_general *general, *accum_general;
+       struct iwl39_stats_general *delta_general, *max_general;
+       struct stats_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
+       struct iwl39_stats_div *div, *accum_div, *delta_div, *max_div;
+
+       if (!il_is_alive(il))
+               return -EAGAIN;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       /*
+        * The statistic information display here is based on
+        * the last stats notification from uCode
+        * might not reflect the current uCode activity
+        */
+       general = &il->_3945.stats.general;
+       dbg = &il->_3945.stats.general.dbg;
+       div = &il->_3945.stats.general.div;
+       accum_general = &il->_3945.accum_stats.general;
+       delta_general = &il->_3945.delta_stats.general;
+       max_general = &il->_3945.max_delta.general;
+       accum_dbg = &il->_3945.accum_stats.general.dbg;
+       delta_dbg = &il->_3945.delta_stats.general.dbg;
+       max_dbg = &il->_3945.max_delta.general.dbg;
+       accum_div = &il->_3945.accum_stats.general.div;
+       delta_div = &il->_3945.delta_stats.general.div;
+       max_div = &il->_3945.max_delta.general.div;
+       pos += il3945_stats_flag(il, buf, bufsz);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "%-32s     current"
+                     "acumulative       delta         max\n",
+                     "Statistics_General:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "burst_check:",
+                     le32_to_cpu(dbg->burst_check), accum_dbg->burst_check,
+                     delta_dbg->burst_check, max_dbg->burst_check);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "burst_count:",
+                     le32_to_cpu(dbg->burst_count), accum_dbg->burst_count,
+                     delta_dbg->burst_count, max_dbg->burst_count);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "sleep_time:",
+                     le32_to_cpu(general->sleep_time),
+                     accum_general->sleep_time, delta_general->sleep_time,
+                     max_general->sleep_time);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "slots_out:",
+                     le32_to_cpu(general->slots_out), accum_general->slots_out,
+                     delta_general->slots_out, max_general->slots_out);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "slots_idle:",
+                     le32_to_cpu(general->slots_idle),
+                     accum_general->slots_idle, delta_general->slots_idle,
+                     max_general->slots_idle);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
+                     le32_to_cpu(general->ttl_timestamp));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "tx_on_a:",
+                     le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
+                     delta_div->tx_on_a, max_div->tx_on_a);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "tx_on_b:",
+                     le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
+                     delta_div->tx_on_b, max_div->tx_on_b);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "exec_time:",
+                     le32_to_cpu(div->exec_time), accum_div->exec_time,
+                     delta_div->exec_time, max_div->exec_time);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "  %-30s %10u  %10u  %10u  %10u\n", "probe_time:",
+                     le32_to_cpu(div->probe_time), accum_div->probe_time,
+                     delta_div->probe_time, max_div->probe_time);
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c
new file mode 100644 (file)
index 0000000..daef6b5
--- /dev/null
@@ -0,0 +1,3977 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
+#include <net/ieee80211_radiotap.h>
+#include <net/mac80211.h>
+
+#include <asm/div64.h>
+
+#define DRV_NAME       "iwl3945"
+
+#include "commands.h"
+#include "common.h"
+#include "3945.h"
+#include "iwl-spectrum.h"
+
+/*
+ * module name, copyright, version, etc.
+ */
+
+#define DRV_DESCRIPTION        \
+"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+#define VD "d"
+#else
+#define VD
+#endif
+
+/*
+ * add "s" to indicate spectrum measurement included.
+ * we add it here to be consistent with previous releases in which
+ * this was configurable.
+ */
+#define DRV_VERSION  IWLWIFI_VERSION VD "s"
+#define DRV_COPYRIGHT  "Copyright(c) 2003-2011 Intel Corporation"
+#define DRV_AUTHOR     "<ilw@linux.intel.com>"
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+MODULE_LICENSE("GPL");
+
+ /* module parameters */
+struct il_mod_params il3945_mod_params = {
+       .sw_crypto = 1,
+       .restart_fw = 1,
+       .disable_hw_scan = 1,
+       /* the rest are 0 by default */
+};
+
+/**
+ * il3945_get_antenna_flags - Get antenna flags for RXON command
+ * @il: eeprom and antenna fields are used to determine antenna flags
+ *
+ * il->eeprom39  is used to determine if antenna AUX/MAIN are reversed
+ * il3945_mod_params.antenna specifies the antenna diversity mode:
+ *
+ * IL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
+ * IL_ANTENNA_MAIN      - Force MAIN antenna
+ * IL_ANTENNA_AUX       - Force AUX antenna
+ */
+__le32
+il3945_get_antenna_flags(const struct il_priv *il)
+{
+       struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
+
+       switch (il3945_mod_params.antenna) {
+       case IL_ANTENNA_DIVERSITY:
+               return 0;
+
+       case IL_ANTENNA_MAIN:
+               if (eeprom->antenna_switch_type)
+                       return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
+               return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
+
+       case IL_ANTENNA_AUX:
+               if (eeprom->antenna_switch_type)
+                       return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
+               return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
+       }
+
+       /* bad antenna selector value */
+       IL_ERR("Bad antenna selector value (0x%x)\n",
+              il3945_mod_params.antenna);
+
+       return 0;               /* "diversity" is default if error */
+}
+
+static int
+il3945_set_ccmp_dynamic_key_info(struct il_priv *il,
+                                struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+       unsigned long flags;
+       __le16 key_flags = 0;
+       int ret;
+
+       key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
+       key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+
+       if (sta_id == il->ctx.bcast_sta_id)
+               key_flags |= STA_KEY_MULTICAST_MSK;
+
+       keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+       keyconf->hw_key_idx = keyconf->keyidx;
+       key_flags &= ~STA_KEY_FLG_INVALID;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+       il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+       memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen);
+
+       memcpy(il->stations[sta_id].sta.key.key, keyconf->key, keyconf->keylen);
+
+       if ((il->stations[sta_id].sta.key.
+            key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
+               il->stations[sta_id].sta.key.key_offset =
+                   il_get_free_ucode_key_idx(il);
+       /* else, we are overriding an existing key => no need to allocated room
+        * in uCode. */
+
+       WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+            "no space for a new key");
+
+       il->stations[sta_id].sta.key.key_flags = key_flags;
+       il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+       il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+       D_INFO("hwcrypto: modify ucode station key info\n");
+
+       ret = il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC);
+
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return ret;
+}
+
+static int
+il3945_set_tkip_dynamic_key_info(struct il_priv *il,
+                                struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+       return -EOPNOTSUPP;
+}
+
+static int
+il3945_set_wep_dynamic_key_info(struct il_priv *il,
+                               struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+       return -EOPNOTSUPP;
+}
+
+static int
+il3945_clear_sta_key_info(struct il_priv *il, u8 sta_id)
+{
+       unsigned long flags;
+       struct il_addsta_cmd sta_cmd;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       memset(&il->stations[sta_id].keyinfo, 0, sizeof(struct il_hw_key));
+       memset(&il->stations[sta_id].sta.key, 0, sizeof(struct il4965_keyinfo));
+       il->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
+       il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+       il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+       memcpy(&sta_cmd, &il->stations[sta_id].sta,
+              sizeof(struct il_addsta_cmd));
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       D_INFO("hwcrypto: clear ucode station key info\n");
+       return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
+}
+
+static int
+il3945_set_dynamic_key(struct il_priv *il, struct ieee80211_key_conf *keyconf,
+                      u8 sta_id)
+{
+       int ret = 0;
+
+       keyconf->hw_key_idx = HW_KEY_DYNAMIC;
+
+       switch (keyconf->cipher) {
+       case WLAN_CIPHER_SUITE_CCMP:
+               ret = il3945_set_ccmp_dynamic_key_info(il, keyconf, sta_id);
+               break;
+       case WLAN_CIPHER_SUITE_TKIP:
+               ret = il3945_set_tkip_dynamic_key_info(il, keyconf, sta_id);
+               break;
+       case WLAN_CIPHER_SUITE_WEP40:
+       case WLAN_CIPHER_SUITE_WEP104:
+               ret = il3945_set_wep_dynamic_key_info(il, keyconf, sta_id);
+               break;
+       default:
+               IL_ERR("Unknown alg: %s alg=%x\n", __func__, keyconf->cipher);
+               ret = -EINVAL;
+       }
+
+       D_WEP("Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
+             keyconf->cipher, keyconf->keylen, keyconf->keyidx, sta_id, ret);
+
+       return ret;
+}
+
+static int
+il3945_remove_static_key(struct il_priv *il)
+{
+       int ret = -EOPNOTSUPP;
+
+       return ret;
+}
+
+static int
+il3945_set_static_key(struct il_priv *il, struct ieee80211_key_conf *key)
+{
+       if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+           key->cipher == WLAN_CIPHER_SUITE_WEP104)
+               return -EOPNOTSUPP;
+
+       IL_ERR("Static key invalid: cipher %x\n", key->cipher);
+       return -EINVAL;
+}
+
+static void
+il3945_clear_free_frames(struct il_priv *il)
+{
+       struct list_head *element;
+
+       D_INFO("%d frames on pre-allocated heap on clear.\n", il->frames_count);
+
+       while (!list_empty(&il->free_frames)) {
+               element = il->free_frames.next;
+               list_del(element);
+               kfree(list_entry(element, struct il3945_frame, list));
+               il->frames_count--;
+       }
+
+       if (il->frames_count) {
+               IL_WARN("%d frames still in use.  Did we lose one?\n",
+                       il->frames_count);
+               il->frames_count = 0;
+       }
+}
+
+static struct il3945_frame *
+il3945_get_free_frame(struct il_priv *il)
+{
+       struct il3945_frame *frame;
+       struct list_head *element;
+       if (list_empty(&il->free_frames)) {
+               frame = kzalloc(sizeof(*frame), GFP_KERNEL);
+               if (!frame) {
+                       IL_ERR("Could not allocate frame!\n");
+                       return NULL;
+               }
+
+               il->frames_count++;
+               return frame;
+       }
+
+       element = il->free_frames.next;
+       list_del(element);
+       return list_entry(element, struct il3945_frame, list);
+}
+
+static void
+il3945_free_frame(struct il_priv *il, struct il3945_frame *frame)
+{
+       memset(frame, 0, sizeof(*frame));
+       list_add(&frame->list, &il->free_frames);
+}
+
+unsigned int
+il3945_fill_beacon_frame(struct il_priv *il, struct ieee80211_hdr *hdr,
+                        int left)
+{
+
+       if (!il_is_associated(il) || !il->beacon_skb)
+               return 0;
+
+       if (il->beacon_skb->len > left)
+               return 0;
+
+       memcpy(hdr, il->beacon_skb->data, il->beacon_skb->len);
+
+       return il->beacon_skb->len;
+}
+
+static int
+il3945_send_beacon_cmd(struct il_priv *il)
+{
+       struct il3945_frame *frame;
+       unsigned int frame_size;
+       int rc;
+       u8 rate;
+
+       frame = il3945_get_free_frame(il);
+
+       if (!frame) {
+               IL_ERR("Could not obtain free frame buffer for beacon "
+                      "command.\n");
+               return -ENOMEM;
+       }
+
+       rate = il_get_lowest_plcp(il, &il->ctx);
+
+       frame_size = il3945_hw_get_beacon_cmd(il, frame, rate);
+
+       rc = il_send_cmd_pdu(il, C_TX_BEACON, frame_size, &frame->u.cmd[0]);
+
+       il3945_free_frame(il, frame);
+
+       return rc;
+}
+
+static void
+il3945_unset_hw_params(struct il_priv *il)
+{
+       if (il->_3945.shared_virt)
+               dma_free_coherent(&il->pci_dev->dev,
+                                 sizeof(struct il3945_shared),
+                                 il->_3945.shared_virt, il->_3945.shared_phys);
+}
+
+static void
+il3945_build_tx_cmd_hwcrypto(struct il_priv *il, struct ieee80211_tx_info *info,
+                            struct il_device_cmd *cmd,
+                            struct sk_buff *skb_frag, int sta_id)
+{
+       struct il3945_tx_cmd *tx_cmd = (struct il3945_tx_cmd *)cmd->cmd.payload;
+       struct il_hw_key *keyinfo = &il->stations[sta_id].keyinfo;
+
+       tx_cmd->sec_ctl = 0;
+
+       switch (keyinfo->cipher) {
+       case WLAN_CIPHER_SUITE_CCMP:
+               tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
+               memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
+               D_TX("tx_cmd with AES hwcrypto\n");
+               break;
+
+       case WLAN_CIPHER_SUITE_TKIP:
+               break;
+
+       case WLAN_CIPHER_SUITE_WEP104:
+               tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+               /* fall through */
+       case WLAN_CIPHER_SUITE_WEP40:
+               tx_cmd->sec_ctl |=
+                   TX_CMD_SEC_WEP | (info->control.hw_key->
+                                     hw_key_idx & TX_CMD_SEC_MSK) <<
+                   TX_CMD_SEC_SHIFT;
+
+               memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
+
+               D_TX("Configuring packet for WEP encryption " "with key %d\n",
+                    info->control.hw_key->hw_key_idx);
+               break;
+
+       default:
+               IL_ERR("Unknown encode cipher %x\n", keyinfo->cipher);
+               break;
+       }
+}
+
+/*
+ * handle build C_TX command notification.
+ */
+static void
+il3945_build_tx_cmd_basic(struct il_priv *il, struct il_device_cmd *cmd,
+                         struct ieee80211_tx_info *info,
+                         struct ieee80211_hdr *hdr, u8 std_id)
+{
+       struct il3945_tx_cmd *tx_cmd = (struct il3945_tx_cmd *)cmd->cmd.payload;
+       __le32 tx_flags = tx_cmd->tx_flags;
+       __le16 fc = hdr->frame_control;
+
+       tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+               tx_flags |= TX_CMD_FLG_ACK_MSK;
+               if (ieee80211_is_mgmt(fc))
+                       tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+               if (ieee80211_is_probe_resp(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;
+       }
+
+       tx_cmd->sta_id = std_id;
+       if (ieee80211_has_morefrags(fc))
+               tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
+
+       if (ieee80211_is_data_qos(fc)) {
+               u8 *qc = ieee80211_get_qos_ctl(hdr);
+               tx_cmd->tid_tspec = qc[0] & 0xf;
+               tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
+       } else {
+               tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+       }
+
+       il_tx_cmd_protection(il, info, fc, &tx_flags);
+
+       tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
+       if (ieee80211_is_mgmt(fc)) {
+               if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
+                       tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
+               else
+                       tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
+       } else {
+               tx_cmd->timeout.pm_frame_timeout = 0;
+       }
+
+       tx_cmd->driver_txop = 0;
+       tx_cmd->tx_flags = tx_flags;
+       tx_cmd->next_frame_len = 0;
+}
+
+/*
+ * start C_TX command process
+ */
+static int
+il3945_tx_skb(struct il_priv *il, struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct il3945_tx_cmd *tx_cmd;
+       struct il_tx_queue *txq = NULL;
+       struct il_queue *q = NULL;
+       struct il_device_cmd *out_cmd;
+       struct il_cmd_meta *out_meta;
+       dma_addr_t phys_addr;
+       dma_addr_t txcmd_phys;
+       int txq_id = skb_get_queue_mapping(skb);
+       u16 len, idx, hdr_len;
+       u8 id;
+       u8 unicast;
+       u8 sta_id;
+       u8 tid = 0;
+       __le16 fc;
+       u8 wait_write_ptr = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&il->lock, flags);
+       if (il_is_rfkill(il)) {
+               D_DROP("Dropping - RF KILL\n");
+               goto drop_unlock;
+       }
+
+       if ((ieee80211_get_tx_rate(il->hw, info)->hw_value & 0xFF) ==
+           IL_INVALID_RATE) {
+               IL_ERR("ERROR: No TX rate available.\n");
+               goto drop_unlock;
+       }
+
+       unicast = !is_multicast_ether_addr(hdr->addr1);
+       id = 0;
+
+       fc = hdr->frame_control;
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+       if (ieee80211_is_auth(fc))
+               D_TX("Sending AUTH frame\n");
+       else if (ieee80211_is_assoc_req(fc))
+               D_TX("Sending ASSOC frame\n");
+       else if (ieee80211_is_reassoc_req(fc))
+               D_TX("Sending REASSOC frame\n");
+#endif
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       hdr_len = ieee80211_hdrlen(fc);
+
+       /* Find idx into station table for destination station */
+       sta_id = il_sta_id_or_broadcast(il, &il->ctx, info->control.sta);
+       if (sta_id == IL_INVALID_STATION) {
+               D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1);
+               goto drop;
+       }
+
+       D_RATE("station Id %d\n", sta_id);
+
+       if (ieee80211_is_data_qos(fc)) {
+               u8 *qc = ieee80211_get_qos_ctl(hdr);
+               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+               if (unlikely(tid >= MAX_TID_COUNT))
+                       goto drop;
+       }
+
+       /* Descriptor for chosen Tx queue */
+       txq = &il->txq[txq_id];
+       q = &txq->q;
+
+       if ((il_queue_space(q) < q->high_mark))
+               goto drop;
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       idx = il_get_cmd_idx(q, q->write_ptr, 0);
+
+       /* Set up driver data for this TFD */
+       memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct il_tx_info));
+       txq->txb[q->write_ptr].skb = skb;
+       txq->txb[q->write_ptr].ctx = &il->ctx;
+
+       /* Init first empty entry in queue's array of Tx/cmd buffers */
+       out_cmd = txq->cmd[idx];
+       out_meta = &txq->meta[idx];
+       tx_cmd = (struct il3945_tx_cmd *)out_cmd->cmd.payload;
+       memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
+       memset(tx_cmd, 0, sizeof(*tx_cmd));
+
+       /*
+        * Set up the Tx-command (not MAC!) header.
+        * Store the chosen Tx queue and TFD idx within the sequence field;
+        * after Tx, uCode's Tx response will return this value so driver can
+        * locate the frame within the tx queue and do post-tx processing.
+        */
+       out_cmd->hdr.cmd = C_TX;
+       out_cmd->hdr.sequence =
+           cpu_to_le16((u16)
+                       (QUEUE_TO_SEQ(txq_id) | IDX_TO_SEQ(q->write_ptr)));
+
+       /* Copy MAC header from skb into command buffer */
+       memcpy(tx_cmd->hdr, hdr, hdr_len);
+
+       if (info->control.hw_key)
+               il3945_build_tx_cmd_hwcrypto(il, info, out_cmd, skb, sta_id);
+
+       /* TODO need this for burst mode later on */
+       il3945_build_tx_cmd_basic(il, out_cmd, info, hdr, sta_id);
+
+       /* set is_hcca to 0; it probably will never be implemented */
+       il3945_hw_build_tx_cmd_rate(il, out_cmd, info, hdr, sta_id, 0);
+
+       /* Total # bytes to be transmitted */
+       len = (u16) skb->len;
+       tx_cmd->len = cpu_to_le16(len);
+
+       il_dbg_log_tx_data_frame(il, len, hdr);
+       il_update_stats(il, true, fc, len);
+       tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
+       tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
+
+       if (!ieee80211_has_morefrags(hdr->frame_control)) {
+               txq->need_update = 1;
+       } else {
+               wait_write_ptr = 1;
+               txq->need_update = 0;
+       }
+
+       D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence));
+       D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
+       il_print_hex_dump(il, IL_DL_TX, tx_cmd, sizeof(*tx_cmd));
+       il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd->hdr,
+                         ieee80211_hdrlen(fc));
+
+       /*
+        * Use the first empty entry in this queue's command buffer array
+        * to contain the Tx command and MAC header concatenated together
+        * (payload data will be in another buffer).
+        * Size of this varies, due to varying MAC header length.
+        * If end is not dword aligned, we'll have 2 extra bytes at the end
+        * of the MAC header (device reads on dword boundaries).
+        * We'll tell device about this padding later.
+        */
+       len =
+           sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) +
+           hdr_len;
+       len = (len + 3) & ~3;
+
+       /* Physical address of this Tx command's header (not MAC header!),
+        * within command buffer array. */
+       txcmd_phys =
+           pci_map_single(il->pci_dev, &out_cmd->hdr, len, PCI_DMA_TODEVICE);
+       /* we do not map meta data ... so we can safely access address to
+        * provide to unmap command*/
+       dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+       dma_unmap_len_set(out_meta, len, len);
+
+       /* Add buffer containing Tx command and MAC(!) header to TFD's
+        * first entry */
+       il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1,
+                                                0);
+
+       /* Set up TFD's 2nd entry to point directly to remainder of skb,
+        * if any (802.11 null frames have no payload). */
+       len = skb->len - hdr_len;
+       if (len) {
+               phys_addr =
+                   pci_map_single(il->pci_dev, skb->data + hdr_len, len,
+                                  PCI_DMA_TODEVICE);
+               il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr,
+                                                        len, 0, U32_PAD(len));
+       }
+
+       /* Tell device the write idx *just past* this latest filled TFD */
+       q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);
+       il_txq_update_write_ptr(il, txq);
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       if (il_queue_space(q) < q->high_mark && il->mac80211_registered) {
+               if (wait_write_ptr) {
+                       spin_lock_irqsave(&il->lock, flags);
+                       txq->need_update = 1;
+                       il_txq_update_write_ptr(il, txq);
+                       spin_unlock_irqrestore(&il->lock, flags);
+               }
+
+               il_stop_queue(il, txq);
+       }
+
+       return 0;
+
+drop_unlock:
+       spin_unlock_irqrestore(&il->lock, flags);
+drop:
+       return -1;
+}
+
+static int
+il3945_get_measurement(struct il_priv *il,
+                      struct ieee80211_measurement_params *params, u8 type)
+{
+       struct il_spectrum_cmd spectrum;
+       struct il_rx_pkt *pkt;
+       struct il_host_cmd cmd = {
+               .id = C_SPECTRUM_MEASUREMENT,
+               .data = (void *)&spectrum,
+               .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);
+       struct il_rxon_context *ctx = &il->ctx;
+
+       if (il_is_associated(il))
+               add_time =
+                   il_usecs_to_beacons(il,
+                                       le64_to_cpu(params->start_time) -
+                                       il->_3945.last_tsf,
+                                       le16_to_cpu(ctx->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 (il_is_associated(il))
+               spectrum.start_time =
+                   il_add_beacon_time(il, il->_3945.last_beacon_time, add_time,
+                                      le16_to_cpu(ctx->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 (ctx->active.flags & RXON_FLG_BAND_24G_MSK)
+               spectrum.flags |=
+                   RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK |
+                   RXON_FLG_TGG_PROTECT_MSK;
+
+       rc = il_send_cmd_sync(il, &cmd);
+       if (rc)
+               return rc;
+
+       pkt = (struct il_rx_pkt *)cmd.reply_page;
+       if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
+               IL_ERR("Bad return from N_RX_ON_ASSOC command\n");
+               rc = -EIO;
+       }
+
+       spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
+       switch (spectrum_resp_status) {
+       case 0:         /* Command will be handled */
+               if (pkt->u.spectrum.id != 0xff) {
+                       D_INFO("Replaced existing measurement: %d\n",
+                              pkt->u.spectrum.id);
+                       il->measurement_status &= ~MEASUREMENT_READY;
+               }
+               il->measurement_status |= MEASUREMENT_ACTIVE;
+               rc = 0;
+               break;
+
+       case 1:         /* Command will not be handled */
+               rc = -EAGAIN;
+               break;
+       }
+
+       il_free_pages(il, cmd.reply_page);
+
+       return rc;
+}
+
+static void
+il3945_hdl_alive(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_alive_resp *palive;
+       struct delayed_work *pwork;
+
+       palive = &pkt->u.alive_frame;
+
+       D_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) {
+               D_INFO("Initialization Alive received.\n");
+               memcpy(&il->card_alive_init, &pkt->u.alive_frame,
+                      sizeof(struct il_alive_resp));
+               pwork = &il->init_alive_start;
+       } else {
+               D_INFO("Runtime Alive received.\n");
+               memcpy(&il->card_alive, &pkt->u.alive_frame,
+                      sizeof(struct il_alive_resp));
+               pwork = &il->alive_start;
+               il3945_disable_events(il);
+       }
+
+       /* 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(il->workqueue, pwork, msecs_to_jiffies(5));
+       else
+               IL_WARN("uCode did not respond OK.\n");
+}
+
+static void
+il3945_hdl_add_sta(struct il_priv *il, struct il_rx_buf *rxb)
+{
+#ifdef CONFIG_IWLEGACY_DEBUG
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+#endif
+
+       D_RX("Received C_ADD_STA: 0x%02X\n", pkt->u.status);
+}
+
+static void
+il3945_hdl_beacon(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il3945_beacon_notif *beacon = &(pkt->u.beacon_status);
+#ifdef CONFIG_IWLEGACY_DEBUG
+       u8 rate = beacon->beacon_notify_hdr.rate;
+
+       D_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
+
+       il->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+
+}
+
+/* Handle notification from uCode that card's power state is changing
+ * due to software, hardware, or critical temperature RFKILL */
+static void
+il3945_hdl_card_state(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
+       unsigned long status = il->status;
+
+       IL_WARN("Card state received: HW:%s SW:%s\n",
+               (flags & HW_CARD_DISABLED) ? "Kill" : "On",
+               (flags & SW_CARD_DISABLED) ? "Kill" : "On");
+
+       _il_wr(il, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+       if (flags & HW_CARD_DISABLED)
+               set_bit(S_RF_KILL_HW, &il->status);
+       else
+               clear_bit(S_RF_KILL_HW, &il->status);
+
+       il_scan_cancel(il);
+
+       if ((test_bit(S_RF_KILL_HW, &status) !=
+            test_bit(S_RF_KILL_HW, &il->status)))
+               wiphy_rfkill_set_hw_state(il->hw->wiphy,
+                                         test_bit(S_RF_KILL_HW, &il->status));
+       else
+               wake_up(&il->wait_command_queue);
+}
+
+/**
+ * il3945_setup_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
+il3945_setup_handlers(struct il_priv *il)
+{
+       il->handlers[N_ALIVE] = il3945_hdl_alive;
+       il->handlers[C_ADD_STA] = il3945_hdl_add_sta;
+       il->handlers[N_ERROR] = il_hdl_error;
+       il->handlers[N_CHANNEL_SWITCH] = il_hdl_csa;
+       il->handlers[N_SPECTRUM_MEASUREMENT] = il_hdl_spectrum_measurement;
+       il->handlers[N_PM_SLEEP] = il_hdl_pm_sleep;
+       il->handlers[N_PM_DEBUG_STATS] = il_hdl_pm_debug_stats;
+       il->handlers[N_BEACON] = il3945_hdl_beacon;
+
+       /*
+        * The same handler is used for both the REPLY to a discrete
+        * stats request from the host as well as for the periodic
+        * stats notifications (after received beacons) from the uCode.
+        */
+       il->handlers[C_STATS] = il3945_hdl_c_stats;
+       il->handlers[N_STATS] = il3945_hdl_stats;
+
+       il_setup_rx_scan_handlers(il);
+       il->handlers[N_CARD_STATE] = il3945_hdl_card_state;
+
+       /* Set up hardware specific Rx handlers */
+       il3945_hw_handler_setup(il);
+}
+
+/************************** RX-FUNCTIONS ****************************/
+/*
+ * Rx theory of operation
+ *
+ * The host allocates 32 DMA target addresses and passes the host address
+ * to the firmware at register IL_RFDS_TBL_LOWER + N * RFD_SIZE where N is
+ * 0 to 31
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two idx registers for managing the Rx buffers.
+ *
+ * The READ idx 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 idx is managed by the firmware once the card is enabled.
+ *
+ * The WRITE idx 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
+ * IDX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer, it will advance the READ idx
+ * and fire the RX interrupt.  The driver can then query the READ idx and
+ * process as many packets as possible, moving the WRITE idx 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 iwl->rxq->rx_free.  When
+ *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ *   to replenish the iwl->rxq->rx_free.
+ * + In il3945_rx_replenish (scheduled) if 'processed' != 'read' then the
+ *   iwl->rxq is replenished and the READ IDX is updated (updating the
+ *   'processed' and 'read' driver idxes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ *   detached from the iwl->rxq.  The driver 'processed' idx is updated.
+ * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
+ *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
+ *   IDX is not incremented and iwl->status(RX_STALLED) is set.  If there
+ *   were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * il3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
+ *                            il3945_rx_queue_restock
+ * il3945_rx_queue_restock() Moves available buffers from rx_free into Rx
+ *                            queue, updates firmware pointers, and updates
+ *                            the WRITE idx.  If insufficient rx_free buffers
+ *                            are available, schedules il3945_rx_replenish
+ *
+ * -- enable interrupts --
+ * ISR - il3945_rx()         Detach il_rx_bufs from pool up to the
+ *                            READ IDX, detaching the SKB from the pool.
+ *                            Moves the packet buffer from queue to rx_used.
+ *                            Calls il3945_rx_queue_restock to refill any empty
+ *                            slots.
+ * ...
+ *
+ */
+
+/**
+ * il3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32
+il3945_dma_addr2rbd_ptr(struct il_priv *il, dma_addr_t dma_addr)
+{
+       return cpu_to_le32((u32) dma_addr);
+}
+
+/**
+ * il3945_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' idx forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+static void
+il3945_rx_queue_restock(struct il_priv *il)
+{
+       struct il_rx_queue *rxq = &il->rxq;
+       struct list_head *element;
+       struct il_rx_buf *rxb;
+       unsigned long flags;
+       int write;
+
+       spin_lock_irqsave(&rxq->lock, flags);
+       write = rxq->write & ~0x7;
+       while (il_rx_queue_space(rxq) > 0 && rxq->free_count) {
+               /* Get next free Rx buffer, remove from free list */
+               element = rxq->rx_free.next;
+               rxb = list_entry(element, struct il_rx_buf, list);
+               list_del(element);
+
+               /* Point to Rx buffer via next RBD in circular buffer */
+               rxq->bd[rxq->write] =
+                   il3945_dma_addr2rbd_ptr(il, rxb->page_dma);
+               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(il->workqueue, &il->rx_replenish);
+
+       /* If we've added more space for the firmware to place data, tell it.
+        * Increment device's write pointer in multiples of 8. */
+       if (rxq->write_actual != (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);
+               il_rx_queue_update_write_ptr(il, rxq);
+       }
+}
+
+/**
+ * il3945_rx_replenish - 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 il3945_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
+ */
+static void
+il3945_rx_allocate(struct il_priv *il, gfp_t priority)
+{
+       struct il_rx_queue *rxq = &il->rxq;
+       struct list_head *element;
+       struct il_rx_buf *rxb;
+       struct page *page;
+       unsigned long flags;
+       gfp_t gfp_mask = priority;
+
+       while (1) {
+               spin_lock_irqsave(&rxq->lock, flags);
+
+               if (list_empty(&rxq->rx_used)) {
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       return;
+               }
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               if (rxq->free_count > RX_LOW_WATERMARK)
+                       gfp_mask |= __GFP_NOWARN;
+
+               if (il->hw_params.rx_page_order > 0)
+                       gfp_mask |= __GFP_COMP;
+
+               /* Alloc a new receive buffer */
+               page = alloc_pages(gfp_mask, il->hw_params.rx_page_order);
+               if (!page) {
+                       if (net_ratelimit())
+                               D_INFO("Failed to allocate SKB buffer.\n");
+                       if (rxq->free_count <= RX_LOW_WATERMARK &&
+                           net_ratelimit())
+                               IL_ERR("Failed to allocate SKB buffer with %0x."
+                                      "Only %u free buffers remaining.\n",
+                                      priority, rxq->free_count);
+                       /* 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;
+               }
+
+               spin_lock_irqsave(&rxq->lock, flags);
+               if (list_empty(&rxq->rx_used)) {
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       __free_pages(page, il->hw_params.rx_page_order);
+                       return;
+               }
+               element = rxq->rx_used.next;
+               rxb = list_entry(element, struct il_rx_buf, list);
+               list_del(element);
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               rxb->page = page;
+               /* Get physical address of RB/SKB */
+               rxb->page_dma =
+                   pci_map_page(il->pci_dev, page, 0,
+                                PAGE_SIZE << il->hw_params.rx_page_order,
+                                PCI_DMA_FROMDEVICE);
+
+               spin_lock_irqsave(&rxq->lock, flags);
+
+               list_add_tail(&rxb->list, &rxq->rx_free);
+               rxq->free_count++;
+               il->alloc_rxb_page++;
+
+               spin_unlock_irqrestore(&rxq->lock, flags);
+       }
+}
+
+void
+il3945_rx_queue_reset(struct il_priv *il, struct il_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].page != NULL) {
+                       pci_unmap_page(il->pci_dev, rxq->pool[i].page_dma,
+                                      PAGE_SIZE << il->hw_params.rx_page_order,
+                                      PCI_DMA_FROMDEVICE);
+                       __il_free_pages(il, rxq->pool[i].page);
+                       rxq->pool[i].page = 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->write_actual = 0;
+       rxq->free_count = 0;
+       spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
+void
+il3945_rx_replenish(void *data)
+{
+       struct il_priv *il = data;
+       unsigned long flags;
+
+       il3945_rx_allocate(il, GFP_KERNEL);
+
+       spin_lock_irqsave(&il->lock, flags);
+       il3945_rx_queue_restock(il);
+       spin_unlock_irqrestore(&il->lock, flags);
+}
+
+static void
+il3945_rx_replenish_now(struct il_priv *il)
+{
+       il3945_rx_allocate(il, GFP_ATOMIC);
+
+       il3945_rx_queue_restock(il);
+}
+
+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
+ * If an SKB has been detached, the POOL needs to have its 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
+ */
+static void
+il3945_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq)
+{
+       int i;
+       for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+               if (rxq->pool[i].page != NULL) {
+                       pci_unmap_page(il->pci_dev, rxq->pool[i].page_dma,
+                                      PAGE_SIZE << il->hw_params.rx_page_order,
+                                      PCI_DMA_FROMDEVICE);
+                       __il_free_pages(il, rxq->pool[i].page);
+                       rxq->pool[i].page = NULL;
+               }
+       }
+
+       dma_free_coherent(&il->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+                         rxq->bd_dma);
+       dma_free_coherent(&il->pci_dev->dev, sizeof(struct il_rb_status),
+                         rxq->rb_stts, rxq->rb_stts_dma);
+       rxq->bd = NULL;
+       rxq->rb_stts = NULL;
+}
+
+/* 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
+il3945_calc_db_from_ratio(int sig_ratio)
+{
+       /* 1000:1 or higher just report as 60 dB */
+       if (sig_ratio >= 1000)
+               return 60;
+
+       /* 100:1 or higher, 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];
+}
+
+/**
+ * il3945_rx_handle - Main entry function for receiving responses from uCode
+ *
+ * Uses the il->handlers callback function array to invoke
+ * the appropriate handlers, including command responses,
+ * frame-received notifications, and other notifications.
+ */
+static void
+il3945_rx_handle(struct il_priv *il)
+{
+       struct il_rx_buf *rxb;
+       struct il_rx_pkt *pkt;
+       struct il_rx_queue *rxq = &il->rxq;
+       u32 r, i;
+       int reclaim;
+       unsigned long flags;
+       u8 fill_rx = 0;
+       u32 count = 8;
+       int total_empty = 0;
+
+       /* uCode's read idx (stored in shared DRAM) indicates the last Rx
+        * buffer that the driver may process (last buffer filled by ucode). */
+       r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
+       i = rxq->read;
+
+       /* calculate total frames need to be restock after handling RX */
+       total_empty = r - rxq->write_actual;
+       if (total_empty < 0)
+               total_empty += RX_QUEUE_SIZE;
+
+       if (total_empty > (RX_QUEUE_SIZE / 2))
+               fill_rx = 1;
+       /* Rx interrupt, but nothing sent from uCode */
+       if (i == r)
+               D_RX("r = %d, i = %d\n", r, i);
+
+       while (i != r) {
+               int len;
+
+               rxb = rxq->queue[i];
+
+               /* If an RXB doesn't have a Rx 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_unmap_page(il->pci_dev, rxb->page_dma,
+                              PAGE_SIZE << il->hw_params.rx_page_order,
+                              PCI_DMA_FROMDEVICE);
+               pkt = rxb_addr(rxb);
+
+               len = le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK;
+               len += sizeof(u32);     /* account for status word */
+
+               /* 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 != N_STATS && pkt->hdr.cmd != C_TX;
+
+               /* Based on type of command response or notification,
+                *   handle those that need handling via function in
+                *   handlers table.  See il3945_setup_handlers() */
+               if (il->handlers[pkt->hdr.cmd]) {
+                       D_RX("r = %d, i = %d, %s, 0x%02x\n", r, i,
+                            il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+                       il->isr_stats.handlers[pkt->hdr.cmd]++;
+                       il->handlers[pkt->hdr.cmd] (il, rxb);
+               } else {
+                       /* No handling needed */
+                       D_RX("r %d i %d No handler needed for %s, 0x%02x\n", r,
+                            i, il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+               }
+
+               /*
+                * XXX: After here, we should always check rxb->page
+                * against NULL before touching it or its virtual
+                * memory (pkt). Because some handler might have
+                * already taken or freed the pages.
+                */
+
+               if (reclaim) {
+                       /* Invoke any callbacks, transfer the buffer to caller,
+                        * and fire off the (possibly) blocking il_send_cmd()
+                        * as we reclaim the driver command queue */
+                       if (rxb->page)
+                               il_tx_cmd_complete(il, rxb);
+                       else
+                               IL_WARN("Claim null rxb?\n");
+               }
+
+               /* Reuse the page if possible. For notification packets and
+                * SKBs that fail to Rx correctly, add them back into the
+                * rx_free list for reuse later. */
+               spin_lock_irqsave(&rxq->lock, flags);
+               if (rxb->page != NULL) {
+                       rxb->page_dma =
+                           pci_map_page(il->pci_dev, rxb->page, 0,
+                                        PAGE_SIZE << il->hw_params.
+                                        rx_page_order, PCI_DMA_FROMDEVICE);
+                       list_add_tail(&rxb->list, &rxq->rx_free);
+                       rxq->free_count++;
+               } else
+                       list_add_tail(&rxb->list, &rxq->rx_used);
+
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               i = (i + 1) & RX_QUEUE_MASK;
+               /* If there are a lot of unused frames,
+                * restock the Rx queue so ucode won't assert. */
+               if (fill_rx) {
+                       count++;
+                       if (count >= 8) {
+                               rxq->read = i;
+                               il3945_rx_replenish_now(il);
+                               count = 0;
+                       }
+               }
+       }
+
+       /* Backtrack one entry */
+       rxq->read = i;
+       if (fill_rx)
+               il3945_rx_replenish_now(il);
+       else
+               il3945_rx_queue_restock(il);
+}
+
+/* call this function to flush any scheduled tasklet */
+static inline void
+il3945_synchronize_irq(struct il_priv *il)
+{
+       /* wait to make sure we flush pending tasklet */
+       synchronize_irq(il->pci_dev->irq);
+       tasklet_kill(&il->irq_tasklet);
+}
+
+static const char *
+il3945_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))
+
+void
+il3945_dump_nic_error_log(struct il_priv *il)
+{
+       u32 i;
+       u32 desc, time, count, base, data1;
+       u32 blink1, blink2, ilink1, ilink2;
+
+       base = le32_to_cpu(il->card_alive.error_event_table_ptr);
+
+       if (!il3945_hw_valid_rtc_data_addr(base)) {
+               IL_ERR("Not valid error log pointer 0x%08X\n", base);
+               return;
+       }
+
+       count = il_read_targ_mem(il, base);
+
+       if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+               IL_ERR("Start IWL Error Log Dump:\n");
+               IL_ERR("Status: 0x%08lX, count: %d\n", il->status, count);
+       }
+
+       IL_ERR("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 = il_read_targ_mem(il, base + i);
+               time = il_read_targ_mem(il, base + i + 1 * sizeof(u32));
+               blink1 = il_read_targ_mem(il, base + i + 2 * sizeof(u32));
+               blink2 = il_read_targ_mem(il, base + i + 3 * sizeof(u32));
+               ilink1 = il_read_targ_mem(il, base + i + 4 * sizeof(u32));
+               ilink2 = il_read_targ_mem(il, base + i + 5 * sizeof(u32));
+               data1 = il_read_targ_mem(il, base + i + 6 * sizeof(u32));
+
+               IL_ERR("%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
+                      il3945_desc_lookup(desc), desc, time, blink1, blink2,
+                      ilink1, ilink2, data1);
+       }
+}
+
+static void
+il3945_irq_tasklet(struct il_priv *il)
+{
+       u32 inta, handled = 0;
+       u32 inta_fh;
+       unsigned long flags;
+#ifdef CONFIG_IWLEGACY_DEBUG
+       u32 inta_mask;
+#endif
+
+       spin_lock_irqsave(&il->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 = _il_rd(il, CSR_INT);
+       _il_wr(il, 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 = _il_rd(il, CSR_FH_INT_STATUS);
+       _il_wr(il, CSR_FH_INT_STATUS, inta_fh);
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+       if (il_get_debug_level(il) & IL_DL_ISR) {
+               /* just for debug */
+               inta_mask = _il_rd(il, CSR_INT_MASK);
+               D_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta,
+                     inta_mask, inta_fh);
+       }
+#endif
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       /* 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 & CSR39_FH_INT_RX_MASK)
+               inta |= CSR_INT_BIT_FH_RX;
+       if (inta_fh & CSR39_FH_INT_TX_MASK)
+               inta |= CSR_INT_BIT_FH_TX;
+
+       /* Now service all interrupt bits discovered above. */
+       if (inta & CSR_INT_BIT_HW_ERR) {
+               IL_ERR("Hardware error detected.  Restarting.\n");
+
+               /* Tell the device to stop sending interrupts */
+               il_disable_interrupts(il);
+
+               il->isr_stats.hw++;
+               il_irq_handle_error(il);
+
+               handled |= CSR_INT_BIT_HW_ERR;
+
+               return;
+       }
+#ifdef CONFIG_IWLEGACY_DEBUG
+       if (il_get_debug_level(il) & (IL_DL_ISR)) {
+               /* NIC fires this, but we don't use it, redundant with WAKEUP */
+               if (inta & CSR_INT_BIT_SCD) {
+                       D_ISR("Scheduler finished to transmit "
+                             "the frame/frames.\n");
+                       il->isr_stats.sch++;
+               }
+
+               /* Alive notification via Rx interrupt will do the real work */
+               if (inta & CSR_INT_BIT_ALIVE) {
+                       D_ISR("Alive interrupt\n");
+                       il->isr_stats.alive++;
+               }
+       }
+#endif
+       /* Safely ignore these bits for debug checks below */
+       inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
+
+       /* Error detected by uCode */
+       if (inta & CSR_INT_BIT_SW_ERR) {
+               IL_ERR("Microcode SW error detected. " "Restarting 0x%X.\n",
+                      inta);
+               il->isr_stats.sw++;
+               il_irq_handle_error(il);
+               handled |= CSR_INT_BIT_SW_ERR;
+       }
+
+       /* uCode wakes up after power-down sleep */
+       if (inta & CSR_INT_BIT_WAKEUP) {
+               D_ISR("Wakeup interrupt\n");
+               il_rx_queue_update_write_ptr(il, &il->rxq);
+               il_txq_update_write_ptr(il, &il->txq[0]);
+               il_txq_update_write_ptr(il, &il->txq[1]);
+               il_txq_update_write_ptr(il, &il->txq[2]);
+               il_txq_update_write_ptr(il, &il->txq[3]);
+               il_txq_update_write_ptr(il, &il->txq[4]);
+               il_txq_update_write_ptr(il, &il->txq[5]);
+
+               il->isr_stats.wakeup++;
+               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)) {
+               il3945_rx_handle(il);
+               il->isr_stats.rx++;
+               handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
+       }
+
+       if (inta & CSR_INT_BIT_FH_TX) {
+               D_ISR("Tx interrupt\n");
+               il->isr_stats.tx++;
+
+               _il_wr(il, CSR_FH_INT_STATUS, (1 << 6));
+               il_wr(il, FH39_TCSR_CREDIT(FH39_SRVC_CHNL), 0x0);
+               handled |= CSR_INT_BIT_FH_TX;
+       }
+
+       if (inta & ~handled) {
+               IL_ERR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
+               il->isr_stats.unhandled++;
+       }
+
+       if (inta & ~il->inta_mask) {
+               IL_WARN("Disabled INTA bits 0x%08x were pending\n",
+                       inta & ~il->inta_mask);
+               IL_WARN("   with inta_fh = 0x%08x\n", inta_fh);
+       }
+
+       /* Re-enable all interrupts */
+       /* only Re-enable if disabled by irq */
+       if (test_bit(S_INT_ENABLED, &il->status))
+               il_enable_interrupts(il);
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+       if (il_get_debug_level(il) & (IL_DL_ISR)) {
+               inta = _il_rd(il, CSR_INT);
+               inta_mask = _il_rd(il, CSR_INT_MASK);
+               inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
+               D_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
+                     "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
+       }
+#endif
+}
+
+static int
+il3945_get_channels_for_scan(struct il_priv *il, enum ieee80211_band band,
+                            u8 is_active, u8 n_probes,
+                            struct il3945_scan_channel *scan_ch,
+                            struct ieee80211_vif *vif)
+{
+       struct ieee80211_channel *chan;
+       const struct ieee80211_supported_band *sband;
+       const struct il_channel_info *ch_info;
+       u16 passive_dwell = 0;
+       u16 active_dwell = 0;
+       int added, i;
+
+       sband = il_get_hw_mode(il, band);
+       if (!sband)
+               return 0;
+
+       active_dwell = il_get_active_dwell_time(il, band, n_probes);
+       passive_dwell = il_get_passive_dwell_time(il, band, vif);
+
+       if (passive_dwell <= active_dwell)
+               passive_dwell = active_dwell + 1;
+
+       for (i = 0, added = 0; i < il->scan_request->n_channels; i++) {
+               chan = il->scan_request->channels[i];
+
+               if (chan->band != band)
+                       continue;
+
+               scan_ch->channel = chan->hw_value;
+
+               ch_info = il_get_channel_info(il, band, scan_ch->channel);
+               if (!il_is_channel_valid(ch_info)) {
+                       D_SCAN("Channel %d is INVALID for this band.\n",
+                              scan_ch->channel);
+                       continue;
+               }
+
+               scan_ch->active_dwell = cpu_to_le16(active_dwell);
+               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+               /* If passive , set up for auto-switch
+                *  and use long active_dwell time.
+                */
+               if (!is_active || il_is_channel_passive(ch_info) ||
+                   (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
+                       scan_ch->type = 0;      /* passive */
+                       if (IL_UCODE_API(il->ucode_ver) == 1)
+                               scan_ch->active_dwell =
+                                   cpu_to_le16(passive_dwell - 1);
+               } else {
+                       scan_ch->type = 1;      /* active */
+               }
+
+               /* Set direct probe bits. These may be used both for active
+                * scan channels (probes gets sent right away),
+                * or for passive channels (probes get se sent only after
+                * hearing clear Rx packet).*/
+               if (IL_UCODE_API(il->ucode_ver) >= 2) {
+                       if (n_probes)
+                               scan_ch->type |= IL39_SCAN_PROBE_MASK(n_probes);
+               } else {
+                       /* uCode v1 does not allow setting direct probe bits on
+                        * passive channel. */
+                       if ((scan_ch->type & 1) && n_probes)
+                               scan_ch->type |= IL39_SCAN_PROBE_MASK(n_probes);
+               }
+
+               /* Set txpower levels to defaults */
+               scan_ch->tpc.dsp_atten = 110;
+               /* scan_pwr_info->tpc.dsp_atten; */
+
+               /*scan_pwr_info->tpc.tx_gain; */
+               if (band == IEEE80211_BAND_5GHZ)
+                       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;
+                        */
+               }
+
+               D_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++;
+       }
+
+       D_SCAN("total channels to scan %d\n", added);
+       return added;
+}
+
+static void
+il3945_init_hw_rates(struct il_priv *il, struct ieee80211_rate *rates)
+{
+       int i;
+
+       for (i = 0; i < RATE_COUNT_LEGACY; i++) {
+               rates[i].bitrate = il3945_rates[i].ieee * 5;
+               rates[i].hw_value = i;  /* Rate scaling will work on idxes */
+               rates[i].hw_value_short = i;
+               rates[i].flags = 0;
+               if (i > IL39_LAST_OFDM_RATE || i < IL_FIRST_OFDM_RATE) {
+                       /*
+                        * If CCK != 1M then set short preamble rate flag.
+                        */
+                       rates[i].flags |=
+                           (il3945_rates[i].plcp ==
+                            10) ? 0 : IEEE80211_RATE_SHORT_PREAMBLE;
+               }
+       }
+}
+
+/******************************************************************************
+ *
+ * uCode download functions
+ *
+ ******************************************************************************/
+
+static void
+il3945_dealloc_ucode_pci(struct il_priv *il)
+{
+       il_free_fw_desc(il->pci_dev, &il->ucode_code);
+       il_free_fw_desc(il->pci_dev, &il->ucode_data);
+       il_free_fw_desc(il->pci_dev, &il->ucode_data_backup);
+       il_free_fw_desc(il->pci_dev, &il->ucode_init);
+       il_free_fw_desc(il->pci_dev, &il->ucode_init_data);
+       il_free_fw_desc(il->pci_dev, &il->ucode_boot);
+}
+
+/**
+ * il3945_verify_inst_full - verify runtime uCode image in card vs. host,
+ *     looking at all data.
+ */
+static int
+il3945_verify_inst_full(struct il_priv *il, __le32 * image, u32 len)
+{
+       u32 val;
+       u32 save_len = len;
+       int rc = 0;
+       u32 errcnt;
+
+       D_INFO("ucode inst image size is %u\n", len);
+
+       il_wr(il, HBUS_TARG_MEM_RADDR, IL39_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 IL_DL_IO is set */
+               val = _il_rd(il, HBUS_TARG_MEM_RDAT);
+               if (val != le32_to_cpu(*image)) {
+                       IL_ERR("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;
+               }
+       }
+
+       if (!errcnt)
+               D_INFO("ucode image in INSTRUCTION memory is good\n");
+
+       return rc;
+}
+
+/**
+ * il3945_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
+il3945_verify_inst_sparse(struct il_priv *il, __le32 * image, u32 len)
+{
+       u32 val;
+       int rc = 0;
+       u32 errcnt = 0;
+       u32 i;
+
+       D_INFO("ucode inst image size is %u\n", len);
+
+       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 IL_DL_IO is set */
+               il_wr(il, HBUS_TARG_MEM_RADDR, i + IL39_RTC_INST_LOWER_BOUND);
+               val = _il_rd(il, HBUS_TARG_MEM_RDAT);
+               if (val != le32_to_cpu(*image)) {
+#if 0                          /* Enable this if you want to see details */
+                       IL_ERR("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;
+               }
+       }
+
+       return rc;
+}
+
+/**
+ * il3945_verify_ucode - determine which instruction image is in SRAM,
+ *    and verify its contents
+ */
+static int
+il3945_verify_ucode(struct il_priv *il)
+{
+       __le32 *image;
+       u32 len;
+       int rc = 0;
+
+       /* Try bootstrap */
+       image = (__le32 *) il->ucode_boot.v_addr;
+       len = il->ucode_boot.len;
+       rc = il3945_verify_inst_sparse(il, image, len);
+       if (rc == 0) {
+               D_INFO("Bootstrap uCode is good in inst SRAM\n");
+               return 0;
+       }
+
+       /* Try initialize */
+       image = (__le32 *) il->ucode_init.v_addr;
+       len = il->ucode_init.len;
+       rc = il3945_verify_inst_sparse(il, image, len);
+       if (rc == 0) {
+               D_INFO("Initialize uCode is good in inst SRAM\n");
+               return 0;
+       }
+
+       /* Try runtime/protocol */
+       image = (__le32 *) il->ucode_code.v_addr;
+       len = il->ucode_code.len;
+       rc = il3945_verify_inst_sparse(il, image, len);
+       if (rc == 0) {
+               D_INFO("Runtime uCode is good in inst SRAM\n");
+               return 0;
+       }
+
+       IL_ERR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
+
+       /* Since nothing seems to match, show first several data entries in
+        * instruction SRAM, so maybe visual inspection will give a clue.
+        * Selection of bootstrap image (vs. other images) is arbitrary. */
+       image = (__le32 *) il->ucode_boot.v_addr;
+       len = il->ucode_boot.len;
+       rc = il3945_verify_inst_full(il, image, len);
+
+       return rc;
+}
+
+static void
+il3945_nic_start(struct il_priv *il)
+{
+       /* Remove all resets to allow NIC to operate */
+       _il_wr(il, CSR_RESET, 0);
+}
+
+#define IL3945_UCODE_GET(item)                                         \
+static u32 il3945_ucode_get_##item(const struct il_ucode_header *ucode)\
+{                                                                      \
+       return le32_to_cpu(ucode->v1.item);                             \
+}
+
+static u32
+il3945_ucode_get_header_size(u32 api_ver)
+{
+       return 24;
+}
+
+static u8 *
+il3945_ucode_get_data(const struct il_ucode_header *ucode)
+{
+       return (u8 *) ucode->v1.data;
+}
+
+IL3945_UCODE_GET(inst_size);
+IL3945_UCODE_GET(data_size);
+IL3945_UCODE_GET(init_size);
+IL3945_UCODE_GET(init_data_size);
+IL3945_UCODE_GET(boot_size);
+
+/**
+ * il3945_read_ucode - Read uCode images from disk file.
+ *
+ * Copy into buffers for card to fetch via bus-mastering
+ */
+static int
+il3945_read_ucode(struct il_priv *il)
+{
+       const struct il_ucode_header *ucode;
+       int ret = -EINVAL, idx;
+       const struct firmware *ucode_raw;
+       /* firmware file name contains uCode/driver compatibility version */
+       const char *name_pre = il->cfg->fw_name_pre;
+       const unsigned int api_max = il->cfg->ucode_api_max;
+       const unsigned int api_min = il->cfg->ucode_api_min;
+       char buf[25];
+       u8 *src;
+       size_t len;
+       u32 api_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. */
+       for (idx = api_max; idx >= api_min; idx--) {
+               sprintf(buf, "%s%u%s", name_pre, idx, ".ucode");
+               ret = request_firmware(&ucode_raw, buf, &il->pci_dev->dev);
+               if (ret < 0) {
+                       IL_ERR("%s firmware file req failed: %d\n", buf, ret);
+                       if (ret == -ENOENT)
+                               continue;
+                       else
+                               goto error;
+               } else {
+                       if (idx < api_max)
+                               IL_ERR("Loaded firmware %s, "
+                                      "which is deprecated. "
+                                      " Please use API v%u instead.\n", buf,
+                                      api_max);
+                       D_INFO("Got firmware '%s' file "
+                              "(%zd bytes) from disk\n", buf, ucode_raw->size);
+                       break;
+               }
+       }
+
+       if (ret < 0)
+               goto error;
+
+       /* Make sure that we got at least our header! */
+       if (ucode_raw->size < il3945_ucode_get_header_size(1)) {
+               IL_ERR("File size way too small!\n");
+               ret = -EINVAL;
+               goto err_release;
+       }
+
+       /* Data from ucode file:  header followed by uCode images */
+       ucode = (struct il_ucode_header *)ucode_raw->data;
+
+       il->ucode_ver = le32_to_cpu(ucode->ver);
+       api_ver = IL_UCODE_API(il->ucode_ver);
+       inst_size = il3945_ucode_get_inst_size(ucode);
+       data_size = il3945_ucode_get_data_size(ucode);
+       init_size = il3945_ucode_get_init_size(ucode);
+       init_data_size = il3945_ucode_get_init_data_size(ucode);
+       boot_size = il3945_ucode_get_boot_size(ucode);
+       src = il3945_ucode_get_data(ucode);
+
+       /* api_ver should match the api version forming part of the
+        * firmware filename ... but we don't check for that and only rely
+        * on the API version read from firmware header from here on forward */
+
+       if (api_ver < api_min || api_ver > api_max) {
+               IL_ERR("Driver unable to support your firmware API. "
+                      "Driver supports v%u, firmware is v%u.\n", api_max,
+                      api_ver);
+               il->ucode_ver = 0;
+               ret = -EINVAL;
+               goto err_release;
+       }
+       if (api_ver != api_max)
+               IL_ERR("Firmware has old API version. Expected %u, "
+                      "got %u. New firmware can be obtained "
+                      "from http://www.intellinuxwireless.org.\n", api_max,
+                      api_ver);
+
+       IL_INFO("loaded firmware version %u.%u.%u.%u\n",
+               IL_UCODE_MAJOR(il->ucode_ver), IL_UCODE_MINOR(il->ucode_ver),
+               IL_UCODE_API(il->ucode_ver), IL_UCODE_SERIAL(il->ucode_ver));
+
+       snprintf(il->hw->wiphy->fw_version, sizeof(il->hw->wiphy->fw_version),
+                "%u.%u.%u.%u", IL_UCODE_MAJOR(il->ucode_ver),
+                IL_UCODE_MINOR(il->ucode_ver), IL_UCODE_API(il->ucode_ver),
+                IL_UCODE_SERIAL(il->ucode_ver));
+
+       D_INFO("f/w package hdr ucode version raw = 0x%x\n", il->ucode_ver);
+       D_INFO("f/w package hdr runtime inst size = %u\n", inst_size);
+       D_INFO("f/w package hdr runtime data size = %u\n", data_size);
+       D_INFO("f/w package hdr init inst size = %u\n", init_size);
+       D_INFO("f/w package hdr init data size = %u\n", init_data_size);
+       D_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 !=
+           il3945_ucode_get_header_size(api_ver) + inst_size + data_size +
+           init_size + init_data_size + boot_size) {
+
+               D_INFO("uCode file size %zd does not match expected size\n",
+                      ucode_raw->size);
+               ret = -EINVAL;
+               goto err_release;
+       }
+
+       /* Verify that uCode images will fit in card's SRAM */
+       if (inst_size > IL39_MAX_INST_SIZE) {
+               D_INFO("uCode instr len %d too large to fit in\n", inst_size);
+               ret = -EINVAL;
+               goto err_release;
+       }
+
+       if (data_size > IL39_MAX_DATA_SIZE) {
+               D_INFO("uCode data len %d too large to fit in\n", data_size);
+               ret = -EINVAL;
+               goto err_release;
+       }
+       if (init_size > IL39_MAX_INST_SIZE) {
+               D_INFO("uCode init instr len %d too large to fit in\n",
+                      init_size);
+               ret = -EINVAL;
+               goto err_release;
+       }
+       if (init_data_size > IL39_MAX_DATA_SIZE) {
+               D_INFO("uCode init data len %d too large to fit in\n",
+                      init_data_size);
+               ret = -EINVAL;
+               goto err_release;
+       }
+       if (boot_size > IL39_MAX_BSM_SIZE) {
+               D_INFO("uCode boot instr len %d too large to fit in\n",
+                      boot_size);
+               ret = -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 */
+       il->ucode_code.len = inst_size;
+       il_alloc_fw_desc(il->pci_dev, &il->ucode_code);
+
+       il->ucode_data.len = data_size;
+       il_alloc_fw_desc(il->pci_dev, &il->ucode_data);
+
+       il->ucode_data_backup.len = data_size;
+       il_alloc_fw_desc(il->pci_dev, &il->ucode_data_backup);
+
+       if (!il->ucode_code.v_addr || !il->ucode_data.v_addr ||
+           !il->ucode_data_backup.v_addr)
+               goto err_pci_alloc;
+
+       /* Initialization instructions and data */
+       if (init_size && init_data_size) {
+               il->ucode_init.len = init_size;
+               il_alloc_fw_desc(il->pci_dev, &il->ucode_init);
+
+               il->ucode_init_data.len = init_data_size;
+               il_alloc_fw_desc(il->pci_dev, &il->ucode_init_data);
+
+               if (!il->ucode_init.v_addr || !il->ucode_init_data.v_addr)
+                       goto err_pci_alloc;
+       }
+
+       /* Bootstrap (instructions only, no data) */
+       if (boot_size) {
+               il->ucode_boot.len = boot_size;
+               il_alloc_fw_desc(il->pci_dev, &il->ucode_boot);
+
+               if (!il->ucode_boot.v_addr)
+                       goto err_pci_alloc;
+       }
+
+       /* Copy images into buffers for card's bus-master reads ... */
+
+       /* Runtime instructions (first block of data in file) */
+       len = inst_size;
+       D_INFO("Copying (but not loading) uCode instr len %zd\n", len);
+       memcpy(il->ucode_code.v_addr, src, len);
+       src += len;
+
+       D_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
+              il->ucode_code.v_addr, (u32) il->ucode_code.p_addr);
+
+       /* Runtime data (2nd block)
+        * NOTE:  Copy into backup buffer will be done in il3945_up()  */
+       len = data_size;
+       D_INFO("Copying (but not loading) uCode data len %zd\n", len);
+       memcpy(il->ucode_data.v_addr, src, len);
+       memcpy(il->ucode_data_backup.v_addr, src, len);
+       src += len;
+
+       /* Initialization instructions (3rd block) */
+       if (init_size) {
+               len = init_size;
+               D_INFO("Copying (but not loading) init instr len %zd\n", len);
+               memcpy(il->ucode_init.v_addr, src, len);
+               src += len;
+       }
+
+       /* Initialization data (4th block) */
+       if (init_data_size) {
+               len = init_data_size;
+               D_INFO("Copying (but not loading) init data len %zd\n", len);
+               memcpy(il->ucode_init_data.v_addr, src, len);
+               src += len;
+       }
+
+       /* Bootstrap instructions (5th block) */
+       len = boot_size;
+       D_INFO("Copying (but not loading) boot instr len %zd\n", len);
+       memcpy(il->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:
+       IL_ERR("failed to allocate pci memory\n");
+       ret = -ENOMEM;
+       il3945_dealloc_ucode_pci(il);
+
+err_release:
+       release_firmware(ucode_raw);
+
+error:
+       return ret;
+}
+
+/**
+ * il3945_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
+il3945_set_ucode_ptrs(struct il_priv *il)
+{
+       dma_addr_t pinst;
+       dma_addr_t pdata;
+
+       /* bits 31:0 for 3945 */
+       pinst = il->ucode_code.p_addr;
+       pdata = il->ucode_data_backup.p_addr;
+
+       /* Tell bootstrap uCode where to find image to load */
+       il_wr_prph(il, BSM_DRAM_INST_PTR_REG, pinst);
+       il_wr_prph(il, BSM_DRAM_DATA_PTR_REG, pdata);
+       il_wr_prph(il, BSM_DRAM_DATA_BYTECOUNT_REG, il->ucode_data.len);
+
+       /* Inst byte count must be last to set up, bit 31 signals uCode
+        *   that all new ptr/size info is in place */
+       il_wr_prph(il, BSM_DRAM_INST_BYTECOUNT_REG,
+                  il->ucode_code.len | BSM_DRAM_INST_LOAD);
+
+       D_INFO("Runtime uCode pointers are set.\n");
+
+       return 0;
+}
+
+/**
+ * il3945_init_alive_start - Called after N_ALIVE notification received
+ *
+ * Called after N_ALIVE notification received from "initialize" uCode.
+ *
+ * Tell "initialize" uCode to go ahead and load the runtime uCode.
+ */
+static void
+il3945_init_alive_start(struct il_priv *il)
+{
+       /* Check alive response for "valid" sign from uCode */
+       if (il->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 */
+               D_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 (il3945_verify_ucode(il)) {
+               /* Runtime instruction load was bad;
+                * take it all the way back down so we can try again */
+               D_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. */
+       D_INFO("Initialization Alive received.\n");
+       if (il3945_set_ucode_ptrs(il)) {
+               /* Runtime instruction load won't happen;
+                * take it all the way back down so we can try again */
+               D_INFO("Couldn't set up uCode pointers.\n");
+               goto restart;
+       }
+       return;
+
+restart:
+       queue_work(il->workqueue, &il->restart);
+}
+
+/**
+ * il3945_alive_start - called after N_ALIVE notification received
+ *                   from protocol/runtime uCode (initialization uCode's
+ *                   Alive gets handled by il3945_init_alive_start()).
+ */
+static void
+il3945_alive_start(struct il_priv *il)
+{
+       int thermal_spin = 0;
+       u32 rfkill;
+       struct il_rxon_context *ctx = &il->ctx;
+
+       D_INFO("Runtime Alive received.\n");
+
+       if (il->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 */
+               D_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 (il3945_verify_ucode(il)) {
+               /* Runtime instruction load was bad;
+                * take it all the way back down so we can try again */
+               D_INFO("Bad runtime uCode load.\n");
+               goto restart;
+       }
+
+       rfkill = il_rd_prph(il, APMG_RFKILL_REG);
+       D_INFO("RFKILL status: 0x%x\n", rfkill);
+
+       if (rfkill & 0x1) {
+               clear_bit(S_RF_KILL_HW, &il->status);
+               /* if RFKILL is not on, then wait for thermal
+                * sensor in adapter to kick in */
+               while (il3945_hw_get_temperature(il) == 0) {
+                       thermal_spin++;
+                       udelay(10);
+               }
+
+               if (thermal_spin)
+                       D_INFO("Thermal calibration took %dus\n",
+                              thermal_spin * 10);
+       } else
+               set_bit(S_RF_KILL_HW, &il->status);
+
+       /* After the ALIVE response, we can send commands to 3945 uCode */
+       set_bit(S_ALIVE, &il->status);
+
+       /* Enable watchdog to monitor the driver tx queues */
+       il_setup_watchdog(il);
+
+       if (il_is_rfkill(il))
+               return;
+
+       ieee80211_wake_queues(il->hw);
+
+       il->active_rate = RATES_MASK_3945;
+
+       il_power_update_mode(il, true);
+
+       if (il_is_associated(il)) {
+               struct il3945_rxon_cmd *active_rxon =
+                   (struct il3945_rxon_cmd *)(&ctx->active);
+
+               ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+               active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+       } else {
+               /* Initialize our rx_config data */
+               il_connection_init_rx_config(il, ctx);
+       }
+
+       /* Configure Bluetooth device coexistence support */
+       il_send_bt_config(il);
+
+       set_bit(S_READY, &il->status);
+
+       /* Configure the adapter for unassociated operation */
+       il3945_commit_rxon(il, ctx);
+
+       il3945_reg_txpower_periodic(il);
+
+       D_INFO("ALIVE processing complete.\n");
+       wake_up(&il->wait_command_queue);
+
+       return;
+
+restart:
+       queue_work(il->workqueue, &il->restart);
+}
+
+static void il3945_cancel_deferred_work(struct il_priv *il);
+
+static void
+__il3945_down(struct il_priv *il)
+{
+       unsigned long flags;
+       int exit_pending;
+
+       D_INFO(DRV_NAME " is going down\n");
+
+       il_scan_cancel_timeout(il, 200);
+
+       exit_pending = test_and_set_bit(S_EXIT_PENDING, &il->status);
+
+       /* Stop TX queues watchdog. We need to have S_EXIT_PENDING bit set
+        * to prevent rearm timer */
+       del_timer_sync(&il->watchdog);
+
+       /* Station information will now be cleared in device */
+       il_clear_ucode_stations(il, NULL);
+       il_dealloc_bcast_stations(il);
+       il_clear_driver_stations(il);
+
+       /* Unblock any waiting calls */
+       wake_up_all(&il->wait_command_queue);
+
+       /* Wipe out the EXIT_PENDING status bit if we are not actually
+        * exiting the module */
+       if (!exit_pending)
+               clear_bit(S_EXIT_PENDING, &il->status);
+
+       /* stop and reset the on-board processor */
+       _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+       /* tell the device to stop sending interrupts */
+       spin_lock_irqsave(&il->lock, flags);
+       il_disable_interrupts(il);
+       spin_unlock_irqrestore(&il->lock, flags);
+       il3945_synchronize_irq(il);
+
+       if (il->mac80211_registered)
+               ieee80211_stop_queues(il->hw);
+
+       /* If we have not previously called il3945_init() then
+        * clear all bits but the RF Kill bits and return */
+       if (!il_is_init(il)) {
+               il->status =
+                   test_bit(S_RF_KILL_HW,
+                            &il->
+                            status) << S_RF_KILL_HW |
+                   test_bit(S_GEO_CONFIGURED,
+                            &il->
+                            status) << S_GEO_CONFIGURED |
+                   test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
+               goto exit;
+       }
+
+       /* ...otherwise clear out all the status bits but the RF Kill
+        * bit and continue taking the NIC down. */
+       il->status &=
+           test_bit(S_RF_KILL_HW,
+                    &il->status) << S_RF_KILL_HW | test_bit(S_GEO_CONFIGURED,
+                                                            &il->
+                                                            status) <<
+           S_GEO_CONFIGURED | test_bit(S_FW_ERROR,
+                                       &il->
+                                       status) << S_FW_ERROR |
+           test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
+
+       il3945_hw_txq_ctx_stop(il);
+       il3945_hw_rxq_stop(il);
+
+       /* Power-down device's busmaster DMA clocks */
+       il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+       udelay(5);
+
+       /* Stop the device, and put it in low power state */
+       il_apm_stop(il);
+
+exit:
+       memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
+
+       if (il->beacon_skb)
+               dev_kfree_skb(il->beacon_skb);
+       il->beacon_skb = NULL;
+
+       /* clear out any free frames */
+       il3945_clear_free_frames(il);
+}
+
+static void
+il3945_down(struct il_priv *il)
+{
+       mutex_lock(&il->mutex);
+       __il3945_down(il);
+       mutex_unlock(&il->mutex);
+
+       il3945_cancel_deferred_work(il);
+}
+
+#define MAX_HW_RESTARTS 5
+
+static int
+il3945_alloc_bcast_station(struct il_priv *il)
+{
+       struct il_rxon_context *ctx = &il->ctx;
+       unsigned long flags;
+       u8 sta_id;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       sta_id = il_prep_station(il, ctx, il_bcast_addr, false, NULL);
+       if (sta_id == IL_INVALID_STATION) {
+               IL_ERR("Unable to prepare broadcast station\n");
+               spin_unlock_irqrestore(&il->sta_lock, flags);
+
+               return -EINVAL;
+       }
+
+       il->stations[sta_id].used |= IL_STA_DRIVER_ACTIVE;
+       il->stations[sta_id].used |= IL_STA_BCAST;
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return 0;
+}
+
+static int
+__il3945_up(struct il_priv *il)
+{
+       int rc, i;
+
+       rc = il3945_alloc_bcast_station(il);
+       if (rc)
+               return rc;
+
+       if (test_bit(S_EXIT_PENDING, &il->status)) {
+               IL_WARN("Exit pending; will not bring the NIC up\n");
+               return -EIO;
+       }
+
+       if (!il->ucode_data_backup.v_addr || !il->ucode_data.v_addr) {
+               IL_ERR("ucode not available for device bring up\n");
+               return -EIO;
+       }
+
+       /* If platform's RF_KILL switch is NOT set to KILL */
+       if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+               clear_bit(S_RF_KILL_HW, &il->status);
+       else {
+               set_bit(S_RF_KILL_HW, &il->status);
+               IL_WARN("Radio disabled by HW RF Kill switch\n");
+               return -ENODEV;
+       }
+
+       _il_wr(il, CSR_INT, 0xFFFFFFFF);
+
+       rc = il3945_hw_nic_init(il);
+       if (rc) {
+               IL_ERR("Unable to int nic\n");
+               return rc;
+       }
+
+       /* make sure rfkill handshake bits are cleared */
+       _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+       /* clear (again), then enable host interrupts */
+       _il_wr(il, CSR_INT, 0xFFFFFFFF);
+       il_enable_interrupts(il);
+
+       /* really make sure rfkill handshake bits are cleared */
+       _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       _il_wr(il, 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(il->ucode_data_backup.v_addr, il->ucode_data.v_addr,
+              il->ucode_data.len);
+
+       /* We return success when we resume from suspend and rf_kill is on. */
+       if (test_bit(S_RF_KILL_HW, &il->status))
+               return 0;
+
+       for (i = 0; i < MAX_HW_RESTARTS; i++) {
+
+               /* load bootstrap state machine,
+                * load bootstrap program into processor's memory,
+                * prepare to load the "initialize" uCode */
+               rc = il->cfg->ops->lib->load_ucode(il);
+
+               if (rc) {
+                       IL_ERR("Unable to set up bootstrap uCode: %d\n", rc);
+                       continue;
+               }
+
+               /* start card; "initialize" will load runtime ucode */
+               il3945_nic_start(il);
+
+               D_INFO(DRV_NAME " is coming up\n");
+
+               return 0;
+       }
+
+       set_bit(S_EXIT_PENDING, &il->status);
+       __il3945_down(il);
+       clear_bit(S_EXIT_PENDING, &il->status);
+
+       /* tried to restart and config the device for as long as our
+        * patience could withstand */
+       IL_ERR("Unable to initialize device after %d attempts.\n", i);
+       return -EIO;
+}
+
+/*****************************************************************************
+ *
+ * Workqueue callbacks
+ *
+ *****************************************************************************/
+
+static void
+il3945_bg_init_alive_start(struct work_struct *data)
+{
+       struct il_priv *il =
+           container_of(data, struct il_priv, init_alive_start.work);
+
+       mutex_lock(&il->mutex);
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               goto out;
+
+       il3945_init_alive_start(il);
+out:
+       mutex_unlock(&il->mutex);
+}
+
+static void
+il3945_bg_alive_start(struct work_struct *data)
+{
+       struct il_priv *il =
+           container_of(data, struct il_priv, alive_start.work);
+
+       mutex_lock(&il->mutex);
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               goto out;
+
+       il3945_alive_start(il);
+out:
+       mutex_unlock(&il->mutex);
+}
+
+/*
+ * 3945 cannot interrupt driver when hardware rf kill switch toggles;
+ * driver must poll CSR_GP_CNTRL_REG register for change.  This register
+ * *is* readable even when device has been SW_RESET into low power mode
+ * (e.g. during RF KILL).
+ */
+static void
+il3945_rfkill_poll(struct work_struct *data)
+{
+       struct il_priv *il =
+           container_of(data, struct il_priv, _3945.rfkill_poll.work);
+       bool old_rfkill = test_bit(S_RF_KILL_HW, &il->status);
+       bool new_rfkill =
+           !(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
+
+       if (new_rfkill != old_rfkill) {
+               if (new_rfkill)
+                       set_bit(S_RF_KILL_HW, &il->status);
+               else
+                       clear_bit(S_RF_KILL_HW, &il->status);
+
+               wiphy_rfkill_set_hw_state(il->hw->wiphy, new_rfkill);
+
+               D_RF_KILL("RF_KILL bit toggled to %s.\n",
+                         new_rfkill ? "disable radio" : "enable radio");
+       }
+
+       /* Keep this running, even if radio now enabled.  This will be
+        * cancelled in mac_start() if system decides to start again */
+       queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll,
+                          round_jiffies_relative(2 * HZ));
+
+}
+
+int
+il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif)
+{
+       struct il_host_cmd cmd = {
+               .id = C_SCAN,
+               .len = sizeof(struct il3945_scan_cmd),
+               .flags = CMD_SIZE_HUGE,
+       };
+       struct il3945_scan_cmd *scan;
+       u8 n_probes = 0;
+       enum ieee80211_band band;
+       bool is_active = false;
+       int ret;
+       u16 len;
+
+       lockdep_assert_held(&il->mutex);
+
+       if (!il->scan_cmd) {
+               il->scan_cmd =
+                   kmalloc(sizeof(struct il3945_scan_cmd) + IL_MAX_SCAN_SIZE,
+                           GFP_KERNEL);
+               if (!il->scan_cmd) {
+                       D_SCAN("Fail to allocate scan memory\n");
+                       return -ENOMEM;
+               }
+       }
+       scan = il->scan_cmd;
+       memset(scan, 0, sizeof(struct il3945_scan_cmd) + IL_MAX_SCAN_SIZE);
+
+       scan->quiet_plcp_th = IL_PLCP_QUIET_THRESH;
+       scan->quiet_time = IL_ACTIVE_QUIET_TIME;
+
+       if (il_is_associated(il)) {
+               u16 interval;
+               u32 extra;
+               u32 suspend_time = 100;
+               u32 scan_suspend_time = 100;
+
+               D_INFO("Scanning while associated...\n");
+
+               interval = vif->bss_conf.beacon_int;
+
+               scan->suspend_time = 0;
+               scan->max_out_time = cpu_to_le32(200 * 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);
+               D_SCAN("suspend_time 0x%X beacon interval %d\n",
+                      scan_suspend_time, interval);
+       }
+
+       if (il->scan_request->n_ssids) {
+               int i, p = 0;
+               D_SCAN("Kicking off active scan\n");
+               for (i = 0; i < il->scan_request->n_ssids; i++) {
+                       /* always does wildcard anyway */
+                       if (!il->scan_request->ssids[i].ssid_len)
+                               continue;
+                       scan->direct_scan[p].id = WLAN_EID_SSID;
+                       scan->direct_scan[p].len =
+                           il->scan_request->ssids[i].ssid_len;
+                       memcpy(scan->direct_scan[p].ssid,
+                              il->scan_request->ssids[i].ssid,
+                              il->scan_request->ssids[i].ssid_len);
+                       n_probes++;
+                       p++;
+               }
+               is_active = true;
+       } else
+               D_SCAN("Kicking off passive scan.\n");
+
+       /* 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.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
+       scan->tx_cmd.sta_id = il->ctx.bcast_sta_id;
+       scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+       /* flags + rate selection */
+
+       switch (il->scan_band) {
+       case IEEE80211_BAND_2GHZ:
+               scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
+               scan->tx_cmd.rate = RATE_1M_PLCP;
+               band = IEEE80211_BAND_2GHZ;
+               break;
+       case IEEE80211_BAND_5GHZ:
+               scan->tx_cmd.rate = RATE_6M_PLCP;
+               band = IEEE80211_BAND_5GHZ;
+               break;
+       default:
+               IL_WARN("Invalid scan band\n");
+               return -EIO;
+       }
+
+       /*
+        * If active scaning is requested but a certain channel
+        * is marked passive, we can do active scanning if we
+        * detect transmissions.
+        */
+       scan->good_CRC_th =
+           is_active ? IL_GOOD_CRC_TH_DEFAULT : IL_GOOD_CRC_TH_DISABLED;
+
+       len =
+           il_fill_probe_req(il, (struct ieee80211_mgmt *)scan->data,
+                             vif->addr, il->scan_request->ie,
+                             il->scan_request->ie_len,
+                             IL_MAX_SCAN_SIZE - sizeof(*scan));
+       scan->tx_cmd.len = cpu_to_le16(len);
+
+       /* select Rx antennas */
+       scan->flags |= il3945_get_antenna_flags(il);
+
+       scan->channel_count =
+           il3945_get_channels_for_scan(il, band, is_active, n_probes,
+                                        (void *)&scan->data[len], vif);
+       if (scan->channel_count == 0) {
+               D_SCAN("channel count %d\n", scan->channel_count);
+               return -EIO;
+       }
+
+       cmd.len +=
+           le16_to_cpu(scan->tx_cmd.len) +
+           scan->channel_count * sizeof(struct il3945_scan_channel);
+       cmd.data = scan;
+       scan->len = cpu_to_le16(cmd.len);
+
+       set_bit(S_SCAN_HW, &il->status);
+       ret = il_send_cmd_sync(il, &cmd);
+       if (ret)
+               clear_bit(S_SCAN_HW, &il->status);
+       return ret;
+}
+
+void
+il3945_post_scan(struct il_priv *il)
+{
+       struct il_rxon_context *ctx = &il->ctx;
+
+       /*
+        * Since setting the RXON may have been deferred while
+        * performing the scan, fire one off if needed
+        */
+       if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+               il3945_commit_rxon(il, ctx);
+}
+
+static void
+il3945_bg_restart(struct work_struct *data)
+{
+       struct il_priv *il = container_of(data, struct il_priv, restart);
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
+               mutex_lock(&il->mutex);
+               il->ctx.vif = NULL;
+               il->is_open = 0;
+               mutex_unlock(&il->mutex);
+               il3945_down(il);
+               ieee80211_restart_hw(il->hw);
+       } else {
+               il3945_down(il);
+
+               mutex_lock(&il->mutex);
+               if (test_bit(S_EXIT_PENDING, &il->status)) {
+                       mutex_unlock(&il->mutex);
+                       return;
+               }
+
+               __il3945_up(il);
+               mutex_unlock(&il->mutex);
+       }
+}
+
+static void
+il3945_bg_rx_replenish(struct work_struct *data)
+{
+       struct il_priv *il = container_of(data, struct il_priv, rx_replenish);
+
+       mutex_lock(&il->mutex);
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               goto out;
+
+       il3945_rx_replenish(il);
+out:
+       mutex_unlock(&il->mutex);
+}
+
+void
+il3945_post_associate(struct il_priv *il)
+{
+       int rc = 0;
+       struct ieee80211_conf *conf = NULL;
+       struct il_rxon_context *ctx = &il->ctx;
+
+       if (!ctx->vif || !il->is_open)
+               return;
+
+       D_ASSOC("Associated as %d to: %pM\n", ctx->vif->bss_conf.aid,
+               ctx->active.bssid_addr);
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       il_scan_cancel_timeout(il, 200);
+
+       conf = &il->hw->conf;
+
+       ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+       il3945_commit_rxon(il, ctx);
+
+       rc = il_send_rxon_timing(il, ctx);
+       if (rc)
+               IL_WARN("C_RXON_TIMING failed - " "Attempting to continue.\n");
+
+       ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+
+       ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
+
+       D_ASSOC("assoc id %d beacon interval %d\n", ctx->vif->bss_conf.aid,
+               ctx->vif->bss_conf.beacon_int);
+
+       if (ctx->vif->bss_conf.use_short_preamble)
+               ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+       else
+               ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+       if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+               if (ctx->vif->bss_conf.use_short_slot)
+                       ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+               else
+                       ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+       }
+
+       il3945_commit_rxon(il, ctx);
+
+       switch (ctx->vif->type) {
+       case NL80211_IFTYPE_STATION:
+               il3945_rate_scale_init(il->hw, IL_AP_ID);
+               break;
+       case NL80211_IFTYPE_ADHOC:
+               il3945_send_beacon_cmd(il);
+               break;
+       default:
+               IL_ERR("%s Should not be called in %d mode\n", __func__,
+                      ctx->vif->type);
+               break;
+       }
+}
+
+/*****************************************************************************
+ *
+ * mac80211 entry point functions
+ *
+ *****************************************************************************/
+
+#define UCODE_READY_TIMEOUT    (2 * HZ)
+
+static int
+il3945_mac_start(struct ieee80211_hw *hw)
+{
+       struct il_priv *il = hw->priv;
+       int ret;
+
+       D_MAC80211("enter\n");
+
+       /* we should be verifying the device is ready to be opened */
+       mutex_lock(&il->mutex);
+
+       /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
+        * ucode filename and max sizes are card-specific. */
+
+       if (!il->ucode_code.len) {
+               ret = il3945_read_ucode(il);
+               if (ret) {
+                       IL_ERR("Could not read microcode: %d\n", ret);
+                       mutex_unlock(&il->mutex);
+                       goto out_release_irq;
+               }
+       }
+
+       ret = __il3945_up(il);
+
+       mutex_unlock(&il->mutex);
+
+       if (ret)
+               goto out_release_irq;
+
+       D_INFO("Start UP work.\n");
+
+       /* Wait for START_ALIVE from ucode. Otherwise callbacks from
+        * mac80211 will not be run successfully. */
+       ret = wait_event_timeout(il->wait_command_queue,
+                                test_bit(S_READY, &il->status),
+                                UCODE_READY_TIMEOUT);
+       if (!ret) {
+               if (!test_bit(S_READY, &il->status)) {
+                       IL_ERR("Wait for START_ALIVE timeout after %dms.\n",
+                              jiffies_to_msecs(UCODE_READY_TIMEOUT));
+                       ret = -ETIMEDOUT;
+                       goto out_release_irq;
+               }
+       }
+
+       /* ucode is running and will send rfkill notifications,
+        * no need to poll the killswitch state anymore */
+       cancel_delayed_work(&il->_3945.rfkill_poll);
+
+       il->is_open = 1;
+       D_MAC80211("leave\n");
+       return 0;
+
+out_release_irq:
+       il->is_open = 0;
+       D_MAC80211("leave - failed\n");
+       return ret;
+}
+
+static void
+il3945_mac_stop(struct ieee80211_hw *hw)
+{
+       struct il_priv *il = hw->priv;
+
+       D_MAC80211("enter\n");
+
+       if (!il->is_open) {
+               D_MAC80211("leave - skip\n");
+               return;
+       }
+
+       il->is_open = 0;
+
+       il3945_down(il);
+
+       flush_workqueue(il->workqueue);
+
+       /* start polling the killswitch state again */
+       queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll,
+                          round_jiffies_relative(2 * HZ));
+
+       D_MAC80211("leave\n");
+}
+
+static void
+il3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+       struct il_priv *il = hw->priv;
+
+       D_MAC80211("enter\n");
+
+       D_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+            ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
+
+       if (il3945_tx_skb(il, skb))
+               dev_kfree_skb_any(skb);
+
+       D_MAC80211("leave\n");
+}
+
+void
+il3945_config_ap(struct il_priv *il)
+{
+       struct il_rxon_context *ctx = &il->ctx;
+       struct ieee80211_vif *vif = ctx->vif;
+       int rc = 0;
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       /* The following should be done only at AP bring up */
+       if (!(il_is_associated(il))) {
+
+               /* RXON - unassoc (to set timing command) */
+               ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+               il3945_commit_rxon(il, ctx);
+
+               /* RXON Timing */
+               rc = il_send_rxon_timing(il, ctx);
+               if (rc)
+                       IL_WARN("C_RXON_TIMING failed - "
+                               "Attempting to continue.\n");
+
+               ctx->staging.assoc_id = 0;
+
+               if (vif->bss_conf.use_short_preamble)
+                       ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+               else
+                       ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+               if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+                       if (vif->bss_conf.use_short_slot)
+                               ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+                       else
+                               ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+               }
+               /* restore RXON assoc */
+               ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+               il3945_commit_rxon(il, ctx);
+       }
+       il3945_send_beacon_cmd(il);
+}
+
+static int
+il3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+                  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+                  struct ieee80211_key_conf *key)
+{
+       struct il_priv *il = hw->priv;
+       int ret = 0;
+       u8 sta_id = IL_INVALID_STATION;
+       u8 static_key;
+
+       D_MAC80211("enter\n");
+
+       if (il3945_mod_params.sw_crypto) {
+               D_MAC80211("leave - hwcrypto disabled\n");
+               return -EOPNOTSUPP;
+       }
+
+       /*
+        * To support IBSS RSN, don't program group keys in IBSS, the
+        * hardware will then not attempt to decrypt the frames.
+        */
+       if (vif->type == NL80211_IFTYPE_ADHOC &&
+           !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+               return -EOPNOTSUPP;
+
+       static_key = !il_is_associated(il);
+
+       if (!static_key) {
+               sta_id = il_sta_id_or_broadcast(il, &il->ctx, sta);
+               if (sta_id == IL_INVALID_STATION)
+                       return -EINVAL;
+       }
+
+       mutex_lock(&il->mutex);
+       il_scan_cancel_timeout(il, 100);
+
+       switch (cmd) {
+       case SET_KEY:
+               if (static_key)
+                       ret = il3945_set_static_key(il, key);
+               else
+                       ret = il3945_set_dynamic_key(il, key, sta_id);
+               D_MAC80211("enable hwcrypto key\n");
+               break;
+       case DISABLE_KEY:
+               if (static_key)
+                       ret = il3945_remove_static_key(il);
+               else
+                       ret = il3945_clear_sta_key_info(il, sta_id);
+               D_MAC80211("disable hwcrypto key\n");
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       mutex_unlock(&il->mutex);
+       D_MAC80211("leave\n");
+
+       return ret;
+}
+
+static int
+il3945_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                  struct ieee80211_sta *sta)
+{
+       struct il_priv *il = hw->priv;
+       struct il3945_sta_priv *sta_priv = (void *)sta->drv_priv;
+       int ret;
+       bool is_ap = vif->type == NL80211_IFTYPE_STATION;
+       u8 sta_id;
+
+       D_INFO("received request to add station %pM\n", sta->addr);
+       mutex_lock(&il->mutex);
+       D_INFO("proceeding to add station %pM\n", sta->addr);
+       sta_priv->common.sta_id = IL_INVALID_STATION;
+
+       ret =
+           il_add_station_common(il, &il->ctx, sta->addr, is_ap, sta, &sta_id);
+       if (ret) {
+               IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret);
+               /* Should we return success if return code is EEXIST ? */
+               mutex_unlock(&il->mutex);
+               return ret;
+       }
+
+       sta_priv->common.sta_id = sta_id;
+
+       /* Initialize rate scaling */
+       D_INFO("Initializing rate scaling for station %pM\n", sta->addr);
+       il3945_rs_rate_init(il, sta, sta_id);
+       mutex_unlock(&il->mutex);
+
+       return 0;
+}
+
+static void
+il3945_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
+                       unsigned int *total_flags, u64 multicast)
+{
+       struct il_priv *il = hw->priv;
+       __le32 filter_or = 0, filter_nand = 0;
+       struct il_rxon_context *ctx = &il->ctx;
+
+#define CHK(test, flag)        do { \
+       if (*total_flags & (test))              \
+               filter_or |= (flag);            \
+       else                                    \
+               filter_nand |= (flag);          \
+       } while (0)
+
+       D_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", changed_flags,
+                  *total_flags);
+
+       CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
+       CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
+       CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
+
+#undef CHK
+
+       mutex_lock(&il->mutex);
+
+       ctx->staging.filter_flags &= ~filter_nand;
+       ctx->staging.filter_flags |= filter_or;
+
+       /*
+        * Not committing directly because hardware can perform a scan,
+        * but even if hw is ready, committing here breaks for some reason,
+        * we'll eventually commit the filter flags change anyway.
+        */
+
+       mutex_unlock(&il->mutex);
+
+       /*
+        * Receiving all multicast frames is always enabled by the
+        * default flags setup in il_connection_init_rx_config()
+        * since we currently do not support programming multicast
+        * filters into the device.
+        */
+       *total_flags &=
+           FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
+           FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
+}
+
+/*****************************************************************************
+ *
+ * sysfs attributes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_IWLEGACY_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/iwl/)
+ * used for controlling the debug level.
+ *
+ * See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
+ */
+static ssize_t
+il3945_show_debug_level(struct device *d, struct device_attribute *attr,
+                       char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       return sprintf(buf, "0x%08X\n", il_get_debug_level(il));
+}
+
+static ssize_t
+il3945_store_debug_level(struct device *d, struct device_attribute *attr,
+                        const char *buf, size_t count)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 0, &val);
+       if (ret)
+               IL_INFO("%s is not in hex or decimal form.\n", buf);
+       else {
+               il->debug_level = val;
+               if (il_alloc_traffic_mem(il))
+                       IL_ERR("Not enough memory to generate traffic log\n");
+       }
+       return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, il3945_show_debug_level,
+                  il3945_store_debug_level);
+
+#endif /* CONFIG_IWLEGACY_DEBUG */
+
+static ssize_t
+il3945_show_temperature(struct device *d, struct device_attribute *attr,
+                       char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+
+       if (!il_is_alive(il))
+               return -EAGAIN;
+
+       return sprintf(buf, "%d\n", il3945_hw_get_temperature(il));
+}
+
+static DEVICE_ATTR(temperature, S_IRUGO, il3945_show_temperature, NULL);
+
+static ssize_t
+il3945_show_tx_power(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       return sprintf(buf, "%d\n", il->tx_power_user_lmt);
+}
+
+static ssize_t
+il3945_store_tx_power(struct device *d, struct device_attribute *attr,
+                     const char *buf, size_t count)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       char *p = (char *)buf;
+       u32 val;
+
+       val = simple_strtoul(p, &p, 10);
+       if (p == buf)
+               IL_INFO(": %s is not in decimal form.\n", buf);
+       else
+               il3945_hw_reg_set_txpower(il, val);
+
+       return count;
+}
+
+static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, il3945_show_tx_power,
+                  il3945_store_tx_power);
+
+static ssize_t
+il3945_show_flags(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       struct il_rxon_context *ctx = &il->ctx;
+
+       return sprintf(buf, "0x%04X\n", ctx->active.flags);
+}
+
+static ssize_t
+il3945_store_flags(struct device *d, struct device_attribute *attr,
+                  const char *buf, size_t count)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       u32 flags = simple_strtoul(buf, NULL, 0);
+       struct il_rxon_context *ctx = &il->ctx;
+
+       mutex_lock(&il->mutex);
+       if (le32_to_cpu(ctx->staging.flags) != flags) {
+               /* Cancel any currently running scans... */
+               if (il_scan_cancel_timeout(il, 100))
+                       IL_WARN("Could not cancel scan.\n");
+               else {
+                       D_INFO("Committing rxon.flags = 0x%04X\n", flags);
+                       ctx->staging.flags = cpu_to_le32(flags);
+                       il3945_commit_rxon(il, ctx);
+               }
+       }
+       mutex_unlock(&il->mutex);
+
+       return count;
+}
+
+static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, il3945_show_flags,
+                  il3945_store_flags);
+
+static ssize_t
+il3945_show_filter_flags(struct device *d, struct device_attribute *attr,
+                        char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       struct il_rxon_context *ctx = &il->ctx;
+
+       return sprintf(buf, "0x%04X\n", le32_to_cpu(ctx->active.filter_flags));
+}
+
+static ssize_t
+il3945_store_filter_flags(struct device *d, struct device_attribute *attr,
+                         const char *buf, size_t count)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       struct il_rxon_context *ctx = &il->ctx;
+       u32 filter_flags = simple_strtoul(buf, NULL, 0);
+
+       mutex_lock(&il->mutex);
+       if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) {
+               /* Cancel any currently running scans... */
+               if (il_scan_cancel_timeout(il, 100))
+                       IL_WARN("Could not cancel scan.\n");
+               else {
+                       D_INFO("Committing rxon.filter_flags = " "0x%04X\n",
+                              filter_flags);
+                       ctx->staging.filter_flags = cpu_to_le32(filter_flags);
+                       il3945_commit_rxon(il, ctx);
+               }
+       }
+       mutex_unlock(&il->mutex);
+
+       return count;
+}
+
+static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, il3945_show_filter_flags,
+                  il3945_store_filter_flags);
+
+static ssize_t
+il3945_show_measurement(struct device *d, struct device_attribute *attr,
+                       char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       struct il_spectrum_notification measure_report;
+       u32 size = sizeof(measure_report), len = 0, ofs = 0;
+       u8 *data = (u8 *) &measure_report;
+       unsigned long flags;
+
+       spin_lock_irqsave(&il->lock, flags);
+       if (!(il->measurement_status & MEASUREMENT_READY)) {
+               spin_unlock_irqrestore(&il->lock, flags);
+               return 0;
+       }
+       memcpy(&measure_report, &il->measure_report, size);
+       il->measurement_status = 0;
+       spin_unlock_irqrestore(&il->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);
+       }
+
+       return len;
+}
+
+static ssize_t
+il3945_store_measurement(struct device *d, struct device_attribute *attr,
+                        const char *buf, size_t count)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       struct il_rxon_context *ctx = &il->ctx;
+       struct ieee80211_measurement_params params = {
+               .channel = le16_to_cpu(ctx->active.channel),
+               .start_time = cpu_to_le64(il->_3945.last_tsf),
+               .duration = cpu_to_le16(1),
+       };
+       u8 type = IL_MEASURE_BASIC;
+       u8 buffer[32];
+       u8 channel;
+
+       if (count) {
+               char *p = buffer;
+               strncpy(buffer, buf, min(sizeof(buffer), count));
+               channel = simple_strtoul(p, NULL, 0);
+               if (channel)
+                       params.channel = channel;
+
+               p = buffer;
+               while (*p && *p != ' ')
+                       p++;
+               if (*p)
+                       type = simple_strtoul(p + 1, NULL, 0);
+       }
+
+       D_INFO("Invoking measurement of type %d on " "channel %d (for '%s')\n",
+              type, params.channel, buf);
+       il3945_get_measurement(il, &params, type);
+
+       return count;
+}
+
+static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, il3945_show_measurement,
+                  il3945_store_measurement);
+
+static ssize_t
+il3945_store_retry_rate(struct device *d, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+
+       il->retry_rate = simple_strtoul(buf, NULL, 0);
+       if (il->retry_rate <= 0)
+               il->retry_rate = 1;
+
+       return count;
+}
+
+static ssize_t
+il3945_show_retry_rate(struct device *d, struct device_attribute *attr,
+                      char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       return sprintf(buf, "%d", il->retry_rate);
+}
+
+static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, il3945_show_retry_rate,
+                  il3945_store_retry_rate);
+
+static ssize_t
+il3945_show_channels(struct device *d, struct device_attribute *attr, char *buf)
+{
+       /* all this shit doesn't belong into sysfs anyway */
+       return 0;
+}
+
+static DEVICE_ATTR(channels, S_IRUSR, il3945_show_channels, NULL);
+
+static ssize_t
+il3945_show_antenna(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+
+       if (!il_is_alive(il))
+               return -EAGAIN;
+
+       return sprintf(buf, "%d\n", il3945_mod_params.antenna);
+}
+
+static ssize_t
+il3945_store_antenna(struct device *d, struct device_attribute *attr,
+                    const char *buf, size_t count)
+{
+       struct il_priv *il __maybe_unused = dev_get_drvdata(d);
+       int ant;
+
+       if (count == 0)
+               return 0;
+
+       if (sscanf(buf, "%1i", &ant) != 1) {
+               D_INFO("not in hex or decimal form.\n");
+               return count;
+       }
+
+       if (ant >= 0 && ant <= 2) {
+               D_INFO("Setting antenna select to %d.\n", ant);
+               il3945_mod_params.antenna = (enum il3945_antenna)ant;
+       } else
+               D_INFO("Bad antenna select value %d.\n", ant);
+
+       return count;
+}
+
+static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, il3945_show_antenna,
+                  il3945_store_antenna);
+
+static ssize_t
+il3945_show_status(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       if (!il_is_alive(il))
+               return -EAGAIN;
+       return sprintf(buf, "0x%08x\n", (int)il->status);
+}
+
+static DEVICE_ATTR(status, S_IRUGO, il3945_show_status, NULL);
+
+static ssize_t
+il3945_dump_error_log(struct device *d, struct device_attribute *attr,
+                     const char *buf, size_t count)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       char *p = (char *)buf;
+
+       if (p[0] == '1')
+               il3945_dump_nic_error_log(il);
+
+       return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, il3945_dump_error_log);
+
+/*****************************************************************************
+ *
+ * driver setup and tear down
+ *
+ *****************************************************************************/
+
+static void
+il3945_setup_deferred_work(struct il_priv *il)
+{
+       il->workqueue = create_singlethread_workqueue(DRV_NAME);
+
+       init_waitqueue_head(&il->wait_command_queue);
+
+       INIT_WORK(&il->restart, il3945_bg_restart);
+       INIT_WORK(&il->rx_replenish, il3945_bg_rx_replenish);
+       INIT_DELAYED_WORK(&il->init_alive_start, il3945_bg_init_alive_start);
+       INIT_DELAYED_WORK(&il->alive_start, il3945_bg_alive_start);
+       INIT_DELAYED_WORK(&il->_3945.rfkill_poll, il3945_rfkill_poll);
+
+       il_setup_scan_deferred_work(il);
+
+       il3945_hw_setup_deferred_work(il);
+
+       init_timer(&il->watchdog);
+       il->watchdog.data = (unsigned long)il;
+       il->watchdog.function = il_bg_watchdog;
+
+       tasklet_init(&il->irq_tasklet,
+                    (void (*)(unsigned long))il3945_irq_tasklet,
+                    (unsigned long)il);
+}
+
+static void
+il3945_cancel_deferred_work(struct il_priv *il)
+{
+       il3945_hw_cancel_deferred_work(il);
+
+       cancel_delayed_work_sync(&il->init_alive_start);
+       cancel_delayed_work(&il->alive_start);
+
+       il_cancel_scan_deferred_work(il);
+}
+
+static struct attribute *il3945_sysfs_entries[] = {
+       &dev_attr_antenna.attr,
+       &dev_attr_channels.attr,
+       &dev_attr_dump_errors.attr,
+       &dev_attr_flags.attr,
+       &dev_attr_filter_flags.attr,
+       &dev_attr_measurement.attr,
+       &dev_attr_retry_rate.attr,
+       &dev_attr_status.attr,
+       &dev_attr_temperature.attr,
+       &dev_attr_tx_power.attr,
+#ifdef CONFIG_IWLEGACY_DEBUG
+       &dev_attr_debug_level.attr,
+#endif
+       NULL
+};
+
+static struct attribute_group il3945_attribute_group = {
+       .name = NULL,           /* put in device directory */
+       .attrs = il3945_sysfs_entries,
+};
+
+struct ieee80211_ops il3945_hw_ops = {
+       .tx = il3945_mac_tx,
+       .start = il3945_mac_start,
+       .stop = il3945_mac_stop,
+       .add_interface = il_mac_add_interface,
+       .remove_interface = il_mac_remove_interface,
+       .change_interface = il_mac_change_interface,
+       .config = il_mac_config,
+       .configure_filter = il3945_configure_filter,
+       .set_key = il3945_mac_set_key,
+       .conf_tx = il_mac_conf_tx,
+       .reset_tsf = il_mac_reset_tsf,
+       .bss_info_changed = il_mac_bss_info_changed,
+       .hw_scan = il_mac_hw_scan,
+       .sta_add = il3945_mac_sta_add,
+       .sta_remove = il_mac_sta_remove,
+       .tx_last_beacon = il_mac_tx_last_beacon,
+};
+
+static int
+il3945_init_drv(struct il_priv *il)
+{
+       int ret;
+       struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
+
+       il->retry_rate = 1;
+       il->beacon_skb = NULL;
+
+       spin_lock_init(&il->sta_lock);
+       spin_lock_init(&il->hcmd_lock);
+
+       INIT_LIST_HEAD(&il->free_frames);
+
+       mutex_init(&il->mutex);
+
+       il->ieee_channels = NULL;
+       il->ieee_rates = NULL;
+       il->band = IEEE80211_BAND_2GHZ;
+
+       il->iw_mode = NL80211_IFTYPE_STATION;
+       il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
+
+       /* initialize force reset */
+       il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD;
+
+       if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
+               IL_WARN("Unsupported EEPROM version: 0x%04X\n",
+                       eeprom->version);
+               ret = -EINVAL;
+               goto err;
+       }
+       ret = il_init_channel_map(il);
+       if (ret) {
+               IL_ERR("initializing regulatory failed: %d\n", ret);
+               goto err;
+       }
+
+       /* Set up txpower settings in driver for all channels */
+       if (il3945_txpower_set_from_eeprom(il)) {
+               ret = -EIO;
+               goto err_free_channel_map;
+       }
+
+       ret = il_init_geos(il);
+       if (ret) {
+               IL_ERR("initializing geos failed: %d\n", ret);
+               goto err_free_channel_map;
+       }
+       il3945_init_hw_rates(il, il->ieee_rates);
+
+       return 0;
+
+err_free_channel_map:
+       il_free_channel_map(il);
+err:
+       return ret;
+}
+
+#define IL3945_MAX_PROBE_REQUEST       200
+
+static int
+il3945_setup_mac(struct il_priv *il)
+{
+       int ret;
+       struct ieee80211_hw *hw = il->hw;
+
+       hw->rate_control_algorithm = "iwl-3945-rs";
+       hw->sta_data_size = sizeof(struct il3945_sta_priv);
+       hw->vif_data_size = sizeof(struct il_vif_priv);
+
+       /* Tell mac80211 our characteristics */
+       hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT;
+
+       hw->wiphy->interface_modes = il->ctx.interface_modes;
+
+       hw->wiphy->flags |=
+           WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS |
+           WIPHY_FLAG_IBSS_RSN;
+
+       hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
+       /* we create the 802.11 header and a zero-length SSID element */
+       hw->wiphy->max_scan_ie_len = IL3945_MAX_PROBE_REQUEST - 24 - 2;
+
+       /* Default value; 4 EDCA QOS priorities */
+       hw->queues = 4;
+
+       if (il->bands[IEEE80211_BAND_2GHZ].n_channels)
+               il->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+                   &il->bands[IEEE80211_BAND_2GHZ];
+
+       if (il->bands[IEEE80211_BAND_5GHZ].n_channels)
+               il->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+                   &il->bands[IEEE80211_BAND_5GHZ];
+
+       il_leds_init(il);
+
+       ret = ieee80211_register_hw(il->hw);
+       if (ret) {
+               IL_ERR("Failed to register hw (error %d)\n", ret);
+               return ret;
+       }
+       il->mac80211_registered = 1;
+
+       return 0;
+}
+
+static int
+il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       int err = 0;
+       struct il_priv *il;
+       struct ieee80211_hw *hw;
+       struct il_cfg *cfg = (struct il_cfg *)(ent->driver_data);
+       struct il3945_eeprom *eeprom;
+       unsigned long flags;
+
+       /***********************
+        * 1. Allocating HW data
+        * ********************/
+
+       /* mac80211 allocates memory for this device instance, including
+        *   space for this driver's ilate structure */
+       hw = il_alloc_all(cfg);
+       if (hw == NULL) {
+               pr_err("Can not allocate network device\n");
+               err = -ENOMEM;
+               goto out;
+       }
+       il = hw->priv;
+       SET_IEEE80211_DEV(hw, &pdev->dev);
+
+       il->cmd_queue = IL39_CMD_QUEUE_NUM;
+
+       il->ctx.ctxid = 0;
+
+       il->ctx.rxon_cmd = C_RXON;
+       il->ctx.rxon_timing_cmd = C_RXON_TIMING;
+       il->ctx.rxon_assoc_cmd = C_RXON_ASSOC;
+       il->ctx.qos_cmd = C_QOS_PARAM;
+       il->ctx.ap_sta_id = IL_AP_ID;
+       il->ctx.wep_key_cmd = C_WEPKEY;
+       il->ctx.interface_modes =
+           BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
+       il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS;
+       il->ctx.station_devtype = RXON_DEV_TYPE_ESS;
+       il->ctx.unused_devtype = RXON_DEV_TYPE_ESS;
+
+       /*
+        * Disabling hardware scan means that mac80211 will perform scans
+        * "the hard way", rather than using device's scan.
+        */
+       if (il3945_mod_params.disable_hw_scan) {
+               D_INFO("Disabling hw_scan\n");
+               il3945_hw_ops.hw_scan = NULL;
+       }
+
+       D_INFO("*** LOAD DRIVER ***\n");
+       il->cfg = cfg;
+       il->pci_dev = pdev;
+       il->inta_mask = CSR_INI_SET_MASK;
+
+       if (il_alloc_traffic_mem(il))
+               IL_ERR("Not enough memory to generate traffic log\n");
+
+       /***************************
+        * 2. Initializing PCI bus
+        * *************************/
+       pci_disable_link_state(pdev,
+                              PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                              PCIE_LINK_STATE_CLKPM);
+
+       if (pci_enable_device(pdev)) {
+               err = -ENODEV;
+               goto out_ieee80211_free_hw;
+       }
+
+       pci_set_master(pdev);
+
+       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (!err)
+               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (err) {
+               IL_WARN("No suitable DMA available.\n");
+               goto out_pci_disable_device;
+       }
+
+       pci_set_drvdata(pdev, il);
+       err = pci_request_regions(pdev, DRV_NAME);
+       if (err)
+               goto out_pci_disable_device;
+
+       /***********************
+        * 3. Read REV Register
+        * ********************/
+       il->hw_base = pci_iomap(pdev, 0, 0);
+       if (!il->hw_base) {
+               err = -ENODEV;
+               goto out_pci_release_regions;
+       }
+
+       D_INFO("pci_resource_len = 0x%08llx\n",
+              (unsigned long long)pci_resource_len(pdev, 0));
+       D_INFO("pci_resource_base = %p\n", il->hw_base);
+
+       /* 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);
+
+       /* these spin locks will be used in apm_ops.init and EEPROM access
+        * we should init now
+        */
+       spin_lock_init(&il->reg_lock);
+       spin_lock_init(&il->lock);
+
+       /*
+        * stop and reset the on-board processor just in case it is in a
+        * strange state ... like being left stranded by a primary kernel
+        * and this is now the kdump kernel trying to start up
+        */
+       _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+       /***********************
+        * 4. Read EEPROM
+        * ********************/
+
+       /* Read the EEPROM */
+       err = il_eeprom_init(il);
+       if (err) {
+               IL_ERR("Unable to init EEPROM\n");
+               goto out_iounmap;
+       }
+       /* MAC Address location in EEPROM same for 3945/4965 */
+       eeprom = (struct il3945_eeprom *)il->eeprom;
+       D_INFO("MAC address: %pM\n", eeprom->mac_address);
+       SET_IEEE80211_PERM_ADDR(il->hw, eeprom->mac_address);
+
+       /***********************
+        * 5. Setup HW Constants
+        * ********************/
+       /* Device-specific setup */
+       if (il3945_hw_set_hw_params(il)) {
+               IL_ERR("failed to set hw settings\n");
+               goto out_eeprom_free;
+       }
+
+       /***********************
+        * 6. Setup il
+        * ********************/
+
+       err = il3945_init_drv(il);
+       if (err) {
+               IL_ERR("initializing driver failed\n");
+               goto out_unset_hw_params;
+       }
+
+       IL_INFO("Detected Intel Wireless WiFi Link %s\n", il->cfg->name);
+
+       /***********************
+        * 7. Setup Services
+        * ********************/
+
+       spin_lock_irqsave(&il->lock, flags);
+       il_disable_interrupts(il);
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       pci_enable_msi(il->pci_dev);
+
+       err = request_irq(il->pci_dev->irq, il_isr, IRQF_SHARED, DRV_NAME, il);
+       if (err) {
+               IL_ERR("Error allocating IRQ %d\n", il->pci_dev->irq);
+               goto out_disable_msi;
+       }
+
+       err = sysfs_create_group(&pdev->dev.kobj, &il3945_attribute_group);
+       if (err) {
+               IL_ERR("failed to create sysfs device attributes\n");
+               goto out_release_irq;
+       }
+
+       il_set_rxon_channel(il, &il->bands[IEEE80211_BAND_2GHZ].channels[5],
+                           &il->ctx);
+       il3945_setup_deferred_work(il);
+       il3945_setup_handlers(il);
+       il_power_initialize(il);
+
+       /*********************************
+        * 8. Setup and Register mac80211
+        * *******************************/
+
+       il_enable_interrupts(il);
+
+       err = il3945_setup_mac(il);
+       if (err)
+               goto out_remove_sysfs;
+
+       err = il_dbgfs_register(il, DRV_NAME);
+       if (err)
+               IL_ERR("failed to create debugfs files. Ignoring error: %d\n",
+                      err);
+
+       /* Start monitoring the killswitch */
+       queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll, 2 * HZ);
+
+       return 0;
+
+out_remove_sysfs:
+       destroy_workqueue(il->workqueue);
+       il->workqueue = NULL;
+       sysfs_remove_group(&pdev->dev.kobj, &il3945_attribute_group);
+out_release_irq:
+       free_irq(il->pci_dev->irq, il);
+out_disable_msi:
+       pci_disable_msi(il->pci_dev);
+       il_free_geos(il);
+       il_free_channel_map(il);
+out_unset_hw_params:
+       il3945_unset_hw_params(il);
+out_eeprom_free:
+       il_eeprom_free(il);
+out_iounmap:
+       pci_iounmap(pdev, il->hw_base);
+out_pci_release_regions:
+       pci_release_regions(pdev);
+out_pci_disable_device:
+       pci_set_drvdata(pdev, NULL);
+       pci_disable_device(pdev);
+out_ieee80211_free_hw:
+       il_free_traffic_mem(il);
+       ieee80211_free_hw(il->hw);
+out:
+       return err;
+}
+
+static void __devexit
+il3945_pci_remove(struct pci_dev *pdev)
+{
+       struct il_priv *il = pci_get_drvdata(pdev);
+       unsigned long flags;
+
+       if (!il)
+               return;
+
+       D_INFO("*** UNLOAD DRIVER ***\n");
+
+       il_dbgfs_unregister(il);
+
+       set_bit(S_EXIT_PENDING, &il->status);
+
+       il_leds_exit(il);
+
+       if (il->mac80211_registered) {
+               ieee80211_unregister_hw(il->hw);
+               il->mac80211_registered = 0;
+       } else {
+               il3945_down(il);
+       }
+
+       /*
+        * Make sure device is reset to low power before unloading driver.
+        * This may be redundant with il_down(), but there are paths to
+        * run il_down() without calling apm_ops.stop(), and there are
+        * paths to avoid running il_down() at all before leaving driver.
+        * This (inexpensive) call *makes sure* device is reset.
+        */
+       il_apm_stop(il);
+
+       /* make sure we flush any pending irq or
+        * tasklet for the driver
+        */
+       spin_lock_irqsave(&il->lock, flags);
+       il_disable_interrupts(il);
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       il3945_synchronize_irq(il);
+
+       sysfs_remove_group(&pdev->dev.kobj, &il3945_attribute_group);
+
+       cancel_delayed_work_sync(&il->_3945.rfkill_poll);
+
+       il3945_dealloc_ucode_pci(il);
+
+       if (il->rxq.bd)
+               il3945_rx_queue_free(il, &il->rxq);
+       il3945_hw_txq_ctx_free(il);
+
+       il3945_unset_hw_params(il);
+
+       /*netif_stop_queue(dev); */
+       flush_workqueue(il->workqueue);
+
+       /* ieee80211_unregister_hw calls il3945_mac_stop, which flushes
+        * il->workqueue... so we can't take down the workqueue
+        * until now... */
+       destroy_workqueue(il->workqueue);
+       il->workqueue = NULL;
+       il_free_traffic_mem(il);
+
+       free_irq(pdev->irq, il);
+       pci_disable_msi(pdev);
+
+       pci_iounmap(pdev, il->hw_base);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+
+       il_free_channel_map(il);
+       il_free_geos(il);
+       kfree(il->scan_cmd);
+       if (il->beacon_skb)
+               dev_kfree_skb(il->beacon_skb);
+
+       ieee80211_free_hw(il->hw);
+}
+
+/*****************************************************************************
+ *
+ * driver and module entry point
+ *
+ *****************************************************************************/
+
+static struct pci_driver il3945_driver = {
+       .name = DRV_NAME,
+       .id_table = il3945_hw_card_ids,
+       .probe = il3945_pci_probe,
+       .remove = __devexit_p(il3945_pci_remove),
+       .driver.pm = IL_LEGACY_PM_OPS,
+};
+
+static int __init
+il3945_init(void)
+{
+
+       int ret;
+       pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+       pr_info(DRV_COPYRIGHT "\n");
+
+       ret = il3945_rate_control_register();
+       if (ret) {
+               pr_err("Unable to register rate control algorithm: %d\n", ret);
+               return ret;
+       }
+
+       ret = pci_register_driver(&il3945_driver);
+       if (ret) {
+               pr_err("Unable to initialize PCI module\n");
+               goto error_register;
+       }
+
+       return ret;
+
+error_register:
+       il3945_rate_control_unregister();
+       return ret;
+}
+
+static void __exit
+il3945_exit(void)
+{
+       pci_unregister_driver(&il3945_driver);
+       il3945_rate_control_unregister();
+}
+
+MODULE_FIRMWARE(IL3945_MODULE_FIRMWARE(IL3945_UCODE_API_MAX));
+
+module_param_named(antenna, il3945_mod_params.antenna, int, S_IRUGO);
+MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
+module_param_named(swcrypto, il3945_mod_params.sw_crypto, int, S_IRUGO);
+MODULE_PARM_DESC(swcrypto, "using software crypto (default 1 [software])");
+module_param_named(disable_hw_scan, il3945_mod_params.disable_hw_scan, int,
+                  S_IRUGO);
+MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 1)");
+#ifdef CONFIG_IWLEGACY_DEBUG
+module_param_named(debug, il_debug_level, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "debug output mask");
+#endif
+module_param_named(fw_restart, il3945_mod_params.restart_fw, int, S_IRUGO);
+MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
+
+module_exit(il3945_exit);
+module_init(il3945_init);
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c
new file mode 100644 (file)
index 0000000..30ad404
--- /dev/null
@@ -0,0 +1,995 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2005 - 2011 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:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+
+#include <linux/workqueue.h>
+
+#include "commands.h"
+#include "3945.h"
+
+#define RS_NAME "iwl-3945-rs"
+
+static s32 il3945_expected_tpt_g[RATE_COUNT_3945] = {
+       7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
+};
+
+static s32 il3945_expected_tpt_g_prot[RATE_COUNT_3945] = {
+       7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
+};
+
+static s32 il3945_expected_tpt_a[RATE_COUNT_3945] = {
+       0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
+};
+
+static s32 il3945_expected_tpt_b[RATE_COUNT_3945] = {
+       7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+struct il3945_tpt_entry {
+       s8 min_rssi;
+       u8 idx;
+};
+
+static struct il3945_tpt_entry il3945_tpt_table_a[] = {
+       {-60, RATE_54M_IDX},
+       {-64, RATE_48M_IDX},
+       {-72, RATE_36M_IDX},
+       {-80, RATE_24M_IDX},
+       {-84, RATE_18M_IDX},
+       {-85, RATE_12M_IDX},
+       {-87, RATE_9M_IDX},
+       {-89, RATE_6M_IDX}
+};
+
+static struct il3945_tpt_entry il3945_tpt_table_g[] = {
+       {-60, RATE_54M_IDX},
+       {-64, RATE_48M_IDX},
+       {-68, RATE_36M_IDX},
+       {-80, RATE_24M_IDX},
+       {-84, RATE_18M_IDX},
+       {-85, RATE_12M_IDX},
+       {-86, RATE_11M_IDX},
+       {-88, RATE_5M_IDX},
+       {-90, RATE_2M_IDX},
+       {-92, RATE_1M_IDX}
+};
+
+#define RATE_MAX_WINDOW          62
+#define RATE_FLUSH             (3*HZ)
+#define RATE_WIN_FLUSH       (HZ/2)
+#define IL39_RATE_HIGH_TH          11520
+#define IL_SUCCESS_UP_TH          8960
+#define IL_SUCCESS_DOWN_TH       10880
+#define RATE_MIN_FAILURE_TH       6
+#define RATE_MIN_SUCCESS_TH       8
+#define RATE_DECREASE_TH       1920
+#define RATE_RETRY_TH       15
+
+static u8
+il3945_get_rate_idx_by_rssi(s32 rssi, enum ieee80211_band band)
+{
+       u32 idx = 0;
+       u32 table_size = 0;
+       struct il3945_tpt_entry *tpt_table = NULL;
+
+       if (rssi < IL_MIN_RSSI_VAL || rssi > IL_MAX_RSSI_VAL)
+               rssi = IL_MIN_RSSI_VAL;
+
+       switch (band) {
+       case IEEE80211_BAND_2GHZ:
+               tpt_table = il3945_tpt_table_g;
+               table_size = ARRAY_SIZE(il3945_tpt_table_g);
+               break;
+
+       case IEEE80211_BAND_5GHZ:
+               tpt_table = il3945_tpt_table_a;
+               table_size = ARRAY_SIZE(il3945_tpt_table_a);
+               break;
+
+       default:
+               BUG();
+               break;
+       }
+
+       while (idx < table_size && rssi < tpt_table[idx].min_rssi)
+               idx++;
+
+       idx = min(idx, (table_size - 1));
+
+       return tpt_table[idx].idx;
+}
+
+static void
+il3945_clear_win(struct il3945_rate_scale_data *win)
+{
+       win->data = 0;
+       win->success_counter = 0;
+       win->success_ratio = -1;
+       win->counter = 0;
+       win->average_tpt = IL_INVALID_VALUE;
+       win->stamp = 0;
+}
+
+/**
+ * il3945_rate_scale_flush_wins - flush out the rate scale wins
+ *
+ * Returns the number of wins that have gathered data but were
+ * not flushed.  If there were any that were not flushed, then
+ * reschedule the rate flushing routine.
+ */
+static int
+il3945_rate_scale_flush_wins(struct il3945_rs_sta *rs_sta)
+{
+       int unflushed = 0;
+       int i;
+       unsigned long flags;
+       struct il_priv *il __maybe_unused = rs_sta->il;
+
+       /*
+        * For each rate, if we have collected data on that rate
+        * and it has been more than RATE_WIN_FLUSH
+        * since we flushed, clear out the gathered stats
+        */
+       for (i = 0; i < RATE_COUNT_3945; i++) {
+               if (!rs_sta->win[i].counter)
+                       continue;
+
+               spin_lock_irqsave(&rs_sta->lock, flags);
+               if (time_after(jiffies, rs_sta->win[i].stamp + RATE_WIN_FLUSH)) {
+                       D_RATE("flushing %d samples of rate " "idx %d\n",
+                              rs_sta->win[i].counter, i);
+                       il3945_clear_win(&rs_sta->win[i]);
+               } else
+                       unflushed++;
+               spin_unlock_irqrestore(&rs_sta->lock, flags);
+       }
+
+       return unflushed;
+}
+
+#define RATE_FLUSH_MAX              5000       /* msec */
+#define RATE_FLUSH_MIN              50 /* msec */
+#define IL_AVERAGE_PACKETS             1500
+
+static void
+il3945_bg_rate_scale_flush(unsigned long data)
+{
+       struct il3945_rs_sta *rs_sta = (void *)data;
+       struct il_priv *il __maybe_unused = rs_sta->il;
+       int unflushed = 0;
+       unsigned long flags;
+       u32 packet_count, duration, pps;
+
+       D_RATE("enter\n");
+
+       unflushed = il3945_rate_scale_flush_wins(rs_sta);
+
+       spin_lock_irqsave(&rs_sta->lock, flags);
+
+       /* Number of packets Rx'd since last time this timer ran */
+       packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
+
+       rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
+
+       if (unflushed) {
+               duration =
+                   jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
+
+               D_RATE("Tx'd %d packets in %dms\n", packet_count, duration);
+
+               /* Determine packets per second */
+               if (duration)
+                       pps = (packet_count * 1000) / duration;
+               else
+                       pps = 0;
+
+               if (pps) {
+                       duration = (IL_AVERAGE_PACKETS * 1000) / pps;
+                       if (duration < RATE_FLUSH_MIN)
+                               duration = RATE_FLUSH_MIN;
+                       else if (duration > RATE_FLUSH_MAX)
+                               duration = RATE_FLUSH_MAX;
+               } else
+                       duration = RATE_FLUSH_MAX;
+
+               rs_sta->flush_time = msecs_to_jiffies(duration);
+
+               D_RATE("new flush period: %d msec ave %d\n", duration,
+                      packet_count);
+
+               mod_timer(&rs_sta->rate_scale_flush,
+                         jiffies + rs_sta->flush_time);
+
+               rs_sta->last_partial_flush = jiffies;
+       } else {
+               rs_sta->flush_time = RATE_FLUSH;
+               rs_sta->flush_pending = 0;
+       }
+       /* If there weren't any unflushed entries, we don't schedule the timer
+        * to run again */
+
+       rs_sta->last_flush = jiffies;
+
+       spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+       D_RATE("leave\n");
+}
+
+/**
+ * il3945_collect_tx_data - Update the success/failure sliding win
+ *
+ * We keep a sliding win of the last 64 packets transmitted
+ * at this rate.  win->data contains the bitmask of successful
+ * packets.
+ */
+static void
+il3945_collect_tx_data(struct il3945_rs_sta *rs_sta,
+                      struct il3945_rate_scale_data *win, int success,
+                      int retries, int idx)
+{
+       unsigned long flags;
+       s32 fail_count;
+       struct il_priv *il __maybe_unused = rs_sta->il;
+
+       if (!retries) {
+               D_RATE("leave: retries == 0 -- should be at least 1\n");
+               return;
+       }
+
+       spin_lock_irqsave(&rs_sta->lock, flags);
+
+       /*
+        * Keep track of only the latest 62 tx frame attempts in this rate's
+        * history win; anything older isn't really relevant any more.
+        * If we have filled up the sliding win, drop the oldest attempt;
+        * if the oldest attempt (highest bit in bitmap) shows "success",
+        * subtract "1" from the success counter (this is the main reason
+        * we keep these bitmaps!).
+        * */
+       while (retries > 0) {
+               if (win->counter >= RATE_MAX_WINDOW) {
+
+                       /* remove earliest */
+                       win->counter = RATE_MAX_WINDOW - 1;
+
+                       if (win->data & (1ULL << (RATE_MAX_WINDOW - 1))) {
+                               win->data &= ~(1ULL << (RATE_MAX_WINDOW - 1));
+                               win->success_counter--;
+                       }
+               }
+
+               /* Increment frames-attempted counter */
+               win->counter++;
+
+               /* Shift bitmap by one frame (throw away oldest history),
+                * OR in "1", and increment "success" if this
+                * frame was successful. */
+               win->data <<= 1;
+               if (success > 0) {
+                       win->success_counter++;
+                       win->data |= 0x1;
+                       success--;
+               }
+
+               retries--;
+       }
+
+       /* Calculate current success ratio, avoid divide-by-0! */
+       if (win->counter > 0)
+               win->success_ratio =
+                   128 * (100 * win->success_counter) / win->counter;
+       else
+               win->success_ratio = IL_INVALID_VALUE;
+
+       fail_count = win->counter - win->success_counter;
+
+       /* Calculate average throughput, if we have enough history. */
+       if (fail_count >= RATE_MIN_FAILURE_TH ||
+           win->success_counter >= RATE_MIN_SUCCESS_TH)
+               win->average_tpt =
+                   ((win->success_ratio * rs_sta->expected_tpt[idx] +
+                     64) / 128);
+       else
+               win->average_tpt = IL_INVALID_VALUE;
+
+       /* Tag this win as having been updated */
+       win->stamp = jiffies;
+
+       spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+}
+
+/*
+ * Called after adding a new station to initialize rate scaling
+ */
+void
+il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
+{
+       struct ieee80211_hw *hw = il->hw;
+       struct ieee80211_conf *conf = &il->hw->conf;
+       struct il3945_sta_priv *psta;
+       struct il3945_rs_sta *rs_sta;
+       struct ieee80211_supported_band *sband;
+       int i;
+
+       D_INFO("enter\n");
+       if (sta_id == il->ctx.bcast_sta_id)
+               goto out;
+
+       psta = (struct il3945_sta_priv *)sta->drv_priv;
+       rs_sta = &psta->rs_sta;
+       sband = hw->wiphy->bands[conf->channel->band];
+
+       rs_sta->il = il;
+
+       rs_sta->start_rate = RATE_INVALID;
+
+       /* default to just 802.11b */
+       rs_sta->expected_tpt = il3945_expected_tpt_b;
+
+       rs_sta->last_partial_flush = jiffies;
+       rs_sta->last_flush = jiffies;
+       rs_sta->flush_time = RATE_FLUSH;
+       rs_sta->last_tx_packets = 0;
+
+       rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
+       rs_sta->rate_scale_flush.function = il3945_bg_rate_scale_flush;
+
+       for (i = 0; i < RATE_COUNT_3945; i++)
+               il3945_clear_win(&rs_sta->win[i]);
+
+       /* TODO: what is a good starting rate for STA? About middle? Maybe not
+        * the lowest or the highest rate.. Could consider using RSSI from
+        * previous packets? Need to have IEEE 802.1X auth succeed immediately
+        * after assoc.. */
+
+       for (i = sband->n_bitrates - 1; i >= 0; i--) {
+               if (sta->supp_rates[sband->band] & (1 << i)) {
+                       rs_sta->last_txrate_idx = i;
+                       break;
+               }
+       }
+
+       il->_3945.sta_supp_rates = sta->supp_rates[sband->band];
+       /* For 5 GHz band it start at IL_FIRST_OFDM_RATE */
+       if (sband->band == IEEE80211_BAND_5GHZ) {
+               rs_sta->last_txrate_idx += IL_FIRST_OFDM_RATE;
+               il->_3945.sta_supp_rates =
+                   il->_3945.sta_supp_rates << IL_FIRST_OFDM_RATE;
+       }
+
+out:
+       il->stations[sta_id].used &= ~IL_STA_UCODE_INPROGRESS;
+
+       D_INFO("leave\n");
+}
+
+static void *
+il3945_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+{
+       return hw->priv;
+}
+
+/* rate scale requires free function to be implemented */
+static void
+il3945_rs_free(void *il)
+{
+       return;
+}
+
+static void *
+il3945_rs_alloc_sta(void *il_priv, struct ieee80211_sta *sta, gfp_t gfp)
+{
+       struct il3945_rs_sta *rs_sta;
+       struct il3945_sta_priv *psta = (void *)sta->drv_priv;
+       struct il_priv *il __maybe_unused = il_priv;
+
+       D_RATE("enter\n");
+
+       rs_sta = &psta->rs_sta;
+
+       spin_lock_init(&rs_sta->lock);
+       init_timer(&rs_sta->rate_scale_flush);
+
+       D_RATE("leave\n");
+
+       return rs_sta;
+}
+
+static void
+il3945_rs_free_sta(void *il_priv, struct ieee80211_sta *sta, void *il_sta)
+{
+       struct il3945_rs_sta *rs_sta = il_sta;
+
+       /*
+        * Be careful not to use any members of il3945_rs_sta (like trying
+        * to use il_priv to print out debugging) since it may not be fully
+        * initialized at this point.
+        */
+       del_timer_sync(&rs_sta->rate_scale_flush);
+}
+
+/**
+ * il3945_rs_tx_status - Update rate control values based on Tx results
+ *
+ * NOTE: Uses il_priv->retry_rate for the # of retries attempted by
+ * the hardware for each rate.
+ */
+static void
+il3945_rs_tx_status(void *il_rate, struct ieee80211_supported_band *sband,
+                   struct ieee80211_sta *sta, void *il_sta,
+                   struct sk_buff *skb)
+{
+       s8 retries = 0, current_count;
+       int scale_rate_idx, first_idx, last_idx;
+       unsigned long flags;
+       struct il_priv *il = (struct il_priv *)il_rate;
+       struct il3945_rs_sta *rs_sta = il_sta;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+       D_RATE("enter\n");
+
+       retries = info->status.rates[0].count;
+       /* Sanity Check for retries */
+       if (retries > RATE_RETRY_TH)
+               retries = RATE_RETRY_TH;
+
+       first_idx = sband->bitrates[info->status.rates[0].idx].hw_value;
+       if (first_idx < 0 || first_idx >= RATE_COUNT_3945) {
+               D_RATE("leave: Rate out of bounds: %d\n", first_idx);
+               return;
+       }
+
+       if (!il_sta) {
+               D_RATE("leave: No STA il data to update!\n");
+               return;
+       }
+
+       /* Treat uninitialized rate scaling data same as non-existing. */
+       if (!rs_sta->il) {
+               D_RATE("leave: STA il data uninitialized!\n");
+               return;
+       }
+
+       rs_sta->tx_packets++;
+
+       scale_rate_idx = first_idx;
+       last_idx = first_idx;
+
+       /*
+        * Update the win for each rate.  We determine which rates
+        * were Tx'd based on the total number of retries vs. the number
+        * of retries configured for each rate -- currently set to the
+        * il value 'retry_rate' vs. rate specific
+        *
+        * On exit from this while loop last_idx indicates the rate
+        * at which the frame was finally transmitted (or failed if no
+        * ACK)
+        */
+       while (retries > 1) {
+               if ((retries - 1) < il->retry_rate) {
+                       current_count = (retries - 1);
+                       last_idx = scale_rate_idx;
+               } else {
+                       current_count = il->retry_rate;
+                       last_idx = il3945_rs_next_rate(il, scale_rate_idx);
+               }
+
+               /* Update this rate accounting for as many retries
+                * as was used for it (per current_count) */
+               il3945_collect_tx_data(rs_sta, &rs_sta->win[scale_rate_idx], 0,
+                                      current_count, scale_rate_idx);
+               D_RATE("Update rate %d for %d retries.\n", scale_rate_idx,
+                      current_count);
+
+               retries -= current_count;
+
+               scale_rate_idx = last_idx;
+       }
+
+       /* Update the last idx win with success/failure based on ACK */
+       D_RATE("Update rate %d with %s.\n", last_idx,
+              (info->flags & IEEE80211_TX_STAT_ACK) ? "success" : "failure");
+       il3945_collect_tx_data(rs_sta, &rs_sta->win[last_idx],
+                              info->flags & IEEE80211_TX_STAT_ACK, 1,
+                              last_idx);
+
+       /* We updated the rate scale win -- if its been more than
+        * flush_time since the last run, schedule the flush
+        * again */
+       spin_lock_irqsave(&rs_sta->lock, flags);
+
+       if (!rs_sta->flush_pending &&
+           time_after(jiffies, rs_sta->last_flush + rs_sta->flush_time)) {
+
+               rs_sta->last_partial_flush = jiffies;
+               rs_sta->flush_pending = 1;
+               mod_timer(&rs_sta->rate_scale_flush,
+                         jiffies + rs_sta->flush_time);
+       }
+
+       spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+       D_RATE("leave\n");
+}
+
+static u16
+il3945_get_adjacent_rate(struct il3945_rs_sta *rs_sta, u8 idx, u16 rate_mask,
+                        enum ieee80211_band band)
+{
+       u8 high = RATE_INVALID;
+       u8 low = RATE_INVALID;
+       struct il_priv *il __maybe_unused = rs_sta->il;
+
+       /* 802.11A walks to the next literal adjacent rate in
+        * the rate table */
+       if (unlikely(band == IEEE80211_BAND_5GHZ)) {
+               int i;
+               u32 mask;
+
+               /* Find the previous rate that is in the rate mask */
+               i = idx - 1;
+               for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
+                       if (rate_mask & mask) {
+                               low = i;
+                               break;
+                       }
+               }
+
+               /* Find the next rate that is in the rate mask */
+               i = idx + 1;
+               for (mask = (1 << i); i < RATE_COUNT_3945; i++, mask <<= 1) {
+                       if (rate_mask & mask) {
+                               high = i;
+                               break;
+                       }
+               }
+
+               return (high << 8) | low;
+       }
+
+       low = idx;
+       while (low != RATE_INVALID) {
+               if (rs_sta->tgg)
+                       low = il3945_rates[low].prev_rs_tgg;
+               else
+                       low = il3945_rates[low].prev_rs;
+               if (low == RATE_INVALID)
+                       break;
+               if (rate_mask & (1 << low))
+                       break;
+               D_RATE("Skipping masked lower rate: %d\n", low);
+       }
+
+       high = idx;
+       while (high != RATE_INVALID) {
+               if (rs_sta->tgg)
+                       high = il3945_rates[high].next_rs_tgg;
+               else
+                       high = il3945_rates[high].next_rs;
+               if (high == RATE_INVALID)
+                       break;
+               if (rate_mask & (1 << high))
+                       break;
+               D_RATE("Skipping masked higher rate: %d\n", high);
+       }
+
+       return (high << 8) | low;
+}
+
+/**
+ * il3945_rs_get_rate - find the rate for the requested packet
+ *
+ * Returns the ieee80211_rate structure allocated by the driver.
+ *
+ * The rate control algorithm has no internal mapping between hw_mode's
+ * rate ordering and the rate ordering used by the rate control algorithm.
+ *
+ * The rate control algorithm uses a single table of rates that goes across
+ * the entire A/B/G spectrum vs. being limited to just one particular
+ * hw_mode.
+ *
+ * As such, we can't convert the idx obtained below into the hw_mode's
+ * rate table and must reference the driver allocated rate table
+ *
+ */
+static void
+il3945_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta,
+                  struct ieee80211_tx_rate_control *txrc)
+{
+       struct ieee80211_supported_band *sband = txrc->sband;
+       struct sk_buff *skb = txrc->skb;
+       u8 low = RATE_INVALID;
+       u8 high = RATE_INVALID;
+       u16 high_low;
+       int idx;
+       struct il3945_rs_sta *rs_sta = il_sta;
+       struct il3945_rate_scale_data *win = NULL;
+       int current_tpt = IL_INVALID_VALUE;
+       int low_tpt = IL_INVALID_VALUE;
+       int high_tpt = IL_INVALID_VALUE;
+       u32 fail_count;
+       s8 scale_action = 0;
+       unsigned long flags;
+       u16 rate_mask;
+       s8 max_rate_idx = -1;
+       struct il_priv *il __maybe_unused = (struct il_priv *)il_r;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+       D_RATE("enter\n");
+
+       /* Treat uninitialized rate scaling data same as non-existing. */
+       if (rs_sta && !rs_sta->il) {
+               D_RATE("Rate scaling information not initialized yet.\n");
+               il_sta = NULL;
+       }
+
+       if (rate_control_send_low(sta, il_sta, txrc))
+               return;
+
+       rate_mask = sta->supp_rates[sband->band];
+
+       /* get user max rate if set */
+       max_rate_idx = txrc->max_rate_idx;
+       if (sband->band == IEEE80211_BAND_5GHZ && max_rate_idx != -1)
+               max_rate_idx += IL_FIRST_OFDM_RATE;
+       if (max_rate_idx < 0 || max_rate_idx >= RATE_COUNT)
+               max_rate_idx = -1;
+
+       idx = min(rs_sta->last_txrate_idx & 0xffff, RATE_COUNT_3945 - 1);
+
+       if (sband->band == IEEE80211_BAND_5GHZ)
+               rate_mask = rate_mask << IL_FIRST_OFDM_RATE;
+
+       spin_lock_irqsave(&rs_sta->lock, flags);
+
+       /* for recent assoc, choose best rate regarding
+        * to rssi value
+        */
+       if (rs_sta->start_rate != RATE_INVALID) {
+               if (rs_sta->start_rate < idx &&
+                   (rate_mask & (1 << rs_sta->start_rate)))
+                       idx = rs_sta->start_rate;
+               rs_sta->start_rate = RATE_INVALID;
+       }
+
+       /* force user max rate if set by user */
+       if (max_rate_idx != -1 && max_rate_idx < idx) {
+               if (rate_mask & (1 << max_rate_idx))
+                       idx = max_rate_idx;
+       }
+
+       win = &(rs_sta->win[idx]);
+
+       fail_count = win->counter - win->success_counter;
+
+       if (fail_count < RATE_MIN_FAILURE_TH &&
+           win->success_counter < RATE_MIN_SUCCESS_TH) {
+               spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+               D_RATE("Invalid average_tpt on rate %d: "
+                      "counter: %d, success_counter: %d, "
+                      "expected_tpt is %sNULL\n", idx, win->counter,
+                      win->success_counter,
+                      rs_sta->expected_tpt ? "not " : "");
+
+               /* Can't calculate this yet; not enough history */
+               win->average_tpt = IL_INVALID_VALUE;
+               goto out;
+
+       }
+
+       current_tpt = win->average_tpt;
+
+       high_low =
+           il3945_get_adjacent_rate(rs_sta, idx, rate_mask, sband->band);
+       low = high_low & 0xff;
+       high = (high_low >> 8) & 0xff;
+
+       /* If user set max rate, dont allow higher than user constrain */
+       if (max_rate_idx != -1 && max_rate_idx < high)
+               high = RATE_INVALID;
+
+       /* Collect Measured throughputs of adjacent rates */
+       if (low != RATE_INVALID)
+               low_tpt = rs_sta->win[low].average_tpt;
+
+       if (high != RATE_INVALID)
+               high_tpt = rs_sta->win[high].average_tpt;
+
+       spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+       scale_action = 0;
+
+       /* Low success ratio , need to drop the rate */
+       if (win->success_ratio < RATE_DECREASE_TH || !current_tpt) {
+               D_RATE("decrease rate because of low success_ratio\n");
+               scale_action = -1;
+               /* No throughput measured yet for adjacent rates,
+                * try increase */
+       } else if (low_tpt == IL_INVALID_VALUE && high_tpt == IL_INVALID_VALUE) {
+
+               if (high != RATE_INVALID &&
+                   win->success_ratio >= RATE_INCREASE_TH)
+                       scale_action = 1;
+               else if (low != RATE_INVALID)
+                       scale_action = 0;
+
+               /* Both adjacent throughputs are measured, but neither one has
+                * better throughput; we're using the best rate, don't change
+                * it! */
+       } else if (low_tpt != IL_INVALID_VALUE && high_tpt != IL_INVALID_VALUE
+                  && low_tpt < current_tpt && high_tpt < current_tpt) {
+
+               D_RATE("No action -- low [%d] & high [%d] < "
+                      "current_tpt [%d]\n", low_tpt, high_tpt, current_tpt);
+               scale_action = 0;
+
+               /* At least one of the rates has better throughput */
+       } else {
+               if (high_tpt != IL_INVALID_VALUE) {
+
+                       /* High rate has better throughput, Increase
+                        * rate */
+                       if (high_tpt > current_tpt &&
+                           win->success_ratio >= RATE_INCREASE_TH)
+                               scale_action = 1;
+                       else {
+                               D_RATE("decrease rate because of high tpt\n");
+                               scale_action = 0;
+                       }
+               } else if (low_tpt != IL_INVALID_VALUE) {
+                       if (low_tpt > current_tpt) {
+                               D_RATE("decrease rate because of low tpt\n");
+                               scale_action = -1;
+                       } else if (win->success_ratio >= RATE_INCREASE_TH) {
+                               /* Lower rate has better
+                                * throughput,decrease rate */
+                               scale_action = 1;
+                       }
+               }
+       }
+
+       /* Sanity check; asked for decrease, but success rate or throughput
+        * has been good at old rate.  Don't change it. */
+       if (scale_action == -1 && low != RATE_INVALID &&
+           (win->success_ratio > RATE_HIGH_TH ||
+            current_tpt > 100 * rs_sta->expected_tpt[low]))
+               scale_action = 0;
+
+       switch (scale_action) {
+       case -1:
+
+               /* Decrese rate */
+               if (low != RATE_INVALID)
+                       idx = low;
+               break;
+
+       case 1:
+               /* Increase rate */
+               if (high != RATE_INVALID)
+                       idx = high;
+
+               break;
+
+       case 0:
+       default:
+               /* No change */
+               break;
+       }
+
+       D_RATE("Selected %d (action %d) - low %d high %d\n", idx, scale_action,
+              low, high);
+
+out:
+
+       if (sband->band == IEEE80211_BAND_5GHZ) {
+               if (WARN_ON_ONCE(idx < IL_FIRST_OFDM_RATE))
+                       idx = IL_FIRST_OFDM_RATE;
+               rs_sta->last_txrate_idx = idx;
+               info->control.rates[0].idx = idx - IL_FIRST_OFDM_RATE;
+       } else {
+               rs_sta->last_txrate_idx = idx;
+               info->control.rates[0].idx = rs_sta->last_txrate_idx;
+       }
+
+       D_RATE("leave: %d\n", idx);
+}
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static int
+il3945_open_file_generic(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t
+il3945_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       char *buff;
+       int desc = 0;
+       int j;
+       ssize_t ret;
+       struct il3945_rs_sta *lq_sta = file->private_data;
+
+       buff = kmalloc(1024, GFP_KERNEL);
+       if (!buff)
+               return -ENOMEM;
+
+       desc +=
+           sprintf(buff + desc,
+                   "tx packets=%d last rate idx=%d\n"
+                   "rate=0x%X flush time %d\n", lq_sta->tx_packets,
+                   lq_sta->last_txrate_idx, lq_sta->start_rate,
+                   jiffies_to_msecs(lq_sta->flush_time));
+       for (j = 0; j < RATE_COUNT_3945; j++) {
+               desc +=
+                   sprintf(buff + desc, "counter=%d success=%d %%=%d\n",
+                           lq_sta->win[j].counter,
+                           lq_sta->win[j].success_counter,
+                           lq_sta->win[j].success_ratio);
+       }
+       ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+       kfree(buff);
+       return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
+       .read = il3945_sta_dbgfs_stats_table_read,
+       .open = il3945_open_file_generic,
+       .llseek = default_llseek,
+};
+
+static void
+il3945_add_debugfs(void *il, void *il_sta, struct dentry *dir)
+{
+       struct il3945_rs_sta *lq_sta = il_sta;
+
+       lq_sta->rs_sta_dbgfs_stats_table_file =
+           debugfs_create_file("rate_stats_table", 0600, dir, lq_sta,
+                               &rs_sta_dbgfs_stats_table_ops);
+
+}
+
+static void
+il3945_remove_debugfs(void *il, void *il_sta)
+{
+       struct il3945_rs_sta *lq_sta = il_sta;
+       debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
+}
+#endif
+
+/*
+ * Initialization of rate scaling information is done by driver after
+ * the station is added. Since mac80211 calls this function before a
+ * station is added we ignore it.
+ */
+static void
+il3945_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
+                        struct ieee80211_sta *sta, void *il_sta)
+{
+}
+
+static struct rate_control_ops rs_ops = {
+       .module = NULL,
+       .name = RS_NAME,
+       .tx_status = il3945_rs_tx_status,
+       .get_rate = il3945_rs_get_rate,
+       .rate_init = il3945_rs_rate_init_stub,
+       .alloc = il3945_rs_alloc,
+       .free = il3945_rs_free,
+       .alloc_sta = il3945_rs_alloc_sta,
+       .free_sta = il3945_rs_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+       .add_sta_debugfs = il3945_add_debugfs,
+       .remove_sta_debugfs = il3945_remove_debugfs,
+#endif
+
+};
+
+void
+il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+{
+       struct il_priv *il = hw->priv;
+       s32 rssi = 0;
+       unsigned long flags;
+       struct il3945_rs_sta *rs_sta;
+       struct ieee80211_sta *sta;
+       struct il3945_sta_priv *psta;
+
+       D_RATE("enter\n");
+
+       rcu_read_lock();
+
+       sta =
+           ieee80211_find_sta(il->ctx.vif, il->stations[sta_id].sta.sta.addr);
+       if (!sta) {
+               D_RATE("Unable to find station to initialize rate scaling.\n");
+               rcu_read_unlock();
+               return;
+       }
+
+       psta = (void *)sta->drv_priv;
+       rs_sta = &psta->rs_sta;
+
+       spin_lock_irqsave(&rs_sta->lock, flags);
+
+       rs_sta->tgg = 0;
+       switch (il->band) {
+       case IEEE80211_BAND_2GHZ:
+               /* TODO: this always does G, not a regression */
+               if (il->ctx.active.flags & RXON_FLG_TGG_PROTECT_MSK) {
+                       rs_sta->tgg = 1;
+                       rs_sta->expected_tpt = il3945_expected_tpt_g_prot;
+               } else
+                       rs_sta->expected_tpt = il3945_expected_tpt_g;
+               break;
+
+       case IEEE80211_BAND_5GHZ:
+               rs_sta->expected_tpt = il3945_expected_tpt_a;
+               break;
+       case IEEE80211_NUM_BANDS:
+               BUG();
+               break;
+       }
+
+       spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+       rssi = il->_3945.last_rx_rssi;
+       if (rssi == 0)
+               rssi = IL_MIN_RSSI_VAL;
+
+       D_RATE("Network RSSI: %d\n", rssi);
+
+       rs_sta->start_rate = il3945_get_rate_idx_by_rssi(rssi, il->band);
+
+       D_RATE("leave: rssi %d assign rate idx: " "%d (plcp 0x%x)\n", rssi,
+              rs_sta->start_rate, il3945_rates[rs_sta->start_rate].plcp);
+       rcu_read_unlock();
+}
+
+int
+il3945_rate_control_register(void)
+{
+       return ieee80211_rate_control_register(&rs_ops);
+}
+
+void
+il3945_rate_control_unregister(void)
+{
+       ieee80211_rate_control_unregister(&rs_ops);
+}
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
new file mode 100644 (file)
index 0000000..863664f
--- /dev/null
@@ -0,0 +1,2751 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+#include <net/mac80211.h>
+
+#include "common.h"
+#include "3945.h"
+
+/* Send led command */
+static int
+il3945_send_led_cmd(struct il_priv *il, struct il_led_cmd *led_cmd)
+{
+       struct il_host_cmd cmd = {
+               .id = C_LEDS,
+               .len = sizeof(struct il_led_cmd),
+               .data = led_cmd,
+               .flags = CMD_ASYNC,
+               .callback = NULL,
+       };
+
+       return il_send_cmd(il, &cmd);
+}
+
+const struct il_led_ops il3945_led_ops = {
+       .cmd = il3945_send_led_cmd,
+};
+
+#define IL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
+       [RATE_##r##M_IDX] = { RATE_##r##M_PLCP,   \
+                                   RATE_##r##M_IEEE,   \
+                                   RATE_##ip##M_IDX, \
+                                   RATE_##in##M_IDX, \
+                                   RATE_##rp##M_IDX, \
+                                   RATE_##rn##M_IDX, \
+                                   RATE_##pp##M_IDX, \
+                                   RATE_##np##M_IDX, \
+                                   RATE_##r##M_IDX_TBL, \
+                                   RATE_##ip##M_IDX_TBL }
+
+/*
+ * Parameter order:
+ *   rate, prev rate, next rate, prev tgg rate, next tgg rate
+ *
+ * If there isn't a valid next or previous rate then INV is used which
+ * maps to RATE_INVALID
+ *
+ */
+const struct il3945_rate_info il3945_rates[RATE_COUNT_3945] = {
+       IL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2),        /*  1mbps */
+       IL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5),      /*  2mbps */
+       IL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11),    /*5.5mbps */
+       IL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18),  /* 11mbps */
+       IL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11),    /*  6mbps */
+       IL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11),   /*  9mbps */
+       IL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18),       /* 12mbps */
+       IL_DECLARE_RATE_INFO(18, 12, 24, 12, 24, 11, 24),       /* 18mbps */
+       IL_DECLARE_RATE_INFO(24, 18, 36, 18, 36, 18, 36),       /* 24mbps */
+       IL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48),       /* 36mbps */
+       IL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54),       /* 48mbps */
+       IL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),    /* 54mbps */
+};
+
+static inline u8
+il3945_get_prev_ieee_rate(u8 rate_idx)
+{
+       u8 rate = il3945_rates[rate_idx].prev_ieee;
+
+       if (rate == RATE_INVALID)
+               rate = rate_idx;
+       return rate;
+}
+
+/* 1 = enable the il3945_disable_events() function */
+#define IL_EVT_DISABLE (0)
+#define IL_EVT_DISABLE_SIZE (1532/32)
+
+/**
+ * il3945_disable_events - Disable selected events in uCode event log
+ *
+ * Disable an event by writing "1"s into "disable"
+ *   bitmap in SRAM.  Bit position corresponds to Event # (id/type).
+ *   Default values of 0 enable uCode events to be logged.
+ * Use for only special debugging.  This function is just a placeholder as-is,
+ *   you'll need to provide the special bits! ...
+ *   ... and set IL_EVT_DISABLE to 1. */
+void
+il3945_disable_events(struct il_priv *il)
+{
+       int i;
+       u32 base;               /* SRAM address of event log header */
+       u32 disable_ptr;        /* SRAM address of event-disable bitmap array */
+       u32 array_size;         /* # of u32 entries in array */
+       static const u32 evt_disable[IL_EVT_DISABLE_SIZE] = {
+               0x00000000,     /*   31 -    0  Event id numbers */
+               0x00000000,     /*   63 -   32 */
+               0x00000000,     /*   95 -   64 */
+               0x00000000,     /*  127 -   96 */
+               0x00000000,     /*  159 -  128 */
+               0x00000000,     /*  191 -  160 */
+               0x00000000,     /*  223 -  192 */
+               0x00000000,     /*  255 -  224 */
+               0x00000000,     /*  287 -  256 */
+               0x00000000,     /*  319 -  288 */
+               0x00000000,     /*  351 -  320 */
+               0x00000000,     /*  383 -  352 */
+               0x00000000,     /*  415 -  384 */
+               0x00000000,     /*  447 -  416 */
+               0x00000000,     /*  479 -  448 */
+               0x00000000,     /*  511 -  480 */
+               0x00000000,     /*  543 -  512 */
+               0x00000000,     /*  575 -  544 */
+               0x00000000,     /*  607 -  576 */
+               0x00000000,     /*  639 -  608 */
+               0x00000000,     /*  671 -  640 */
+               0x00000000,     /*  703 -  672 */
+               0x00000000,     /*  735 -  704 */
+               0x00000000,     /*  767 -  736 */
+               0x00000000,     /*  799 -  768 */
+               0x00000000,     /*  831 -  800 */
+               0x00000000,     /*  863 -  832 */
+               0x00000000,     /*  895 -  864 */
+               0x00000000,     /*  927 -  896 */
+               0x00000000,     /*  959 -  928 */
+               0x00000000,     /*  991 -  960 */
+               0x00000000,     /* 1023 -  992 */
+               0x00000000,     /* 1055 - 1024 */
+               0x00000000,     /* 1087 - 1056 */
+               0x00000000,     /* 1119 - 1088 */
+               0x00000000,     /* 1151 - 1120 */
+               0x00000000,     /* 1183 - 1152 */
+               0x00000000,     /* 1215 - 1184 */
+               0x00000000,     /* 1247 - 1216 */
+               0x00000000,     /* 1279 - 1248 */
+               0x00000000,     /* 1311 - 1280 */
+               0x00000000,     /* 1343 - 1312 */
+               0x00000000,     /* 1375 - 1344 */
+               0x00000000,     /* 1407 - 1376 */
+               0x00000000,     /* 1439 - 1408 */
+               0x00000000,     /* 1471 - 1440 */
+               0x00000000,     /* 1503 - 1472 */
+       };
+
+       base = le32_to_cpu(il->card_alive.log_event_table_ptr);
+       if (!il3945_hw_valid_rtc_data_addr(base)) {
+               IL_ERR("Invalid event log pointer 0x%08X\n", base);
+               return;
+       }
+
+       disable_ptr = il_read_targ_mem(il, base + (4 * sizeof(u32)));
+       array_size = il_read_targ_mem(il, base + (5 * sizeof(u32)));
+
+       if (IL_EVT_DISABLE && array_size == IL_EVT_DISABLE_SIZE) {
+               D_INFO("Disabling selected uCode log events at 0x%x\n",
+                      disable_ptr);
+               for (i = 0; i < IL_EVT_DISABLE_SIZE; i++)
+                       il_write_targ_mem(il, disable_ptr + (i * sizeof(u32)),
+                                         evt_disable[i]);
+
+       } else {
+               D_INFO("Selected uCode log events may be disabled\n");
+               D_INFO("  by writing \"1\"s into disable bitmap\n");
+               D_INFO("  in SRAM at 0x%x, size %d u32s\n", disable_ptr,
+                      array_size);
+       }
+
+}
+
+static int
+il3945_hwrate_to_plcp_idx(u8 plcp)
+{
+       int idx;
+
+       for (idx = 0; idx < RATE_COUNT_3945; idx++)
+               if (il3945_rates[idx].plcp == plcp)
+                       return idx;
+       return -1;
+}
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+#define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x
+
+static const char *
+il3945_get_tx_fail_reason(u32 status)
+{
+       switch (status & TX_STATUS_MSK) {
+       case TX_3945_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";
+}
+#else
+static inline const char *
+il3945_get_tx_fail_reason(u32 status)
+{
+       return "";
+}
+#endif
+
+/*
+ * get ieee prev rate from rate scale table.
+ * for A and B mode we need to overright prev
+ * value
+ */
+int
+il3945_rs_next_rate(struct il_priv *il, int rate)
+{
+       int next_rate = il3945_get_prev_ieee_rate(rate);
+
+       switch (il->band) {
+       case IEEE80211_BAND_5GHZ:
+               if (rate == RATE_12M_IDX)
+                       next_rate = RATE_9M_IDX;
+               else if (rate == RATE_6M_IDX)
+                       next_rate = RATE_6M_IDX;
+               break;
+       case IEEE80211_BAND_2GHZ:
+               if (!(il->_3945.sta_supp_rates & IL_OFDM_RATES_MASK) &&
+                   il_is_associated(il)) {
+                       if (rate == RATE_11M_IDX)
+                               next_rate = RATE_5M_IDX;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return next_rate;
+}
+
+/**
+ * il3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
+ *
+ * When FW advances 'R' idx, all entries between old and new 'R' idx
+ * need to be reclaimed. As result, some free space forms. If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+static void
+il3945_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx)
+{
+       struct il_tx_queue *txq = &il->txq[txq_id];
+       struct il_queue *q = &txq->q;
+       struct il_tx_info *tx_info;
+
+       BUG_ON(txq_id == IL39_CMD_QUEUE_NUM);
+
+       for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+            q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+               tx_info = &txq->txb[txq->q.read_ptr];
+               ieee80211_tx_status_irqsafe(il->hw, tx_info->skb);
+               tx_info->skb = NULL;
+               il->cfg->ops->lib->txq_free_tfd(il, txq);
+       }
+
+       if (il_queue_space(q) > q->low_mark && txq_id >= 0 &&
+           txq_id != IL39_CMD_QUEUE_NUM && il->mac80211_registered)
+               il_wake_queue(il, txq);
+}
+
+/**
+ * il3945_hdl_tx - Handle Tx response
+ */
+static void
+il3945_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+       int txq_id = SEQ_TO_QUEUE(sequence);
+       int idx = SEQ_TO_IDX(sequence);
+       struct il_tx_queue *txq = &il->txq[txq_id];
+       struct ieee80211_tx_info *info;
+       struct il3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+       u32 status = le32_to_cpu(tx_resp->status);
+       int rate_idx;
+       int fail;
+
+       if (idx >= txq->q.n_bd || il_queue_used(&txq->q, idx) == 0) {
+               IL_ERR("Read idx for DMA queue txq_id (%d) idx %d "
+                      "is out of range [0-%d] %d %d\n", txq_id, idx,
+                      txq->q.n_bd, txq->q.write_ptr, txq->q.read_ptr);
+               return;
+       }
+
+       txq->time_stamp = jiffies;
+       info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
+       ieee80211_tx_info_clear_status(info);
+
+       /* Fill the MRR chain with some info about on-chip retransmissions */
+       rate_idx = il3945_hwrate_to_plcp_idx(tx_resp->rate);
+       if (info->band == IEEE80211_BAND_5GHZ)
+               rate_idx -= IL_FIRST_OFDM_RATE;
+
+       fail = tx_resp->failure_frame;
+
+       info->status.rates[0].idx = rate_idx;
+       info->status.rates[0].count = fail + 1; /* add final attempt */
+
+       /* tx_status->rts_retry_count = tx_resp->failure_rts; */
+       info->flags |=
+           ((status & TX_STATUS_MSK) ==
+            TX_STATUS_SUCCESS) ? IEEE80211_TX_STAT_ACK : 0;
+
+       D_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", txq_id,
+            il3945_get_tx_fail_reason(status), status, tx_resp->rate,
+            tx_resp->failure_frame);
+
+       D_TX_REPLY("Tx queue reclaim %d\n", idx);
+       il3945_tx_queue_reclaim(il, txq_id, idx);
+
+       if (status & TX_ABORT_REQUIRED_MSK)
+               IL_ERR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
+}
+
+/*****************************************************************************
+ *
+ * Intel PRO/Wireless 3945ABG/BG Network Connection
+ *
+ *  RX handler implementations
+ *
+ *****************************************************************************/
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+static void
+il3945_accumulative_stats(struct il_priv *il, __le32 * stats)
+{
+       int i;
+       __le32 *prev_stats;
+       u32 *accum_stats;
+       u32 *delta, *max_delta;
+
+       prev_stats = (__le32 *) &il->_3945.stats;
+       accum_stats = (u32 *) &il->_3945.accum_stats;
+       delta = (u32 *) &il->_3945.delta_stats;
+       max_delta = (u32 *) &il->_3945.max_delta;
+
+       for (i = sizeof(__le32); i < sizeof(struct il3945_notif_stats);
+            i +=
+            sizeof(__le32), stats++, prev_stats++, delta++, max_delta++,
+            accum_stats++) {
+               if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
+                       *delta =
+                           (le32_to_cpu(*stats) - le32_to_cpu(*prev_stats));
+                       *accum_stats += *delta;
+                       if (*delta > *max_delta)
+                               *max_delta = *delta;
+               }
+       }
+
+       /* reset accumulative stats for "no-counter" type stats */
+       il->_3945.accum_stats.general.temperature =
+           il->_3945.stats.general.temperature;
+       il->_3945.accum_stats.general.ttl_timestamp =
+           il->_3945.stats.general.ttl_timestamp;
+}
+#endif
+
+void
+il3945_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+
+       D_RX("Statistics notification received (%d vs %d).\n",
+            (int)sizeof(struct il3945_notif_stats),
+            le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK);
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+       il3945_accumulative_stats(il, (__le32 *) &pkt->u.raw);
+#endif
+
+       memcpy(&il->_3945.stats, pkt->u.raw, sizeof(il->_3945.stats));
+}
+
+void
+il3945_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       __le32 *flag = (__le32 *) &pkt->u.raw;
+
+       if (le32_to_cpu(*flag) & UCODE_STATS_CLEAR_MSK) {
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+               memset(&il->_3945.accum_stats, 0,
+                      sizeof(struct il3945_notif_stats));
+               memset(&il->_3945.delta_stats, 0,
+                      sizeof(struct il3945_notif_stats));
+               memset(&il->_3945.max_delta, 0,
+                      sizeof(struct il3945_notif_stats));
+#endif
+               D_RX("Statistics have been cleared\n");
+       }
+       il3945_hdl_stats(il, rxb);
+}
+
+/******************************************************************************
+ *
+ * Misc. internal state and helper functions
+ *
+ ******************************************************************************/
+
+/* This is necessary only for a number of stats, see the caller. */
+static int
+il3945_is_network_packet(struct il_priv *il, struct ieee80211_hdr *header)
+{
+       /* Filter incoming packets to determine if they are targeted toward
+        * this network, discarding packets coming from ourselves */
+       switch (il->iw_mode) {
+       case NL80211_IFTYPE_ADHOC:      /* Header: Dest. | Source    | BSSID */
+               /* packets to our IBSS update information */
+               return !compare_ether_addr(header->addr3, il->bssid);
+       case NL80211_IFTYPE_STATION:    /* Header: Dest. | AP{BSSID} | Source */
+               /* packets to our IBSS update information */
+               return !compare_ether_addr(header->addr2, il->bssid);
+       default:
+               return 1;
+       }
+}
+
+static void
+il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
+                              struct ieee80211_rx_status *stats)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
+       struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
+       struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
+       u16 len = le16_to_cpu(rx_hdr->len);
+       struct sk_buff *skb;
+       __le16 fc = hdr->frame_control;
+
+       /* We received data from the HW, so stop the watchdog */
+       if (unlikely
+           (len + IL39_RX_FRAME_SIZE >
+            PAGE_SIZE << il->hw_params.rx_page_order)) {
+               D_DROP("Corruption detected!\n");
+               return;
+       }
+
+       /* We only process data packets if the interface is open */
+       if (unlikely(!il->is_open)) {
+               D_DROP("Dropping packet while interface is not open.\n");
+               return;
+       }
+
+       skb = dev_alloc_skb(128);
+       if (!skb) {
+               IL_ERR("dev_alloc_skb failed\n");
+               return;
+       }
+
+       if (!il3945_mod_params.sw_crypto)
+               il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb),
+                                     le32_to_cpu(rx_end->status), stats);
+
+       skb_add_rx_frag(skb, 0, rxb->page,
+                       (void *)rx_hdr->payload - (void *)pkt, len);
+
+       il_update_stats(il, false, fc, len);
+       memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
+
+       ieee80211_rx(il->hw, skb);
+       il->alloc_rxb_page--;
+       rxb->page = NULL;
+}
+
+#define IL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+
+static void
+il3945_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct ieee80211_hdr *header;
+       struct ieee80211_rx_status rx_status;
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il3945_rx_frame_stats *rx_stats = IL_RX_STATS(pkt);
+       struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
+       struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
+       u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg);
+       u16 rx_stats_noise_diff __maybe_unused =
+           le16_to_cpu(rx_stats->noise_diff);
+       u8 network_packet;
+
+       rx_status.flag = 0;
+       rx_status.mactime = le64_to_cpu(rx_end->timestamp);
+       rx_status.band =
+           (rx_hdr->
+            phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ :
+           IEEE80211_BAND_5GHZ;
+       rx_status.freq =
+           ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel),
+                                          rx_status.band);
+
+       rx_status.rate_idx = il3945_hwrate_to_plcp_idx(rx_hdr->rate);
+       if (rx_status.band == IEEE80211_BAND_5GHZ)
+               rx_status.rate_idx -= IL_FIRST_OFDM_RATE;
+
+       rx_status.antenna =
+           (le16_to_cpu(rx_hdr->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) >>
+           4;
+
+       /* set the preamble flag if appropriate */
+       if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+               rx_status.flag |= RX_FLAG_SHORTPRE;
+
+       if ((unlikely(rx_stats->phy_count > 20))) {
+               D_DROP("dsp size out of range [0,20]: %d/n",
+                      rx_stats->phy_count);
+               return;
+       }
+
+       if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR) ||
+           !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+               D_RX("Bad CRC or FIFO: 0x%08X.\n", rx_end->status);
+               return;
+       }
+
+       /* Convert 3945's rssi indicator to dBm */
+       rx_status.signal = rx_stats->rssi - IL39_RSSI_OFFSET;
+
+       D_STATS("Rssi %d sig_avg %d noise_diff %d\n", rx_status.signal,
+               rx_stats_sig_avg, rx_stats_noise_diff);
+
+       header = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
+
+       network_packet = il3945_is_network_packet(il, header);
+
+       D_STATS("[%c] %d RSSI:%d Signal:%u, Rate:%u\n",
+               network_packet ? '*' : ' ', le16_to_cpu(rx_hdr->channel),
+               rx_status.signal, rx_status.signal, rx_status.rate_idx);
+
+       il_dbg_log_rx_data_frame(il, le16_to_cpu(rx_hdr->len), header);
+
+       if (network_packet) {
+               il->_3945.last_beacon_time =
+                   le32_to_cpu(rx_end->beacon_timestamp);
+               il->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
+               il->_3945.last_rx_rssi = rx_status.signal;
+       }
+
+       il3945_pass_packet_to_mac80211(il, rxb, &rx_status);
+}
+
+int
+il3945_hw_txq_attach_buf_to_tfd(struct il_priv *il, struct il_tx_queue *txq,
+                               dma_addr_t addr, u16 len, u8 reset, u8 pad)
+{
+       int count;
+       struct il_queue *q;
+       struct il3945_tfd *tfd, *tfd_tmp;
+
+       q = &txq->q;
+       tfd_tmp = (struct il3945_tfd *)txq->tfds;
+       tfd = &tfd_tmp[q->write_ptr];
+
+       if (reset)
+               memset(tfd, 0, sizeof(*tfd));
+
+       count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
+
+       if (count >= NUM_TFD_CHUNKS || count < 0) {
+               IL_ERR("Error can not send more than %d chunks\n",
+                      NUM_TFD_CHUNKS);
+               return -EINVAL;
+       }
+
+       tfd->tbs[count].addr = cpu_to_le32(addr);
+       tfd->tbs[count].len = cpu_to_le32(len);
+
+       count++;
+
+       tfd->control_flags =
+           cpu_to_le32(TFD_CTL_COUNT_SET(count) | TFD_CTL_PAD_SET(pad));
+
+       return 0;
+}
+
+/**
+ * il3945_hw_txq_free_tfd - Free one TFD, those at idx [txq->q.read_ptr]
+ *
+ * Does NOT advance any idxes
+ */
+void
+il3945_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq)
+{
+       struct il3945_tfd *tfd_tmp = (struct il3945_tfd *)txq->tfds;
+       int idx = txq->q.read_ptr;
+       struct il3945_tfd *tfd = &tfd_tmp[idx];
+       struct pci_dev *dev = il->pci_dev;
+       int i;
+       int counter;
+
+       /* sanity check */
+       counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
+       if (counter > NUM_TFD_CHUNKS) {
+               IL_ERR("Too many chunks: %i\n", counter);
+               /* @todo issue fatal error, it is quite serious situation */
+               return;
+       }
+
+       /* Unmap tx_cmd */
+       if (counter)
+               pci_unmap_single(dev, dma_unmap_addr(&txq->meta[idx], mapping),
+                                dma_unmap_len(&txq->meta[idx], len),
+                                PCI_DMA_TODEVICE);
+
+       /* unmap chunks if any */
+
+       for (i = 1; i < counter; i++)
+               pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr),
+                                le32_to_cpu(tfd->tbs[i].len),
+                                PCI_DMA_TODEVICE);
+
+       /* free SKB */
+       if (txq->txb) {
+               struct sk_buff *skb;
+
+               skb = txq->txb[txq->q.read_ptr].skb;
+
+               /* can be called from irqs-disabled context */
+               if (skb) {
+                       dev_kfree_skb_any(skb);
+                       txq->txb[txq->q.read_ptr].skb = NULL;
+               }
+       }
+}
+
+/**
+ * il3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
+ *
+*/
+void
+il3945_hw_build_tx_cmd_rate(struct il_priv *il, struct il_device_cmd *cmd,
+                           struct ieee80211_tx_info *info,
+                           struct ieee80211_hdr *hdr, int sta_id, int tx_id)
+{
+       u16 hw_value = ieee80211_get_tx_rate(il->hw, info)->hw_value;
+       u16 rate_idx = min(hw_value & 0xffff, RATE_COUNT_3945);
+       u16 rate_mask;
+       int rate;
+       u8 rts_retry_limit;
+       u8 data_retry_limit;
+       __le32 tx_flags;
+       __le16 fc = hdr->frame_control;
+       struct il3945_tx_cmd *tx_cmd = (struct il3945_tx_cmd *)cmd->cmd.payload;
+
+       rate = il3945_rates[rate_idx].plcp;
+       tx_flags = tx_cmd->tx_flags;
+
+       /* We need to figure out how to get the sta->supp_rates while
+        * in this running context */
+       rate_mask = RATES_MASK_3945;
+
+       /* Set retry limit on DATA packets and Probe Responses */
+       if (ieee80211_is_probe_resp(fc))
+               data_retry_limit = 3;
+       else
+               data_retry_limit = IL_DEFAULT_TX_RETRY;
+       tx_cmd->data_retry_limit = data_retry_limit;
+
+       if (tx_id >= IL39_CMD_QUEUE_NUM)
+               rts_retry_limit = 3;
+       else
+               rts_retry_limit = 7;
+
+       if (data_retry_limit < rts_retry_limit)
+               rts_retry_limit = data_retry_limit;
+       tx_cmd->rts_retry_limit = rts_retry_limit;
+
+       tx_cmd->rate = rate;
+       tx_cmd->tx_flags = tx_flags;
+
+       /* OFDM */
+       tx_cmd->supp_rates[0] =
+           ((rate_mask & IL_OFDM_RATES_MASK) >> IL_FIRST_OFDM_RATE) & 0xFF;
+
+       /* CCK */
+       tx_cmd->supp_rates[1] = (rate_mask & 0xF);
+
+       D_RATE("Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
+              "cck/ofdm mask: 0x%x/0x%x\n", sta_id, tx_cmd->rate,
+              le32_to_cpu(tx_cmd->tx_flags), tx_cmd->supp_rates[1],
+              tx_cmd->supp_rates[0]);
+}
+
+static u8
+il3945_sync_sta(struct il_priv *il, int sta_id, u16 tx_rate)
+{
+       unsigned long flags_spin;
+       struct il_station_entry *station;
+
+       if (sta_id == IL_INVALID_STATION)
+               return IL_INVALID_STATION;
+
+       spin_lock_irqsave(&il->sta_lock, flags_spin);
+       station = &il->stations[sta_id];
+
+       station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
+       station->sta.rate_n_flags = cpu_to_le16(tx_rate);
+       station->sta.mode = STA_CONTROL_MODIFY_MSK;
+       il_send_add_sta(il, &station->sta, CMD_ASYNC);
+       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+
+       D_RATE("SCALE sync station %d to rate %d\n", sta_id, tx_rate);
+       return sta_id;
+}
+
+static void
+il3945_set_pwr_vmain(struct il_priv *il)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do
+
+               if (pci_pme_capable(il->pci_dev, PCI_D3cold)) {
+                       il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
+                                       APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+                                       ~APMG_PS_CTRL_MSK_PWR_SRC);
+
+                       _il_poll_bit(il, CSR_GPIO_IN,
+                                    CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
+                                    CSR_GPIO_IN_BIT_AUX_POWER, 5000);
+               }
+ */
+
+       il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
+                             APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+                             ~APMG_PS_CTRL_MSK_PWR_SRC);
+
+       _il_poll_bit(il, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
+                    CSR_GPIO_IN_BIT_AUX_POWER, 5000);
+}
+
+static int
+il3945_rx_init(struct il_priv *il, struct il_rx_queue *rxq)
+{
+       il_wr(il, FH39_RCSR_RBD_BASE(0), rxq->bd_dma);
+       il_wr(il, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma);
+       il_wr(il, FH39_RCSR_WPTR(0), 0);
+       il_wr(il, FH39_RCSR_CONFIG(0),
+             FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
+             FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
+             FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
+             FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 | (RX_QUEUE_SIZE_LOG
+                                                              <<
+                                                              FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE)
+             | FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST | (1 <<
+                                                                FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH)
+             | FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
+
+       /* fake read to flush all prev I/O */
+       il_rd(il, FH39_RSSR_CTRL);
+
+       return 0;
+}
+
+static int
+il3945_tx_reset(struct il_priv *il)
+{
+
+       /* bypass mode */
+       il_wr_prph(il, ALM_SCD_MODE_REG, 0x2);
+
+       /* RA 0 is active */
+       il_wr_prph(il, ALM_SCD_ARASTAT_REG, 0x01);
+
+       /* all 6 fifo are active */
+       il_wr_prph(il, ALM_SCD_TXFACT_REG, 0x3f);
+
+       il_wr_prph(il, ALM_SCD_SBYP_MODE_1_REG, 0x010000);
+       il_wr_prph(il, ALM_SCD_SBYP_MODE_2_REG, 0x030002);
+       il_wr_prph(il, ALM_SCD_TXF4MF_REG, 0x000004);
+       il_wr_prph(il, ALM_SCD_TXF5MF_REG, 0x000005);
+
+       il_wr(il, FH39_TSSR_CBB_BASE, il->_3945.shared_phys);
+
+       il_wr(il, FH39_TSSR_MSG_CONFIG,
+             FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
+             FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
+             FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
+             FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON |
+             FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON |
+             FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
+             FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
+
+       return 0;
+}
+
+/**
+ * il3945_txq_ctx_reset - Reset TX queue context
+ *
+ * Destroys all DMA structures and initialize them again
+ */
+static int
+il3945_txq_ctx_reset(struct il_priv *il)
+{
+       int rc;
+       int txq_id, slots_num;
+
+       il3945_hw_txq_ctx_free(il);
+
+       /* allocate tx queue structure */
+       rc = il_alloc_txq_mem(il);
+       if (rc)
+               return rc;
+
+       /* Tx CMD queue */
+       rc = il3945_tx_reset(il);
+       if (rc)
+               goto error;
+
+       /* Tx queue(s) */
+       for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
+               slots_num =
+                   (txq_id ==
+                    IL39_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+               rc = il_tx_queue_init(il, &il->txq[txq_id], slots_num, txq_id);
+               if (rc) {
+                       IL_ERR("Tx %d queue init failed\n", txq_id);
+                       goto error;
+               }
+       }
+
+       return rc;
+
+error:
+       il3945_hw_txq_ctx_free(il);
+       return rc;
+}
+
+/*
+ * Start up 3945's basic functionality after it has been reset
+ * (e.g. after platform boot, or shutdown via il_apm_stop())
+ * NOTE:  This does not load uCode nor start the embedded processor
+ */
+static int
+il3945_apm_init(struct il_priv *il)
+{
+       int ret = il_apm_init(il);
+
+       /* Clear APMG (NIC's internal power management) interrupts */
+       il_wr_prph(il, APMG_RTC_INT_MSK_REG, 0x0);
+       il_wr_prph(il, APMG_RTC_INT_STT_REG, 0xFFFFFFFF);
+
+       /* Reset radio chip */
+       il_set_bits_prph(il, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
+       udelay(5);
+       il_clear_bits_prph(il, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
+
+       return ret;
+}
+
+static void
+il3945_nic_config(struct il_priv *il)
+{
+       struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
+       unsigned long flags;
+       u8 rev_id = il->pci_dev->revision;
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       /* Determine HW type */
+       D_INFO("HW Revision ID = 0x%X\n", rev_id);
+
+       if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
+               D_INFO("RTP type\n");
+       else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
+               D_INFO("3945 RADIO-MB type\n");
+               il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                          CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
+       } else {
+               D_INFO("3945 RADIO-MM type\n");
+               il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                          CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
+       }
+
+       if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) {
+               D_INFO("SKU OP mode is mrc\n");
+               il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                          CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
+       } else
+               D_INFO("SKU OP mode is basic\n");
+
+       if ((eeprom->board_revision & 0xF0) == 0xD0) {
+               D_INFO("3945ABG revision is 0x%X\n", eeprom->board_revision);
+               il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                          CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
+       } else {
+               D_INFO("3945ABG revision is 0x%X\n", eeprom->board_revision);
+               il_clear_bit(il, CSR_HW_IF_CONFIG_REG,
+                            CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
+       }
+
+       if (eeprom->almgor_m_version <= 1) {
+               il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                          CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
+               D_INFO("Card M type A version is 0x%X\n",
+                      eeprom->almgor_m_version);
+       } else {
+               D_INFO("Card M type B version is 0x%X\n",
+                      eeprom->almgor_m_version);
+               il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                          CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
+       }
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE)
+               D_RF_KILL("SW RF KILL supported in EEPROM.\n");
+
+       if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE)
+               D_RF_KILL("HW RF KILL supported in EEPROM.\n");
+}
+
+int
+il3945_hw_nic_init(struct il_priv *il)
+{
+       int rc;
+       unsigned long flags;
+       struct il_rx_queue *rxq = &il->rxq;
+
+       spin_lock_irqsave(&il->lock, flags);
+       il->cfg->ops->lib->apm_ops.init(il);
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       il3945_set_pwr_vmain(il);
+
+       il->cfg->ops->lib->apm_ops.config(il);
+
+       /* Allocate the RX queue, or reset if it is already allocated */
+       if (!rxq->bd) {
+               rc = il_rx_queue_alloc(il);
+               if (rc) {
+                       IL_ERR("Unable to initialize Rx queue\n");
+                       return -ENOMEM;
+               }
+       } else
+               il3945_rx_queue_reset(il, rxq);
+
+       il3945_rx_replenish(il);
+
+       il3945_rx_init(il, rxq);
+
+       /* Look at using this instead:
+          rxq->need_update = 1;
+          il_rx_queue_update_write_ptr(il, rxq);
+        */
+
+       il_wr(il, FH39_RCSR_WPTR(0), rxq->write & ~7);
+
+       rc = il3945_txq_ctx_reset(il);
+       if (rc)
+               return rc;
+
+       set_bit(S_INIT, &il->status);
+
+       return 0;
+}
+
+/**
+ * il3945_hw_txq_ctx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void
+il3945_hw_txq_ctx_free(struct il_priv *il)
+{
+       int txq_id;
+
+       /* Tx queues */
+       if (il->txq)
+               for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
+                       if (txq_id == IL39_CMD_QUEUE_NUM)
+                               il_cmd_queue_free(il);
+                       else
+                               il_tx_queue_free(il, txq_id);
+
+       /* free tx queue structure */
+       il_txq_mem(il);
+}
+
+void
+il3945_hw_txq_ctx_stop(struct il_priv *il)
+{
+       int txq_id;
+
+       /* stop SCD */
+       il_wr_prph(il, ALM_SCD_MODE_REG, 0);
+       il_wr_prph(il, ALM_SCD_TXFACT_REG, 0);
+
+       /* reset TFD queues */
+       for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
+               il_wr(il, FH39_TCSR_CONFIG(txq_id), 0x0);
+               il_poll_bit(il, FH39_TSSR_TX_STATUS,
+                           FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
+                           1000);
+       }
+
+       il3945_hw_txq_ctx_free(il);
+}
+
+/**
+ * il3945_hw_reg_adjust_power_by_temp
+ * return idx delta into power gain settings table
+*/
+static int
+il3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
+{
+       return (new_reading - old_reading) * (-11) / 100;
+}
+
+/**
+ * il3945_hw_reg_temp_out_of_range - Keep temperature in sane range
+ */
+static inline int
+il3945_hw_reg_temp_out_of_range(int temperature)
+{
+       return (temperature < -260 || temperature > 25) ? 1 : 0;
+}
+
+int
+il3945_hw_get_temperature(struct il_priv *il)
+{
+       return _il_rd(il, CSR_UCODE_DRV_GP2);
+}
+
+/**
+ * il3945_hw_reg_txpower_get_temperature
+ * get the current temperature by reading from NIC
+*/
+static int
+il3945_hw_reg_txpower_get_temperature(struct il_priv *il)
+{
+       struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
+       int temperature;
+
+       temperature = il3945_hw_get_temperature(il);
+
+       /* driver's okay range is -260 to +25.
+        *   human readable okay range is 0 to +285 */
+       D_INFO("Temperature: %d\n", temperature + IL_TEMP_CONVERT);
+
+       /* handle insane temp reading */
+       if (il3945_hw_reg_temp_out_of_range(temperature)) {
+               IL_ERR("Error bad temperature value  %d\n", temperature);
+
+               /* if really really hot(?),
+                *   substitute the 3rd band/group's temp measured at factory */
+               if (il->last_temperature > 100)
+                       temperature = eeprom->groups[2].temperature;
+               else            /* else use most recent "sane" value from driver */
+                       temperature = il->last_temperature;
+       }
+
+       return temperature;     /* raw, not "human readable" */
+}
+
+/* Adjust Txpower only if temperature variance is greater than threshold.
+ *
+ * Both are lower than older versions' 9 degrees */
+#define IL_TEMPERATURE_LIMIT_TIMER   6
+
+/**
+ * il3945_is_temp_calib_needed - determines if new calibration is needed
+ *
+ * records new temperature in tx_mgr->temperature.
+ * replaces tx_mgr->last_temperature *only* if calib needed
+ *    (assumes caller will actually do the calibration!). */
+static int
+il3945_is_temp_calib_needed(struct il_priv *il)
+{
+       int temp_diff;
+
+       il->temperature = il3945_hw_reg_txpower_get_temperature(il);
+       temp_diff = il->temperature - il->last_temperature;
+
+       /* get absolute value */
+       if (temp_diff < 0) {
+               D_POWER("Getting cooler, delta %d,\n", temp_diff);
+               temp_diff = -temp_diff;
+       } else if (temp_diff == 0)
+               D_POWER("Same temp,\n");
+       else
+               D_POWER("Getting warmer, delta %d,\n", temp_diff);
+
+       /* if we don't need calibration, *don't* update last_temperature */
+       if (temp_diff < IL_TEMPERATURE_LIMIT_TIMER) {
+               D_POWER("Timed thermal calib not needed\n");
+               return 0;
+       }
+
+       D_POWER("Timed thermal calib needed\n");
+
+       /* assume that caller will actually do calib ...
+        *   update the "last temperature" value */
+       il->last_temperature = il->temperature;
+       return 1;
+}
+
+#define IL_MAX_GAIN_ENTRIES 78
+#define IL_CCK_FROM_OFDM_POWER_DIFF  -5
+#define IL_CCK_FROM_OFDM_IDX_DIFF (10)
+
+/* radio and DSP power table, each step is 1/2 dB.
+ * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */
+static struct il3945_tx_power power_gain_table[2][IL_MAX_GAIN_ENTRIES] = {
+       {
+        {251, 127},            /* 2.4 GHz, highest power */
+        {251, 127},
+        {251, 127},
+        {251, 127},
+        {251, 125},
+        {251, 110},
+        {251, 105},
+        {251, 98},
+        {187, 125},
+        {187, 115},
+        {187, 108},
+        {187, 99},
+        {243, 119},
+        {243, 111},
+        {243, 105},
+        {243, 97},
+        {243, 92},
+        {211, 106},
+        {211, 100},
+        {179, 120},
+        {179, 113},
+        {179, 107},
+        {147, 125},
+        {147, 119},
+        {147, 112},
+        {147, 106},
+        {147, 101},
+        {147, 97},
+        {147, 91},
+        {115, 107},
+        {235, 121},
+        {235, 115},
+        {235, 109},
+        {203, 127},
+        {203, 121},
+        {203, 115},
+        {203, 108},
+        {203, 102},
+        {203, 96},
+        {203, 92},
+        {171, 110},
+        {171, 104},
+        {171, 98},
+        {139, 116},
+        {227, 125},
+        {227, 119},
+        {227, 113},
+        {227, 107},
+        {227, 101},
+        {227, 96},
+        {195, 113},
+        {195, 106},
+        {195, 102},
+        {195, 95},
+        {163, 113},
+        {163, 106},
+        {163, 102},
+        {163, 95},
+        {131, 113},
+        {131, 106},
+        {131, 102},
+        {131, 95},
+        {99, 113},
+        {99, 106},
+        {99, 102},
+        {99, 95},
+        {67, 113},
+        {67, 106},
+        {67, 102},
+        {67, 95},
+        {35, 113},
+        {35, 106},
+        {35, 102},
+        {35, 95},
+        {3, 113},
+        {3, 106},
+        {3, 102},
+        {3, 95}                /* 2.4 GHz, lowest power */
+       },
+       {
+        {251, 127},            /* 5.x GHz, highest power */
+        {251, 120},
+        {251, 114},
+        {219, 119},
+        {219, 101},
+        {187, 113},
+        {187, 102},
+        {155, 114},
+        {155, 103},
+        {123, 117},
+        {123, 107},
+        {123, 99},
+        {123, 92},
+        {91, 108},
+        {59, 125},
+        {59, 118},
+        {59, 109},
+        {59, 102},
+        {59, 96},
+        {59, 90},
+        {27, 104},
+        {27, 98},
+        {27, 92},
+        {115, 118},
+        {115, 111},
+        {115, 104},
+        {83, 126},
+        {83, 121},
+        {83, 113},
+        {83, 105},
+        {83, 99},
+        {51, 118},
+        {51, 111},
+        {51, 104},
+        {51, 98},
+        {19, 116},
+        {19, 109},
+        {19, 102},
+        {19, 98},
+        {19, 93},
+        {171, 113},
+        {171, 107},
+        {171, 99},
+        {139, 120},
+        {139, 113},
+        {139, 107},
+        {139, 99},
+        {107, 120},
+        {107, 113},
+        {107, 107},
+        {107, 99},
+        {75, 120},
+        {75, 113},
+        {75, 107},
+        {75, 99},
+        {43, 120},
+        {43, 113},
+        {43, 107},
+        {43, 99},
+        {11, 120},
+        {11, 113},
+        {11, 107},
+        {11, 99},
+        {131, 107},
+        {131, 99},
+        {99, 120},
+        {99, 113},
+        {99, 107},
+        {99, 99},
+        {67, 120},
+        {67, 113},
+        {67, 107},
+        {67, 99},
+        {35, 120},
+        {35, 113},
+        {35, 107},
+        {35, 99},
+        {3, 120}               /* 5.x GHz, lowest power */
+       }
+};
+
+static inline u8
+il3945_hw_reg_fix_power_idx(int idx)
+{
+       if (idx < 0)
+               return 0;
+       if (idx >= IL_MAX_GAIN_ENTRIES)
+               return IL_MAX_GAIN_ENTRIES - 1;
+       return (u8) idx;
+}
+
+/* Kick off thermal recalibration check every 60 seconds */
+#define REG_RECALIB_PERIOD (60)
+
+/**
+ * il3945_hw_reg_set_scan_power - Set Tx power for scan probe requests
+ *
+ * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK)
+ * or 6 Mbit (OFDM) rates.
+ */
+static void
+il3945_hw_reg_set_scan_power(struct il_priv *il, u32 scan_tbl_idx, s32 rate_idx,
+                            const s8 *clip_pwrs,
+                            struct il_channel_info *ch_info, int band_idx)
+{
+       struct il3945_scan_power_info *scan_power_info;
+       s8 power;
+       u8 power_idx;
+
+       scan_power_info = &ch_info->scan_pwr_info[scan_tbl_idx];
+
+       /* use this channel group's 6Mbit clipping/saturation pwr,
+        *   but cap at regulatory scan power restriction (set during init
+        *   based on eeprom channel data) for this channel.  */
+       power = min(ch_info->scan_power, clip_pwrs[RATE_6M_IDX_TBL]);
+
+       power = min(power, il->tx_power_user_lmt);
+       scan_power_info->requested_power = power;
+
+       /* find difference between new scan *power* and current "normal"
+        *   Tx *power* for 6Mb.  Use this difference (x2) to adjust the
+        *   current "normal" temperature-compensated Tx power *idx* for
+        *   this rate (1Mb or 6Mb) to yield new temp-compensated scan power
+        *   *idx*. */
+       power_idx =
+           ch_info->power_info[rate_idx].power_table_idx - (power -
+                                                            ch_info->
+                                                            power_info
+                                                            [RATE_6M_IDX_TBL].
+                                                            requested_power) *
+           2;
+
+       /* store reference idx that we use when adjusting *all* scan
+        *   powers.  So we can accommodate user (all channel) or spectrum
+        *   management (single channel) power changes "between" temperature
+        *   feedback compensation procedures.
+        * don't force fit this reference idx into gain table; it may be a
+        *   negative number.  This will help avoid errors when we're at
+        *   the lower bounds (highest gains, for warmest temperatures)
+        *   of the table. */
+
+       /* don't exceed table bounds for "real" setting */
+       power_idx = il3945_hw_reg_fix_power_idx(power_idx);
+
+       scan_power_info->power_table_idx = power_idx;
+       scan_power_info->tpc.tx_gain =
+           power_gain_table[band_idx][power_idx].tx_gain;
+       scan_power_info->tpc.dsp_atten =
+           power_gain_table[band_idx][power_idx].dsp_atten;
+}
+
+/**
+ * il3945_send_tx_power - fill in Tx Power command with gain settings
+ *
+ * Configures power settings for all rates for the current channel,
+ * using values from channel info struct, and send to NIC
+ */
+static int
+il3945_send_tx_power(struct il_priv *il)
+{
+       int rate_idx, i;
+       const struct il_channel_info *ch_info = NULL;
+       struct il3945_txpowertable_cmd txpower = {
+               .channel = il->ctx.active.channel,
+       };
+       u16 chan;
+
+       if (WARN_ONCE
+           (test_bit(S_SCAN_HW, &il->status),
+            "TX Power requested while scanning!\n"))
+               return -EAGAIN;
+
+       chan = le16_to_cpu(il->ctx.active.channel);
+
+       txpower.band = (il->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
+       ch_info = il_get_channel_info(il, il->band, chan);
+       if (!ch_info) {
+               IL_ERR("Failed to get channel info for channel %d [%d]\n", chan,
+                      il->band);
+               return -EINVAL;
+       }
+
+       if (!il_is_channel_valid(ch_info)) {
+               D_POWER("Not calling TX_PWR_TBL_CMD on " "non-Tx channel.\n");
+               return 0;
+       }
+
+       /* fill cmd with power settings for all rates for current channel */
+       /* Fill OFDM rate */
+       for (rate_idx = IL_FIRST_OFDM_RATE, i = 0;
+            rate_idx <= IL39_LAST_OFDM_RATE; rate_idx++, i++) {
+
+               txpower.power[i].tpc = ch_info->power_info[i].tpc;
+               txpower.power[i].rate = il3945_rates[rate_idx].plcp;
+
+               D_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
+                       le16_to_cpu(txpower.channel), txpower.band,
+                       txpower.power[i].tpc.tx_gain,
+                       txpower.power[i].tpc.dsp_atten, txpower.power[i].rate);
+       }
+       /* Fill CCK rates */
+       for (rate_idx = IL_FIRST_CCK_RATE; rate_idx <= IL_LAST_CCK_RATE;
+            rate_idx++, i++) {
+               txpower.power[i].tpc = ch_info->power_info[i].tpc;
+               txpower.power[i].rate = il3945_rates[rate_idx].plcp;
+
+               D_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
+                       le16_to_cpu(txpower.channel), txpower.band,
+                       txpower.power[i].tpc.tx_gain,
+                       txpower.power[i].tpc.dsp_atten, txpower.power[i].rate);
+       }
+
+       return il_send_cmd_pdu(il, C_TX_PWR_TBL,
+                              sizeof(struct il3945_txpowertable_cmd),
+                              &txpower);
+
+}
+
+/**
+ * il3945_hw_reg_set_new_power - Configures power tables at new levels
+ * @ch_info: Channel to update.  Uses power_info.requested_power.
+ *
+ * Replace requested_power and base_power_idx ch_info fields for
+ * one channel.
+ *
+ * Called if user or spectrum management changes power preferences.
+ * Takes into account h/w and modulation limitations (clip power).
+ *
+ * This does *not* send anything to NIC, just sets up ch_info for one channel.
+ *
+ * NOTE: reg_compensate_for_temperature_dif() *must* be run after this to
+ *      properly fill out the scan powers, and actual h/w gain settings,
+ *      and send changes to NIC
+ */
+static int
+il3945_hw_reg_set_new_power(struct il_priv *il, struct il_channel_info *ch_info)
+{
+       struct il3945_channel_power_info *power_info;
+       int power_changed = 0;
+       int i;
+       const s8 *clip_pwrs;
+       int power;
+
+       /* Get this chnlgrp's rate-to-max/clip-powers table */
+       clip_pwrs = il->_3945.clip_groups[ch_info->group_idx].clip_powers;
+
+       /* Get this channel's rate-to-current-power settings table */
+       power_info = ch_info->power_info;
+
+       /* update OFDM Txpower settings */
+       for (i = RATE_6M_IDX_TBL; i <= RATE_54M_IDX_TBL; i++, ++power_info) {
+               int delta_idx;
+
+               /* limit new power to be no more than h/w capability */
+               power = min(ch_info->curr_txpow, clip_pwrs[i]);
+               if (power == power_info->requested_power)
+                       continue;
+
+               /* find difference between old and new requested powers,
+                *    update base (non-temp-compensated) power idx */
+               delta_idx = (power - power_info->requested_power) * 2;
+               power_info->base_power_idx -= delta_idx;
+
+               /* save new requested power value */
+               power_info->requested_power = power;
+
+               power_changed = 1;
+       }
+
+       /* update CCK Txpower settings, based on OFDM 12M setting ...
+        *    ... all CCK power settings for a given channel are the *same*. */
+       if (power_changed) {
+               power =
+                   ch_info->power_info[RATE_12M_IDX_TBL].requested_power +
+                   IL_CCK_FROM_OFDM_POWER_DIFF;
+
+               /* do all CCK rates' il3945_channel_power_info structures */
+               for (i = RATE_1M_IDX_TBL; i <= RATE_11M_IDX_TBL; i++) {
+                       power_info->requested_power = power;
+                       power_info->base_power_idx =
+                           ch_info->power_info[RATE_12M_IDX_TBL].
+                           base_power_idx + IL_CCK_FROM_OFDM_IDX_DIFF;
+                       ++power_info;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * il3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel
+ *
+ * NOTE: Returned power limit may be less (but not more) than requested,
+ *      based strictly on regulatory (eeprom and spectrum mgt) limitations
+ *      (no consideration for h/w clipping limitations).
+ */
+static int
+il3945_hw_reg_get_ch_txpower_limit(struct il_channel_info *ch_info)
+{
+       s8 max_power;
+
+#if 0
+       /* if we're using TGd limits, use lower of TGd or EEPROM */
+       if (ch_info->tgd_data.max_power != 0)
+               max_power =
+                   min(ch_info->tgd_data.max_power,
+                       ch_info->eeprom.max_power_avg);
+
+       /* else just use EEPROM limits */
+       else
+#endif
+               max_power = ch_info->eeprom.max_power_avg;
+
+       return min(max_power, ch_info->max_power_avg);
+}
+
+/**
+ * il3945_hw_reg_comp_txpower_temp - Compensate for temperature
+ *
+ * Compensate txpower settings of *all* channels for temperature.
+ * This only accounts for the difference between current temperature
+ *   and the factory calibration temperatures, and bases the new settings
+ *   on the channel's base_power_idx.
+ *
+ * If RxOn is "associated", this sends the new Txpower to NIC!
+ */
+static int
+il3945_hw_reg_comp_txpower_temp(struct il_priv *il)
+{
+       struct il_channel_info *ch_info = NULL;
+       struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
+       int delta_idx;
+       const s8 *clip_pwrs;    /* array of h/w max power levels for each rate */
+       u8 a_band;
+       u8 rate_idx;
+       u8 scan_tbl_idx;
+       u8 i;
+       int ref_temp;
+       int temperature = il->temperature;
+
+       if (il->disable_tx_power_cal || test_bit(S_SCANNING, &il->status)) {
+               /* do not perform tx power calibration */
+               return 0;
+       }
+       /* set up new Tx power info for each and every channel, 2.4 and 5.x */
+       for (i = 0; i < il->channel_count; i++) {
+               ch_info = &il->channel_info[i];
+               a_band = il_is_channel_a_band(ch_info);
+
+               /* Get this chnlgrp's factory calibration temperature */
+               ref_temp = (s16) eeprom->groups[ch_info->group_idx].temperature;
+
+               /* get power idx adjustment based on current and factory
+                * temps */
+               delta_idx =
+                   il3945_hw_reg_adjust_power_by_temp(temperature, ref_temp);
+
+               /* set tx power value for all rates, OFDM and CCK */
+               for (rate_idx = 0; rate_idx < RATE_COUNT_3945; rate_idx++) {
+                       int power_idx =
+                           ch_info->power_info[rate_idx].base_power_idx;
+
+                       /* temperature compensate */
+                       power_idx += delta_idx;
+
+                       /* stay within table range */
+                       power_idx = il3945_hw_reg_fix_power_idx(power_idx);
+                       ch_info->power_info[rate_idx].power_table_idx =
+                           (u8) power_idx;
+                       ch_info->power_info[rate_idx].tpc =
+                           power_gain_table[a_band][power_idx];
+               }
+
+               /* Get this chnlgrp's rate-to-max/clip-powers table */
+               clip_pwrs =
+                   il->_3945.clip_groups[ch_info->group_idx].clip_powers;
+
+               /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
+               for (scan_tbl_idx = 0; scan_tbl_idx < IL_NUM_SCAN_RATES;
+                    scan_tbl_idx++) {
+                       s32 actual_idx =
+                           (scan_tbl_idx ==
+                            0) ? RATE_1M_IDX_TBL : RATE_6M_IDX_TBL;
+                       il3945_hw_reg_set_scan_power(il, scan_tbl_idx,
+                                                    actual_idx, clip_pwrs,
+                                                    ch_info, a_band);
+               }
+       }
+
+       /* send Txpower command for current channel to ucode */
+       return il->cfg->ops->lib->send_tx_power(il);
+}
+
+int
+il3945_hw_reg_set_txpower(struct il_priv *il, s8 power)
+{
+       struct il_channel_info *ch_info;
+       s8 max_power;
+       u8 a_band;
+       u8 i;
+
+       if (il->tx_power_user_lmt == power) {
+               D_POWER("Requested Tx power same as current " "limit: %ddBm.\n",
+                       power);
+               return 0;
+       }
+
+       D_POWER("Setting upper limit clamp to %ddBm.\n", power);
+       il->tx_power_user_lmt = power;
+
+       /* set up new Tx powers for each and every channel, 2.4 and 5.x */
+
+       for (i = 0; i < il->channel_count; i++) {
+               ch_info = &il->channel_info[i];
+               a_band = il_is_channel_a_band(ch_info);
+
+               /* find minimum power of all user and regulatory constraints
+                *    (does not consider h/w clipping limitations) */
+               max_power = il3945_hw_reg_get_ch_txpower_limit(ch_info);
+               max_power = min(power, max_power);
+               if (max_power != ch_info->curr_txpow) {
+                       ch_info->curr_txpow = max_power;
+
+                       /* this considers the h/w clipping limitations */
+                       il3945_hw_reg_set_new_power(il, ch_info);
+               }
+       }
+
+       /* update txpower settings for all channels,
+        *   send to NIC if associated. */
+       il3945_is_temp_calib_needed(il);
+       il3945_hw_reg_comp_txpower_temp(il);
+
+       return 0;
+}
+
+static int
+il3945_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       int rc = 0;
+       struct il_rx_pkt *pkt;
+       struct il3945_rxon_assoc_cmd rxon_assoc;
+       struct il_host_cmd cmd = {
+               .id = C_RXON_ASSOC,
+               .len = sizeof(rxon_assoc),
+               .flags = CMD_WANT_SKB,
+               .data = &rxon_assoc,
+       };
+       const struct il_rxon_cmd *rxon1 = &ctx->staging;
+       const struct il_rxon_cmd *rxon2 = &ctx->active;
+
+       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) {
+               D_INFO("Using current RXON_ASSOC.  Not resending.\n");
+               return 0;
+       }
+
+       rxon_assoc.flags = ctx->staging.flags;
+       rxon_assoc.filter_flags = ctx->staging.filter_flags;
+       rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
+       rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
+       rxon_assoc.reserved = 0;
+
+       rc = il_send_cmd_sync(il, &cmd);
+       if (rc)
+               return rc;
+
+       pkt = (struct il_rx_pkt *)cmd.reply_page;
+       if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
+               IL_ERR("Bad return from C_RXON_ASSOC command\n");
+               rc = -EIO;
+       }
+
+       il_free_pages(il, cmd.reply_page);
+
+       return rc;
+}
+
+/**
+ * il3945_commit_rxon - commit staging_rxon to hardware
+ *
+ * The RXON command in staging_rxon is committed 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.
+ */
+int
+il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       /* cast away the const for active_rxon in this function */
+       struct il3945_rxon_cmd *active_rxon = (void *)&ctx->active;
+       struct il3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
+       int rc = 0;
+       bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return -EINVAL;
+
+       if (!il_is_alive(il))
+               return -1;
+
+       /* always get timestamp with Rx frame */
+       staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
+
+       /* select antenna */
+       staging_rxon->flags &= ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
+       staging_rxon->flags |= il3945_get_antenna_flags(il);
+
+       rc = il_check_rxon_cmd(il, ctx);
+       if (rc) {
+               IL_ERR("Invalid RXON configuration.  Not committing.\n");
+               return -EINVAL;
+       }
+
+       /* If we don't need to send a full RXON, we can use
+        * il3945_rxon_assoc_cmd which is used to reconfigure filter
+        * and other flags for the current radio configuration. */
+       if (!il_full_rxon_required(il, &il->ctx)) {
+               rc = il_send_rxon_assoc(il, &il->ctx);
+               if (rc) {
+                       IL_ERR("Error setting RXON_ASSOC "
+                              "configuration (%d).\n", rc);
+                       return rc;
+               }
+
+               memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
+               /*
+                * We do not commit tx power settings while channel changing,
+                * do it now if tx power changed.
+                */
+               il_set_tx_power(il, il->tx_power_next, false);
+               return 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 (il_is_associated(il) && new_assoc) {
+               D_INFO("Toggling associated bit on current RXON\n");
+               active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+               /*
+                * reserved4 and 5 could have been filled by the iwlcore code.
+                * Let's clear them before pushing to the 3945.
+                */
+               active_rxon->reserved4 = 0;
+               active_rxon->reserved5 = 0;
+               rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd),
+                                    &il->ctx.active);
+
+               /* 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;
+                       IL_ERR("Error clearing ASSOC_MSK on current "
+                              "configuration (%d).\n", rc);
+                       return rc;
+               }
+               il_clear_ucode_stations(il, &il->ctx);
+               il_restore_stations(il, &il->ctx);
+       }
+
+       D_INFO("Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n"
+              "* channel = %d\n" "* bssid = %pM\n", (new_assoc ? "" : "out"),
+              le16_to_cpu(staging_rxon->channel), staging_rxon->bssid_addr);
+
+       /*
+        * reserved4 and 5 could have been filled by the iwlcore code.
+        * Let's clear them before pushing to the 3945.
+        */
+       staging_rxon->reserved4 = 0;
+       staging_rxon->reserved5 = 0;
+
+       il_set_rxon_hwcrypto(il, ctx, !il3945_mod_params.sw_crypto);
+
+       /* Apply the new configuration */
+       rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd),
+                            staging_rxon);
+       if (rc) {
+               IL_ERR("Error setting new configuration (%d).\n", rc);
+               return rc;
+       }
+
+       memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
+
+       if (!new_assoc) {
+               il_clear_ucode_stations(il, &il->ctx);
+               il_restore_stations(il, &il->ctx);
+       }
+
+       /* 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 = il_set_tx_power(il, il->tx_power_next, true);
+       if (rc) {
+               IL_ERR("Error setting Tx power (%d).\n", rc);
+               return rc;
+       }
+
+       /* Init the hardware's rate fallback order based on the band */
+       rc = il3945_init_hw_rate_table(il);
+       if (rc) {
+               IL_ERR("Error setting HW rate table: %02X\n", rc);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+/**
+ * il3945_reg_txpower_periodic -  called when time to check our temperature.
+ *
+ * -- reset periodic timer
+ * -- see if temp has changed enough to warrant re-calibration ... if so:
+ *     -- correct coeffs for temp (can reset temp timer)
+ *     -- save this temp as "last",
+ *     -- send new set of gain settings to NIC
+ * NOTE:  This should continue working, even when we're not associated,
+ *   so we can keep our internal table of scan powers current. */
+void
+il3945_reg_txpower_periodic(struct il_priv *il)
+{
+       /* This will kick in the "brute force"
+        * il3945_hw_reg_comp_txpower_temp() below */
+       if (!il3945_is_temp_calib_needed(il))
+               goto reschedule;
+
+       /* Set up a new set of temp-adjusted TxPowers, send to NIC.
+        * This is based *only* on current temperature,
+        * ignoring any previous power measurements */
+       il3945_hw_reg_comp_txpower_temp(il);
+
+reschedule:
+       queue_delayed_work(il->workqueue, &il->_3945.thermal_periodic,
+                          REG_RECALIB_PERIOD * HZ);
+}
+
+static void
+il3945_bg_reg_txpower_periodic(struct work_struct *work)
+{
+       struct il_priv *il = container_of(work, struct il_priv,
+                                         _3945.thermal_periodic.work);
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       mutex_lock(&il->mutex);
+       il3945_reg_txpower_periodic(il);
+       mutex_unlock(&il->mutex);
+}
+
+/**
+ * il3945_hw_reg_get_ch_grp_idx - find the channel-group idx (0-4) for channel.
+ *
+ * This function is used when initializing channel-info structs.
+ *
+ * NOTE: These channel groups do *NOT* match the bands above!
+ *      These channel groups are based on factory-tested channels;
+ *      on A-band, EEPROM's "group frequency" entries represent the top
+ *      channel in each group 1-4.  Group 5 All B/G channels are in group 0.
+ */
+static u16
+il3945_hw_reg_get_ch_grp_idx(struct il_priv *il,
+                            const struct il_channel_info *ch_info)
+{
+       struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
+       struct il3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0];
+       u8 group;
+       u16 group_idx = 0;      /* based on factory calib frequencies */
+       u8 grp_channel;
+
+       /* Find the group idx for the channel ... don't use idx 1(?) */
+       if (il_is_channel_a_band(ch_info)) {
+               for (group = 1; group < 5; group++) {
+                       grp_channel = ch_grp[group].group_channel;
+                       if (ch_info->channel <= grp_channel) {
+                               group_idx = group;
+                               break;
+                       }
+               }
+               /* group 4 has a few channels *above* its factory cal freq */
+               if (group == 5)
+                       group_idx = 4;
+       } else
+               group_idx = 0;  /* 2.4 GHz, group 0 */
+
+       D_POWER("Chnl %d mapped to grp %d\n", ch_info->channel, group_idx);
+       return group_idx;
+}
+
+/**
+ * il3945_hw_reg_get_matched_power_idx - Interpolate to get nominal idx
+ *
+ * Interpolate to get nominal (i.e. at factory calibration temperature) idx
+ *   into radio/DSP gain settings table for requested power.
+ */
+static int
+il3945_hw_reg_get_matched_power_idx(struct il_priv *il, s8 requested_power,
+                                   s32 setting_idx, s32 *new_idx)
+{
+       const struct il3945_eeprom_txpower_group *chnl_grp = NULL;
+       struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
+       s32 idx0, idx1;
+       s32 power = 2 * requested_power;
+       s32 i;
+       const struct il3945_eeprom_txpower_sample *samples;
+       s32 gains0, gains1;
+       s32 res;
+       s32 denominator;
+
+       chnl_grp = &eeprom->groups[setting_idx];
+       samples = chnl_grp->samples;
+       for (i = 0; i < 5; i++) {
+               if (power == samples[i].power) {
+                       *new_idx = samples[i].gain_idx;
+                       return 0;
+               }
+       }
+
+       if (power > samples[1].power) {
+               idx0 = 0;
+               idx1 = 1;
+       } else if (power > samples[2].power) {
+               idx0 = 1;
+               idx1 = 2;
+       } else if (power > samples[3].power) {
+               idx0 = 2;
+               idx1 = 3;
+       } else {
+               idx0 = 3;
+               idx1 = 4;
+       }
+
+       denominator = (s32) samples[idx1].power - (s32) samples[idx0].power;
+       if (denominator == 0)
+               return -EINVAL;
+       gains0 = (s32) samples[idx0].gain_idx * (1 << 19);
+       gains1 = (s32) samples[idx1].gain_idx * (1 << 19);
+       res =
+           gains0 + (gains1 - gains0) * ((s32) power -
+                                         (s32) samples[idx0].power) /
+           denominator + (1 << 18);
+       *new_idx = res >> 19;
+       return 0;
+}
+
+static void
+il3945_hw_reg_init_channel_groups(struct il_priv *il)
+{
+       u32 i;
+       s32 rate_idx;
+       struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
+       const struct il3945_eeprom_txpower_group *group;
+
+       D_POWER("Initializing factory calib info from EEPROM\n");
+
+       for (i = 0; i < IL_NUM_TX_CALIB_GROUPS; i++) {
+               s8 *clip_pwrs;  /* table of power levels for each rate */
+               s8 satur_pwr;   /* saturation power for each chnl group */
+               group = &eeprom->groups[i];
+
+               /* sanity check on factory saturation power value */
+               if (group->saturation_power < 40) {
+                       IL_WARN("Error: saturation power is %d, "
+                               "less than minimum expected 40\n",
+                               group->saturation_power);
+                       return;
+               }
+
+               /*
+                * Derive requested power levels for each rate, based on
+                *   hardware capabilities (saturation power for band).
+                * Basic value is 3dB down from saturation, with further
+                *   power reductions for highest 3 data rates.  These
+                *   backoffs provide headroom for high rate modulation
+                *   power peaks, without too much distortion (clipping).
+                */
+               /* we'll fill in this array with h/w max power levels */
+               clip_pwrs = (s8 *) il->_3945.clip_groups[i].clip_powers;
+
+               /* divide factory saturation power by 2 to find -3dB level */
+               satur_pwr = (s8) (group->saturation_power >> 1);
+
+               /* fill in channel group's nominal powers for each rate */
+               for (rate_idx = 0; rate_idx < RATE_COUNT_3945;
+                    rate_idx++, clip_pwrs++) {
+                       switch (rate_idx) {
+                       case RATE_36M_IDX_TBL:
+                               if (i == 0)     /* B/G */
+                                       *clip_pwrs = satur_pwr;
+                               else    /* A */
+                                       *clip_pwrs = satur_pwr - 5;
+                               break;
+                       case RATE_48M_IDX_TBL:
+                               if (i == 0)
+                                       *clip_pwrs = satur_pwr - 7;
+                               else
+                                       *clip_pwrs = satur_pwr - 10;
+                               break;
+                       case RATE_54M_IDX_TBL:
+                               if (i == 0)
+                                       *clip_pwrs = satur_pwr - 9;
+                               else
+                                       *clip_pwrs = satur_pwr - 12;
+                               break;
+                       default:
+                               *clip_pwrs = satur_pwr;
+                               break;
+                       }
+               }
+       }
+}
+
+/**
+ * il3945_txpower_set_from_eeprom - Set channel power info based on EEPROM
+ *
+ * Second pass (during init) to set up il->channel_info
+ *
+ * Set up Tx-power settings in our channel info database for each VALID
+ * (for this geo/SKU) channel, at all Tx data rates, based on eeprom values
+ * and current temperature.
+ *
+ * Since this is based on current temperature (at init time), these values may
+ * not be valid for very long, but it gives us a starting/default point,
+ * and allows us to active (i.e. using Tx) scan.
+ *
+ * This does *not* write values to NIC, just sets up our internal table.
+ */
+int
+il3945_txpower_set_from_eeprom(struct il_priv *il)
+{
+       struct il_channel_info *ch_info = NULL;
+       struct il3945_channel_power_info *pwr_info;
+       struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
+       int delta_idx;
+       u8 rate_idx;
+       u8 scan_tbl_idx;
+       const s8 *clip_pwrs;    /* array of power levels for each rate */
+       u8 gain, dsp_atten;
+       s8 power;
+       u8 pwr_idx, base_pwr_idx, a_band;
+       u8 i;
+       int temperature;
+
+       /* save temperature reference,
+        *   so we can determine next time to calibrate */
+       temperature = il3945_hw_reg_txpower_get_temperature(il);
+       il->last_temperature = temperature;
+
+       il3945_hw_reg_init_channel_groups(il);
+
+       /* initialize Tx power info for each and every channel, 2.4 and 5.x */
+       for (i = 0, ch_info = il->channel_info; i < il->channel_count;
+            i++, ch_info++) {
+               a_band = il_is_channel_a_band(ch_info);
+               if (!il_is_channel_valid(ch_info))
+                       continue;
+
+               /* find this channel's channel group (*not* "band") idx */
+               ch_info->group_idx = il3945_hw_reg_get_ch_grp_idx(il, ch_info);
+
+               /* Get this chnlgrp's rate->max/clip-powers table */
+               clip_pwrs =
+                   il->_3945.clip_groups[ch_info->group_idx].clip_powers;
+
+               /* calculate power idx *adjustment* value according to
+                *  diff between current temperature and factory temperature */
+               delta_idx =
+                   il3945_hw_reg_adjust_power_by_temp(temperature,
+                                                      eeprom->groups[ch_info->
+                                                                     group_idx].
+                                                      temperature);
+
+               D_POWER("Delta idx for channel %d: %d [%d]\n", ch_info->channel,
+                       delta_idx, temperature + IL_TEMP_CONVERT);
+
+               /* set tx power value for all OFDM rates */
+               for (rate_idx = 0; rate_idx < IL_OFDM_RATES; rate_idx++) {
+                       s32 uninitialized_var(power_idx);
+                       int rc;
+
+                       /* use channel group's clip-power table,
+                        *   but don't exceed channel's max power */
+                       s8 pwr = min(ch_info->max_power_avg,
+                                    clip_pwrs[rate_idx]);
+
+                       pwr_info = &ch_info->power_info[rate_idx];
+
+                       /* get base (i.e. at factory-measured temperature)
+                        *    power table idx for this rate's power */
+                       rc = il3945_hw_reg_get_matched_power_idx(il, pwr,
+                                                                ch_info->
+                                                                group_idx,
+                                                                &power_idx);
+                       if (rc) {
+                               IL_ERR("Invalid power idx\n");
+                               return rc;
+                       }
+                       pwr_info->base_power_idx = (u8) power_idx;
+
+                       /* temperature compensate */
+                       power_idx += delta_idx;
+
+                       /* stay within range of gain table */
+                       power_idx = il3945_hw_reg_fix_power_idx(power_idx);
+
+                       /* fill 1 OFDM rate's il3945_channel_power_info struct */
+                       pwr_info->requested_power = pwr;
+                       pwr_info->power_table_idx = (u8) power_idx;
+                       pwr_info->tpc.tx_gain =
+                           power_gain_table[a_band][power_idx].tx_gain;
+                       pwr_info->tpc.dsp_atten =
+                           power_gain_table[a_band][power_idx].dsp_atten;
+               }
+
+               /* set tx power for CCK rates, based on OFDM 12 Mbit settings */
+               pwr_info = &ch_info->power_info[RATE_12M_IDX_TBL];
+               power = pwr_info->requested_power + IL_CCK_FROM_OFDM_POWER_DIFF;
+               pwr_idx = pwr_info->power_table_idx + IL_CCK_FROM_OFDM_IDX_DIFF;
+               base_pwr_idx =
+                   pwr_info->base_power_idx + IL_CCK_FROM_OFDM_IDX_DIFF;
+
+               /* stay within table range */
+               pwr_idx = il3945_hw_reg_fix_power_idx(pwr_idx);
+               gain = power_gain_table[a_band][pwr_idx].tx_gain;
+               dsp_atten = power_gain_table[a_band][pwr_idx].dsp_atten;
+
+               /* fill each CCK rate's il3945_channel_power_info structure
+                * NOTE:  All CCK-rate Txpwrs are the same for a given chnl!
+                * NOTE:  CCK rates start at end of OFDM rates! */
+               for (rate_idx = 0; rate_idx < IL_CCK_RATES; rate_idx++) {
+                       pwr_info =
+                           &ch_info->power_info[rate_idx + IL_OFDM_RATES];
+                       pwr_info->requested_power = power;
+                       pwr_info->power_table_idx = pwr_idx;
+                       pwr_info->base_power_idx = base_pwr_idx;
+                       pwr_info->tpc.tx_gain = gain;
+                       pwr_info->tpc.dsp_atten = dsp_atten;
+               }
+
+               /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
+               for (scan_tbl_idx = 0; scan_tbl_idx < IL_NUM_SCAN_RATES;
+                    scan_tbl_idx++) {
+                       s32 actual_idx =
+                           (scan_tbl_idx ==
+                            0) ? RATE_1M_IDX_TBL : RATE_6M_IDX_TBL;
+                       il3945_hw_reg_set_scan_power(il, scan_tbl_idx,
+                                                    actual_idx, clip_pwrs,
+                                                    ch_info, a_band);
+               }
+       }
+
+       return 0;
+}
+
+int
+il3945_hw_rxq_stop(struct il_priv *il)
+{
+       int rc;
+
+       il_wr(il, FH39_RCSR_CONFIG(0), 0);
+       rc = il_poll_bit(il, FH39_RSSR_STATUS,
+                        FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+       if (rc < 0)
+               IL_ERR("Can't stop Rx DMA.\n");
+
+       return 0;
+}
+
+int
+il3945_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq)
+{
+       int txq_id = txq->q.id;
+
+       struct il3945_shared *shared_data = il->_3945.shared_virt;
+
+       shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32) txq->q.dma_addr);
+
+       il_wr(il, FH39_CBCC_CTRL(txq_id), 0);
+       il_wr(il, FH39_CBCC_BASE(txq_id), 0);
+
+       il_wr(il, FH39_TCSR_CONFIG(txq_id),
+             FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |
+             FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |
+             FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |
+             FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |
+             FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);
+
+       /* fake read to flush all prev. writes */
+       _il_rd(il, FH39_TSSR_CBB_BASE);
+
+       return 0;
+}
+
+/*
+ * HCMD utils
+ */
+static u16
+il3945_get_hcmd_size(u8 cmd_id, u16 len)
+{
+       switch (cmd_id) {
+       case C_RXON:
+               return sizeof(struct il3945_rxon_cmd);
+       case C_POWER_TBL:
+               return sizeof(struct il3945_powertable_cmd);
+       default:
+               return len;
+       }
+}
+
+static u16
+il3945_build_addsta_hcmd(const struct il_addsta_cmd *cmd, u8 * data)
+{
+       struct il3945_addsta_cmd *addsta = (struct il3945_addsta_cmd *)data;
+       addsta->mode = cmd->mode;
+       memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
+       memcpy(&addsta->key, &cmd->key, sizeof(struct il4965_keyinfo));
+       addsta->station_flags = cmd->station_flags;
+       addsta->station_flags_msk = cmd->station_flags_msk;
+       addsta->tid_disable_tx = cpu_to_le16(0);
+       addsta->rate_n_flags = cmd->rate_n_flags;
+       addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
+       addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
+       addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
+
+       return (u16) sizeof(struct il3945_addsta_cmd);
+}
+
+static int
+il3945_add_bssid_station(struct il_priv *il, const u8 * addr, u8 * sta_id_r)
+{
+       struct il_rxon_context *ctx = &il->ctx;
+       int ret;
+       u8 sta_id;
+       unsigned long flags;
+
+       if (sta_id_r)
+               *sta_id_r = IL_INVALID_STATION;
+
+       ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id);
+       if (ret) {
+               IL_ERR("Unable to add station %pM\n", addr);
+               return ret;
+       }
+
+       if (sta_id_r)
+               *sta_id_r = sta_id;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       il->stations[sta_id].used |= IL_STA_LOCAL;
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return 0;
+}
+
+static int
+il3945_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif,
+                          bool add)
+{
+       struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
+       int ret;
+
+       if (add) {
+               ret =
+                   il3945_add_bssid_station(il, vif->bss_conf.bssid,
+                                            &vif_priv->ibss_bssid_sta_id);
+               if (ret)
+                       return ret;
+
+               il3945_sync_sta(il, vif_priv->ibss_bssid_sta_id,
+                               (il->band ==
+                                IEEE80211_BAND_5GHZ) ? RATE_6M_PLCP :
+                               RATE_1M_PLCP);
+               il3945_rate_scale_init(il->hw, vif_priv->ibss_bssid_sta_id);
+
+               return 0;
+       }
+
+       return il_remove_station(il, vif_priv->ibss_bssid_sta_id,
+                                vif->bss_conf.bssid);
+}
+
+/**
+ * il3945_init_hw_rate_table - Initialize the hardware rate fallback table
+ */
+int
+il3945_init_hw_rate_table(struct il_priv *il)
+{
+       int rc, i, idx, prev_idx;
+       struct il3945_rate_scaling_cmd rate_cmd = {
+               .reserved = {0, 0, 0},
+       };
+       struct il3945_rate_scaling_info *table = rate_cmd.table;
+
+       for (i = 0; i < ARRAY_SIZE(il3945_rates); i++) {
+               idx = il3945_rates[i].table_rs_idx;
+
+               table[idx].rate_n_flags =
+                   il3945_hw_set_rate_n_flags(il3945_rates[i].plcp, 0);
+               table[idx].try_cnt = il->retry_rate;
+               prev_idx = il3945_get_prev_ieee_rate(i);
+               table[idx].next_rate_idx = il3945_rates[prev_idx].table_rs_idx;
+       }
+
+       switch (il->band) {
+       case IEEE80211_BAND_5GHZ:
+               D_RATE("Select A mode rate scale\n");
+               /* If one of the following CCK rates is used,
+                * have it fall back to the 6M OFDM rate */
+               for (i = RATE_1M_IDX_TBL; i <= RATE_11M_IDX_TBL; i++)
+                       table[i].next_rate_idx =
+                           il3945_rates[IL_FIRST_OFDM_RATE].table_rs_idx;
+
+               /* Don't fall back to CCK rates */
+               table[RATE_12M_IDX_TBL].next_rate_idx = RATE_9M_IDX_TBL;
+
+               /* Don't drop out of OFDM rates */
+               table[RATE_6M_IDX_TBL].next_rate_idx =
+                   il3945_rates[IL_FIRST_OFDM_RATE].table_rs_idx;
+               break;
+
+       case IEEE80211_BAND_2GHZ:
+               D_RATE("Select B/G mode rate scale\n");
+               /* If an OFDM rate is used, have it fall back to the
+                * 1M CCK rates */
+
+               if (!(il->_3945.sta_supp_rates & IL_OFDM_RATES_MASK) &&
+                   il_is_associated(il)) {
+
+                       idx = IL_FIRST_CCK_RATE;
+                       for (i = RATE_6M_IDX_TBL; i <= RATE_54M_IDX_TBL; i++)
+                               table[i].next_rate_idx =
+                                   il3945_rates[idx].table_rs_idx;
+
+                       idx = RATE_11M_IDX_TBL;
+                       /* CCK shouldn't fall back to OFDM... */
+                       table[idx].next_rate_idx = RATE_5M_IDX_TBL;
+               }
+               break;
+
+       default:
+               WARN_ON(1);
+               break;
+       }
+
+       /* Update the rate scaling for control frame Tx */
+       rate_cmd.table_id = 0;
+       rc = il_send_cmd_pdu(il, C_RATE_SCALE, sizeof(rate_cmd), &rate_cmd);
+       if (rc)
+               return rc;
+
+       /* Update the rate scaling for data frame Tx */
+       rate_cmd.table_id = 1;
+       return il_send_cmd_pdu(il, C_RATE_SCALE, sizeof(rate_cmd), &rate_cmd);
+}
+
+/* Called when initializing driver */
+int
+il3945_hw_set_hw_params(struct il_priv *il)
+{
+       memset((void *)&il->hw_params, 0, sizeof(struct il_hw_params));
+
+       il->_3945.shared_virt =
+           dma_alloc_coherent(&il->pci_dev->dev, sizeof(struct il3945_shared),
+                              &il->_3945.shared_phys, GFP_KERNEL);
+       if (!il->_3945.shared_virt) {
+               IL_ERR("failed to allocate pci memory\n");
+               return -ENOMEM;
+       }
+
+       /* Assign number of Usable TX queues */
+       il->hw_params.max_txq_num = il->cfg->base_params->num_of_queues;
+
+       il->hw_params.tfd_size = sizeof(struct il3945_tfd);
+       il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_3K);
+       il->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+       il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+       il->hw_params.max_stations = IL3945_STATION_COUNT;
+       il->ctx.bcast_sta_id = IL3945_BROADCAST_ID;
+
+       il->sta_key_max_num = STA_KEY_MAX_NUM;
+
+       il->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
+       il->hw_params.max_beacon_itrvl = IL39_MAX_UCODE_BEACON_INTERVAL;
+       il->hw_params.beacon_time_tsf_bits = IL3945_EXT_BEACON_TIME_POS;
+
+       return 0;
+}
+
+unsigned int
+il3945_hw_get_beacon_cmd(struct il_priv *il, struct il3945_frame *frame,
+                        u8 rate)
+{
+       struct il3945_tx_beacon_cmd *tx_beacon_cmd;
+       unsigned int frame_size;
+
+       tx_beacon_cmd = (struct il3945_tx_beacon_cmd *)&frame->u;
+       memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+
+       tx_beacon_cmd->tx.sta_id = il->ctx.bcast_sta_id;
+       tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+       frame_size =
+           il3945_fill_beacon_frame(il, tx_beacon_cmd->frame,
+                                    sizeof(frame->u) - sizeof(*tx_beacon_cmd));
+
+       BUG_ON(frame_size > MAX_MPDU_SIZE);
+       tx_beacon_cmd->tx.len = cpu_to_le16((u16) frame_size);
+
+       tx_beacon_cmd->tx.rate = rate;
+       tx_beacon_cmd->tx.tx_flags =
+           (TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK);
+
+       /* supp_rates[0] == OFDM start at IL_FIRST_OFDM_RATE */
+       tx_beacon_cmd->tx.supp_rates[0] =
+           (IL_OFDM_BASIC_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF;
+
+       tx_beacon_cmd->tx.supp_rates[1] = (IL_CCK_BASIC_RATES_MASK & 0xF);
+
+       return sizeof(struct il3945_tx_beacon_cmd) + frame_size;
+}
+
+void
+il3945_hw_handler_setup(struct il_priv *il)
+{
+       il->handlers[C_TX] = il3945_hdl_tx;
+       il->handlers[N_3945_RX] = il3945_hdl_rx;
+}
+
+void
+il3945_hw_setup_deferred_work(struct il_priv *il)
+{
+       INIT_DELAYED_WORK(&il->_3945.thermal_periodic,
+                         il3945_bg_reg_txpower_periodic);
+}
+
+void
+il3945_hw_cancel_deferred_work(struct il_priv *il)
+{
+       cancel_delayed_work(&il->_3945.thermal_periodic);
+}
+
+/* check contents of special bootstrap uCode SRAM */
+static int
+il3945_verify_bsm(struct il_priv *il)
+{
+       __le32 *image = il->ucode_boot.v_addr;
+       u32 len = il->ucode_boot.len;
+       u32 reg;
+       u32 val;
+
+       D_INFO("Begin verify bsm\n");
+
+       /* verify BSM SRAM contents */
+       val = il_rd_prph(il, BSM_WR_DWCOUNT_REG);
+       for (reg = BSM_SRAM_LOWER_BOUND; reg < BSM_SRAM_LOWER_BOUND + len;
+            reg += sizeof(u32), image++) {
+               val = il_rd_prph(il, reg);
+               if (val != le32_to_cpu(*image)) {
+                       IL_ERR("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;
+               }
+       }
+
+       D_INFO("BSM bootstrap uCode image OK\n");
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+ ******************************************************************************/
+
+/*
+ * Clear the OWNER_MSK, to establish driver (instead of uCode running on
+ * embedded controller) as EEPROM reader; each read is a series of pulses
+ * to/from the EEPROM chip, not a single event, so even reads could conflict
+ * if they weren't arbitrated by some ownership mechanism.  Here, the driver
+ * simply claims ownership, which should be safe when this function is called
+ * (i.e. before loading uCode!).
+ */
+static int
+il3945_eeprom_acquire_semaphore(struct il_priv *il)
+{
+       _il_clear_bit(il, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
+       return 0;
+}
+
+static void
+il3945_eeprom_release_semaphore(struct il_priv *il)
+{
+       return;
+}
+
+ /**
+  * il3945_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
+il3945_load_bsm(struct il_priv *il)
+{
+       __le32 *image = il->ucode_boot.v_addr;
+       u32 len = il->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;
+
+       D_INFO("Begin load bsm\n");
+
+       /* make sure bootstrap program is no larger than BSM's SRAM size */
+       if (len > IL39_MAX_BSM_SIZE)
+               return -EINVAL;
+
+       /* Tell bootstrap uCode where to find the "Initialize" uCode
+        *   in host DRAM ... host DRAM physical address bits 31:0 for 3945.
+        * NOTE:  il3945_initialize_alive_start() will replace these values,
+        *        after the "initialize" uCode has run, to point to
+        *        runtime/protocol instructions and backup data cache. */
+       pinst = il->ucode_init.p_addr;
+       pdata = il->ucode_init_data.p_addr;
+       inst_len = il->ucode_init.len;
+       data_len = il->ucode_init_data.len;
+
+       il_wr_prph(il, BSM_DRAM_INST_PTR_REG, pinst);
+       il_wr_prph(il, BSM_DRAM_DATA_PTR_REG, pdata);
+       il_wr_prph(il, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+       il_wr_prph(il, 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++)
+               _il_wr_prph(il, reg_offset, le32_to_cpu(*image));
+
+       rc = il3945_verify_bsm(il);
+       if (rc)
+               return rc;
+
+       /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
+       il_wr_prph(il, BSM_WR_MEM_SRC_REG, 0x0);
+       il_wr_prph(il, BSM_WR_MEM_DST_REG, IL39_RTC_INST_LOWER_BOUND);
+       il_wr_prph(il, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+
+       /* Load bootstrap code into instruction SRAM now,
+        *   to prepare to load "initialize" uCode */
+       il_wr_prph(il, 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 = il_rd_prph(il, BSM_WR_CTRL_REG);
+               if (!(done & BSM_WR_CTRL_REG_BIT_START))
+                       break;
+               udelay(10);
+       }
+       if (i < 100)
+               D_INFO("BSM write complete, poll %d iterations\n", i);
+       else {
+               IL_ERR("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) */
+       il_wr_prph(il, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
+
+       return 0;
+}
+
+static struct il_hcmd_ops il3945_hcmd = {
+       .rxon_assoc = il3945_send_rxon_assoc,
+       .commit_rxon = il3945_commit_rxon,
+};
+
+static struct il_lib_ops il3945_lib = {
+       .txq_attach_buf_to_tfd = il3945_hw_txq_attach_buf_to_tfd,
+       .txq_free_tfd = il3945_hw_txq_free_tfd,
+       .txq_init = il3945_hw_tx_queue_init,
+       .load_ucode = il3945_load_bsm,
+       .dump_nic_error_log = il3945_dump_nic_error_log,
+       .apm_ops = {
+                   .init = il3945_apm_init,
+                   .config = il3945_nic_config,
+                   },
+       .eeprom_ops = {
+                      .regulatory_bands = {
+                                           EEPROM_REGULATORY_BAND_1_CHANNELS,
+                                           EEPROM_REGULATORY_BAND_2_CHANNELS,
+                                           EEPROM_REGULATORY_BAND_3_CHANNELS,
+                                           EEPROM_REGULATORY_BAND_4_CHANNELS,
+                                           EEPROM_REGULATORY_BAND_5_CHANNELS,
+                                           EEPROM_REGULATORY_BAND_NO_HT40,
+                                           EEPROM_REGULATORY_BAND_NO_HT40,
+                                           },
+                      .acquire_semaphore = il3945_eeprom_acquire_semaphore,
+                      .release_semaphore = il3945_eeprom_release_semaphore,
+                      },
+       .send_tx_power = il3945_send_tx_power,
+       .is_valid_rtc_data_addr = il3945_hw_valid_rtc_data_addr,
+
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+       .debugfs_ops = {
+                       .rx_stats_read = il3945_ucode_rx_stats_read,
+                       .tx_stats_read = il3945_ucode_tx_stats_read,
+                       .general_stats_read = il3945_ucode_general_stats_read,
+                       },
+#endif
+};
+
+static const struct il_legacy_ops il3945_legacy_ops = {
+       .post_associate = il3945_post_associate,
+       .config_ap = il3945_config_ap,
+       .manage_ibss_station = il3945_manage_ibss_station,
+};
+
+static struct il_hcmd_utils_ops il3945_hcmd_utils = {
+       .get_hcmd_size = il3945_get_hcmd_size,
+       .build_addsta_hcmd = il3945_build_addsta_hcmd,
+       .request_scan = il3945_request_scan,
+       .post_scan = il3945_post_scan,
+};
+
+static const struct il_ops il3945_ops = {
+       .lib = &il3945_lib,
+       .hcmd = &il3945_hcmd,
+       .utils = &il3945_hcmd_utils,
+       .led = &il3945_led_ops,
+       .legacy = &il3945_legacy_ops,
+       .ieee80211_ops = &il3945_hw_ops,
+};
+
+static struct il_base_params il3945_base_params = {
+       .eeprom_size = IL3945_EEPROM_IMG_SIZE,
+       .num_of_queues = IL39_NUM_QUEUES,
+       .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
+       .set_l0s = false,
+       .use_bsm = true,
+       .led_compensation = 64,
+       .wd_timeout = IL_DEF_WD_TIMEOUT,
+};
+
+static struct il_cfg il3945_bg_cfg = {
+       .name = "3945BG",
+       .fw_name_pre = IL3945_FW_PRE,
+       .ucode_api_max = IL3945_UCODE_API_MAX,
+       .ucode_api_min = IL3945_UCODE_API_MIN,
+       .sku = IL_SKU_G,
+       .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
+       .ops = &il3945_ops,
+       .mod_params = &il3945_mod_params,
+       .base_params = &il3945_base_params,
+       .led_mode = IL_LED_BLINK,
+};
+
+static struct il_cfg il3945_abg_cfg = {
+       .name = "3945ABG",
+       .fw_name_pre = IL3945_FW_PRE,
+       .ucode_api_max = IL3945_UCODE_API_MAX,
+       .ucode_api_min = IL3945_UCODE_API_MIN,
+       .sku = IL_SKU_A | IL_SKU_G,
+       .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
+       .ops = &il3945_ops,
+       .mod_params = &il3945_mod_params,
+       .base_params = &il3945_base_params,
+       .led_mode = IL_LED_BLINK,
+};
+
+DEFINE_PCI_DEVICE_TABLE(il3945_hw_card_ids) = {
+       {IL_PCI_DEVICE(0x4222, 0x1005, il3945_bg_cfg)},
+       {IL_PCI_DEVICE(0x4222, 0x1034, il3945_bg_cfg)},
+       {IL_PCI_DEVICE(0x4222, 0x1044, il3945_bg_cfg)},
+       {IL_PCI_DEVICE(0x4227, 0x1014, il3945_bg_cfg)},
+       {IL_PCI_DEVICE(0x4222, PCI_ANY_ID, il3945_abg_cfg)},
+       {IL_PCI_DEVICE(0x4227, PCI_ANY_ID, il3945_abg_cfg)},
+       {0}
+};
+
+MODULE_DEVICE_TABLE(pci, il3945_hw_card_ids);
diff --git a/drivers/net/wireless/iwlegacy/3945.h b/drivers/net/wireless/iwlegacy/3945.h
new file mode 100644 (file)
index 0000000..2b2895c
--- /dev/null
@@ -0,0 +1,626 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __il_3945_h__
+#define __il_3945_h__
+
+#include <linux/pci.h>         /* for struct pci_device_id */
+#include <linux/kernel.h>
+#include <net/ieee80211_radiotap.h>
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+extern const struct pci_device_id il3945_hw_card_ids[];
+
+#include "common.h"
+
+/* Highest firmware API version supported */
+#define IL3945_UCODE_API_MAX 2
+
+/* Lowest firmware API version supported */
+#define IL3945_UCODE_API_MIN 1
+
+#define IL3945_FW_PRE  "iwlwifi-3945-"
+#define _IL3945_MODULE_FIRMWARE(api) IL3945_FW_PRE #api ".ucode"
+#define IL3945_MODULE_FIRMWARE(api) _IL3945_MODULE_FIRMWARE(api)
+
+/* Default noise level to report when noise measurement is not available.
+ *   This may be because we're:
+ *   1)  Not associated (4965, no beacon stats being sent to driver)
+ *   2)  Scanning (noise measurement does not apply to associated channel)
+ *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
+ * Use default noise value of -127 ... this is below the range of measurable
+ *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
+ *   Also, -127 works better than 0 when averaging frames with/without
+ *   noise info (e.g. averaging might be done in app); measured dBm values are
+ *   always negative ... using a negative value as the default keeps all
+ *   averages within an s8's (used in some apps) range of negative values. */
+#define IL_NOISE_MEAS_NOT_AVAILABLE (-127)
+
+/* Module parameters accessible from iwl-*.c */
+extern struct il_mod_params il3945_mod_params;
+
+struct il3945_rate_scale_data {
+       u64 data;
+       s32 success_counter;
+       s32 success_ratio;
+       s32 counter;
+       s32 average_tpt;
+       unsigned long stamp;
+};
+
+struct il3945_rs_sta {
+       spinlock_t lock;
+       struct il_priv *il;
+       s32 *expected_tpt;
+       unsigned long last_partial_flush;
+       unsigned long last_flush;
+       u32 flush_time;
+       u32 last_tx_packets;
+       u32 tx_packets;
+       u8 tgg;
+       u8 flush_pending;
+       u8 start_rate;
+       struct timer_list rate_scale_flush;
+       struct il3945_rate_scale_data win[RATE_COUNT_3945];
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct dentry *rs_sta_dbgfs_stats_table_file;
+#endif
+
+       /* used to be in sta_info */
+       int last_txrate_idx;
+};
+
+/*
+ * The common struct MUST be first because it is shared between
+ * 3945 and 4965!
+ */
+struct il3945_sta_priv {
+       struct il_station_priv_common common;
+       struct il3945_rs_sta rs_sta;
+};
+
+enum il3945_antenna {
+       IL_ANTENNA_DIVERSITY,
+       IL_ANTENNA_MAIN,
+       IL_ANTENNA_AUX
+};
+
+/*
+ * RTS threshold here is total size [2347] minus 4 FCS bytes
+ * Per spec:
+ *   a value of 0 means RTS on all data/management packets
+ *   a value > max MSDU size means no RTS
+ * else RTS for data/management frames where MPDU is larger
+ *   than RTS value.
+ */
+#define DEFAULT_RTS_THRESHOLD     2347U
+#define MIN_RTS_THRESHOLD         0U
+#define MAX_RTS_THRESHOLD         2347U
+#define MAX_MSDU_SIZE            2304U
+#define MAX_MPDU_SIZE            2346U
+#define DEFAULT_BEACON_INTERVAL   100U
+#define        DEFAULT_SHORT_RETRY_LIMIT 7U
+#define        DEFAULT_LONG_RETRY_LIMIT  4U
+
+#define IL_TX_FIFO_AC0 0
+#define IL_TX_FIFO_AC1 1
+#define IL_TX_FIFO_AC2 2
+#define IL_TX_FIFO_AC3 3
+#define IL_TX_FIFO_HCCA_1      5
+#define IL_TX_FIFO_HCCA_2      6
+#define IL_TX_FIFO_NONE        7
+
+#define IEEE80211_DATA_LEN              2304
+#define IEEE80211_4ADDR_LEN             30
+#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+struct il3945_frame {
+       union {
+               struct ieee80211_hdr frame;
+               struct il3945_tx_beacon_cmd beacon;
+               u8 raw[IEEE80211_FRAME_LEN];
+               u8 cmd[360];
+       } u;
+       struct list_head list;
+};
+
+#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
+#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
+
+#define IL_SUPPORTED_RATES_IE_LEN         8
+
+#define SCAN_INTERVAL 100
+
+#define MAX_TID_COUNT        9
+
+#define IL_INVALID_RATE     0xFF
+#define IL_INVALID_VALUE    -1
+
+#define STA_PS_STATUS_WAKE             0
+#define STA_PS_STATUS_SLEEP            1
+
+struct il3945_ibss_seq {
+       u8 mac[ETH_ALEN];
+       u16 seq_num;
+       u16 frag_num;
+       unsigned long packet_time;
+       struct list_head list;
+};
+
+#define IL_RX_HDR(x) ((struct il3945_rx_frame_hdr *)(\
+                      x->u.rx_frame.stats.payload + \
+                      x->u.rx_frame.stats.phy_count))
+#define IL_RX_END(x) ((struct il3945_rx_frame_end *)(\
+                      IL_RX_HDR(x)->payload + \
+                      le16_to_cpu(IL_RX_HDR(x)->len)))
+#define IL_RX_STATS(x) (&x->u.rx_frame.stats)
+#define IL_RX_DATA(x) (IL_RX_HDR(x)->payload)
+
+/******************************************************************************
+ *
+ * Functions implemented in iwl3945-base.c which are forward declared here
+ * for use by iwl-*.c
+ *
+ *****************************************************************************/
+extern int il3945_calc_db_from_ratio(int sig_ratio);
+extern void il3945_rx_replenish(void *data);
+extern void il3945_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq);
+extern unsigned int il3945_fill_beacon_frame(struct il_priv *il,
+                                            struct ieee80211_hdr *hdr,
+                                            int left);
+extern int il3945_dump_nic_event_log(struct il_priv *il, bool full_log,
+                                    char **buf, bool display);
+extern void il3945_dump_nic_error_log(struct il_priv *il);
+
+/******************************************************************************
+ *
+ * Functions implemented in iwl-[34]*.c which are forward declared here
+ * for use by iwl3945-base.c
+ *
+ * NOTE:  The implementation of these functions are hardware specific
+ * which is why they are in the hardware specific files (vs. iwl-base.c)
+ *
+ * Naming convention --
+ * il3945_         <-- Its part of iwlwifi (should be changed to il3945_)
+ * il3945_hw_      <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
+ * iwlXXXX_     <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
+ * il3945_bg_      <-- Called from work queue context
+ * il3945_mac_     <-- mac80211 callback
+ *
+ ****************************************************************************/
+extern void il3945_hw_handler_setup(struct il_priv *il);
+extern void il3945_hw_setup_deferred_work(struct il_priv *il);
+extern void il3945_hw_cancel_deferred_work(struct il_priv *il);
+extern int il3945_hw_rxq_stop(struct il_priv *il);
+extern int il3945_hw_set_hw_params(struct il_priv *il);
+extern int il3945_hw_nic_init(struct il_priv *il);
+extern int il3945_hw_nic_stop_master(struct il_priv *il);
+extern void il3945_hw_txq_ctx_free(struct il_priv *il);
+extern void il3945_hw_txq_ctx_stop(struct il_priv *il);
+extern int il3945_hw_nic_reset(struct il_priv *il);
+extern int il3945_hw_txq_attach_buf_to_tfd(struct il_priv *il,
+                                          struct il_tx_queue *txq,
+                                          dma_addr_t addr, u16 len, u8 reset,
+                                          u8 pad);
+extern void il3945_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq);
+extern int il3945_hw_get_temperature(struct il_priv *il);
+extern int il3945_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq);
+extern unsigned int il3945_hw_get_beacon_cmd(struct il_priv *il,
+                                            struct il3945_frame *frame,
+                                            u8 rate);
+void il3945_hw_build_tx_cmd_rate(struct il_priv *il, struct il_device_cmd *cmd,
+                                struct ieee80211_tx_info *info,
+                                struct ieee80211_hdr *hdr, int sta_id,
+                                int tx_id);
+extern int il3945_hw_reg_send_txpower(struct il_priv *il);
+extern int il3945_hw_reg_set_txpower(struct il_priv *il, s8 power);
+extern void il3945_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb);
+void il3945_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb);
+extern void il3945_disable_events(struct il_priv *il);
+extern int il4965_get_temperature(const struct il_priv *il);
+extern void il3945_post_associate(struct il_priv *il);
+extern void il3945_config_ap(struct il_priv *il);
+
+extern int il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx);
+
+/**
+ * il3945_hw_find_station - Find station id for a given BSSID
+ * @bssid: MAC address of station ID to find
+ *
+ * NOTE:  This should not be hardware specific but the code has
+ * not yet been merged into a single common layer for managing the
+ * station tables.
+ */
+extern u8 il3945_hw_find_station(struct il_priv *il, const u8 * bssid);
+
+extern struct ieee80211_ops il3945_hw_ops;
+
+extern __le32 il3945_get_antenna_flags(const struct il_priv *il);
+extern int il3945_init_hw_rate_table(struct il_priv *il);
+extern void il3945_reg_txpower_periodic(struct il_priv *il);
+extern int il3945_txpower_set_from_eeprom(struct il_priv *il);
+
+extern int il3945_rs_next_rate(struct il_priv *il, int rate);
+
+/* scanning */
+int il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif);
+void il3945_post_scan(struct il_priv *il);
+
+/* rates */
+extern const struct il3945_rate_info il3945_rates[RATE_COUNT_3945];
+
+/* RSSI to dBm */
+#define IL39_RSSI_OFFSET       95
+
+/*
+ * EEPROM related constants, enums, and structures.
+ */
+#define EEPROM_SKU_CAP_OP_MODE_MRC                      (1 << 7)
+
+/*
+ * Mapping of a Tx power level, at factory calibration temperature,
+ *   to a radio/DSP gain table idx.
+ * 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.
+ * DO NOT ALTER THIS STRUCTURE!!!
+ */
+struct il3945_eeprom_txpower_sample {
+       u8 gain_idx;            /* idx into power (gain) setup table ... */
+       s8 power;               /* ... for this pwr level for this chnl group */
+       u16 v_det;              /* PA output voltage */
+} __packed;
+
+/*
+ * Mappings of Tx power levels -> nominal radio/DSP gain table idxes.
+ * 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 il3945_eeprom_txpower_group {
+       struct il3945_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) */
+} __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 il3945_eeprom_temperature_corr {
+       u32 Ta;
+       u32 Tb;
+       u32 Tc;
+       u32 Td;
+       u32 Te;
+} __packed;
+
+/*
+ * EEPROM map
+ */
+struct il3945_eeprom {
+       u8 reserved0[16];
+       u16 device_id;          /* abs.ofs: 16 */
+       u8 reserved1[2];
+       u16 pmc;                /* abs.ofs: 20 */
+       u8 reserved2[20];
+       u8 mac_address[6];      /* abs.ofs: 42 */
+       u8 reserved3[58];
+       u16 board_revision;     /* abs.ofs: 106 */
+       u8 reserved4[11];
+       u8 board_pba_number[9]; /* abs.ofs: 119 */
+       u8 reserved5[8];
+       u16 version;            /* abs.ofs: 136 */
+       u8 sku_cap;             /* abs.ofs: 138 */
+       u8 leds_mode;           /* abs.ofs: 139 */
+       u16 oem_mode;
+       u16 wowlan_mode;        /* abs.ofs: 142 */
+       u16 leds_time_interval; /* abs.ofs: 144 */
+       u8 leds_off_time;       /* abs.ofs: 146 */
+       u8 leds_on_time;        /* abs.ofs: 147 */
+       u8 almgor_m_version;    /* abs.ofs: 148 */
+       u8 antenna_switch_type; /* abs.ofs: 149 */
+       u8 reserved6[42];
+       u8 sku_id[4];           /* abs.ofs: 192 */
+
+/*
+ * Per-channel regulatory data.
+ *
+ * Each channel that *might* be supported by 3945 has a fixed location
+ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
+ * txpower (MSB).
+ *
+ * Entries immediately below are for 20 MHz channel width.
+ *
+ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ */
+       u16 band_1_count;       /* abs.ofs: 196 */
+       struct il_eeprom_channel band_1_channels[14];   /* abs.ofs: 198 */
+
+/*
+ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
+ * 5.0 GHz channels 7, 8, 11, 12, 16
+ * (4915-5080MHz) (none of these is ever supported)
+ */
+       u16 band_2_count;       /* abs.ofs: 226 */
+       struct il_eeprom_channel band_2_channels[13];   /* abs.ofs: 228 */
+
+/*
+ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+ * (5170-5320MHz)
+ */
+       u16 band_3_count;       /* abs.ofs: 254 */
+       struct il_eeprom_channel band_3_channels[12];   /* abs.ofs: 256 */
+
+/*
+ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+ * (5500-5700MHz)
+ */
+       u16 band_4_count;       /* abs.ofs: 280 */
+       struct il_eeprom_channel band_4_channels[11];   /* abs.ofs: 282 */
+
+/*
+ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+ * (5725-5825MHz)
+ */
+       u16 band_5_count;       /* abs.ofs: 304 */
+       struct il_eeprom_channel band_5_channels[6];    /* abs.ofs: 306 */
+
+       u8 reserved9[194];
+
+/*
+ * 3945 Txpower calibration data.
+ */
+#define IL_NUM_TX_CALIB_GROUPS 5
+       struct il3945_eeprom_txpower_group groups[IL_NUM_TX_CALIB_GROUPS];
+/* abs.ofs: 512 */
+       struct il3945_eeprom_temperature_corr corrections;      /* abs.ofs: 832 */
+       u8 reserved16[172];     /* fill out to full 1024 byte block */
+} __packed;
+
+#define IL3945_EEPROM_IMG_SIZE 1024
+
+/* End of EEPROM */
+
+#define PCI_CFG_REV_ID_BIT_BASIC_SKU                (0x40)     /* bit 6    */
+#define PCI_CFG_REV_ID_BIT_RTP                      (0x80)     /* bit 7    */
+
+/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
+#define IL39_NUM_QUEUES        5
+#define IL39_CMD_QUEUE_NUM     4
+
+#define IL_DEFAULT_TX_RETRY  15
+
+/*********************************************/
+
+#define RFD_SIZE                              4
+#define NUM_TFD_CHUNKS                        4
+
+#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)
+
+/* Sizes and addresses for instruction and data memory (SRAM) in
+ * 3945's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
+#define IL39_RTC_INST_LOWER_BOUND              (0x000000)
+#define IL39_RTC_INST_UPPER_BOUND              (0x014000)
+
+#define IL39_RTC_DATA_LOWER_BOUND              (0x800000)
+#define IL39_RTC_DATA_UPPER_BOUND              (0x808000)
+
+#define IL39_RTC_INST_SIZE (IL39_RTC_INST_UPPER_BOUND - \
+                               IL39_RTC_INST_LOWER_BOUND)
+#define IL39_RTC_DATA_SIZE (IL39_RTC_DATA_UPPER_BOUND - \
+                               IL39_RTC_DATA_LOWER_BOUND)
+
+#define IL39_MAX_INST_SIZE IL39_RTC_INST_SIZE
+#define IL39_MAX_DATA_SIZE IL39_RTC_DATA_SIZE
+
+/* Size of uCode instruction memory in bootstrap state machine */
+#define IL39_MAX_BSM_SIZE IL39_RTC_INST_SIZE
+
+static inline int
+il3945_hw_valid_rtc_data_addr(u32 addr)
+{
+       return (addr >= IL39_RTC_DATA_LOWER_BOUND &&
+               addr < IL39_RTC_DATA_UPPER_BOUND);
+}
+
+/* Base physical address of il3945_shared is provided to FH39_TSSR_CBB_BASE
+ * and &il3945_shared.rx_read_ptr[0] is provided to FH39_RCSR_RPTR_ADDR(0) */
+struct il3945_shared {
+       __le32 tx_base_ptr[8];
+} __packed;
+
+static inline u8
+il3945_hw_get_rate(__le16 rate_n_flags)
+{
+       return le16_to_cpu(rate_n_flags) & 0xFF;
+}
+
+static inline u16
+il3945_hw_get_rate_n_flags(__le16 rate_n_flags)
+{
+       return le16_to_cpu(rate_n_flags);
+}
+
+static inline __le16
+il3945_hw_set_rate_n_flags(u8 rate, u16 flags)
+{
+       return cpu_to_le16((u16) rate | flags);
+}
+
+/************************************/
+/* iwl3945 Flow Handler Definitions */
+/************************************/
+
+/**
+ * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
+ * Addresses are offsets from device's PCI hardware base address.
+ */
+#define FH39_MEM_LOWER_BOUND                   (0x0800)
+#define FH39_MEM_UPPER_BOUND                   (0x1000)
+
+#define FH39_CBCC_TBL          (FH39_MEM_LOWER_BOUND + 0x140)
+#define FH39_TFDB_TBL          (FH39_MEM_LOWER_BOUND + 0x180)
+#define FH39_RCSR_TBL          (FH39_MEM_LOWER_BOUND + 0x400)
+#define FH39_RSSR_TBL          (FH39_MEM_LOWER_BOUND + 0x4c0)
+#define FH39_TCSR_TBL          (FH39_MEM_LOWER_BOUND + 0x500)
+#define FH39_TSSR_TBL          (FH39_MEM_LOWER_BOUND + 0x680)
+
+/* TFDB (Transmit Frame Buffer Descriptor) */
+#define FH39_TFDB(_ch, buf)                    (FH39_TFDB_TBL + \
+                                                ((_ch) * 2 + (buf)) * 0x28)
+#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch)       (FH39_TFDB_TBL + 0x50 * (_ch))
+
+/* CBCC channel is [0,2] */
+#define FH39_CBCC(_ch)         (FH39_CBCC_TBL + (_ch) * 0x8)
+#define FH39_CBCC_CTRL(_ch)    (FH39_CBCC(_ch) + 0x00)
+#define FH39_CBCC_BASE(_ch)    (FH39_CBCC(_ch) + 0x04)
+
+/* RCSR channel is [0,2] */
+#define FH39_RCSR(_ch)                 (FH39_RCSR_TBL + (_ch) * 0x40)
+#define FH39_RCSR_CONFIG(_ch)          (FH39_RCSR(_ch) + 0x00)
+#define FH39_RCSR_RBD_BASE(_ch)                (FH39_RCSR(_ch) + 0x04)
+#define FH39_RCSR_WPTR(_ch)            (FH39_RCSR(_ch) + 0x20)
+#define FH39_RCSR_RPTR_ADDR(_ch)       (FH39_RCSR(_ch) + 0x24)
+
+#define FH39_RSCSR_CHNL0_WPTR          (FH39_RCSR_WPTR(0))
+
+/* RSSR */
+#define FH39_RSSR_CTRL                 (FH39_RSSR_TBL + 0x000)
+#define FH39_RSSR_STATUS               (FH39_RSSR_TBL + 0x004)
+
+/* TCSR */
+#define FH39_TCSR(_ch)                 (FH39_TCSR_TBL + (_ch) * 0x20)
+#define FH39_TCSR_CONFIG(_ch)          (FH39_TCSR(_ch) + 0x00)
+#define FH39_TCSR_CREDIT(_ch)          (FH39_TCSR(_ch) + 0x04)
+#define FH39_TCSR_BUFF_STTS(_ch)       (FH39_TCSR(_ch) + 0x08)
+
+/* TSSR */
+#define FH39_TSSR_CBB_BASE        (FH39_TSSR_TBL + 0x000)
+#define FH39_TSSR_MSG_CONFIG      (FH39_TSSR_TBL + 0x008)
+#define FH39_TSSR_TX_STATUS       (FH39_TSSR_TBL + 0x010)
+
+/* DBM */
+
+#define FH39_SRVC_CHNL                            (6)
+
+#define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE     (20)
+#define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH      (4)
+
+#define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN    (0x08000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE        (0x80000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE           (0x20000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128          (0x01000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST          (0x00001000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH                        (0x00000000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF               (0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER            (0x00000001)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL     (0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL      (0x00000008)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD            (0x00200000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT             (0x00000000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE             (0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE            (0x80000000)
+
+#define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID           (0x00004000)
+
+#define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR            (0x00000001)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON       (0xFF000000)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON       (0x00FF0000)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B     (0x00000400)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON                (0x00000100)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON                (0x00000080)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH      (0x00000020)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH            (0x00000005)
+
+#define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch)    (BIT(_ch) << 24)
+#define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch)   (BIT(_ch) << 16)
+
+#define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \
+       (FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \
+        FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch))
+
+#define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE                    (0x01000000)
+
+struct il3945_tfd_tb {
+       __le32 addr;
+       __le32 len;
+} __packed;
+
+struct il3945_tfd {
+       __le32 control_flags;
+       struct il3945_tfd_tb tbs[4];
+       u8 __pad[28];
+} __packed;
+
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+ssize_t il3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+                                  size_t count, loff_t *ppos);
+ssize_t il3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+                                  size_t count, loff_t *ppos);
+ssize_t il3945_ucode_general_stats_read(struct file *file,
+                                       char __user *user_buf, size_t count,
+                                       loff_t *ppos);
+#endif
+
+#endif
similarity index 55%
rename from drivers/net/wireless/iwlegacy/iwl-4965-calib.c
rename to drivers/net/wireless/iwlegacy/4965-calib.c
index 162d877e6869ce4c4991074b9da24512f2d50eb6..d3248e3ef23bb6c917e709f56c90c11c93ca1482 100644 (file)
 #include <linux/slab.h>
 #include <net/mac80211.h>
 
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-4965-calib.h"
+#include "common.h"
+#include "4965.h"
 
 /*****************************************************************************
  * INIT calibrations framework
  *****************************************************************************/
 
-struct statistics_general_data {
+struct stats_general_data {
        u32 beacon_silence_rssi_a;
        u32 beacon_silence_rssi_b;
        u32 beacon_silence_rssi_c;
@@ -80,14 +79,15 @@ struct statistics_general_data {
        u32 beacon_energy_c;
 };
 
-void iwl4965_calib_free_results(struct iwl_priv *priv)
+void
+il4965_calib_free_results(struct il_priv *il)
 {
        int i;
 
-       for (i = 0; i < IWL_CALIB_MAX; i++) {
-               kfree(priv->calib_results[i].buf);
-               priv->calib_results[i].buf = NULL;
-               priv->calib_results[i].buf_len = 0;
+       for (i = 0; i < IL_CALIB_MAX; i++) {
+               kfree(il->calib_results[i].buf);
+               il->calib_results[i].buf = NULL;
+               il->calib_results[i].buf_len = 0;
        }
 }
 
@@ -103,10 +103,9 @@ void iwl4965_calib_free_results(struct iwl_priv *priv)
  *   enough to receive all of our own network traffic, but not so
  *   high that our DSP gets too busy trying to lock onto non-network
  *   activity/noise. */
-static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
-                                  u32 norm_fa,
-                                  u32 rx_enable_time,
-                                  struct statistics_general_data *rx_info)
+static int
+il4965_sens_energy_cck(struct il_priv *il, u32 norm_fa, u32 rx_enable_time,
+                      struct stats_general_data *rx_info)
 {
        u32 max_nrg_cck = 0;
        int i = 0;
@@ -129,22 +128,22 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
        u32 false_alarms = norm_fa * 200 * 1024;
        u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
        u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
-       struct iwl_sensitivity_data *data = NULL;
-       const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+       struct il_sensitivity_data *data = NULL;
+       const struct il_sensitivity_ranges *ranges = il->hw_params.sens;
 
-       data = &(priv->sensitivity_data);
+       data = &(il->sensitivity_data);
 
        data->nrg_auto_corr_silence_diff = 0;
 
        /* Find max silence rssi among all 3 receivers.
         * This is background noise, which may include transmissions from other
         *    networks, measured during silence before our network's beacon */
-       silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a &
-                           ALL_BAND_FILTER) >> 8);
-       silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b &
-                           ALL_BAND_FILTER) >> 8);
-       silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c &
-                           ALL_BAND_FILTER) >> 8);
+       silence_rssi_a =
+           (u8) ((rx_info->beacon_silence_rssi_a & ALL_BAND_FILTER) >> 8);
+       silence_rssi_b =
+           (u8) ((rx_info->beacon_silence_rssi_b & ALL_BAND_FILTER) >> 8);
+       silence_rssi_c =
+           (u8) ((rx_info->beacon_silence_rssi_c & ALL_BAND_FILTER) >> 8);
 
        val = max(silence_rssi_b, silence_rssi_c);
        max_silence_rssi = max(silence_rssi_a, (u8) val);
@@ -160,9 +159,8 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
                val = data->nrg_silence_rssi[i];
                silence_ref = max(silence_ref, val);
        }
-       IWL_DEBUG_CALIB(priv, "silence a %u, b %u, c %u, 20-bcn max %u\n",
-                       silence_rssi_a, silence_rssi_b, silence_rssi_c,
-                       silence_ref);
+       D_CALIB("silence a %u, b %u, c %u, 20-bcn max %u\n", silence_rssi_a,
+               silence_rssi_b, silence_rssi_c, silence_ref);
 
        /* Find max rx energy (min value!) among all 3 receivers,
         *   measured during beacon frame.
@@ -184,9 +182,9 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
                max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i]));
        max_nrg_cck += 6;
 
-       IWL_DEBUG_CALIB(priv, "rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
-                       rx_info->beacon_energy_a, rx_info->beacon_energy_b,
-                       rx_info->beacon_energy_c, max_nrg_cck - 6);
+       D_CALIB("rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
+               rx_info->beacon_energy_a, rx_info->beacon_energy_b,
+               rx_info->beacon_energy_c, max_nrg_cck - 6);
 
        /* Count number of consecutive beacons with fewer-than-desired
         *   false alarms. */
@@ -194,35 +192,34 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
                data->num_in_cck_no_fa++;
        else
                data->num_in_cck_no_fa = 0;
-       IWL_DEBUG_CALIB(priv, "consecutive bcns with few false alarms = %u\n",
-                       data->num_in_cck_no_fa);
+       D_CALIB("consecutive bcns with few false alarms = %u\n",
+               data->num_in_cck_no_fa);
 
        /* If we got too many false alarms this time, reduce sensitivity */
-       if ((false_alarms > max_false_alarms) &&
-               (data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK)) {
-               IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u\n",
-                    false_alarms, max_false_alarms);
-               IWL_DEBUG_CALIB(priv, "... reducing sensitivity\n");
-               data->nrg_curr_state = IWL_FA_TOO_MANY;
+       if (false_alarms > max_false_alarms &&
+           data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK) {
+               D_CALIB("norm FA %u > max FA %u\n", false_alarms,
+                       max_false_alarms);
+               D_CALIB("... reducing sensitivity\n");
+               data->nrg_curr_state = IL_FA_TOO_MANY;
                /* Store for "fewer than desired" on later beacon */
                data->nrg_silence_ref = silence_ref;
 
                /* increase energy threshold (reduce nrg value)
                 *   to decrease sensitivity */
                data->nrg_th_cck = data->nrg_th_cck - NRG_STEP_CCK;
-       /* Else if we got fewer than desired, increase sensitivity */
+               /* Else if we got fewer than desired, increase sensitivity */
        } else if (false_alarms < min_false_alarms) {
-               data->nrg_curr_state = IWL_FA_TOO_FEW;
+               data->nrg_curr_state = IL_FA_TOO_FEW;
 
                /* Compare silence level with silence level for most recent
                 *   healthy number or too many false alarms */
-               data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref -
-                                                  (s32)silence_ref;
+               data->nrg_auto_corr_silence_diff =
+                   (s32) data->nrg_silence_ref - (s32) silence_ref;
 
-               IWL_DEBUG_CALIB(priv,
-                        "norm FA %u < min FA %u, silence diff %d\n",
-                        false_alarms, min_false_alarms,
-                        data->nrg_auto_corr_silence_diff);
+               D_CALIB("norm FA %u < min FA %u, silence diff %d\n",
+                       false_alarms, min_false_alarms,
+                       data->nrg_auto_corr_silence_diff);
 
                /* Increase value to increase sensitivity, but only if:
                 * 1a) previous beacon did *not* have *too many* false alarms
@@ -230,23 +227,22 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
                 *      from a previous beacon with too many, or healthy # FAs
                 * OR 2) We've seen a lot of beacons (100) with too few
                 *       false alarms */
-               if ((data->nrg_prev_state != IWL_FA_TOO_MANY) &&
-                       ((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
-                       (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
+               if (data->nrg_prev_state != IL_FA_TOO_MANY &&
+                   (data->nrg_auto_corr_silence_diff > NRG_DIFF ||
+                    data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA)) {
 
-                       IWL_DEBUG_CALIB(priv, "... increasing sensitivity\n");
+                       D_CALIB("... increasing sensitivity\n");
                        /* Increase nrg value to increase sensitivity */
                        val = data->nrg_th_cck + NRG_STEP_CCK;
-                       data->nrg_th_cck = min((u32)ranges->min_nrg_cck, val);
+                       data->nrg_th_cck = min((u32) ranges->min_nrg_cck, val);
                } else {
-                       IWL_DEBUG_CALIB(priv,
-                                        "... but not changing sensitivity\n");
+                       D_CALIB("... but not changing sensitivity\n");
                }
 
-       /* Else we got a healthy number of false alarms, keep status quo */
+               /* Else we got a healthy number of false alarms, keep status quo */
        } else {
-               IWL_DEBUG_CALIB(priv, " FA in safe zone\n");
-               data->nrg_curr_state = IWL_FA_GOOD_RANGE;
+               D_CALIB(" FA in safe zone\n");
+               data->nrg_curr_state = IL_FA_GOOD_RANGE;
 
                /* Store for use in "fewer than desired" with later beacon */
                data->nrg_silence_ref = silence_ref;
@@ -254,8 +250,8 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
                /* If previous beacon had too many false alarms,
                 *   give it some extra margin by reducing sensitivity again
                 *   (but don't go below measured energy of desired Rx) */
-               if (IWL_FA_TOO_MANY == data->nrg_prev_state) {
-                       IWL_DEBUG_CALIB(priv, "... increasing margin\n");
+               if (IL_FA_TOO_MANY == data->nrg_prev_state) {
+                       D_CALIB("... increasing margin\n");
                        if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN))
                                data->nrg_th_cck -= NRG_MARGIN;
                        else
@@ -269,7 +265,7 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
         * Lower value is higher energy, so we use max()!
         */
        data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck);
-       IWL_DEBUG_CALIB(priv, "new nrg_th_cck %u\n", data->nrg_th_cck);
+       D_CALIB("new nrg_th_cck %u\n", data->nrg_th_cck);
 
        data->nrg_prev_state = data->nrg_curr_state;
 
@@ -284,190 +280,187 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
                else {
                        val = data->auto_corr_cck + AUTO_CORR_STEP_CCK;
                        data->auto_corr_cck =
-                               min((u32)ranges->auto_corr_max_cck, val);
+                           min((u32) ranges->auto_corr_max_cck, val);
                }
                val = data->auto_corr_cck_mrc + AUTO_CORR_STEP_CCK;
                data->auto_corr_cck_mrc =
-                       min((u32)ranges->auto_corr_max_cck_mrc, val);
-       } else if ((false_alarms < min_false_alarms) &&
-          ((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
-          (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
+                   min((u32) ranges->auto_corr_max_cck_mrc, val);
+       } else if (false_alarms < min_false_alarms &&
+                  (data->nrg_auto_corr_silence_diff > NRG_DIFF ||
+                   data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA)) {
 
                /* Decrease auto_corr values to increase sensitivity */
                val = data->auto_corr_cck - AUTO_CORR_STEP_CCK;
-               data->auto_corr_cck =
-                       max((u32)ranges->auto_corr_min_cck, val);
+               data->auto_corr_cck = max((u32) ranges->auto_corr_min_cck, val);
                val = data->auto_corr_cck_mrc - AUTO_CORR_STEP_CCK;
                data->auto_corr_cck_mrc =
-                       max((u32)ranges->auto_corr_min_cck_mrc, val);
+                   max((u32) ranges->auto_corr_min_cck_mrc, val);
        }
 
        return 0;
 }
 
-
-static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv,
-                                      u32 norm_fa,
-                                      u32 rx_enable_time)
+static int
+il4965_sens_auto_corr_ofdm(struct il_priv *il, u32 norm_fa, u32 rx_enable_time)
 {
        u32 val;
        u32 false_alarms = norm_fa * 200 * 1024;
        u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
        u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
-       struct iwl_sensitivity_data *data = NULL;
-       const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+       struct il_sensitivity_data *data = NULL;
+       const struct il_sensitivity_ranges *ranges = il->hw_params.sens;
 
-       data = &(priv->sensitivity_data);
+       data = &(il->sensitivity_data);
 
        /* If we got too many false alarms this time, reduce sensitivity */
        if (false_alarms > max_false_alarms) {
 
-               IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u)\n",
-                            false_alarms, max_false_alarms);
+               D_CALIB("norm FA %u > max FA %u)\n", false_alarms,
+                       max_false_alarms);
 
                val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM;
                data->auto_corr_ofdm =
-                       min((u32)ranges->auto_corr_max_ofdm, val);
+                   min((u32) ranges->auto_corr_max_ofdm, val);
 
                val = data->auto_corr_ofdm_mrc + AUTO_CORR_STEP_OFDM;
                data->auto_corr_ofdm_mrc =
-                       min((u32)ranges->auto_corr_max_ofdm_mrc, val);
+                   min((u32) ranges->auto_corr_max_ofdm_mrc, val);
 
                val = data->auto_corr_ofdm_x1 + AUTO_CORR_STEP_OFDM;
                data->auto_corr_ofdm_x1 =
-                       min((u32)ranges->auto_corr_max_ofdm_x1, val);
+                   min((u32) ranges->auto_corr_max_ofdm_x1, val);
 
                val = data->auto_corr_ofdm_mrc_x1 + AUTO_CORR_STEP_OFDM;
                data->auto_corr_ofdm_mrc_x1 =
-                       min((u32)ranges->auto_corr_max_ofdm_mrc_x1, val);
+                   min((u32) ranges->auto_corr_max_ofdm_mrc_x1, val);
        }
 
        /* Else if we got fewer than desired, increase sensitivity */
        else if (false_alarms < min_false_alarms) {
 
-               IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u\n",
-                            false_alarms, min_false_alarms);
+               D_CALIB("norm FA %u < min FA %u\n", false_alarms,
+                       min_false_alarms);
 
                val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM;
                data->auto_corr_ofdm =
-                       max((u32)ranges->auto_corr_min_ofdm, val);
+                   max((u32) ranges->auto_corr_min_ofdm, val);
 
                val = data->auto_corr_ofdm_mrc - AUTO_CORR_STEP_OFDM;
                data->auto_corr_ofdm_mrc =
-                       max((u32)ranges->auto_corr_min_ofdm_mrc, val);
+                   max((u32) ranges->auto_corr_min_ofdm_mrc, val);
 
                val = data->auto_corr_ofdm_x1 - AUTO_CORR_STEP_OFDM;
                data->auto_corr_ofdm_x1 =
-                       max((u32)ranges->auto_corr_min_ofdm_x1, val);
+                   max((u32) ranges->auto_corr_min_ofdm_x1, val);
 
                val = data->auto_corr_ofdm_mrc_x1 - AUTO_CORR_STEP_OFDM;
                data->auto_corr_ofdm_mrc_x1 =
-                       max((u32)ranges->auto_corr_min_ofdm_mrc_x1, val);
+                   max((u32) ranges->auto_corr_min_ofdm_mrc_x1, val);
        } else {
-               IWL_DEBUG_CALIB(priv, "min FA %u < norm FA %u < max FA %u OK\n",
-                        min_false_alarms, false_alarms, max_false_alarms);
+               D_CALIB("min FA %u < norm FA %u < max FA %u OK\n",
+                       min_false_alarms, false_alarms, max_false_alarms);
        }
        return 0;
 }
 
-static void iwl4965_prepare_legacy_sensitivity_tbl(struct iwl_priv *priv,
-                               struct iwl_sensitivity_data *data,
-                               __le16 *tbl)
+static void
+il4965_prepare_legacy_sensitivity_tbl(struct il_priv *il,
+                                     struct il_sensitivity_data *data,
+                                     __le16 *tbl)
 {
-       tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] =
-                               cpu_to_le16((u16)data->auto_corr_ofdm);
-       tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] =
-                               cpu_to_le16((u16)data->auto_corr_ofdm_mrc);
-       tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] =
-                               cpu_to_le16((u16)data->auto_corr_ofdm_x1);
-       tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] =
-                               cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1);
-
-       tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] =
-                               cpu_to_le16((u16)data->auto_corr_cck);
-       tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] =
-                               cpu_to_le16((u16)data->auto_corr_cck_mrc);
-
-       tbl[HD_MIN_ENERGY_CCK_DET_INDEX] =
-                               cpu_to_le16((u16)data->nrg_th_cck);
-       tbl[HD_MIN_ENERGY_OFDM_DET_INDEX] =
-                               cpu_to_le16((u16)data->nrg_th_ofdm);
-
-       tbl[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
-                               cpu_to_le16(data->barker_corr_th_min);
-       tbl[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
-                               cpu_to_le16(data->barker_corr_th_min_mrc);
-       tbl[HD_OFDM_ENERGY_TH_IN_INDEX] =
-                               cpu_to_le16(data->nrg_th_cca);
-
-       IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
-                       data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
-                       data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1,
-                       data->nrg_th_ofdm);
-
-       IWL_DEBUG_CALIB(priv, "cck: ac %u mrc %u thresh %u\n",
-                       data->auto_corr_cck, data->auto_corr_cck_mrc,
-                       data->nrg_th_cck);
+       tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_IDX] =
+           cpu_to_le16((u16) data->auto_corr_ofdm);
+       tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX] =
+           cpu_to_le16((u16) data->auto_corr_ofdm_mrc);
+       tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_IDX] =
+           cpu_to_le16((u16) data->auto_corr_ofdm_x1);
+       tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX] =
+           cpu_to_le16((u16) data->auto_corr_ofdm_mrc_x1);
+
+       tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_IDX] =
+           cpu_to_le16((u16) data->auto_corr_cck);
+       tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX] =
+           cpu_to_le16((u16) data->auto_corr_cck_mrc);
+
+       tbl[HD_MIN_ENERGY_CCK_DET_IDX] = cpu_to_le16((u16) data->nrg_th_cck);
+       tbl[HD_MIN_ENERGY_OFDM_DET_IDX] = cpu_to_le16((u16) data->nrg_th_ofdm);
+
+       tbl[HD_BARKER_CORR_TH_ADD_MIN_IDX] =
+           cpu_to_le16(data->barker_corr_th_min);
+       tbl[HD_BARKER_CORR_TH_ADD_MIN_MRC_IDX] =
+           cpu_to_le16(data->barker_corr_th_min_mrc);
+       tbl[HD_OFDM_ENERGY_TH_IN_IDX] = cpu_to_le16(data->nrg_th_cca);
+
+       D_CALIB("ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
+               data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
+               data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1,
+               data->nrg_th_ofdm);
+
+       D_CALIB("cck: ac %u mrc %u thresh %u\n", data->auto_corr_cck,
+               data->auto_corr_cck_mrc, data->nrg_th_cck);
 }
 
-/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
-static int iwl4965_sensitivity_write(struct iwl_priv *priv)
+/* Prepare a C_SENSITIVITY, send to uCode if values have changed */
+static int
+il4965_sensitivity_write(struct il_priv *il)
 {
-       struct iwl_sensitivity_cmd cmd;
-       struct iwl_sensitivity_data *data = NULL;
-       struct iwl_host_cmd cmd_out = {
-               .id = SENSITIVITY_CMD,
-               .len = sizeof(struct iwl_sensitivity_cmd),
+       struct il_sensitivity_cmd cmd;
+       struct il_sensitivity_data *data = NULL;
+       struct il_host_cmd cmd_out = {
+               .id = C_SENSITIVITY,
+               .len = sizeof(struct il_sensitivity_cmd),
                .flags = CMD_ASYNC,
                .data = &cmd,
        };
 
-       data = &(priv->sensitivity_data);
+       data = &(il->sensitivity_data);
 
        memset(&cmd, 0, sizeof(cmd));
 
-       iwl4965_prepare_legacy_sensitivity_tbl(priv, data, &cmd.table[0]);
+       il4965_prepare_legacy_sensitivity_tbl(il, data, &cmd.table[0]);
 
        /* Update uCode's "work" table, and copy it to DSP */
-       cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
+       cmd.control = C_SENSITIVITY_CONTROL_WORK_TBL;
 
        /* Don't send command to uCode if nothing has changed */
-       if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]),
-                   sizeof(u16)*HD_TABLE_SIZE)) {
-               IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n");
+       if (!memcmp
+           (&cmd.table[0], &(il->sensitivity_tbl[0]),
+            sizeof(u16) * HD_TBL_SIZE)) {
+               D_CALIB("No change in C_SENSITIVITY\n");
                return 0;
        }
 
        /* Copy table for comparison next time */
-       memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
-              sizeof(u16)*HD_TABLE_SIZE);
+       memcpy(&(il->sensitivity_tbl[0]), &(cmd.table[0]),
+              sizeof(u16) * HD_TBL_SIZE);
 
-       return iwl_legacy_send_cmd(priv, &cmd_out);
+       return il_send_cmd(il, &cmd_out);
 }
 
-void iwl4965_init_sensitivity(struct iwl_priv *priv)
+void
+il4965_init_sensitivity(struct il_priv *il)
 {
        int ret = 0;
        int i;
-       struct iwl_sensitivity_data *data = NULL;
-       const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+       struct il_sensitivity_data *data = NULL;
+       const struct il_sensitivity_ranges *ranges = il->hw_params.sens;
 
-       if (priv->disable_sens_cal)
+       if (il->disable_sens_cal)
                return;
 
-       IWL_DEBUG_CALIB(priv, "Start iwl4965_init_sensitivity\n");
+       D_CALIB("Start il4965_init_sensitivity\n");
 
        /* Clear driver's sensitivity algo data */
-       data = &(priv->sensitivity_data);
+       data = &(il->sensitivity_data);
 
        if (ranges == NULL)
                return;
 
-       memset(data, 0, sizeof(struct iwl_sensitivity_data));
+       memset(data, 0, sizeof(struct il_sensitivity_data));
 
        data->num_in_cck_no_fa = 0;
-       data->nrg_curr_state = IWL_FA_TOO_MANY;
-       data->nrg_prev_state = IWL_FA_TOO_MANY;
+       data->nrg_curr_state = IL_FA_TOO_MANY;
+       data->nrg_prev_state = IL_FA_TOO_MANY;
        data->nrg_silence_ref = 0;
        data->nrg_silence_idx = 0;
        data->nrg_energy_idx = 0;
@@ -478,9 +471,9 @@ void iwl4965_init_sensitivity(struct iwl_priv *priv)
        for (i = 0; i < NRG_NUM_PREV_STAT_L; i++)
                data->nrg_silence_rssi[i] = 0;
 
-       data->auto_corr_ofdm =  ranges->auto_corr_min_ofdm;
+       data->auto_corr_ofdm = ranges->auto_corr_min_ofdm;
        data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc;
-       data->auto_corr_ofdm_x1  = ranges->auto_corr_min_ofdm_x1;
+       data->auto_corr_ofdm_x1 = ranges->auto_corr_min_ofdm_x1;
        data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1;
        data->auto_corr_cck = AUTO_CORR_CCK_MIN_VAL_DEF;
        data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc;
@@ -495,11 +488,12 @@ void iwl4965_init_sensitivity(struct iwl_priv *priv)
        data->last_bad_plcp_cnt_cck = 0;
        data->last_fa_cnt_cck = 0;
 
-       ret |= iwl4965_sensitivity_write(priv);
-       IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
+       ret |= il4965_sensitivity_write(il);
+       D_CALIB("<<return 0x%X\n", ret);
 }
 
-void iwl4965_sensitivity_calibration(struct iwl_priv *priv, void *resp)
+void
+il4965_sensitivity_calibration(struct il_priv *il, void *resp)
 {
        u32 rx_enable_time;
        u32 fa_cck;
@@ -508,31 +502,31 @@ void iwl4965_sensitivity_calibration(struct iwl_priv *priv, void *resp)
        u32 bad_plcp_ofdm;
        u32 norm_fa_ofdm;
        u32 norm_fa_cck;
-       struct iwl_sensitivity_data *data = NULL;
-       struct statistics_rx_non_phy *rx_info;
-       struct statistics_rx_phy *ofdm, *cck;
+       struct il_sensitivity_data *data = NULL;
+       struct stats_rx_non_phy *rx_info;
+       struct stats_rx_phy *ofdm, *cck;
        unsigned long flags;
-       struct statistics_general_data statis;
+       struct stats_general_data statis;
 
-       if (priv->disable_sens_cal)
+       if (il->disable_sens_cal)
                return;
 
-       data = &(priv->sensitivity_data);
+       data = &(il->sensitivity_data);
 
-       if (!iwl_legacy_is_any_associated(priv)) {
-               IWL_DEBUG_CALIB(priv, "<< - not associated\n");
+       if (!il_is_any_associated(il)) {
+               D_CALIB("<< - not associated\n");
                return;
        }
 
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irqsave(&il->lock, flags);
 
-       rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general);
-       ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm);
-       cck = &(((struct iwl_notif_statistics *)resp)->rx.cck);
+       rx_info = &(((struct il_notif_stats *)resp)->rx.general);
+       ofdm = &(((struct il_notif_stats *)resp)->rx.ofdm);
+       cck = &(((struct il_notif_stats *)resp)->rx.cck);
 
        if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
-               IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
-               spin_unlock_irqrestore(&priv->lock, flags);
+               D_CALIB("<< invalid data.\n");
+               spin_unlock_irqrestore(&il->lock, flags);
                return;
        }
 
@@ -544,30 +538,27 @@ void iwl4965_sensitivity_calibration(struct iwl_priv *priv, void *resp)
        bad_plcp_ofdm = le32_to_cpu(ofdm->plcp_err);
 
        statis.beacon_silence_rssi_a =
-                       le32_to_cpu(rx_info->beacon_silence_rssi_a);
+           le32_to_cpu(rx_info->beacon_silence_rssi_a);
        statis.beacon_silence_rssi_b =
-                       le32_to_cpu(rx_info->beacon_silence_rssi_b);
+           le32_to_cpu(rx_info->beacon_silence_rssi_b);
        statis.beacon_silence_rssi_c =
-                       le32_to_cpu(rx_info->beacon_silence_rssi_c);
-       statis.beacon_energy_a =
-                       le32_to_cpu(rx_info->beacon_energy_a);
-       statis.beacon_energy_b =
-                       le32_to_cpu(rx_info->beacon_energy_b);
-       statis.beacon_energy_c =
-                       le32_to_cpu(rx_info->beacon_energy_c);
+           le32_to_cpu(rx_info->beacon_silence_rssi_c);
+       statis.beacon_energy_a = le32_to_cpu(rx_info->beacon_energy_a);
+       statis.beacon_energy_b = le32_to_cpu(rx_info->beacon_energy_b);
+       statis.beacon_energy_c = le32_to_cpu(rx_info->beacon_energy_c);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&il->lock, flags);
 
-       IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
+       D_CALIB("rx_enable_time = %u usecs\n", rx_enable_time);
 
        if (!rx_enable_time) {
-               IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n");
+               D_CALIB("<< RX Enable Time == 0!\n");
                return;
        }
 
-       /* These statistics increase monotonically, and do not reset
+       /* These stats increase monotonically, and do not reset
         *   at each beacon.  Calculate difference from last value, or just
-        *   use the new statistics value if it has reset or wrapped around. */
+        *   use the new stats value if it has reset or wrapped around. */
        if (data->last_bad_plcp_cnt_cck > bad_plcp_cck)
                data->last_bad_plcp_cnt_cck = bad_plcp_cck;
        else {
@@ -600,17 +591,17 @@ void iwl4965_sensitivity_calibration(struct iwl_priv *priv, void *resp)
        norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm;
        norm_fa_cck = fa_cck + bad_plcp_cck;
 
-       IWL_DEBUG_CALIB(priv,
-                        "cck: fa %u badp %u  ofdm: fa %u badp %u\n", fa_cck,
-                       bad_plcp_cck, fa_ofdm, bad_plcp_ofdm);
+       D_CALIB("cck: fa %u badp %u  ofdm: fa %u badp %u\n", fa_cck,
+               bad_plcp_cck, fa_ofdm, bad_plcp_ofdm);
 
-       iwl4965_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
-       iwl4965_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
+       il4965_sens_auto_corr_ofdm(il, norm_fa_ofdm, rx_enable_time);
+       il4965_sens_energy_cck(il, norm_fa_cck, rx_enable_time, &statis);
 
-       iwl4965_sensitivity_write(priv);
+       il4965_sensitivity_write(il);
 }
 
-static inline u8 iwl4965_find_first_chain(u8 mask)
+static inline u8
+il4965_find_first_chain(u8 mask)
 {
        if (mask & ANT_A)
                return CHAIN_A;
@@ -624,8 +615,8 @@ static inline u8 iwl4965_find_first_chain(u8 mask)
  * disconnected.
  */
 static void
-iwl4965_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
-                                    struct iwl_chain_noise_data *data)
+il4965_find_disconn_antenna(struct il_priv *il, u32 * average_sig,
+                           struct il_chain_noise_data *data)
 {
        u32 active_chains = 0;
        u32 max_average_sig;
@@ -634,12 +625,15 @@ iwl4965_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
        u8 first_chain;
        u16 i = 0;
 
-       average_sig[0] = data->chain_signal_a /
-                        priv->cfg->base_params->chain_noise_num_beacons;
-       average_sig[1] = data->chain_signal_b /
-                        priv->cfg->base_params->chain_noise_num_beacons;
-       average_sig[2] = data->chain_signal_c /
-                        priv->cfg->base_params->chain_noise_num_beacons;
+       average_sig[0] =
+           data->chain_signal_a /
+           il->cfg->base_params->chain_noise_num_beacons;
+       average_sig[1] =
+           data->chain_signal_b /
+           il->cfg->base_params->chain_noise_num_beacons;
+       average_sig[2] =
+           data->chain_signal_c /
+           il->cfg->base_params->chain_noise_num_beacons;
 
        if (average_sig[0] >= average_sig[1]) {
                max_average_sig = average_sig[0];
@@ -657,10 +651,10 @@ iwl4965_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
                active_chains = (1 << max_average_sig_antenna_i);
        }
 
-       IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
-                    average_sig[0], average_sig[1], average_sig[2]);
-       IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
-                    max_average_sig, max_average_sig_antenna_i);
+       D_CALIB("average_sig: a %d b %d c %d\n", average_sig[0], average_sig[1],
+               average_sig[2]);
+       D_CALIB("max_average_sig = %d, antenna %d\n", max_average_sig,
+               max_average_sig_antenna_i);
 
        /* Compare signal strengths for all 3 receivers. */
        for (i = 0; i < NUM_RX_CHAINS; i++) {
@@ -673,9 +667,9 @@ iwl4965_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
                                data->disconn_array[i] = 1;
                        else
                                active_chains |= (1 << i);
-                       IWL_DEBUG_CALIB(priv, "i = %d  rssiDelta = %d  "
-                            "disconn_array[i] = %d\n",
-                            i, rssi_delta, data->disconn_array[i]);
+                       D_CALIB("i = %d  rssiDelta = %d  "
+                               "disconn_array[i] = %d\n", i, rssi_delta,
+                               data->disconn_array[i]);
                }
        }
 
@@ -689,119 +683,110 @@ iwl4965_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
         * To be safe, simply mask out any chains that we know
         * are not on the device.
         */
-       active_chains &= priv->hw_params.valid_rx_ant;
+       active_chains &= il->hw_params.valid_rx_ant;
 
        num_tx_chains = 0;
        for (i = 0; i < NUM_RX_CHAINS; i++) {
                /* loops on all the bits of
-                * priv->hw_setting.valid_tx_ant */
+                * il->hw_setting.valid_tx_ant */
                u8 ant_msk = (1 << i);
-               if (!(priv->hw_params.valid_tx_ant & ant_msk))
+               if (!(il->hw_params.valid_tx_ant & ant_msk))
                        continue;
 
                num_tx_chains++;
                if (data->disconn_array[i] == 0)
                        /* there is a Tx antenna connected */
                        break;
-               if (num_tx_chains == priv->hw_params.tx_chains_num &&
+               if (num_tx_chains == il->hw_params.tx_chains_num &&
                    data->disconn_array[i]) {
                        /*
                         * If all chains are disconnected
                         * connect the first valid tx chain
                         */
                        first_chain =
-                       iwl4965_find_first_chain(priv->cfg->valid_tx_ant);
+                           il4965_find_first_chain(il->cfg->valid_tx_ant);
                        data->disconn_array[first_chain] = 0;
                        active_chains |= BIT(first_chain);
-                       IWL_DEBUG_CALIB(priv,
-                                       "All Tx chains are disconnected W/A - declare %d as connected\n",
-                                       first_chain);
+                       D_CALIB("All Tx chains are disconnected"
+                               "- declare %d as connected\n", first_chain);
                        break;
                }
        }
 
-       if (active_chains != priv->hw_params.valid_rx_ant &&
-           active_chains != priv->chain_noise_data.active_chains)
-               IWL_DEBUG_CALIB(priv,
-                               "Detected that not all antennas are connected! "
-                               "Connected: %#x, valid: %#x.\n",
-                               active_chains, priv->hw_params.valid_rx_ant);
+       if (active_chains != il->hw_params.valid_rx_ant &&
+           active_chains != il->chain_noise_data.active_chains)
+               D_CALIB("Detected that not all antennas are connected! "
+                       "Connected: %#x, valid: %#x.\n", active_chains,
+                       il->hw_params.valid_rx_ant);
 
        /* Save for use within RXON, TX, SCAN commands, etc. */
        data->active_chains = active_chains;
-       IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
-                       active_chains);
+       D_CALIB("active_chains (bitwise) = 0x%x\n", active_chains);
 }
 
-static void iwl4965_gain_computation(struct iwl_priv *priv,
-               u32 *average_noise,
-               u16 min_average_noise_antenna_i,
-               u32 min_average_noise,
-               u8 default_chain)
+static void
+il4965_gain_computation(struct il_priv *il, u32 * average_noise,
+                       u16 min_average_noise_antenna_i, u32 min_average_noise,
+                       u8 default_chain)
 {
        int i, ret;
-       struct iwl_chain_noise_data *data = &priv->chain_noise_data;
+       struct il_chain_noise_data *data = &il->chain_noise_data;
 
        data->delta_gain_code[min_average_noise_antenna_i] = 0;
 
        for (i = default_chain; i < NUM_RX_CHAINS; i++) {
                s32 delta_g = 0;
 
-               if (!(data->disconn_array[i]) &&
-                   (data->delta_gain_code[i] ==
-                            CHAIN_NOISE_DELTA_GAIN_INIT_VAL)) {
+               if (!data->disconn_array[i] &&
+                   data->delta_gain_code[i] ==
+                   CHAIN_NOISE_DELTA_GAIN_INIT_VAL) {
                        delta_g = average_noise[i] - min_average_noise;
-                       data->delta_gain_code[i] = (u8)((delta_g * 10) / 15);
+                       data->delta_gain_code[i] = (u8) ((delta_g * 10) / 15);
                        data->delta_gain_code[i] =
-                               min(data->delta_gain_code[i],
+                           min(data->delta_gain_code[i],
                                (u8) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
 
                        data->delta_gain_code[i] =
-                               (data->delta_gain_code[i] | (1 << 2));
+                           (data->delta_gain_code[i] | (1 << 2));
                } else {
                        data->delta_gain_code[i] = 0;
                }
        }
-       IWL_DEBUG_CALIB(priv, "delta_gain_codes: a %d b %d c %d\n",
-                    data->delta_gain_code[0],
-                    data->delta_gain_code[1],
-                    data->delta_gain_code[2]);
+       D_CALIB("delta_gain_codes: a %d b %d c %d\n", data->delta_gain_code[0],
+               data->delta_gain_code[1], data->delta_gain_code[2]);
 
        /* Differential gain gets sent to uCode only once */
        if (!data->radio_write) {
-               struct iwl_calib_diff_gain_cmd cmd;
+               struct il_calib_diff_gain_cmd cmd;
                data->radio_write = 1;
 
                memset(&cmd, 0, sizeof(cmd));
-               cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
+               cmd.hdr.op_code = IL_PHY_CALIBRATE_DIFF_GAIN_CMD;
                cmd.diff_gain_a = data->delta_gain_code[0];
                cmd.diff_gain_b = data->delta_gain_code[1];
                cmd.diff_gain_c = data->delta_gain_code[2];
-               ret = iwl_legacy_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-                                     sizeof(cmd), &cmd);
+               ret = il_send_cmd_pdu(il, C_PHY_CALIBRATION, sizeof(cmd), &cmd);
                if (ret)
-                       IWL_DEBUG_CALIB(priv, "fail sending cmd "
-                                    "REPLY_PHY_CALIBRATION_CMD\n");
+                       D_CALIB("fail sending cmd " "C_PHY_CALIBRATION\n");
 
                /* TODO we might want recalculate
                 * rx_chain in rxon cmd */
 
                /* Mark so we run this algo only once! */
-               data->state = IWL_CHAIN_NOISE_CALIBRATED;
+               data->state = IL_CHAIN_NOISE_CALIBRATED;
        }
 }
 
-
-
 /*
- * Accumulate 16 beacons of signal and noise statistics for each of
+ * Accumulate 16 beacons of signal and noise stats for each of
  *   3 receivers/antennas/rx-chains, then figure out:
  * 1)  Which antennas are connected.
  * 2)  Differential rx gain settings to balance the 3 receivers.
  */
-void iwl4965_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
+void
+il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp)
 {
-       struct iwl_chain_noise_data *data = NULL;
+       struct il_chain_noise_data *data = NULL;
 
        u32 chain_noise_a;
        u32 chain_noise_b;
@@ -809,8 +794,8 @@ void iwl4965_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
        u32 chain_sig_a;
        u32 chain_sig_b;
        u32 chain_sig_c;
-       u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
-       u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
+       u32 average_sig[NUM_RX_CHAINS] = { INITIALIZATION_VALUE };
+       u32 average_noise[NUM_RX_CHAINS] = { INITIALIZATION_VALUE };
        u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
        u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
        u16 i = 0;
@@ -819,70 +804,69 @@ void iwl4965_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
        u8 rxon_band24;
        u8 stat_band24;
        unsigned long flags;
-       struct statistics_rx_non_phy *rx_info;
+       struct stats_rx_non_phy *rx_info;
 
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+       struct il_rxon_context *ctx = &il->ctx;
 
-       if (priv->disable_chain_noise_cal)
+       if (il->disable_chain_noise_cal)
                return;
 
-       data = &(priv->chain_noise_data);
+       data = &(il->chain_noise_data);
 
        /*
         * Accumulate just the first "chain_noise_num_beacons" after
         * the first association, then we're done forever.
         */
-       if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) {
-               if (data->state == IWL_CHAIN_NOISE_ALIVE)
-                       IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n");
+       if (data->state != IL_CHAIN_NOISE_ACCUMULATE) {
+               if (data->state == IL_CHAIN_NOISE_ALIVE)
+                       D_CALIB("Wait for noise calib reset\n");
                return;
        }
 
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irqsave(&il->lock, flags);
 
-       rx_info = &(((struct iwl_notif_statistics *)stat_resp)->
-                     rx.general);
+       rx_info = &(((struct il_notif_stats *)stat_resp)->rx.general);
 
        if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
-               IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
-               spin_unlock_irqrestore(&priv->lock, flags);
+               D_CALIB(" << Interference data unavailable\n");
+               spin_unlock_irqrestore(&il->lock, flags);
                return;
        }
 
        rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
        rxon_chnum = le16_to_cpu(ctx->staging.channel);
 
-       stat_band24 = !!(((struct iwl_notif_statistics *)
-                        stat_resp)->flag &
-                        STATISTICS_REPLY_FLG_BAND_24G_MSK);
-       stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *)
-                                stat_resp)->flag) >> 16;
+       stat_band24 =
+           !!(((struct il_notif_stats *)stat_resp)->
+              flag & STATS_REPLY_FLG_BAND_24G_MSK);
+       stat_chnum =
+           le32_to_cpu(((struct il_notif_stats *)stat_resp)->flag) >> 16;
 
        /* Make sure we accumulate data for just the associated channel
         *   (even if scanning). */
-       if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
-               IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
-                               rxon_chnum, rxon_band24);
-               spin_unlock_irqrestore(&priv->lock, flags);
+       if (rxon_chnum != stat_chnum || rxon_band24 != stat_band24) {
+               D_CALIB("Stats not from chan=%d, band24=%d\n", rxon_chnum,
+                       rxon_band24);
+               spin_unlock_irqrestore(&il->lock, flags);
                return;
        }
 
        /*
-        *  Accumulate beacon statistics values across
+        *  Accumulate beacon stats values across
         * "chain_noise_num_beacons"
         */
-       chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) &
-                               IN_BAND_FILTER;
-       chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) &
-                               IN_BAND_FILTER;
-       chain_noise_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) &
-                               IN_BAND_FILTER;
+       chain_noise_a =
+           le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
+       chain_noise_b =
+           le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
+       chain_noise_c =
+           le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
 
        chain_sig_a = le32_to_cpu(rx_info->beacon_rssi_a) & IN_BAND_FILTER;
        chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
        chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&il->lock, flags);
 
        data->beacon_count++;
 
@@ -894,34 +878,33 @@ void iwl4965_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
        data->chain_signal_b = (chain_sig_b + data->chain_signal_b);
        data->chain_signal_c = (chain_sig_c + data->chain_signal_c);
 
-       IWL_DEBUG_CALIB(priv, "chan=%d, band24=%d, beacon=%d\n",
-                       rxon_chnum, rxon_band24, data->beacon_count);
-       IWL_DEBUG_CALIB(priv, "chain_sig: a %d b %d c %d\n",
-                       chain_sig_a, chain_sig_b, chain_sig_c);
-       IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n",
-                       chain_noise_a, chain_noise_b, chain_noise_c);
+       D_CALIB("chan=%d, band24=%d, beacon=%d\n", rxon_chnum, rxon_band24,
+               data->beacon_count);
+       D_CALIB("chain_sig: a %d b %d c %d\n", chain_sig_a, chain_sig_b,
+               chain_sig_c);
+       D_CALIB("chain_noise: a %d b %d c %d\n", chain_noise_a, chain_noise_b,
+               chain_noise_c);
 
        /* If this is the "chain_noise_num_beacons", determine:
         * 1)  Disconnected antennas (using signal strengths)
         * 2)  Differential gain (using silence noise) to balance receivers */
-       if (data->beacon_count !=
-               priv->cfg->base_params->chain_noise_num_beacons)
+       if (data->beacon_count != il->cfg->base_params->chain_noise_num_beacons)
                return;
 
        /* Analyze signal for disconnected antenna */
-       iwl4965_find_disconn_antenna(priv, average_sig, data);
+       il4965_find_disconn_antenna(il, average_sig, data);
 
        /* Analyze noise for rx balance */
-       average_noise[0] = data->chain_noise_a /
-                          priv->cfg->base_params->chain_noise_num_beacons;
-       average_noise[1] = data->chain_noise_b /
-                          priv->cfg->base_params->chain_noise_num_beacons;
-       average_noise[2] = data->chain_noise_c /
-                          priv->cfg->base_params->chain_noise_num_beacons;
+       average_noise[0] =
+           data->chain_noise_a / il->cfg->base_params->chain_noise_num_beacons;
+       average_noise[1] =
+           data->chain_noise_b / il->cfg->base_params->chain_noise_num_beacons;
+       average_noise[2] =
+           data->chain_noise_c / il->cfg->base_params->chain_noise_num_beacons;
 
        for (i = 0; i < NUM_RX_CHAINS; i++) {
-               if (!(data->disconn_array[i]) &&
-                  (average_noise[i] <= min_average_noise)) {
+               if (!data->disconn_array[i] &&
+                   average_noise[i] <= min_average_noise) {
                        /* This means that chain i is active and has
                         * lower noise values so far: */
                        min_average_noise = average_noise[i];
@@ -929,39 +912,37 @@ void iwl4965_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
                }
        }
 
-       IWL_DEBUG_CALIB(priv, "average_noise: a %d b %d c %d\n",
-                       average_noise[0], average_noise[1],
-                       average_noise[2]);
+       D_CALIB("average_noise: a %d b %d c %d\n", average_noise[0],
+               average_noise[1], average_noise[2]);
 
-       IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",
-                       min_average_noise, min_average_noise_antenna_i);
+       D_CALIB("min_average_noise = %d, antenna %d\n", min_average_noise,
+               min_average_noise_antenna_i);
 
-       iwl4965_gain_computation(priv, average_noise,
-                       min_average_noise_antenna_i, min_average_noise,
-                       iwl4965_find_first_chain(priv->cfg->valid_rx_ant));
+       il4965_gain_computation(il, average_noise, min_average_noise_antenna_i,
+                               min_average_noise,
+                               il4965_find_first_chain(il->cfg->valid_rx_ant));
 
        /* Some power changes may have been made during the calibration.
         * Update and commit the RXON
         */
-       if (priv->cfg->ops->lib->update_chain_flags)
-               priv->cfg->ops->lib->update_chain_flags(priv);
+       if (il->cfg->ops->lib->update_chain_flags)
+               il->cfg->ops->lib->update_chain_flags(il);
 
-       data->state = IWL_CHAIN_NOISE_DONE;
-       iwl_legacy_power_update_mode(priv, false);
+       data->state = IL_CHAIN_NOISE_DONE;
+       il_power_update_mode(il, false);
 }
 
-void iwl4965_reset_run_time_calib(struct iwl_priv *priv)
+void
+il4965_reset_run_time_calib(struct il_priv *il)
 {
        int i;
-       memset(&(priv->sensitivity_data), 0,
-              sizeof(struct iwl_sensitivity_data));
-       memset(&(priv->chain_noise_data), 0,
-              sizeof(struct iwl_chain_noise_data));
+       memset(&(il->sensitivity_data), 0, sizeof(struct il_sensitivity_data));
+       memset(&(il->chain_noise_data), 0, sizeof(struct il_chain_noise_data));
        for (i = 0; i < NUM_RX_CHAINS; i++)
-               priv->chain_noise_data.delta_gain_code[i] =
-                               CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
+               il->chain_noise_data.delta_gain_code[i] =
+                   CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
 
-       /* Ask for statistics now, the uCode will send notification
+       /* Ask for stats now, the uCode will send notification
         * periodically after association */
-       iwl_legacy_send_statistics_request(priv, CMD_ASYNC, true);
+       il_send_stats_request(il, CMD_ASYNC, true);
 }
diff --git a/drivers/net/wireless/iwlegacy/4965-debug.c b/drivers/net/wireless/iwlegacy/4965-debug.c
new file mode 100644 (file)
index 0000000..98ec39f
--- /dev/null
@@ -0,0 +1,746 @@
+/******************************************************************************
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 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.GPL.
+*
+* Contact Information:
+*  Intel Linux Wireless <ilw@linux.intel.com>
+* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*****************************************************************************/
+#include "common.h"
+#include "4965.h"
+
+static const char *fmt_value = "  %-30s %10u\n";
+static const char *fmt_table = "  %-30s %10u  %10u  %10u  %10u\n";
+static const char *fmt_header =
+    "%-32s    current  cumulative       delta         max\n";
+
+static int
+il4965_stats_flag(struct il_priv *il, char *buf, int bufsz)
+{
+       int p = 0;
+       u32 flag;
+
+       flag = le32_to_cpu(il->_4965.stats.flag);
+
+       p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
+       if (flag & UCODE_STATS_CLEAR_MSK)
+               p += scnprintf(buf + p, bufsz - p,
+                              "\tStatistics have been cleared\n");
+       p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
+                      (flag & UCODE_STATS_FREQUENCY_MSK) ? "2.4 GHz" :
+                      "5.2 GHz");
+       p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
+                      (flag & UCODE_STATS_NARROW_BAND_MSK) ? "enabled" :
+                      "disabled");
+
+       return p;
+}
+
+ssize_t
+il4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+                          size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       char *buf;
+       int bufsz =
+           sizeof(struct stats_rx_phy) * 40 +
+           sizeof(struct stats_rx_non_phy) * 40 +
+           sizeof(struct stats_rx_ht_phy) * 40 + 400;
+       ssize_t ret;
+       struct stats_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
+       struct stats_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
+       struct stats_rx_non_phy *general, *accum_general;
+       struct stats_rx_non_phy *delta_general, *max_general;
+       struct stats_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
+
+       if (!il_is_alive(il))
+               return -EAGAIN;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       /*
+        * the statistic information display here is based on
+        * the last stats notification from uCode
+        * might not reflect the current uCode activity
+        */
+       ofdm = &il->_4965.stats.rx.ofdm;
+       cck = &il->_4965.stats.rx.cck;
+       general = &il->_4965.stats.rx.general;
+       ht = &il->_4965.stats.rx.ofdm_ht;
+       accum_ofdm = &il->_4965.accum_stats.rx.ofdm;
+       accum_cck = &il->_4965.accum_stats.rx.cck;
+       accum_general = &il->_4965.accum_stats.rx.general;
+       accum_ht = &il->_4965.accum_stats.rx.ofdm_ht;
+       delta_ofdm = &il->_4965.delta_stats.rx.ofdm;
+       delta_cck = &il->_4965.delta_stats.rx.cck;
+       delta_general = &il->_4965.delta_stats.rx.general;
+       delta_ht = &il->_4965.delta_stats.rx.ofdm_ht;
+       max_ofdm = &il->_4965.max_delta.rx.ofdm;
+       max_cck = &il->_4965.max_delta.rx.cck;
+       max_general = &il->_4965.max_delta.rx.general;
+       max_ht = &il->_4965.max_delta.rx.ofdm_ht;
+
+       pos += il4965_stats_flag(il, buf, bufsz);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_header,
+                     "Statistics_Rx - OFDM:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "ina_cnt:",
+                     le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt,
+                     delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_cnt:",
+                     le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
+                     delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "plcp_err:",
+                     le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
+                     delta_ofdm->plcp_err, max_ofdm->plcp_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_err:",
+                     le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
+                     delta_ofdm->crc32_err, max_ofdm->crc32_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "overrun_err:",
+                     le32_to_cpu(ofdm->overrun_err), accum_ofdm->overrun_err,
+                     delta_ofdm->overrun_err, max_ofdm->overrun_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "early_overrun_err:",
+                     le32_to_cpu(ofdm->early_overrun_err),
+                     accum_ofdm->early_overrun_err,
+                     delta_ofdm->early_overrun_err,
+                     max_ofdm->early_overrun_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_good:",
+                     le32_to_cpu(ofdm->crc32_good), accum_ofdm->crc32_good,
+                     delta_ofdm->crc32_good, max_ofdm->crc32_good);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "false_alarm_cnt:",
+                     le32_to_cpu(ofdm->false_alarm_cnt),
+                     accum_ofdm->false_alarm_cnt, delta_ofdm->false_alarm_cnt,
+                     max_ofdm->false_alarm_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_sync_err_cnt:",
+                     le32_to_cpu(ofdm->fina_sync_err_cnt),
+                     accum_ofdm->fina_sync_err_cnt,
+                     delta_ofdm->fina_sync_err_cnt,
+                     max_ofdm->fina_sync_err_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "sfd_timeout:",
+                     le32_to_cpu(ofdm->sfd_timeout), accum_ofdm->sfd_timeout,
+                     delta_ofdm->sfd_timeout, max_ofdm->sfd_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_timeout:",
+                     le32_to_cpu(ofdm->fina_timeout), accum_ofdm->fina_timeout,
+                     delta_ofdm->fina_timeout, max_ofdm->fina_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "unresponded_rts:",
+                     le32_to_cpu(ofdm->unresponded_rts),
+                     accum_ofdm->unresponded_rts, delta_ofdm->unresponded_rts,
+                     max_ofdm->unresponded_rts);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "rxe_frame_lmt_ovrun:",
+                     le32_to_cpu(ofdm->rxe_frame_limit_overrun),
+                     accum_ofdm->rxe_frame_limit_overrun,
+                     delta_ofdm->rxe_frame_limit_overrun,
+                     max_ofdm->rxe_frame_limit_overrun);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_ack_cnt:",
+                     le32_to_cpu(ofdm->sent_ack_cnt), accum_ofdm->sent_ack_cnt,
+                     delta_ofdm->sent_ack_cnt, max_ofdm->sent_ack_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_cts_cnt:",
+                     le32_to_cpu(ofdm->sent_cts_cnt), accum_ofdm->sent_cts_cnt,
+                     delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_ba_rsp_cnt:",
+                     le32_to_cpu(ofdm->sent_ba_rsp_cnt),
+                     accum_ofdm->sent_ba_rsp_cnt, delta_ofdm->sent_ba_rsp_cnt,
+                     max_ofdm->sent_ba_rsp_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "dsp_self_kill:",
+                     le32_to_cpu(ofdm->dsp_self_kill),
+                     accum_ofdm->dsp_self_kill, delta_ofdm->dsp_self_kill,
+                     max_ofdm->dsp_self_kill);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "mh_format_err:",
+                     le32_to_cpu(ofdm->mh_format_err),
+                     accum_ofdm->mh_format_err, delta_ofdm->mh_format_err,
+                     max_ofdm->mh_format_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "re_acq_main_rssi_sum:",
+                     le32_to_cpu(ofdm->re_acq_main_rssi_sum),
+                     accum_ofdm->re_acq_main_rssi_sum,
+                     delta_ofdm->re_acq_main_rssi_sum,
+                     max_ofdm->re_acq_main_rssi_sum);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_header,
+                     "Statistics_Rx - CCK:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "ina_cnt:",
+                     le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
+                     delta_cck->ina_cnt, max_cck->ina_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_cnt:",
+                     le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
+                     delta_cck->fina_cnt, max_cck->fina_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "plcp_err:",
+                     le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
+                     delta_cck->plcp_err, max_cck->plcp_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_err:",
+                     le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
+                     delta_cck->crc32_err, max_cck->crc32_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "overrun_err:",
+                     le32_to_cpu(cck->overrun_err), accum_cck->overrun_err,
+                     delta_cck->overrun_err, max_cck->overrun_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "early_overrun_err:",
+                     le32_to_cpu(cck->early_overrun_err),
+                     accum_cck->early_overrun_err,
+                     delta_cck->early_overrun_err, max_cck->early_overrun_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_good:",
+                     le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
+                     delta_cck->crc32_good, max_cck->crc32_good);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "false_alarm_cnt:",
+                     le32_to_cpu(cck->false_alarm_cnt),
+                     accum_cck->false_alarm_cnt, delta_cck->false_alarm_cnt,
+                     max_cck->false_alarm_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_sync_err_cnt:",
+                     le32_to_cpu(cck->fina_sync_err_cnt),
+                     accum_cck->fina_sync_err_cnt,
+                     delta_cck->fina_sync_err_cnt, max_cck->fina_sync_err_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "sfd_timeout:",
+                     le32_to_cpu(cck->sfd_timeout), accum_cck->sfd_timeout,
+                     delta_cck->sfd_timeout, max_cck->sfd_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "fina_timeout:",
+                     le32_to_cpu(cck->fina_timeout), accum_cck->fina_timeout,
+                     delta_cck->fina_timeout, max_cck->fina_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "unresponded_rts:",
+                     le32_to_cpu(cck->unresponded_rts),
+                     accum_cck->unresponded_rts, delta_cck->unresponded_rts,
+                     max_cck->unresponded_rts);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "rxe_frame_lmt_ovrun:",
+                     le32_to_cpu(cck->rxe_frame_limit_overrun),
+                     accum_cck->rxe_frame_limit_overrun,
+                     delta_cck->rxe_frame_limit_overrun,
+                     max_cck->rxe_frame_limit_overrun);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_ack_cnt:",
+                     le32_to_cpu(cck->sent_ack_cnt), accum_cck->sent_ack_cnt,
+                     delta_cck->sent_ack_cnt, max_cck->sent_ack_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_cts_cnt:",
+                     le32_to_cpu(cck->sent_cts_cnt), accum_cck->sent_cts_cnt,
+                     delta_cck->sent_cts_cnt, max_cck->sent_cts_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "sent_ba_rsp_cnt:",
+                     le32_to_cpu(cck->sent_ba_rsp_cnt),
+                     accum_cck->sent_ba_rsp_cnt, delta_cck->sent_ba_rsp_cnt,
+                     max_cck->sent_ba_rsp_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "dsp_self_kill:",
+                     le32_to_cpu(cck->dsp_self_kill), accum_cck->dsp_self_kill,
+                     delta_cck->dsp_self_kill, max_cck->dsp_self_kill);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "mh_format_err:",
+                     le32_to_cpu(cck->mh_format_err), accum_cck->mh_format_err,
+                     delta_cck->mh_format_err, max_cck->mh_format_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "re_acq_main_rssi_sum:",
+                     le32_to_cpu(cck->re_acq_main_rssi_sum),
+                     accum_cck->re_acq_main_rssi_sum,
+                     delta_cck->re_acq_main_rssi_sum,
+                     max_cck->re_acq_main_rssi_sum);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_header,
+                     "Statistics_Rx - GENERAL:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "bogus_cts:",
+                     le32_to_cpu(general->bogus_cts), accum_general->bogus_cts,
+                     delta_general->bogus_cts, max_general->bogus_cts);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "bogus_ack:",
+                     le32_to_cpu(general->bogus_ack), accum_general->bogus_ack,
+                     delta_general->bogus_ack, max_general->bogus_ack);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "non_bssid_frames:",
+                     le32_to_cpu(general->non_bssid_frames),
+                     accum_general->non_bssid_frames,
+                     delta_general->non_bssid_frames,
+                     max_general->non_bssid_frames);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "filtered_frames:",
+                     le32_to_cpu(general->filtered_frames),
+                     accum_general->filtered_frames,
+                     delta_general->filtered_frames,
+                     max_general->filtered_frames);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "non_channel_beacons:",
+                     le32_to_cpu(general->non_channel_beacons),
+                     accum_general->non_channel_beacons,
+                     delta_general->non_channel_beacons,
+                     max_general->non_channel_beacons);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "channel_beacons:",
+                     le32_to_cpu(general->channel_beacons),
+                     accum_general->channel_beacons,
+                     delta_general->channel_beacons,
+                     max_general->channel_beacons);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "num_missed_bcon:",
+                     le32_to_cpu(general->num_missed_bcon),
+                     accum_general->num_missed_bcon,
+                     delta_general->num_missed_bcon,
+                     max_general->num_missed_bcon);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "adc_rx_saturation_time:",
+                     le32_to_cpu(general->adc_rx_saturation_time),
+                     accum_general->adc_rx_saturation_time,
+                     delta_general->adc_rx_saturation_time,
+                     max_general->adc_rx_saturation_time);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "ina_detect_search_tm:",
+                     le32_to_cpu(general->ina_detection_search_time),
+                     accum_general->ina_detection_search_time,
+                     delta_general->ina_detection_search_time,
+                     max_general->ina_detection_search_time);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "beacon_silence_rssi_a:",
+                     le32_to_cpu(general->beacon_silence_rssi_a),
+                     accum_general->beacon_silence_rssi_a,
+                     delta_general->beacon_silence_rssi_a,
+                     max_general->beacon_silence_rssi_a);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "beacon_silence_rssi_b:",
+                     le32_to_cpu(general->beacon_silence_rssi_b),
+                     accum_general->beacon_silence_rssi_b,
+                     delta_general->beacon_silence_rssi_b,
+                     max_general->beacon_silence_rssi_b);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "beacon_silence_rssi_c:",
+                     le32_to_cpu(general->beacon_silence_rssi_c),
+                     accum_general->beacon_silence_rssi_c,
+                     delta_general->beacon_silence_rssi_c,
+                     max_general->beacon_silence_rssi_c);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "interference_data_flag:",
+                     le32_to_cpu(general->interference_data_flag),
+                     accum_general->interference_data_flag,
+                     delta_general->interference_data_flag,
+                     max_general->interference_data_flag);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "channel_load:",
+                     le32_to_cpu(general->channel_load),
+                     accum_general->channel_load, delta_general->channel_load,
+                     max_general->channel_load);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "dsp_false_alarms:",
+                     le32_to_cpu(general->dsp_false_alarms),
+                     accum_general->dsp_false_alarms,
+                     delta_general->dsp_false_alarms,
+                     max_general->dsp_false_alarms);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_rssi_a:",
+                     le32_to_cpu(general->beacon_rssi_a),
+                     accum_general->beacon_rssi_a,
+                     delta_general->beacon_rssi_a, max_general->beacon_rssi_a);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_rssi_b:",
+                     le32_to_cpu(general->beacon_rssi_b),
+                     accum_general->beacon_rssi_b,
+                     delta_general->beacon_rssi_b, max_general->beacon_rssi_b);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_rssi_c:",
+                     le32_to_cpu(general->beacon_rssi_c),
+                     accum_general->beacon_rssi_c,
+                     delta_general->beacon_rssi_c, max_general->beacon_rssi_c);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_energy_a:",
+                     le32_to_cpu(general->beacon_energy_a),
+                     accum_general->beacon_energy_a,
+                     delta_general->beacon_energy_a,
+                     max_general->beacon_energy_a);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_energy_b:",
+                     le32_to_cpu(general->beacon_energy_b),
+                     accum_general->beacon_energy_b,
+                     delta_general->beacon_energy_b,
+                     max_general->beacon_energy_b);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "beacon_energy_c:",
+                     le32_to_cpu(general->beacon_energy_c),
+                     accum_general->beacon_energy_c,
+                     delta_general->beacon_energy_c,
+                     max_general->beacon_energy_c);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_header,
+                     "Statistics_Rx - OFDM_HT:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "plcp_err:",
+                     le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
+                     delta_ht->plcp_err, max_ht->plcp_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "overrun_err:",
+                     le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
+                     delta_ht->overrun_err, max_ht->overrun_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "early_overrun_err:",
+                     le32_to_cpu(ht->early_overrun_err),
+                     accum_ht->early_overrun_err, delta_ht->early_overrun_err,
+                     max_ht->early_overrun_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_good:",
+                     le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
+                     delta_ht->crc32_good, max_ht->crc32_good);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "crc32_err:",
+                     le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
+                     delta_ht->crc32_err, max_ht->crc32_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "mh_format_err:",
+                     le32_to_cpu(ht->mh_format_err), accum_ht->mh_format_err,
+                     delta_ht->mh_format_err, max_ht->mh_format_err);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "agg_crc32_good:",
+                     le32_to_cpu(ht->agg_crc32_good), accum_ht->agg_crc32_good,
+                     delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "agg_mpdu_cnt:",
+                     le32_to_cpu(ht->agg_mpdu_cnt), accum_ht->agg_mpdu_cnt,
+                     delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "agg_cnt:",
+                     le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
+                     delta_ht->agg_cnt, max_ht->agg_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "unsupport_mcs:",
+                     le32_to_cpu(ht->unsupport_mcs), accum_ht->unsupport_mcs,
+                     delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+ssize_t
+il4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+                          size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       char *buf;
+       int bufsz = (sizeof(struct stats_tx) * 48) + 250;
+       ssize_t ret;
+       struct stats_tx *tx, *accum_tx, *delta_tx, *max_tx;
+
+       if (!il_is_alive(il))
+               return -EAGAIN;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       /* the statistic information display here is based on
+        * the last stats notification from uCode
+        * might not reflect the current uCode activity
+        */
+       tx = &il->_4965.stats.tx;
+       accum_tx = &il->_4965.accum_stats.tx;
+       delta_tx = &il->_4965.delta_stats.tx;
+       max_tx = &il->_4965.max_delta.tx;
+
+       pos += il4965_stats_flag(il, buf, bufsz);
+       pos += scnprintf(buf + pos, bufsz - pos, fmt_header, "Statistics_Tx:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "preamble:",
+                     le32_to_cpu(tx->preamble_cnt), accum_tx->preamble_cnt,
+                     delta_tx->preamble_cnt, max_tx->preamble_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "rx_detected_cnt:",
+                     le32_to_cpu(tx->rx_detected_cnt),
+                     accum_tx->rx_detected_cnt, delta_tx->rx_detected_cnt,
+                     max_tx->rx_detected_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "bt_prio_defer_cnt:",
+                     le32_to_cpu(tx->bt_prio_defer_cnt),
+                     accum_tx->bt_prio_defer_cnt, delta_tx->bt_prio_defer_cnt,
+                     max_tx->bt_prio_defer_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "bt_prio_kill_cnt:",
+                     le32_to_cpu(tx->bt_prio_kill_cnt),
+                     accum_tx->bt_prio_kill_cnt, delta_tx->bt_prio_kill_cnt,
+                     max_tx->bt_prio_kill_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "few_bytes_cnt:",
+                     le32_to_cpu(tx->few_bytes_cnt), accum_tx->few_bytes_cnt,
+                     delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "cts_timeout:",
+                     le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
+                     delta_tx->cts_timeout, max_tx->cts_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "ack_timeout:",
+                     le32_to_cpu(tx->ack_timeout), accum_tx->ack_timeout,
+                     delta_tx->ack_timeout, max_tx->ack_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "expected_ack_cnt:",
+                     le32_to_cpu(tx->expected_ack_cnt),
+                     accum_tx->expected_ack_cnt, delta_tx->expected_ack_cnt,
+                     max_tx->expected_ack_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "actual_ack_cnt:",
+                     le32_to_cpu(tx->actual_ack_cnt), accum_tx->actual_ack_cnt,
+                     delta_tx->actual_ack_cnt, max_tx->actual_ack_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "dump_msdu_cnt:",
+                     le32_to_cpu(tx->dump_msdu_cnt), accum_tx->dump_msdu_cnt,
+                     delta_tx->dump_msdu_cnt, max_tx->dump_msdu_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "abort_nxt_frame_mismatch:",
+                     le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
+                     accum_tx->burst_abort_next_frame_mismatch_cnt,
+                     delta_tx->burst_abort_next_frame_mismatch_cnt,
+                     max_tx->burst_abort_next_frame_mismatch_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "abort_missing_nxt_frame:",
+                     le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
+                     accum_tx->burst_abort_missing_next_frame_cnt,
+                     delta_tx->burst_abort_missing_next_frame_cnt,
+                     max_tx->burst_abort_missing_next_frame_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "cts_timeout_collision:",
+                     le32_to_cpu(tx->cts_timeout_collision),
+                     accum_tx->cts_timeout_collision,
+                     delta_tx->cts_timeout_collision,
+                     max_tx->cts_timeout_collision);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "ack_ba_timeout_collision:",
+                     le32_to_cpu(tx->ack_or_ba_timeout_collision),
+                     accum_tx->ack_or_ba_timeout_collision,
+                     delta_tx->ack_or_ba_timeout_collision,
+                     max_tx->ack_or_ba_timeout_collision);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "agg ba_timeout:",
+                     le32_to_cpu(tx->agg.ba_timeout), accum_tx->agg.ba_timeout,
+                     delta_tx->agg.ba_timeout, max_tx->agg.ba_timeout);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "agg ba_resched_frames:",
+                     le32_to_cpu(tx->agg.ba_reschedule_frames),
+                     accum_tx->agg.ba_reschedule_frames,
+                     delta_tx->agg.ba_reschedule_frames,
+                     max_tx->agg.ba_reschedule_frames);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "agg scd_query_agg_frame:",
+                     le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
+                     accum_tx->agg.scd_query_agg_frame_cnt,
+                     delta_tx->agg.scd_query_agg_frame_cnt,
+                     max_tx->agg.scd_query_agg_frame_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "agg scd_query_no_agg:",
+                     le32_to_cpu(tx->agg.scd_query_no_agg),
+                     accum_tx->agg.scd_query_no_agg,
+                     delta_tx->agg.scd_query_no_agg,
+                     max_tx->agg.scd_query_no_agg);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "agg scd_query_agg:",
+                     le32_to_cpu(tx->agg.scd_query_agg),
+                     accum_tx->agg.scd_query_agg, delta_tx->agg.scd_query_agg,
+                     max_tx->agg.scd_query_agg);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "agg scd_query_mismatch:",
+                     le32_to_cpu(tx->agg.scd_query_mismatch),
+                     accum_tx->agg.scd_query_mismatch,
+                     delta_tx->agg.scd_query_mismatch,
+                     max_tx->agg.scd_query_mismatch);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "agg frame_not_ready:",
+                     le32_to_cpu(tx->agg.frame_not_ready),
+                     accum_tx->agg.frame_not_ready,
+                     delta_tx->agg.frame_not_ready,
+                     max_tx->agg.frame_not_ready);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "agg underrun:",
+                     le32_to_cpu(tx->agg.underrun), accum_tx->agg.underrun,
+                     delta_tx->agg.underrun, max_tx->agg.underrun);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "agg bt_prio_kill:",
+                     le32_to_cpu(tx->agg.bt_prio_kill),
+                     accum_tx->agg.bt_prio_kill, delta_tx->agg.bt_prio_kill,
+                     max_tx->agg.bt_prio_kill);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "agg rx_ba_rsp_cnt:",
+                     le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
+                     accum_tx->agg.rx_ba_rsp_cnt, delta_tx->agg.rx_ba_rsp_cnt,
+                     max_tx->agg.rx_ba_rsp_cnt);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+ssize_t
+il4965_ucode_general_stats_read(struct file *file, char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       char *buf;
+       int bufsz = sizeof(struct stats_general) * 10 + 300;
+       ssize_t ret;
+       struct stats_general_common *general, *accum_general;
+       struct stats_general_common *delta_general, *max_general;
+       struct stats_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
+       struct stats_div *div, *accum_div, *delta_div, *max_div;
+
+       if (!il_is_alive(il))
+               return -EAGAIN;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       /* the statistic information display here is based on
+        * the last stats notification from uCode
+        * might not reflect the current uCode activity
+        */
+       general = &il->_4965.stats.general.common;
+       dbg = &il->_4965.stats.general.common.dbg;
+       div = &il->_4965.stats.general.common.div;
+       accum_general = &il->_4965.accum_stats.general.common;
+       accum_dbg = &il->_4965.accum_stats.general.common.dbg;
+       accum_div = &il->_4965.accum_stats.general.common.div;
+       delta_general = &il->_4965.delta_stats.general.common;
+       max_general = &il->_4965.max_delta.general.common;
+       delta_dbg = &il->_4965.delta_stats.general.common.dbg;
+       max_dbg = &il->_4965.max_delta.general.common.dbg;
+       delta_div = &il->_4965.delta_stats.general.common.div;
+       max_div = &il->_4965.max_delta.general.common.div;
+
+       pos += il4965_stats_flag(il, buf, bufsz);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_header,
+                     "Statistics_General:");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_value, "temperature:",
+                     le32_to_cpu(general->temperature));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_value, "ttl_timestamp:",
+                     le32_to_cpu(general->ttl_timestamp));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "burst_check:",
+                     le32_to_cpu(dbg->burst_check), accum_dbg->burst_check,
+                     delta_dbg->burst_check, max_dbg->burst_check);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "burst_count:",
+                     le32_to_cpu(dbg->burst_count), accum_dbg->burst_count,
+                     delta_dbg->burst_count, max_dbg->burst_count);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table,
+                     "wait_for_silence_timeout_count:",
+                     le32_to_cpu(dbg->wait_for_silence_timeout_cnt),
+                     accum_dbg->wait_for_silence_timeout_cnt,
+                     delta_dbg->wait_for_silence_timeout_cnt,
+                     max_dbg->wait_for_silence_timeout_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "sleep_time:",
+                     le32_to_cpu(general->sleep_time),
+                     accum_general->sleep_time, delta_general->sleep_time,
+                     max_general->sleep_time);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "slots_out:",
+                     le32_to_cpu(general->slots_out), accum_general->slots_out,
+                     delta_general->slots_out, max_general->slots_out);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "slots_idle:",
+                     le32_to_cpu(general->slots_idle),
+                     accum_general->slots_idle, delta_general->slots_idle,
+                     max_general->slots_idle);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "tx_on_a:",
+                     le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
+                     delta_div->tx_on_a, max_div->tx_on_a);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "tx_on_b:",
+                     le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
+                     delta_div->tx_on_b, max_div->tx_on_b);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "exec_time:",
+                     le32_to_cpu(div->exec_time), accum_div->exec_time,
+                     delta_div->exec_time, max_div->exec_time);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "probe_time:",
+                     le32_to_cpu(div->probe_time), accum_div->probe_time,
+                     delta_div->probe_time, max_div->probe_time);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "rx_enable_counter:",
+                     le32_to_cpu(general->rx_enable_counter),
+                     accum_general->rx_enable_counter,
+                     delta_general->rx_enable_counter,
+                     max_general->rx_enable_counter);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, fmt_table, "num_of_sos_states:",
+                     le32_to_cpu(general->num_of_sos_states),
+                     accum_general->num_of_sos_states,
+                     delta_general->num_of_sos_states,
+                     max_general->num_of_sos_states);
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
new file mode 100644 (file)
index 0000000..4aaef41
--- /dev/null
@@ -0,0 +1,6536 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
+#include <net/mac80211.h>
+
+#include <asm/div64.h>
+
+#define DRV_NAME        "iwl4965"
+
+#include "common.h"
+#include "4965.h"
+
+/******************************************************************************
+ *
+ * module boiler plate
+ *
+ ******************************************************************************/
+
+/*
+ * module name, copyright, version, etc.
+ */
+#define DRV_DESCRIPTION        "Intel(R) Wireless WiFi 4965 driver for Linux"
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+#define VD "d"
+#else
+#define VD
+#endif
+
+#define DRV_VERSION     IWLWIFI_VERSION VD
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("iwl4965");
+
+void
+il4965_check_abort_status(struct il_priv *il, u8 frame_count, u32 status)
+{
+       if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
+               IL_ERR("Tx flush command to flush out all frames\n");
+               if (!test_bit(S_EXIT_PENDING, &il->status))
+                       queue_work(il->workqueue, &il->tx_flush);
+       }
+}
+
+/*
+ * EEPROM
+ */
+struct il_mod_params il4965_mod_params = {
+       .amsdu_size_8K = 1,
+       .restart_fw = 1,
+       /* the rest are 0 by default */
+};
+
+void
+il4965_rx_queue_reset(struct il_priv *il, struct il_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].page != NULL) {
+                       pci_unmap_page(il->pci_dev, rxq->pool[i].page_dma,
+                                      PAGE_SIZE << il->hw_params.rx_page_order,
+                                      PCI_DMA_FROMDEVICE);
+                       __il_free_pages(il, rxq->pool[i].page);
+                       rxq->pool[i].page = NULL;
+               }
+               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+       }
+
+       for (i = 0; i < RX_QUEUE_SIZE; i++)
+               rxq->queue[i] = NULL;
+
+       /* 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->write_actual = 0;
+       rxq->free_count = 0;
+       spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
+int
+il4965_rx_init(struct il_priv *il, struct il_rx_queue *rxq)
+{
+       u32 rb_size;
+       const u32 rfdnlog = RX_QUEUE_SIZE_LOG;  /* 256 RBDs */
+       u32 rb_timeout = 0;
+
+       if (il->cfg->mod_params->amsdu_size_8K)
+               rb_size = FH49_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+       else
+               rb_size = FH49_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+
+       /* Stop Rx DMA */
+       il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+       /* Reset driver's Rx queue write idx */
+       il_wr(il, FH49_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+
+       /* Tell device where to find RBD circular buffer in DRAM */
+       il_wr(il, FH49_RSCSR_CHNL0_RBDCB_BASE_REG, (u32) (rxq->bd_dma >> 8));
+
+       /* Tell device where in DRAM to update its Rx status */
+       il_wr(il, FH49_RSCSR_CHNL0_STTS_WPTR_REG, rxq->rb_stts_dma >> 4);
+
+       /* Enable Rx DMA
+        * Direct rx interrupts to hosts
+        * Rx buffer size 4 or 8k
+        * RB timeout 0x10
+        * 256 RBDs
+        */
+       il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG,
+             FH49_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+             FH49_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+             FH49_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
+             rb_size |
+             (rb_timeout << FH49_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |
+             (rfdnlog << FH49_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
+
+       /* Set interrupt coalescing timer to default (2048 usecs) */
+       il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_TIMEOUT_DEF);
+
+       return 0;
+}
+
+static void
+il4965_set_pwr_vmain(struct il_priv *il)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do:
+
+               if (pci_pme_capable(il->pci_dev, PCI_D3cold))
+                       il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
+                                              APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+                                              ~APMG_PS_CTRL_MSK_PWR_SRC);
+ */
+
+       il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
+                             APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+                             ~APMG_PS_CTRL_MSK_PWR_SRC);
+}
+
+int
+il4965_hw_nic_init(struct il_priv *il)
+{
+       unsigned long flags;
+       struct il_rx_queue *rxq = &il->rxq;
+       int ret;
+
+       /* nic_init */
+       spin_lock_irqsave(&il->lock, flags);
+       il->cfg->ops->lib->apm_ops.init(il);
+
+       /* Set interrupt coalescing calibration timer to default (512 usecs) */
+       il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_CALIB_TIMEOUT_DEF);
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       il4965_set_pwr_vmain(il);
+
+       il->cfg->ops->lib->apm_ops.config(il);
+
+       /* Allocate the RX queue, or reset if it is already allocated */
+       if (!rxq->bd) {
+               ret = il_rx_queue_alloc(il);
+               if (ret) {
+                       IL_ERR("Unable to initialize Rx queue\n");
+                       return -ENOMEM;
+               }
+       } else
+               il4965_rx_queue_reset(il, rxq);
+
+       il4965_rx_replenish(il);
+
+       il4965_rx_init(il, rxq);
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       rxq->need_update = 1;
+       il_rx_queue_update_write_ptr(il, rxq);
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       /* Allocate or reset and init all Tx and Command queues */
+       if (!il->txq) {
+               ret = il4965_txq_ctx_alloc(il);
+               if (ret)
+                       return ret;
+       } else
+               il4965_txq_ctx_reset(il);
+
+       set_bit(S_INIT, &il->status);
+
+       return 0;
+}
+
+/**
+ * il4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32
+il4965_dma_addr2rbd_ptr(struct il_priv *il, dma_addr_t dma_addr)
+{
+       return cpu_to_le32((u32) (dma_addr >> 8));
+}
+
+/**
+ * il4965_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' idx forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+void
+il4965_rx_queue_restock(struct il_priv *il)
+{
+       struct il_rx_queue *rxq = &il->rxq;
+       struct list_head *element;
+       struct il_rx_buf *rxb;
+       unsigned long flags;
+
+       spin_lock_irqsave(&rxq->lock, flags);
+       while (il_rx_queue_space(rxq) > 0 && rxq->free_count) {
+               /* The overwritten rxb must be a used one */
+               rxb = rxq->queue[rxq->write];
+               BUG_ON(rxb && rxb->page);
+
+               /* Get next free Rx buffer, remove from free list */
+               element = rxq->rx_free.next;
+               rxb = list_entry(element, struct il_rx_buf, list);
+               list_del(element);
+
+               /* Point to Rx buffer via next RBD in circular buffer */
+               rxq->bd[rxq->write] =
+                   il4965_dma_addr2rbd_ptr(il, rxb->page_dma);
+               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(il->workqueue, &il->rx_replenish);
+
+       /* If we've added more space for the firmware to place data, tell it.
+        * Increment device's write pointer in multiples of 8. */
+       if (rxq->write_actual != (rxq->write & ~0x7)) {
+               spin_lock_irqsave(&rxq->lock, flags);
+               rxq->need_update = 1;
+               spin_unlock_irqrestore(&rxq->lock, flags);
+               il_rx_queue_update_write_ptr(il, rxq);
+       }
+}
+
+/**
+ * il4965_rx_replenish - 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 il_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
+ */
+static void
+il4965_rx_allocate(struct il_priv *il, gfp_t priority)
+{
+       struct il_rx_queue *rxq = &il->rxq;
+       struct list_head *element;
+       struct il_rx_buf *rxb;
+       struct page *page;
+       unsigned long flags;
+       gfp_t gfp_mask = priority;
+
+       while (1) {
+               spin_lock_irqsave(&rxq->lock, flags);
+               if (list_empty(&rxq->rx_used)) {
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       return;
+               }
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               if (rxq->free_count > RX_LOW_WATERMARK)
+                       gfp_mask |= __GFP_NOWARN;
+
+               if (il->hw_params.rx_page_order > 0)
+                       gfp_mask |= __GFP_COMP;
+
+               /* Alloc a new receive buffer */
+               page = alloc_pages(gfp_mask, il->hw_params.rx_page_order);
+               if (!page) {
+                       if (net_ratelimit())
+                               D_INFO("alloc_pages failed, " "order: %d\n",
+                                      il->hw_params.rx_page_order);
+
+                       if (rxq->free_count <= RX_LOW_WATERMARK &&
+                           net_ratelimit())
+                               IL_ERR("Failed to alloc_pages with %s. "
+                                      "Only %u free buffers remaining.\n",
+                                      priority ==
+                                      GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
+                                      rxq->free_count);
+                       /* We don't reschedule replenish work here -- we will
+                        * call the restock method and if it still needs
+                        * more buffers it will schedule replenish */
+                       return;
+               }
+
+               spin_lock_irqsave(&rxq->lock, flags);
+
+               if (list_empty(&rxq->rx_used)) {
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       __free_pages(page, il->hw_params.rx_page_order);
+                       return;
+               }
+               element = rxq->rx_used.next;
+               rxb = list_entry(element, struct il_rx_buf, list);
+               list_del(element);
+
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               BUG_ON(rxb->page);
+               rxb->page = page;
+               /* Get physical address of the RB */
+               rxb->page_dma =
+                   pci_map_page(il->pci_dev, page, 0,
+                                PAGE_SIZE << il->hw_params.rx_page_order,
+                                PCI_DMA_FROMDEVICE);
+               /* dma address must be no more than 36 bits */
+               BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
+               /* and also 256 byte aligned! */
+               BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
+
+               spin_lock_irqsave(&rxq->lock, flags);
+
+               list_add_tail(&rxb->list, &rxq->rx_free);
+               rxq->free_count++;
+               il->alloc_rxb_page++;
+
+               spin_unlock_irqrestore(&rxq->lock, flags);
+       }
+}
+
+void
+il4965_rx_replenish(struct il_priv *il)
+{
+       unsigned long flags;
+
+       il4965_rx_allocate(il, GFP_KERNEL);
+
+       spin_lock_irqsave(&il->lock, flags);
+       il4965_rx_queue_restock(il);
+       spin_unlock_irqrestore(&il->lock, flags);
+}
+
+void
+il4965_rx_replenish_now(struct il_priv *il)
+{
+       il4965_rx_allocate(il, GFP_ATOMIC);
+
+       il4965_rx_queue_restock(il);
+}
+
+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
+ * If an SKB has been detached, the POOL needs to have its 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
+il4965_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq)
+{
+       int i;
+       for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+               if (rxq->pool[i].page != NULL) {
+                       pci_unmap_page(il->pci_dev, rxq->pool[i].page_dma,
+                                      PAGE_SIZE << il->hw_params.rx_page_order,
+                                      PCI_DMA_FROMDEVICE);
+                       __il_free_pages(il, rxq->pool[i].page);
+                       rxq->pool[i].page = NULL;
+               }
+       }
+
+       dma_free_coherent(&il->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+                         rxq->bd_dma);
+       dma_free_coherent(&il->pci_dev->dev, sizeof(struct il_rb_status),
+                         rxq->rb_stts, rxq->rb_stts_dma);
+       rxq->bd = NULL;
+       rxq->rb_stts = NULL;
+}
+
+int
+il4965_rxq_stop(struct il_priv *il)
+{
+
+       /* stop Rx DMA */
+       il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+       il_poll_bit(il, FH49_MEM_RSSR_RX_STATUS_REG,
+                   FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+
+       return 0;
+}
+
+int
+il4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
+{
+       int idx = 0;
+       int band_offset = 0;
+
+       /* HT rate format: mac80211 wants an MCS number, which is just LSB */
+       if (rate_n_flags & RATE_MCS_HT_MSK) {
+               idx = (rate_n_flags & 0xff);
+               return idx;
+               /* Legacy rate format, search for match in table */
+       } else {
+               if (band == IEEE80211_BAND_5GHZ)
+                       band_offset = IL_FIRST_OFDM_RATE;
+               for (idx = band_offset; idx < RATE_COUNT_LEGACY; idx++)
+                       if (il_rates[idx].plcp == (rate_n_flags & 0xFF))
+                               return idx - band_offset;
+       }
+
+       return -1;
+}
+
+static int
+il4965_calc_rssi(struct il_priv *il, struct il_rx_phy_res *rx_resp)
+{
+       /* data from PHY/DSP regarding signal strength, etc.,
+        *   contents are always there, not configurable by host.  */
+       struct il4965_rx_non_cfg_phy *ncphy =
+           (struct il4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
+       u32 agc =
+           (le16_to_cpu(ncphy->agc_info) & IL49_AGC_DB_MASK) >>
+           IL49_AGC_DB_POS;
+
+       u32 valid_antennae =
+           (le16_to_cpu(rx_resp->phy_flags) & IL49_RX_PHY_FLAGS_ANTENNAE_MASK)
+           >> IL49_RX_PHY_FLAGS_ANTENNAE_OFFSET;
+       u8 max_rssi = 0;
+       u32 i;
+
+       /* Find max rssi among 3 possible receivers.
+        * These values are measured by the digital signal processor (DSP).
+        * They should stay fairly constant even as the signal strength varies,
+        *   if the radio's automatic gain control (AGC) is working right.
+        * AGC value (see below) will provide the "interesting" info. */
+       for (i = 0; i < 3; i++)
+               if (valid_antennae & (1 << i))
+                       max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
+
+       D_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
+               ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
+               max_rssi, agc);
+
+       /* dBm = max_rssi dB - agc dB - constant.
+        * Higher AGC (higher radio gain) means lower signal. */
+       return max_rssi - agc - IL4965_RSSI_OFFSET;
+}
+
+static u32
+il4965_translate_rx_status(struct il_priv *il, u32 decrypt_in)
+{
+       u32 decrypt_out = 0;
+
+       if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
+           RX_RES_STATUS_STATION_FOUND)
+               decrypt_out |=
+                   (RX_RES_STATUS_STATION_FOUND |
+                    RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
+
+       decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
+
+       /* packet was not encrypted */
+       if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+           RX_RES_STATUS_SEC_TYPE_NONE)
+               return decrypt_out;
+
+       /* packet was encrypted with unknown alg */
+       if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+           RX_RES_STATUS_SEC_TYPE_ERR)
+               return decrypt_out;
+
+       /* decryption was not done in HW */
+       if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
+           RX_MPDU_RES_STATUS_DEC_DONE_MSK)
+               return decrypt_out;
+
+       switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
+
+       case RX_RES_STATUS_SEC_TYPE_CCMP:
+               /* alg is CCM: check MIC only */
+               if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
+                       /* Bad MIC */
+                       decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+               else
+                       decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+
+               break;
+
+       case RX_RES_STATUS_SEC_TYPE_TKIP:
+               if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
+                       /* Bad TTAK */
+                       decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
+                       break;
+               }
+               /* fall through if TTAK OK */
+       default:
+               if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
+                       decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+               else
+                       decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+               break;
+       }
+
+       D_RX("decrypt_in:0x%x  decrypt_out = 0x%x\n", decrypt_in, decrypt_out);
+
+       return decrypt_out;
+}
+
+static void
+il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
+                              u16 len, u32 ampdu_status, struct il_rx_buf *rxb,
+                              struct ieee80211_rx_status *stats)
+{
+       struct sk_buff *skb;
+       __le16 fc = hdr->frame_control;
+
+       /* We only process data packets if the interface is open */
+       if (unlikely(!il->is_open)) {
+               D_DROP("Dropping packet while interface is not open.\n");
+               return;
+       }
+
+       /* In case of HW accelerated crypto and bad decryption, drop */
+       if (!il->cfg->mod_params->sw_crypto &&
+           il_set_decrypted_flag(il, hdr, ampdu_status, stats))
+               return;
+
+       skb = dev_alloc_skb(128);
+       if (!skb) {
+               IL_ERR("dev_alloc_skb failed\n");
+               return;
+       }
+
+       skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
+
+       il_update_stats(il, false, fc, len);
+       memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
+
+       ieee80211_rx(il->hw, skb);
+       il->alloc_rxb_page--;
+       rxb->page = NULL;
+}
+
+/* Called for N_RX (legacy ABG frames), or
+ * N_RX_MPDU (HT high-throughput N frames). */
+void
+il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct ieee80211_hdr *header;
+       struct ieee80211_rx_status rx_status;
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_rx_phy_res *phy_res;
+       __le32 rx_pkt_status;
+       struct il_rx_mpdu_res_start *amsdu;
+       u32 len;
+       u32 ampdu_status;
+       u32 rate_n_flags;
+
+       /**
+        * N_RX and N_RX_MPDU are handled differently.
+        *      N_RX: physical layer info is in this buffer
+        *      N_RX_MPDU: physical layer info was sent in separate
+        *              command and cached in il->last_phy_res
+        *
+        * Here we set up local variables depending on which command is
+        * received.
+        */
+       if (pkt->hdr.cmd == N_RX) {
+               phy_res = (struct il_rx_phy_res *)pkt->u.raw;
+               header =
+                   (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) +
+                                            phy_res->cfg_phy_cnt);
+
+               len = le16_to_cpu(phy_res->byte_count);
+               rx_pkt_status =
+                   *(__le32 *) (pkt->u.raw + sizeof(*phy_res) +
+                                phy_res->cfg_phy_cnt + len);
+               ampdu_status = le32_to_cpu(rx_pkt_status);
+       } else {
+               if (!il->_4965.last_phy_res_valid) {
+                       IL_ERR("MPDU frame without cached PHY data\n");
+                       return;
+               }
+               phy_res = &il->_4965.last_phy_res;
+               amsdu = (struct il_rx_mpdu_res_start *)pkt->u.raw;
+               header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
+               len = le16_to_cpu(amsdu->byte_count);
+               rx_pkt_status = *(__le32 *) (pkt->u.raw + sizeof(*amsdu) + len);
+               ampdu_status =
+                   il4965_translate_rx_status(il, le32_to_cpu(rx_pkt_status));
+       }
+
+       if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
+               D_DROP("dsp size out of range [0,20]: %d/n",
+                      phy_res->cfg_phy_cnt);
+               return;
+       }
+
+       if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
+           !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+               D_RX("Bad CRC or FIFO: 0x%08X.\n", le32_to_cpu(rx_pkt_status));
+               return;
+       }
+
+       /* This will be used in several places later */
+       rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
+
+       /* rx_status carries information about the packet to mac80211 */
+       rx_status.mactime = le64_to_cpu(phy_res->timestamp);
+       rx_status.band =
+           (phy_res->
+            phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ :
+           IEEE80211_BAND_5GHZ;
+       rx_status.freq =
+           ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
+                                          rx_status.band);
+       rx_status.rate_idx =
+           il4965_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
+       rx_status.flag = 0;
+
+       /* TSF isn't reliable. In order to allow smooth user experience,
+        * this W/A doesn't propagate it to the mac80211 */
+       /*rx_status.flag |= RX_FLAG_MACTIME_MPDU; */
+
+       il->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
+
+       /* Find max signal strength (dBm) among 3 antenna/receiver chains */
+       rx_status.signal = il4965_calc_rssi(il, phy_res);
+
+       il_dbg_log_rx_data_frame(il, len, header);
+       D_STATS("Rssi %d, TSF %llu\n", rx_status.signal,
+               (unsigned long long)rx_status.mactime);
+
+       /*
+        * "antenna number"
+        *
+        * It seems that the antenna field in the phy flags value
+        * is actually a bit field. This is undefined by radiotap,
+        * it wants an actual antenna number but I always get "7"
+        * for most legacy frames I receive indicating that the
+        * same frame was received on all three RX chains.
+        *
+        * I think this field should be removed in favor of a
+        * new 802.11n radiotap field "RX chains" that is defined
+        * as a bitmask.
+        */
+       rx_status.antenna =
+           (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) >>
+           RX_RES_PHY_FLAGS_ANTENNA_POS;
+
+       /* set the preamble flag if appropriate */
+       if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+               rx_status.flag |= RX_FLAG_SHORTPRE;
+
+       /* Set up the HT phy flags */
+       if (rate_n_flags & RATE_MCS_HT_MSK)
+               rx_status.flag |= RX_FLAG_HT;
+       if (rate_n_flags & RATE_MCS_HT40_MSK)
+               rx_status.flag |= RX_FLAG_40MHZ;
+       if (rate_n_flags & RATE_MCS_SGI_MSK)
+               rx_status.flag |= RX_FLAG_SHORT_GI;
+
+       il4965_pass_packet_to_mac80211(il, header, len, ampdu_status, rxb,
+                                      &rx_status);
+}
+
+/* Cache phy data (Rx signal strength, etc) for HT frame (N_RX_PHY).
+ * This will be used later in il_hdl_rx() for N_RX_MPDU. */
+void
+il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       il->_4965.last_phy_res_valid = true;
+       memcpy(&il->_4965.last_phy_res, pkt->u.raw,
+              sizeof(struct il_rx_phy_res));
+}
+
+static int
+il4965_get_channels_for_scan(struct il_priv *il, struct ieee80211_vif *vif,
+                            enum ieee80211_band band, u8 is_active,
+                            u8 n_probes, struct il_scan_channel *scan_ch)
+{
+       struct ieee80211_channel *chan;
+       const struct ieee80211_supported_band *sband;
+       const struct il_channel_info *ch_info;
+       u16 passive_dwell = 0;
+       u16 active_dwell = 0;
+       int added, i;
+       u16 channel;
+
+       sband = il_get_hw_mode(il, band);
+       if (!sband)
+               return 0;
+
+       active_dwell = il_get_active_dwell_time(il, band, n_probes);
+       passive_dwell = il_get_passive_dwell_time(il, band, vif);
+
+       if (passive_dwell <= active_dwell)
+               passive_dwell = active_dwell + 1;
+
+       for (i = 0, added = 0; i < il->scan_request->n_channels; i++) {
+               chan = il->scan_request->channels[i];
+
+               if (chan->band != band)
+                       continue;
+
+               channel = chan->hw_value;
+               scan_ch->channel = cpu_to_le16(channel);
+
+               ch_info = il_get_channel_info(il, band, channel);
+               if (!il_is_channel_valid(ch_info)) {
+                       D_SCAN("Channel %d is INVALID for this band.\n",
+                              channel);
+                       continue;
+               }
+
+               if (!is_active || il_is_channel_passive(ch_info) ||
+                   (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
+                       scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+               else
+                       scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
+
+               if (n_probes)
+                       scan_ch->type |= IL_SCAN_PROBE_MASK(n_probes);
+
+               scan_ch->active_dwell = cpu_to_le16(active_dwell);
+               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+
+               /* Set txpower levels to defaults */
+               scan_ch->dsp_atten = 110;
+
+               /* NOTE: if we were doing 6Mb OFDM for scans we'd use
+                * power level:
+                * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+                */
+               if (band == IEEE80211_BAND_5GHZ)
+                       scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+               else
+                       scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+
+               D_SCAN("Scanning ch=%d prob=0x%X [%s %d]\n", channel,
+                      le32_to_cpu(scan_ch->type),
+                      (scan_ch->
+                       type & SCAN_CHANNEL_TYPE_ACTIVE) ? "ACTIVE" : "PASSIVE",
+                      (scan_ch->
+                       type & SCAN_CHANNEL_TYPE_ACTIVE) ? active_dwell :
+                      passive_dwell);
+
+               scan_ch++;
+               added++;
+       }
+
+       D_SCAN("total channels to scan %d\n", added);
+       return added;
+}
+
+static inline u32
+il4965_ant_idx_to_flags(u8 ant_idx)
+{
+       return BIT(ant_idx) << RATE_MCS_ANT_POS;
+}
+
+int
+il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif)
+{
+       struct il_host_cmd cmd = {
+               .id = C_SCAN,
+               .len = sizeof(struct il_scan_cmd),
+               .flags = CMD_SIZE_HUGE,
+       };
+       struct il_scan_cmd *scan;
+       struct il_rxon_context *ctx = &il->ctx;
+       u32 rate_flags = 0;
+       u16 cmd_len;
+       u16 rx_chain = 0;
+       enum ieee80211_band band;
+       u8 n_probes = 0;
+       u8 rx_ant = il->hw_params.valid_rx_ant;
+       u8 rate;
+       bool is_active = false;
+       int chan_mod;
+       u8 active_chains;
+       u8 scan_tx_antennas = il->hw_params.valid_tx_ant;
+       int ret;
+
+       lockdep_assert_held(&il->mutex);
+
+       ctx = il_rxon_ctx_from_vif(vif);
+
+       if (!il->scan_cmd) {
+               il->scan_cmd =
+                   kmalloc(sizeof(struct il_scan_cmd) + IL_MAX_SCAN_SIZE,
+                           GFP_KERNEL);
+               if (!il->scan_cmd) {
+                       D_SCAN("fail to allocate memory for scan\n");
+                       return -ENOMEM;
+               }
+       }
+       scan = il->scan_cmd;
+       memset(scan, 0, sizeof(struct il_scan_cmd) + IL_MAX_SCAN_SIZE);
+
+       scan->quiet_plcp_th = IL_PLCP_QUIET_THRESH;
+       scan->quiet_time = IL_ACTIVE_QUIET_TIME;
+
+       if (il_is_any_associated(il)) {
+               u16 interval;
+               u32 extra;
+               u32 suspend_time = 100;
+               u32 scan_suspend_time = 100;
+
+               D_INFO("Scanning while associated...\n");
+               interval = vif->bss_conf.beacon_int;
+
+               scan->suspend_time = 0;
+               scan->max_out_time = cpu_to_le32(200 * 1024);
+               if (!interval)
+                       interval = suspend_time;
+
+               extra = (suspend_time / interval) << 22;
+               scan_suspend_time =
+                   (extra | ((suspend_time % interval) * 1024));
+               scan->suspend_time = cpu_to_le32(scan_suspend_time);
+               D_SCAN("suspend_time 0x%X beacon interval %d\n",
+                      scan_suspend_time, interval);
+       }
+
+       if (il->scan_request->n_ssids) {
+               int i, p = 0;
+               D_SCAN("Kicking off active scan\n");
+               for (i = 0; i < il->scan_request->n_ssids; i++) {
+                       /* always does wildcard anyway */
+                       if (!il->scan_request->ssids[i].ssid_len)
+                               continue;
+                       scan->direct_scan[p].id = WLAN_EID_SSID;
+                       scan->direct_scan[p].len =
+                           il->scan_request->ssids[i].ssid_len;
+                       memcpy(scan->direct_scan[p].ssid,
+                              il->scan_request->ssids[i].ssid,
+                              il->scan_request->ssids[i].ssid_len);
+                       n_probes++;
+                       p++;
+               }
+               is_active = true;
+       } else
+               D_SCAN("Start passive scan.\n");
+
+       scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
+       scan->tx_cmd.sta_id = ctx->bcast_sta_id;
+       scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+       switch (il->scan_band) {
+       case IEEE80211_BAND_2GHZ:
+               scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
+               chan_mod =
+                   le32_to_cpu(il->ctx.active.
+                               flags & RXON_FLG_CHANNEL_MODE_MSK) >>
+                   RXON_FLG_CHANNEL_MODE_POS;
+               if (chan_mod == CHANNEL_MODE_PURE_40) {
+                       rate = RATE_6M_PLCP;
+               } else {
+                       rate = RATE_1M_PLCP;
+                       rate_flags = RATE_MCS_CCK_MSK;
+               }
+               break;
+       case IEEE80211_BAND_5GHZ:
+               rate = RATE_6M_PLCP;
+               break;
+       default:
+               IL_WARN("Invalid scan band\n");
+               return -EIO;
+       }
+
+       /*
+        * If active scanning is requested but a certain channel is
+        * marked passive, we can do active scanning if we detect
+        * transmissions.
+        *
+        * There is an issue with some firmware versions that triggers
+        * a sysassert on a "good CRC threshold" of zero (== disabled),
+        * on a radar channel even though this means that we should NOT
+        * send probes.
+        *
+        * The "good CRC threshold" is the number of frames that we
+        * need to receive during our dwell time on a channel before
+        * sending out probes -- setting this to a huge value will
+        * mean we never reach it, but at the same time work around
+        * the aforementioned issue. Thus use IL_GOOD_CRC_TH_NEVER
+        * here instead of IL_GOOD_CRC_TH_DISABLED.
+        */
+       scan->good_CRC_th =
+           is_active ? IL_GOOD_CRC_TH_DEFAULT : IL_GOOD_CRC_TH_NEVER;
+
+       band = il->scan_band;
+
+       if (il->cfg->scan_rx_antennas[band])
+               rx_ant = il->cfg->scan_rx_antennas[band];
+
+       il->scan_tx_ant[band] =
+           il4965_toggle_tx_ant(il, il->scan_tx_ant[band], scan_tx_antennas);
+       rate_flags |= il4965_ant_idx_to_flags(il->scan_tx_ant[band]);
+       scan->tx_cmd.rate_n_flags =
+           il4965_hw_set_rate_n_flags(rate, rate_flags);
+
+       /* In power save mode use one chain, otherwise use all chains */
+       if (test_bit(S_POWER_PMI, &il->status)) {
+               /* rx_ant has been set to all valid chains previously */
+               active_chains =
+                   rx_ant & ((u8) (il->chain_noise_data.active_chains));
+               if (!active_chains)
+                       active_chains = rx_ant;
+
+               D_SCAN("chain_noise_data.active_chains: %u\n",
+                      il->chain_noise_data.active_chains);
+
+               rx_ant = il4965_first_antenna(active_chains);
+       }
+
+       /* MIMO is not used here, but value is required */
+       rx_chain |= il->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
+       rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
+       rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
+       rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
+       scan->rx_chain = cpu_to_le16(rx_chain);
+
+       cmd_len =
+           il_fill_probe_req(il, (struct ieee80211_mgmt *)scan->data,
+                             vif->addr, il->scan_request->ie,
+                             il->scan_request->ie_len,
+                             IL_MAX_SCAN_SIZE - sizeof(*scan));
+       scan->tx_cmd.len = cpu_to_le16(cmd_len);
+
+       scan->filter_flags |=
+           (RXON_FILTER_ACCEPT_GRP_MSK | RXON_FILTER_BCON_AWARE_MSK);
+
+       scan->channel_count =
+           il4965_get_channels_for_scan(il, vif, band, is_active, n_probes,
+                                        (void *)&scan->data[cmd_len]);
+       if (scan->channel_count == 0) {
+               D_SCAN("channel count %d\n", scan->channel_count);
+               return -EIO;
+       }
+
+       cmd.len +=
+           le16_to_cpu(scan->tx_cmd.len) +
+           scan->channel_count * sizeof(struct il_scan_channel);
+       cmd.data = scan;
+       scan->len = cpu_to_le16(cmd.len);
+
+       set_bit(S_SCAN_HW, &il->status);
+
+       ret = il_send_cmd_sync(il, &cmd);
+       if (ret)
+               clear_bit(S_SCAN_HW, &il->status);
+
+       return ret;
+}
+
+int
+il4965_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif,
+                          bool add)
+{
+       struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
+
+       if (add)
+               return il4965_add_bssid_station(il, vif_priv->ctx,
+                                               vif->bss_conf.bssid,
+                                               &vif_priv->ibss_bssid_sta_id);
+       return il_remove_station(il, vif_priv->ibss_bssid_sta_id,
+                                vif->bss_conf.bssid);
+}
+
+void
+il4965_free_tfds_in_queue(struct il_priv *il, int sta_id, int tid, int freed)
+{
+       lockdep_assert_held(&il->sta_lock);
+
+       if (il->stations[sta_id].tid[tid].tfds_in_queue >= freed)
+               il->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+       else {
+               D_TX("free more than tfds_in_queue (%u:%d)\n",
+                    il->stations[sta_id].tid[tid].tfds_in_queue, freed);
+               il->stations[sta_id].tid[tid].tfds_in_queue = 0;
+       }
+}
+
+#define IL_TX_QUEUE_MSK        0xfffff
+
+static bool
+il4965_is_single_rx_stream(struct il_priv *il)
+{
+       return il->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
+           il->current_ht_config.single_chain_sufficient;
+}
+
+#define IL_NUM_RX_CHAINS_MULTIPLE      3
+#define IL_NUM_RX_CHAINS_SINGLE        2
+#define IL_NUM_IDLE_CHAINS_DUAL        2
+#define IL_NUM_IDLE_CHAINS_SINGLE      1
+
+/*
+ * Determine how many receiver/antenna chains to use.
+ *
+ * More provides better reception via diversity.  Fewer saves power
+ * at the expense of throughput, but only when not in powersave to
+ * start with.
+ *
+ * MIMO (dual stream) requires at least 2, but works better with 3.
+ * This does not determine *which* chains to use, just how many.
+ */
+static int
+il4965_get_active_rx_chain_count(struct il_priv *il)
+{
+       /* # of Rx chains to use when expecting MIMO. */
+       if (il4965_is_single_rx_stream(il))
+               return IL_NUM_RX_CHAINS_SINGLE;
+       else
+               return IL_NUM_RX_CHAINS_MULTIPLE;
+}
+
+/*
+ * When we are in power saving mode, unless device support spatial
+ * multiplexing power save, use the active count for rx chain count.
+ */
+static int
+il4965_get_idle_rx_chain_count(struct il_priv *il, int active_cnt)
+{
+       /* # Rx chains when idling, depending on SMPS mode */
+       switch (il->current_ht_config.smps) {
+       case IEEE80211_SMPS_STATIC:
+       case IEEE80211_SMPS_DYNAMIC:
+               return IL_NUM_IDLE_CHAINS_SINGLE;
+       case IEEE80211_SMPS_OFF:
+               return active_cnt;
+       default:
+               WARN(1, "invalid SMPS mode %d", il->current_ht_config.smps);
+               return active_cnt;
+       }
+}
+
+/* up to 4 chains */
+static u8
+il4965_count_chain_bitmap(u32 chain_bitmap)
+{
+       u8 res;
+       res = (chain_bitmap & BIT(0)) >> 0;
+       res += (chain_bitmap & BIT(1)) >> 1;
+       res += (chain_bitmap & BIT(2)) >> 2;
+       res += (chain_bitmap & BIT(3)) >> 3;
+       return res;
+}
+
+/**
+ * il4965_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
+ *
+ * Selects how many and which Rx receivers/antennas/chains to use.
+ * This should not be used for scan command ... it puts data in wrong place.
+ */
+void
+il4965_set_rxon_chain(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       bool is_single = il4965_is_single_rx_stream(il);
+       bool is_cam = !test_bit(S_POWER_PMI, &il->status);
+       u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
+       u32 active_chains;
+       u16 rx_chain;
+
+       /* Tell uCode which antennas are actually connected.
+        * Before first association, we assume all antennas are connected.
+        * Just after first association, il4965_chain_noise_calibration()
+        *    checks which antennas actually *are* connected. */
+       if (il->chain_noise_data.active_chains)
+               active_chains = il->chain_noise_data.active_chains;
+       else
+               active_chains = il->hw_params.valid_rx_ant;
+
+       rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
+
+       /* How many receivers should we use? */
+       active_rx_cnt = il4965_get_active_rx_chain_count(il);
+       idle_rx_cnt = il4965_get_idle_rx_chain_count(il, active_rx_cnt);
+
+       /* correct rx chain count according hw settings
+        * and chain noise calibration
+        */
+       valid_rx_cnt = il4965_count_chain_bitmap(active_chains);
+       if (valid_rx_cnt < active_rx_cnt)
+               active_rx_cnt = valid_rx_cnt;
+
+       if (valid_rx_cnt < idle_rx_cnt)
+               idle_rx_cnt = valid_rx_cnt;
+
+       rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
+       rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
+
+       ctx->staging.rx_chain = cpu_to_le16(rx_chain);
+
+       if (!is_single && active_rx_cnt >= IL_NUM_RX_CHAINS_SINGLE && is_cam)
+               ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
+       else
+               ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
+
+       D_ASSOC("rx_chain=0x%X active=%d idle=%d\n", ctx->staging.rx_chain,
+               active_rx_cnt, idle_rx_cnt);
+
+       WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
+               active_rx_cnt < idle_rx_cnt);
+}
+
+u8
+il4965_toggle_tx_ant(struct il_priv *il, u8 ant, u8 valid)
+{
+       int i;
+       u8 ind = ant;
+
+       for (i = 0; i < RATE_ANT_NUM - 1; i++) {
+               ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
+               if (valid & BIT(ind))
+                       return ind;
+       }
+       return ant;
+}
+
+static const char *
+il4965_get_fh_string(int cmd)
+{
+       switch (cmd) {
+               IL_CMD(FH49_RSCSR_CHNL0_STTS_WPTR_REG);
+               IL_CMD(FH49_RSCSR_CHNL0_RBDCB_BASE_REG);
+               IL_CMD(FH49_RSCSR_CHNL0_WPTR);
+               IL_CMD(FH49_MEM_RCSR_CHNL0_CONFIG_REG);
+               IL_CMD(FH49_MEM_RSSR_SHARED_CTRL_REG);
+               IL_CMD(FH49_MEM_RSSR_RX_STATUS_REG);
+               IL_CMD(FH49_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
+               IL_CMD(FH49_TSSR_TX_STATUS_REG);
+               IL_CMD(FH49_TSSR_TX_ERROR_REG);
+       default:
+               return "UNKNOWN";
+       }
+}
+
+int
+il4965_dump_fh(struct il_priv *il, char **buf, bool display)
+{
+       int i;
+#ifdef CONFIG_IWLEGACY_DEBUG
+       int pos = 0;
+       size_t bufsz = 0;
+#endif
+       static const u32 fh_tbl[] = {
+               FH49_RSCSR_CHNL0_STTS_WPTR_REG,
+               FH49_RSCSR_CHNL0_RBDCB_BASE_REG,
+               FH49_RSCSR_CHNL0_WPTR,
+               FH49_MEM_RCSR_CHNL0_CONFIG_REG,
+               FH49_MEM_RSSR_SHARED_CTRL_REG,
+               FH49_MEM_RSSR_RX_STATUS_REG,
+               FH49_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
+               FH49_TSSR_TX_STATUS_REG,
+               FH49_TSSR_TX_ERROR_REG
+       };
+#ifdef CONFIG_IWLEGACY_DEBUG
+       if (display) {
+               bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+               *buf = kmalloc(bufsz, GFP_KERNEL);
+               if (!*buf)
+                       return -ENOMEM;
+               pos +=
+                   scnprintf(*buf + pos, bufsz - pos, "FH register values:\n");
+               for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+                       pos +=
+                           scnprintf(*buf + pos, bufsz - pos,
+                                     "  %34s: 0X%08x\n",
+                                     il4965_get_fh_string(fh_tbl[i]),
+                                     il_rd(il, fh_tbl[i]));
+               }
+               return pos;
+       }
+#endif
+       IL_ERR("FH register values:\n");
+       for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+               IL_ERR("  %34s: 0X%08x\n", il4965_get_fh_string(fh_tbl[i]),
+                      il_rd(il, fh_tbl[i]));
+       }
+       return 0;
+}
+
+void
+il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_missed_beacon_notif *missed_beacon;
+
+       missed_beacon = &pkt->u.missed_beacon;
+       if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
+           il->missed_beacon_threshold) {
+               D_CALIB("missed bcn cnsq %d totl %d rcd %d expctd %d\n",
+                       le32_to_cpu(missed_beacon->consecutive_missed_beacons),
+                       le32_to_cpu(missed_beacon->total_missed_becons),
+                       le32_to_cpu(missed_beacon->num_recvd_beacons),
+                       le32_to_cpu(missed_beacon->num_expected_beacons));
+               if (!test_bit(S_SCANNING, &il->status))
+                       il4965_init_sensitivity(il);
+       }
+}
+
+/* Calculate noise level, based on measurements during network silence just
+ *   before arriving beacon.  This measurement can be done only if we know
+ *   exactly when to expect beacons, therefore only when we're associated. */
+static void
+il4965_rx_calc_noise(struct il_priv *il)
+{
+       struct stats_rx_non_phy *rx_info;
+       int num_active_rx = 0;
+       int total_silence = 0;
+       int bcn_silence_a, bcn_silence_b, bcn_silence_c;
+       int last_rx_noise;
+
+       rx_info = &(il->_4965.stats.rx.general);
+       bcn_silence_a =
+           le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
+       bcn_silence_b =
+           le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
+       bcn_silence_c =
+           le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
+
+       if (bcn_silence_a) {
+               total_silence += bcn_silence_a;
+               num_active_rx++;
+       }
+       if (bcn_silence_b) {
+               total_silence += bcn_silence_b;
+               num_active_rx++;
+       }
+       if (bcn_silence_c) {
+               total_silence += bcn_silence_c;
+               num_active_rx++;
+       }
+
+       /* Average among active antennas */
+       if (num_active_rx)
+               last_rx_noise = (total_silence / num_active_rx) - 107;
+       else
+               last_rx_noise = IL_NOISE_MEAS_NOT_AVAILABLE;
+
+       D_CALIB("inband silence a %u, b %u, c %u, dBm %d\n", bcn_silence_a,
+               bcn_silence_b, bcn_silence_c, last_rx_noise);
+}
+
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+/*
+ *  based on the assumption of all stats counter are in DWORD
+ *  FIXME: This function is for debugging, do not deal with
+ *  the case of counters roll-over.
+ */
+static void
+il4965_accumulative_stats(struct il_priv *il, __le32 * stats)
+{
+       int i, size;
+       __le32 *prev_stats;
+       u32 *accum_stats;
+       u32 *delta, *max_delta;
+       struct stats_general_common *general, *accum_general;
+       struct stats_tx *tx, *accum_tx;
+
+       prev_stats = (__le32 *) &il->_4965.stats;
+       accum_stats = (u32 *) &il->_4965.accum_stats;
+       size = sizeof(struct il_notif_stats);
+       general = &il->_4965.stats.general.common;
+       accum_general = &il->_4965.accum_stats.general.common;
+       tx = &il->_4965.stats.tx;
+       accum_tx = &il->_4965.accum_stats.tx;
+       delta = (u32 *) &il->_4965.delta_stats;
+       max_delta = (u32 *) &il->_4965.max_delta;
+
+       for (i = sizeof(__le32); i < size;
+            i +=
+            sizeof(__le32), stats++, prev_stats++, delta++, max_delta++,
+            accum_stats++) {
+               if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
+                       *delta =
+                           (le32_to_cpu(*stats) - le32_to_cpu(*prev_stats));
+                       *accum_stats += *delta;
+                       if (*delta > *max_delta)
+                               *max_delta = *delta;
+               }
+       }
+
+       /* reset accumulative stats for "no-counter" type stats */
+       accum_general->temperature = general->temperature;
+       accum_general->ttl_timestamp = general->ttl_timestamp;
+}
+#endif
+
+#define REG_RECALIB_PERIOD (60)
+
+void
+il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       int change;
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+
+       D_RX("Statistics notification received (%d vs %d).\n",
+            (int)sizeof(struct il_notif_stats),
+            le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK);
+
+       change =
+           ((il->_4965.stats.general.common.temperature !=
+             pkt->u.stats.general.common.temperature) ||
+            ((il->_4965.stats.flag & STATS_REPLY_FLG_HT40_MODE_MSK) !=
+             (pkt->u.stats.flag & STATS_REPLY_FLG_HT40_MODE_MSK)));
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+       il4965_accumulative_stats(il, (__le32 *) &pkt->u.stats);
+#endif
+
+       /* TODO: reading some of stats is unneeded */
+       memcpy(&il->_4965.stats, &pkt->u.stats, sizeof(il->_4965.stats));
+
+       set_bit(S_STATS, &il->status);
+
+       /* Reschedule the stats timer to occur in
+        * REG_RECALIB_PERIOD seconds to ensure we get a
+        * thermal update even if the uCode doesn't give
+        * us one */
+       mod_timer(&il->stats_periodic,
+                 jiffies + msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
+
+       if (unlikely(!test_bit(S_SCANNING, &il->status)) &&
+           (pkt->hdr.cmd == N_STATS)) {
+               il4965_rx_calc_noise(il);
+               queue_work(il->workqueue, &il->run_time_calib_work);
+       }
+       if (il->cfg->ops->lib->temp_ops.temperature && change)
+               il->cfg->ops->lib->temp_ops.temperature(il);
+}
+
+void
+il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+
+       if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATS_CLEAR_MSK) {
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+               memset(&il->_4965.accum_stats, 0,
+                      sizeof(struct il_notif_stats));
+               memset(&il->_4965.delta_stats, 0,
+                      sizeof(struct il_notif_stats));
+               memset(&il->_4965.max_delta, 0, sizeof(struct il_notif_stats));
+#endif
+               D_RX("Statistics have been cleared\n");
+       }
+       il4965_hdl_stats(il, rxb);
+}
+
+
+/*
+ * mac80211 queues, ACs, hardware queues, FIFOs.
+ *
+ * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
+ *
+ * Mac80211 uses the following numbers, which we get as from it
+ * by way of skb_get_queue_mapping(skb):
+ *
+ *     VO      0
+ *     VI      1
+ *     BE      2
+ *     BK      3
+ *
+ *
+ * Regular (not A-MPDU) frames are put into hardware queues corresponding
+ * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
+ * own queue per aggregation session (RA/TID combination), such queues are
+ * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
+ * order to map frames to the right queue, we also need an AC->hw queue
+ * mapping. This is implemented here.
+ *
+ * Due to the way hw queues are set up (by the hw specific modules like
+ * 4965.c), the AC->hw queue mapping is the identity
+ * mapping.
+ */
+
+static const u8 tid_to_ac[] = {
+       IEEE80211_AC_BE,
+       IEEE80211_AC_BK,
+       IEEE80211_AC_BK,
+       IEEE80211_AC_BE,
+       IEEE80211_AC_VI,
+       IEEE80211_AC_VI,
+       IEEE80211_AC_VO,
+       IEEE80211_AC_VO
+};
+
+static inline int
+il4965_get_ac_from_tid(u16 tid)
+{
+       if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+               return tid_to_ac[tid];
+
+       /* no support for TIDs 8-15 yet */
+       return -EINVAL;
+}
+
+static inline int
+il4965_get_fifo_from_tid(struct il_rxon_context *ctx, u16 tid)
+{
+       if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+               return ctx->ac_to_fifo[tid_to_ac[tid]];
+
+       /* no support for TIDs 8-15 yet */
+       return -EINVAL;
+}
+
+/*
+ * handle build C_TX command notification.
+ */
+static void
+il4965_tx_cmd_build_basic(struct il_priv *il, struct sk_buff *skb,
+                         struct il_tx_cmd *tx_cmd,
+                         struct ieee80211_tx_info *info,
+                         struct ieee80211_hdr *hdr, u8 std_id)
+{
+       __le16 fc = hdr->frame_control;
+       __le32 tx_flags = tx_cmd->tx_flags;
+
+       tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+               tx_flags |= TX_CMD_FLG_ACK_MSK;
+               if (ieee80211_is_mgmt(fc))
+                       tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+               if (ieee80211_is_probe_resp(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;
+       }
+
+       if (ieee80211_is_back_req(fc))
+               tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
+
+       tx_cmd->sta_id = std_id;
+       if (ieee80211_has_morefrags(fc))
+               tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
+
+       if (ieee80211_is_data_qos(fc)) {
+               u8 *qc = ieee80211_get_qos_ctl(hdr);
+               tx_cmd->tid_tspec = qc[0] & 0xf;
+               tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
+       } else {
+               tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+       }
+
+       il_tx_cmd_protection(il, info, fc, &tx_flags);
+
+       tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
+       if (ieee80211_is_mgmt(fc)) {
+               if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
+                       tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
+               else
+                       tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
+       } else {
+               tx_cmd->timeout.pm_frame_timeout = 0;
+       }
+
+       tx_cmd->driver_txop = 0;
+       tx_cmd->tx_flags = tx_flags;
+       tx_cmd->next_frame_len = 0;
+}
+
+#define RTS_DFAULT_RETRY_LIMIT         60
+
+static void
+il4965_tx_cmd_build_rate(struct il_priv *il, struct il_tx_cmd *tx_cmd,
+                        struct ieee80211_tx_info *info, __le16 fc)
+{
+       u32 rate_flags;
+       int rate_idx;
+       u8 rts_retry_limit;
+       u8 data_retry_limit;
+       u8 rate_plcp;
+
+       /* Set retry limit on DATA packets and Probe Responses */
+       if (ieee80211_is_probe_resp(fc))
+               data_retry_limit = 3;
+       else
+               data_retry_limit = IL4965_DEFAULT_TX_RETRY;
+       tx_cmd->data_retry_limit = data_retry_limit;
+
+       /* Set retry limit on RTS packets */
+       rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
+       if (data_retry_limit < rts_retry_limit)
+               rts_retry_limit = data_retry_limit;
+       tx_cmd->rts_retry_limit = rts_retry_limit;
+
+       /* DATA packets will use the uCode station table for rate/antenna
+        * selection */
+       if (ieee80211_is_data(fc)) {
+               tx_cmd->initial_rate_idx = 0;
+               tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
+               return;
+       }
+
+       /**
+        * If the current TX rate stored in mac80211 has the MCS bit set, it's
+        * not really a TX rate.  Thus, we use the lowest supported rate for
+        * this band.  Also use the lowest supported rate if the stored rate
+        * idx is invalid.
+        */
+       rate_idx = info->control.rates[0].idx;
+       if ((info->control.rates[0].flags & IEEE80211_TX_RC_MCS) || rate_idx < 0
+           || rate_idx > RATE_COUNT_LEGACY)
+               rate_idx =
+                   rate_lowest_index(&il->bands[info->band],
+                                     info->control.sta);
+       /* For 5 GHZ band, remap mac80211 rate indices into driver indices */
+       if (info->band == IEEE80211_BAND_5GHZ)
+               rate_idx += IL_FIRST_OFDM_RATE;
+       /* Get PLCP rate for tx_cmd->rate_n_flags */
+       rate_plcp = il_rates[rate_idx].plcp;
+       /* Zero out flags for this packet */
+       rate_flags = 0;
+
+       /* Set CCK flag as needed */
+       if (rate_idx >= IL_FIRST_CCK_RATE && rate_idx <= IL_LAST_CCK_RATE)
+               rate_flags |= RATE_MCS_CCK_MSK;
+
+       /* Set up antennas */
+       il->mgmt_tx_ant =
+           il4965_toggle_tx_ant(il, il->mgmt_tx_ant,
+                                il->hw_params.valid_tx_ant);
+
+       rate_flags |= il4965_ant_idx_to_flags(il->mgmt_tx_ant);
+
+       /* Set the rate in the TX cmd */
+       tx_cmd->rate_n_flags =
+           il4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
+}
+
+static void
+il4965_tx_cmd_build_hwcrypto(struct il_priv *il, struct ieee80211_tx_info *info,
+                            struct il_tx_cmd *tx_cmd, struct sk_buff *skb_frag,
+                            int sta_id)
+{
+       struct ieee80211_key_conf *keyconf = info->control.hw_key;
+
+       switch (keyconf->cipher) {
+       case WLAN_CIPHER_SUITE_CCMP:
+               tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
+               memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
+               if (info->flags & IEEE80211_TX_CTL_AMPDU)
+                       tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
+               D_TX("tx_cmd with AES hwcrypto\n");
+               break;
+
+       case WLAN_CIPHER_SUITE_TKIP:
+               tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
+               ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
+               D_TX("tx_cmd with tkip hwcrypto\n");
+               break;
+
+       case WLAN_CIPHER_SUITE_WEP104:
+               tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+               /* fall through */
+       case WLAN_CIPHER_SUITE_WEP40:
+               tx_cmd->sec_ctl |=
+                   (TX_CMD_SEC_WEP | (keyconf->keyidx & TX_CMD_SEC_MSK) <<
+                    TX_CMD_SEC_SHIFT);
+
+               memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
+
+               D_TX("Configuring packet for WEP encryption " "with key %d\n",
+                    keyconf->keyidx);
+               break;
+
+       default:
+               IL_ERR("Unknown encode cipher %x\n", keyconf->cipher);
+               break;
+       }
+}
+
+/*
+ * start C_TX command process
+ */
+int
+il4965_tx_skb(struct il_priv *il, struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_sta *sta = info->control.sta;
+       struct il_station_priv *sta_priv = NULL;
+       struct il_tx_queue *txq;
+       struct il_queue *q;
+       struct il_device_cmd *out_cmd;
+       struct il_cmd_meta *out_meta;
+       struct il_tx_cmd *tx_cmd;
+       struct il_rxon_context *ctx = &il->ctx;
+       int txq_id;
+       dma_addr_t phys_addr;
+       dma_addr_t txcmd_phys;
+       dma_addr_t scratch_phys;
+       u16 len, firstlen, secondlen;
+       u16 seq_number = 0;
+       __le16 fc;
+       u8 hdr_len;
+       u8 sta_id;
+       u8 wait_write_ptr = 0;
+       u8 tid = 0;
+       u8 *qc = NULL;
+       unsigned long flags;
+       bool is_agg = false;
+
+       if (info->control.vif)
+               ctx = il_rxon_ctx_from_vif(info->control.vif);
+
+       spin_lock_irqsave(&il->lock, flags);
+       if (il_is_rfkill(il)) {
+               D_DROP("Dropping - RF KILL\n");
+               goto drop_unlock;
+       }
+
+       fc = hdr->frame_control;
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+       if (ieee80211_is_auth(fc))
+               D_TX("Sending AUTH frame\n");
+       else if (ieee80211_is_assoc_req(fc))
+               D_TX("Sending ASSOC frame\n");
+       else if (ieee80211_is_reassoc_req(fc))
+               D_TX("Sending REASSOC frame\n");
+#endif
+
+       hdr_len = ieee80211_hdrlen(fc);
+
+       /* For management frames use broadcast id to do not break aggregation */
+       if (!ieee80211_is_data(fc))
+               sta_id = ctx->bcast_sta_id;
+       else {
+               /* Find idx into station table for destination station */
+               sta_id = il_sta_id_or_broadcast(il, ctx, info->control.sta);
+
+               if (sta_id == IL_INVALID_STATION) {
+                       D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1);
+                       goto drop_unlock;
+               }
+       }
+
+       D_TX("station Id %d\n", sta_id);
+
+       if (sta)
+               sta_priv = (void *)sta->drv_priv;
+
+       if (sta_priv && sta_priv->asleep &&
+           (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) {
+               /*
+                * This sends an asynchronous command to the device,
+                * but we can rely on it being processed before the
+                * next frame is processed -- and the next frame to
+                * this station is the one that will consume this
+                * counter.
+                * For now set the counter to just 1 since we do not
+                * support uAPSD yet.
+                */
+               il4965_sta_modify_sleep_tx_count(il, sta_id, 1);
+       }
+
+       /*
+        * Send this frame after DTIM -- there's a special queue
+        * reserved for this for contexts that support AP mode.
+        */
+       if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+               txq_id = ctx->mcast_queue;
+               /*
+                * The microcode will clear the more data
+                * bit in the last frame it transmits.
+                */
+               hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+       } else
+               txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
+
+       /* irqs already disabled/saved above when locking il->lock */
+       spin_lock(&il->sta_lock);
+
+       if (ieee80211_is_data_qos(fc)) {
+               qc = ieee80211_get_qos_ctl(hdr);
+               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+               if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) {
+                       spin_unlock(&il->sta_lock);
+                       goto drop_unlock;
+               }
+               seq_number = il->stations[sta_id].tid[tid].seq_number;
+               seq_number &= IEEE80211_SCTL_SEQ;
+               hdr->seq_ctrl =
+                   hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG);
+               hdr->seq_ctrl |= cpu_to_le16(seq_number);
+               seq_number += 0x10;
+               /* aggregation is on for this <sta,tid> */
+               if (info->flags & IEEE80211_TX_CTL_AMPDU &&
+                   il->stations[sta_id].tid[tid].agg.state == IL_AGG_ON) {
+                       txq_id = il->stations[sta_id].tid[tid].agg.txq_id;
+                       is_agg = true;
+               }
+       }
+
+       txq = &il->txq[txq_id];
+       q = &txq->q;
+
+       if (unlikely(il_queue_space(q) < q->high_mark)) {
+               spin_unlock(&il->sta_lock);
+               goto drop_unlock;
+       }
+
+       if (ieee80211_is_data_qos(fc)) {
+               il->stations[sta_id].tid[tid].tfds_in_queue++;
+               if (!ieee80211_has_morefrags(fc))
+                       il->stations[sta_id].tid[tid].seq_number = seq_number;
+       }
+
+       spin_unlock(&il->sta_lock);
+
+       /* Set up driver data for this TFD */
+       memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct il_tx_info));
+       txq->txb[q->write_ptr].skb = skb;
+       txq->txb[q->write_ptr].ctx = ctx;
+
+       /* Set up first empty entry in queue's array of Tx/cmd buffers */
+       out_cmd = txq->cmd[q->write_ptr];
+       out_meta = &txq->meta[q->write_ptr];
+       tx_cmd = &out_cmd->cmd.tx;
+       memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
+       memset(tx_cmd, 0, sizeof(struct il_tx_cmd));
+
+       /*
+        * Set up the Tx-command (not MAC!) header.
+        * Store the chosen Tx queue and TFD idx within the sequence field;
+        * after Tx, uCode's Tx response will return this value so driver can
+        * locate the frame within the tx queue and do post-tx processing.
+        */
+       out_cmd->hdr.cmd = C_TX;
+       out_cmd->hdr.sequence =
+           cpu_to_le16((u16)
+                       (QUEUE_TO_SEQ(txq_id) | IDX_TO_SEQ(q->write_ptr)));
+
+       /* Copy MAC header from skb into command buffer */
+       memcpy(tx_cmd->hdr, hdr, hdr_len);
+
+       /* Total # bytes to be transmitted */
+       len = (u16) skb->len;
+       tx_cmd->len = cpu_to_le16(len);
+
+       if (info->control.hw_key)
+               il4965_tx_cmd_build_hwcrypto(il, info, tx_cmd, skb, sta_id);
+
+       /* TODO need this for burst mode later on */
+       il4965_tx_cmd_build_basic(il, skb, tx_cmd, info, hdr, sta_id);
+       il_dbg_log_tx_data_frame(il, len, hdr);
+
+       il4965_tx_cmd_build_rate(il, tx_cmd, info, fc);
+
+       il_update_stats(il, true, fc, len);
+       /*
+        * Use the first empty entry in this queue's command buffer array
+        * to contain the Tx command and MAC header concatenated together
+        * (payload data will be in another buffer).
+        * Size of this varies, due to varying MAC header length.
+        * If end is not dword aligned, we'll have 2 extra bytes at the end
+        * of the MAC header (device reads on dword boundaries).
+        * We'll tell device about this padding later.
+        */
+       len = sizeof(struct il_tx_cmd) + sizeof(struct il_cmd_header) + hdr_len;
+       firstlen = (len + 3) & ~3;
+
+       /* Tell NIC about any 2-byte padding after MAC header */
+       if (firstlen != len)
+               tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
+
+       /* Physical address of this Tx command's header (not MAC header!),
+        * within command buffer array. */
+       txcmd_phys =
+           pci_map_single(il->pci_dev, &out_cmd->hdr, firstlen,
+                          PCI_DMA_BIDIRECTIONAL);
+       dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+       dma_unmap_len_set(out_meta, len, firstlen);
+       /* Add buffer containing Tx command and MAC(!) header to TFD's
+        * first entry */
+       il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen,
+                                                1, 0);
+
+       if (!ieee80211_has_morefrags(hdr->frame_control)) {
+               txq->need_update = 1;
+       } else {
+               wait_write_ptr = 1;
+               txq->need_update = 0;
+       }
+
+       /* Set up TFD's 2nd entry to point directly to remainder of skb,
+        * if any (802.11 null frames have no payload). */
+       secondlen = skb->len - hdr_len;
+       if (secondlen > 0) {
+               phys_addr =
+                   pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen,
+                                  PCI_DMA_TODEVICE);
+               il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr,
+                                                        secondlen, 0, 0);
+       }
+
+       scratch_phys =
+           txcmd_phys + sizeof(struct il_cmd_header) +
+           offsetof(struct il_tx_cmd, scratch);
+
+       /* take back ownership of DMA buffer to enable update */
+       pci_dma_sync_single_for_cpu(il->pci_dev, txcmd_phys, firstlen,
+                                   PCI_DMA_BIDIRECTIONAL);
+       tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
+       tx_cmd->dram_msb_ptr = il_get_dma_hi_addr(scratch_phys);
+
+       D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence));
+       D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
+       il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd, sizeof(*tx_cmd));
+       il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd->hdr, hdr_len);
+
+       /* Set up entry for this TFD in Tx byte-count array */
+       if (info->flags & IEEE80211_TX_CTL_AMPDU)
+               il->cfg->ops->lib->txq_update_byte_cnt_tbl(il, txq,
+                                                          le16_to_cpu(tx_cmd->
+                                                                      len));
+
+       pci_dma_sync_single_for_device(il->pci_dev, txcmd_phys, firstlen,
+                                      PCI_DMA_BIDIRECTIONAL);
+
+       /* Tell device the write idx *just past* this latest filled TFD */
+       q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);
+       il_txq_update_write_ptr(il, txq);
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       /*
+        * At this point the frame is "transmitted" successfully
+        * and we will get a TX status notification eventually,
+        * regardless of the value of ret. "ret" only indicates
+        * whether or not we should update the write pointer.
+        */
+
+       /*
+        * Avoid atomic ops if it isn't an associated client.
+        * Also, if this is a packet for aggregation, don't
+        * increase the counter because the ucode will stop
+        * aggregation queues when their respective station
+        * goes to sleep.
+        */
+       if (sta_priv && sta_priv->client && !is_agg)
+               atomic_inc(&sta_priv->pending_frames);
+
+       if (il_queue_space(q) < q->high_mark && il->mac80211_registered) {
+               if (wait_write_ptr) {
+                       spin_lock_irqsave(&il->lock, flags);
+                       txq->need_update = 1;
+                       il_txq_update_write_ptr(il, txq);
+                       spin_unlock_irqrestore(&il->lock, flags);
+               } else {
+                       il_stop_queue(il, txq);
+               }
+       }
+
+       return 0;
+
+drop_unlock:
+       spin_unlock_irqrestore(&il->lock, flags);
+       return -1;
+}
+
+static inline int
+il4965_alloc_dma_ptr(struct il_priv *il, struct il_dma_ptr *ptr, size_t size)
+{
+       ptr->addr =
+           dma_alloc_coherent(&il->pci_dev->dev, size, &ptr->dma, GFP_KERNEL);
+       if (!ptr->addr)
+               return -ENOMEM;
+       ptr->size = size;
+       return 0;
+}
+
+static inline void
+il4965_free_dma_ptr(struct il_priv *il, struct il_dma_ptr *ptr)
+{
+       if (unlikely(!ptr->addr))
+               return;
+
+       dma_free_coherent(&il->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
+       memset(ptr, 0, sizeof(*ptr));
+}
+
+/**
+ * il4965_hw_txq_ctx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void
+il4965_hw_txq_ctx_free(struct il_priv *il)
+{
+       int txq_id;
+
+       /* Tx queues */
+       if (il->txq) {
+               for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
+                       if (txq_id == il->cmd_queue)
+                               il_cmd_queue_free(il);
+                       else
+                               il_tx_queue_free(il, txq_id);
+       }
+       il4965_free_dma_ptr(il, &il->kw);
+
+       il4965_free_dma_ptr(il, &il->scd_bc_tbls);
+
+       /* free tx queue structure */
+       il_txq_mem(il);
+}
+
+/**
+ * il4965_txq_ctx_alloc - allocate TX queue context
+ * Allocate all Tx DMA structures and initialize them
+ *
+ * @param il
+ * @return error code
+ */
+int
+il4965_txq_ctx_alloc(struct il_priv *il)
+{
+       int ret;
+       int txq_id, slots_num;
+       unsigned long flags;
+
+       /* Free all tx/cmd queues and keep-warm buffer */
+       il4965_hw_txq_ctx_free(il);
+
+       ret =
+           il4965_alloc_dma_ptr(il, &il->scd_bc_tbls,
+                                il->hw_params.scd_bc_tbls_size);
+       if (ret) {
+               IL_ERR("Scheduler BC Table allocation failed\n");
+               goto error_bc_tbls;
+       }
+       /* Alloc keep-warm buffer */
+       ret = il4965_alloc_dma_ptr(il, &il->kw, IL_KW_SIZE);
+       if (ret) {
+               IL_ERR("Keep Warm allocation failed\n");
+               goto error_kw;
+       }
+
+       /* allocate tx queue structure */
+       ret = il_alloc_txq_mem(il);
+       if (ret)
+               goto error;
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       /* Turn off all Tx DMA fifos */
+       il4965_txq_set_sched(il, 0);
+
+       /* Tell NIC where to find the "keep warm" buffer */
+       il_wr(il, FH49_KW_MEM_ADDR_REG, il->kw.dma >> 4);
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       /* Alloc and init all Tx queues, including the command queue (#4/#9) */
+       for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
+               slots_num =
+                   (txq_id ==
+                    il->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+               ret = il_tx_queue_init(il, &il->txq[txq_id], slots_num, txq_id);
+               if (ret) {
+                       IL_ERR("Tx %d queue init failed\n", txq_id);
+                       goto error;
+               }
+       }
+
+       return ret;
+
+error:
+       il4965_hw_txq_ctx_free(il);
+       il4965_free_dma_ptr(il, &il->kw);
+error_kw:
+       il4965_free_dma_ptr(il, &il->scd_bc_tbls);
+error_bc_tbls:
+       return ret;
+}
+
+void
+il4965_txq_ctx_reset(struct il_priv *il)
+{
+       int txq_id, slots_num;
+       unsigned long flags;
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       /* Turn off all Tx DMA fifos */
+       il4965_txq_set_sched(il, 0);
+
+       /* Tell NIC where to find the "keep warm" buffer */
+       il_wr(il, FH49_KW_MEM_ADDR_REG, il->kw.dma >> 4);
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       /* Alloc and init all Tx queues, including the command queue (#4) */
+       for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
+               slots_num =
+                   txq_id == il->cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+               il_tx_queue_reset(il, &il->txq[txq_id], slots_num, txq_id);
+       }
+}
+
+/**
+ * il4965_txq_ctx_stop - Stop all Tx DMA channels
+ */
+void
+il4965_txq_ctx_stop(struct il_priv *il)
+{
+       int ch, txq_id;
+       unsigned long flags;
+
+       /* Turn off all Tx DMA fifos */
+       spin_lock_irqsave(&il->lock, flags);
+
+       il4965_txq_set_sched(il, 0);
+
+       /* Stop each Tx DMA channel, and wait for it to be idle */
+       for (ch = 0; ch < il->hw_params.dma_chnl_num; ch++) {
+               il_wr(il, FH49_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
+               if (il_poll_bit
+                   (il, FH49_TSSR_TX_STATUS_REG,
+                    FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000))
+                       IL_ERR("Failing on timeout while stopping"
+                              " DMA channel %d [0x%08x]", ch,
+                              il_rd(il, FH49_TSSR_TX_STATUS_REG));
+       }
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       if (!il->txq)
+               return;
+
+       /* Unmap DMA from host system and free skb's */
+       for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
+               if (txq_id == il->cmd_queue)
+                       il_cmd_queue_unmap(il);
+               else
+                       il_tx_queue_unmap(il, txq_id);
+}
+
+/*
+ * Find first available (lowest unused) Tx Queue, mark it "active".
+ * Called only when finding queue for aggregation.
+ * Should never return anything < 7, because they should already
+ * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
+ */
+static int
+il4965_txq_ctx_activate_free(struct il_priv *il)
+{
+       int txq_id;
+
+       for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
+               if (!test_and_set_bit(txq_id, &il->txq_ctx_active_msk))
+                       return txq_id;
+       return -1;
+}
+
+/**
+ * il4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
+ */
+static void
+il4965_tx_queue_stop_scheduler(struct il_priv *il, u16 txq_id)
+{
+       /* Simply stop the queue, but don't change any configuration;
+        * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
+       il_wr_prph(il, IL49_SCD_QUEUE_STATUS_BITS(txq_id),
+                  (0 << IL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
+                  (1 << IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
+}
+
+/**
+ * il4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
+ */
+static int
+il4965_tx_queue_set_q2ratid(struct il_priv *il, u16 ra_tid, u16 txq_id)
+{
+       u32 tbl_dw_addr;
+       u32 tbl_dw;
+       u16 scd_q2ratid;
+
+       scd_q2ratid = ra_tid & IL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
+
+       tbl_dw_addr =
+           il->scd_base_addr + IL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
+
+       tbl_dw = il_read_targ_mem(il, tbl_dw_addr);
+
+       if (txq_id & 0x1)
+               tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
+       else
+               tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
+
+       il_write_targ_mem(il, tbl_dw_addr, tbl_dw);
+
+       return 0;
+}
+
+/**
+ * il4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
+ *
+ * NOTE:  txq_id must be greater than IL49_FIRST_AMPDU_QUEUE,
+ *        i.e. it must be one of the higher queues used for aggregation
+ */
+static int
+il4965_txq_agg_enable(struct il_priv *il, int txq_id, int tx_fifo, int sta_id,
+                     int tid, u16 ssn_idx)
+{
+       unsigned long flags;
+       u16 ra_tid;
+       int ret;
+
+       if ((IL49_FIRST_AMPDU_QUEUE > txq_id) ||
+           (IL49_FIRST_AMPDU_QUEUE +
+            il->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
+               IL_WARN("queue number out of range: %d, must be %d to %d\n",
+                       txq_id, IL49_FIRST_AMPDU_QUEUE,
+                       IL49_FIRST_AMPDU_QUEUE +
+                       il->cfg->base_params->num_of_ampdu_queues - 1);
+               return -EINVAL;
+       }
+
+       ra_tid = BUILD_RAxTID(sta_id, tid);
+
+       /* Modify device's station table to Tx this TID */
+       ret = il4965_sta_tx_modify_enable_tid(il, sta_id, tid);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       /* Stop this Tx queue before configuring it */
+       il4965_tx_queue_stop_scheduler(il, txq_id);
+
+       /* Map receiver-address / traffic-ID to this queue */
+       il4965_tx_queue_set_q2ratid(il, ra_tid, txq_id);
+
+       /* Set this queue as a chain-building queue */
+       il_set_bits_prph(il, IL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
+
+       /* Place first TFD at idx corresponding to start sequence number.
+        * Assumes that ssn_idx is valid (!= 0xFFF) */
+       il->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+       il->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+       il4965_set_wr_ptrs(il, txq_id, ssn_idx);
+
+       /* Set up Tx win size and frame limit for this queue */
+       il_write_targ_mem(il,
+                         il->scd_base_addr +
+                         IL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id),
+                         (SCD_WIN_SIZE << IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS)
+                         & IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
+
+       il_write_targ_mem(il,
+                         il->scd_base_addr +
+                         IL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
+                         (SCD_FRAME_LIMIT <<
+                          IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
+                         IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
+
+       il_set_bits_prph(il, IL49_SCD_INTERRUPT_MASK, (1 << txq_id));
+
+       /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
+       il4965_tx_queue_set_status(il, &il->txq[txq_id], tx_fifo, 1);
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       return 0;
+}
+
+int
+il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif,
+                   struct ieee80211_sta *sta, u16 tid, u16 * ssn)
+{
+       int sta_id;
+       int tx_fifo;
+       int txq_id;
+       int ret;
+       unsigned long flags;
+       struct il_tid_data *tid_data;
+
+       tx_fifo = il4965_get_fifo_from_tid(il_rxon_ctx_from_vif(vif), tid);
+       if (unlikely(tx_fifo < 0))
+               return tx_fifo;
+
+       D_HT("%s on ra = %pM tid = %d\n", __func__, sta->addr, tid);
+
+       sta_id = il_sta_id(sta);
+       if (sta_id == IL_INVALID_STATION) {
+               IL_ERR("Start AGG on invalid station\n");
+               return -ENXIO;
+       }
+       if (unlikely(tid >= MAX_TID_COUNT))
+               return -EINVAL;
+
+       if (il->stations[sta_id].tid[tid].agg.state != IL_AGG_OFF) {
+               IL_ERR("Start AGG when state is not IL_AGG_OFF !\n");
+               return -ENXIO;
+       }
+
+       txq_id = il4965_txq_ctx_activate_free(il);
+       if (txq_id == -1) {
+               IL_ERR("No free aggregation queue available\n");
+               return -ENXIO;
+       }
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       tid_data = &il->stations[sta_id].tid[tid];
+       *ssn = SEQ_TO_SN(tid_data->seq_number);
+       tid_data->agg.txq_id = txq_id;
+       il_set_swq_id(&il->txq[txq_id], il4965_get_ac_from_tid(tid), txq_id);
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       ret = il4965_txq_agg_enable(il, txq_id, tx_fifo, sta_id, tid, *ssn);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       tid_data = &il->stations[sta_id].tid[tid];
+       if (tid_data->tfds_in_queue == 0) {
+               D_HT("HW queue is empty\n");
+               tid_data->agg.state = IL_AGG_ON;
+               ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+       } else {
+               D_HT("HW queue is NOT empty: %d packets in HW queue\n",
+                    tid_data->tfds_in_queue);
+               tid_data->agg.state = IL_EMPTYING_HW_QUEUE_ADDBA;
+       }
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+       return ret;
+}
+
+/**
+ * txq_id must be greater than IL49_FIRST_AMPDU_QUEUE
+ * il->lock must be held by the caller
+ */
+static int
+il4965_txq_agg_disable(struct il_priv *il, u16 txq_id, u16 ssn_idx, u8 tx_fifo)
+{
+       if ((IL49_FIRST_AMPDU_QUEUE > txq_id) ||
+           (IL49_FIRST_AMPDU_QUEUE +
+            il->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
+               IL_WARN("queue number out of range: %d, must be %d to %d\n",
+                       txq_id, IL49_FIRST_AMPDU_QUEUE,
+                       IL49_FIRST_AMPDU_QUEUE +
+                       il->cfg->base_params->num_of_ampdu_queues - 1);
+               return -EINVAL;
+       }
+
+       il4965_tx_queue_stop_scheduler(il, txq_id);
+
+       il_clear_bits_prph(il, IL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
+
+       il->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+       il->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+       /* supposes that ssn_idx is valid (!= 0xFFF) */
+       il4965_set_wr_ptrs(il, txq_id, ssn_idx);
+
+       il_clear_bits_prph(il, IL49_SCD_INTERRUPT_MASK, (1 << txq_id));
+       il_txq_ctx_deactivate(il, txq_id);
+       il4965_tx_queue_set_status(il, &il->txq[txq_id], tx_fifo, 0);
+
+       return 0;
+}
+
+int
+il4965_tx_agg_stop(struct il_priv *il, struct ieee80211_vif *vif,
+                  struct ieee80211_sta *sta, u16 tid)
+{
+       int tx_fifo_id, txq_id, sta_id, ssn;
+       struct il_tid_data *tid_data;
+       int write_ptr, read_ptr;
+       unsigned long flags;
+
+       tx_fifo_id = il4965_get_fifo_from_tid(il_rxon_ctx_from_vif(vif), tid);
+       if (unlikely(tx_fifo_id < 0))
+               return tx_fifo_id;
+
+       sta_id = il_sta_id(sta);
+
+       if (sta_id == IL_INVALID_STATION) {
+               IL_ERR("Invalid station for AGG tid %d\n", tid);
+               return -ENXIO;
+       }
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+
+       tid_data = &il->stations[sta_id].tid[tid];
+       ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
+       txq_id = tid_data->agg.txq_id;
+
+       switch (il->stations[sta_id].tid[tid].agg.state) {
+       case IL_EMPTYING_HW_QUEUE_ADDBA:
+               /*
+                * This can happen if the peer stops aggregation
+                * again before we've had a chance to drain the
+                * queue we selected previously, i.e. before the
+                * session was really started completely.
+                */
+               D_HT("AGG stop before setup done\n");
+               goto turn_off;
+       case IL_AGG_ON:
+               break;
+       default:
+               IL_WARN("Stopping AGG while state not ON or starting\n");
+       }
+
+       write_ptr = il->txq[txq_id].q.write_ptr;
+       read_ptr = il->txq[txq_id].q.read_ptr;
+
+       /* The queue is not empty */
+       if (write_ptr != read_ptr) {
+               D_HT("Stopping a non empty AGG HW QUEUE\n");
+               il->stations[sta_id].tid[tid].agg.state =
+                   IL_EMPTYING_HW_QUEUE_DELBA;
+               spin_unlock_irqrestore(&il->sta_lock, flags);
+               return 0;
+       }
+
+       D_HT("HW queue is empty\n");
+turn_off:
+       il->stations[sta_id].tid[tid].agg.state = IL_AGG_OFF;
+
+       /* do not restore/save irqs */
+       spin_unlock(&il->sta_lock);
+       spin_lock(&il->lock);
+
+       /*
+        * the only reason this call can fail is queue number out of range,
+        * which can happen if uCode is reloaded and all the station
+        * information are lost. if it is outside the range, there is no need
+        * to deactivate the uCode queue, just return "success" to allow
+        *  mac80211 to clean up it own data.
+        */
+       il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo_id);
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+
+       return 0;
+}
+
+int
+il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id)
+{
+       struct il_queue *q = &il->txq[txq_id].q;
+       u8 *addr = il->stations[sta_id].sta.sta.addr;
+       struct il_tid_data *tid_data = &il->stations[sta_id].tid[tid];
+       struct il_rxon_context *ctx;
+
+       ctx = &il->ctx;
+
+       lockdep_assert_held(&il->sta_lock);
+
+       switch (il->stations[sta_id].tid[tid].agg.state) {
+       case IL_EMPTYING_HW_QUEUE_DELBA:
+               /* We are reclaiming the last packet of the */
+               /* aggregated HW queue */
+               if (txq_id == tid_data->agg.txq_id &&
+                   q->read_ptr == q->write_ptr) {
+                       u16 ssn = SEQ_TO_SN(tid_data->seq_number);
+                       int tx_fifo = il4965_get_fifo_from_tid(ctx, tid);
+                       D_HT("HW queue empty: continue DELBA flow\n");
+                       il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo);
+                       tid_data->agg.state = IL_AGG_OFF;
+                       ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
+               }
+               break;
+       case IL_EMPTYING_HW_QUEUE_ADDBA:
+               /* We are reclaiming the last packet of the queue */
+               if (tid_data->tfds_in_queue == 0) {
+                       D_HT("HW queue empty: continue ADDBA flow\n");
+                       tid_data->agg.state = IL_AGG_ON;
+                       ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
+               }
+               break;
+       }
+
+       return 0;
+}
+
+static void
+il4965_non_agg_tx_status(struct il_priv *il, struct il_rxon_context *ctx,
+                        const u8 *addr1)
+{
+       struct ieee80211_sta *sta;
+       struct il_station_priv *sta_priv;
+
+       rcu_read_lock();
+       sta = ieee80211_find_sta(ctx->vif, addr1);
+       if (sta) {
+               sta_priv = (void *)sta->drv_priv;
+               /* avoid atomic ops if this isn't a client */
+               if (sta_priv->client &&
+                   atomic_dec_return(&sta_priv->pending_frames) == 0)
+                       ieee80211_sta_block_awake(il->hw, sta, false);
+       }
+       rcu_read_unlock();
+}
+
+static void
+il4965_tx_status(struct il_priv *il, struct il_tx_info *tx_info, bool is_agg)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data;
+
+       if (!is_agg)
+               il4965_non_agg_tx_status(il, tx_info->ctx, hdr->addr1);
+
+       ieee80211_tx_status_irqsafe(il->hw, tx_info->skb);
+}
+
+int
+il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx)
+{
+       struct il_tx_queue *txq = &il->txq[txq_id];
+       struct il_queue *q = &txq->q;
+       struct il_tx_info *tx_info;
+       int nfreed = 0;
+       struct ieee80211_hdr *hdr;
+
+       if (idx >= q->n_bd || il_queue_used(q, idx) == 0) {
+               IL_ERR("Read idx for DMA queue txq id (%d), idx %d, "
+                      "is out of range [0-%d] %d %d.\n", txq_id, idx, q->n_bd,
+                      q->write_ptr, q->read_ptr);
+               return 0;
+       }
+
+       for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+            q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+               tx_info = &txq->txb[txq->q.read_ptr];
+
+               if (WARN_ON_ONCE(tx_info->skb == NULL))
+                       continue;
+
+               hdr = (struct ieee80211_hdr *)tx_info->skb->data;
+               if (ieee80211_is_data_qos(hdr->frame_control))
+                       nfreed++;
+
+               il4965_tx_status(il, tx_info,
+                                txq_id >= IL4965_FIRST_AMPDU_QUEUE);
+               tx_info->skb = NULL;
+
+               il->cfg->ops->lib->txq_free_tfd(il, txq);
+       }
+       return nfreed;
+}
+
+/**
+ * il4965_tx_status_reply_compressed_ba - Update tx status from block-ack
+ *
+ * Go through block-ack's bitmap of ACK'd frames, update driver's record of
+ * ACK vs. not.  This gets sent to mac80211, then to rate scaling algo.
+ */
+static int
+il4965_tx_status_reply_compressed_ba(struct il_priv *il, struct il_ht_agg *agg,
+                                    struct il_compressed_ba_resp *ba_resp)
+{
+       int i, sh, ack;
+       u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
+       u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+       int successes = 0;
+       struct ieee80211_tx_info *info;
+       u64 bitmap, sent_bitmap;
+
+       if (unlikely(!agg->wait_for_ba)) {
+               if (unlikely(ba_resp->bitmap))
+                       IL_ERR("Received BA when not expected\n");
+               return -EINVAL;
+       }
+
+       /* Mark that the expected block-ack response arrived */
+       agg->wait_for_ba = 0;
+       D_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
+
+       /* Calculate shift to align block-ack bits with our Tx win bits */
+       sh = agg->start_idx - SEQ_TO_IDX(seq_ctl >> 4);
+       if (sh < 0)             /* tbw something is wrong with indices */
+               sh += 0x100;
+
+       if (agg->frame_count > (64 - sh)) {
+               D_TX_REPLY("more frames than bitmap size");
+               return -1;
+       }
+
+       /* don't use 64-bit values for now */
+       bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
+
+       /* check for success or failure according to the
+        * transmitted bitmap and block-ack bitmap */
+       sent_bitmap = bitmap & agg->bitmap;
+
+       /* For each frame attempted in aggregation,
+        * update driver's record of tx frame's status. */
+       i = 0;
+       while (sent_bitmap) {
+               ack = sent_bitmap & 1ULL;
+               successes += ack;
+               D_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", ack ? "ACK" : "NACK",
+                          i, (agg->start_idx + i) & 0xff, agg->start_idx + i);
+               sent_bitmap >>= 1;
+               ++i;
+       }
+
+       D_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
+
+       info = IEEE80211_SKB_CB(il->txq[scd_flow].txb[agg->start_idx].skb);
+       memset(&info->status, 0, sizeof(info->status));
+       info->flags |= IEEE80211_TX_STAT_ACK;
+       info->flags |= IEEE80211_TX_STAT_AMPDU;
+       info->status.ampdu_ack_len = successes;
+       info->status.ampdu_len = agg->frame_count;
+       il4965_hwrate_to_tx_control(il, agg->rate_n_flags, info);
+
+       return 0;
+}
+
+/**
+ * translate ucode response to mac80211 tx status control values
+ */
+void
+il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags,
+                           struct ieee80211_tx_info *info)
+{
+       struct ieee80211_tx_rate *r = &info->control.rates[0];
+
+       info->antenna_sel_tx =
+           ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
+       if (rate_n_flags & RATE_MCS_HT_MSK)
+               r->flags |= IEEE80211_TX_RC_MCS;
+       if (rate_n_flags & RATE_MCS_GF_MSK)
+               r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
+       if (rate_n_flags & RATE_MCS_HT40_MSK)
+               r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+       if (rate_n_flags & RATE_MCS_DUP_MSK)
+               r->flags |= IEEE80211_TX_RC_DUP_DATA;
+       if (rate_n_flags & RATE_MCS_SGI_MSK)
+               r->flags |= IEEE80211_TX_RC_SHORT_GI;
+       r->idx = il4965_hwrate_to_mac80211_idx(rate_n_flags, info->band);
+}
+
+/**
+ * il4965_hdl_compressed_ba - Handler for N_COMPRESSED_BA
+ *
+ * Handles block-acknowledge notification from device, which reports success
+ * of frames sent via aggregation.
+ */
+void
+il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
+       struct il_tx_queue *txq = NULL;
+       struct il_ht_agg *agg;
+       int idx;
+       int sta_id;
+       int tid;
+       unsigned long flags;
+
+       /* "flow" corresponds to Tx queue */
+       u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+
+       /* "ssn" is start of block-ack Tx win, corresponds to idx
+        * (in Tx queue's circular buffer) of first TFD/frame in win */
+       u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
+
+       if (scd_flow >= il->hw_params.max_txq_num) {
+               IL_ERR("BUG_ON scd_flow is bigger than number of queues\n");
+               return;
+       }
+
+       txq = &il->txq[scd_flow];
+       sta_id = ba_resp->sta_id;
+       tid = ba_resp->tid;
+       agg = &il->stations[sta_id].tid[tid].agg;
+       if (unlikely(agg->txq_id != scd_flow)) {
+               /*
+                * FIXME: this is a uCode bug which need to be addressed,
+                * log the information and return for now!
+                * since it is possible happen very often and in order
+                * not to fill the syslog, don't enable the logging by default
+                */
+               D_TX_REPLY("BA scd_flow %d does not match txq_id %d\n",
+                          scd_flow, agg->txq_id);
+               return;
+       }
+
+       /* Find idx just before block-ack win */
+       idx = il_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+
+       D_TX_REPLY("N_COMPRESSED_BA [%d] Received from %pM, " "sta_id = %d\n",
+                  agg->wait_for_ba, (u8 *) &ba_resp->sta_addr_lo32,
+                  ba_resp->sta_id);
+       D_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx," "scd_flow = "
+                  "%d, scd_ssn = %d\n", ba_resp->tid, ba_resp->seq_ctl,
+                  (unsigned long long)le64_to_cpu(ba_resp->bitmap),
+                  ba_resp->scd_flow, ba_resp->scd_ssn);
+       D_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx\n", agg->start_idx,
+                  (unsigned long long)agg->bitmap);
+
+       /* Update driver's record of ACK vs. not for each frame in win */
+       il4965_tx_status_reply_compressed_ba(il, agg, ba_resp);
+
+       /* Release all TFDs before the SSN, i.e. all TFDs in front of
+        * block-ack win (we assume that they've been successfully
+        * transmitted ... if not, it's too late anyway). */
+       if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
+               /* calculate mac80211 ampdu sw queue to wake */
+               int freed = il4965_tx_queue_reclaim(il, scd_flow, idx);
+               il4965_free_tfds_in_queue(il, sta_id, tid, freed);
+
+               if (il_queue_space(&txq->q) > txq->q.low_mark &&
+                   il->mac80211_registered &&
+                   agg->state != IL_EMPTYING_HW_QUEUE_DELBA)
+                       il_wake_queue(il, txq);
+
+               il4965_txq_check_empty(il, sta_id, tid, scd_flow);
+       }
+
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+}
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+const char *
+il4965_get_tx_fail_reason(u32 status)
+{
+#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
+#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
+
+       switch (status & TX_STATUS_MSK) {
+       case TX_STATUS_SUCCESS:
+               return "SUCCESS";
+               TX_STATUS_POSTPONE(DELAY);
+               TX_STATUS_POSTPONE(FEW_BYTES);
+               TX_STATUS_POSTPONE(QUIET_PERIOD);
+               TX_STATUS_POSTPONE(CALC_TTAK);
+               TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
+               TX_STATUS_FAIL(SHORT_LIMIT);
+               TX_STATUS_FAIL(LONG_LIMIT);
+               TX_STATUS_FAIL(FIFO_UNDERRUN);
+               TX_STATUS_FAIL(DRAIN_FLOW);
+               TX_STATUS_FAIL(RFKILL_FLUSH);
+               TX_STATUS_FAIL(LIFE_EXPIRE);
+               TX_STATUS_FAIL(DEST_PS);
+               TX_STATUS_FAIL(HOST_ABORTED);
+               TX_STATUS_FAIL(BT_RETRY);
+               TX_STATUS_FAIL(STA_INVALID);
+               TX_STATUS_FAIL(FRAG_DROPPED);
+               TX_STATUS_FAIL(TID_DISABLE);
+               TX_STATUS_FAIL(FIFO_FLUSHED);
+               TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
+               TX_STATUS_FAIL(PASSIVE_NO_RX);
+               TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
+       }
+
+       return "UNKNOWN";
+
+#undef TX_STATUS_FAIL
+#undef TX_STATUS_POSTPONE
+}
+#endif /* CONFIG_IWLEGACY_DEBUG */
+
+static struct il_link_quality_cmd *
+il4965_sta_alloc_lq(struct il_priv *il, u8 sta_id)
+{
+       int i, r;
+       struct il_link_quality_cmd *link_cmd;
+       u32 rate_flags = 0;
+       __le32 rate_n_flags;
+
+       link_cmd = kzalloc(sizeof(struct il_link_quality_cmd), GFP_KERNEL);
+       if (!link_cmd) {
+               IL_ERR("Unable to allocate memory for LQ cmd.\n");
+               return NULL;
+       }
+       /* Set up the rate scaling to start at selected rate, fall back
+        * all the way down to 1M in IEEE order, and then spin on 1M */
+       if (il->band == IEEE80211_BAND_5GHZ)
+               r = RATE_6M_IDX;
+       else
+               r = RATE_1M_IDX;
+
+       if (r >= IL_FIRST_CCK_RATE && r <= IL_LAST_CCK_RATE)
+               rate_flags |= RATE_MCS_CCK_MSK;
+
+       rate_flags |=
+           il4965_first_antenna(il->hw_params.
+                                valid_tx_ant) << RATE_MCS_ANT_POS;
+       rate_n_flags = il4965_hw_set_rate_n_flags(il_rates[r].plcp, rate_flags);
+       for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+               link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
+
+       link_cmd->general_params.single_stream_ant_msk =
+           il4965_first_antenna(il->hw_params.valid_tx_ant);
+
+       link_cmd->general_params.dual_stream_ant_msk =
+           il->hw_params.valid_tx_ant & ~il4965_first_antenna(il->hw_params.
+                                                              valid_tx_ant);
+       if (!link_cmd->general_params.dual_stream_ant_msk) {
+               link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
+       } else if (il4965_num_of_ant(il->hw_params.valid_tx_ant) == 2) {
+               link_cmd->general_params.dual_stream_ant_msk =
+                   il->hw_params.valid_tx_ant;
+       }
+
+       link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+       link_cmd->agg_params.agg_time_limit =
+           cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
+
+       link_cmd->sta_id = sta_id;
+
+       return link_cmd;
+}
+
+/*
+ * il4965_add_bssid_station - Add the special IBSS BSSID station
+ *
+ * Function sleeps.
+ */
+int
+il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx,
+                        const u8 *addr, u8 *sta_id_r)
+{
+       int ret;
+       u8 sta_id;
+       struct il_link_quality_cmd *link_cmd;
+       unsigned long flags;
+
+       if (sta_id_r)
+               *sta_id_r = IL_INVALID_STATION;
+
+       ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id);
+       if (ret) {
+               IL_ERR("Unable to add station %pM\n", addr);
+               return ret;
+       }
+
+       if (sta_id_r)
+               *sta_id_r = sta_id;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       il->stations[sta_id].used |= IL_STA_LOCAL;
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       /* Set up default rate scaling table in device's station table */
+       link_cmd = il4965_sta_alloc_lq(il, sta_id);
+       if (!link_cmd) {
+               IL_ERR("Unable to initialize rate scaling for station %pM.\n",
+                      addr);
+               return -ENOMEM;
+       }
+
+       ret = il_send_lq_cmd(il, ctx, link_cmd, CMD_SYNC, true);
+       if (ret)
+               IL_ERR("Link quality command failed (%d)\n", ret);
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       il->stations[sta_id].lq = link_cmd;
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return 0;
+}
+
+static int
+il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx,
+                        bool send_if_empty)
+{
+       int i, not_empty = 0;
+       u8 buff[sizeof(struct il_wep_cmd) +
+               sizeof(struct il_wep_key) * WEP_KEYS_MAX];
+       struct il_wep_cmd *wep_cmd = (struct il_wep_cmd *)buff;
+       size_t cmd_size = sizeof(struct il_wep_cmd);
+       struct il_host_cmd cmd = {
+               .id = ctx->wep_key_cmd,
+               .data = wep_cmd,
+               .flags = CMD_SYNC,
+       };
+
+       might_sleep();
+
+       memset(wep_cmd, 0,
+              cmd_size + (sizeof(struct il_wep_key) * WEP_KEYS_MAX));
+
+       for (i = 0; i < WEP_KEYS_MAX; i++) {
+               wep_cmd->key[i].key_idx = i;
+               if (ctx->wep_keys[i].key_size) {
+                       wep_cmd->key[i].key_offset = i;
+                       not_empty = 1;
+               } else {
+                       wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
+               }
+
+               wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
+               memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
+                      ctx->wep_keys[i].key_size);
+       }
+
+       wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
+       wep_cmd->num_keys = WEP_KEYS_MAX;
+
+       cmd_size += sizeof(struct il_wep_key) * WEP_KEYS_MAX;
+
+       cmd.len = cmd_size;
+
+       if (not_empty || send_if_empty)
+               return il_send_cmd(il, &cmd);
+       else
+               return 0;
+}
+
+int
+il4965_restore_default_wep_keys(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       lockdep_assert_held(&il->mutex);
+
+       return il4965_static_wepkey_cmd(il, ctx, false);
+}
+
+int
+il4965_remove_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx,
+                             struct ieee80211_key_conf *keyconf)
+{
+       int ret;
+
+       lockdep_assert_held(&il->mutex);
+
+       D_WEP("Removing default WEP key: idx=%d\n", keyconf->keyidx);
+
+       memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
+       if (il_is_rfkill(il)) {
+               D_WEP("Not sending C_WEPKEY command due to RFKILL.\n");
+               /* but keys in device are clear anyway so return success */
+               return 0;
+       }
+       ret = il4965_static_wepkey_cmd(il, ctx, 1);
+       D_WEP("Remove default WEP key: idx=%d ret=%d\n", keyconf->keyidx, ret);
+
+       return ret;
+}
+
+int
+il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx,
+                          struct ieee80211_key_conf *keyconf)
+{
+       int ret;
+
+       lockdep_assert_held(&il->mutex);
+
+       if (keyconf->keylen != WEP_KEY_LEN_128 &&
+           keyconf->keylen != WEP_KEY_LEN_64) {
+               D_WEP("Bad WEP key length %d\n", keyconf->keylen);
+               return -EINVAL;
+       }
+
+       keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+       keyconf->hw_key_idx = HW_KEY_DEFAULT;
+       il->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
+
+       ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
+       memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
+              keyconf->keylen);
+
+       ret = il4965_static_wepkey_cmd(il, ctx, false);
+       D_WEP("Set default WEP key: len=%d idx=%d ret=%d\n", keyconf->keylen,
+             keyconf->keyidx, ret);
+
+       return ret;
+}
+
+static int
+il4965_set_wep_dynamic_key_info(struct il_priv *il, struct il_rxon_context *ctx,
+                               struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+       unsigned long flags;
+       __le16 key_flags = 0;
+       struct il_addsta_cmd sta_cmd;
+
+       lockdep_assert_held(&il->mutex);
+
+       keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+
+       key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
+       key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+       key_flags &= ~STA_KEY_FLG_INVALID;
+
+       if (keyconf->keylen == WEP_KEY_LEN_128)
+               key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
+
+       if (sta_id == ctx->bcast_sta_id)
+               key_flags |= STA_KEY_MULTICAST_MSK;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+
+       il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+       il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+       il->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
+
+       memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen);
+
+       memcpy(&il->stations[sta_id].sta.key.key[3], keyconf->key,
+              keyconf->keylen);
+
+       if ((il->stations[sta_id].sta.key.
+            key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
+               il->stations[sta_id].sta.key.key_offset =
+                   il_get_free_ucode_key_idx(il);
+       /* else, we are overriding an existing key => no need to allocated room
+        * in uCode. */
+
+       WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+            "no space for a new key");
+
+       il->stations[sta_id].sta.key.key_flags = key_flags;
+       il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+       il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+       memcpy(&sta_cmd, &il->stations[sta_id].sta,
+              sizeof(struct il_addsta_cmd));
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
+}
+
+static int
+il4965_set_ccmp_dynamic_key_info(struct il_priv *il,
+                                struct il_rxon_context *ctx,
+                                struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+       unsigned long flags;
+       __le16 key_flags = 0;
+       struct il_addsta_cmd sta_cmd;
+
+       lockdep_assert_held(&il->mutex);
+
+       key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
+       key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+       key_flags &= ~STA_KEY_FLG_INVALID;
+
+       if (sta_id == ctx->bcast_sta_id)
+               key_flags |= STA_KEY_MULTICAST_MSK;
+
+       keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+       il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+
+       memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen);
+
+       memcpy(il->stations[sta_id].sta.key.key, keyconf->key, keyconf->keylen);
+
+       if ((il->stations[sta_id].sta.key.
+            key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
+               il->stations[sta_id].sta.key.key_offset =
+                   il_get_free_ucode_key_idx(il);
+       /* else, we are overriding an existing key => no need to allocated room
+        * in uCode. */
+
+       WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+            "no space for a new key");
+
+       il->stations[sta_id].sta.key.key_flags = key_flags;
+       il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+       il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+       memcpy(&sta_cmd, &il->stations[sta_id].sta,
+              sizeof(struct il_addsta_cmd));
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
+}
+
+static int
+il4965_set_tkip_dynamic_key_info(struct il_priv *il,
+                                struct il_rxon_context *ctx,
+                                struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+       unsigned long flags;
+       int ret = 0;
+       __le16 key_flags = 0;
+
+       key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
+       key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+       key_flags &= ~STA_KEY_FLG_INVALID;
+
+       if (sta_id == ctx->bcast_sta_id)
+               key_flags |= STA_KEY_MULTICAST_MSK;
+
+       keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+       keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+
+       il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+       il->stations[sta_id].keyinfo.keylen = 16;
+
+       if ((il->stations[sta_id].sta.key.
+            key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
+               il->stations[sta_id].sta.key.key_offset =
+                   il_get_free_ucode_key_idx(il);
+       /* else, we are overriding an existing key => no need to allocated room
+        * in uCode. */
+
+       WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+            "no space for a new key");
+
+       il->stations[sta_id].sta.key.key_flags = key_flags;
+
+       /* This copy is acutally not needed: we get the key with each TX */
+       memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, 16);
+
+       memcpy(il->stations[sta_id].sta.key.key, keyconf->key, 16);
+
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return ret;
+}
+
+void
+il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx,
+                      struct ieee80211_key_conf *keyconf,
+                      struct ieee80211_sta *sta, u32 iv32, u16 * phase1key)
+{
+       u8 sta_id;
+       unsigned long flags;
+       int i;
+
+       if (il_scan_cancel(il)) {
+               /* cancel scan failed, just live w/ bad key and rely
+                  briefly on SW decryption */
+               return;
+       }
+
+       sta_id = il_sta_id_or_broadcast(il, ctx, sta);
+       if (sta_id == IL_INVALID_STATION)
+               return;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+
+       il->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
+
+       for (i = 0; i < 5; i++)
+               il->stations[sta_id].sta.key.tkip_rx_ttak[i] =
+                   cpu_to_le16(phase1key[i]);
+
+       il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+       il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+       il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC);
+
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+}
+
+int
+il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx,
+                         struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+       unsigned long flags;
+       u16 key_flags;
+       u8 keyidx;
+       struct il_addsta_cmd sta_cmd;
+
+       lockdep_assert_held(&il->mutex);
+
+       ctx->key_mapping_keys--;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       key_flags = le16_to_cpu(il->stations[sta_id].sta.key.key_flags);
+       keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
+
+       D_WEP("Remove dynamic key: idx=%d sta=%d\n", keyconf->keyidx, sta_id);
+
+       if (keyconf->keyidx != keyidx) {
+               /* We need to remove a key with idx different that the one
+                * in the uCode. This means that the key we need to remove has
+                * been replaced by another one with different idx.
+                * Don't do anything and return ok
+                */
+               spin_unlock_irqrestore(&il->sta_lock, flags);
+               return 0;
+       }
+
+       if (il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
+               IL_WARN("Removing wrong key %d 0x%x\n", keyconf->keyidx,
+                       key_flags);
+               spin_unlock_irqrestore(&il->sta_lock, flags);
+               return 0;
+       }
+
+       if (!test_and_clear_bit
+           (il->stations[sta_id].sta.key.key_offset, &il->ucode_key_table))
+               IL_ERR("idx %d not used in uCode key table.\n",
+                      il->stations[sta_id].sta.key.key_offset);
+       memset(&il->stations[sta_id].keyinfo, 0, sizeof(struct il_hw_key));
+       memset(&il->stations[sta_id].sta.key, 0, sizeof(struct il4965_keyinfo));
+       il->stations[sta_id].sta.key.key_flags =
+           STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
+       il->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
+       il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+       il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+       if (il_is_rfkill(il)) {
+               D_WEP
+                   ("Not sending C_ADD_STA command because RFKILL enabled.\n");
+               spin_unlock_irqrestore(&il->sta_lock, flags);
+               return 0;
+       }
+       memcpy(&sta_cmd, &il->stations[sta_id].sta,
+              sizeof(struct il_addsta_cmd));
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
+}
+
+int
+il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx,
+                      struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+       int ret;
+
+       lockdep_assert_held(&il->mutex);
+
+       ctx->key_mapping_keys++;
+       keyconf->hw_key_idx = HW_KEY_DYNAMIC;
+
+       switch (keyconf->cipher) {
+       case WLAN_CIPHER_SUITE_CCMP:
+               ret =
+                   il4965_set_ccmp_dynamic_key_info(il, ctx, keyconf, sta_id);
+               break;
+       case WLAN_CIPHER_SUITE_TKIP:
+               ret =
+                   il4965_set_tkip_dynamic_key_info(il, ctx, keyconf, sta_id);
+               break;
+       case WLAN_CIPHER_SUITE_WEP40:
+       case WLAN_CIPHER_SUITE_WEP104:
+               ret = il4965_set_wep_dynamic_key_info(il, ctx, keyconf, sta_id);
+               break;
+       default:
+               IL_ERR("Unknown alg: %s cipher = %x\n", __func__,
+                      keyconf->cipher);
+               ret = -EINVAL;
+       }
+
+       D_WEP("Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
+             keyconf->cipher, keyconf->keylen, keyconf->keyidx, sta_id, ret);
+
+       return ret;
+}
+
+/**
+ * il4965_alloc_bcast_station - add broadcast station into driver's station table.
+ *
+ * This adds the broadcast station into the driver's station table
+ * and marks it driver active, so that it will be restored to the
+ * device at the next best time.
+ */
+int
+il4965_alloc_bcast_station(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       struct il_link_quality_cmd *link_cmd;
+       unsigned long flags;
+       u8 sta_id;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       sta_id = il_prep_station(il, ctx, il_bcast_addr, false, NULL);
+       if (sta_id == IL_INVALID_STATION) {
+               IL_ERR("Unable to prepare broadcast station\n");
+               spin_unlock_irqrestore(&il->sta_lock, flags);
+
+               return -EINVAL;
+       }
+
+       il->stations[sta_id].used |= IL_STA_DRIVER_ACTIVE;
+       il->stations[sta_id].used |= IL_STA_BCAST;
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       link_cmd = il4965_sta_alloc_lq(il, sta_id);
+       if (!link_cmd) {
+               IL_ERR
+                   ("Unable to initialize rate scaling for bcast station.\n");
+               return -ENOMEM;
+       }
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       il->stations[sta_id].lq = link_cmd;
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return 0;
+}
+
+/**
+ * il4965_update_bcast_station - update broadcast station's LQ command
+ *
+ * Only used by iwl4965. Placed here to have all bcast station management
+ * code together.
+ */
+static int
+il4965_update_bcast_station(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       unsigned long flags;
+       struct il_link_quality_cmd *link_cmd;
+       u8 sta_id = ctx->bcast_sta_id;
+
+       link_cmd = il4965_sta_alloc_lq(il, sta_id);
+       if (!link_cmd) {
+               IL_ERR("Unable to initialize rate scaling for bcast sta.\n");
+               return -ENOMEM;
+       }
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       if (il->stations[sta_id].lq)
+               kfree(il->stations[sta_id].lq);
+       else
+               D_INFO("Bcast sta rate scaling has not been initialized.\n");
+       il->stations[sta_id].lq = link_cmd;
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return 0;
+}
+
+int
+il4965_update_bcast_stations(struct il_priv *il)
+{
+       return il4965_update_bcast_station(il, &il->ctx);
+}
+
+/**
+ * il4965_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
+ */
+int
+il4965_sta_tx_modify_enable_tid(struct il_priv *il, int sta_id, int tid)
+{
+       unsigned long flags;
+       struct il_addsta_cmd sta_cmd;
+
+       lockdep_assert_held(&il->mutex);
+
+       /* Remove "disable" flag, to enable Tx for this TID */
+       spin_lock_irqsave(&il->sta_lock, flags);
+       il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
+       il->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
+       il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+       memcpy(&sta_cmd, &il->stations[sta_id].sta,
+              sizeof(struct il_addsta_cmd));
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
+}
+
+int
+il4965_sta_rx_agg_start(struct il_priv *il, struct ieee80211_sta *sta, int tid,
+                       u16 ssn)
+{
+       unsigned long flags;
+       int sta_id;
+       struct il_addsta_cmd sta_cmd;
+
+       lockdep_assert_held(&il->mutex);
+
+       sta_id = il_sta_id(sta);
+       if (sta_id == IL_INVALID_STATION)
+               return -ENXIO;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       il->stations[sta_id].sta.station_flags_msk = 0;
+       il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
+       il->stations[sta_id].sta.add_immediate_ba_tid = (u8) tid;
+       il->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
+       il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+       memcpy(&sta_cmd, &il->stations[sta_id].sta,
+              sizeof(struct il_addsta_cmd));
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
+}
+
+int
+il4965_sta_rx_agg_stop(struct il_priv *il, struct ieee80211_sta *sta, int tid)
+{
+       unsigned long flags;
+       int sta_id;
+       struct il_addsta_cmd sta_cmd;
+
+       lockdep_assert_held(&il->mutex);
+
+       sta_id = il_sta_id(sta);
+       if (sta_id == IL_INVALID_STATION) {
+               IL_ERR("Invalid station for AGG tid %d\n", tid);
+               return -ENXIO;
+       }
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       il->stations[sta_id].sta.station_flags_msk = 0;
+       il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
+       il->stations[sta_id].sta.remove_immediate_ba_tid = (u8) tid;
+       il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+       memcpy(&sta_cmd, &il->stations[sta_id].sta,
+              sizeof(struct il_addsta_cmd));
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
+}
+
+void
+il4965_sta_modify_sleep_tx_count(struct il_priv *il, int sta_id, int cnt)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       il->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
+       il->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
+       il->stations[sta_id].sta.sta.modify_mask =
+           STA_MODIFY_SLEEP_TX_COUNT_MSK;
+       il->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
+       il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+       il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC);
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+}
+
+void
+il4965_update_chain_flags(struct il_priv *il)
+{
+       if (il->cfg->ops->hcmd->set_rxon_chain) {
+               il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx);
+               if (il->ctx.active.rx_chain != il->ctx.staging.rx_chain)
+                       il_commit_rxon(il, &il->ctx);
+       }
+}
+
+static void
+il4965_clear_free_frames(struct il_priv *il)
+{
+       struct list_head *element;
+
+       D_INFO("%d frames on pre-allocated heap on clear.\n", il->frames_count);
+
+       while (!list_empty(&il->free_frames)) {
+               element = il->free_frames.next;
+               list_del(element);
+               kfree(list_entry(element, struct il_frame, list));
+               il->frames_count--;
+       }
+
+       if (il->frames_count) {
+               IL_WARN("%d frames still in use.  Did we lose one?\n",
+                       il->frames_count);
+               il->frames_count = 0;
+       }
+}
+
+static struct il_frame *
+il4965_get_free_frame(struct il_priv *il)
+{
+       struct il_frame *frame;
+       struct list_head *element;
+       if (list_empty(&il->free_frames)) {
+               frame = kzalloc(sizeof(*frame), GFP_KERNEL);
+               if (!frame) {
+                       IL_ERR("Could not allocate frame!\n");
+                       return NULL;
+               }
+
+               il->frames_count++;
+               return frame;
+       }
+
+       element = il->free_frames.next;
+       list_del(element);
+       return list_entry(element, struct il_frame, list);
+}
+
+static void
+il4965_free_frame(struct il_priv *il, struct il_frame *frame)
+{
+       memset(frame, 0, sizeof(*frame));
+       list_add(&frame->list, &il->free_frames);
+}
+
+static u32
+il4965_fill_beacon_frame(struct il_priv *il, struct ieee80211_hdr *hdr,
+                        int left)
+{
+       lockdep_assert_held(&il->mutex);
+
+       if (!il->beacon_skb)
+               return 0;
+
+       if (il->beacon_skb->len > left)
+               return 0;
+
+       memcpy(hdr, il->beacon_skb->data, il->beacon_skb->len);
+
+       return il->beacon_skb->len;
+}
+
+/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
+static void
+il4965_set_beacon_tim(struct il_priv *il,
+                     struct il_tx_beacon_cmd *tx_beacon_cmd, u8 * beacon,
+                     u32 frame_size)
+{
+       u16 tim_idx;
+       struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
+
+       /*
+        * The idx is relative to frame start but we start looking at the
+        * variable-length part of the beacon.
+        */
+       tim_idx = mgmt->u.beacon.variable - beacon;
+
+       /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
+       while ((tim_idx < (frame_size - 2)) &&
+              (beacon[tim_idx] != WLAN_EID_TIM))
+               tim_idx += beacon[tim_idx + 1] + 2;
+
+       /* If TIM field was found, set variables */
+       if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
+               tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
+               tx_beacon_cmd->tim_size = beacon[tim_idx + 1];
+       } else
+               IL_WARN("Unable to find TIM Element in beacon\n");
+}
+
+static unsigned int
+il4965_hw_get_beacon_cmd(struct il_priv *il, struct il_frame *frame)
+{
+       struct il_tx_beacon_cmd *tx_beacon_cmd;
+       u32 frame_size;
+       u32 rate_flags;
+       u32 rate;
+       /*
+        * We have to set up the TX command, the TX Beacon command, and the
+        * beacon contents.
+        */
+
+       lockdep_assert_held(&il->mutex);
+
+       if (!il->beacon_ctx) {
+               IL_ERR("trying to build beacon w/o beacon context!\n");
+               return 0;
+       }
+
+       /* Initialize memory */
+       tx_beacon_cmd = &frame->u.beacon;
+       memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+
+       /* Set up TX beacon contents */
+       frame_size =
+           il4965_fill_beacon_frame(il, tx_beacon_cmd->frame,
+                                    sizeof(frame->u) - sizeof(*tx_beacon_cmd));
+       if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
+               return 0;
+       if (!frame_size)
+               return 0;
+
+       /* Set up TX command fields */
+       tx_beacon_cmd->tx.len = cpu_to_le16((u16) frame_size);
+       tx_beacon_cmd->tx.sta_id = il->beacon_ctx->bcast_sta_id;
+       tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+       tx_beacon_cmd->tx.tx_flags =
+           TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK |
+           TX_CMD_FLG_STA_RATE_MSK;
+
+       /* Set up TX beacon command fields */
+       il4965_set_beacon_tim(il, tx_beacon_cmd, (u8 *) tx_beacon_cmd->frame,
+                             frame_size);
+
+       /* Set up packet rate and flags */
+       rate = il_get_lowest_plcp(il, il->beacon_ctx);
+       il->mgmt_tx_ant =
+           il4965_toggle_tx_ant(il, il->mgmt_tx_ant,
+                                il->hw_params.valid_tx_ant);
+       rate_flags = il4965_ant_idx_to_flags(il->mgmt_tx_ant);
+       if ((rate >= IL_FIRST_CCK_RATE) && (rate <= IL_LAST_CCK_RATE))
+               rate_flags |= RATE_MCS_CCK_MSK;
+       tx_beacon_cmd->tx.rate_n_flags =
+           il4965_hw_set_rate_n_flags(rate, rate_flags);
+
+       return sizeof(*tx_beacon_cmd) + frame_size;
+}
+
+int
+il4965_send_beacon_cmd(struct il_priv *il)
+{
+       struct il_frame *frame;
+       unsigned int frame_size;
+       int rc;
+
+       frame = il4965_get_free_frame(il);
+       if (!frame) {
+               IL_ERR("Could not obtain free frame buffer for beacon "
+                      "command.\n");
+               return -ENOMEM;
+       }
+
+       frame_size = il4965_hw_get_beacon_cmd(il, frame);
+       if (!frame_size) {
+               IL_ERR("Error configuring the beacon command\n");
+               il4965_free_frame(il, frame);
+               return -EINVAL;
+       }
+
+       rc = il_send_cmd_pdu(il, C_TX_BEACON, frame_size, &frame->u.cmd[0]);
+
+       il4965_free_frame(il, frame);
+
+       return rc;
+}
+
+static inline dma_addr_t
+il4965_tfd_tb_get_addr(struct il_tfd *tfd, u8 idx)
+{
+       struct il_tfd_tb *tb = &tfd->tbs[idx];
+
+       dma_addr_t addr = get_unaligned_le32(&tb->lo);
+       if (sizeof(dma_addr_t) > sizeof(u32))
+               addr |=
+                   ((dma_addr_t) (le16_to_cpu(tb->hi_n_len) & 0xF) << 16) <<
+                   16;
+
+       return addr;
+}
+
+static inline u16
+il4965_tfd_tb_get_len(struct il_tfd *tfd, u8 idx)
+{
+       struct il_tfd_tb *tb = &tfd->tbs[idx];
+
+       return le16_to_cpu(tb->hi_n_len) >> 4;
+}
+
+static inline void
+il4965_tfd_set_tb(struct il_tfd *tfd, u8 idx, dma_addr_t addr, u16 len)
+{
+       struct il_tfd_tb *tb = &tfd->tbs[idx];
+       u16 hi_n_len = len << 4;
+
+       put_unaligned_le32(addr, &tb->lo);
+       if (sizeof(dma_addr_t) > sizeof(u32))
+               hi_n_len |= ((addr >> 16) >> 16) & 0xF;
+
+       tb->hi_n_len = cpu_to_le16(hi_n_len);
+
+       tfd->num_tbs = idx + 1;
+}
+
+static inline u8
+il4965_tfd_get_num_tbs(struct il_tfd *tfd)
+{
+       return tfd->num_tbs & 0x1f;
+}
+
+/**
+ * il4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+ * @il - driver ilate data
+ * @txq - tx queue
+ *
+ * Does NOT advance any TFD circular buffer read/write idxes
+ * Does NOT free the TFD itself (which is within circular buffer)
+ */
+void
+il4965_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq)
+{
+       struct il_tfd *tfd_tmp = (struct il_tfd *)txq->tfds;
+       struct il_tfd *tfd;
+       struct pci_dev *dev = il->pci_dev;
+       int idx = txq->q.read_ptr;
+       int i;
+       int num_tbs;
+
+       tfd = &tfd_tmp[idx];
+
+       /* Sanity check on number of chunks */
+       num_tbs = il4965_tfd_get_num_tbs(tfd);
+
+       if (num_tbs >= IL_NUM_OF_TBS) {
+               IL_ERR("Too many chunks: %i\n", num_tbs);
+               /* @todo issue fatal error, it is quite serious situation */
+               return;
+       }
+
+       /* Unmap tx_cmd */
+       if (num_tbs)
+               pci_unmap_single(dev, dma_unmap_addr(&txq->meta[idx], mapping),
+                                dma_unmap_len(&txq->meta[idx], len),
+                                PCI_DMA_BIDIRECTIONAL);
+
+       /* Unmap chunks, if any. */
+       for (i = 1; i < num_tbs; i++)
+               pci_unmap_single(dev, il4965_tfd_tb_get_addr(tfd, i),
+                                il4965_tfd_tb_get_len(tfd, i),
+                                PCI_DMA_TODEVICE);
+
+       /* free SKB */
+       if (txq->txb) {
+               struct sk_buff *skb;
+
+               skb = txq->txb[txq->q.read_ptr].skb;
+
+               /* can be called from irqs-disabled context */
+               if (skb) {
+                       dev_kfree_skb_any(skb);
+                       txq->txb[txq->q.read_ptr].skb = NULL;
+               }
+       }
+}
+
+int
+il4965_hw_txq_attach_buf_to_tfd(struct il_priv *il, struct il_tx_queue *txq,
+                               dma_addr_t addr, u16 len, u8 reset, u8 pad)
+{
+       struct il_queue *q;
+       struct il_tfd *tfd, *tfd_tmp;
+       u32 num_tbs;
+
+       q = &txq->q;
+       tfd_tmp = (struct il_tfd *)txq->tfds;
+       tfd = &tfd_tmp[q->write_ptr];
+
+       if (reset)
+               memset(tfd, 0, sizeof(*tfd));
+
+       num_tbs = il4965_tfd_get_num_tbs(tfd);
+
+       /* Each TFD can point to a maximum 20 Tx buffers */
+       if (num_tbs >= IL_NUM_OF_TBS) {
+               IL_ERR("Error can not send more than %d chunks\n",
+                      IL_NUM_OF_TBS);
+               return -EINVAL;
+       }
+
+       BUG_ON(addr & ~DMA_BIT_MASK(36));
+       if (unlikely(addr & ~IL_TX_DMA_MASK))
+               IL_ERR("Unaligned address = %llx\n", (unsigned long long)addr);
+
+       il4965_tfd_set_tb(tfd, num_tbs, addr, len);
+
+       return 0;
+}
+
+/*
+ * Tell nic where to find circular buffer of Tx Frame Descriptors for
+ * given Tx queue, and enable the DMA channel used for that queue.
+ *
+ * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
+ * channels supported in hardware.
+ */
+int
+il4965_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq)
+{
+       int txq_id = txq->q.id;
+
+       /* Circular buffer (TFD queue in DRAM) physical base address */
+       il_wr(il, FH49_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8);
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ * Generic RX handler implementations
+ *
+ ******************************************************************************/
+static void
+il4965_hdl_alive(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_alive_resp *palive;
+       struct delayed_work *pwork;
+
+       palive = &pkt->u.alive_frame;
+
+       D_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) {
+               D_INFO("Initialization Alive received.\n");
+               memcpy(&il->card_alive_init, &pkt->u.alive_frame,
+                      sizeof(struct il_init_alive_resp));
+               pwork = &il->init_alive_start;
+       } else {
+               D_INFO("Runtime Alive received.\n");
+               memcpy(&il->card_alive, &pkt->u.alive_frame,
+                      sizeof(struct il_alive_resp));
+               pwork = &il->alive_start;
+       }
+
+       /* 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(il->workqueue, pwork, msecs_to_jiffies(5));
+       else
+               IL_WARN("uCode did not respond OK.\n");
+}
+
+/**
+ * il4965_bg_stats_periodic - Timer callback to queue stats
+ *
+ * This callback is provided in order to send a stats request.
+ *
+ * This timer function is continually reset to execute within
+ * REG_RECALIB_PERIOD seconds since the last N_STATS
+ * was received.  We need to ensure we receive the stats in order
+ * to update the temperature used for calibrating the TXPOWER.
+ */
+static void
+il4965_bg_stats_periodic(unsigned long data)
+{
+       struct il_priv *il = (struct il_priv *)data;
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       /* dont send host command if rf-kill is on */
+       if (!il_is_ready_rf(il))
+               return;
+
+       il_send_stats_request(il, CMD_ASYNC, false);
+}
+
+static void
+il4965_hdl_beacon(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il4965_beacon_notif *beacon =
+           (struct il4965_beacon_notif *)pkt->u.raw;
+#ifdef CONFIG_IWLEGACY_DEBUG
+       u8 rate = il4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+
+       D_RX("beacon status %x retries %d iss %d " "tsf %d %d rate %d\n",
+            le32_to_cpu(beacon->beacon_notify_hdr.u.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
+
+       il->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+}
+
+static void
+il4965_perform_ct_kill_task(struct il_priv *il)
+{
+       unsigned long flags;
+
+       D_POWER("Stop all queues\n");
+
+       if (il->mac80211_registered)
+               ieee80211_stop_queues(il->hw);
+
+       _il_wr(il, CSR_UCODE_DRV_GP1_SET,
+              CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+       _il_rd(il, CSR_UCODE_DRV_GP1);
+
+       spin_lock_irqsave(&il->reg_lock, flags);
+       if (!_il_grab_nic_access(il))
+               _il_release_nic_access(il);
+       spin_unlock_irqrestore(&il->reg_lock, flags);
+}
+
+/* Handle notification from uCode that card's power state is changing
+ * due to software, hardware, or critical temperature RFKILL */
+static void
+il4965_hdl_card_state(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
+       unsigned long status = il->status;
+
+       D_RF_KILL("Card state received: HW:%s SW:%s CT:%s\n",
+                 (flags & HW_CARD_DISABLED) ? "Kill" : "On",
+                 (flags & SW_CARD_DISABLED) ? "Kill" : "On",
+                 (flags & CT_CARD_DISABLED) ? "Reached" : "Not reached");
+
+       if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | CT_CARD_DISABLED)) {
+
+               _il_wr(il, CSR_UCODE_DRV_GP1_SET,
+                      CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+               il_wr(il, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
+
+               if (!(flags & RXON_CARD_DISABLED)) {
+                       _il_wr(il, CSR_UCODE_DRV_GP1_CLR,
+                              CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+                       il_wr(il, HBUS_TARG_MBX_C,
+                             HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
+               }
+       }
+
+       if (flags & CT_CARD_DISABLED)
+               il4965_perform_ct_kill_task(il);
+
+       if (flags & HW_CARD_DISABLED)
+               set_bit(S_RF_KILL_HW, &il->status);
+       else
+               clear_bit(S_RF_KILL_HW, &il->status);
+
+       if (!(flags & RXON_CARD_DISABLED))
+               il_scan_cancel(il);
+
+       if ((test_bit(S_RF_KILL_HW, &status) !=
+            test_bit(S_RF_KILL_HW, &il->status)))
+               wiphy_rfkill_set_hw_state(il->hw->wiphy,
+                                         test_bit(S_RF_KILL_HW, &il->status));
+       else
+               wake_up(&il->wait_command_queue);
+}
+
+/**
+ * il4965_setup_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
+il4965_setup_handlers(struct il_priv *il)
+{
+       il->handlers[N_ALIVE] = il4965_hdl_alive;
+       il->handlers[N_ERROR] = il_hdl_error;
+       il->handlers[N_CHANNEL_SWITCH] = il_hdl_csa;
+       il->handlers[N_SPECTRUM_MEASUREMENT] = il_hdl_spectrum_measurement;
+       il->handlers[N_PM_SLEEP] = il_hdl_pm_sleep;
+       il->handlers[N_PM_DEBUG_STATS] = il_hdl_pm_debug_stats;
+       il->handlers[N_BEACON] = il4965_hdl_beacon;
+
+       /*
+        * The same handler is used for both the REPLY to a discrete
+        * stats request from the host as well as for the periodic
+        * stats notifications (after received beacons) from the uCode.
+        */
+       il->handlers[C_STATS] = il4965_hdl_c_stats;
+       il->handlers[N_STATS] = il4965_hdl_stats;
+
+       il_setup_rx_scan_handlers(il);
+
+       /* status change handler */
+       il->handlers[N_CARD_STATE] = il4965_hdl_card_state;
+
+       il->handlers[N_MISSED_BEACONS] = il4965_hdl_missed_beacon;
+       /* Rx handlers */
+       il->handlers[N_RX_PHY] = il4965_hdl_rx_phy;
+       il->handlers[N_RX_MPDU] = il4965_hdl_rx;
+       /* block ack */
+       il->handlers[N_COMPRESSED_BA] = il4965_hdl_compressed_ba;
+       /* Set up hardware specific Rx handlers */
+       il->cfg->ops->lib->handler_setup(il);
+}
+
+/**
+ * il4965_rx_handle - Main entry function for receiving responses from uCode
+ *
+ * Uses the il->handlers callback function array to invoke
+ * the appropriate handlers, including command responses,
+ * frame-received notifications, and other notifications.
+ */
+void
+il4965_rx_handle(struct il_priv *il)
+{
+       struct il_rx_buf *rxb;
+       struct il_rx_pkt *pkt;
+       struct il_rx_queue *rxq = &il->rxq;
+       u32 r, i;
+       int reclaim;
+       unsigned long flags;
+       u8 fill_rx = 0;
+       u32 count = 8;
+       int total_empty;
+
+       /* uCode's read idx (stored in shared DRAM) indicates the last Rx
+        * buffer that the driver may process (last buffer filled by ucode). */
+       r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
+       i = rxq->read;
+
+       /* Rx interrupt, but nothing sent from uCode */
+       if (i == r)
+               D_RX("r = %d, i = %d\n", r, i);
+
+       /* calculate total frames need to be restock after handling RX */
+       total_empty = r - rxq->write_actual;
+       if (total_empty < 0)
+               total_empty += RX_QUEUE_SIZE;
+
+       if (total_empty > (RX_QUEUE_SIZE / 2))
+               fill_rx = 1;
+
+       while (i != r) {
+               int len;
+
+               rxb = rxq->queue[i];
+
+               /* If an RXB doesn't have a Rx 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_unmap_page(il->pci_dev, rxb->page_dma,
+                              PAGE_SIZE << il->hw_params.rx_page_order,
+                              PCI_DMA_FROMDEVICE);
+               pkt = rxb_addr(rxb);
+
+               len = le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK;
+               len += sizeof(u32);     /* account for status word */
+
+               /* 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 != N_RX_PHY) && (pkt->hdr.cmd != N_RX) &&
+                   (pkt->hdr.cmd != N_RX_MPDU) &&
+                   (pkt->hdr.cmd != N_COMPRESSED_BA) &&
+                   (pkt->hdr.cmd != N_STATS) && (pkt->hdr.cmd != C_TX);
+
+               /* Based on type of command response or notification,
+                *   handle those that need handling via function in
+                *   handlers table.  See il4965_setup_handlers() */
+               if (il->handlers[pkt->hdr.cmd]) {
+                       D_RX("r = %d, i = %d, %s, 0x%02x\n", r, i,
+                            il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+                       il->isr_stats.handlers[pkt->hdr.cmd]++;
+                       il->handlers[pkt->hdr.cmd] (il, rxb);
+               } else {
+                       /* No handling needed */
+                       D_RX("r %d i %d No handler needed for %s, 0x%02x\n", r,
+                            i, il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+               }
+
+               /*
+                * XXX: After here, we should always check rxb->page
+                * against NULL before touching it or its virtual
+                * memory (pkt). Because some handler might have
+                * already taken or freed the pages.
+                */
+
+               if (reclaim) {
+                       /* Invoke any callbacks, transfer the buffer to caller,
+                        * and fire off the (possibly) blocking il_send_cmd()
+                        * as we reclaim the driver command queue */
+                       if (rxb->page)
+                               il_tx_cmd_complete(il, rxb);
+                       else
+                               IL_WARN("Claim null rxb?\n");
+               }
+
+               /* Reuse the page if possible. For notification packets and
+                * SKBs that fail to Rx correctly, add them back into the
+                * rx_free list for reuse later. */
+               spin_lock_irqsave(&rxq->lock, flags);
+               if (rxb->page != NULL) {
+                       rxb->page_dma =
+                           pci_map_page(il->pci_dev, rxb->page, 0,
+                                        PAGE_SIZE << il->hw_params.
+                                        rx_page_order, PCI_DMA_FROMDEVICE);
+                       list_add_tail(&rxb->list, &rxq->rx_free);
+                       rxq->free_count++;
+               } else
+                       list_add_tail(&rxb->list, &rxq->rx_used);
+
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               i = (i + 1) & RX_QUEUE_MASK;
+               /* If there are a lot of unused frames,
+                * restock the Rx queue so ucode wont assert. */
+               if (fill_rx) {
+                       count++;
+                       if (count >= 8) {
+                               rxq->read = i;
+                               il4965_rx_replenish_now(il);
+                               count = 0;
+                       }
+               }
+       }
+
+       /* Backtrack one entry */
+       rxq->read = i;
+       if (fill_rx)
+               il4965_rx_replenish_now(il);
+       else
+               il4965_rx_queue_restock(il);
+}
+
+/* call this function to flush any scheduled tasklet */
+static inline void
+il4965_synchronize_irq(struct il_priv *il)
+{
+       /* wait to make sure we flush pending tasklet */
+       synchronize_irq(il->pci_dev->irq);
+       tasklet_kill(&il->irq_tasklet);
+}
+
+static void
+il4965_irq_tasklet(struct il_priv *il)
+{
+       u32 inta, handled = 0;
+       u32 inta_fh;
+       unsigned long flags;
+       u32 i;
+#ifdef CONFIG_IWLEGACY_DEBUG
+       u32 inta_mask;
+#endif
+
+       spin_lock_irqsave(&il->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 = _il_rd(il, CSR_INT);
+       _il_wr(il, 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 = _il_rd(il, CSR_FH_INT_STATUS);
+       _il_wr(il, CSR_FH_INT_STATUS, inta_fh);
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+       if (il_get_debug_level(il) & IL_DL_ISR) {
+               /* just for debug */
+               inta_mask = _il_rd(il, CSR_INT_MASK);
+               D_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta,
+                     inta_mask, inta_fh);
+       }
+#endif
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       /* 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 & CSR49_FH_INT_RX_MASK)
+               inta |= CSR_INT_BIT_FH_RX;
+       if (inta_fh & CSR49_FH_INT_TX_MASK)
+               inta |= CSR_INT_BIT_FH_TX;
+
+       /* Now service all interrupt bits discovered above. */
+       if (inta & CSR_INT_BIT_HW_ERR) {
+               IL_ERR("Hardware error detected.  Restarting.\n");
+
+               /* Tell the device to stop sending interrupts */
+               il_disable_interrupts(il);
+
+               il->isr_stats.hw++;
+               il_irq_handle_error(il);
+
+               handled |= CSR_INT_BIT_HW_ERR;
+
+               return;
+       }
+#ifdef CONFIG_IWLEGACY_DEBUG
+       if (il_get_debug_level(il) & (IL_DL_ISR)) {
+               /* NIC fires this, but we don't use it, redundant with WAKEUP */
+               if (inta & CSR_INT_BIT_SCD) {
+                       D_ISR("Scheduler finished to transmit "
+                             "the frame/frames.\n");
+                       il->isr_stats.sch++;
+               }
+
+               /* Alive notification via Rx interrupt will do the real work */
+               if (inta & CSR_INT_BIT_ALIVE) {
+                       D_ISR("Alive interrupt\n");
+                       il->isr_stats.alive++;
+               }
+       }
+#endif
+       /* Safely ignore these bits for debug checks below */
+       inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
+
+       /* HW RF KILL switch toggled */
+       if (inta & CSR_INT_BIT_RF_KILL) {
+               int hw_rf_kill = 0;
+               if (!
+                   (_il_rd(il, CSR_GP_CNTRL) &
+                    CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+                       hw_rf_kill = 1;
+
+               IL_WARN("RF_KILL bit toggled to %s.\n",
+                       hw_rf_kill ? "disable radio" : "enable radio");
+
+               il->isr_stats.rfkill++;
+
+               /* driver only loads ucode once setting the interface up.
+                * the driver allows loading the ucode even if the radio
+                * is killed. Hence update the killswitch state here. The
+                * rfkill handler will care about restarting if needed.
+                */
+               if (!test_bit(S_ALIVE, &il->status)) {
+                       if (hw_rf_kill)
+                               set_bit(S_RF_KILL_HW, &il->status);
+                       else
+                               clear_bit(S_RF_KILL_HW, &il->status);
+                       wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
+               }
+
+               handled |= CSR_INT_BIT_RF_KILL;
+       }
+
+       /* Chip got too hot and stopped itself */
+       if (inta & CSR_INT_BIT_CT_KILL) {
+               IL_ERR("Microcode CT kill error detected.\n");
+               il->isr_stats.ctkill++;
+               handled |= CSR_INT_BIT_CT_KILL;
+       }
+
+       /* Error detected by uCode */
+       if (inta & CSR_INT_BIT_SW_ERR) {
+               IL_ERR("Microcode SW error detected. " " Restarting 0x%X.\n",
+                      inta);
+               il->isr_stats.sw++;
+               il_irq_handle_error(il);
+               handled |= CSR_INT_BIT_SW_ERR;
+       }
+
+       /*
+        * uCode wakes up after power-down sleep.
+        * Tell device about any new tx or host commands enqueued,
+        * and about any Rx buffers made available while asleep.
+        */
+       if (inta & CSR_INT_BIT_WAKEUP) {
+               D_ISR("Wakeup interrupt\n");
+               il_rx_queue_update_write_ptr(il, &il->rxq);
+               for (i = 0; i < il->hw_params.max_txq_num; i++)
+                       il_txq_update_write_ptr(il, &il->txq[i]);
+               il->isr_stats.wakeup++;
+               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)) {
+               il4965_rx_handle(il);
+               il->isr_stats.rx++;
+               handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
+       }
+
+       /* This "Tx" DMA channel is used only for loading uCode */
+       if (inta & CSR_INT_BIT_FH_TX) {
+               D_ISR("uCode load interrupt\n");
+               il->isr_stats.tx++;
+               handled |= CSR_INT_BIT_FH_TX;
+               /* Wake up uCode load routine, now that load is complete */
+               il->ucode_write_complete = 1;
+               wake_up(&il->wait_command_queue);
+       }
+
+       if (inta & ~handled) {
+               IL_ERR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
+               il->isr_stats.unhandled++;
+       }
+
+       if (inta & ~(il->inta_mask)) {
+               IL_WARN("Disabled INTA bits 0x%08x were pending\n",
+                       inta & ~il->inta_mask);
+               IL_WARN("   with FH49_INT = 0x%08x\n", inta_fh);
+       }
+
+       /* Re-enable all interrupts */
+       /* only Re-enable if disabled by irq */
+       if (test_bit(S_INT_ENABLED, &il->status))
+               il_enable_interrupts(il);
+       /* Re-enable RF_KILL if it occurred */
+       else if (handled & CSR_INT_BIT_RF_KILL)
+               il_enable_rfkill_int(il);
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+       if (il_get_debug_level(il) & (IL_DL_ISR)) {
+               inta = _il_rd(il, CSR_INT);
+               inta_mask = _il_rd(il, CSR_INT_MASK);
+               inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
+               D_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
+                     "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
+       }
+#endif
+}
+
+/*****************************************************************************
+ *
+ * sysfs attributes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+
+/*
+ * The following adds a new attribute to the sysfs representation
+ * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
+ * used for controlling the debug level.
+ *
+ * See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
+ */
+static ssize_t
+il4965_show_debug_level(struct device *d, struct device_attribute *attr,
+                       char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       return sprintf(buf, "0x%08X\n", il_get_debug_level(il));
+}
+
+static ssize_t
+il4965_store_debug_level(struct device *d, struct device_attribute *attr,
+                        const char *buf, size_t count)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 0, &val);
+       if (ret)
+               IL_ERR("%s is not in hex or decimal form.\n", buf);
+       else {
+               il->debug_level = val;
+               if (il_alloc_traffic_mem(il))
+                       IL_ERR("Not enough memory to generate traffic log\n");
+       }
+       return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, il4965_show_debug_level,
+                  il4965_store_debug_level);
+
+#endif /* CONFIG_IWLEGACY_DEBUG */
+
+static ssize_t
+il4965_show_temperature(struct device *d, struct device_attribute *attr,
+                       char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+
+       if (!il_is_alive(il))
+               return -EAGAIN;
+
+       return sprintf(buf, "%d\n", il->temperature);
+}
+
+static DEVICE_ATTR(temperature, S_IRUGO, il4965_show_temperature, NULL);
+
+static ssize_t
+il4965_show_tx_power(struct device *d, struct device_attribute *attr, char *buf)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+
+       if (!il_is_ready_rf(il))
+               return sprintf(buf, "off\n");
+       else
+               return sprintf(buf, "%d\n", il->tx_power_user_lmt);
+}
+
+static ssize_t
+il4965_store_tx_power(struct device *d, struct device_attribute *attr,
+                     const char *buf, size_t count)
+{
+       struct il_priv *il = dev_get_drvdata(d);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret)
+               IL_INFO("%s is not in decimal form.\n", buf);
+       else {
+               ret = il_set_tx_power(il, val, false);
+               if (ret)
+                       IL_ERR("failed setting tx power (0x%d).\n", ret);
+               else
+                       ret = count;
+       }
+       return ret;
+}
+
+static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, il4965_show_tx_power,
+                  il4965_store_tx_power);
+
+static struct attribute *il_sysfs_entries[] = {
+       &dev_attr_temperature.attr,
+       &dev_attr_tx_power.attr,
+#ifdef CONFIG_IWLEGACY_DEBUG
+       &dev_attr_debug_level.attr,
+#endif
+       NULL
+};
+
+static struct attribute_group il_attribute_group = {
+       .name = NULL,           /* put in device directory */
+       .attrs = il_sysfs_entries,
+};
+
+/******************************************************************************
+ *
+ * uCode download functions
+ *
+ ******************************************************************************/
+
+static void
+il4965_dealloc_ucode_pci(struct il_priv *il)
+{
+       il_free_fw_desc(il->pci_dev, &il->ucode_code);
+       il_free_fw_desc(il->pci_dev, &il->ucode_data);
+       il_free_fw_desc(il->pci_dev, &il->ucode_data_backup);
+       il_free_fw_desc(il->pci_dev, &il->ucode_init);
+       il_free_fw_desc(il->pci_dev, &il->ucode_init_data);
+       il_free_fw_desc(il->pci_dev, &il->ucode_boot);
+}
+
+static void
+il4965_nic_start(struct il_priv *il)
+{
+       /* Remove all resets to allow NIC to operate */
+       _il_wr(il, CSR_RESET, 0);
+}
+
+static void il4965_ucode_callback(const struct firmware *ucode_raw,
+                                 void *context);
+static int il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length);
+
+static int __must_check
+il4965_request_firmware(struct il_priv *il, bool first)
+{
+       const char *name_pre = il->cfg->fw_name_pre;
+       char tag[8];
+
+       if (first) {
+               il->fw_idx = il->cfg->ucode_api_max;
+               sprintf(tag, "%d", il->fw_idx);
+       } else {
+               il->fw_idx--;
+               sprintf(tag, "%d", il->fw_idx);
+       }
+
+       if (il->fw_idx < il->cfg->ucode_api_min) {
+               IL_ERR("no suitable firmware found!\n");
+               return -ENOENT;
+       }
+
+       sprintf(il->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
+
+       D_INFO("attempting to load firmware '%s'\n", il->firmware_name);
+
+       return request_firmware_nowait(THIS_MODULE, 1, il->firmware_name,
+                                      &il->pci_dev->dev, GFP_KERNEL, il,
+                                      il4965_ucode_callback);
+}
+
+struct il4965_firmware_pieces {
+       const void *inst, *data, *init, *init_data, *boot;
+       size_t inst_size, data_size, init_size, init_data_size, boot_size;
+};
+
+static int
+il4965_load_firmware(struct il_priv *il, const struct firmware *ucode_raw,
+                    struct il4965_firmware_pieces *pieces)
+{
+       struct il_ucode_header *ucode = (void *)ucode_raw->data;
+       u32 api_ver, hdr_size;
+       const u8 *src;
+
+       il->ucode_ver = le32_to_cpu(ucode->ver);
+       api_ver = IL_UCODE_API(il->ucode_ver);
+
+       switch (api_ver) {
+       default:
+       case 0:
+       case 1:
+       case 2:
+               hdr_size = 24;
+               if (ucode_raw->size < hdr_size) {
+                       IL_ERR("File size too small!\n");
+                       return -EINVAL;
+               }
+               pieces->inst_size = le32_to_cpu(ucode->v1.inst_size);
+               pieces->data_size = le32_to_cpu(ucode->v1.data_size);
+               pieces->init_size = le32_to_cpu(ucode->v1.init_size);
+               pieces->init_data_size = le32_to_cpu(ucode->v1.init_data_size);
+               pieces->boot_size = le32_to_cpu(ucode->v1.boot_size);
+               src = ucode->v1.data;
+               break;
+       }
+
+       /* Verify size of file vs. image size info in file's header */
+       if (ucode_raw->size !=
+           hdr_size + pieces->inst_size + pieces->data_size +
+           pieces->init_size + pieces->init_data_size + pieces->boot_size) {
+
+               IL_ERR("uCode file size %d does not match expected size\n",
+                      (int)ucode_raw->size);
+               return -EINVAL;
+       }
+
+       pieces->inst = src;
+       src += pieces->inst_size;
+       pieces->data = src;
+       src += pieces->data_size;
+       pieces->init = src;
+       src += pieces->init_size;
+       pieces->init_data = src;
+       src += pieces->init_data_size;
+       pieces->boot = src;
+       src += pieces->boot_size;
+
+       return 0;
+}
+
+/**
+ * il4965_ucode_callback - callback when firmware was loaded
+ *
+ * If loaded successfully, copies the firmware into buffers
+ * for the card to fetch (via DMA).
+ */
+static void
+il4965_ucode_callback(const struct firmware *ucode_raw, void *context)
+{
+       struct il_priv *il = context;
+       struct il_ucode_header *ucode;
+       int err;
+       struct il4965_firmware_pieces pieces;
+       const unsigned int api_max = il->cfg->ucode_api_max;
+       const unsigned int api_min = il->cfg->ucode_api_min;
+       u32 api_ver;
+
+       u32 max_probe_length = 200;
+       u32 standard_phy_calibration_size =
+           IL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+
+       memset(&pieces, 0, sizeof(pieces));
+
+       if (!ucode_raw) {
+               if (il->fw_idx <= il->cfg->ucode_api_max)
+                       IL_ERR("request for firmware file '%s' failed.\n",
+                              il->firmware_name);
+               goto try_again;
+       }
+
+       D_INFO("Loaded firmware file '%s' (%zd bytes).\n", il->firmware_name,
+              ucode_raw->size);
+
+       /* Make sure that we got at least the API version number */
+       if (ucode_raw->size < 4) {
+               IL_ERR("File size way too small!\n");
+               goto try_again;
+       }
+
+       /* Data from ucode file:  header followed by uCode images */
+       ucode = (struct il_ucode_header *)ucode_raw->data;
+
+       err = il4965_load_firmware(il, ucode_raw, &pieces);
+
+       if (err)
+               goto try_again;
+
+       api_ver = IL_UCODE_API(il->ucode_ver);
+
+       /*
+        * api_ver should match the api version forming part of the
+        * firmware filename ... but we don't check for that and only rely
+        * on the API version read from firmware header from here on forward
+        */
+       if (api_ver < api_min || api_ver > api_max) {
+               IL_ERR("Driver unable to support your firmware API. "
+                      "Driver supports v%u, firmware is v%u.\n", api_max,
+                      api_ver);
+               goto try_again;
+       }
+
+       if (api_ver != api_max)
+               IL_ERR("Firmware has old API version. Expected v%u, "
+                      "got v%u. New firmware can be obtained "
+                      "from http://www.intellinuxwireless.org.\n", api_max,
+                      api_ver);
+
+       IL_INFO("loaded firmware version %u.%u.%u.%u\n",
+               IL_UCODE_MAJOR(il->ucode_ver), IL_UCODE_MINOR(il->ucode_ver),
+               IL_UCODE_API(il->ucode_ver), IL_UCODE_SERIAL(il->ucode_ver));
+
+       snprintf(il->hw->wiphy->fw_version, sizeof(il->hw->wiphy->fw_version),
+                "%u.%u.%u.%u", IL_UCODE_MAJOR(il->ucode_ver),
+                IL_UCODE_MINOR(il->ucode_ver), IL_UCODE_API(il->ucode_ver),
+                IL_UCODE_SERIAL(il->ucode_ver));
+
+       /*
+        * For any of the failures below (before allocating pci memory)
+        * we will try to load a version with a smaller API -- maybe the
+        * user just got a corrupted version of the latest API.
+        */
+
+       D_INFO("f/w package hdr ucode version raw = 0x%x\n", il->ucode_ver);
+       D_INFO("f/w package hdr runtime inst size = %Zd\n", pieces.inst_size);
+       D_INFO("f/w package hdr runtime data size = %Zd\n", pieces.data_size);
+       D_INFO("f/w package hdr init inst size = %Zd\n", pieces.init_size);
+       D_INFO("f/w package hdr init data size = %Zd\n", pieces.init_data_size);
+       D_INFO("f/w package hdr boot inst size = %Zd\n", pieces.boot_size);
+
+       /* Verify that uCode images will fit in card's SRAM */
+       if (pieces.inst_size > il->hw_params.max_inst_size) {
+               IL_ERR("uCode instr len %Zd too large to fit in\n",
+                      pieces.inst_size);
+               goto try_again;
+       }
+
+       if (pieces.data_size > il->hw_params.max_data_size) {
+               IL_ERR("uCode data len %Zd too large to fit in\n",
+                      pieces.data_size);
+               goto try_again;
+       }
+
+       if (pieces.init_size > il->hw_params.max_inst_size) {
+               IL_ERR("uCode init instr len %Zd too large to fit in\n",
+                      pieces.init_size);
+               goto try_again;
+       }
+
+       if (pieces.init_data_size > il->hw_params.max_data_size) {
+               IL_ERR("uCode init data len %Zd too large to fit in\n",
+                      pieces.init_data_size);
+               goto try_again;
+       }
+
+       if (pieces.boot_size > il->hw_params.max_bsm_size) {
+               IL_ERR("uCode boot instr len %Zd too large to fit in\n",
+                      pieces.boot_size);
+               goto try_again;
+       }
+
+       /* 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 */
+       il->ucode_code.len = pieces.inst_size;
+       il_alloc_fw_desc(il->pci_dev, &il->ucode_code);
+
+       il->ucode_data.len = pieces.data_size;
+       il_alloc_fw_desc(il->pci_dev, &il->ucode_data);
+
+       il->ucode_data_backup.len = pieces.data_size;
+       il_alloc_fw_desc(il->pci_dev, &il->ucode_data_backup);
+
+       if (!il->ucode_code.v_addr || !il->ucode_data.v_addr ||
+           !il->ucode_data_backup.v_addr)
+               goto err_pci_alloc;
+
+       /* Initialization instructions and data */
+       if (pieces.init_size && pieces.init_data_size) {
+               il->ucode_init.len = pieces.init_size;
+               il_alloc_fw_desc(il->pci_dev, &il->ucode_init);
+
+               il->ucode_init_data.len = pieces.init_data_size;
+               il_alloc_fw_desc(il->pci_dev, &il->ucode_init_data);
+
+               if (!il->ucode_init.v_addr || !il->ucode_init_data.v_addr)
+                       goto err_pci_alloc;
+       }
+
+       /* Bootstrap (instructions only, no data) */
+       if (pieces.boot_size) {
+               il->ucode_boot.len = pieces.boot_size;
+               il_alloc_fw_desc(il->pci_dev, &il->ucode_boot);
+
+               if (!il->ucode_boot.v_addr)
+                       goto err_pci_alloc;
+       }
+
+       /* Now that we can no longer fail, copy information */
+
+       il->sta_key_max_num = STA_KEY_MAX_NUM;
+
+       /* Copy images into buffers for card's bus-master reads ... */
+
+       /* Runtime instructions (first block of data in file) */
+       D_INFO("Copying (but not loading) uCode instr len %Zd\n",
+              pieces.inst_size);
+       memcpy(il->ucode_code.v_addr, pieces.inst, pieces.inst_size);
+
+       D_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
+              il->ucode_code.v_addr, (u32) il->ucode_code.p_addr);
+
+       /*
+        * Runtime data
+        * NOTE:  Copy into backup buffer will be done in il_up()
+        */
+       D_INFO("Copying (but not loading) uCode data len %Zd\n",
+              pieces.data_size);
+       memcpy(il->ucode_data.v_addr, pieces.data, pieces.data_size);
+       memcpy(il->ucode_data_backup.v_addr, pieces.data, pieces.data_size);
+
+       /* Initialization instructions */
+       if (pieces.init_size) {
+               D_INFO("Copying (but not loading) init instr len %Zd\n",
+                      pieces.init_size);
+               memcpy(il->ucode_init.v_addr, pieces.init, pieces.init_size);
+       }
+
+       /* Initialization data */
+       if (pieces.init_data_size) {
+               D_INFO("Copying (but not loading) init data len %Zd\n",
+                      pieces.init_data_size);
+               memcpy(il->ucode_init_data.v_addr, pieces.init_data,
+                      pieces.init_data_size);
+       }
+
+       /* Bootstrap instructions */
+       D_INFO("Copying (but not loading) boot instr len %Zd\n",
+              pieces.boot_size);
+       memcpy(il->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
+
+       /*
+        * figure out the offset of chain noise reset and gain commands
+        * base on the size of standard phy calibration commands table size
+        */
+       il->_4965.phy_calib_chain_noise_reset_cmd =
+           standard_phy_calibration_size;
+       il->_4965.phy_calib_chain_noise_gain_cmd =
+           standard_phy_calibration_size + 1;
+
+       /**************************************************
+        * This is still part of probe() in a sense...
+        *
+        * 9. Setup and register with mac80211 and debugfs
+        **************************************************/
+       err = il4965_mac_setup_register(il, max_probe_length);
+       if (err)
+               goto out_unbind;
+
+       err = il_dbgfs_register(il, DRV_NAME);
+       if (err)
+               IL_ERR("failed to create debugfs files. Ignoring error: %d\n",
+                      err);
+
+       err = sysfs_create_group(&il->pci_dev->dev.kobj, &il_attribute_group);
+       if (err) {
+               IL_ERR("failed to create sysfs device attributes\n");
+               goto out_unbind;
+       }
+
+       /* We have our copies now, allow OS release its copies */
+       release_firmware(ucode_raw);
+       complete(&il->_4965.firmware_loading_complete);
+       return;
+
+try_again:
+       /* try next, if any */
+       if (il4965_request_firmware(il, false))
+               goto out_unbind;
+       release_firmware(ucode_raw);
+       return;
+
+err_pci_alloc:
+       IL_ERR("failed to allocate pci memory\n");
+       il4965_dealloc_ucode_pci(il);
+out_unbind:
+       complete(&il->_4965.firmware_loading_complete);
+       device_release_driver(&il->pci_dev->dev);
+       release_firmware(ucode_raw);
+}
+
+static const char *const desc_lookup_text[] = {
+       "OK",
+       "FAIL",
+       "BAD_PARAM",
+       "BAD_CHECKSUM",
+       "NMI_INTERRUPT_WDG",
+       "SYSASSERT",
+       "FATAL_ERROR",
+       "BAD_COMMAND",
+       "HW_ERROR_TUNE_LOCK",
+       "HW_ERROR_TEMPERATURE",
+       "ILLEGAL_CHAN_FREQ",
+       "VCC_NOT_STBL",
+       "FH49_ERROR",
+       "NMI_INTERRUPT_HOST",
+       "NMI_INTERRUPT_ACTION_PT",
+       "NMI_INTERRUPT_UNKNOWN",
+       "UCODE_VERSION_MISMATCH",
+       "HW_ERROR_ABS_LOCK",
+       "HW_ERROR_CAL_LOCK_FAIL",
+       "NMI_INTERRUPT_INST_ACTION_PT",
+       "NMI_INTERRUPT_DATA_ACTION_PT",
+       "NMI_TRM_HW_ER",
+       "NMI_INTERRUPT_TRM",
+       "NMI_INTERRUPT_BREAK_POINT",
+       "DEBUG_0",
+       "DEBUG_1",
+       "DEBUG_2",
+       "DEBUG_3",
+};
+
+static struct {
+       char *name;
+       u8 num;
+} advanced_lookup[] = {
+       {
+       "NMI_INTERRUPT_WDG", 0x34}, {
+       "SYSASSERT", 0x35}, {
+       "UCODE_VERSION_MISMATCH", 0x37}, {
+       "BAD_COMMAND", 0x38}, {
+       "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C}, {
+       "FATAL_ERROR", 0x3D}, {
+       "NMI_TRM_HW_ERR", 0x46}, {
+       "NMI_INTERRUPT_TRM", 0x4C}, {
+       "NMI_INTERRUPT_BREAK_POINT", 0x54}, {
+       "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C}, {
+       "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64}, {
+       "NMI_INTERRUPT_HOST", 0x66}, {
+       "NMI_INTERRUPT_ACTION_PT", 0x7C}, {
+       "NMI_INTERRUPT_UNKNOWN", 0x84}, {
+       "NMI_INTERRUPT_INST_ACTION_PT", 0x86}, {
+"ADVANCED_SYSASSERT", 0},};
+
+static const char *
+il4965_desc_lookup(u32 num)
+{
+       int i;
+       int max = ARRAY_SIZE(desc_lookup_text);
+
+       if (num < max)
+               return desc_lookup_text[num];
+
+       max = ARRAY_SIZE(advanced_lookup) - 1;
+       for (i = 0; i < max; i++) {
+               if (advanced_lookup[i].num == num)
+                       break;
+       }
+       return advanced_lookup[i].name;
+}
+
+#define ERROR_START_OFFSET  (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
+
+void
+il4965_dump_nic_error_log(struct il_priv *il)
+{
+       u32 data2, line;
+       u32 desc, time, count, base, data1;
+       u32 blink1, blink2, ilink1, ilink2;
+       u32 pc, hcmd;
+
+       if (il->ucode_type == UCODE_INIT)
+               base = le32_to_cpu(il->card_alive_init.error_event_table_ptr);
+       else
+               base = le32_to_cpu(il->card_alive.error_event_table_ptr);
+
+       if (!il->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+               IL_ERR("Not valid error log pointer 0x%08X for %s uCode\n",
+                      base, (il->ucode_type == UCODE_INIT) ? "Init" : "RT");
+               return;
+       }
+
+       count = il_read_targ_mem(il, base);
+
+       if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+               IL_ERR("Start IWL Error Log Dump:\n");
+               IL_ERR("Status: 0x%08lX, count: %d\n", il->status, count);
+       }
+
+       desc = il_read_targ_mem(il, base + 1 * sizeof(u32));
+       il->isr_stats.err_code = desc;
+       pc = il_read_targ_mem(il, base + 2 * sizeof(u32));
+       blink1 = il_read_targ_mem(il, base + 3 * sizeof(u32));
+       blink2 = il_read_targ_mem(il, base + 4 * sizeof(u32));
+       ilink1 = il_read_targ_mem(il, base + 5 * sizeof(u32));
+       ilink2 = il_read_targ_mem(il, base + 6 * sizeof(u32));
+       data1 = il_read_targ_mem(il, base + 7 * sizeof(u32));
+       data2 = il_read_targ_mem(il, base + 8 * sizeof(u32));
+       line = il_read_targ_mem(il, base + 9 * sizeof(u32));
+       time = il_read_targ_mem(il, base + 11 * sizeof(u32));
+       hcmd = il_read_targ_mem(il, base + 22 * sizeof(u32));
+
+       IL_ERR("Desc                                  Time       "
+              "data1      data2      line\n");
+       IL_ERR("%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
+              il4965_desc_lookup(desc), desc, time, data1, data2, line);
+       IL_ERR("pc      blink1  blink2  ilink1  ilink2  hcmd\n");
+       IL_ERR("0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", pc, blink1,
+              blink2, ilink1, ilink2, hcmd);
+}
+
+static void
+il4965_rf_kill_ct_config(struct il_priv *il)
+{
+       struct il_ct_kill_config cmd;
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&il->lock, flags);
+       _il_wr(il, CSR_UCODE_DRV_GP1_CLR,
+              CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       cmd.critical_temperature_R =
+           cpu_to_le32(il->hw_params.ct_kill_threshold);
+
+       ret = il_send_cmd_pdu(il, C_CT_KILL_CONFIG, sizeof(cmd), &cmd);
+       if (ret)
+               IL_ERR("C_CT_KILL_CONFIG failed\n");
+       else
+               D_INFO("C_CT_KILL_CONFIG " "succeeded, "
+                      "critical temperature is %d\n",
+                      il->hw_params.ct_kill_threshold);
+}
+
+static const s8 default_queue_to_tx_fifo[] = {
+       IL_TX_FIFO_VO,
+       IL_TX_FIFO_VI,
+       IL_TX_FIFO_BE,
+       IL_TX_FIFO_BK,
+       IL49_CMD_FIFO_NUM,
+       IL_TX_FIFO_UNUSED,
+       IL_TX_FIFO_UNUSED,
+};
+
+#define IL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
+
+static int
+il4965_alive_notify(struct il_priv *il)
+{
+       u32 a;
+       unsigned long flags;
+       int i, chan;
+       u32 reg_val;
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       /* Clear 4965's internal Tx Scheduler data base */
+       il->scd_base_addr = il_rd_prph(il, IL49_SCD_SRAM_BASE_ADDR);
+       a = il->scd_base_addr + IL49_SCD_CONTEXT_DATA_OFFSET;
+       for (; a < il->scd_base_addr + IL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4)
+               il_write_targ_mem(il, a, 0);
+       for (; a < il->scd_base_addr + IL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
+               il_write_targ_mem(il, a, 0);
+       for (;
+            a <
+            il->scd_base_addr +
+            IL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(il->hw_params.max_txq_num);
+            a += 4)
+               il_write_targ_mem(il, a, 0);
+
+       /* Tel 4965 where to find Tx byte count tables */
+       il_wr_prph(il, IL49_SCD_DRAM_BASE_ADDR, il->scd_bc_tbls.dma >> 10);
+
+       /* Enable DMA channel */
+       for (chan = 0; chan < FH49_TCSR_CHNL_NUM; chan++)
+               il_wr(il, FH49_TCSR_CHNL_TX_CONFIG_REG(chan),
+                     FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+                     FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
+
+       /* Update FH chicken bits */
+       reg_val = il_rd(il, FH49_TX_CHICKEN_BITS_REG);
+       il_wr(il, FH49_TX_CHICKEN_BITS_REG,
+             reg_val | FH49_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
+
+       /* Disable chain mode for all queues */
+       il_wr_prph(il, IL49_SCD_QUEUECHAIN_SEL, 0);
+
+       /* Initialize each Tx queue (including the command queue) */
+       for (i = 0; i < il->hw_params.max_txq_num; i++) {
+
+               /* TFD circular buffer read/write idxes */
+               il_wr_prph(il, IL49_SCD_QUEUE_RDPTR(i), 0);
+               il_wr(il, HBUS_TARG_WRPTR, 0 | (i << 8));
+
+               /* Max Tx Window size for Scheduler-ACK mode */
+               il_write_targ_mem(il,
+                                 il->scd_base_addr +
+                                 IL49_SCD_CONTEXT_QUEUE_OFFSET(i),
+                                 (SCD_WIN_SIZE <<
+                                  IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
+                                 IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
+
+               /* Frame limit */
+               il_write_targ_mem(il,
+                                 il->scd_base_addr +
+                                 IL49_SCD_CONTEXT_QUEUE_OFFSET(i) +
+                                 sizeof(u32),
+                                 (SCD_FRAME_LIMIT <<
+                                  IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
+                                 IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
+
+       }
+       il_wr_prph(il, IL49_SCD_INTERRUPT_MASK,
+                  (1 << il->hw_params.max_txq_num) - 1);
+
+       /* Activate all Tx DMA/FIFO channels */
+       il4965_txq_set_sched(il, IL_MASK(0, 6));
+
+       il4965_set_wr_ptrs(il, IL_DEFAULT_CMD_QUEUE_NUM, 0);
+
+       /* make sure all queue are not stopped */
+       memset(&il->queue_stopped[0], 0, sizeof(il->queue_stopped));
+       for (i = 0; i < 4; i++)
+               atomic_set(&il->queue_stop_count[i], 0);
+
+       /* reset to 0 to enable all the queue first */
+       il->txq_ctx_active_msk = 0;
+       /* Map each Tx/cmd queue to its corresponding fifo */
+       BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
+
+       for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
+               int ac = default_queue_to_tx_fifo[i];
+
+               il_txq_ctx_activate(il, i);
+
+               if (ac == IL_TX_FIFO_UNUSED)
+                       continue;
+
+               il4965_tx_queue_set_status(il, &il->txq[i], ac, 0);
+       }
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       return 0;
+}
+
+/**
+ * il4965_alive_start - called after N_ALIVE notification received
+ *                   from protocol/runtime uCode (initialization uCode's
+ *                   Alive gets handled by il_init_alive_start()).
+ */
+static void
+il4965_alive_start(struct il_priv *il)
+{
+       int ret = 0;
+       struct il_rxon_context *ctx = &il->ctx;
+
+       D_INFO("Runtime Alive received.\n");
+
+       if (il->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 */
+               D_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 (il4965_verify_ucode(il)) {
+               /* Runtime instruction load was bad;
+                * take it all the way back down so we can try again */
+               D_INFO("Bad runtime uCode load.\n");
+               goto restart;
+       }
+
+       ret = il4965_alive_notify(il);
+       if (ret) {
+               IL_WARN("Could not complete ALIVE transition [ntf]: %d\n", ret);
+               goto restart;
+       }
+
+       /* After the ALIVE response, we can send host commands to the uCode */
+       set_bit(S_ALIVE, &il->status);
+
+       /* Enable watchdog to monitor the driver tx queues */
+       il_setup_watchdog(il);
+
+       if (il_is_rfkill(il))
+               return;
+
+       ieee80211_wake_queues(il->hw);
+
+       il->active_rate = RATES_MASK;
+
+       if (il_is_associated_ctx(ctx)) {
+               struct il_rxon_cmd *active_rxon =
+                   (struct il_rxon_cmd *)&ctx->active;
+               /* apply any changes in staging */
+               ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+               active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+       } else {
+               /* Initialize our rx_config data */
+               il_connection_init_rx_config(il, &il->ctx);
+
+               if (il->cfg->ops->hcmd->set_rxon_chain)
+                       il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
+       }
+
+       /* Configure bluetooth coexistence if enabled */
+       il_send_bt_config(il);
+
+       il4965_reset_run_time_calib(il);
+
+       set_bit(S_READY, &il->status);
+
+       /* Configure the adapter for unassociated operation */
+       il_commit_rxon(il, ctx);
+
+       /* At this point, the NIC is initialized and operational */
+       il4965_rf_kill_ct_config(il);
+
+       D_INFO("ALIVE processing complete.\n");
+       wake_up(&il->wait_command_queue);
+
+       il_power_update_mode(il, true);
+       D_INFO("Updated power mode\n");
+
+       return;
+
+restart:
+       queue_work(il->workqueue, &il->restart);
+}
+
+static void il4965_cancel_deferred_work(struct il_priv *il);
+
+static void
+__il4965_down(struct il_priv *il)
+{
+       unsigned long flags;
+       int exit_pending;
+
+       D_INFO(DRV_NAME " is going down\n");
+
+       il_scan_cancel_timeout(il, 200);
+
+       exit_pending = test_and_set_bit(S_EXIT_PENDING, &il->status);
+
+       /* Stop TX queues watchdog. We need to have S_EXIT_PENDING bit set
+        * to prevent rearm timer */
+       del_timer_sync(&il->watchdog);
+
+       il_clear_ucode_stations(il, NULL);
+       il_dealloc_bcast_stations(il);
+       il_clear_driver_stations(il);
+
+       /* Unblock any waiting calls */
+       wake_up_all(&il->wait_command_queue);
+
+       /* Wipe out the EXIT_PENDING status bit if we are not actually
+        * exiting the module */
+       if (!exit_pending)
+               clear_bit(S_EXIT_PENDING, &il->status);
+
+       /* stop and reset the on-board processor */
+       _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+       /* tell the device to stop sending interrupts */
+       spin_lock_irqsave(&il->lock, flags);
+       il_disable_interrupts(il);
+       spin_unlock_irqrestore(&il->lock, flags);
+       il4965_synchronize_irq(il);
+
+       if (il->mac80211_registered)
+               ieee80211_stop_queues(il->hw);
+
+       /* If we have not previously called il_init() then
+        * clear all bits but the RF Kill bit and return */
+       if (!il_is_init(il)) {
+               il->status =
+                   test_bit(S_RF_KILL_HW,
+                            &il->
+                            status) << S_RF_KILL_HW |
+                   test_bit(S_GEO_CONFIGURED,
+                            &il->
+                            status) << S_GEO_CONFIGURED |
+                   test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
+               goto exit;
+       }
+
+       /* ...otherwise clear out all the status bits but the RF Kill
+        * bit and continue taking the NIC down. */
+       il->status &=
+           test_bit(S_RF_KILL_HW,
+                    &il->status) << S_RF_KILL_HW | test_bit(S_GEO_CONFIGURED,
+                                                            &il->
+                                                            status) <<
+           S_GEO_CONFIGURED | test_bit(S_FW_ERROR,
+                                       &il->
+                                       status) << S_FW_ERROR |
+           test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
+
+       il4965_txq_ctx_stop(il);
+       il4965_rxq_stop(il);
+
+       /* Power-down device's busmaster DMA clocks */
+       il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+       udelay(5);
+
+       /* Make sure (redundant) we've released our request to stay awake */
+       il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+       /* Stop the device, and put it in low power state */
+       il_apm_stop(il);
+
+exit:
+       memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
+
+       dev_kfree_skb(il->beacon_skb);
+       il->beacon_skb = NULL;
+
+       /* clear out any free frames */
+       il4965_clear_free_frames(il);
+}
+
+static void
+il4965_down(struct il_priv *il)
+{
+       mutex_lock(&il->mutex);
+       __il4965_down(il);
+       mutex_unlock(&il->mutex);
+
+       il4965_cancel_deferred_work(il);
+}
+
+#define HW_READY_TIMEOUT (50)
+
+static int
+il4965_set_hw_ready(struct il_priv *il)
+{
+       int ret = 0;
+
+       il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                  CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
+
+       /* See if we got it */
+       ret =
+           _il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
+                        CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+                        CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, HW_READY_TIMEOUT);
+       if (ret != -ETIMEDOUT)
+               il->hw_ready = true;
+       else
+               il->hw_ready = false;
+
+       D_INFO("hardware %s\n", (il->hw_ready == 1) ? "ready" : "not ready");
+       return ret;
+}
+
+static int
+il4965_prepare_card_hw(struct il_priv *il)
+{
+       int ret = 0;
+
+       D_INFO("il4965_prepare_card_hw enter\n");
+
+       ret = il4965_set_hw_ready(il);
+       if (il->hw_ready)
+               return ret;
+
+       /* If HW is not ready, prepare the conditions to check again */
+       il_set_bit(il, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PREPARE);
+
+       ret =
+           _il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
+                        ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
+                        CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
+
+       /* HW should be ready by now, check again. */
+       if (ret != -ETIMEDOUT)
+               il4965_set_hw_ready(il);
+
+       return ret;
+}
+
+#define MAX_HW_RESTARTS 5
+
+static int
+__il4965_up(struct il_priv *il)
+{
+       int i;
+       int ret;
+
+       if (test_bit(S_EXIT_PENDING, &il->status)) {
+               IL_WARN("Exit pending; will not bring the NIC up\n");
+               return -EIO;
+       }
+
+       if (!il->ucode_data_backup.v_addr || !il->ucode_data.v_addr) {
+               IL_ERR("ucode not available for device bringup\n");
+               return -EIO;
+       }
+
+       ret = il4965_alloc_bcast_station(il, &il->ctx);
+       if (ret) {
+               il_dealloc_bcast_stations(il);
+               return ret;
+       }
+
+       il4965_prepare_card_hw(il);
+
+       if (!il->hw_ready) {
+               IL_WARN("Exit HW not ready\n");
+               return -EIO;
+       }
+
+       /* If platform's RF_KILL switch is NOT set to KILL */
+       if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+               clear_bit(S_RF_KILL_HW, &il->status);
+       else
+               set_bit(S_RF_KILL_HW, &il->status);
+
+       if (il_is_rfkill(il)) {
+               wiphy_rfkill_set_hw_state(il->hw->wiphy, true);
+
+               il_enable_interrupts(il);
+               IL_WARN("Radio disabled by HW RF Kill switch\n");
+               return 0;
+       }
+
+       _il_wr(il, CSR_INT, 0xFFFFFFFF);
+
+       /* must be initialised before il_hw_nic_init */
+       il->cmd_queue = IL_DEFAULT_CMD_QUEUE_NUM;
+
+       ret = il4965_hw_nic_init(il);
+       if (ret) {
+               IL_ERR("Unable to init nic\n");
+               return ret;
+       }
+
+       /* make sure rfkill handshake bits are cleared */
+       _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+       /* clear (again), then enable host interrupts */
+       _il_wr(il, CSR_INT, 0xFFFFFFFF);
+       il_enable_interrupts(il);
+
+       /* really make sure rfkill handshake bits are cleared */
+       _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       _il_wr(il, 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(il->ucode_data_backup.v_addr, il->ucode_data.v_addr,
+              il->ucode_data.len);
+
+       for (i = 0; i < MAX_HW_RESTARTS; i++) {
+
+               /* load bootstrap state machine,
+                * load bootstrap program into processor's memory,
+                * prepare to load the "initialize" uCode */
+               ret = il->cfg->ops->lib->load_ucode(il);
+
+               if (ret) {
+                       IL_ERR("Unable to set up bootstrap uCode: %d\n", ret);
+                       continue;
+               }
+
+               /* start card; "initialize" will load runtime ucode */
+               il4965_nic_start(il);
+
+               D_INFO(DRV_NAME " is coming up\n");
+
+               return 0;
+       }
+
+       set_bit(S_EXIT_PENDING, &il->status);
+       __il4965_down(il);
+       clear_bit(S_EXIT_PENDING, &il->status);
+
+       /* tried to restart and config the device for as long as our
+        * patience could withstand */
+       IL_ERR("Unable to initialize device after %d attempts.\n", i);
+       return -EIO;
+}
+
+/*****************************************************************************
+ *
+ * Workqueue callbacks
+ *
+ *****************************************************************************/
+
+static void
+il4965_bg_init_alive_start(struct work_struct *data)
+{
+       struct il_priv *il =
+           container_of(data, struct il_priv, init_alive_start.work);
+
+       mutex_lock(&il->mutex);
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               goto out;
+
+       il->cfg->ops->lib->init_alive_start(il);
+out:
+       mutex_unlock(&il->mutex);
+}
+
+static void
+il4965_bg_alive_start(struct work_struct *data)
+{
+       struct il_priv *il =
+           container_of(data, struct il_priv, alive_start.work);
+
+       mutex_lock(&il->mutex);
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               goto out;
+
+       il4965_alive_start(il);
+out:
+       mutex_unlock(&il->mutex);
+}
+
+static void
+il4965_bg_run_time_calib_work(struct work_struct *work)
+{
+       struct il_priv *il = container_of(work, struct il_priv,
+                                         run_time_calib_work);
+
+       mutex_lock(&il->mutex);
+
+       if (test_bit(S_EXIT_PENDING, &il->status) ||
+           test_bit(S_SCANNING, &il->status)) {
+               mutex_unlock(&il->mutex);
+               return;
+       }
+
+       if (il->start_calib) {
+               il4965_chain_noise_calibration(il, (void *)&il->_4965.stats);
+               il4965_sensitivity_calibration(il, (void *)&il->_4965.stats);
+       }
+
+       mutex_unlock(&il->mutex);
+}
+
+static void
+il4965_bg_restart(struct work_struct *data)
+{
+       struct il_priv *il = container_of(data, struct il_priv, restart);
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
+               mutex_lock(&il->mutex);
+               il->ctx.vif = NULL;
+               il->is_open = 0;
+
+               __il4965_down(il);
+
+               mutex_unlock(&il->mutex);
+               il4965_cancel_deferred_work(il);
+               ieee80211_restart_hw(il->hw);
+       } else {
+               il4965_down(il);
+
+               mutex_lock(&il->mutex);
+               if (test_bit(S_EXIT_PENDING, &il->status)) {
+                       mutex_unlock(&il->mutex);
+                       return;
+               }
+
+               __il4965_up(il);
+               mutex_unlock(&il->mutex);
+       }
+}
+
+static void
+il4965_bg_rx_replenish(struct work_struct *data)
+{
+       struct il_priv *il = container_of(data, struct il_priv, rx_replenish);
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       mutex_lock(&il->mutex);
+       il4965_rx_replenish(il);
+       mutex_unlock(&il->mutex);
+}
+
+/*****************************************************************************
+ *
+ * mac80211 entry point functions
+ *
+ *****************************************************************************/
+
+#define UCODE_READY_TIMEOUT    (4 * HZ)
+
+/*
+ * Not a mac80211 entry point function, but it fits in with all the
+ * other mac80211 functions grouped here.
+ */
+static int
+il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
+{
+       int ret;
+       struct ieee80211_hw *hw = il->hw;
+
+       hw->rate_control_algorithm = "iwl-4965-rs";
+
+       /* Tell mac80211 our characteristics */
+       hw->flags =
+           IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |
+           IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT |
+           IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+
+       if (il->cfg->sku & IL_SKU_N)
+               hw->flags |=
+                   IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
+                   IEEE80211_HW_SUPPORTS_STATIC_SMPS;
+
+       hw->sta_data_size = sizeof(struct il_station_priv);
+       hw->vif_data_size = sizeof(struct il_vif_priv);
+
+       hw->wiphy->interface_modes |= il->ctx.interface_modes;
+       hw->wiphy->interface_modes |= il->ctx.exclusive_interface_modes;
+
+       hw->wiphy->flags |=
+           WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS;
+
+       /*
+        * For now, disable PS by default because it affects
+        * RX performance significantly.
+        */
+       hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+       hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
+       /* we create the 802.11 header and a zero-length SSID element */
+       hw->wiphy->max_scan_ie_len = max_probe_length - 24 - 2;
+
+       /* Default value; 4 EDCA QOS priorities */
+       hw->queues = 4;
+
+       hw->max_listen_interval = IL_CONN_MAX_LISTEN_INTERVAL;
+
+       if (il->bands[IEEE80211_BAND_2GHZ].n_channels)
+               il->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+                   &il->bands[IEEE80211_BAND_2GHZ];
+       if (il->bands[IEEE80211_BAND_5GHZ].n_channels)
+               il->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+                   &il->bands[IEEE80211_BAND_5GHZ];
+
+       il_leds_init(il);
+
+       ret = ieee80211_register_hw(il->hw);
+       if (ret) {
+               IL_ERR("Failed to register hw (error %d)\n", ret);
+               return ret;
+       }
+       il->mac80211_registered = 1;
+
+       return 0;
+}
+
+int
+il4965_mac_start(struct ieee80211_hw *hw)
+{
+       struct il_priv *il = hw->priv;
+       int ret;
+
+       D_MAC80211("enter\n");
+
+       /* we should be verifying the device is ready to be opened */
+       mutex_lock(&il->mutex);
+       ret = __il4965_up(il);
+       mutex_unlock(&il->mutex);
+
+       if (ret)
+               return ret;
+
+       if (il_is_rfkill(il))
+               goto out;
+
+       D_INFO("Start UP work done.\n");
+
+       /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
+        * mac80211 will not be run successfully. */
+       ret = wait_event_timeout(il->wait_command_queue,
+                                test_bit(S_READY, &il->status),
+                                UCODE_READY_TIMEOUT);
+       if (!ret) {
+               if (!test_bit(S_READY, &il->status)) {
+                       IL_ERR("START_ALIVE timeout after %dms.\n",
+                               jiffies_to_msecs(UCODE_READY_TIMEOUT));
+                       return -ETIMEDOUT;
+               }
+       }
+
+       il4965_led_enable(il);
+
+out:
+       il->is_open = 1;
+       D_MAC80211("leave\n");
+       return 0;
+}
+
+void
+il4965_mac_stop(struct ieee80211_hw *hw)
+{
+       struct il_priv *il = hw->priv;
+
+       D_MAC80211("enter\n");
+
+       if (!il->is_open)
+               return;
+
+       il->is_open = 0;
+
+       il4965_down(il);
+
+       flush_workqueue(il->workqueue);
+
+       /* User space software may expect getting rfkill changes
+        * even if interface is down */
+       _il_wr(il, CSR_INT, 0xFFFFFFFF);
+       il_enable_rfkill_int(il);
+
+       D_MAC80211("leave\n");
+}
+
+void
+il4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+       struct il_priv *il = hw->priv;
+
+       D_MACDUMP("enter\n");
+
+       D_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+            ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
+
+       if (il4965_tx_skb(il, skb))
+               dev_kfree_skb_any(skb);
+
+       D_MACDUMP("leave\n");
+}
+
+void
+il4965_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                          struct ieee80211_key_conf *keyconf,
+                          struct ieee80211_sta *sta, u32 iv32, u16 * phase1key)
+{
+       struct il_priv *il = hw->priv;
+       struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
+
+       D_MAC80211("enter\n");
+
+       il4965_update_tkip_key(il, vif_priv->ctx, keyconf, sta, iv32,
+                              phase1key);
+
+       D_MAC80211("leave\n");
+}
+
+int
+il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+                  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+                  struct ieee80211_key_conf *key)
+{
+       struct il_priv *il = hw->priv;
+       struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
+       struct il_rxon_context *ctx = vif_priv->ctx;
+       int ret;
+       u8 sta_id;
+       bool is_default_wep_key = false;
+
+       D_MAC80211("enter\n");
+
+       if (il->cfg->mod_params->sw_crypto) {
+               D_MAC80211("leave - hwcrypto disabled\n");
+               return -EOPNOTSUPP;
+       }
+
+       sta_id = il_sta_id_or_broadcast(il, vif_priv->ctx, sta);
+       if (sta_id == IL_INVALID_STATION)
+               return -EINVAL;
+
+       mutex_lock(&il->mutex);
+       il_scan_cancel_timeout(il, 100);
+
+       /*
+        * If we are getting WEP group key and we didn't receive any key mapping
+        * so far, we are in legacy wep mode (group key only), otherwise we are
+        * in 1X mode.
+        * In legacy wep mode, we use another host command to the uCode.
+        */
+       if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+            key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) {
+               if (cmd == SET_KEY)
+                       is_default_wep_key = !ctx->key_mapping_keys;
+               else
+                       is_default_wep_key =
+                           (key->hw_key_idx == HW_KEY_DEFAULT);
+       }
+
+       switch (cmd) {
+       case SET_KEY:
+               if (is_default_wep_key)
+                       ret =
+                           il4965_set_default_wep_key(il, vif_priv->ctx, key);
+               else
+                       ret =
+                           il4965_set_dynamic_key(il, vif_priv->ctx, key,
+                                                  sta_id);
+
+               D_MAC80211("enable hwcrypto key\n");
+               break;
+       case DISABLE_KEY:
+               if (is_default_wep_key)
+                       ret = il4965_remove_default_wep_key(il, ctx, key);
+               else
+                       ret = il4965_remove_dynamic_key(il, ctx, key, sta_id);
+
+               D_MAC80211("disable hwcrypto key\n");
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       mutex_unlock(&il->mutex);
+       D_MAC80211("leave\n");
+
+       return ret;
+}
+
+int
+il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                       enum ieee80211_ampdu_mlme_action action,
+                       struct ieee80211_sta *sta, u16 tid, u16 * ssn,
+                       u8 buf_size)
+{
+       struct il_priv *il = hw->priv;
+       int ret = -EINVAL;
+
+       D_HT("A-MPDU action on addr %pM tid %d\n", sta->addr, tid);
+
+       if (!(il->cfg->sku & IL_SKU_N))
+               return -EACCES;
+
+       mutex_lock(&il->mutex);
+
+       switch (action) {
+       case IEEE80211_AMPDU_RX_START:
+               D_HT("start Rx\n");
+               ret = il4965_sta_rx_agg_start(il, sta, tid, *ssn);
+               break;
+       case IEEE80211_AMPDU_RX_STOP:
+               D_HT("stop Rx\n");
+               ret = il4965_sta_rx_agg_stop(il, sta, tid);
+               if (test_bit(S_EXIT_PENDING, &il->status))
+                       ret = 0;
+               break;
+       case IEEE80211_AMPDU_TX_START:
+               D_HT("start Tx\n");
+               ret = il4965_tx_agg_start(il, vif, sta, tid, ssn);
+               break;
+       case IEEE80211_AMPDU_TX_STOP:
+               D_HT("stop Tx\n");
+               ret = il4965_tx_agg_stop(il, vif, sta, tid);
+               if (test_bit(S_EXIT_PENDING, &il->status))
+                       ret = 0;
+               break;
+       case IEEE80211_AMPDU_TX_OPERATIONAL:
+               ret = 0;
+               break;
+       }
+       mutex_unlock(&il->mutex);
+
+       return ret;
+}
+
+int
+il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                  struct ieee80211_sta *sta)
+{
+       struct il_priv *il = hw->priv;
+       struct il_station_priv *sta_priv = (void *)sta->drv_priv;
+       struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
+       bool is_ap = vif->type == NL80211_IFTYPE_STATION;
+       int ret;
+       u8 sta_id;
+
+       D_INFO("received request to add station %pM\n", sta->addr);
+       mutex_lock(&il->mutex);
+       D_INFO("proceeding to add station %pM\n", sta->addr);
+       sta_priv->common.sta_id = IL_INVALID_STATION;
+
+       atomic_set(&sta_priv->pending_frames, 0);
+
+       ret =
+           il_add_station_common(il, vif_priv->ctx, sta->addr, is_ap, sta,
+                                 &sta_id);
+       if (ret) {
+               IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret);
+               /* Should we return success if return code is EEXIST ? */
+               mutex_unlock(&il->mutex);
+               return ret;
+       }
+
+       sta_priv->common.sta_id = sta_id;
+
+       /* Initialize rate scaling */
+       D_INFO("Initializing rate scaling for station %pM\n", sta->addr);
+       il4965_rs_rate_init(il, sta, sta_id);
+       mutex_unlock(&il->mutex);
+
+       return 0;
+}
+
+void
+il4965_mac_channel_switch(struct ieee80211_hw *hw,
+                         struct ieee80211_channel_switch *ch_switch)
+{
+       struct il_priv *il = hw->priv;
+       const struct il_channel_info *ch_info;
+       struct ieee80211_conf *conf = &hw->conf;
+       struct ieee80211_channel *channel = ch_switch->channel;
+       struct il_ht_config *ht_conf = &il->current_ht_config;
+
+       struct il_rxon_context *ctx = &il->ctx;
+       u16 ch;
+
+       D_MAC80211("enter\n");
+
+       mutex_lock(&il->mutex);
+
+       if (il_is_rfkill(il))
+               goto out;
+
+       if (test_bit(S_EXIT_PENDING, &il->status) ||
+           test_bit(S_SCANNING, &il->status) ||
+           test_bit(S_CHANNEL_SWITCH_PENDING, &il->status))
+               goto out;
+
+       if (!il_is_associated_ctx(ctx))
+               goto out;
+
+       if (!il->cfg->ops->lib->set_channel_switch)
+               goto out;
+
+       ch = channel->hw_value;
+       if (le16_to_cpu(ctx->active.channel) == ch)
+               goto out;
+
+       ch_info = il_get_channel_info(il, channel->band, ch);
+       if (!il_is_channel_valid(ch_info)) {
+               D_MAC80211("invalid channel\n");
+               goto out;
+       }
+
+       spin_lock_irq(&il->lock);
+
+       il->current_ht_config.smps = conf->smps_mode;
+
+       /* Configure HT40 channels */
+       ctx->ht.enabled = conf_is_ht(conf);
+       if (ctx->ht.enabled) {
+               if (conf_is_ht40_minus(conf)) {
+                       ctx->ht.extension_chan_offset =
+                           IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+                       ctx->ht.is_40mhz = true;
+               } else if (conf_is_ht40_plus(conf)) {
+                       ctx->ht.extension_chan_offset =
+                           IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+                       ctx->ht.is_40mhz = true;
+               } else {
+                       ctx->ht.extension_chan_offset =
+                           IEEE80211_HT_PARAM_CHA_SEC_NONE;
+                       ctx->ht.is_40mhz = false;
+               }
+       } else
+               ctx->ht.is_40mhz = false;
+
+       if ((le16_to_cpu(ctx->staging.channel) != ch))
+               ctx->staging.flags = 0;
+
+       il_set_rxon_channel(il, channel, ctx);
+       il_set_rxon_ht(il, ht_conf);
+       il_set_flags_for_band(il, ctx, channel->band, ctx->vif);
+
+       spin_unlock_irq(&il->lock);
+
+       il_set_rate(il);
+       /*
+        * at this point, staging_rxon has the
+        * configuration for channel switch
+        */
+       set_bit(S_CHANNEL_SWITCH_PENDING, &il->status);
+       il->switch_channel = cpu_to_le16(ch);
+       if (il->cfg->ops->lib->set_channel_switch(il, ch_switch)) {
+               clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status);
+               il->switch_channel = 0;
+               ieee80211_chswitch_done(ctx->vif, false);
+       }
+
+out:
+       mutex_unlock(&il->mutex);
+       D_MAC80211("leave\n");
+}
+
+void
+il4965_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
+                       unsigned int *total_flags, u64 multicast)
+{
+       struct il_priv *il = hw->priv;
+       __le32 filter_or = 0, filter_nand = 0;
+
+#define CHK(test, flag)        do { \
+       if (*total_flags & (test))              \
+               filter_or |= (flag);            \
+       else                                    \
+               filter_nand |= (flag);          \
+       } while (0)
+
+       D_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", changed_flags,
+                  *total_flags);
+
+       CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
+       /* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */
+       CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
+       CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
+
+#undef CHK
+
+       mutex_lock(&il->mutex);
+
+       il->ctx.staging.filter_flags &= ~filter_nand;
+       il->ctx.staging.filter_flags |= filter_or;
+
+       /*
+        * Not committing directly because hardware can perform a scan,
+        * but we'll eventually commit the filter flags change anyway.
+        */
+
+       mutex_unlock(&il->mutex);
+
+       /*
+        * Receiving all multicast frames is always enabled by the
+        * default flags setup in il_connection_init_rx_config()
+        * since we currently do not support programming multicast
+        * filters into the device.
+        */
+       *total_flags &=
+           FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
+           FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
+}
+
+/*****************************************************************************
+ *
+ * driver setup and teardown
+ *
+ *****************************************************************************/
+
+static void
+il4965_bg_txpower_work(struct work_struct *work)
+{
+       struct il_priv *il = container_of(work, struct il_priv,
+                                         txpower_work);
+
+       mutex_lock(&il->mutex);
+
+       /* If a scan happened to start before we got here
+        * then just return; the stats notification will
+        * kick off another scheduled work to compensate for
+        * any temperature delta we missed here. */
+       if (test_bit(S_EXIT_PENDING, &il->status) ||
+           test_bit(S_SCANNING, &il->status))
+               goto out;
+
+       /* Regardless of if we are associated, we must reconfigure the
+        * TX power since frames can be sent on non-radar channels while
+        * not associated */
+       il->cfg->ops->lib->send_tx_power(il);
+
+       /* Update last_temperature to keep is_calib_needed from running
+        * when it isn't needed... */
+       il->last_temperature = il->temperature;
+out:
+       mutex_unlock(&il->mutex);
+}
+
+static void
+il4965_setup_deferred_work(struct il_priv *il)
+{
+       il->workqueue = create_singlethread_workqueue(DRV_NAME);
+
+       init_waitqueue_head(&il->wait_command_queue);
+
+       INIT_WORK(&il->restart, il4965_bg_restart);
+       INIT_WORK(&il->rx_replenish, il4965_bg_rx_replenish);
+       INIT_WORK(&il->run_time_calib_work, il4965_bg_run_time_calib_work);
+       INIT_DELAYED_WORK(&il->init_alive_start, il4965_bg_init_alive_start);
+       INIT_DELAYED_WORK(&il->alive_start, il4965_bg_alive_start);
+
+       il_setup_scan_deferred_work(il);
+
+       INIT_WORK(&il->txpower_work, il4965_bg_txpower_work);
+
+       init_timer(&il->stats_periodic);
+       il->stats_periodic.data = (unsigned long)il;
+       il->stats_periodic.function = il4965_bg_stats_periodic;
+
+       init_timer(&il->watchdog);
+       il->watchdog.data = (unsigned long)il;
+       il->watchdog.function = il_bg_watchdog;
+
+       tasklet_init(&il->irq_tasklet,
+                    (void (*)(unsigned long))il4965_irq_tasklet,
+                    (unsigned long)il);
+}
+
+static void
+il4965_cancel_deferred_work(struct il_priv *il)
+{
+       cancel_work_sync(&il->txpower_work);
+       cancel_delayed_work_sync(&il->init_alive_start);
+       cancel_delayed_work(&il->alive_start);
+       cancel_work_sync(&il->run_time_calib_work);
+
+       il_cancel_scan_deferred_work(il);
+
+       del_timer_sync(&il->stats_periodic);
+}
+
+static void
+il4965_init_hw_rates(struct il_priv *il, struct ieee80211_rate *rates)
+{
+       int i;
+
+       for (i = 0; i < RATE_COUNT_LEGACY; i++) {
+               rates[i].bitrate = il_rates[i].ieee * 5;
+               rates[i].hw_value = i;  /* Rate scaling will work on idxes */
+               rates[i].hw_value_short = i;
+               rates[i].flags = 0;
+               if ((i >= IL_FIRST_CCK_RATE) && (i <= IL_LAST_CCK_RATE)) {
+                       /*
+                        * If CCK != 1M then set short preamble rate flag.
+                        */
+                       rates[i].flags |=
+                           (il_rates[i].plcp ==
+                            RATE_1M_PLCP) ? 0 : IEEE80211_RATE_SHORT_PREAMBLE;
+               }
+       }
+}
+
+/*
+ * Acquire il->lock before calling this function !
+ */
+void
+il4965_set_wr_ptrs(struct il_priv *il, int txq_id, u32 idx)
+{
+       il_wr(il, HBUS_TARG_WRPTR, (idx & 0xff) | (txq_id << 8));
+       il_wr_prph(il, IL49_SCD_QUEUE_RDPTR(txq_id), idx);
+}
+
+void
+il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq,
+                          int tx_fifo_id, int scd_retry)
+{
+       int txq_id = txq->q.id;
+
+       /* Find out whether to activate Tx queue */
+       int active = test_bit(txq_id, &il->txq_ctx_active_msk) ? 1 : 0;
+
+       /* Set up and activate */
+       il_wr_prph(il, IL49_SCD_QUEUE_STATUS_BITS(txq_id),
+                  (active << IL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
+                  (tx_fifo_id << IL49_SCD_QUEUE_STTS_REG_POS_TXF) |
+                  (scd_retry << IL49_SCD_QUEUE_STTS_REG_POS_WSL) |
+                  (scd_retry << IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) |
+                  IL49_SCD_QUEUE_STTS_REG_MSK);
+
+       txq->sched_retry = scd_retry;
+
+       D_INFO("%s %s Queue %d on AC %d\n", active ? "Activate" : "Deactivate",
+              scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
+}
+
+static int
+il4965_init_drv(struct il_priv *il)
+{
+       int ret;
+
+       spin_lock_init(&il->sta_lock);
+       spin_lock_init(&il->hcmd_lock);
+
+       INIT_LIST_HEAD(&il->free_frames);
+
+       mutex_init(&il->mutex);
+
+       il->ieee_channels = NULL;
+       il->ieee_rates = NULL;
+       il->band = IEEE80211_BAND_2GHZ;
+
+       il->iw_mode = NL80211_IFTYPE_STATION;
+       il->current_ht_config.smps = IEEE80211_SMPS_STATIC;
+       il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
+
+       /* initialize force reset */
+       il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD;
+
+       /* Choose which receivers/antennas to use */
+       if (il->cfg->ops->hcmd->set_rxon_chain)
+               il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx);
+
+       il_init_scan_params(il);
+
+       ret = il_init_channel_map(il);
+       if (ret) {
+               IL_ERR("initializing regulatory failed: %d\n", ret);
+               goto err;
+       }
+
+       ret = il_init_geos(il);
+       if (ret) {
+               IL_ERR("initializing geos failed: %d\n", ret);
+               goto err_free_channel_map;
+       }
+       il4965_init_hw_rates(il, il->ieee_rates);
+
+       return 0;
+
+err_free_channel_map:
+       il_free_channel_map(il);
+err:
+       return ret;
+}
+
+static void
+il4965_uninit_drv(struct il_priv *il)
+{
+       il4965_calib_free_results(il);
+       il_free_geos(il);
+       il_free_channel_map(il);
+       kfree(il->scan_cmd);
+}
+
+static void
+il4965_hw_detect(struct il_priv *il)
+{
+       il->hw_rev = _il_rd(il, CSR_HW_REV);
+       il->hw_wa_rev = _il_rd(il, CSR_HW_REV_WA_REG);
+       il->rev_id = il->pci_dev->revision;
+       D_INFO("HW Revision ID = 0x%X\n", il->rev_id);
+}
+
+static int
+il4965_set_hw_params(struct il_priv *il)
+{
+       il->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+       il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+       if (il->cfg->mod_params->amsdu_size_8K)
+               il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_8K);
+       else
+               il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_4K);
+
+       il->hw_params.max_beacon_itrvl = IL_MAX_UCODE_BEACON_INTERVAL;
+
+       if (il->cfg->mod_params->disable_11n)
+               il->cfg->sku &= ~IL_SKU_N;
+
+       /* Device-specific setup */
+       return il->cfg->ops->lib->set_hw_params(il);
+}
+
+static const u8 il4965_bss_ac_to_fifo[] = {
+       IL_TX_FIFO_VO,
+       IL_TX_FIFO_VI,
+       IL_TX_FIFO_BE,
+       IL_TX_FIFO_BK,
+};
+
+static const u8 il4965_bss_ac_to_queue[] = {
+       0, 1, 2, 3,
+};
+
+static int
+il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       int err = 0;
+       struct il_priv *il;
+       struct ieee80211_hw *hw;
+       struct il_cfg *cfg = (struct il_cfg *)(ent->driver_data);
+       unsigned long flags;
+       u16 pci_cmd;
+
+       /************************
+        * 1. Allocating HW data
+        ************************/
+
+       hw = il_alloc_all(cfg);
+       if (!hw) {
+               err = -ENOMEM;
+               goto out;
+       }
+       il = hw->priv;
+       /* At this point both hw and il are allocated. */
+
+       il->ctx.ctxid = 0;
+
+       il->ctx.always_active = true;
+       il->ctx.is_active = true;
+       il->ctx.rxon_cmd = C_RXON;
+       il->ctx.rxon_timing_cmd = C_RXON_TIMING;
+       il->ctx.rxon_assoc_cmd = C_RXON_ASSOC;
+       il->ctx.qos_cmd = C_QOS_PARAM;
+       il->ctx.ap_sta_id = IL_AP_ID;
+       il->ctx.wep_key_cmd = C_WEPKEY;
+       il->ctx.ac_to_fifo = il4965_bss_ac_to_fifo;
+       il->ctx.ac_to_queue = il4965_bss_ac_to_queue;
+       il->ctx.exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC);
+       il->ctx.interface_modes = BIT(NL80211_IFTYPE_STATION);
+       il->ctx.ap_devtype = RXON_DEV_TYPE_AP;
+       il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS;
+       il->ctx.station_devtype = RXON_DEV_TYPE_ESS;
+       il->ctx.unused_devtype = RXON_DEV_TYPE_ESS;
+
+       SET_IEEE80211_DEV(hw, &pdev->dev);
+
+       D_INFO("*** LOAD DRIVER ***\n");
+       il->cfg = cfg;
+       il->pci_dev = pdev;
+       il->inta_mask = CSR_INI_SET_MASK;
+
+       if (il_alloc_traffic_mem(il))
+               IL_ERR("Not enough memory to generate traffic log\n");
+
+       /**************************
+        * 2. Initializing PCI bus
+        **************************/
+       pci_disable_link_state(pdev,
+                              PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                              PCIE_LINK_STATE_CLKPM);
+
+       if (pci_enable_device(pdev)) {
+               err = -ENODEV;
+               goto out_ieee80211_free_hw;
+       }
+
+       pci_set_master(pdev);
+
+       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
+       if (!err)
+               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
+       if (err) {
+               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               if (!err)
+                       err =
+                           pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+               /* both attempts failed: */
+               if (err) {
+                       IL_WARN("No suitable DMA available.\n");
+                       goto out_pci_disable_device;
+               }
+       }
+
+       err = pci_request_regions(pdev, DRV_NAME);
+       if (err)
+               goto out_pci_disable_device;
+
+       pci_set_drvdata(pdev, il);
+
+       /***********************
+        * 3. Read REV register
+        ***********************/
+       il->hw_base = pci_iomap(pdev, 0, 0);
+       if (!il->hw_base) {
+               err = -ENODEV;
+               goto out_pci_release_regions;
+       }
+
+       D_INFO("pci_resource_len = 0x%08llx\n",
+              (unsigned long long)pci_resource_len(pdev, 0));
+       D_INFO("pci_resource_base = %p\n", il->hw_base);
+
+       /* these spin locks will be used in apm_ops.init and EEPROM access
+        * we should init now
+        */
+       spin_lock_init(&il->reg_lock);
+       spin_lock_init(&il->lock);
+
+       /*
+        * stop and reset the on-board processor just in case it is in a
+        * strange state ... like being left stranded by a primary kernel
+        * and this is now the kdump kernel trying to start up
+        */
+       _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+       il4965_hw_detect(il);
+       IL_INFO("Detected %s, REV=0x%X\n", il->cfg->name, il->hw_rev);
+
+       /* We disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state */
+       pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+       il4965_prepare_card_hw(il);
+       if (!il->hw_ready) {
+               IL_WARN("Failed, HW not ready\n");
+               goto out_iounmap;
+       }
+
+       /*****************
+        * 4. Read EEPROM
+        *****************/
+       /* Read the EEPROM */
+       err = il_eeprom_init(il);
+       if (err) {
+               IL_ERR("Unable to init EEPROM\n");
+               goto out_iounmap;
+       }
+       err = il4965_eeprom_check_version(il);
+       if (err)
+               goto out_free_eeprom;
+
+       if (err)
+               goto out_free_eeprom;
+
+       /* extract MAC Address */
+       il4965_eeprom_get_mac(il, il->addresses[0].addr);
+       D_INFO("MAC address: %pM\n", il->addresses[0].addr);
+       il->hw->wiphy->addresses = il->addresses;
+       il->hw->wiphy->n_addresses = 1;
+
+       /************************
+        * 5. Setup HW constants
+        ************************/
+       if (il4965_set_hw_params(il)) {
+               IL_ERR("failed to set hw parameters\n");
+               goto out_free_eeprom;
+       }
+
+       /*******************
+        * 6. Setup il
+        *******************/
+
+       err = il4965_init_drv(il);
+       if (err)
+               goto out_free_eeprom;
+       /* At this point both hw and il are initialized. */
+
+       /********************
+        * 7. Setup services
+        ********************/
+       spin_lock_irqsave(&il->lock, flags);
+       il_disable_interrupts(il);
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       pci_enable_msi(il->pci_dev);
+
+       err = request_irq(il->pci_dev->irq, il_isr, IRQF_SHARED, DRV_NAME, il);
+       if (err) {
+               IL_ERR("Error allocating IRQ %d\n", il->pci_dev->irq);
+               goto out_disable_msi;
+       }
+
+       il4965_setup_deferred_work(il);
+       il4965_setup_handlers(il);
+
+       /*********************************************
+        * 8. Enable interrupts and read RFKILL state
+        *********************************************/
+
+       /* enable rfkill interrupt: hw bug w/a */
+       pci_read_config_word(il->pci_dev, PCI_COMMAND, &pci_cmd);
+       if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+               pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+               pci_write_config_word(il->pci_dev, PCI_COMMAND, pci_cmd);
+       }
+
+       il_enable_rfkill_int(il);
+
+       /* If platform's RF_KILL switch is NOT set to KILL */
+       if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+               clear_bit(S_RF_KILL_HW, &il->status);
+       else
+               set_bit(S_RF_KILL_HW, &il->status);
+
+       wiphy_rfkill_set_hw_state(il->hw->wiphy,
+                                 test_bit(S_RF_KILL_HW, &il->status));
+
+       il_power_initialize(il);
+
+       init_completion(&il->_4965.firmware_loading_complete);
+
+       err = il4965_request_firmware(il, true);
+       if (err)
+               goto out_destroy_workqueue;
+
+       return 0;
+
+out_destroy_workqueue:
+       destroy_workqueue(il->workqueue);
+       il->workqueue = NULL;
+       free_irq(il->pci_dev->irq, il);
+out_disable_msi:
+       pci_disable_msi(il->pci_dev);
+       il4965_uninit_drv(il);
+out_free_eeprom:
+       il_eeprom_free(il);
+out_iounmap:
+       pci_iounmap(pdev, il->hw_base);
+out_pci_release_regions:
+       pci_set_drvdata(pdev, NULL);
+       pci_release_regions(pdev);
+out_pci_disable_device:
+       pci_disable_device(pdev);
+out_ieee80211_free_hw:
+       il_free_traffic_mem(il);
+       ieee80211_free_hw(il->hw);
+out:
+       return err;
+}
+
+static void __devexit
+il4965_pci_remove(struct pci_dev *pdev)
+{
+       struct il_priv *il = pci_get_drvdata(pdev);
+       unsigned long flags;
+
+       if (!il)
+               return;
+
+       wait_for_completion(&il->_4965.firmware_loading_complete);
+
+       D_INFO("*** UNLOAD DRIVER ***\n");
+
+       il_dbgfs_unregister(il);
+       sysfs_remove_group(&pdev->dev.kobj, &il_attribute_group);
+
+       /* ieee80211_unregister_hw call wil cause il_mac_stop to
+        * to be called and il4965_down since we are removing the device
+        * we need to set S_EXIT_PENDING bit.
+        */
+       set_bit(S_EXIT_PENDING, &il->status);
+
+       il_leds_exit(il);
+
+       if (il->mac80211_registered) {
+               ieee80211_unregister_hw(il->hw);
+               il->mac80211_registered = 0;
+       } else {
+               il4965_down(il);
+       }
+
+       /*
+        * Make sure device is reset to low power before unloading driver.
+        * This may be redundant with il4965_down(), but there are paths to
+        * run il4965_down() without calling apm_ops.stop(), and there are
+        * paths to avoid running il4965_down() at all before leaving driver.
+        * This (inexpensive) call *makes sure* device is reset.
+        */
+       il_apm_stop(il);
+
+       /* make sure we flush any pending irq or
+        * tasklet for the driver
+        */
+       spin_lock_irqsave(&il->lock, flags);
+       il_disable_interrupts(il);
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       il4965_synchronize_irq(il);
+
+       il4965_dealloc_ucode_pci(il);
+
+       if (il->rxq.bd)
+               il4965_rx_queue_free(il, &il->rxq);
+       il4965_hw_txq_ctx_free(il);
+
+       il_eeprom_free(il);
+
+       /*netif_stop_queue(dev); */
+       flush_workqueue(il->workqueue);
+
+       /* ieee80211_unregister_hw calls il_mac_stop, which flushes
+        * il->workqueue... so we can't take down the workqueue
+        * until now... */
+       destroy_workqueue(il->workqueue);
+       il->workqueue = NULL;
+       il_free_traffic_mem(il);
+
+       free_irq(il->pci_dev->irq, il);
+       pci_disable_msi(il->pci_dev);
+       pci_iounmap(pdev, il->hw_base);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+
+       il4965_uninit_drv(il);
+
+       dev_kfree_skb(il->beacon_skb);
+
+       ieee80211_free_hw(il->hw);
+}
+
+/*
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
+ * must be called under il->lock and mac access
+ */
+void
+il4965_txq_set_sched(struct il_priv *il, u32 mask)
+{
+       il_wr_prph(il, IL49_SCD_TXFACT, mask);
+}
+
+/*****************************************************************************
+ *
+ * driver and module entry point
+ *
+ *****************************************************************************/
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+static DEFINE_PCI_DEVICE_TABLE(il4965_hw_card_ids) = {
+       {IL_PCI_DEVICE(0x4229, PCI_ANY_ID, il4965_cfg)},
+       {IL_PCI_DEVICE(0x4230, PCI_ANY_ID, il4965_cfg)},
+       {0}
+};
+MODULE_DEVICE_TABLE(pci, il4965_hw_card_ids);
+
+static struct pci_driver il4965_driver = {
+       .name = DRV_NAME,
+       .id_table = il4965_hw_card_ids,
+       .probe = il4965_pci_probe,
+       .remove = __devexit_p(il4965_pci_remove),
+       .driver.pm = IL_LEGACY_PM_OPS,
+};
+
+static int __init
+il4965_init(void)
+{
+
+       int ret;
+       pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+       pr_info(DRV_COPYRIGHT "\n");
+
+       ret = il4965_rate_control_register();
+       if (ret) {
+               pr_err("Unable to register rate control algorithm: %d\n", ret);
+               return ret;
+       }
+
+       ret = pci_register_driver(&il4965_driver);
+       if (ret) {
+               pr_err("Unable to initialize PCI module\n");
+               goto error_register;
+       }
+
+       return ret;
+
+error_register:
+       il4965_rate_control_unregister();
+       return ret;
+}
+
+static void __exit
+il4965_exit(void)
+{
+       pci_unregister_driver(&il4965_driver);
+       il4965_rate_control_unregister();
+}
+
+module_exit(il4965_exit);
+module_init(il4965_init);
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+module_param_named(debug, il_debug_level, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "debug output mask");
+#endif
+
+module_param_named(swcrypto, il4965_mod_params.sw_crypto, int, S_IRUGO);
+MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
+module_param_named(queues_num, il4965_mod_params.num_of_queues, int, S_IRUGO);
+MODULE_PARM_DESC(queues_num, "number of hw queues.");
+module_param_named(11n_disable, il4965_mod_params.disable_11n, int, S_IRUGO);
+MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
+module_param_named(amsdu_size_8K, il4965_mod_params.amsdu_size_8K, int,
+                  S_IRUGO);
+MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
+module_param_named(fw_restart, il4965_mod_params.restart_fw, int, S_IRUGO);
+MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
new file mode 100644 (file)
index 0000000..467d0cb
--- /dev/null
@@ -0,0 +1,2860 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2005 - 2011 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:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+
+#include <linux/workqueue.h>
+
+#include "common.h"
+#include "4965.h"
+
+#define IL4965_RS_NAME "iwl-4965-rs"
+
+#define NUM_TRY_BEFORE_ANT_TOGGLE 1
+#define IL_NUMBER_TRY      1
+#define IL_HT_NUMBER_TRY   3
+
+#define RATE_MAX_WINDOW                62      /* # tx in history win */
+#define RATE_MIN_FAILURE_TH            6       /* min failures to calc tpt */
+#define RATE_MIN_SUCCESS_TH            8       /* min successes to calc tpt */
+
+/* max allowed rate miss before sync LQ cmd */
+#define IL_MISSED_RATE_MAX             15
+/* max time to accum history 2 seconds */
+#define RATE_SCALE_FLUSH_INTVL   (3*HZ)
+
+static u8 rs_ht_to_legacy[] = {
+       RATE_6M_IDX, RATE_6M_IDX,
+       RATE_6M_IDX, RATE_6M_IDX,
+       RATE_6M_IDX,
+       RATE_6M_IDX, RATE_9M_IDX,
+       RATE_12M_IDX, RATE_18M_IDX,
+       RATE_24M_IDX, RATE_36M_IDX,
+       RATE_48M_IDX, RATE_54M_IDX
+};
+
+static const u8 ant_toggle_lookup[] = {
+       /*ANT_NONE -> */ ANT_NONE,
+       /*ANT_A    -> */ ANT_B,
+       /*ANT_B    -> */ ANT_C,
+       /*ANT_AB   -> */ ANT_BC,
+       /*ANT_C    -> */ ANT_A,
+       /*ANT_AC   -> */ ANT_AB,
+       /*ANT_BC   -> */ ANT_AC,
+       /*ANT_ABC  -> */ ANT_ABC,
+};
+
+#define IL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np)    \
+       [RATE_##r##M_IDX] = { RATE_##r##M_PLCP,      \
+                                   RATE_SISO_##s##M_PLCP, \
+                                   RATE_MIMO2_##s##M_PLCP,\
+                                   RATE_##r##M_IEEE,      \
+                                   RATE_##ip##M_IDX,    \
+                                   RATE_##in##M_IDX,    \
+                                   RATE_##rp##M_IDX,    \
+                                   RATE_##rn##M_IDX,    \
+                                   RATE_##pp##M_IDX,    \
+                                   RATE_##np##M_IDX }
+
+/*
+ * Parameter order:
+ *   rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
+ *
+ * If there isn't a valid next or previous rate then INV is used which
+ * maps to RATE_INVALID
+ *
+ */
+const struct il_rate_info il_rates[RATE_COUNT] = {
+       IL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2),   /*  1mbps */
+       IL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5),         /*  2mbps */
+       IL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11),       /*5.5mbps */
+       IL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18),     /* 11mbps */
+       IL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11),         /*  6mbps */
+       IL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11),        /*  9mbps */
+       IL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18),   /* 12mbps */
+       IL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24),   /* 18mbps */
+       IL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36),   /* 24mbps */
+       IL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48),   /* 36mbps */
+       IL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54),   /* 48mbps */
+       IL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */
+       IL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
+};
+
+static int
+il4965_hwrate_to_plcp_idx(u32 rate_n_flags)
+{
+       int idx = 0;
+
+       /* HT rate format */
+       if (rate_n_flags & RATE_MCS_HT_MSK) {
+               idx = (rate_n_flags & 0xff);
+
+               if (idx >= RATE_MIMO2_6M_PLCP)
+                       idx = idx - RATE_MIMO2_6M_PLCP;
+
+               idx += IL_FIRST_OFDM_RATE;
+               /* skip 9M not supported in ht */
+               if (idx >= RATE_9M_IDX)
+                       idx += 1;
+               if (idx >= IL_FIRST_OFDM_RATE && idx <= IL_LAST_OFDM_RATE)
+                       return idx;
+
+               /* legacy rate format, search for match in table */
+       } else {
+               for (idx = 0; idx < ARRAY_SIZE(il_rates); idx++)
+                       if (il_rates[idx].plcp == (rate_n_flags & 0xFF))
+                               return idx;
+       }
+
+       return -1;
+}
+
+static void il4965_rs_rate_scale_perform(struct il_priv *il,
+                                        struct sk_buff *skb,
+                                        struct ieee80211_sta *sta,
+                                        struct il_lq_sta *lq_sta);
+static void il4965_rs_fill_link_cmd(struct il_priv *il,
+                                   struct il_lq_sta *lq_sta, u32 rate_n_flags);
+static void il4965_rs_stay_in_table(struct il_lq_sta *lq_sta,
+                                   bool force_search);
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static void il4965_rs_dbgfs_set_mcs(struct il_lq_sta *lq_sta,
+                                   u32 *rate_n_flags, int idx);
+#else
+static void
+il4965_rs_dbgfs_set_mcs(struct il_lq_sta *lq_sta, u32 * rate_n_flags, int idx)
+{
+}
+#endif
+
+/**
+ * The following tables contain the expected throughput metrics for all rates
+ *
+ *     1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
+ *
+ * where invalid entries are zeros.
+ *
+ * CCK rates are only valid in legacy table and will only be used in G
+ * (2.4 GHz) band.
+ */
+
+static s32 expected_tpt_legacy[RATE_COUNT] = {
+       7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0
+};
+
+static s32 expected_tpt_siso20MHz[4][RATE_COUNT] = {
+       {0, 0, 0, 0, 42, 0, 76, 102, 124, 158, 183, 193, 202},  /* Norm */
+       {0, 0, 0, 0, 46, 0, 82, 110, 132, 167, 192, 202, 210},  /* SGI */
+       {0, 0, 0, 0, 48, 0, 93, 135, 176, 251, 319, 351, 381},  /* AGG */
+       {0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */
+};
+
+static s32 expected_tpt_siso40MHz[4][RATE_COUNT] = {
+       {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */
+       {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */
+       {0, 0, 0, 0, 96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */
+       {0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683},        /* AGG+SGI */
+};
+
+static s32 expected_tpt_mimo2_20MHz[4][RATE_COUNT] = {
+       {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */
+       {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */
+       {0, 0, 0, 0, 92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */
+       {0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660},        /* AGG+SGI */
+};
+
+static s32 expected_tpt_mimo2_40MHz[4][RATE_COUNT] = {
+       {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289},        /* Norm */
+       {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293},        /* SGI */
+       {0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922},        /* AGG */
+       {0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966},        /* AGG+SGI */
+};
+
+/* mbps, mcs */
+static const struct il_rate_mcs_info il_rate_mcs[RATE_COUNT] = {
+       {"1", "BPSK DSSS"},
+       {"2", "QPSK DSSS"},
+       {"5.5", "BPSK CCK"},
+       {"11", "QPSK CCK"},
+       {"6", "BPSK 1/2"},
+       {"9", "BPSK 1/2"},
+       {"12", "QPSK 1/2"},
+       {"18", "QPSK 3/4"},
+       {"24", "16QAM 1/2"},
+       {"36", "16QAM 3/4"},
+       {"48", "64QAM 2/3"},
+       {"54", "64QAM 3/4"},
+       {"60", "64QAM 5/6"},
+};
+
+#define MCS_IDX_PER_STREAM     (8)
+
+static inline u8
+il4965_rs_extract_rate(u32 rate_n_flags)
+{
+       return (u8) (rate_n_flags & 0xFF);
+}
+
+static void
+il4965_rs_rate_scale_clear_win(struct il_rate_scale_data *win)
+{
+       win->data = 0;
+       win->success_counter = 0;
+       win->success_ratio = IL_INVALID_VALUE;
+       win->counter = 0;
+       win->average_tpt = IL_INVALID_VALUE;
+       win->stamp = 0;
+}
+
+static inline u8
+il4965_rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
+{
+       return (ant_type & valid_antenna) == ant_type;
+}
+
+/*
+ *     removes the old data from the stats. All data that is older than
+ *     TID_MAX_TIME_DIFF, will be deleted.
+ */
+static void
+il4965_rs_tl_rm_old_stats(struct il_traffic_load *tl, u32 curr_time)
+{
+       /* The oldest age we want to keep */
+       u32 oldest_time = curr_time - TID_MAX_TIME_DIFF;
+
+       while (tl->queue_count && tl->time_stamp < oldest_time) {
+               tl->total -= tl->packet_count[tl->head];
+               tl->packet_count[tl->head] = 0;
+               tl->time_stamp += TID_QUEUE_CELL_SPACING;
+               tl->queue_count--;
+               tl->head++;
+               if (tl->head >= TID_QUEUE_MAX_SIZE)
+                       tl->head = 0;
+       }
+}
+
+/*
+ *     increment traffic load value for tid and also remove
+ *     any old values if passed the certain time period
+ */
+static u8
+il4965_rs_tl_add_packet(struct il_lq_sta *lq_data, struct ieee80211_hdr *hdr)
+{
+       u32 curr_time = jiffies_to_msecs(jiffies);
+       u32 time_diff;
+       s32 idx;
+       struct il_traffic_load *tl = NULL;
+       u8 tid;
+
+       if (ieee80211_is_data_qos(hdr->frame_control)) {
+               u8 *qc = ieee80211_get_qos_ctl(hdr);
+               tid = qc[0] & 0xf;
+       } else
+               return MAX_TID_COUNT;
+
+       if (unlikely(tid >= TID_MAX_LOAD_COUNT))
+               return MAX_TID_COUNT;
+
+       tl = &lq_data->load[tid];
+
+       curr_time -= curr_time % TID_ROUND_VALUE;
+
+       /* Happens only for the first packet. Initialize the data */
+       if (!(tl->queue_count)) {
+               tl->total = 1;
+               tl->time_stamp = curr_time;
+               tl->queue_count = 1;
+               tl->head = 0;
+               tl->packet_count[0] = 1;
+               return MAX_TID_COUNT;
+       }
+
+       time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
+       idx = time_diff / TID_QUEUE_CELL_SPACING;
+
+       /* The history is too long: remove data that is older than */
+       /* TID_MAX_TIME_DIFF */
+       if (idx >= TID_QUEUE_MAX_SIZE)
+               il4965_rs_tl_rm_old_stats(tl, curr_time);
+
+       idx = (tl->head + idx) % TID_QUEUE_MAX_SIZE;
+       tl->packet_count[idx] = tl->packet_count[idx] + 1;
+       tl->total = tl->total + 1;
+
+       if ((idx + 1) > tl->queue_count)
+               tl->queue_count = idx + 1;
+
+       return tid;
+}
+
+/*
+       get the traffic load value for tid
+*/
+static u32
+il4965_rs_tl_get_load(struct il_lq_sta *lq_data, u8 tid)
+{
+       u32 curr_time = jiffies_to_msecs(jiffies);
+       u32 time_diff;
+       s32 idx;
+       struct il_traffic_load *tl = NULL;
+
+       if (tid >= TID_MAX_LOAD_COUNT)
+               return 0;
+
+       tl = &(lq_data->load[tid]);
+
+       curr_time -= curr_time % TID_ROUND_VALUE;
+
+       if (!(tl->queue_count))
+               return 0;
+
+       time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
+       idx = time_diff / TID_QUEUE_CELL_SPACING;
+
+       /* The history is too long: remove data that is older than */
+       /* TID_MAX_TIME_DIFF */
+       if (idx >= TID_QUEUE_MAX_SIZE)
+               il4965_rs_tl_rm_old_stats(tl, curr_time);
+
+       return tl->total;
+}
+
+static int
+il4965_rs_tl_turn_on_agg_for_tid(struct il_priv *il, struct il_lq_sta *lq_data,
+                                u8 tid, struct ieee80211_sta *sta)
+{
+       int ret = -EAGAIN;
+       u32 load;
+
+       load = il4965_rs_tl_get_load(lq_data, tid);
+
+       if (load > IL_AGG_LOAD_THRESHOLD) {
+               D_HT("Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid);
+               ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
+               if (ret == -EAGAIN) {
+                       /*
+                        * driver and mac80211 is out of sync
+                        * this might be cause by reloading firmware
+                        * stop the tx ba session here
+                        */
+                       IL_ERR("Fail start Tx agg on tid: %d\n", tid);
+                       ieee80211_stop_tx_ba_session(sta, tid);
+               }
+       } else
+               D_HT("Aggregation not enabled for tid %d because load = %u\n",
+                    tid, load);
+
+       return ret;
+}
+
+static void
+il4965_rs_tl_turn_on_agg(struct il_priv *il, u8 tid, struct il_lq_sta *lq_data,
+                        struct ieee80211_sta *sta)
+{
+       if (tid < TID_MAX_LOAD_COUNT)
+               il4965_rs_tl_turn_on_agg_for_tid(il, lq_data, tid, sta);
+       else
+               IL_ERR("tid exceeds max load count: %d/%d\n", tid,
+                      TID_MAX_LOAD_COUNT);
+}
+
+static inline int
+il4965_get_il4965_num_of_ant_from_rate(u32 rate_n_flags)
+{
+       return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) +
+           !!(rate_n_flags & RATE_MCS_ANT_B_MSK) +
+           !!(rate_n_flags & RATE_MCS_ANT_C_MSK);
+}
+
+/*
+ * Static function to get the expected throughput from an il_scale_tbl_info
+ * that wraps a NULL pointer check
+ */
+static s32
+il4965_get_expected_tpt(struct il_scale_tbl_info *tbl, int rs_idx)
+{
+       if (tbl->expected_tpt)
+               return tbl->expected_tpt[rs_idx];
+       return 0;
+}
+
+/**
+ * il4965_rs_collect_tx_data - Update the success/failure sliding win
+ *
+ * We keep a sliding win of the last 62 packets transmitted
+ * at this rate.  win->data contains the bitmask of successful
+ * packets.
+ */
+static int
+il4965_rs_collect_tx_data(struct il_scale_tbl_info *tbl, int scale_idx,
+                         int attempts, int successes)
+{
+       struct il_rate_scale_data *win = NULL;
+       static const u64 mask = (((u64) 1) << (RATE_MAX_WINDOW - 1));
+       s32 fail_count, tpt;
+
+       if (scale_idx < 0 || scale_idx >= RATE_COUNT)
+               return -EINVAL;
+
+       /* Select win for current tx bit rate */
+       win = &(tbl->win[scale_idx]);
+
+       /* Get expected throughput */
+       tpt = il4965_get_expected_tpt(tbl, scale_idx);
+
+       /*
+        * Keep track of only the latest 62 tx frame attempts in this rate's
+        * history win; anything older isn't really relevant any more.
+        * If we have filled up the sliding win, drop the oldest attempt;
+        * if the oldest attempt (highest bit in bitmap) shows "success",
+        * subtract "1" from the success counter (this is the main reason
+        * we keep these bitmaps!).
+        */
+       while (attempts > 0) {
+               if (win->counter >= RATE_MAX_WINDOW) {
+
+                       /* remove earliest */
+                       win->counter = RATE_MAX_WINDOW - 1;
+
+                       if (win->data & mask) {
+                               win->data &= ~mask;
+                               win->success_counter--;
+                       }
+               }
+
+               /* Increment frames-attempted counter */
+               win->counter++;
+
+               /* Shift bitmap by one frame to throw away oldest history */
+               win->data <<= 1;
+
+               /* Mark the most recent #successes attempts as successful */
+               if (successes > 0) {
+                       win->success_counter++;
+                       win->data |= 0x1;
+                       successes--;
+               }
+
+               attempts--;
+       }
+
+       /* Calculate current success ratio, avoid divide-by-0! */
+       if (win->counter > 0)
+               win->success_ratio =
+                   128 * (100 * win->success_counter) / win->counter;
+       else
+               win->success_ratio = IL_INVALID_VALUE;
+
+       fail_count = win->counter - win->success_counter;
+
+       /* Calculate average throughput, if we have enough history. */
+       if (fail_count >= RATE_MIN_FAILURE_TH ||
+           win->success_counter >= RATE_MIN_SUCCESS_TH)
+               win->average_tpt = (win->success_ratio * tpt + 64) / 128;
+       else
+               win->average_tpt = IL_INVALID_VALUE;
+
+       /* Tag this win as having been updated */
+       win->stamp = jiffies;
+
+       return 0;
+}
+
+/*
+ * Fill uCode API rate_n_flags field, based on "search" or "active" table.
+ */
+static u32
+il4965_rate_n_flags_from_tbl(struct il_priv *il, struct il_scale_tbl_info *tbl,
+                            int idx, u8 use_green)
+{
+       u32 rate_n_flags = 0;
+
+       if (is_legacy(tbl->lq_type)) {
+               rate_n_flags = il_rates[idx].plcp;
+               if (idx >= IL_FIRST_CCK_RATE && idx <= IL_LAST_CCK_RATE)
+                       rate_n_flags |= RATE_MCS_CCK_MSK;
+
+       } else if (is_Ht(tbl->lq_type)) {
+               if (idx > IL_LAST_OFDM_RATE) {
+                       IL_ERR("Invalid HT rate idx %d\n", idx);
+                       idx = IL_LAST_OFDM_RATE;
+               }
+               rate_n_flags = RATE_MCS_HT_MSK;
+
+               if (is_siso(tbl->lq_type))
+                       rate_n_flags |= il_rates[idx].plcp_siso;
+               else
+                       rate_n_flags |= il_rates[idx].plcp_mimo2;
+       } else {
+               IL_ERR("Invalid tbl->lq_type %d\n", tbl->lq_type);
+       }
+
+       rate_n_flags |=
+           ((tbl->ant_type << RATE_MCS_ANT_POS) & RATE_MCS_ANT_ABC_MSK);
+
+       if (is_Ht(tbl->lq_type)) {
+               if (tbl->is_ht40) {
+                       if (tbl->is_dup)
+                               rate_n_flags |= RATE_MCS_DUP_MSK;
+                       else
+                               rate_n_flags |= RATE_MCS_HT40_MSK;
+               }
+               if (tbl->is_SGI)
+                       rate_n_flags |= RATE_MCS_SGI_MSK;
+
+               if (use_green) {
+                       rate_n_flags |= RATE_MCS_GF_MSK;
+                       if (is_siso(tbl->lq_type) && tbl->is_SGI) {
+                               rate_n_flags &= ~RATE_MCS_SGI_MSK;
+                               IL_ERR("GF was set with SGI:SISO\n");
+                       }
+               }
+       }
+       return rate_n_flags;
+}
+
+/*
+ * Interpret uCode API's rate_n_flags format,
+ * fill "search" or "active" tx mode table.
+ */
+static int
+il4965_rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
+                               enum ieee80211_band band,
+                               struct il_scale_tbl_info *tbl, int *rate_idx)
+{
+       u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK);
+       u8 il4965_num_of_ant =
+           il4965_get_il4965_num_of_ant_from_rate(rate_n_flags);
+       u8 mcs;
+
+       memset(tbl, 0, sizeof(struct il_scale_tbl_info));
+       *rate_idx = il4965_hwrate_to_plcp_idx(rate_n_flags);
+
+       if (*rate_idx == RATE_INVALID) {
+               *rate_idx = -1;
+               return -EINVAL;
+       }
+       tbl->is_SGI = 0;        /* default legacy setup */
+       tbl->is_ht40 = 0;
+       tbl->is_dup = 0;
+       tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS);
+       tbl->lq_type = LQ_NONE;
+       tbl->max_search = IL_MAX_SEARCH;
+
+       /* legacy rate format */
+       if (!(rate_n_flags & RATE_MCS_HT_MSK)) {
+               if (il4965_num_of_ant == 1) {
+                       if (band == IEEE80211_BAND_5GHZ)
+                               tbl->lq_type = LQ_A;
+                       else
+                               tbl->lq_type = LQ_G;
+               }
+               /* HT rate format */
+       } else {
+               if (rate_n_flags & RATE_MCS_SGI_MSK)
+                       tbl->is_SGI = 1;
+
+               if ((rate_n_flags & RATE_MCS_HT40_MSK) ||
+                   (rate_n_flags & RATE_MCS_DUP_MSK))
+                       tbl->is_ht40 = 1;
+
+               if (rate_n_flags & RATE_MCS_DUP_MSK)
+                       tbl->is_dup = 1;
+
+               mcs = il4965_rs_extract_rate(rate_n_flags);
+
+               /* SISO */
+               if (mcs <= RATE_SISO_60M_PLCP) {
+                       if (il4965_num_of_ant == 1)
+                               tbl->lq_type = LQ_SISO; /*else NONE */
+                       /* MIMO2 */
+               } else {
+                       if (il4965_num_of_ant == 2)
+                               tbl->lq_type = LQ_MIMO2;
+               }
+       }
+       return 0;
+}
+
+/* switch to another antenna/antennas and return 1 */
+/* if no other valid antenna found, return 0 */
+static int
+il4965_rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
+                        struct il_scale_tbl_info *tbl)
+{
+       u8 new_ant_type;
+
+       if (!tbl->ant_type || tbl->ant_type > ANT_ABC)
+               return 0;
+
+       if (!il4965_rs_is_valid_ant(valid_ant, tbl->ant_type))
+               return 0;
+
+       new_ant_type = ant_toggle_lookup[tbl->ant_type];
+
+       while (new_ant_type != tbl->ant_type &&
+              !il4965_rs_is_valid_ant(valid_ant, new_ant_type))
+               new_ant_type = ant_toggle_lookup[new_ant_type];
+
+       if (new_ant_type == tbl->ant_type)
+               return 0;
+
+       tbl->ant_type = new_ant_type;
+       *rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK;
+       *rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS;
+       return 1;
+}
+
+/**
+ * Green-field mode is valid if the station supports it and
+ * there are no non-GF stations present in the BSS.
+ */
+static bool
+il4965_rs_use_green(struct ieee80211_sta *sta)
+{
+       struct il_station_priv *sta_priv = (void *)sta->drv_priv;
+       struct il_rxon_context *ctx = sta_priv->common.ctx;
+
+       return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
+           !(ctx->ht.non_gf_sta_present);
+}
+
+/**
+ * il4965_rs_get_supported_rates - get the available rates
+ *
+ * if management frame or broadcast frame only return
+ * basic available rates.
+ *
+ */
+static u16
+il4965_rs_get_supported_rates(struct il_lq_sta *lq_sta,
+                             struct ieee80211_hdr *hdr,
+                             enum il_table_type rate_type)
+{
+       if (is_legacy(rate_type)) {
+               return lq_sta->active_legacy_rate;
+       } else {
+               if (is_siso(rate_type))
+                       return lq_sta->active_siso_rate;
+               else
+                       return lq_sta->active_mimo2_rate;
+       }
+}
+
+static u16
+il4965_rs_get_adjacent_rate(struct il_priv *il, u8 idx, u16 rate_mask,
+                           int rate_type)
+{
+       u8 high = RATE_INVALID;
+       u8 low = RATE_INVALID;
+
+       /* 802.11A or ht walks to the next literal adjacent rate in
+        * the rate table */
+       if (is_a_band(rate_type) || !is_legacy(rate_type)) {
+               int i;
+               u32 mask;
+
+               /* Find the previous rate that is in the rate mask */
+               i = idx - 1;
+               for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
+                       if (rate_mask & mask) {
+                               low = i;
+                               break;
+                       }
+               }
+
+               /* Find the next rate that is in the rate mask */
+               i = idx + 1;
+               for (mask = (1 << i); i < RATE_COUNT; i++, mask <<= 1) {
+                       if (rate_mask & mask) {
+                               high = i;
+                               break;
+                       }
+               }
+
+               return (high << 8) | low;
+       }
+
+       low = idx;
+       while (low != RATE_INVALID) {
+               low = il_rates[low].prev_rs;
+               if (low == RATE_INVALID)
+                       break;
+               if (rate_mask & (1 << low))
+                       break;
+               D_RATE("Skipping masked lower rate: %d\n", low);
+       }
+
+       high = idx;
+       while (high != RATE_INVALID) {
+               high = il_rates[high].next_rs;
+               if (high == RATE_INVALID)
+                       break;
+               if (rate_mask & (1 << high))
+                       break;
+               D_RATE("Skipping masked higher rate: %d\n", high);
+       }
+
+       return (high << 8) | low;
+}
+
+static u32
+il4965_rs_get_lower_rate(struct il_lq_sta *lq_sta,
+                        struct il_scale_tbl_info *tbl, u8 scale_idx,
+                        u8 ht_possible)
+{
+       s32 low;
+       u16 rate_mask;
+       u16 high_low;
+       u8 switch_to_legacy = 0;
+       u8 is_green = lq_sta->is_green;
+       struct il_priv *il = lq_sta->drv;
+
+       /* check if we need to switch from HT to legacy rates.
+        * assumption is that mandatory rates (1Mbps or 6Mbps)
+        * are always supported (spec demand) */
+       if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_idx)) {
+               switch_to_legacy = 1;
+               scale_idx = rs_ht_to_legacy[scale_idx];
+               if (lq_sta->band == IEEE80211_BAND_5GHZ)
+                       tbl->lq_type = LQ_A;
+               else
+                       tbl->lq_type = LQ_G;
+
+               if (il4965_num_of_ant(tbl->ant_type) > 1)
+                       tbl->ant_type =
+                           il4965_first_antenna(il->hw_params.valid_tx_ant);
+
+               tbl->is_ht40 = 0;
+               tbl->is_SGI = 0;
+               tbl->max_search = IL_MAX_SEARCH;
+       }
+
+       rate_mask = il4965_rs_get_supported_rates(lq_sta, NULL, tbl->lq_type);
+
+       /* Mask with station rate restriction */
+       if (is_legacy(tbl->lq_type)) {
+               /* supp_rates has no CCK bits in A mode */
+               if (lq_sta->band == IEEE80211_BAND_5GHZ)
+                       rate_mask =
+                           (u16) (rate_mask &
+                                  (lq_sta->supp_rates << IL_FIRST_OFDM_RATE));
+               else
+                       rate_mask = (u16) (rate_mask & lq_sta->supp_rates);
+       }
+
+       /* If we switched from HT to legacy, check current rate */
+       if (switch_to_legacy && (rate_mask & (1 << scale_idx))) {
+               low = scale_idx;
+               goto out;
+       }
+
+       high_low =
+           il4965_rs_get_adjacent_rate(lq_sta->drv, scale_idx, rate_mask,
+                                       tbl->lq_type);
+       low = high_low & 0xff;
+
+       if (low == RATE_INVALID)
+               low = scale_idx;
+
+out:
+       return il4965_rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green);
+}
+
+/*
+ * Simple function to compare two rate scale table types
+ */
+static bool
+il4965_table_type_matches(struct il_scale_tbl_info *a,
+                         struct il_scale_tbl_info *b)
+{
+       return (a->lq_type == b->lq_type && a->ant_type == b->ant_type &&
+               a->is_SGI == b->is_SGI);
+}
+
+/*
+ * mac80211 sends us Tx status
+ */
+static void
+il4965_rs_tx_status(void *il_r, struct ieee80211_supported_band *sband,
+                   struct ieee80211_sta *sta, void *il_sta,
+                   struct sk_buff *skb)
+{
+       int legacy_success;
+       int retries;
+       int rs_idx, mac_idx, i;
+       struct il_lq_sta *lq_sta = il_sta;
+       struct il_link_quality_cmd *table;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct il_priv *il = (struct il_priv *)il_r;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       enum mac80211_rate_control_flags mac_flags;
+       u32 tx_rate;
+       struct il_scale_tbl_info tbl_type;
+       struct il_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
+       struct il_station_priv *sta_priv = (void *)sta->drv_priv;
+       struct il_rxon_context *ctx = sta_priv->common.ctx;
+
+       D_RATE("get frame ack response, update rate scale win\n");
+
+       /* Treat uninitialized rate scaling data same as non-existing. */
+       if (!lq_sta) {
+               D_RATE("Station rate scaling not created yet.\n");
+               return;
+       } else if (!lq_sta->drv) {
+               D_RATE("Rate scaling not initialized yet.\n");
+               return;
+       }
+
+       if (!ieee80211_is_data(hdr->frame_control) ||
+           (info->flags & IEEE80211_TX_CTL_NO_ACK))
+               return;
+
+       /* This packet was aggregated but doesn't carry status info */
+       if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
+           !(info->flags & IEEE80211_TX_STAT_AMPDU))
+               return;
+
+       /*
+        * Ignore this Tx frame response if its initial rate doesn't match
+        * that of latest Link Quality command.  There may be stragglers
+        * from a previous Link Quality command, but we're no longer interested
+        * in those; they're either from the "active" mode while we're trying
+        * to check "search" mode, or a prior "search" mode after we've moved
+        * to a new "search" mode (which might become the new "active" mode).
+        */
+       table = &lq_sta->lq;
+       tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
+       il4965_rs_get_tbl_info_from_mcs(tx_rate, il->band, &tbl_type, &rs_idx);
+       if (il->band == IEEE80211_BAND_5GHZ)
+               rs_idx -= IL_FIRST_OFDM_RATE;
+       mac_flags = info->status.rates[0].flags;
+       mac_idx = info->status.rates[0].idx;
+       /* For HT packets, map MCS to PLCP */
+       if (mac_flags & IEEE80211_TX_RC_MCS) {
+               mac_idx &= RATE_MCS_CODE_MSK;   /* Remove # of streams */
+               if (mac_idx >= (RATE_9M_IDX - IL_FIRST_OFDM_RATE))
+                       mac_idx++;
+               /*
+                * mac80211 HT idx is always zero-idxed; we need to move
+                * HT OFDM rates after CCK rates in 2.4 GHz band
+                */
+               if (il->band == IEEE80211_BAND_2GHZ)
+                       mac_idx += IL_FIRST_OFDM_RATE;
+       }
+       /* Here we actually compare this rate to the latest LQ command */
+       if (mac_idx < 0 ||
+           tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI) ||
+           tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ||
+           tbl_type.is_dup != !!(mac_flags & IEEE80211_TX_RC_DUP_DATA) ||
+           tbl_type.ant_type != info->antenna_sel_tx ||
+           !!(tx_rate & RATE_MCS_HT_MSK) != !!(mac_flags & IEEE80211_TX_RC_MCS)
+           || !!(tx_rate & RATE_MCS_GF_MSK) !=
+           !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD) || rs_idx != mac_idx) {
+               D_RATE("initial rate %d does not match %d (0x%x)\n", mac_idx,
+                      rs_idx, tx_rate);
+               /*
+                * Since rates mis-match, the last LQ command may have failed.
+                * After IL_MISSED_RATE_MAX mis-matches, resync the uCode with
+                * ... driver.
+                */
+               lq_sta->missed_rate_counter++;
+               if (lq_sta->missed_rate_counter > IL_MISSED_RATE_MAX) {
+                       lq_sta->missed_rate_counter = 0;
+                       il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_ASYNC, false);
+               }
+               /* Regardless, ignore this status info for outdated rate */
+               return;
+       } else
+               /* Rate did match, so reset the missed_rate_counter */
+               lq_sta->missed_rate_counter = 0;
+
+       /* Figure out if rate scale algorithm is in active or search table */
+       if (il4965_table_type_matches
+           (&tbl_type, &(lq_sta->lq_info[lq_sta->active_tbl]))) {
+               curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+               other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
+       } else
+           if (il4965_table_type_matches
+               (&tbl_type, &lq_sta->lq_info[1 - lq_sta->active_tbl])) {
+               curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
+               other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+       } else {
+               D_RATE("Neither active nor search matches tx rate\n");
+               tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+               D_RATE("active- lq:%x, ant:%x, SGI:%d\n", tmp_tbl->lq_type,
+                      tmp_tbl->ant_type, tmp_tbl->is_SGI);
+               tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
+               D_RATE("search- lq:%x, ant:%x, SGI:%d\n", tmp_tbl->lq_type,
+                      tmp_tbl->ant_type, tmp_tbl->is_SGI);
+               D_RATE("actual- lq:%x, ant:%x, SGI:%d\n", tbl_type.lq_type,
+                      tbl_type.ant_type, tbl_type.is_SGI);
+               /*
+                * no matching table found, let's by-pass the data collection
+                * and continue to perform rate scale to find the rate table
+                */
+               il4965_rs_stay_in_table(lq_sta, true);
+               goto done;
+       }
+
+       /*
+        * Updating the frame history depends on whether packets were
+        * aggregated.
+        *
+        * For aggregation, all packets were transmitted at the same rate, the
+        * first idx into rate scale table.
+        */
+       if (info->flags & IEEE80211_TX_STAT_AMPDU) {
+               tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
+               il4965_rs_get_tbl_info_from_mcs(tx_rate, il->band, &tbl_type,
+                                               &rs_idx);
+               il4965_rs_collect_tx_data(curr_tbl, rs_idx,
+                                         info->status.ampdu_len,
+                                         info->status.ampdu_ack_len);
+
+               /* Update success/fail counts if not searching for new mode */
+               if (lq_sta->stay_in_tbl) {
+                       lq_sta->total_success += info->status.ampdu_ack_len;
+                       lq_sta->total_failed +=
+                           (info->status.ampdu_len -
+                            info->status.ampdu_ack_len);
+               }
+       } else {
+               /*
+                * For legacy, update frame history with for each Tx retry.
+                */
+               retries = info->status.rates[0].count - 1;
+               /* HW doesn't send more than 15 retries */
+               retries = min(retries, 15);
+
+               /* The last transmission may have been successful */
+               legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+               /* Collect data for each rate used during failed TX attempts */
+               for (i = 0; i <= retries; ++i) {
+                       tx_rate = le32_to_cpu(table->rs_table[i].rate_n_flags);
+                       il4965_rs_get_tbl_info_from_mcs(tx_rate, il->band,
+                                                       &tbl_type, &rs_idx);
+                       /*
+                        * Only collect stats if retried rate is in the same RS
+                        * table as active/search.
+                        */
+                       if (il4965_table_type_matches(&tbl_type, curr_tbl))
+                               tmp_tbl = curr_tbl;
+                       else if (il4965_table_type_matches
+                                (&tbl_type, other_tbl))
+                               tmp_tbl = other_tbl;
+                       else
+                               continue;
+                       il4965_rs_collect_tx_data(tmp_tbl, rs_idx, 1,
+                                                 i <
+                                                 retries ? 0 : legacy_success);
+               }
+
+               /* Update success/fail counts if not searching for new mode */
+               if (lq_sta->stay_in_tbl) {
+                       lq_sta->total_success += legacy_success;
+                       lq_sta->total_failed += retries + (1 - legacy_success);
+               }
+       }
+       /* The last TX rate is cached in lq_sta; it's set in if/else above */
+       lq_sta->last_rate_n_flags = tx_rate;
+done:
+       /* See if there's a better rate or modulation mode to try. */
+       if (sta->supp_rates[sband->band])
+               il4965_rs_rate_scale_perform(il, skb, sta, lq_sta);
+}
+
+/*
+ * Begin a period of staying with a selected modulation mode.
+ * Set "stay_in_tbl" flag to prevent any mode switches.
+ * Set frame tx success limits according to legacy vs. high-throughput,
+ * and reset overall (spanning all rates) tx success history stats.
+ * These control how long we stay using same modulation mode before
+ * searching for a new mode.
+ */
+static void
+il4965_rs_set_stay_in_table(struct il_priv *il, u8 is_legacy,
+                           struct il_lq_sta *lq_sta)
+{
+       D_RATE("we are staying in the same table\n");
+       lq_sta->stay_in_tbl = 1;        /* only place this gets set */
+       if (is_legacy) {
+               lq_sta->table_count_limit = IL_LEGACY_TBL_COUNT;
+               lq_sta->max_failure_limit = IL_LEGACY_FAILURE_LIMIT;
+               lq_sta->max_success_limit = IL_LEGACY_SUCCESS_LIMIT;
+       } else {
+               lq_sta->table_count_limit = IL_NONE_LEGACY_TBL_COUNT;
+               lq_sta->max_failure_limit = IL_NONE_LEGACY_FAILURE_LIMIT;
+               lq_sta->max_success_limit = IL_NONE_LEGACY_SUCCESS_LIMIT;
+       }
+       lq_sta->table_count = 0;
+       lq_sta->total_failed = 0;
+       lq_sta->total_success = 0;
+       lq_sta->flush_timer = jiffies;
+       lq_sta->action_counter = 0;
+}
+
+/*
+ * Find correct throughput table for given mode of modulation
+ */
+static void
+il4965_rs_set_expected_tpt_table(struct il_lq_sta *lq_sta,
+                                struct il_scale_tbl_info *tbl)
+{
+       /* Used to choose among HT tables */
+       s32(*ht_tbl_pointer)[RATE_COUNT];
+
+       /* Check for invalid LQ type */
+       if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) {
+               tbl->expected_tpt = expected_tpt_legacy;
+               return;
+       }
+
+       /* Legacy rates have only one table */
+       if (is_legacy(tbl->lq_type)) {
+               tbl->expected_tpt = expected_tpt_legacy;
+               return;
+       }
+
+       /* Choose among many HT tables depending on number of streams
+        * (SISO/MIMO2), channel width (20/40), SGI, and aggregation
+        * status */
+       if (is_siso(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
+               ht_tbl_pointer = expected_tpt_siso20MHz;
+       else if (is_siso(tbl->lq_type))
+               ht_tbl_pointer = expected_tpt_siso40MHz;
+       else if (is_mimo2(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
+               ht_tbl_pointer = expected_tpt_mimo2_20MHz;
+       else                    /* if (is_mimo2(tbl->lq_type)) <-- must be true */
+               ht_tbl_pointer = expected_tpt_mimo2_40MHz;
+
+       if (!tbl->is_SGI && !lq_sta->is_agg)    /* Normal */
+               tbl->expected_tpt = ht_tbl_pointer[0];
+       else if (tbl->is_SGI && !lq_sta->is_agg)        /* SGI */
+               tbl->expected_tpt = ht_tbl_pointer[1];
+       else if (!tbl->is_SGI && lq_sta->is_agg)        /* AGG */
+               tbl->expected_tpt = ht_tbl_pointer[2];
+       else                    /* AGG+SGI */
+               tbl->expected_tpt = ht_tbl_pointer[3];
+}
+
+/*
+ * Find starting rate for new "search" high-throughput mode of modulation.
+ * Goal is to find lowest expected rate (under perfect conditions) that is
+ * above the current measured throughput of "active" mode, to give new mode
+ * a fair chance to prove itself without too many challenges.
+ *
+ * This gets called when transitioning to more aggressive modulation
+ * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive
+ * (i.e. MIMO to SISO).  When moving to MIMO, bit rate will typically need
+ * to decrease to match "active" throughput.  When moving from MIMO to SISO,
+ * bit rate will typically need to increase, but not if performance was bad.
+ */
+static s32
+il4965_rs_get_best_rate(struct il_priv *il, struct il_lq_sta *lq_sta,
+                       struct il_scale_tbl_info *tbl,  /* "search" */
+                       u16 rate_mask, s8 idx)
+{
+       /* "active" values */
+       struct il_scale_tbl_info *active_tbl =
+           &(lq_sta->lq_info[lq_sta->active_tbl]);
+       s32 active_sr = active_tbl->win[idx].success_ratio;
+       s32 active_tpt = active_tbl->expected_tpt[idx];
+
+       /* expected "search" throughput */
+       s32 *tpt_tbl = tbl->expected_tpt;
+
+       s32 new_rate, high, low, start_hi;
+       u16 high_low;
+       s8 rate = idx;
+
+       new_rate = high = low = start_hi = RATE_INVALID;
+
+       for (;;) {
+               high_low =
+                   il4965_rs_get_adjacent_rate(il, rate, rate_mask,
+                                               tbl->lq_type);
+
+               low = high_low & 0xff;
+               high = (high_low >> 8) & 0xff;
+
+               /*
+                * Lower the "search" bit rate, to give new "search" mode
+                * approximately the same throughput as "active" if:
+                *
+                * 1) "Active" mode has been working modestly well (but not
+                *    great), and expected "search" throughput (under perfect
+                *    conditions) at candidate rate is above the actual
+                *    measured "active" throughput (but less than expected
+                *    "active" throughput under perfect conditions).
+                * OR
+                * 2) "Active" mode has been working perfectly or very well
+                *    and expected "search" throughput (under perfect
+                *    conditions) at candidate rate is above expected
+                *    "active" throughput (under perfect conditions).
+                */
+               if ((100 * tpt_tbl[rate] > lq_sta->last_tpt &&
+                    (active_sr > RATE_DECREASE_TH && active_sr <= RATE_HIGH_TH
+                     && tpt_tbl[rate] <= active_tpt)) ||
+                   (active_sr >= RATE_SCALE_SWITCH &&
+                    tpt_tbl[rate] > active_tpt)) {
+
+                       /* (2nd or later pass)
+                        * If we've already tried to raise the rate, and are
+                        * now trying to lower it, use the higher rate. */
+                       if (start_hi != RATE_INVALID) {
+                               new_rate = start_hi;
+                               break;
+                       }
+
+                       new_rate = rate;
+
+                       /* Loop again with lower rate */
+                       if (low != RATE_INVALID)
+                               rate = low;
+
+                       /* Lower rate not available, use the original */
+                       else
+                               break;
+
+                       /* Else try to raise the "search" rate to match "active" */
+               } else {
+                       /* (2nd or later pass)
+                        * If we've already tried to lower the rate, and are
+                        * now trying to raise it, use the lower rate. */
+                       if (new_rate != RATE_INVALID)
+                               break;
+
+                       /* Loop again with higher rate */
+                       else if (high != RATE_INVALID) {
+                               start_hi = high;
+                               rate = high;
+
+                               /* Higher rate not available, use the original */
+                       } else {
+                               new_rate = rate;
+                               break;
+                       }
+               }
+       }
+
+       return new_rate;
+}
+
+/*
+ * Set up search table for MIMO2
+ */
+static int
+il4965_rs_switch_to_mimo2(struct il_priv *il, struct il_lq_sta *lq_sta,
+                         struct ieee80211_conf *conf,
+                         struct ieee80211_sta *sta,
+                         struct il_scale_tbl_info *tbl, int idx)
+{
+       u16 rate_mask;
+       s32 rate;
+       s8 is_green = lq_sta->is_green;
+       struct il_station_priv *sta_priv = (void *)sta->drv_priv;
+       struct il_rxon_context *ctx = sta_priv->common.ctx;
+
+       if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
+               return -1;
+
+       if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) ==
+           WLAN_HT_CAP_SM_PS_STATIC)
+               return -1;
+
+       /* Need both Tx chains/antennas to support MIMO */
+       if (il->hw_params.tx_chains_num < 2)
+               return -1;
+
+       D_RATE("LQ: try to switch to MIMO2\n");
+
+       tbl->lq_type = LQ_MIMO2;
+       tbl->is_dup = lq_sta->is_dup;
+       tbl->action = 0;
+       tbl->max_search = IL_MAX_SEARCH;
+       rate_mask = lq_sta->active_mimo2_rate;
+
+       if (il_is_ht40_tx_allowed(il, ctx, &sta->ht_cap))
+               tbl->is_ht40 = 1;
+       else
+               tbl->is_ht40 = 0;
+
+       il4965_rs_set_expected_tpt_table(lq_sta, tbl);
+
+       rate = il4965_rs_get_best_rate(il, lq_sta, tbl, rate_mask, idx);
+
+       D_RATE("LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask);
+       if (rate == RATE_INVALID || !((1 << rate) & rate_mask)) {
+               D_RATE("Can't switch with idx %d rate mask %x\n", rate,
+                      rate_mask);
+               return -1;
+       }
+       tbl->current_rate =
+           il4965_rate_n_flags_from_tbl(il, tbl, rate, is_green);
+
+       D_RATE("LQ: Switch to new mcs %X idx is green %X\n", tbl->current_rate,
+              is_green);
+       return 0;
+}
+
+/*
+ * Set up search table for SISO
+ */
+static int
+il4965_rs_switch_to_siso(struct il_priv *il, struct il_lq_sta *lq_sta,
+                        struct ieee80211_conf *conf, struct ieee80211_sta *sta,
+                        struct il_scale_tbl_info *tbl, int idx)
+{
+       u16 rate_mask;
+       u8 is_green = lq_sta->is_green;
+       s32 rate;
+       struct il_station_priv *sta_priv = (void *)sta->drv_priv;
+       struct il_rxon_context *ctx = sta_priv->common.ctx;
+
+       if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
+               return -1;
+
+       D_RATE("LQ: try to switch to SISO\n");
+
+       tbl->is_dup = lq_sta->is_dup;
+       tbl->lq_type = LQ_SISO;
+       tbl->action = 0;
+       tbl->max_search = IL_MAX_SEARCH;
+       rate_mask = lq_sta->active_siso_rate;
+
+       if (il_is_ht40_tx_allowed(il, ctx, &sta->ht_cap))
+               tbl->is_ht40 = 1;
+       else
+               tbl->is_ht40 = 0;
+
+       if (is_green)
+               tbl->is_SGI = 0;        /*11n spec: no SGI in SISO+Greenfield */
+
+       il4965_rs_set_expected_tpt_table(lq_sta, tbl);
+       rate = il4965_rs_get_best_rate(il, lq_sta, tbl, rate_mask, idx);
+
+       D_RATE("LQ: get best rate %d mask %X\n", rate, rate_mask);
+       if (rate == RATE_INVALID || !((1 << rate) & rate_mask)) {
+               D_RATE("can not switch with idx %d rate mask %x\n", rate,
+                      rate_mask);
+               return -1;
+       }
+       tbl->current_rate =
+           il4965_rate_n_flags_from_tbl(il, tbl, rate, is_green);
+       D_RATE("LQ: Switch to new mcs %X idx is green %X\n", tbl->current_rate,
+              is_green);
+       return 0;
+}
+
+/*
+ * Try to switch to new modulation mode from legacy
+ */
+static int
+il4965_rs_move_legacy_other(struct il_priv *il, struct il_lq_sta *lq_sta,
+                           struct ieee80211_conf *conf,
+                           struct ieee80211_sta *sta, int idx)
+{
+       struct il_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+       struct il_scale_tbl_info *search_tbl =
+           &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+       struct il_rate_scale_data *win = &(tbl->win[idx]);
+       u32 sz =
+           (sizeof(struct il_scale_tbl_info) -
+            (sizeof(struct il_rate_scale_data) * RATE_COUNT));
+       u8 start_action;
+       u8 valid_tx_ant = il->hw_params.valid_tx_ant;
+       u8 tx_chains_num = il->hw_params.tx_chains_num;
+       int ret = 0;
+       u8 update_search_tbl_counter = 0;
+
+       tbl->action = IL_LEGACY_SWITCH_SISO;
+
+       start_action = tbl->action;
+       for (;;) {
+               lq_sta->action_counter++;
+               switch (tbl->action) {
+               case IL_LEGACY_SWITCH_ANTENNA1:
+               case IL_LEGACY_SWITCH_ANTENNA2:
+                       D_RATE("LQ: Legacy toggle Antenna\n");
+
+                       if ((tbl->action == IL_LEGACY_SWITCH_ANTENNA1 &&
+                            tx_chains_num <= 1) ||
+                           (tbl->action == IL_LEGACY_SWITCH_ANTENNA2 &&
+                            tx_chains_num <= 2))
+                               break;
+
+                       /* Don't change antenna if success has been great */
+                       if (win->success_ratio >= IL_RS_GOOD_RATIO)
+                               break;
+
+                       /* Set up search table to try other antenna */
+                       memcpy(search_tbl, tbl, sz);
+
+                       if (il4965_rs_toggle_antenna
+                           (valid_tx_ant, &search_tbl->current_rate,
+                            search_tbl)) {
+                               update_search_tbl_counter = 1;
+                               il4965_rs_set_expected_tpt_table(lq_sta,
+                                                                search_tbl);
+                               goto out;
+                       }
+                       break;
+               case IL_LEGACY_SWITCH_SISO:
+                       D_RATE("LQ: Legacy switch to SISO\n");
+
+                       /* Set up search table to try SISO */
+                       memcpy(search_tbl, tbl, sz);
+                       search_tbl->is_SGI = 0;
+                       ret =
+                           il4965_rs_switch_to_siso(il, lq_sta, conf, sta,
+                                                    search_tbl, idx);
+                       if (!ret) {
+                               lq_sta->action_counter = 0;
+                               goto out;
+                       }
+
+                       break;
+               case IL_LEGACY_SWITCH_MIMO2_AB:
+               case IL_LEGACY_SWITCH_MIMO2_AC:
+               case IL_LEGACY_SWITCH_MIMO2_BC:
+                       D_RATE("LQ: Legacy switch to MIMO2\n");
+
+                       /* Set up search table to try MIMO */
+                       memcpy(search_tbl, tbl, sz);
+                       search_tbl->is_SGI = 0;
+
+                       if (tbl->action == IL_LEGACY_SWITCH_MIMO2_AB)
+                               search_tbl->ant_type = ANT_AB;
+                       else if (tbl->action == IL_LEGACY_SWITCH_MIMO2_AC)
+                               search_tbl->ant_type = ANT_AC;
+                       else
+                               search_tbl->ant_type = ANT_BC;
+
+                       if (!il4965_rs_is_valid_ant
+                           (valid_tx_ant, search_tbl->ant_type))
+                               break;
+
+                       ret =
+                           il4965_rs_switch_to_mimo2(il, lq_sta, conf, sta,
+                                                     search_tbl, idx);
+                       if (!ret) {
+                               lq_sta->action_counter = 0;
+                               goto out;
+                       }
+                       break;
+               }
+               tbl->action++;
+               if (tbl->action > IL_LEGACY_SWITCH_MIMO2_BC)
+                       tbl->action = IL_LEGACY_SWITCH_ANTENNA1;
+
+               if (tbl->action == start_action)
+                       break;
+
+       }
+       search_tbl->lq_type = LQ_NONE;
+       return 0;
+
+out:
+       lq_sta->search_better_tbl = 1;
+       tbl->action++;
+       if (tbl->action > IL_LEGACY_SWITCH_MIMO2_BC)
+               tbl->action = IL_LEGACY_SWITCH_ANTENNA1;
+       if (update_search_tbl_counter)
+               search_tbl->action = tbl->action;
+       return 0;
+
+}
+
+/*
+ * Try to switch to new modulation mode from SISO
+ */
+static int
+il4965_rs_move_siso_to_other(struct il_priv *il, struct il_lq_sta *lq_sta,
+                            struct ieee80211_conf *conf,
+                            struct ieee80211_sta *sta, int idx)
+{
+       u8 is_green = lq_sta->is_green;
+       struct il_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+       struct il_scale_tbl_info *search_tbl =
+           &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+       struct il_rate_scale_data *win = &(tbl->win[idx]);
+       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+       u32 sz =
+           (sizeof(struct il_scale_tbl_info) -
+            (sizeof(struct il_rate_scale_data) * RATE_COUNT));
+       u8 start_action;
+       u8 valid_tx_ant = il->hw_params.valid_tx_ant;
+       u8 tx_chains_num = il->hw_params.tx_chains_num;
+       u8 update_search_tbl_counter = 0;
+       int ret;
+
+       start_action = tbl->action;
+
+       for (;;) {
+               lq_sta->action_counter++;
+               switch (tbl->action) {
+               case IL_SISO_SWITCH_ANTENNA1:
+               case IL_SISO_SWITCH_ANTENNA2:
+                       D_RATE("LQ: SISO toggle Antenna\n");
+                       if ((tbl->action == IL_SISO_SWITCH_ANTENNA1 &&
+                            tx_chains_num <= 1) ||
+                           (tbl->action == IL_SISO_SWITCH_ANTENNA2 &&
+                            tx_chains_num <= 2))
+                               break;
+
+                       if (win->success_ratio >= IL_RS_GOOD_RATIO)
+                               break;
+
+                       memcpy(search_tbl, tbl, sz);
+                       if (il4965_rs_toggle_antenna
+                           (valid_tx_ant, &search_tbl->current_rate,
+                            search_tbl)) {
+                               update_search_tbl_counter = 1;
+                               goto out;
+                       }
+                       break;
+               case IL_SISO_SWITCH_MIMO2_AB:
+               case IL_SISO_SWITCH_MIMO2_AC:
+               case IL_SISO_SWITCH_MIMO2_BC:
+                       D_RATE("LQ: SISO switch to MIMO2\n");
+                       memcpy(search_tbl, tbl, sz);
+                       search_tbl->is_SGI = 0;
+
+                       if (tbl->action == IL_SISO_SWITCH_MIMO2_AB)
+                               search_tbl->ant_type = ANT_AB;
+                       else if (tbl->action == IL_SISO_SWITCH_MIMO2_AC)
+                               search_tbl->ant_type = ANT_AC;
+                       else
+                               search_tbl->ant_type = ANT_BC;
+
+                       if (!il4965_rs_is_valid_ant
+                           (valid_tx_ant, search_tbl->ant_type))
+                               break;
+
+                       ret =
+                           il4965_rs_switch_to_mimo2(il, lq_sta, conf, sta,
+                                                     search_tbl, idx);
+                       if (!ret)
+                               goto out;
+                       break;
+               case IL_SISO_SWITCH_GI:
+                       if (!tbl->is_ht40 &&
+                           !(ht_cap->cap & IEEE80211_HT_CAP_SGI_20))
+                               break;
+                       if (tbl->is_ht40 &&
+                           !(ht_cap->cap & IEEE80211_HT_CAP_SGI_40))
+                               break;
+
+                       D_RATE("LQ: SISO toggle SGI/NGI\n");
+
+                       memcpy(search_tbl, tbl, sz);
+                       if (is_green) {
+                               if (!tbl->is_SGI)
+                                       break;
+                               else
+                                       IL_ERR("SGI was set in GF+SISO\n");
+                       }
+                       search_tbl->is_SGI = !tbl->is_SGI;
+                       il4965_rs_set_expected_tpt_table(lq_sta, search_tbl);
+                       if (tbl->is_SGI) {
+                               s32 tpt = lq_sta->last_tpt / 100;
+                               if (tpt >= search_tbl->expected_tpt[idx])
+                                       break;
+                       }
+                       search_tbl->current_rate =
+                           il4965_rate_n_flags_from_tbl(il, search_tbl, idx,
+                                                        is_green);
+                       update_search_tbl_counter = 1;
+                       goto out;
+               }
+               tbl->action++;
+               if (tbl->action > IL_SISO_SWITCH_GI)
+                       tbl->action = IL_SISO_SWITCH_ANTENNA1;
+
+               if (tbl->action == start_action)
+                       break;
+       }
+       search_tbl->lq_type = LQ_NONE;
+       return 0;
+
+out:
+       lq_sta->search_better_tbl = 1;
+       tbl->action++;
+       if (tbl->action > IL_SISO_SWITCH_GI)
+               tbl->action = IL_SISO_SWITCH_ANTENNA1;
+       if (update_search_tbl_counter)
+               search_tbl->action = tbl->action;
+
+       return 0;
+}
+
+/*
+ * Try to switch to new modulation mode from MIMO2
+ */
+static int
+il4965_rs_move_mimo2_to_other(struct il_priv *il, struct il_lq_sta *lq_sta,
+                             struct ieee80211_conf *conf,
+                             struct ieee80211_sta *sta, int idx)
+{
+       s8 is_green = lq_sta->is_green;
+       struct il_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+       struct il_scale_tbl_info *search_tbl =
+           &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+       struct il_rate_scale_data *win = &(tbl->win[idx]);
+       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+       u32 sz =
+           (sizeof(struct il_scale_tbl_info) -
+            (sizeof(struct il_rate_scale_data) * RATE_COUNT));
+       u8 start_action;
+       u8 valid_tx_ant = il->hw_params.valid_tx_ant;
+       u8 tx_chains_num = il->hw_params.tx_chains_num;
+       u8 update_search_tbl_counter = 0;
+       int ret;
+
+       start_action = tbl->action;
+       for (;;) {
+               lq_sta->action_counter++;
+               switch (tbl->action) {
+               case IL_MIMO2_SWITCH_ANTENNA1:
+               case IL_MIMO2_SWITCH_ANTENNA2:
+                       D_RATE("LQ: MIMO2 toggle Antennas\n");
+
+                       if (tx_chains_num <= 2)
+                               break;
+
+                       if (win->success_ratio >= IL_RS_GOOD_RATIO)
+                               break;
+
+                       memcpy(search_tbl, tbl, sz);
+                       if (il4965_rs_toggle_antenna
+                           (valid_tx_ant, &search_tbl->current_rate,
+                            search_tbl)) {
+                               update_search_tbl_counter = 1;
+                               goto out;
+                       }
+                       break;
+               case IL_MIMO2_SWITCH_SISO_A:
+               case IL_MIMO2_SWITCH_SISO_B:
+               case IL_MIMO2_SWITCH_SISO_C:
+                       D_RATE("LQ: MIMO2 switch to SISO\n");
+
+                       /* Set up new search table for SISO */
+                       memcpy(search_tbl, tbl, sz);
+
+                       if (tbl->action == IL_MIMO2_SWITCH_SISO_A)
+                               search_tbl->ant_type = ANT_A;
+                       else if (tbl->action == IL_MIMO2_SWITCH_SISO_B)
+                               search_tbl->ant_type = ANT_B;
+                       else
+                               search_tbl->ant_type = ANT_C;
+
+                       if (!il4965_rs_is_valid_ant
+                           (valid_tx_ant, search_tbl->ant_type))
+                               break;
+
+                       ret =
+                           il4965_rs_switch_to_siso(il, lq_sta, conf, sta,
+                                                    search_tbl, idx);
+                       if (!ret)
+                               goto out;
+
+                       break;
+
+               case IL_MIMO2_SWITCH_GI:
+                       if (!tbl->is_ht40 &&
+                           !(ht_cap->cap & IEEE80211_HT_CAP_SGI_20))
+                               break;
+                       if (tbl->is_ht40 &&
+                           !(ht_cap->cap & IEEE80211_HT_CAP_SGI_40))
+                               break;
+
+                       D_RATE("LQ: MIMO2 toggle SGI/NGI\n");
+
+                       /* Set up new search table for MIMO2 */
+                       memcpy(search_tbl, tbl, sz);
+                       search_tbl->is_SGI = !tbl->is_SGI;
+                       il4965_rs_set_expected_tpt_table(lq_sta, search_tbl);
+                       /*
+                        * If active table already uses the fastest possible
+                        * modulation (dual stream with short guard interval),
+                        * and it's working well, there's no need to look
+                        * for a better type of modulation!
+                        */
+                       if (tbl->is_SGI) {
+                               s32 tpt = lq_sta->last_tpt / 100;
+                               if (tpt >= search_tbl->expected_tpt[idx])
+                                       break;
+                       }
+                       search_tbl->current_rate =
+                           il4965_rate_n_flags_from_tbl(il, search_tbl, idx,
+                                                        is_green);
+                       update_search_tbl_counter = 1;
+                       goto out;
+
+               }
+               tbl->action++;
+               if (tbl->action > IL_MIMO2_SWITCH_GI)
+                       tbl->action = IL_MIMO2_SWITCH_ANTENNA1;
+
+               if (tbl->action == start_action)
+                       break;
+       }
+       search_tbl->lq_type = LQ_NONE;
+       return 0;
+out:
+       lq_sta->search_better_tbl = 1;
+       tbl->action++;
+       if (tbl->action > IL_MIMO2_SWITCH_GI)
+               tbl->action = IL_MIMO2_SWITCH_ANTENNA1;
+       if (update_search_tbl_counter)
+               search_tbl->action = tbl->action;
+
+       return 0;
+
+}
+
+/*
+ * Check whether we should continue using same modulation mode, or
+ * begin search for a new mode, based on:
+ * 1) # tx successes or failures while using this mode
+ * 2) # times calling this function
+ * 3) elapsed time in this mode (not used, for now)
+ */
+static void
+il4965_rs_stay_in_table(struct il_lq_sta *lq_sta, bool force_search)
+{
+       struct il_scale_tbl_info *tbl;
+       int i;
+       int active_tbl;
+       int flush_interval_passed = 0;
+       struct il_priv *il;
+
+       il = lq_sta->drv;
+       active_tbl = lq_sta->active_tbl;
+
+       tbl = &(lq_sta->lq_info[active_tbl]);
+
+       /* If we've been disallowing search, see if we should now allow it */
+       if (lq_sta->stay_in_tbl) {
+
+               /* Elapsed time using current modulation mode */
+               if (lq_sta->flush_timer)
+                       flush_interval_passed =
+                           time_after(jiffies,
+                                      (unsigned long)(lq_sta->flush_timer +
+                                                      RATE_SCALE_FLUSH_INTVL));
+
+               /*
+                * Check if we should allow search for new modulation mode.
+                * If many frames have failed or succeeded, or we've used
+                * this same modulation for a long time, allow search, and
+                * reset history stats that keep track of whether we should
+                * allow a new search.  Also (below) reset all bitmaps and
+                * stats in active history.
+                */
+               if (force_search ||
+                   lq_sta->total_failed > lq_sta->max_failure_limit ||
+                   lq_sta->total_success > lq_sta->max_success_limit ||
+                   (!lq_sta->search_better_tbl && lq_sta->flush_timer &&
+                    flush_interval_passed)) {
+                       D_RATE("LQ: stay is expired %d %d %d\n:",
+                              lq_sta->total_failed, lq_sta->total_success,
+                              flush_interval_passed);
+
+                       /* Allow search for new mode */
+                       lq_sta->stay_in_tbl = 0;        /* only place reset */
+                       lq_sta->total_failed = 0;
+                       lq_sta->total_success = 0;
+                       lq_sta->flush_timer = 0;
+
+                       /*
+                        * Else if we've used this modulation mode enough repetitions
+                        * (regardless of elapsed time or success/failure), reset
+                        * history bitmaps and rate-specific stats for all rates in
+                        * active table.
+                        */
+               } else {
+                       lq_sta->table_count++;
+                       if (lq_sta->table_count >= lq_sta->table_count_limit) {
+                               lq_sta->table_count = 0;
+
+                               D_RATE("LQ: stay in table clear win\n");
+                               for (i = 0; i < RATE_COUNT; i++)
+                                       il4965_rs_rate_scale_clear_win(&
+                                                                      (tbl->
+                                                                       win
+                                                                       [i]));
+                       }
+               }
+
+               /* If transitioning to allow "search", reset all history
+                * bitmaps and stats in active table (this will become the new
+                * "search" table). */
+               if (!lq_sta->stay_in_tbl) {
+                       for (i = 0; i < RATE_COUNT; i++)
+                               il4965_rs_rate_scale_clear_win(&(tbl->win[i]));
+               }
+       }
+}
+
+/*
+ * setup rate table in uCode
+ */
+static void
+il4965_rs_update_rate_tbl(struct il_priv *il, struct il_rxon_context *ctx,
+                         struct il_lq_sta *lq_sta,
+                         struct il_scale_tbl_info *tbl, int idx, u8 is_green)
+{
+       u32 rate;
+
+       /* Update uCode's rate table. */
+       rate = il4965_rate_n_flags_from_tbl(il, tbl, idx, is_green);
+       il4965_rs_fill_link_cmd(il, lq_sta, rate);
+       il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_ASYNC, false);
+}
+
+/*
+ * Do rate scaling and search for new modulation mode.
+ */
+static void
+il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb,
+                            struct ieee80211_sta *sta,
+                            struct il_lq_sta *lq_sta)
+{
+       struct ieee80211_hw *hw = il->hw;
+       struct ieee80211_conf *conf = &hw->conf;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       int low = RATE_INVALID;
+       int high = RATE_INVALID;
+       int idx;
+       int i;
+       struct il_rate_scale_data *win = NULL;
+       int current_tpt = IL_INVALID_VALUE;
+       int low_tpt = IL_INVALID_VALUE;
+       int high_tpt = IL_INVALID_VALUE;
+       u32 fail_count;
+       s8 scale_action = 0;
+       u16 rate_mask;
+       u8 update_lq = 0;
+       struct il_scale_tbl_info *tbl, *tbl1;
+       u16 rate_scale_idx_msk = 0;
+       u8 is_green = 0;
+       u8 active_tbl = 0;
+       u8 done_search = 0;
+       u16 high_low;
+       s32 sr;
+       u8 tid = MAX_TID_COUNT;
+       struct il_tid_data *tid_data;
+       struct il_station_priv *sta_priv = (void *)sta->drv_priv;
+       struct il_rxon_context *ctx = sta_priv->common.ctx;
+
+       D_RATE("rate scale calculate new rate for skb\n");
+
+       /* Send management frames and NO_ACK data using lowest rate. */
+       /* TODO: this could probably be improved.. */
+       if (!ieee80211_is_data(hdr->frame_control) ||
+           (info->flags & IEEE80211_TX_CTL_NO_ACK))
+               return;
+
+       lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
+
+       tid = il4965_rs_tl_add_packet(lq_sta, hdr);
+       if (tid != MAX_TID_COUNT && (lq_sta->tx_agg_tid_en & (1 << tid))) {
+               tid_data = &il->stations[lq_sta->lq.sta_id].tid[tid];
+               if (tid_data->agg.state == IL_AGG_OFF)
+                       lq_sta->is_agg = 0;
+               else
+                       lq_sta->is_agg = 1;
+       } else
+               lq_sta->is_agg = 0;
+
+       /*
+        * Select rate-scale / modulation-mode table to work with in
+        * the rest of this function:  "search" if searching for better
+        * modulation mode, or "active" if doing rate scaling within a mode.
+        */
+       if (!lq_sta->search_better_tbl)
+               active_tbl = lq_sta->active_tbl;
+       else
+               active_tbl = 1 - lq_sta->active_tbl;
+
+       tbl = &(lq_sta->lq_info[active_tbl]);
+       if (is_legacy(tbl->lq_type))
+               lq_sta->is_green = 0;
+       else
+               lq_sta->is_green = il4965_rs_use_green(sta);
+       is_green = lq_sta->is_green;
+
+       /* current tx rate */
+       idx = lq_sta->last_txrate_idx;
+
+       D_RATE("Rate scale idx %d for type %d\n", idx, tbl->lq_type);
+
+       /* rates available for this association, and for modulation mode */
+       rate_mask = il4965_rs_get_supported_rates(lq_sta, hdr, tbl->lq_type);
+
+       D_RATE("mask 0x%04X\n", rate_mask);
+
+       /* mask with station rate restriction */
+       if (is_legacy(tbl->lq_type)) {
+               if (lq_sta->band == IEEE80211_BAND_5GHZ)
+                       /* supp_rates has no CCK bits in A mode */
+                       rate_scale_idx_msk =
+                           (u16) (rate_mask &
+                                  (lq_sta->supp_rates << IL_FIRST_OFDM_RATE));
+               else
+                       rate_scale_idx_msk =
+                           (u16) (rate_mask & lq_sta->supp_rates);
+
+       } else
+               rate_scale_idx_msk = rate_mask;
+
+       if (!rate_scale_idx_msk)
+               rate_scale_idx_msk = rate_mask;
+
+       if (!((1 << idx) & rate_scale_idx_msk)) {
+               IL_ERR("Current Rate is not valid\n");
+               if (lq_sta->search_better_tbl) {
+                       /* revert to active table if search table is not valid */
+                       tbl->lq_type = LQ_NONE;
+                       lq_sta->search_better_tbl = 0;
+                       tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+                       /* get "active" rate info */
+                       idx = il4965_hwrate_to_plcp_idx(tbl->current_rate);
+                       il4965_rs_update_rate_tbl(il, ctx, lq_sta, tbl, idx,
+                                                     is_green);
+               }
+               return;
+       }
+
+       /* Get expected throughput table and history win for current rate */
+       if (!tbl->expected_tpt) {
+               IL_ERR("tbl->expected_tpt is NULL\n");
+               return;
+       }
+
+       /* force user max rate if set by user */
+       if (lq_sta->max_rate_idx != -1 && lq_sta->max_rate_idx < idx) {
+               idx = lq_sta->max_rate_idx;
+               update_lq = 1;
+               win = &(tbl->win[idx]);
+               goto lq_update;
+       }
+
+       win = &(tbl->win[idx]);
+
+       /*
+        * If there is not enough history to calculate actual average
+        * throughput, keep analyzing results of more tx frames, without
+        * changing rate or mode (bypass most of the rest of this function).
+        * Set up new rate table in uCode only if old rate is not supported
+        * in current association (use new rate found above).
+        */
+       fail_count = win->counter - win->success_counter;
+       if (fail_count < RATE_MIN_FAILURE_TH &&
+           win->success_counter < RATE_MIN_SUCCESS_TH) {
+               D_RATE("LQ: still below TH. succ=%d total=%d " "for idx %d\n",
+                      win->success_counter, win->counter, idx);
+
+               /* Can't calculate this yet; not enough history */
+               win->average_tpt = IL_INVALID_VALUE;
+
+               /* Should we stay with this modulation mode,
+                * or search for a new one? */
+               il4965_rs_stay_in_table(lq_sta, false);
+
+               goto out;
+       }
+       /* Else we have enough samples; calculate estimate of
+        * actual average throughput */
+       if (win->average_tpt !=
+           ((win->success_ratio * tbl->expected_tpt[idx] + 64) / 128)) {
+               IL_ERR("expected_tpt should have been calculated by now\n");
+               win->average_tpt =
+                   ((win->success_ratio * tbl->expected_tpt[idx] + 64) / 128);
+       }
+
+       /* If we are searching for better modulation mode, check success. */
+       if (lq_sta->search_better_tbl) {
+               /* If good success, continue using the "search" mode;
+                * no need to send new link quality command, since we're
+                * continuing to use the setup that we've been trying. */
+               if (win->average_tpt > lq_sta->last_tpt) {
+
+                       D_RATE("LQ: SWITCHING TO NEW TBL "
+                              "suc=%d cur-tpt=%d old-tpt=%d\n",
+                              win->success_ratio, win->average_tpt,
+                              lq_sta->last_tpt);
+
+                       if (!is_legacy(tbl->lq_type))
+                               lq_sta->enable_counter = 1;
+
+                       /* Swap tables; "search" becomes "active" */
+                       lq_sta->active_tbl = active_tbl;
+                       current_tpt = win->average_tpt;
+
+                       /* Else poor success; go back to mode in "active" table */
+               } else {
+
+                       D_RATE("LQ: GOING BACK TO THE OLD TBL "
+                              "suc=%d cur-tpt=%d old-tpt=%d\n",
+                              win->success_ratio, win->average_tpt,
+                              lq_sta->last_tpt);
+
+                       /* Nullify "search" table */
+                       tbl->lq_type = LQ_NONE;
+
+                       /* Revert to "active" table */
+                       active_tbl = lq_sta->active_tbl;
+                       tbl = &(lq_sta->lq_info[active_tbl]);
+
+                       /* Revert to "active" rate and throughput info */
+                       idx = il4965_hwrate_to_plcp_idx(tbl->current_rate);
+                       current_tpt = lq_sta->last_tpt;
+
+                       /* Need to set up a new rate table in uCode */
+                       update_lq = 1;
+               }
+
+               /* Either way, we've made a decision; modulation mode
+                * search is done, allow rate adjustment next time. */
+               lq_sta->search_better_tbl = 0;
+               done_search = 1;        /* Don't switch modes below! */
+               goto lq_update;
+       }
+
+       /* (Else) not in search of better modulation mode, try for better
+        * starting rate, while staying in this mode. */
+       high_low =
+           il4965_rs_get_adjacent_rate(il, idx, rate_scale_idx_msk,
+                                       tbl->lq_type);
+       low = high_low & 0xff;
+       high = (high_low >> 8) & 0xff;
+
+       /* If user set max rate, dont allow higher than user constrain */
+       if (lq_sta->max_rate_idx != -1 && lq_sta->max_rate_idx < high)
+               high = RATE_INVALID;
+
+       sr = win->success_ratio;
+
+       /* Collect measured throughputs for current and adjacent rates */
+       current_tpt = win->average_tpt;
+       if (low != RATE_INVALID)
+               low_tpt = tbl->win[low].average_tpt;
+       if (high != RATE_INVALID)
+               high_tpt = tbl->win[high].average_tpt;
+
+       scale_action = 0;
+
+       /* Too many failures, decrease rate */
+       if (sr <= RATE_DECREASE_TH || current_tpt == 0) {
+               D_RATE("decrease rate because of low success_ratio\n");
+               scale_action = -1;
+
+               /* No throughput measured yet for adjacent rates; try increase. */
+       } else if (low_tpt == IL_INVALID_VALUE && high_tpt == IL_INVALID_VALUE) {
+
+               if (high != RATE_INVALID && sr >= RATE_INCREASE_TH)
+                       scale_action = 1;
+               else if (low != RATE_INVALID)
+                       scale_action = 0;
+       }
+
+       /* Both adjacent throughputs are measured, but neither one has better
+        * throughput; we're using the best rate, don't change it! */
+       else if (low_tpt != IL_INVALID_VALUE && high_tpt != IL_INVALID_VALUE &&
+                low_tpt < current_tpt && high_tpt < current_tpt)
+               scale_action = 0;
+
+       /* At least one adjacent rate's throughput is measured,
+        * and may have better performance. */
+       else {
+               /* Higher adjacent rate's throughput is measured */
+               if (high_tpt != IL_INVALID_VALUE) {
+                       /* Higher rate has better throughput */
+                       if (high_tpt > current_tpt && sr >= RATE_INCREASE_TH)
+                               scale_action = 1;
+                       else
+                               scale_action = 0;
+
+                       /* Lower adjacent rate's throughput is measured */
+               } else if (low_tpt != IL_INVALID_VALUE) {
+                       /* Lower rate has better throughput */
+                       if (low_tpt > current_tpt) {
+                               D_RATE("decrease rate because of low tpt\n");
+                               scale_action = -1;
+                       } else if (sr >= RATE_INCREASE_TH) {
+                               scale_action = 1;
+                       }
+               }
+       }
+
+       /* Sanity check; asked for decrease, but success rate or throughput
+        * has been good at old rate.  Don't change it. */
+       if (scale_action == -1 && low != RATE_INVALID &&
+           (sr > RATE_HIGH_TH || current_tpt > 100 * tbl->expected_tpt[low]))
+               scale_action = 0;
+
+       switch (scale_action) {
+       case -1:
+               /* Decrease starting rate, update uCode's rate table */
+               if (low != RATE_INVALID) {
+                       update_lq = 1;
+                       idx = low;
+               }
+
+               break;
+       case 1:
+               /* Increase starting rate, update uCode's rate table */
+               if (high != RATE_INVALID) {
+                       update_lq = 1;
+                       idx = high;
+               }
+
+               break;
+       case 0:
+               /* No change */
+       default:
+               break;
+       }
+
+       D_RATE("choose rate scale idx %d action %d low %d " "high %d type %d\n",
+              idx, scale_action, low, high, tbl->lq_type);
+
+lq_update:
+       /* Replace uCode's rate table for the destination station. */
+       if (update_lq)
+               il4965_rs_update_rate_tbl(il, ctx, lq_sta, tbl, idx,
+                                             is_green);
+
+       /* Should we stay with this modulation mode,
+        * or search for a new one? */
+       il4965_rs_stay_in_table(lq_sta, false);
+
+       /*
+        * Search for new modulation mode if we're:
+        * 1)  Not changing rates right now
+        * 2)  Not just finishing up a search
+        * 3)  Allowing a new search
+        */
+       if (!update_lq && !done_search && !lq_sta->stay_in_tbl && win->counter) {
+               /* Save current throughput to compare with "search" throughput */
+               lq_sta->last_tpt = current_tpt;
+
+               /* Select a new "search" modulation mode to try.
+                * If one is found, set up the new "search" table. */
+               if (is_legacy(tbl->lq_type))
+                       il4965_rs_move_legacy_other(il, lq_sta, conf, sta, idx);
+               else if (is_siso(tbl->lq_type))
+                       il4965_rs_move_siso_to_other(il, lq_sta, conf, sta,
+                                                    idx);
+               else            /* (is_mimo2(tbl->lq_type)) */
+                       il4965_rs_move_mimo2_to_other(il, lq_sta, conf, sta,
+                                                     idx);
+
+               /* If new "search" mode was selected, set up in uCode table */
+               if (lq_sta->search_better_tbl) {
+                       /* Access the "search" table, clear its history. */
+                       tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+                       for (i = 0; i < RATE_COUNT; i++)
+                               il4965_rs_rate_scale_clear_win(&(tbl->win[i]));
+
+                       /* Use new "search" start rate */
+                       idx = il4965_hwrate_to_plcp_idx(tbl->current_rate);
+
+                       D_RATE("Switch current  mcs: %X idx: %d\n",
+                              tbl->current_rate, idx);
+                       il4965_rs_fill_link_cmd(il, lq_sta, tbl->current_rate);
+                       il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_ASYNC, false);
+               } else
+                       done_search = 1;
+       }
+
+       if (done_search && !lq_sta->stay_in_tbl) {
+               /* If the "active" (non-search) mode was legacy,
+                * and we've tried switching antennas,
+                * but we haven't been able to try HT modes (not available),
+                * stay with best antenna legacy modulation for a while
+                * before next round of mode comparisons. */
+               tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
+               if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) &&
+                   lq_sta->action_counter > tbl1->max_search) {
+                       D_RATE("LQ: STAY in legacy table\n");
+                       il4965_rs_set_stay_in_table(il, 1, lq_sta);
+               }
+
+               /* If we're in an HT mode, and all 3 mode switch actions
+                * have been tried and compared, stay in this best modulation
+                * mode for a while before next round of mode comparisons. */
+               if (lq_sta->enable_counter &&
+                   lq_sta->action_counter >= tbl1->max_search) {
+                       if (lq_sta->last_tpt > IL_AGG_TPT_THREHOLD &&
+                           (lq_sta->tx_agg_tid_en & (1 << tid)) &&
+                           tid != MAX_TID_COUNT) {
+                               tid_data =
+                                   &il->stations[lq_sta->lq.sta_id].tid[tid];
+                               if (tid_data->agg.state == IL_AGG_OFF) {
+                                       D_RATE("try to aggregate tid %d\n",
+                                              tid);
+                                       il4965_rs_tl_turn_on_agg(il, tid,
+                                                                lq_sta, sta);
+                               }
+                       }
+                       il4965_rs_set_stay_in_table(il, 0, lq_sta);
+               }
+       }
+
+out:
+       tbl->current_rate =
+           il4965_rate_n_flags_from_tbl(il, tbl, idx, is_green);
+       i = idx;
+       lq_sta->last_txrate_idx = i;
+}
+
+/**
+ * il4965_rs_initialize_lq - Initialize a station's hardware rate table
+ *
+ * The uCode's station table contains a table of fallback rates
+ * for automatic fallback during transmission.
+ *
+ * NOTE: This sets up a default set of values.  These will be replaced later
+ *       if the driver's iwl-4965-rs rate scaling algorithm is used, instead of
+ *       rc80211_simple.
+ *
+ * NOTE: Run C_ADD_STA command to set up station table entry, before
+ *       calling this function (which runs C_TX_LINK_QUALITY_CMD,
+ *       which requires station table entry to exist).
+ */
+static void
+il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
+                       struct ieee80211_sta *sta, struct il_lq_sta *lq_sta)
+{
+       struct il_scale_tbl_info *tbl;
+       int rate_idx;
+       int i;
+       u32 rate;
+       u8 use_green = il4965_rs_use_green(sta);
+       u8 active_tbl = 0;
+       u8 valid_tx_ant;
+       struct il_station_priv *sta_priv;
+       struct il_rxon_context *ctx;
+
+       if (!sta || !lq_sta)
+               return;
+
+       sta_priv = (void *)sta->drv_priv;
+       ctx = sta_priv->common.ctx;
+
+       i = lq_sta->last_txrate_idx;
+
+       valid_tx_ant = il->hw_params.valid_tx_ant;
+
+       if (!lq_sta->search_better_tbl)
+               active_tbl = lq_sta->active_tbl;
+       else
+               active_tbl = 1 - lq_sta->active_tbl;
+
+       tbl = &(lq_sta->lq_info[active_tbl]);
+
+       if (i < 0 || i >= RATE_COUNT)
+               i = 0;
+
+       rate = il_rates[i].plcp;
+       tbl->ant_type = il4965_first_antenna(valid_tx_ant);
+       rate |= tbl->ant_type << RATE_MCS_ANT_POS;
+
+       if (i >= IL_FIRST_CCK_RATE && i <= IL_LAST_CCK_RATE)
+               rate |= RATE_MCS_CCK_MSK;
+
+       il4965_rs_get_tbl_info_from_mcs(rate, il->band, tbl, &rate_idx);
+       if (!il4965_rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
+               il4965_rs_toggle_antenna(valid_tx_ant, &rate, tbl);
+
+       rate = il4965_rate_n_flags_from_tbl(il, tbl, rate_idx, use_green);
+       tbl->current_rate = rate;
+       il4965_rs_set_expected_tpt_table(lq_sta, tbl);
+       il4965_rs_fill_link_cmd(NULL, lq_sta, rate);
+       il->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
+       il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_SYNC, true);
+}
+
+static void
+il4965_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta,
+                  struct ieee80211_tx_rate_control *txrc)
+{
+
+       struct sk_buff *skb = txrc->skb;
+       struct ieee80211_supported_band *sband = txrc->sband;
+       struct il_priv *il __maybe_unused = (struct il_priv *)il_r;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct il_lq_sta *lq_sta = il_sta;
+       int rate_idx;
+
+       D_RATE("rate scale calculate new rate for skb\n");
+
+       /* Get max rate if user set max rate */
+       if (lq_sta) {
+               lq_sta->max_rate_idx = txrc->max_rate_idx;
+               if (sband->band == IEEE80211_BAND_5GHZ &&
+                   lq_sta->max_rate_idx != -1)
+                       lq_sta->max_rate_idx += IL_FIRST_OFDM_RATE;
+               if (lq_sta->max_rate_idx < 0 ||
+                   lq_sta->max_rate_idx >= RATE_COUNT)
+                       lq_sta->max_rate_idx = -1;
+       }
+
+       /* Treat uninitialized rate scaling data same as non-existing. */
+       if (lq_sta && !lq_sta->drv) {
+               D_RATE("Rate scaling not initialized yet.\n");
+               il_sta = NULL;
+       }
+
+       /* Send management frames and NO_ACK data using lowest rate. */
+       if (rate_control_send_low(sta, il_sta, txrc))
+               return;
+
+       if (!lq_sta)
+               return;
+
+       rate_idx = lq_sta->last_txrate_idx;
+
+       if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
+               rate_idx -= IL_FIRST_OFDM_RATE;
+               /* 6M and 9M shared same MCS idx */
+               rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0;
+               if (il4965_rs_extract_rate(lq_sta->last_rate_n_flags) >=
+                   RATE_MIMO2_6M_PLCP)
+                       rate_idx = rate_idx + MCS_IDX_PER_STREAM;
+               info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
+               if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK)
+                       info->control.rates[0].flags |=
+                           IEEE80211_TX_RC_SHORT_GI;
+               if (lq_sta->last_rate_n_flags & RATE_MCS_DUP_MSK)
+                       info->control.rates[0].flags |=
+                           IEEE80211_TX_RC_DUP_DATA;
+               if (lq_sta->last_rate_n_flags & RATE_MCS_HT40_MSK)
+                       info->control.rates[0].flags |=
+                           IEEE80211_TX_RC_40_MHZ_WIDTH;
+               if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK)
+                       info->control.rates[0].flags |=
+                           IEEE80211_TX_RC_GREEN_FIELD;
+       } else {
+               /* Check for invalid rates */
+               if (rate_idx < 0 || rate_idx >= RATE_COUNT_LEGACY ||
+                   (sband->band == IEEE80211_BAND_5GHZ &&
+                    rate_idx < IL_FIRST_OFDM_RATE))
+                       rate_idx = rate_lowest_index(sband, sta);
+               /* On valid 5 GHz rate, adjust idx */
+               else if (sband->band == IEEE80211_BAND_5GHZ)
+                       rate_idx -= IL_FIRST_OFDM_RATE;
+               info->control.rates[0].flags = 0;
+       }
+       info->control.rates[0].idx = rate_idx;
+
+}
+
+static void *
+il4965_rs_alloc_sta(void *il_rate, struct ieee80211_sta *sta, gfp_t gfp)
+{
+       struct il_station_priv *sta_priv =
+           (struct il_station_priv *)sta->drv_priv;
+       struct il_priv *il;
+
+       il = (struct il_priv *)il_rate;
+       D_RATE("create station rate scale win\n");
+
+       return &sta_priv->lq_sta;
+}
+
+/*
+ * Called after adding a new station to initialize rate scaling
+ */
+void
+il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
+{
+       int i, j;
+       struct ieee80211_hw *hw = il->hw;
+       struct ieee80211_conf *conf = &il->hw->conf;
+       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+       struct il_station_priv *sta_priv;
+       struct il_lq_sta *lq_sta;
+       struct ieee80211_supported_band *sband;
+
+       sta_priv = (struct il_station_priv *)sta->drv_priv;
+       lq_sta = &sta_priv->lq_sta;
+       sband = hw->wiphy->bands[conf->channel->band];
+
+       lq_sta->lq.sta_id = sta_id;
+
+       for (j = 0; j < LQ_SIZE; j++)
+               for (i = 0; i < RATE_COUNT; i++)
+                       il4965_rs_rate_scale_clear_win(&lq_sta->lq_info[j].
+                                                      win[i]);
+
+       lq_sta->flush_timer = 0;
+       lq_sta->supp_rates = sta->supp_rates[sband->band];
+       for (j = 0; j < LQ_SIZE; j++)
+               for (i = 0; i < RATE_COUNT; i++)
+                       il4965_rs_rate_scale_clear_win(&lq_sta->lq_info[j].
+                                                      win[i]);
+
+       D_RATE("LQ:" "*** rate scale station global init for station %d ***\n",
+              sta_id);
+       /* TODO: what is a good starting rate for STA? About middle? Maybe not
+        * the lowest or the highest rate.. Could consider using RSSI from
+        * previous packets? Need to have IEEE 802.1X auth succeed immediately
+        * after assoc.. */
+
+       lq_sta->is_dup = 0;
+       lq_sta->max_rate_idx = -1;
+       lq_sta->missed_rate_counter = IL_MISSED_RATE_MAX;
+       lq_sta->is_green = il4965_rs_use_green(sta);
+       lq_sta->active_legacy_rate = il->active_rate & ~(0x1000);
+       lq_sta->band = il->band;
+       /*
+        * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
+        * supp_rates[] does not; shift to convert format, force 9 MBits off.
+        */
+       lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1;
+       lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1;
+       lq_sta->active_siso_rate &= ~((u16) 0x2);
+       lq_sta->active_siso_rate <<= IL_FIRST_OFDM_RATE;
+
+       /* Same here */
+       lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1;
+       lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1;
+       lq_sta->active_mimo2_rate &= ~((u16) 0x2);
+       lq_sta->active_mimo2_rate <<= IL_FIRST_OFDM_RATE;
+
+       /* These values will be overridden later */
+       lq_sta->lq.general_params.single_stream_ant_msk =
+           il4965_first_antenna(il->hw_params.valid_tx_ant);
+       lq_sta->lq.general_params.dual_stream_ant_msk =
+           il->hw_params.valid_tx_ant & ~il4965_first_antenna(il->hw_params.
+                                                              valid_tx_ant);
+       if (!lq_sta->lq.general_params.dual_stream_ant_msk) {
+               lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
+       } else if (il4965_num_of_ant(il->hw_params.valid_tx_ant) == 2) {
+               lq_sta->lq.general_params.dual_stream_ant_msk =
+                   il->hw_params.valid_tx_ant;
+       }
+
+       /* as default allow aggregation for all tids */
+       lq_sta->tx_agg_tid_en = IL_AGG_ALL_TID;
+       lq_sta->drv = il;
+
+       /* Set last_txrate_idx to lowest rate */
+       lq_sta->last_txrate_idx = rate_lowest_index(sband, sta);
+       if (sband->band == IEEE80211_BAND_5GHZ)
+               lq_sta->last_txrate_idx += IL_FIRST_OFDM_RATE;
+       lq_sta->is_agg = 0;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       lq_sta->dbg_fixed_rate = 0;
+#endif
+
+       il4965_rs_initialize_lq(il, conf, sta, lq_sta);
+}
+
+static void
+il4965_rs_fill_link_cmd(struct il_priv *il, struct il_lq_sta *lq_sta,
+                       u32 new_rate)
+{
+       struct il_scale_tbl_info tbl_type;
+       int idx = 0;
+       int rate_idx;
+       int repeat_rate = 0;
+       u8 ant_toggle_cnt = 0;
+       u8 use_ht_possible = 1;
+       u8 valid_tx_ant = 0;
+       struct il_link_quality_cmd *lq_cmd = &lq_sta->lq;
+
+       /* Override starting rate (idx 0) if needed for debug purposes */
+       il4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, idx);
+
+       /* Interpret new_rate (rate_n_flags) */
+       il4965_rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type,
+                                       &rate_idx);
+
+       /* How many times should we repeat the initial rate? */
+       if (is_legacy(tbl_type.lq_type)) {
+               ant_toggle_cnt = 1;
+               repeat_rate = IL_NUMBER_TRY;
+       } else {
+               repeat_rate = IL_HT_NUMBER_TRY;
+       }
+
+       lq_cmd->general_params.mimo_delimiter =
+           is_mimo(tbl_type.lq_type) ? 1 : 0;
+
+       /* Fill 1st table entry (idx 0) */
+       lq_cmd->rs_table[idx].rate_n_flags = cpu_to_le32(new_rate);
+
+       if (il4965_num_of_ant(tbl_type.ant_type) == 1) {
+               lq_cmd->general_params.single_stream_ant_msk =
+                   tbl_type.ant_type;
+       } else if (il4965_num_of_ant(tbl_type.ant_type) == 2) {
+               lq_cmd->general_params.dual_stream_ant_msk = tbl_type.ant_type;
+       }
+       /* otherwise we don't modify the existing value */
+       idx++;
+       repeat_rate--;
+       if (il)
+               valid_tx_ant = il->hw_params.valid_tx_ant;
+
+       /* Fill rest of rate table */
+       while (idx < LINK_QUAL_MAX_RETRY_NUM) {
+               /* Repeat initial/next rate.
+                * For legacy IL_NUMBER_TRY == 1, this loop will not execute.
+                * For HT IL_HT_NUMBER_TRY == 3, this executes twice. */
+               while (repeat_rate > 0 && idx < LINK_QUAL_MAX_RETRY_NUM) {
+                       if (is_legacy(tbl_type.lq_type)) {
+                               if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
+                                       ant_toggle_cnt++;
+                               else if (il &&
+                                        il4965_rs_toggle_antenna(valid_tx_ant,
+                                                                 &new_rate,
+                                                                 &tbl_type))
+                                       ant_toggle_cnt = 1;
+                       }
+
+                       /* Override next rate if needed for debug purposes */
+                       il4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, idx);
+
+                       /* Fill next table entry */
+                       lq_cmd->rs_table[idx].rate_n_flags =
+                           cpu_to_le32(new_rate);
+                       repeat_rate--;
+                       idx++;
+               }
+
+               il4965_rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
+                                               &tbl_type, &rate_idx);
+
+               /* Indicate to uCode which entries might be MIMO.
+                * If initial rate was MIMO, this will finally end up
+                * as (IL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */
+               if (is_mimo(tbl_type.lq_type))
+                       lq_cmd->general_params.mimo_delimiter = idx;
+
+               /* Get next rate */
+               new_rate =
+                   il4965_rs_get_lower_rate(lq_sta, &tbl_type, rate_idx,
+                                            use_ht_possible);
+
+               /* How many times should we repeat the next rate? */
+               if (is_legacy(tbl_type.lq_type)) {
+                       if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
+                               ant_toggle_cnt++;
+                       else if (il &&
+                                il4965_rs_toggle_antenna(valid_tx_ant,
+                                                         &new_rate, &tbl_type))
+                               ant_toggle_cnt = 1;
+
+                       repeat_rate = IL_NUMBER_TRY;
+               } else {
+                       repeat_rate = IL_HT_NUMBER_TRY;
+               }
+
+               /* Don't allow HT rates after next pass.
+                * il4965_rs_get_lower_rate() will change type to LQ_A or LQ_G. */
+               use_ht_possible = 0;
+
+               /* Override next rate if needed for debug purposes */
+               il4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, idx);
+
+               /* Fill next table entry */
+               lq_cmd->rs_table[idx].rate_n_flags = cpu_to_le32(new_rate);
+
+               idx++;
+               repeat_rate--;
+       }
+
+       lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+       lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+
+       lq_cmd->agg_params.agg_time_limit =
+           cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
+}
+
+static void *
+il4965_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+{
+       return hw->priv;
+}
+
+/* rate scale requires free function to be implemented */
+static void
+il4965_rs_free(void *il_rate)
+{
+       return;
+}
+
+static void
+il4965_rs_free_sta(void *il_r, struct ieee80211_sta *sta, void *il_sta)
+{
+       struct il_priv *il __maybe_unused = il_r;
+
+       D_RATE("enter\n");
+       D_RATE("leave\n");
+}
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static int
+il4965_open_file_generic(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static void
+il4965_rs_dbgfs_set_mcs(struct il_lq_sta *lq_sta, u32 * rate_n_flags, int idx)
+{
+       struct il_priv *il;
+       u8 valid_tx_ant;
+       u8 ant_sel_tx;
+
+       il = lq_sta->drv;
+       valid_tx_ant = il->hw_params.valid_tx_ant;
+       if (lq_sta->dbg_fixed_rate) {
+               ant_sel_tx =
+                   ((lq_sta->
+                     dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) >>
+                    RATE_MCS_ANT_POS);
+               if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) {
+                       *rate_n_flags = lq_sta->dbg_fixed_rate;
+                       D_RATE("Fixed rate ON\n");
+               } else {
+                       lq_sta->dbg_fixed_rate = 0;
+                       IL_ERR
+                           ("Invalid antenna selection 0x%X, Valid is 0x%X\n",
+                            ant_sel_tx, valid_tx_ant);
+                       D_RATE("Fixed rate OFF\n");
+               }
+       } else {
+               D_RATE("Fixed rate OFF\n");
+       }
+}
+
+static ssize_t
+il4965_rs_sta_dbgfs_scale_table_write(struct file *file,
+                                     const char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct il_lq_sta *lq_sta = file->private_data;
+       struct il_priv *il;
+       char buf[64];
+       size_t buf_size;
+       u32 parsed_rate;
+       struct il_station_priv *sta_priv =
+           container_of(lq_sta, struct il_station_priv, lq_sta);
+       struct il_rxon_context *ctx = sta_priv->common.ctx;
+
+       il = lq_sta->drv;
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+
+       if (sscanf(buf, "%x", &parsed_rate) == 1)
+               lq_sta->dbg_fixed_rate = parsed_rate;
+       else
+               lq_sta->dbg_fixed_rate = 0;
+
+       lq_sta->active_legacy_rate = 0x0FFF;    /* 1 - 54 MBits, includes CCK */
+       lq_sta->active_siso_rate = 0x1FD0;      /* 6 - 60 MBits, no 9, no CCK */
+       lq_sta->active_mimo2_rate = 0x1FD0;     /* 6 - 60 MBits, no 9, no CCK */
+
+       D_RATE("sta_id %d rate 0x%X\n", lq_sta->lq.sta_id,
+              lq_sta->dbg_fixed_rate);
+
+       if (lq_sta->dbg_fixed_rate) {
+               il4965_rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
+               il_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC, false);
+       }
+
+       return count;
+}
+
+static ssize_t
+il4965_rs_sta_dbgfs_scale_table_read(struct file *file, char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       char *buff;
+       int desc = 0;
+       int i = 0;
+       int idx = 0;
+       ssize_t ret;
+
+       struct il_lq_sta *lq_sta = file->private_data;
+       struct il_priv *il;
+       struct il_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+
+       il = lq_sta->drv;
+       buff = kmalloc(1024, GFP_KERNEL);
+       if (!buff)
+               return -ENOMEM;
+
+       desc += sprintf(buff + desc, "sta_id %d\n", lq_sta->lq.sta_id);
+       desc +=
+           sprintf(buff + desc, "failed=%d success=%d rate=0%X\n",
+                   lq_sta->total_failed, lq_sta->total_success,
+                   lq_sta->active_legacy_rate);
+       desc +=
+           sprintf(buff + desc, "fixed rate 0x%X\n", lq_sta->dbg_fixed_rate);
+       desc +=
+           sprintf(buff + desc, "valid_tx_ant %s%s%s\n",
+                   (il->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",
+                   (il->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "",
+                   (il->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : "");
+       desc +=
+           sprintf(buff + desc, "lq type %s\n",
+                   (is_legacy(tbl->lq_type)) ? "legacy" : "HT");
+       if (is_Ht(tbl->lq_type)) {
+               desc +=
+                   sprintf(buff + desc, " %s",
+                           (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2");
+               desc +=
+                   sprintf(buff + desc, " %s",
+                           (tbl->is_ht40) ? "40MHz" : "20MHz");
+               desc +=
+                   sprintf(buff + desc, " %s %s %s\n",
+                           (tbl->is_SGI) ? "SGI" : "",
+                           (lq_sta->is_green) ? "GF enabled" : "",
+                           (lq_sta->is_agg) ? "AGG on" : "");
+       }
+       desc +=
+           sprintf(buff + desc, "last tx rate=0x%X\n",
+                   lq_sta->last_rate_n_flags);
+       desc +=
+           sprintf(buff + desc,
+                   "general:" "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n",
+                   lq_sta->lq.general_params.flags,
+                   lq_sta->lq.general_params.mimo_delimiter,
+                   lq_sta->lq.general_params.single_stream_ant_msk,
+                   lq_sta->lq.general_params.dual_stream_ant_msk);
+
+       desc +=
+           sprintf(buff + desc,
+                   "agg:"
+                   "time_limit=%d dist_start_th=%d frame_cnt_limit=%d\n",
+                   le16_to_cpu(lq_sta->lq.agg_params.agg_time_limit),
+                   lq_sta->lq.agg_params.agg_dis_start_th,
+                   lq_sta->lq.agg_params.agg_frame_cnt_limit);
+
+       desc +=
+           sprintf(buff + desc,
+                   "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n",
+                   lq_sta->lq.general_params.start_rate_idx[0],
+                   lq_sta->lq.general_params.start_rate_idx[1],
+                   lq_sta->lq.general_params.start_rate_idx[2],
+                   lq_sta->lq.general_params.start_rate_idx[3]);
+
+       for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+               idx =
+                   il4965_hwrate_to_plcp_idx(le32_to_cpu
+                                             (lq_sta->lq.rs_table[i].
+                                              rate_n_flags));
+               if (is_legacy(tbl->lq_type)) {
+                       desc +=
+                           sprintf(buff + desc, " rate[%d] 0x%X %smbps\n", i,
+                                   le32_to_cpu(lq_sta->lq.rs_table[i].
+                                               rate_n_flags),
+                                   il_rate_mcs[idx].mbps);
+               } else {
+                       desc +=
+                           sprintf(buff + desc, " rate[%d] 0x%X %smbps (%s)\n",
+                                   i,
+                                   le32_to_cpu(lq_sta->lq.rs_table[i].
+                                               rate_n_flags),
+                                   il_rate_mcs[idx].mbps,
+                                   il_rate_mcs[idx].mcs);
+               }
+       }
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+       kfree(buff);
+       return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
+       .write = il4965_rs_sta_dbgfs_scale_table_write,
+       .read = il4965_rs_sta_dbgfs_scale_table_read,
+       .open = il4965_open_file_generic,
+       .llseek = default_llseek,
+};
+
+static ssize_t
+il4965_rs_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       char *buff;
+       int desc = 0;
+       int i, j;
+       ssize_t ret;
+
+       struct il_lq_sta *lq_sta = file->private_data;
+
+       buff = kmalloc(1024, GFP_KERNEL);
+       if (!buff)
+               return -ENOMEM;
+
+       for (i = 0; i < LQ_SIZE; i++) {
+               desc +=
+                   sprintf(buff + desc,
+                           "%s type=%d SGI=%d HT40=%d DUP=%d GF=%d\n"
+                           "rate=0x%X\n", lq_sta->active_tbl == i ? "*" : "x",
+                           lq_sta->lq_info[i].lq_type,
+                           lq_sta->lq_info[i].is_SGI,
+                           lq_sta->lq_info[i].is_ht40,
+                           lq_sta->lq_info[i].is_dup, lq_sta->is_green,
+                           lq_sta->lq_info[i].current_rate);
+               for (j = 0; j < RATE_COUNT; j++) {
+                       desc +=
+                           sprintf(buff + desc,
+                                   "counter=%d success=%d %%=%d\n",
+                                   lq_sta->lq_info[i].win[j].counter,
+                                   lq_sta->lq_info[i].win[j].success_counter,
+                                   lq_sta->lq_info[i].win[j].success_ratio);
+               }
+       }
+       ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+       kfree(buff);
+       return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
+       .read = il4965_rs_sta_dbgfs_stats_table_read,
+       .open = il4965_open_file_generic,
+       .llseek = default_llseek,
+};
+
+static ssize_t
+il4965_rs_sta_dbgfs_rate_scale_data_read(struct file *file,
+                                        char __user *user_buf, size_t count,
+                                        loff_t *ppos)
+{
+       char buff[120];
+       int desc = 0;
+       struct il_lq_sta *lq_sta = file->private_data;
+       struct il_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+
+       if (is_Ht(tbl->lq_type))
+               desc +=
+                   sprintf(buff + desc, "Bit Rate= %d Mb/s\n",
+                           tbl->expected_tpt[lq_sta->last_txrate_idx]);
+       else
+               desc +=
+                   sprintf(buff + desc, "Bit Rate= %d Mb/s\n",
+                           il_rates[lq_sta->last_txrate_idx].ieee >> 1);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+}
+
+static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
+       .read = il4965_rs_sta_dbgfs_rate_scale_data_read,
+       .open = il4965_open_file_generic,
+       .llseek = default_llseek,
+};
+
+static void
+il4965_rs_add_debugfs(void *il, void *il_sta, struct dentry *dir)
+{
+       struct il_lq_sta *lq_sta = il_sta;
+       lq_sta->rs_sta_dbgfs_scale_table_file =
+           debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir,
+                               lq_sta, &rs_sta_dbgfs_scale_table_ops);
+       lq_sta->rs_sta_dbgfs_stats_table_file =
+           debugfs_create_file("rate_stats_table", S_IRUSR, dir, lq_sta,
+                               &rs_sta_dbgfs_stats_table_ops);
+       lq_sta->rs_sta_dbgfs_rate_scale_data_file =
+           debugfs_create_file("rate_scale_data", S_IRUSR, dir, lq_sta,
+                               &rs_sta_dbgfs_rate_scale_data_ops);
+       lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
+           debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
+                             &lq_sta->tx_agg_tid_en);
+
+}
+
+static void
+il4965_rs_remove_debugfs(void *il, void *il_sta)
+{
+       struct il_lq_sta *lq_sta = il_sta;
+       debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
+       debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
+       debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file);
+       debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
+}
+#endif
+
+/*
+ * Initialization of rate scaling information is done by driver after
+ * the station is added. Since mac80211 calls this function before a
+ * station is added we ignore it.
+ */
+static void
+il4965_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
+                        struct ieee80211_sta *sta, void *il_sta)
+{
+}
+
+static struct rate_control_ops rs_4965_ops = {
+       .module = NULL,
+       .name = IL4965_RS_NAME,
+       .tx_status = il4965_rs_tx_status,
+       .get_rate = il4965_rs_get_rate,
+       .rate_init = il4965_rs_rate_init_stub,
+       .alloc = il4965_rs_alloc,
+       .free = il4965_rs_free,
+       .alloc_sta = il4965_rs_alloc_sta,
+       .free_sta = il4965_rs_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+       .add_sta_debugfs = il4965_rs_add_debugfs,
+       .remove_sta_debugfs = il4965_rs_remove_debugfs,
+#endif
+};
+
+int
+il4965_rate_control_register(void)
+{
+       return ieee80211_rate_control_register(&rs_4965_ops);
+}
+
+void
+il4965_rate_control_unregister(void)
+{
+       ieee80211_rate_control_unregister(&rs_4965_ops);
+}
diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c
new file mode 100644 (file)
index 0000000..84c54dc
--- /dev/null
@@ -0,0 +1,2421 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "common.h"
+#include "4965.h"
+
+/**
+ * il_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
+il4965_verify_inst_sparse(struct il_priv *il, __le32 * image, u32 len)
+{
+       u32 val;
+       int ret = 0;
+       u32 errcnt = 0;
+       u32 i;
+
+       D_INFO("ucode inst image size is %u\n", len);
+
+       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 IL_DL_IO is set */
+               il_wr(il, HBUS_TARG_MEM_RADDR, i + IL4965_RTC_INST_LOWER_BOUND);
+               val = _il_rd(il, HBUS_TARG_MEM_RDAT);
+               if (val != le32_to_cpu(*image)) {
+                       ret = -EIO;
+                       errcnt++;
+                       if (errcnt >= 3)
+                               break;
+               }
+       }
+
+       return ret;
+}
+
+/**
+ * il4965_verify_inst_full - verify runtime uCode image in card vs. host,
+ *     looking at all data.
+ */
+static int
+il4965_verify_inst_full(struct il_priv *il, __le32 * image, u32 len)
+{
+       u32 val;
+       u32 save_len = len;
+       int ret = 0;
+       u32 errcnt;
+
+       D_INFO("ucode inst image size is %u\n", len);
+
+       il_wr(il, HBUS_TARG_MEM_RADDR, IL4965_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 IL_DL_IO is set */
+               val = _il_rd(il, HBUS_TARG_MEM_RDAT);
+               if (val != le32_to_cpu(*image)) {
+                       IL_ERR("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));
+                       ret = -EIO;
+                       errcnt++;
+                       if (errcnt >= 20)
+                               break;
+               }
+       }
+
+       if (!errcnt)
+               D_INFO("ucode image in INSTRUCTION memory is good\n");
+
+       return ret;
+}
+
+/**
+ * il4965_verify_ucode - determine which instruction image is in SRAM,
+ *    and verify its contents
+ */
+int
+il4965_verify_ucode(struct il_priv *il)
+{
+       __le32 *image;
+       u32 len;
+       int ret;
+
+       /* Try bootstrap */
+       image = (__le32 *) il->ucode_boot.v_addr;
+       len = il->ucode_boot.len;
+       ret = il4965_verify_inst_sparse(il, image, len);
+       if (!ret) {
+               D_INFO("Bootstrap uCode is good in inst SRAM\n");
+               return 0;
+       }
+
+       /* Try initialize */
+       image = (__le32 *) il->ucode_init.v_addr;
+       len = il->ucode_init.len;
+       ret = il4965_verify_inst_sparse(il, image, len);
+       if (!ret) {
+               D_INFO("Initialize uCode is good in inst SRAM\n");
+               return 0;
+       }
+
+       /* Try runtime/protocol */
+       image = (__le32 *) il->ucode_code.v_addr;
+       len = il->ucode_code.len;
+       ret = il4965_verify_inst_sparse(il, image, len);
+       if (!ret) {
+               D_INFO("Runtime uCode is good in inst SRAM\n");
+               return 0;
+       }
+
+       IL_ERR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
+
+       /* Since nothing seems to match, show first several data entries in
+        * instruction SRAM, so maybe visual inspection will give a clue.
+        * Selection of bootstrap image (vs. other images) is arbitrary. */
+       image = (__le32 *) il->ucode_boot.v_addr;
+       len = il->ucode_boot.len;
+       ret = il4965_verify_inst_full(il, image, len);
+
+       return ret;
+}
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+******************************************************************************/
+
+/*
+ * The device's EEPROM semaphore prevents conflicts between driver and uCode
+ * when accessing the EEPROM; each access is a series of pulses to/from the
+ * EEPROM chip, not a single event, so even reads could conflict if they
+ * weren't arbitrated by the semaphore.
+ */
+int
+il4965_eeprom_acquire_semaphore(struct il_priv *il)
+{
+       u16 count;
+       int ret;
+
+       for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
+               /* Request semaphore */
+               il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                          CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+               /* See if we got it */
+               ret =
+                   _il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
+                                CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+                                CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+                                EEPROM_SEM_TIMEOUT);
+               if (ret >= 0)
+                       return ret;
+       }
+
+       return ret;
+}
+
+void
+il4965_eeprom_release_semaphore(struct il_priv *il)
+{
+       il_clear_bit(il, CSR_HW_IF_CONFIG_REG,
+                    CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+}
+
+int
+il4965_eeprom_check_version(struct il_priv *il)
+{
+       u16 eeprom_ver;
+       u16 calib_ver;
+
+       eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION);
+       calib_ver = il_eeprom_query16(il, EEPROM_4965_CALIB_VERSION_OFFSET);
+
+       if (eeprom_ver < il->cfg->eeprom_ver ||
+           calib_ver < il->cfg->eeprom_calib_ver)
+               goto err;
+
+       IL_INFO("device EEPROM VER=0x%x, CALIB=0x%x\n", eeprom_ver, calib_ver);
+
+       return 0;
+err:
+       IL_ERR("Unsupported (too old) EEPROM VER=0x%x < 0x%x "
+              "CALIB=0x%x < 0x%x\n", eeprom_ver, il->cfg->eeprom_ver,
+              calib_ver, il->cfg->eeprom_calib_ver);
+       return -EINVAL;
+
+}
+
+void
+il4965_eeprom_get_mac(const struct il_priv *il, u8 * mac)
+{
+       const u8 *addr = il_eeprom_query_addr(il,
+                                             EEPROM_MAC_ADDRESS);
+       memcpy(mac, addr, ETH_ALEN);
+}
+
+/* Send led command */
+static int
+il4965_send_led_cmd(struct il_priv *il, struct il_led_cmd *led_cmd)
+{
+       struct il_host_cmd cmd = {
+               .id = C_LEDS,
+               .len = sizeof(struct il_led_cmd),
+               .data = led_cmd,
+               .flags = CMD_ASYNC,
+               .callback = NULL,
+       };
+       u32 reg;
+
+       reg = _il_rd(il, CSR_LED_REG);
+       if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
+               _il_wr(il, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
+
+       return il_send_cmd(il, &cmd);
+}
+
+/* Set led register off */
+void
+il4965_led_enable(struct il_priv *il)
+{
+       _il_wr(il, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
+}
+
+const struct il_led_ops il4965_led_ops = {
+       .cmd = il4965_send_led_cmd,
+};
+
+static int il4965_send_tx_power(struct il_priv *il);
+static int il4965_hw_get_temperature(struct il_priv *il);
+
+/* Highest firmware API version supported */
+#define IL4965_UCODE_API_MAX 2
+
+/* Lowest firmware API version supported */
+#define IL4965_UCODE_API_MIN 2
+
+#define IL4965_FW_PRE "iwlwifi-4965-"
+#define _IL4965_MODULE_FIRMWARE(api) IL4965_FW_PRE #api ".ucode"
+#define IL4965_MODULE_FIRMWARE(api) _IL4965_MODULE_FIRMWARE(api)
+
+/* check contents of special bootstrap uCode SRAM */
+static int
+il4965_verify_bsm(struct il_priv *il)
+{
+       __le32 *image = il->ucode_boot.v_addr;
+       u32 len = il->ucode_boot.len;
+       u32 reg;
+       u32 val;
+
+       D_INFO("Begin verify bsm\n");
+
+       /* verify BSM SRAM contents */
+       val = il_rd_prph(il, BSM_WR_DWCOUNT_REG);
+       for (reg = BSM_SRAM_LOWER_BOUND; reg < BSM_SRAM_LOWER_BOUND + len;
+            reg += sizeof(u32), image++) {
+               val = il_rd_prph(il, reg);
+               if (val != le32_to_cpu(*image)) {
+                       IL_ERR("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;
+               }
+       }
+
+       D_INFO("BSM bootstrap uCode image OK\n");
+
+       return 0;
+}
+
+/**
+ * il4965_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
+il4965_load_bsm(struct il_priv *il)
+{
+       __le32 *image = il->ucode_boot.v_addr;
+       u32 len = il->ucode_boot.len;
+       dma_addr_t pinst;
+       dma_addr_t pdata;
+       u32 inst_len;
+       u32 data_len;
+       int i;
+       u32 done;
+       u32 reg_offset;
+       int ret;
+
+       D_INFO("Begin load bsm\n");
+
+       il->ucode_type = UCODE_RT;
+
+       /* make sure bootstrap program is no larger than BSM's SRAM size */
+       if (len > IL49_MAX_BSM_SIZE)
+               return -EINVAL;
+
+       /* Tell bootstrap uCode where to find the "Initialize" uCode
+        *   in host DRAM ... host DRAM physical address bits 35:4 for 4965.
+        * NOTE:  il_init_alive_start() will replace these values,
+        *        after the "initialize" uCode has run, to point to
+        *        runtime/protocol instructions and backup data cache.
+        */
+       pinst = il->ucode_init.p_addr >> 4;
+       pdata = il->ucode_init_data.p_addr >> 4;
+       inst_len = il->ucode_init.len;
+       data_len = il->ucode_init_data.len;
+
+       il_wr_prph(il, BSM_DRAM_INST_PTR_REG, pinst);
+       il_wr_prph(il, BSM_DRAM_DATA_PTR_REG, pdata);
+       il_wr_prph(il, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+       il_wr_prph(il, 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++)
+               _il_wr_prph(il, reg_offset, le32_to_cpu(*image));
+
+       ret = il4965_verify_bsm(il);
+       if (ret)
+               return ret;
+
+       /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
+       il_wr_prph(il, BSM_WR_MEM_SRC_REG, 0x0);
+       il_wr_prph(il, BSM_WR_MEM_DST_REG, IL49_RTC_INST_LOWER_BOUND);
+       il_wr_prph(il, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+
+       /* Load bootstrap code into instruction SRAM now,
+        *   to prepare to load "initialize" uCode */
+       il_wr_prph(il, 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 = il_rd_prph(il, BSM_WR_CTRL_REG);
+               if (!(done & BSM_WR_CTRL_REG_BIT_START))
+                       break;
+               udelay(10);
+       }
+       if (i < 100)
+               D_INFO("BSM write complete, poll %d iterations\n", i);
+       else {
+               IL_ERR("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) */
+       il_wr_prph(il, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
+
+       return 0;
+}
+
+/**
+ * il4965_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
+il4965_set_ucode_ptrs(struct il_priv *il)
+{
+       dma_addr_t pinst;
+       dma_addr_t pdata;
+       int ret = 0;
+
+       /* bits 35:4 for 4965 */
+       pinst = il->ucode_code.p_addr >> 4;
+       pdata = il->ucode_data_backup.p_addr >> 4;
+
+       /* Tell bootstrap uCode where to find image to load */
+       il_wr_prph(il, BSM_DRAM_INST_PTR_REG, pinst);
+       il_wr_prph(il, BSM_DRAM_DATA_PTR_REG, pdata);
+       il_wr_prph(il, BSM_DRAM_DATA_BYTECOUNT_REG, il->ucode_data.len);
+
+       /* Inst byte count must be last to set up, bit 31 signals uCode
+        *   that all new ptr/size info is in place */
+       il_wr_prph(il, BSM_DRAM_INST_BYTECOUNT_REG,
+                  il->ucode_code.len | BSM_DRAM_INST_LOAD);
+       D_INFO("Runtime uCode pointers are set.\n");
+
+       return ret;
+}
+
+/**
+ * il4965_init_alive_start - Called after N_ALIVE notification received
+ *
+ * Called after N_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 il
+ *   (3945 does not contain this data).
+ *
+ * Tell "initialize" uCode to go ahead and load the runtime uCode.
+*/
+static void
+il4965_init_alive_start(struct il_priv *il)
+{
+       /* 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 (il4965_verify_ucode(il)) {
+               /* Runtime instruction load was bad;
+                * take it all the way back down so we can try again */
+               D_INFO("Bad \"initialize\" uCode load.\n");
+               goto restart;
+       }
+
+       /* Calculate temperature */
+       il->temperature = il4965_hw_get_temperature(il);
+
+       /* Send pointers to protocol/runtime uCode image ... init code will
+        * load and launch runtime uCode, which will send us another "Alive"
+        * notification. */
+       D_INFO("Initialization Alive received.\n");
+       if (il4965_set_ucode_ptrs(il)) {
+               /* Runtime instruction load won't happen;
+                * take it all the way back down so we can try again */
+               D_INFO("Couldn't set up uCode pointers.\n");
+               goto restart;
+       }
+       return;
+
+restart:
+       queue_work(il->workqueue, &il->restart);
+}
+
+static bool
+iw4965_is_ht40_channel(__le32 rxon_flags)
+{
+       int chan_mod =
+           le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK) >>
+           RXON_FLG_CHANNEL_MODE_POS;
+       return (chan_mod == CHANNEL_MODE_PURE_40 ||
+               chan_mod == CHANNEL_MODE_MIXED);
+}
+
+static void
+il4965_nic_config(struct il_priv *il)
+{
+       unsigned long flags;
+       u16 radio_cfg;
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       radio_cfg = il_eeprom_query16(il, EEPROM_RADIO_CONFIG);
+
+       /* write radio config values to register */
+       if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) == EEPROM_4965_RF_CFG_TYPE_MAX)
+               il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                          EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
+                          EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
+                          EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+
+       /* set CSR_HW_CONFIG_REG for uCode use */
+       il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                  CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
+                  CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+
+       il->calib_info =
+           (struct il_eeprom_calib_info *)
+           il_eeprom_query_addr(il, EEPROM_4965_CALIB_TXPOWER_OFFSET);
+
+       spin_unlock_irqrestore(&il->lock, flags);
+}
+
+/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
+ * Called after every association, but this runs only once!
+ *  ... once chain noise is calibrated the first time, it's good forever.  */
+static void
+il4965_chain_noise_reset(struct il_priv *il)
+{
+       struct il_chain_noise_data *data = &(il->chain_noise_data);
+
+       if (data->state == IL_CHAIN_NOISE_ALIVE && il_is_any_associated(il)) {
+               struct il_calib_diff_gain_cmd cmd;
+
+               /* clear data for chain noise calibration algorithm */
+               data->chain_noise_a = 0;
+               data->chain_noise_b = 0;
+               data->chain_noise_c = 0;
+               data->chain_signal_a = 0;
+               data->chain_signal_b = 0;
+               data->chain_signal_c = 0;
+               data->beacon_count = 0;
+
+               memset(&cmd, 0, sizeof(cmd));
+               cmd.hdr.op_code = IL_PHY_CALIBRATE_DIFF_GAIN_CMD;
+               cmd.diff_gain_a = 0;
+               cmd.diff_gain_b = 0;
+               cmd.diff_gain_c = 0;
+               if (il_send_cmd_pdu(il, C_PHY_CALIBRATION, sizeof(cmd), &cmd))
+                       IL_ERR("Could not send C_PHY_CALIBRATION\n");
+               data->state = IL_CHAIN_NOISE_ACCUMULATE;
+               D_CALIB("Run chain_noise_calibrate\n");
+       }
+}
+
+static struct il_sensitivity_ranges il4965_sensitivity = {
+       .min_nrg_cck = 97,
+       .max_nrg_cck = 0,       /* not used, set to 0 */
+
+       .auto_corr_min_ofdm = 85,
+       .auto_corr_min_ofdm_mrc = 170,
+       .auto_corr_min_ofdm_x1 = 105,
+       .auto_corr_min_ofdm_mrc_x1 = 220,
+
+       .auto_corr_max_ofdm = 120,
+       .auto_corr_max_ofdm_mrc = 210,
+       .auto_corr_max_ofdm_x1 = 140,
+       .auto_corr_max_ofdm_mrc_x1 = 270,
+
+       .auto_corr_min_cck = 125,
+       .auto_corr_max_cck = 200,
+       .auto_corr_min_cck_mrc = 200,
+       .auto_corr_max_cck_mrc = 400,
+
+       .nrg_th_cck = 100,
+       .nrg_th_ofdm = 100,
+
+       .barker_corr_th_min = 190,
+       .barker_corr_th_min_mrc = 390,
+       .nrg_th_cca = 62,
+};
+
+static void
+il4965_set_ct_threshold(struct il_priv *il)
+{
+       /* want Kelvin */
+       il->hw_params.ct_kill_threshold =
+           CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY);
+}
+
+/**
+ * il4965_hw_set_hw_params
+ *
+ * Called when initializing driver
+ */
+static int
+il4965_hw_set_hw_params(struct il_priv *il)
+{
+       if (il->cfg->mod_params->num_of_queues >= IL_MIN_NUM_QUEUES &&
+           il->cfg->mod_params->num_of_queues <= IL49_NUM_QUEUES)
+               il->cfg->base_params->num_of_queues =
+                   il->cfg->mod_params->num_of_queues;
+
+       il->hw_params.max_txq_num = il->cfg->base_params->num_of_queues;
+       il->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
+       il->hw_params.scd_bc_tbls_size =
+           il->cfg->base_params->num_of_queues *
+           sizeof(struct il4965_scd_bc_tbl);
+       il->hw_params.tfd_size = sizeof(struct il_tfd);
+       il->hw_params.max_stations = IL4965_STATION_COUNT;
+       il->ctx.bcast_sta_id = IL4965_BROADCAST_ID;
+       il->hw_params.max_data_size = IL49_RTC_DATA_SIZE;
+       il->hw_params.max_inst_size = IL49_RTC_INST_SIZE;
+       il->hw_params.max_bsm_size = BSM_SRAM_SIZE;
+       il->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ);
+
+       il->hw_params.rx_wrt_ptr_reg = FH49_RSCSR_CHNL0_WPTR;
+
+       il->hw_params.tx_chains_num = il4965_num_of_ant(il->cfg->valid_tx_ant);
+       il->hw_params.rx_chains_num = il4965_num_of_ant(il->cfg->valid_rx_ant);
+       il->hw_params.valid_tx_ant = il->cfg->valid_tx_ant;
+       il->hw_params.valid_rx_ant = il->cfg->valid_rx_ant;
+
+       il4965_set_ct_threshold(il);
+
+       il->hw_params.sens = &il4965_sensitivity;
+       il->hw_params.beacon_time_tsf_bits = IL4965_EXT_BEACON_TIME_POS;
+
+       return 0;
+}
+
+static s32
+il4965_math_div_round(s32 num, s32 denom, s32 * res)
+{
+       s32 sign = 1;
+
+       if (num < 0) {
+               sign = -sign;
+               num = -num;
+       }
+       if (denom < 0) {
+               sign = -sign;
+               denom = -denom;
+       }
+       *res = 1;
+       *res = ((num * 2 + denom) / (denom * 2)) * sign;
+
+       return 1;
+}
+
+/**
+ * il4965_get_voltage_compensation - Power supply voltage comp for txpower
+ *
+ * Determines power supply voltage compensation for txpower calculations.
+ * Returns number of 1/2-dB steps to subtract from gain table idx,
+ * to compensate for difference between power supply voltage during
+ * factory measurements, vs. current power supply voltage.
+ *
+ * Voltage indication is higher for lower voltage.
+ * Lower voltage requires more gain (lower gain table idx).
+ */
+static s32
+il4965_get_voltage_compensation(s32 eeprom_voltage, s32 current_voltage)
+{
+       s32 comp = 0;
+
+       if (TX_POWER_IL_ILLEGAL_VOLTAGE == eeprom_voltage ||
+           TX_POWER_IL_ILLEGAL_VOLTAGE == current_voltage)
+               return 0;
+
+       il4965_math_div_round(current_voltage - eeprom_voltage,
+                             TX_POWER_IL_VOLTAGE_CODES_PER_03V, &comp);
+
+       if (current_voltage > eeprom_voltage)
+               comp *= 2;
+       if ((comp < -2) || (comp > 2))
+               comp = 0;
+
+       return comp;
+}
+
+static s32
+il4965_get_tx_atten_grp(u16 channel)
+{
+       if (channel >= CALIB_IL_TX_ATTEN_GR5_FCH &&
+           channel <= CALIB_IL_TX_ATTEN_GR5_LCH)
+               return CALIB_CH_GROUP_5;
+
+       if (channel >= CALIB_IL_TX_ATTEN_GR1_FCH &&
+           channel <= CALIB_IL_TX_ATTEN_GR1_LCH)
+               return CALIB_CH_GROUP_1;
+
+       if (channel >= CALIB_IL_TX_ATTEN_GR2_FCH &&
+           channel <= CALIB_IL_TX_ATTEN_GR2_LCH)
+               return CALIB_CH_GROUP_2;
+
+       if (channel >= CALIB_IL_TX_ATTEN_GR3_FCH &&
+           channel <= CALIB_IL_TX_ATTEN_GR3_LCH)
+               return CALIB_CH_GROUP_3;
+
+       if (channel >= CALIB_IL_TX_ATTEN_GR4_FCH &&
+           channel <= CALIB_IL_TX_ATTEN_GR4_LCH)
+               return CALIB_CH_GROUP_4;
+
+       return -EINVAL;
+}
+
+static u32
+il4965_get_sub_band(const struct il_priv *il, u32 channel)
+{
+       s32 b = -1;
+
+       for (b = 0; b < EEPROM_TX_POWER_BANDS; b++) {
+               if (il->calib_info->band_info[b].ch_from == 0)
+                       continue;
+
+               if (channel >= il->calib_info->band_info[b].ch_from &&
+                   channel <= il->calib_info->band_info[b].ch_to)
+                       break;
+       }
+
+       return b;
+}
+
+static s32
+il4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
+{
+       s32 val;
+
+       if (x2 == x1)
+               return y1;
+       else {
+               il4965_math_div_round((x2 - x) * (y1 - y2), (x2 - x1), &val);
+               return val + y2;
+       }
+}
+
+/**
+ * il4965_interpolate_chan - Interpolate factory measurements for one channel
+ *
+ * Interpolates factory measurements from the two sample channels within a
+ * sub-band, to apply to channel of interest.  Interpolation is proportional to
+ * differences in channel frequencies, which is proportional to differences
+ * in channel number.
+ */
+static int
+il4965_interpolate_chan(struct il_priv *il, u32 channel,
+                       struct il_eeprom_calib_ch_info *chan_info)
+{
+       s32 s = -1;
+       u32 c;
+       u32 m;
+       const struct il_eeprom_calib_measure *m1;
+       const struct il_eeprom_calib_measure *m2;
+       struct il_eeprom_calib_measure *omeas;
+       u32 ch_i1;
+       u32 ch_i2;
+
+       s = il4965_get_sub_band(il, channel);
+       if (s >= EEPROM_TX_POWER_BANDS) {
+               IL_ERR("Tx Power can not find channel %d\n", channel);
+               return -1;
+       }
+
+       ch_i1 = il->calib_info->band_info[s].ch1.ch_num;
+       ch_i2 = il->calib_info->band_info[s].ch2.ch_num;
+       chan_info->ch_num = (u8) channel;
+
+       D_TXPOWER("channel %d subband %d factory cal ch %d & %d\n", channel, s,
+                 ch_i1, ch_i2);
+
+       for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) {
+               for (m = 0; m < EEPROM_TX_POWER_MEASUREMENTS; m++) {
+                       m1 = &(il->calib_info->band_info[s].ch1.
+                              measurements[c][m]);
+                       m2 = &(il->calib_info->band_info[s].ch2.
+                              measurements[c][m]);
+                       omeas = &(chan_info->measurements[c][m]);
+
+                       omeas->actual_pow =
+                           (u8) il4965_interpolate_value(channel, ch_i1,
+                                                         m1->actual_pow, ch_i2,
+                                                         m2->actual_pow);
+                       omeas->gain_idx =
+                           (u8) il4965_interpolate_value(channel, ch_i1,
+                                                         m1->gain_idx, ch_i2,
+                                                         m2->gain_idx);
+                       omeas->temperature =
+                           (u8) il4965_interpolate_value(channel, ch_i1,
+                                                         m1->temperature,
+                                                         ch_i2,
+                                                         m2->temperature);
+                       omeas->pa_det =
+                           (s8) il4965_interpolate_value(channel, ch_i1,
+                                                         m1->pa_det, ch_i2,
+                                                         m2->pa_det);
+
+                       D_TXPOWER("chain %d meas %d AP1=%d AP2=%d AP=%d\n", c,
+                                 m, m1->actual_pow, m2->actual_pow,
+                                 omeas->actual_pow);
+                       D_TXPOWER("chain %d meas %d NI1=%d NI2=%d NI=%d\n", c,
+                                 m, m1->gain_idx, m2->gain_idx,
+                                 omeas->gain_idx);
+                       D_TXPOWER("chain %d meas %d PA1=%d PA2=%d PA=%d\n", c,
+                                 m, m1->pa_det, m2->pa_det, omeas->pa_det);
+                       D_TXPOWER("chain %d meas %d  T1=%d  T2=%d  T=%d\n", c,
+                                 m, m1->temperature, m2->temperature,
+                                 omeas->temperature);
+               }
+       }
+
+       return 0;
+}
+
+/* bit-rate-dependent table to prevent Tx distortion, in half-dB units,
+ * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. */
+static s32 back_off_table[] = {
+       10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 20 MHz */
+       10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 20 MHz */
+       10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 40 MHz */
+       10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 40 MHz */
+       10                      /* CCK */
+};
+
+/* Thermal compensation values for txpower for various frequency ranges ...
+ *   ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */
+static struct il4965_txpower_comp_entry {
+       s32 degrees_per_05db_a;
+       s32 degrees_per_05db_a_denom;
+} tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = {
+       {
+       9, 2},                  /* group 0 5.2, ch  34-43 */
+       {
+       4, 1},                  /* group 1 5.2, ch  44-70 */
+       {
+       4, 1},                  /* group 2 5.2, ch  71-124 */
+       {
+       4, 1},                  /* group 3 5.2, ch 125-200 */
+       {
+       3, 1}                   /* group 4 2.4, ch   all */
+};
+
+static s32
+get_min_power_idx(s32 rate_power_idx, u32 band)
+{
+       if (!band) {
+               if ((rate_power_idx & 7) <= 4)
+                       return MIN_TX_GAIN_IDX_52GHZ_EXT;
+       }
+       return MIN_TX_GAIN_IDX;
+}
+
+struct gain_entry {
+       u8 dsp;
+       u8 radio;
+};
+
+static const struct gain_entry gain_table[2][108] = {
+       /* 5.2GHz power gain idx table */
+       {
+        {123, 0x3F},           /* highest txpower */
+        {117, 0x3F},
+        {110, 0x3F},
+        {104, 0x3F},
+        {98, 0x3F},
+        {110, 0x3E},
+        {104, 0x3E},
+        {98, 0x3E},
+        {110, 0x3D},
+        {104, 0x3D},
+        {98, 0x3D},
+        {110, 0x3C},
+        {104, 0x3C},
+        {98, 0x3C},
+        {110, 0x3B},
+        {104, 0x3B},
+        {98, 0x3B},
+        {110, 0x3A},
+        {104, 0x3A},
+        {98, 0x3A},
+        {110, 0x39},
+        {104, 0x39},
+        {98, 0x39},
+        {110, 0x38},
+        {104, 0x38},
+        {98, 0x38},
+        {110, 0x37},
+        {104, 0x37},
+        {98, 0x37},
+        {110, 0x36},
+        {104, 0x36},
+        {98, 0x36},
+        {110, 0x35},
+        {104, 0x35},
+        {98, 0x35},
+        {110, 0x34},
+        {104, 0x34},
+        {98, 0x34},
+        {110, 0x33},
+        {104, 0x33},
+        {98, 0x33},
+        {110, 0x32},
+        {104, 0x32},
+        {98, 0x32},
+        {110, 0x31},
+        {104, 0x31},
+        {98, 0x31},
+        {110, 0x30},
+        {104, 0x30},
+        {98, 0x30},
+        {110, 0x25},
+        {104, 0x25},
+        {98, 0x25},
+        {110, 0x24},
+        {104, 0x24},
+        {98, 0x24},
+        {110, 0x23},
+        {104, 0x23},
+        {98, 0x23},
+        {110, 0x22},
+        {104, 0x18},
+        {98, 0x18},
+        {110, 0x17},
+        {104, 0x17},
+        {98, 0x17},
+        {110, 0x16},
+        {104, 0x16},
+        {98, 0x16},
+        {110, 0x15},
+        {104, 0x15},
+        {98, 0x15},
+        {110, 0x14},
+        {104, 0x14},
+        {98, 0x14},
+        {110, 0x13},
+        {104, 0x13},
+        {98, 0x13},
+        {110, 0x12},
+        {104, 0x08},
+        {98, 0x08},
+        {110, 0x07},
+        {104, 0x07},
+        {98, 0x07},
+        {110, 0x06},
+        {104, 0x06},
+        {98, 0x06},
+        {110, 0x05},
+        {104, 0x05},
+        {98, 0x05},
+        {110, 0x04},
+        {104, 0x04},
+        {98, 0x04},
+        {110, 0x03},
+        {104, 0x03},
+        {98, 0x03},
+        {110, 0x02},
+        {104, 0x02},
+        {98, 0x02},
+        {110, 0x01},
+        {104, 0x01},
+        {98, 0x01},
+        {110, 0x00},
+        {104, 0x00},
+        {98, 0x00},
+        {93, 0x00},
+        {88, 0x00},
+        {83, 0x00},
+        {78, 0x00},
+        },
+       /* 2.4GHz power gain idx table */
+       {
+        {110, 0x3f},           /* highest txpower */
+        {104, 0x3f},
+        {98, 0x3f},
+        {110, 0x3e},
+        {104, 0x3e},
+        {98, 0x3e},
+        {110, 0x3d},
+        {104, 0x3d},
+        {98, 0x3d},
+        {110, 0x3c},
+        {104, 0x3c},
+        {98, 0x3c},
+        {110, 0x3b},
+        {104, 0x3b},
+        {98, 0x3b},
+        {110, 0x3a},
+        {104, 0x3a},
+        {98, 0x3a},
+        {110, 0x39},
+        {104, 0x39},
+        {98, 0x39},
+        {110, 0x38},
+        {104, 0x38},
+        {98, 0x38},
+        {110, 0x37},
+        {104, 0x37},
+        {98, 0x37},
+        {110, 0x36},
+        {104, 0x36},
+        {98, 0x36},
+        {110, 0x35},
+        {104, 0x35},
+        {98, 0x35},
+        {110, 0x34},
+        {104, 0x34},
+        {98, 0x34},
+        {110, 0x33},
+        {104, 0x33},
+        {98, 0x33},
+        {110, 0x32},
+        {104, 0x32},
+        {98, 0x32},
+        {110, 0x31},
+        {104, 0x31},
+        {98, 0x31},
+        {110, 0x30},
+        {104, 0x30},
+        {98, 0x30},
+        {110, 0x6},
+        {104, 0x6},
+        {98, 0x6},
+        {110, 0x5},
+        {104, 0x5},
+        {98, 0x5},
+        {110, 0x4},
+        {104, 0x4},
+        {98, 0x4},
+        {110, 0x3},
+        {104, 0x3},
+        {98, 0x3},
+        {110, 0x2},
+        {104, 0x2},
+        {98, 0x2},
+        {110, 0x1},
+        {104, 0x1},
+        {98, 0x1},
+        {110, 0x0},
+        {104, 0x0},
+        {98, 0x0},
+        {97, 0},
+        {96, 0},
+        {95, 0},
+        {94, 0},
+        {93, 0},
+        {92, 0},
+        {91, 0},
+        {90, 0},
+        {89, 0},
+        {88, 0},
+        {87, 0},
+        {86, 0},
+        {85, 0},
+        {84, 0},
+        {83, 0},
+        {82, 0},
+        {81, 0},
+        {80, 0},
+        {79, 0},
+        {78, 0},
+        {77, 0},
+        {76, 0},
+        {75, 0},
+        {74, 0},
+        {73, 0},
+        {72, 0},
+        {71, 0},
+        {70, 0},
+        {69, 0},
+        {68, 0},
+        {67, 0},
+        {66, 0},
+        {65, 0},
+        {64, 0},
+        {63, 0},
+        {62, 0},
+        {61, 0},
+        {60, 0},
+        {59, 0},
+        }
+};
+
+static int
+il4965_fill_txpower_tbl(struct il_priv *il, u8 band, u16 channel, u8 is_ht40,
+                       u8 ctrl_chan_high,
+                       struct il4965_tx_power_db *tx_power_tbl)
+{
+       u8 saturation_power;
+       s32 target_power;
+       s32 user_target_power;
+       s32 power_limit;
+       s32 current_temp;
+       s32 reg_limit;
+       s32 current_regulatory;
+       s32 txatten_grp = CALIB_CH_GROUP_MAX;
+       int i;
+       int c;
+       const struct il_channel_info *ch_info = NULL;
+       struct il_eeprom_calib_ch_info ch_eeprom_info;
+       const struct il_eeprom_calib_measure *measurement;
+       s16 voltage;
+       s32 init_voltage;
+       s32 voltage_compensation;
+       s32 degrees_per_05db_num;
+       s32 degrees_per_05db_denom;
+       s32 factory_temp;
+       s32 temperature_comp[2];
+       s32 factory_gain_idx[2];
+       s32 factory_actual_pwr[2];
+       s32 power_idx;
+
+       /* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units
+        *   are used for idxing into txpower table) */
+       user_target_power = 2 * il->tx_power_user_lmt;
+
+       /* Get current (RXON) channel, band, width */
+       D_TXPOWER("chan %d band %d is_ht40 %d\n", channel, band, is_ht40);
+
+       ch_info = il_get_channel_info(il, il->band, channel);
+
+       if (!il_is_channel_valid(ch_info))
+               return -EINVAL;
+
+       /* get txatten group, used to select 1) thermal txpower adjustment
+        *   and 2) mimo txpower balance between Tx chains. */
+       txatten_grp = il4965_get_tx_atten_grp(channel);
+       if (txatten_grp < 0) {
+               IL_ERR("Can't find txatten group for channel %d.\n", channel);
+               return txatten_grp;
+       }
+
+       D_TXPOWER("channel %d belongs to txatten group %d\n", channel,
+                 txatten_grp);
+
+       if (is_ht40) {
+               if (ctrl_chan_high)
+                       channel -= 2;
+               else
+                       channel += 2;
+       }
+
+       /* hardware txpower limits ...
+        * saturation (clipping distortion) txpowers are in half-dBm */
+       if (band)
+               saturation_power = il->calib_info->saturation_power24;
+       else
+               saturation_power = il->calib_info->saturation_power52;
+
+       if (saturation_power < IL_TX_POWER_SATURATION_MIN ||
+           saturation_power > IL_TX_POWER_SATURATION_MAX) {
+               if (band)
+                       saturation_power = IL_TX_POWER_DEFAULT_SATURATION_24;
+               else
+                       saturation_power = IL_TX_POWER_DEFAULT_SATURATION_52;
+       }
+
+       /* regulatory txpower limits ... reg_limit values are in half-dBm,
+        *   max_power_avg values are in dBm, convert * 2 */
+       if (is_ht40)
+               reg_limit = ch_info->ht40_max_power_avg * 2;
+       else
+               reg_limit = ch_info->max_power_avg * 2;
+
+       if ((reg_limit < IL_TX_POWER_REGULATORY_MIN) ||
+           (reg_limit > IL_TX_POWER_REGULATORY_MAX)) {
+               if (band)
+                       reg_limit = IL_TX_POWER_DEFAULT_REGULATORY_24;
+               else
+                       reg_limit = IL_TX_POWER_DEFAULT_REGULATORY_52;
+       }
+
+       /* Interpolate txpower calibration values for this channel,
+        *   based on factory calibration tests on spaced channels. */
+       il4965_interpolate_chan(il, channel, &ch_eeprom_info);
+
+       /* calculate tx gain adjustment based on power supply voltage */
+       voltage = le16_to_cpu(il->calib_info->voltage);
+       init_voltage = (s32) le32_to_cpu(il->card_alive_init.voltage);
+       voltage_compensation =
+           il4965_get_voltage_compensation(voltage, init_voltage);
+
+       D_TXPOWER("curr volt %d eeprom volt %d volt comp %d\n", init_voltage,
+                 voltage, voltage_compensation);
+
+       /* get current temperature (Celsius) */
+       current_temp = max(il->temperature, IL_TX_POWER_TEMPERATURE_MIN);
+       current_temp = min(il->temperature, IL_TX_POWER_TEMPERATURE_MAX);
+       current_temp = KELVIN_TO_CELSIUS(current_temp);
+
+       /* select thermal txpower adjustment params, based on channel group
+        *   (same frequency group used for mimo txatten adjustment) */
+       degrees_per_05db_num =
+           tx_power_cmp_tble[txatten_grp].degrees_per_05db_a;
+       degrees_per_05db_denom =
+           tx_power_cmp_tble[txatten_grp].degrees_per_05db_a_denom;
+
+       /* get per-chain txpower values from factory measurements */
+       for (c = 0; c < 2; c++) {
+               measurement = &ch_eeprom_info.measurements[c][1];
+
+               /* txgain adjustment (in half-dB steps) based on difference
+                *   between factory and current temperature */
+               factory_temp = measurement->temperature;
+               il4965_math_div_round((current_temp -
+                                      factory_temp) * degrees_per_05db_denom,
+                                     degrees_per_05db_num,
+                                     &temperature_comp[c]);
+
+               factory_gain_idx[c] = measurement->gain_idx;
+               factory_actual_pwr[c] = measurement->actual_pow;
+
+               D_TXPOWER("chain = %d\n", c);
+               D_TXPOWER("fctry tmp %d, " "curr tmp %d, comp %d steps\n",
+                         factory_temp, current_temp, temperature_comp[c]);
+
+               D_TXPOWER("fctry idx %d, fctry pwr %d\n", factory_gain_idx[c],
+                         factory_actual_pwr[c]);
+       }
+
+       /* for each of 33 bit-rates (including 1 for CCK) */
+       for (i = 0; i < POWER_TBL_NUM_ENTRIES; i++) {
+               u8 is_mimo_rate;
+               union il4965_tx_power_dual_stream tx_power;
+
+               /* for mimo, reduce each chain's txpower by half
+                * (3dB, 6 steps), so total output power is regulatory
+                * compliant. */
+               if (i & 0x8) {
+                       current_regulatory =
+                           reg_limit -
+                           IL_TX_POWER_MIMO_REGULATORY_COMPENSATION;
+                       is_mimo_rate = 1;
+               } else {
+                       current_regulatory = reg_limit;
+                       is_mimo_rate = 0;
+               }
+
+               /* find txpower limit, either hardware or regulatory */
+               power_limit = saturation_power - back_off_table[i];
+               if (power_limit > current_regulatory)
+                       power_limit = current_regulatory;
+
+               /* reduce user's txpower request if necessary
+                * for this rate on this channel */
+               target_power = user_target_power;
+               if (target_power > power_limit)
+                       target_power = power_limit;
+
+               D_TXPOWER("rate %d sat %d reg %d usr %d tgt %d\n", i,
+                         saturation_power - back_off_table[i],
+                         current_regulatory, user_target_power, target_power);
+
+               /* for each of 2 Tx chains (radio transmitters) */
+               for (c = 0; c < 2; c++) {
+                       s32 atten_value;
+
+                       if (is_mimo_rate)
+                               atten_value =
+                                   (s32) le32_to_cpu(il->card_alive_init.
+                                                     tx_atten[txatten_grp][c]);
+                       else
+                               atten_value = 0;
+
+                       /* calculate idx; higher idx means lower txpower */
+                       power_idx =
+                           (u8) (factory_gain_idx[c] -
+                                 (target_power - factory_actual_pwr[c]) -
+                                 temperature_comp[c] - voltage_compensation +
+                                 atten_value);
+
+/*                     D_TXPOWER("calculated txpower idx %d\n",
+                                               power_idx); */
+
+                       if (power_idx < get_min_power_idx(i, band))
+                               power_idx = get_min_power_idx(i, band);
+
+                       /* adjust 5 GHz idx to support negative idxes */
+                       if (!band)
+                               power_idx += 9;
+
+                       /* CCK, rate 32, reduce txpower for CCK */
+                       if (i == POWER_TBL_CCK_ENTRY)
+                               power_idx +=
+                                   IL_TX_POWER_CCK_COMPENSATION_C_STEP;
+
+                       /* stay within the table! */
+                       if (power_idx > 107) {
+                               IL_WARN("txpower idx %d > 107\n", power_idx);
+                               power_idx = 107;
+                       }
+                       if (power_idx < 0) {
+                               IL_WARN("txpower idx %d < 0\n", power_idx);
+                               power_idx = 0;
+                       }
+
+                       /* fill txpower command for this rate/chain */
+                       tx_power.s.radio_tx_gain[c] =
+                           gain_table[band][power_idx].radio;
+                       tx_power.s.dsp_predis_atten[c] =
+                           gain_table[band][power_idx].dsp;
+
+                       D_TXPOWER("chain %d mimo %d idx %d "
+                                 "gain 0x%02x dsp %d\n", c, atten_value,
+                                 power_idx, tx_power.s.radio_tx_gain[c],
+                                 tx_power.s.dsp_predis_atten[c]);
+               }               /* for each chain */
+
+               tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw);
+
+       }                       /* for each rate */
+
+       return 0;
+}
+
+/**
+ * il4965_send_tx_power - Configure the TXPOWER level user limit
+ *
+ * Uses the active RXON for channel, band, and characteristics (ht40, high)
+ * The power limit is taken from il->tx_power_user_lmt.
+ */
+static int
+il4965_send_tx_power(struct il_priv *il)
+{
+       struct il4965_txpowertable_cmd cmd = { 0 };
+       int ret;
+       u8 band = 0;
+       bool is_ht40 = false;
+       u8 ctrl_chan_high = 0;
+       struct il_rxon_context *ctx = &il->ctx;
+
+       if (WARN_ONCE
+           (test_bit(S_SCAN_HW, &il->status),
+            "TX Power requested while scanning!\n"))
+               return -EAGAIN;
+
+       band = il->band == IEEE80211_BAND_2GHZ;
+
+       is_ht40 = iw4965_is_ht40_channel(ctx->active.flags);
+
+       if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+               ctrl_chan_high = 1;
+
+       cmd.band = band;
+       cmd.channel = ctx->active.channel;
+
+       ret =
+           il4965_fill_txpower_tbl(il, band, le16_to_cpu(ctx->active.channel),
+                                   is_ht40, ctrl_chan_high, &cmd.tx_power);
+       if (ret)
+               goto out;
+
+       ret = il_send_cmd_pdu(il, C_TX_PWR_TBL, sizeof(cmd), &cmd);
+
+out:
+       return ret;
+}
+
+static int
+il4965_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       int ret = 0;
+       struct il4965_rxon_assoc_cmd rxon_assoc;
+       const struct il_rxon_cmd *rxon1 = &ctx->staging;
+       const struct il_rxon_cmd *rxon2 = &ctx->active;
+
+       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) {
+               D_INFO("Using current RXON_ASSOC.  Not resending.\n");
+               return 0;
+       }
+
+       rxon_assoc.flags = ctx->staging.flags;
+       rxon_assoc.filter_flags = ctx->staging.filter_flags;
+       rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
+       rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
+       rxon_assoc.reserved = 0;
+       rxon_assoc.ofdm_ht_single_stream_basic_rates =
+           ctx->staging.ofdm_ht_single_stream_basic_rates;
+       rxon_assoc.ofdm_ht_dual_stream_basic_rates =
+           ctx->staging.ofdm_ht_dual_stream_basic_rates;
+       rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
+
+       ret =
+           il_send_cmd_pdu_async(il, C_RXON_ASSOC, sizeof(rxon_assoc),
+                                 &rxon_assoc, NULL);
+
+       return ret;
+}
+
+static int
+il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       /* cast away the const for active_rxon in this function */
+       struct il_rxon_cmd *active_rxon = (void *)&ctx->active;
+       int ret;
+       bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
+
+       if (!il_is_alive(il))
+               return -EBUSY;
+
+       if (!ctx->is_active)
+               return 0;
+
+       /* always get timestamp with Rx frame */
+       ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
+
+       ret = il_check_rxon_cmd(il, ctx);
+       if (ret) {
+               IL_ERR("Invalid RXON configuration.  Not committing.\n");
+               return -EINVAL;
+       }
+
+       /*
+        * receive commit_rxon request
+        * abort any previous channel switch if still in process
+        */
+       if (test_bit(S_CHANNEL_SWITCH_PENDING, &il->status) &&
+           il->switch_channel != ctx->staging.channel) {
+               D_11H("abort channel switch on %d\n",
+                     le16_to_cpu(il->switch_channel));
+               il_chswitch_done(il, false);
+       }
+
+       /* If we don't need to send a full RXON, we can use
+        * il_rxon_assoc_cmd which is used to reconfigure filter
+        * and other flags for the current radio configuration. */
+       if (!il_full_rxon_required(il, ctx)) {
+               ret = il_send_rxon_assoc(il, ctx);
+               if (ret) {
+                       IL_ERR("Error setting RXON_ASSOC (%d)\n", ret);
+                       return ret;
+               }
+
+               memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+               il_print_rx_config_cmd(il, ctx);
+               /*
+                * We do not commit tx power settings while channel changing,
+                * do it now if tx power changed.
+                */
+               il_set_tx_power(il, il->tx_power_next, false);
+               return 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 (il_is_associated_ctx(ctx) && new_assoc) {
+               D_INFO("Toggling associated bit on current RXON\n");
+               active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+               ret =
+                   il_send_cmd_pdu(il, ctx->rxon_cmd,
+                                   sizeof(struct il_rxon_cmd), active_rxon);
+
+               /* If the mask clearing failed then we set
+                * active_rxon back to what it was previously */
+               if (ret) {
+                       active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
+                       IL_ERR("Error clearing ASSOC_MSK (%d)\n", ret);
+                       return ret;
+               }
+               il_clear_ucode_stations(il, ctx);
+               il_restore_stations(il, ctx);
+               ret = il4965_restore_default_wep_keys(il, ctx);
+               if (ret) {
+                       IL_ERR("Failed to restore WEP keys (%d)\n", ret);
+                       return ret;
+               }
+       }
+
+       D_INFO("Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n"
+              "* channel = %d\n" "* bssid = %pM\n", (new_assoc ? "" : "out"),
+              le16_to_cpu(ctx->staging.channel), ctx->staging.bssid_addr);
+
+       il_set_rxon_hwcrypto(il, ctx, !il->cfg->mod_params->sw_crypto);
+
+       /* Apply the new configuration
+        * RXON unassoc clears the station table in uCode so restoration of
+        * stations is needed after it (the RXON command) completes
+        */
+       if (!new_assoc) {
+               ret =
+                   il_send_cmd_pdu(il, ctx->rxon_cmd,
+                                   sizeof(struct il_rxon_cmd), &ctx->staging);
+               if (ret) {
+                       IL_ERR("Error setting new RXON (%d)\n", ret);
+                       return ret;
+               }
+               D_INFO("Return from !new_assoc RXON.\n");
+               memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+               il_clear_ucode_stations(il, ctx);
+               il_restore_stations(il, ctx);
+               ret = il4965_restore_default_wep_keys(il, ctx);
+               if (ret) {
+                       IL_ERR("Failed to restore WEP keys (%d)\n", ret);
+                       return ret;
+               }
+       }
+       if (new_assoc) {
+               il->start_calib = 0;
+               /* Apply the new configuration
+                * RXON assoc doesn't clear the station table in uCode,
+                */
+               ret =
+                   il_send_cmd_pdu(il, ctx->rxon_cmd,
+                                   sizeof(struct il_rxon_cmd), &ctx->staging);
+               if (ret) {
+                       IL_ERR("Error setting new RXON (%d)\n", ret);
+                       return ret;
+               }
+               memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+       }
+       il_print_rx_config_cmd(il, ctx);
+
+       il4965_init_sensitivity(il);
+
+       /* 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 */
+       ret = il_set_tx_power(il, il->tx_power_next, true);
+       if (ret) {
+               IL_ERR("Error sending TX power (%d)\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int
+il4965_hw_channel_switch(struct il_priv *il,
+                        struct ieee80211_channel_switch *ch_switch)
+{
+       struct il_rxon_context *ctx = &il->ctx;
+       int rc;
+       u8 band = 0;
+       bool is_ht40 = false;
+       u8 ctrl_chan_high = 0;
+       struct il4965_channel_switch_cmd cmd;
+       const struct il_channel_info *ch_info;
+       u32 switch_time_in_usec, ucode_switch_time;
+       u16 ch;
+       u32 tsf_low;
+       u8 switch_count;
+       u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
+       struct ieee80211_vif *vif = ctx->vif;
+       band = il->band == IEEE80211_BAND_2GHZ;
+
+       is_ht40 = iw4965_is_ht40_channel(ctx->staging.flags);
+
+       if (is_ht40 && (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+               ctrl_chan_high = 1;
+
+       cmd.band = band;
+       cmd.expect_beacon = 0;
+       ch = ch_switch->channel->hw_value;
+       cmd.channel = cpu_to_le16(ch);
+       cmd.rxon_flags = ctx->staging.flags;
+       cmd.rxon_filter_flags = ctx->staging.filter_flags;
+       switch_count = ch_switch->count;
+       tsf_low = ch_switch->timestamp & 0x0ffffffff;
+       /*
+        * calculate the ucode channel switch time
+        * adding TSF as one of the factor for when to switch
+        */
+       if (il->ucode_beacon_time > tsf_low && beacon_interval) {
+               if (switch_count >
+                   ((il->ucode_beacon_time - tsf_low) / beacon_interval)) {
+                       switch_count -=
+                           (il->ucode_beacon_time - tsf_low) / beacon_interval;
+               } else
+                       switch_count = 0;
+       }
+       if (switch_count <= 1)
+               cmd.switch_time = cpu_to_le32(il->ucode_beacon_time);
+       else {
+               switch_time_in_usec =
+                   vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
+               ucode_switch_time =
+                   il_usecs_to_beacons(il, switch_time_in_usec,
+                                       beacon_interval);
+               cmd.switch_time =
+                   il_add_beacon_time(il, il->ucode_beacon_time,
+                                      ucode_switch_time, beacon_interval);
+       }
+       D_11H("uCode time for the switch is 0x%x\n", cmd.switch_time);
+       ch_info = il_get_channel_info(il, il->band, ch);
+       if (ch_info)
+               cmd.expect_beacon = il_is_channel_radar(ch_info);
+       else {
+               IL_ERR("invalid channel switch from %u to %u\n",
+                      ctx->active.channel, ch);
+               return -EFAULT;
+       }
+
+       rc = il4965_fill_txpower_tbl(il, band, ch, is_ht40, ctrl_chan_high,
+                                    &cmd.tx_power);
+       if (rc) {
+               D_11H("error:%d  fill txpower_tbl\n", rc);
+               return rc;
+       }
+
+       return il_send_cmd_pdu(il, C_CHANNEL_SWITCH, sizeof(cmd), &cmd);
+}
+
+/**
+ * il4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
+ */
+static void
+il4965_txq_update_byte_cnt_tbl(struct il_priv *il, struct il_tx_queue *txq,
+                              u16 byte_cnt)
+{
+       struct il4965_scd_bc_tbl *scd_bc_tbl = il->scd_bc_tbls.addr;
+       int txq_id = txq->q.id;
+       int write_ptr = txq->q.write_ptr;
+       int len = byte_cnt + IL_TX_CRC_SIZE + IL_TX_DELIMITER_SIZE;
+       __le16 bc_ent;
+
+       WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
+
+       bc_ent = cpu_to_le16(len & 0xFFF);
+       /* Set up byte count within first 256 entries */
+       scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
+
+       /* If within first 64 entries, duplicate at end */
+       if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+               scd_bc_tbl[txq_id].tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] =
+                   bc_ent;
+}
+
+/**
+ * il4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
+ * @stats: Provides the temperature reading from the uCode
+ *
+ * A return of <0 indicates bogus data in the stats
+ */
+static int
+il4965_hw_get_temperature(struct il_priv *il)
+{
+       s32 temperature;
+       s32 vt;
+       s32 R1, R2, R3;
+       u32 R4;
+
+       if (test_bit(S_TEMPERATURE, &il->status) &&
+           (il->_4965.stats.flag & STATS_REPLY_FLG_HT40_MODE_MSK)) {
+               D_TEMP("Running HT40 temperature calibration\n");
+               R1 = (s32) le32_to_cpu(il->card_alive_init.therm_r1[1]);
+               R2 = (s32) le32_to_cpu(il->card_alive_init.therm_r2[1]);
+               R3 = (s32) le32_to_cpu(il->card_alive_init.therm_r3[1]);
+               R4 = le32_to_cpu(il->card_alive_init.therm_r4[1]);
+       } else {
+               D_TEMP("Running temperature calibration\n");
+               R1 = (s32) le32_to_cpu(il->card_alive_init.therm_r1[0]);
+               R2 = (s32) le32_to_cpu(il->card_alive_init.therm_r2[0]);
+               R3 = (s32) le32_to_cpu(il->card_alive_init.therm_r3[0]);
+               R4 = le32_to_cpu(il->card_alive_init.therm_r4[0]);
+       }
+
+       /*
+        * Temperature is only 23 bits, so sign extend out to 32.
+        *
+        * NOTE If we haven't received a stats notification yet
+        * with an updated temperature, use R4 provided to us in the
+        * "initialize" ALIVE response.
+        */
+       if (!test_bit(S_TEMPERATURE, &il->status))
+               vt = sign_extend32(R4, 23);
+       else
+               vt = sign_extend32(le32_to_cpu
+                                  (il->_4965.stats.general.common.temperature),
+                                  23);
+
+       D_TEMP("Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
+
+       if (R3 == R1) {
+               IL_ERR("Calibration conflict R1 == R3\n");
+               return -1;
+       }
+
+       /* Calculate temperature in degrees Kelvin, adjust by 97%.
+        * Add offset to center the adjustment around 0 degrees Centigrade. */
+       temperature = TEMPERATURE_CALIB_A_VAL * (vt - R2);
+       temperature /= (R3 - R1);
+       temperature =
+           (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET;
+
+       D_TEMP("Calibrated temperature: %dK, %dC\n", temperature,
+              KELVIN_TO_CELSIUS(temperature));
+
+       return temperature;
+}
+
+/* Adjust Txpower only if temperature variance is greater than threshold. */
+#define IL_TEMPERATURE_THRESHOLD   3
+
+/**
+ * il4965_is_temp_calib_needed - determines if new calibration is needed
+ *
+ * If the temperature changed has changed sufficiently, then a recalibration
+ * is needed.
+ *
+ * Assumes caller will replace il->last_temperature once calibration
+ * executed.
+ */
+static int
+il4965_is_temp_calib_needed(struct il_priv *il)
+{
+       int temp_diff;
+
+       if (!test_bit(S_STATS, &il->status)) {
+               D_TEMP("Temperature not updated -- no stats.\n");
+               return 0;
+       }
+
+       temp_diff = il->temperature - il->last_temperature;
+
+       /* get absolute value */
+       if (temp_diff < 0) {
+               D_POWER("Getting cooler, delta %d\n", temp_diff);
+               temp_diff = -temp_diff;
+       } else if (temp_diff == 0)
+               D_POWER("Temperature unchanged\n");
+       else
+               D_POWER("Getting warmer, delta %d\n", temp_diff);
+
+       if (temp_diff < IL_TEMPERATURE_THRESHOLD) {
+               D_POWER(" => thermal txpower calib not needed\n");
+               return 0;
+       }
+
+       D_POWER(" => thermal txpower calib needed\n");
+
+       return 1;
+}
+
+static void
+il4965_temperature_calib(struct il_priv *il)
+{
+       s32 temp;
+
+       temp = il4965_hw_get_temperature(il);
+       if (IL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(temp))
+               return;
+
+       if (il->temperature != temp) {
+               if (il->temperature)
+                       D_TEMP("Temperature changed " "from %dC to %dC\n",
+                              KELVIN_TO_CELSIUS(il->temperature),
+                              KELVIN_TO_CELSIUS(temp));
+               else
+                       D_TEMP("Temperature " "initialized to %dC\n",
+                              KELVIN_TO_CELSIUS(temp));
+       }
+
+       il->temperature = temp;
+       set_bit(S_TEMPERATURE, &il->status);
+
+       if (!il->disable_tx_power_cal &&
+           unlikely(!test_bit(S_SCANNING, &il->status)) &&
+           il4965_is_temp_calib_needed(il))
+               queue_work(il->workqueue, &il->txpower_work);
+}
+
+static u16
+il4965_get_hcmd_size(u8 cmd_id, u16 len)
+{
+       switch (cmd_id) {
+       case C_RXON:
+               return (u16) sizeof(struct il4965_rxon_cmd);
+       default:
+               return len;
+       }
+}
+
+static u16
+il4965_build_addsta_hcmd(const struct il_addsta_cmd *cmd, u8 * data)
+{
+       struct il4965_addsta_cmd *addsta = (struct il4965_addsta_cmd *)data;
+       addsta->mode = cmd->mode;
+       memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
+       memcpy(&addsta->key, &cmd->key, sizeof(struct il4965_keyinfo));
+       addsta->station_flags = cmd->station_flags;
+       addsta->station_flags_msk = cmd->station_flags_msk;
+       addsta->tid_disable_tx = cmd->tid_disable_tx;
+       addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
+       addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
+       addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
+       addsta->sleep_tx_count = cmd->sleep_tx_count;
+       addsta->reserved1 = cpu_to_le16(0);
+       addsta->reserved2 = cpu_to_le16(0);
+
+       return (u16) sizeof(struct il4965_addsta_cmd);
+}
+
+static inline u32
+il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp)
+{
+       return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN;
+}
+
+static inline u32
+il4965_tx_status_to_mac80211(u32 status)
+{
+       status &= TX_STATUS_MSK;
+
+       switch (status) {
+       case TX_STATUS_SUCCESS:
+       case TX_STATUS_DIRECT_DONE:
+               return IEEE80211_TX_STAT_ACK;
+       case TX_STATUS_FAIL_DEST_PS:
+               return IEEE80211_TX_STAT_TX_FILTERED;
+       default:
+               return 0;
+       }
+}
+
+static inline bool
+il4965_is_tx_success(u32 status)
+{
+       status &= TX_STATUS_MSK;
+       return (status == TX_STATUS_SUCCESS || status == TX_STATUS_DIRECT_DONE);
+}
+
+/**
+ * il4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue
+ */
+static int
+il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg,
+                         struct il4965_tx_resp *tx_resp, int txq_id,
+                         u16 start_idx)
+{
+       u16 status;
+       struct agg_tx_status *frame_status = tx_resp->u.agg_status;
+       struct ieee80211_tx_info *info = NULL;
+       struct ieee80211_hdr *hdr = NULL;
+       u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+       int i, sh, idx;
+       u16 seq;
+       if (agg->wait_for_ba)
+               D_TX_REPLY("got tx response w/o block-ack\n");
+
+       agg->frame_count = tx_resp->frame_count;
+       agg->start_idx = start_idx;
+       agg->rate_n_flags = rate_n_flags;
+       agg->bitmap = 0;
+
+       /* num frames attempted by Tx command */
+       if (agg->frame_count == 1) {
+               /* Only one frame was attempted; no block-ack will arrive */
+               status = le16_to_cpu(frame_status[0].status);
+               idx = start_idx;
+
+               D_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
+                          agg->frame_count, agg->start_idx, idx);
+
+               info = IEEE80211_SKB_CB(il->txq[txq_id].txb[idx].skb);
+               info->status.rates[0].count = tx_resp->failure_frame + 1;
+               info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+               info->flags |= il4965_tx_status_to_mac80211(status);
+               il4965_hwrate_to_tx_control(il, rate_n_flags, info);
+
+               D_TX_REPLY("1 Frame 0x%x failure :%d\n", status & 0xff,
+                          tx_resp->failure_frame);
+               D_TX_REPLY("Rate Info rate_n_flags=%x\n", rate_n_flags);
+
+               agg->wait_for_ba = 0;
+       } else {
+               /* Two or more frames were attempted; expect block-ack */
+               u64 bitmap = 0;
+               int start = agg->start_idx;
+
+               /* Construct bit-map of pending frames within Tx win */
+               for (i = 0; i < agg->frame_count; i++) {
+                       u16 sc;
+                       status = le16_to_cpu(frame_status[i].status);
+                       seq = le16_to_cpu(frame_status[i].sequence);
+                       idx = SEQ_TO_IDX(seq);
+                       txq_id = SEQ_TO_QUEUE(seq);
+
+                       if (status &
+                           (AGG_TX_STATE_FEW_BYTES_MSK |
+                            AGG_TX_STATE_ABORT_MSK))
+                               continue;
+
+                       D_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
+                                  agg->frame_count, txq_id, idx);
+
+                       hdr = il_tx_queue_get_hdr(il, txq_id, idx);
+                       if (!hdr) {
+                               IL_ERR("BUG_ON idx doesn't point to valid skb"
+                                      " idx=%d, txq_id=%d\n", idx, txq_id);
+                               return -1;
+                       }
+
+                       sc = le16_to_cpu(hdr->seq_ctrl);
+                       if (idx != (SEQ_TO_SN(sc) & 0xff)) {
+                               IL_ERR("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;
+                       }
+
+                       D_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 |= 1ULL << sh;
+                       D_TX_REPLY("start=%d bitmap=0x%llx\n", start,
+                                  (unsigned long long)bitmap);
+               }
+
+               agg->bitmap = bitmap;
+               agg->start_idx = start;
+               D_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
+                          agg->frame_count, agg->start_idx,
+                          (unsigned long long)agg->bitmap);
+
+               if (bitmap)
+                       agg->wait_for_ba = 1;
+       }
+       return 0;
+}
+
+static u8
+il4965_find_station(struct il_priv *il, const u8 * addr)
+{
+       int i;
+       int start = 0;
+       int ret = IL_INVALID_STATION;
+       unsigned long flags;
+
+       if ((il->iw_mode == NL80211_IFTYPE_ADHOC))
+               start = IL_STA_ID;
+
+       if (is_broadcast_ether_addr(addr))
+               return il->ctx.bcast_sta_id;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       for (i = start; i < il->hw_params.max_stations; i++)
+               if (il->stations[i].used &&
+                   (!compare_ether_addr(il->stations[i].sta.sta.addr, addr))) {
+                       ret = i;
+                       goto out;
+               }
+
+       D_ASSOC("can not find STA %pM total %d\n", addr, il->num_stations);
+
+out:
+       /*
+        * It may be possible that more commands interacting with stations
+        * arrive before we completed processing the adding of
+        * station
+        */
+       if (ret != IL_INVALID_STATION &&
+           (!(il->stations[ret].used & IL_STA_UCODE_ACTIVE) ||
+            ((il->stations[ret].used & IL_STA_UCODE_ACTIVE) &&
+             (il->stations[ret].used & IL_STA_UCODE_INPROGRESS)))) {
+               IL_ERR("Requested station info for sta %d before ready.\n",
+                      ret);
+               ret = IL_INVALID_STATION;
+       }
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+       return ret;
+}
+
+static int
+il4965_get_ra_sta_id(struct il_priv *il, struct ieee80211_hdr *hdr)
+{
+       if (il->iw_mode == NL80211_IFTYPE_STATION) {
+               return IL_AP_ID;
+       } else {
+               u8 *da = ieee80211_get_DA(hdr);
+               return il4965_find_station(il, da);
+       }
+}
+
+/**
+ * il4965_hdl_tx - Handle standard (non-aggregation) Tx response
+ */
+static void
+il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+       int txq_id = SEQ_TO_QUEUE(sequence);
+       int idx = SEQ_TO_IDX(sequence);
+       struct il_tx_queue *txq = &il->txq[txq_id];
+       struct ieee80211_hdr *hdr;
+       struct ieee80211_tx_info *info;
+       struct il4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+       u32 status = le32_to_cpu(tx_resp->u.status);
+       int uninitialized_var(tid);
+       int sta_id;
+       int freed;
+       u8 *qc = NULL;
+       unsigned long flags;
+
+       if (idx >= txq->q.n_bd || il_queue_used(&txq->q, idx) == 0) {
+               IL_ERR("Read idx for DMA queue txq_id (%d) idx %d "
+                      "is out of range [0-%d] %d %d\n", txq_id, idx,
+                      txq->q.n_bd, txq->q.write_ptr, txq->q.read_ptr);
+               return;
+       }
+
+       txq->time_stamp = jiffies;
+       info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
+       memset(&info->status, 0, sizeof(info->status));
+
+       hdr = il_tx_queue_get_hdr(il, txq_id, idx);
+       if (ieee80211_is_data_qos(hdr->frame_control)) {
+               qc = ieee80211_get_qos_ctl(hdr);
+               tid = qc[0] & 0xf;
+       }
+
+       sta_id = il4965_get_ra_sta_id(il, hdr);
+       if (txq->sched_retry && unlikely(sta_id == IL_INVALID_STATION)) {
+               IL_ERR("Station not known\n");
+               return;
+       }
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       if (txq->sched_retry) {
+               const u32 scd_ssn = il4965_get_scd_ssn(tx_resp);
+               struct il_ht_agg *agg = NULL;
+               WARN_ON(!qc);
+
+               agg = &il->stations[sta_id].tid[tid].agg;
+
+               il4965_tx_status_reply_tx(il, agg, tx_resp, txq_id, idx);
+
+               /* check if BAR is needed */
+               if ((tx_resp->frame_count == 1) &&
+                   !il4965_is_tx_success(status))
+                       info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+
+               if (txq->q.read_ptr != (scd_ssn & 0xff)) {
+                       idx = il_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
+                       D_TX_REPLY("Retry scheduler reclaim scd_ssn "
+                                  "%d idx %d\n", scd_ssn, idx);
+                       freed = il4965_tx_queue_reclaim(il, txq_id, idx);
+                       if (qc)
+                               il4965_free_tfds_in_queue(il, sta_id, tid,
+                                                         freed);
+
+                       if (il->mac80211_registered &&
+                           il_queue_space(&txq->q) > txq->q.low_mark &&
+                           agg->state != IL_EMPTYING_HW_QUEUE_DELBA)
+                               il_wake_queue(il, txq);
+               }
+       } else {
+               info->status.rates[0].count = tx_resp->failure_frame + 1;
+               info->flags |= il4965_tx_status_to_mac80211(status);
+               il4965_hwrate_to_tx_control(il,
+                                           le32_to_cpu(tx_resp->rate_n_flags),
+                                           info);
+
+               D_TX_REPLY("TXQ %d status %s (0x%08x) "
+                          "rate_n_flags 0x%x retries %d\n", txq_id,
+                          il4965_get_tx_fail_reason(status), status,
+                          le32_to_cpu(tx_resp->rate_n_flags),
+                          tx_resp->failure_frame);
+
+               freed = il4965_tx_queue_reclaim(il, txq_id, idx);
+               if (qc && likely(sta_id != IL_INVALID_STATION))
+                       il4965_free_tfds_in_queue(il, sta_id, tid, freed);
+               else if (sta_id == IL_INVALID_STATION)
+                       D_TX_REPLY("Station not known\n");
+
+               if (il->mac80211_registered &&
+                   il_queue_space(&txq->q) > txq->q.low_mark)
+                       il_wake_queue(il, txq);
+       }
+       if (qc && likely(sta_id != IL_INVALID_STATION))
+               il4965_txq_check_empty(il, sta_id, tid, txq_id);
+
+       il4965_check_abort_status(il, tx_resp->frame_count, status);
+
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+}
+
+static void
+il4965_hdl_beacon(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il4965_beacon_notif *beacon = (void *)pkt->u.raw;
+       u8 rate __maybe_unused =
+           il4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+
+       D_RX("beacon status %#x, retries:%d ibssmgr:%d "
+            "tsf:0x%.8x%.8x rate:%d\n",
+            le32_to_cpu(beacon->beacon_notify_hdr.u.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);
+
+       il->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+}
+
+/* Set up 4965-specific Rx frame reply handlers */
+static void
+il4965_handler_setup(struct il_priv *il)
+{
+       /* Legacy Rx frames */
+       il->handlers[N_RX] = il4965_hdl_rx;
+       /* Tx response */
+       il->handlers[C_TX] = il4965_hdl_tx;
+       il->handlers[N_BEACON] = il4965_hdl_beacon;
+}
+
+static struct il_hcmd_ops il4965_hcmd = {
+       .rxon_assoc = il4965_send_rxon_assoc,
+       .commit_rxon = il4965_commit_rxon,
+       .set_rxon_chain = il4965_set_rxon_chain,
+};
+
+static void
+il4965_post_scan(struct il_priv *il)
+{
+       struct il_rxon_context *ctx = &il->ctx;
+
+       /*
+        * Since setting the RXON may have been deferred while
+        * performing the scan, fire one off if needed
+        */
+       if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+               il_commit_rxon(il, ctx);
+}
+
+static void
+il4965_post_associate(struct il_priv *il)
+{
+       struct il_rxon_context *ctx = &il->ctx;
+       struct ieee80211_vif *vif = ctx->vif;
+       struct ieee80211_conf *conf = NULL;
+       int ret = 0;
+
+       if (!vif || !il->is_open)
+               return;
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       il_scan_cancel_timeout(il, 200);
+
+       conf = &il->hw->conf;
+
+       ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+       il_commit_rxon(il, ctx);
+
+       ret = il_send_rxon_timing(il, ctx);
+       if (ret)
+               IL_WARN("RXON timing - " "Attempting to continue.\n");
+
+       ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+
+       il_set_rxon_ht(il, &il->current_ht_config);
+
+       if (il->cfg->ops->hcmd->set_rxon_chain)
+               il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
+
+       ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+
+       D_ASSOC("assoc id %d beacon interval %d\n", vif->bss_conf.aid,
+               vif->bss_conf.beacon_int);
+
+       if (vif->bss_conf.use_short_preamble)
+               ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+       else
+               ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+       if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+               if (vif->bss_conf.use_short_slot)
+                       ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+               else
+                       ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+       }
+
+       il_commit_rxon(il, ctx);
+
+       D_ASSOC("Associated as %d to: %pM\n", vif->bss_conf.aid,
+               ctx->active.bssid_addr);
+
+       switch (vif->type) {
+       case NL80211_IFTYPE_STATION:
+               break;
+       case NL80211_IFTYPE_ADHOC:
+               il4965_send_beacon_cmd(il);
+               break;
+       default:
+               IL_ERR("%s Should not be called in %d mode\n", __func__,
+                      vif->type);
+               break;
+       }
+
+       /* the chain noise calibration will enabled PM upon completion
+        * If chain noise has already been run, then we need to enable
+        * power management here */
+       if (il->chain_noise_data.state == IL_CHAIN_NOISE_DONE)
+               il_power_update_mode(il, false);
+
+       /* Enable Rx differential gain and sensitivity calibrations */
+       il4965_chain_noise_reset(il);
+       il->start_calib = 1;
+}
+
+static void
+il4965_config_ap(struct il_priv *il)
+{
+       struct il_rxon_context *ctx = &il->ctx;
+       struct ieee80211_vif *vif = ctx->vif;
+       int ret = 0;
+
+       lockdep_assert_held(&il->mutex);
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       /* The following should be done only at AP bring up */
+       if (!il_is_associated_ctx(ctx)) {
+
+               /* RXON - unassoc (to set timing command) */
+               ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+               il_commit_rxon(il, ctx);
+
+               /* RXON Timing */
+               ret = il_send_rxon_timing(il, ctx);
+               if (ret)
+                       IL_WARN("RXON timing failed - "
+                               "Attempting to continue.\n");
+
+               /* AP has all antennas */
+               il->chain_noise_data.active_chains = il->hw_params.valid_rx_ant;
+               il_set_rxon_ht(il, &il->current_ht_config);
+               if (il->cfg->ops->hcmd->set_rxon_chain)
+                       il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
+
+               ctx->staging.assoc_id = 0;
+
+               if (vif->bss_conf.use_short_preamble)
+                       ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+               else
+                       ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+               if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+                       if (vif->bss_conf.use_short_slot)
+                               ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+                       else
+                               ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+               }
+               /* need to send beacon cmd before committing assoc RXON! */
+               il4965_send_beacon_cmd(il);
+               /* restore RXON assoc */
+               ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+               il_commit_rxon(il, ctx);
+       }
+       il4965_send_beacon_cmd(il);
+}
+
+static struct il_hcmd_utils_ops il4965_hcmd_utils = {
+       .get_hcmd_size = il4965_get_hcmd_size,
+       .build_addsta_hcmd = il4965_build_addsta_hcmd,
+       .request_scan = il4965_request_scan,
+       .post_scan = il4965_post_scan,
+};
+
+static struct il_lib_ops il4965_lib = {
+       .set_hw_params = il4965_hw_set_hw_params,
+       .txq_update_byte_cnt_tbl = il4965_txq_update_byte_cnt_tbl,
+       .txq_attach_buf_to_tfd = il4965_hw_txq_attach_buf_to_tfd,
+       .txq_free_tfd = il4965_hw_txq_free_tfd,
+       .txq_init = il4965_hw_tx_queue_init,
+       .handler_setup = il4965_handler_setup,
+       .is_valid_rtc_data_addr = il4965_hw_valid_rtc_data_addr,
+       .init_alive_start = il4965_init_alive_start,
+       .load_ucode = il4965_load_bsm,
+       .dump_nic_error_log = il4965_dump_nic_error_log,
+       .dump_fh = il4965_dump_fh,
+       .set_channel_switch = il4965_hw_channel_switch,
+       .apm_ops = {
+                   .init = il_apm_init,
+                   .config = il4965_nic_config,
+                   },
+       .eeprom_ops = {
+                      .regulatory_bands = {
+                                           EEPROM_REGULATORY_BAND_1_CHANNELS,
+                                           EEPROM_REGULATORY_BAND_2_CHANNELS,
+                                           EEPROM_REGULATORY_BAND_3_CHANNELS,
+                                           EEPROM_REGULATORY_BAND_4_CHANNELS,
+                                           EEPROM_REGULATORY_BAND_5_CHANNELS,
+                                           EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
+                                           EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS},
+                      .acquire_semaphore = il4965_eeprom_acquire_semaphore,
+                      .release_semaphore = il4965_eeprom_release_semaphore,
+                      },
+       .send_tx_power = il4965_send_tx_power,
+       .update_chain_flags = il4965_update_chain_flags,
+       .temp_ops = {
+                    .temperature = il4965_temperature_calib,
+                    },
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+       .debugfs_ops = {
+                       .rx_stats_read = il4965_ucode_rx_stats_read,
+                       .tx_stats_read = il4965_ucode_tx_stats_read,
+                       .general_stats_read = il4965_ucode_general_stats_read,
+                       },
+#endif
+};
+
+static const struct il_legacy_ops il4965_legacy_ops = {
+       .post_associate = il4965_post_associate,
+       .config_ap = il4965_config_ap,
+       .manage_ibss_station = il4965_manage_ibss_station,
+       .update_bcast_stations = il4965_update_bcast_stations,
+};
+
+struct ieee80211_ops il4965_hw_ops = {
+       .tx = il4965_mac_tx,
+       .start = il4965_mac_start,
+       .stop = il4965_mac_stop,
+       .add_interface = il_mac_add_interface,
+       .remove_interface = il_mac_remove_interface,
+       .change_interface = il_mac_change_interface,
+       .config = il_mac_config,
+       .configure_filter = il4965_configure_filter,
+       .set_key = il4965_mac_set_key,
+       .update_tkip_key = il4965_mac_update_tkip_key,
+       .conf_tx = il_mac_conf_tx,
+       .reset_tsf = il_mac_reset_tsf,
+       .bss_info_changed = il_mac_bss_info_changed,
+       .ampdu_action = il4965_mac_ampdu_action,
+       .hw_scan = il_mac_hw_scan,
+       .sta_add = il4965_mac_sta_add,
+       .sta_remove = il_mac_sta_remove,
+       .channel_switch = il4965_mac_channel_switch,
+       .tx_last_beacon = il_mac_tx_last_beacon,
+};
+
+static const struct il_ops il4965_ops = {
+       .lib = &il4965_lib,
+       .hcmd = &il4965_hcmd,
+       .utils = &il4965_hcmd_utils,
+       .led = &il4965_led_ops,
+       .legacy = &il4965_legacy_ops,
+       .ieee80211_ops = &il4965_hw_ops,
+};
+
+static struct il_base_params il4965_base_params = {
+       .eeprom_size = IL4965_EEPROM_IMG_SIZE,
+       .num_of_queues = IL49_NUM_QUEUES,
+       .num_of_ampdu_queues = IL49_NUM_AMPDU_QUEUES,
+       .pll_cfg_val = 0,
+       .set_l0s = true,
+       .use_bsm = true,
+       .led_compensation = 61,
+       .chain_noise_num_beacons = IL4965_CAL_NUM_BEACONS,
+       .wd_timeout = IL_DEF_WD_TIMEOUT,
+       .temperature_kelvin = true,
+       .ucode_tracing = true,
+       .sensitivity_calib_by_driver = true,
+       .chain_noise_calib_by_driver = true,
+};
+
+struct il_cfg il4965_cfg = {
+       .name = "Intel(R) Wireless WiFi Link 4965AGN",
+       .fw_name_pre = IL4965_FW_PRE,
+       .ucode_api_max = IL4965_UCODE_API_MAX,
+       .ucode_api_min = IL4965_UCODE_API_MIN,
+       .sku = IL_SKU_A | IL_SKU_G | IL_SKU_N,
+       .valid_tx_ant = ANT_AB,
+       .valid_rx_ant = ANT_ABC,
+       .eeprom_ver = EEPROM_4965_EEPROM_VERSION,
+       .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
+       .ops = &il4965_ops,
+       .mod_params = &il4965_mod_params,
+       .base_params = &il4965_base_params,
+       .led_mode = IL_LED_BLINK,
+       /*
+        * Force use of chains B and C for scan RX on 5 GHz band
+        * because the device has off-channel reception on chain A.
+        */
+       .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
+};
+
+/* Module firmware */
+MODULE_FIRMWARE(IL4965_MODULE_FIRMWARE(IL4965_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
new file mode 100644 (file)
index 0000000..7447231
--- /dev/null
@@ -0,0 +1,1309 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __il_4965_h__
+#define __il_4965_h__
+
+struct il_rx_queue;
+struct il_rx_buf;
+struct il_rx_pkt;
+struct il_tx_queue;
+struct il_rxon_context;
+
+/* configuration for the _4965 devices */
+extern struct il_cfg il4965_cfg;
+
+extern struct il_mod_params il4965_mod_params;
+
+extern struct ieee80211_ops il4965_hw_ops;
+
+/* tx queue */
+void il4965_free_tfds_in_queue(struct il_priv *il, int sta_id, int tid,
+                              int freed);
+
+/* RXON */
+void il4965_set_rxon_chain(struct il_priv *il, struct il_rxon_context *ctx);
+
+/* uCode */
+int il4965_verify_ucode(struct il_priv *il);
+
+/* lib */
+void il4965_check_abort_status(struct il_priv *il, u8 frame_count, u32 status);
+
+void il4965_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq);
+int il4965_rx_init(struct il_priv *il, struct il_rx_queue *rxq);
+int il4965_hw_nic_init(struct il_priv *il);
+int il4965_dump_fh(struct il_priv *il, char **buf, bool display);
+
+/* rx */
+void il4965_rx_queue_restock(struct il_priv *il);
+void il4965_rx_replenish(struct il_priv *il);
+void il4965_rx_replenish_now(struct il_priv *il);
+void il4965_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq);
+int il4965_rxq_stop(struct il_priv *il);
+int il4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
+void il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb);
+void il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb);
+void il4965_rx_handle(struct il_priv *il);
+
+/* tx */
+void il4965_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq);
+int il4965_hw_txq_attach_buf_to_tfd(struct il_priv *il, struct il_tx_queue *txq,
+                                   dma_addr_t addr, u16 len, u8 reset, u8 pad);
+int il4965_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq);
+void il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags,
+                                struct ieee80211_tx_info *info);
+int il4965_tx_skb(struct il_priv *il, struct sk_buff *skb);
+int il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif,
+                       struct ieee80211_sta *sta, u16 tid, u16 * ssn);
+int il4965_tx_agg_stop(struct il_priv *il, struct ieee80211_vif *vif,
+                      struct ieee80211_sta *sta, u16 tid);
+int il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id);
+void il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb);
+int il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx);
+void il4965_hw_txq_ctx_free(struct il_priv *il);
+int il4965_txq_ctx_alloc(struct il_priv *il);
+void il4965_txq_ctx_reset(struct il_priv *il);
+void il4965_txq_ctx_stop(struct il_priv *il);
+void il4965_txq_set_sched(struct il_priv *il, u32 mask);
+
+/*
+ * Acquire il->lock before calling this function !
+ */
+void il4965_set_wr_ptrs(struct il_priv *il, int txq_id, u32 idx);
+/**
+ * il4965_tx_queue_set_status - (optionally) start Tx/Cmd queue
+ * @tx_fifo_id: Tx DMA/FIFO channel (range 0-7) that the queue will feed
+ * @scd_retry: (1) Indicates queue will be used in aggregation mode
+ *
+ * NOTE:  Acquire il->lock before calling this function !
+ */
+void il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq,
+                               int tx_fifo_id, int scd_retry);
+
+u8 il4965_toggle_tx_ant(struct il_priv *il, u8 ant_idx, u8 valid);
+
+/* rx */
+void il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb);
+bool il4965_good_plcp_health(struct il_priv *il, struct il_rx_pkt *pkt);
+void il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb);
+void il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb);
+
+/* scan */
+int il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif);
+
+/* station mgmt */
+int il4965_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif,
+                              bool add);
+
+/* hcmd */
+int il4965_send_beacon_cmd(struct il_priv *il);
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+const char *il4965_get_tx_fail_reason(u32 status);
+#else
+static inline const char *
+il4965_get_tx_fail_reason(u32 status)
+{
+       return "";
+}
+#endif
+
+/* station management */
+int il4965_alloc_bcast_station(struct il_priv *il, struct il_rxon_context *ctx);
+int il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx,
+                            const u8 *addr, u8 *sta_id_r);
+int il4965_remove_default_wep_key(struct il_priv *il,
+                                 struct il_rxon_context *ctx,
+                                 struct ieee80211_key_conf *key);
+int il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx,
+                              struct ieee80211_key_conf *key);
+int il4965_restore_default_wep_keys(struct il_priv *il,
+                                   struct il_rxon_context *ctx);
+int il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx,
+                          struct ieee80211_key_conf *key, u8 sta_id);
+int il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx,
+                             struct ieee80211_key_conf *key, u8 sta_id);
+void il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx,
+                           struct ieee80211_key_conf *keyconf,
+                           struct ieee80211_sta *sta, u32 iv32,
+                           u16 *phase1key);
+int il4965_sta_tx_modify_enable_tid(struct il_priv *il, int sta_id, int tid);
+int il4965_sta_rx_agg_start(struct il_priv *il, struct ieee80211_sta *sta,
+                           int tid, u16 ssn);
+int il4965_sta_rx_agg_stop(struct il_priv *il, struct ieee80211_sta *sta,
+                          int tid);
+void il4965_sta_modify_sleep_tx_count(struct il_priv *il, int sta_id, int cnt);
+int il4965_update_bcast_stations(struct il_priv *il);
+
+/* rate */
+static inline u8
+il4965_hw_get_rate(__le32 rate_n_flags)
+{
+       return le32_to_cpu(rate_n_flags) & 0xFF;
+}
+
+static inline __le32
+il4965_hw_set_rate_n_flags(u8 rate, u32 flags)
+{
+       return cpu_to_le32(flags | (u32) rate);
+}
+
+/* eeprom */
+void il4965_eeprom_get_mac(const struct il_priv *il, u8 * mac);
+int il4965_eeprom_acquire_semaphore(struct il_priv *il);
+void il4965_eeprom_release_semaphore(struct il_priv *il);
+int il4965_eeprom_check_version(struct il_priv *il);
+
+/* mac80211 handlers (for 4965) */
+void il4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+int il4965_mac_start(struct ieee80211_hw *hw);
+void il4965_mac_stop(struct ieee80211_hw *hw);
+void il4965_configure_filter(struct ieee80211_hw *hw,
+                            unsigned int changed_flags,
+                            unsigned int *total_flags, u64 multicast);
+int il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+                      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+                      struct ieee80211_key_conf *key);
+void il4965_mac_update_tkip_key(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
+                               struct ieee80211_key_conf *keyconf,
+                               struct ieee80211_sta *sta, u32 iv32,
+                               u16 *phase1key);
+int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                           enum ieee80211_ampdu_mlme_action action,
+                           struct ieee80211_sta *sta, u16 tid, u16 * ssn,
+                           u8 buf_size);
+int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                      struct ieee80211_sta *sta);
+void il4965_mac_channel_switch(struct ieee80211_hw *hw,
+                              struct ieee80211_channel_switch *ch_switch);
+
+void il4965_led_enable(struct il_priv *il);
+
+/* EEPROM */
+#define IL4965_EEPROM_IMG_SIZE                 1024
+
+/*
+ * uCode queue management definitions ...
+ * The first queue used for block-ack aggregation is #7 (4965 only).
+ * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7.
+ */
+#define IL49_FIRST_AMPDU_QUEUE 7
+
+/* Sizes and addresses for instruction and data memory (SRAM) in
+ * 4965's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
+#define IL49_RTC_INST_LOWER_BOUND              (0x000000)
+#define IL49_RTC_INST_UPPER_BOUND              (0x018000)
+
+#define IL49_RTC_DATA_LOWER_BOUND              (0x800000)
+#define IL49_RTC_DATA_UPPER_BOUND              (0x80A000)
+
+#define IL49_RTC_INST_SIZE  (IL49_RTC_INST_UPPER_BOUND - \
+                               IL49_RTC_INST_LOWER_BOUND)
+#define IL49_RTC_DATA_SIZE  (IL49_RTC_DATA_UPPER_BOUND - \
+                               IL49_RTC_DATA_LOWER_BOUND)
+
+#define IL49_MAX_INST_SIZE IL49_RTC_INST_SIZE
+#define IL49_MAX_DATA_SIZE IL49_RTC_DATA_SIZE
+
+/* Size of uCode instruction memory in bootstrap state machine */
+#define IL49_MAX_BSM_SIZE BSM_SRAM_SIZE
+
+static inline int
+il4965_hw_valid_rtc_data_addr(u32 addr)
+{
+       return (addr >= IL49_RTC_DATA_LOWER_BOUND &&
+               addr < IL49_RTC_DATA_UPPER_BOUND);
+}
+
+/********************* START TEMPERATURE *************************************/
+
+/**
+ * 4965 temperature calculation.
+ *
+ * The driver must calculate the device temperature before calculating
+ * a txpower setting (amplifier gain is temperature dependent).  The
+ * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration
+ * values used for the life of the driver, and one of which (R4) is the
+ * real-time temperature indicator.
+ *
+ * uCode provides all 4 values to the driver via the "initialize alive"
+ * notification (see struct il4965_init_alive_resp).  After the runtime uCode
+ * image loads, uCode updates the R4 value via stats notifications
+ * (see N_STATS), which occur after each received beacon
+ * when associated, or can be requested via C_STATS.
+ *
+ * NOTE:  uCode provides the R4 value as a 23-bit signed value.  Driver
+ *        must sign-extend to 32 bits before applying formula below.
+ *
+ * Formula:
+ *
+ * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8
+ *
+ * NOTE:  The basic formula is 259 * (R4-R2) / (R3-R1).  The 97/100 is
+ * an additional correction, which should be centered around 0 degrees
+ * Celsius (273 degrees Kelvin).  The 8 (3 percent of 273) compensates for
+ * centering the 97/100 correction around 0 degrees K.
+ *
+ * Add 273 to Kelvin value to find degrees Celsius, for comparing current
+ * temperature with factory-measured temperatures when calculating txpower
+ * settings.
+ */
+#define TEMPERATURE_CALIB_KELVIN_OFFSET 8
+#define TEMPERATURE_CALIB_A_VAL 259
+
+/* Limit range of calculated temperature to be between these Kelvin values */
+#define IL_TX_POWER_TEMPERATURE_MIN  (263)
+#define IL_TX_POWER_TEMPERATURE_MAX  (410)
+
+#define IL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(t) \
+       ((t) < IL_TX_POWER_TEMPERATURE_MIN || \
+        (t) > IL_TX_POWER_TEMPERATURE_MAX)
+
+/********************* END TEMPERATURE ***************************************/
+
+/********************* START TXPOWER *****************************************/
+
+/**
+ * 4965 txpower calculations rely on information from three sources:
+ *
+ *     1) EEPROM
+ *     2) "initialize" alive notification
+ *     3) stats notifications
+ *
+ * EEPROM data consists of:
+ *
+ * 1)  Regulatory information (max txpower and channel usage flags) is provided
+ *     separately for each channel that can possibly supported by 4965.
+ *     40 MHz wide (.11n HT40) channels are listed separately from 20 MHz
+ *     (legacy) channels.
+ *
+ *     See struct il4965_eeprom_channel for format, and struct il4965_eeprom
+ *     for locations in EEPROM.
+ *
+ * 2)  Factory txpower calibration information is provided separately for
+ *     sub-bands of contiguous channels.  2.4GHz has just one sub-band,
+ *     but 5 GHz has several sub-bands.
+ *
+ *     In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided.
+ *
+ *     See struct il4965_eeprom_calib_info (and the tree of structures
+ *     contained within it) for format, and struct il4965_eeprom for
+ *     locations in EEPROM.
+ *
+ * "Initialization alive" notification (see struct il4965_init_alive_resp)
+ * consists of:
+ *
+ * 1)  Temperature calculation parameters.
+ *
+ * 2)  Power supply voltage measurement.
+ *
+ * 3)  Tx gain compensation to balance 2 transmitters for MIMO use.
+ *
+ * Statistics notifications deliver:
+ *
+ * 1)  Current values for temperature param R4.
+ */
+
+/**
+ * To calculate a txpower setting for a given desired target txpower, channel,
+ * modulation bit rate, and transmitter chain (4965 has 2 transmitters to
+ * support MIMO and transmit diversity), driver must do the following:
+ *
+ * 1)  Compare desired txpower vs. (EEPROM) regulatory limit for this channel.
+ *     Do not exceed regulatory limit; reduce target txpower if necessary.
+ *
+ *     If setting up txpowers for MIMO rates (rate idxes 8-15, 24-31),
+ *     2 transmitters will be used simultaneously; driver must reduce the
+ *     regulatory limit by 3 dB (half-power) for each transmitter, so the
+ *     combined total output of the 2 transmitters is within regulatory limits.
+ *
+ *
+ * 2)  Compare target txpower vs. (EEPROM) saturation txpower *reduced by
+ *     backoff for this bit rate*.  Do not exceed (saturation - backoff[rate]);
+ *     reduce target txpower if necessary.
+ *
+ *     Backoff values below are in 1/2 dB units (equivalent to steps in
+ *     txpower gain tables):
+ *
+ *     OFDM 6 - 36 MBit:  10 steps (5 dB)
+ *     OFDM 48 MBit:      15 steps (7.5 dB)
+ *     OFDM 54 MBit:      17 steps (8.5 dB)
+ *     OFDM 60 MBit:      20 steps (10 dB)
+ *     CCK all rates:     10 steps (5 dB)
+ *
+ *     Backoff values apply to saturation txpower on a per-transmitter basis;
+ *     when using MIMO (2 transmitters), each transmitter uses the same
+ *     saturation level provided in EEPROM, and the same backoff values;
+ *     no reduction (such as with regulatory txpower limits) is required.
+ *
+ *     Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
+ *     widths and 40 Mhz (.11n HT40) channel widths; there is no separate
+ *     factory measurement for ht40 channels.
+ *
+ *     The result of this step is the final target txpower.  The rest of
+ *     the steps figure out the proper settings for the device to achieve
+ *     that target txpower.
+ *
+ *
+ * 3)  Determine (EEPROM) calibration sub band for the target channel, by
+ *     comparing against first and last channels in each sub band
+ *     (see struct il4965_eeprom_calib_subband_info).
+ *
+ *
+ * 4)  Linearly interpolate (EEPROM) factory calibration measurement sets,
+ *     referencing the 2 factory-measured (sample) channels within the sub band.
+ *
+ *     Interpolation is based on difference between target channel's frequency
+ *     and the sample channels' frequencies.  Since channel numbers are based
+ *     on frequency (5 MHz between each channel number), this is equivalent
+ *     to interpolating based on channel number differences.
+ *
+ *     Note that the sample channels may or may not be the channels at the
+ *     edges of the sub band.  The target channel may be "outside" of the
+ *     span of the sampled channels.
+ *
+ *     Driver may choose the pair (for 2 Tx chains) of measurements (see
+ *     struct il4965_eeprom_calib_ch_info) for which the actual measured
+ *     txpower comes closest to the desired txpower.  Usually, though,
+ *     the middle set of measurements is closest to the regulatory limits,
+ *     and is therefore a good choice for all txpower calculations (this
+ *     assumes that high accuracy is needed for maximizing legal txpower,
+ *     while lower txpower configurations do not need as much accuracy).
+ *
+ *     Driver should interpolate both members of the chosen measurement pair,
+ *     i.e. for both Tx chains (radio transmitters), unless the driver knows
+ *     that only one of the chains will be used (e.g. only one tx antenna
+ *     connected, but this should be unusual).  The rate scaling algorithm
+ *     switches antennas to find best performance, so both Tx chains will
+ *     be used (although only one at a time) even for non-MIMO transmissions.
+ *
+ *     Driver should interpolate factory values for temperature, gain table
+ *     idx, and actual power.  The power amplifier detector values are
+ *     not used by the driver.
+ *
+ *     Sanity check:  If the target channel happens to be one of the sample
+ *     channels, the results should agree with the sample channel's
+ *     measurements!
+ *
+ *
+ * 5)  Find difference between desired txpower and (interpolated)
+ *     factory-measured txpower.  Using (interpolated) factory gain table idx
+ *     (shown elsewhere) as a starting point, adjust this idx lower to
+ *     increase txpower, or higher to decrease txpower, until the target
+ *     txpower is reached.  Each step in the gain table is 1/2 dB.
+ *
+ *     For example, if factory measured txpower is 16 dBm, and target txpower
+ *     is 13 dBm, add 6 steps to the factory gain idx to reduce txpower
+ *     by 3 dB.
+ *
+ *
+ * 6)  Find difference between current device temperature and (interpolated)
+ *     factory-measured temperature for sub-band.  Factory values are in
+ *     degrees Celsius.  To calculate current temperature, see comments for
+ *     "4965 temperature calculation".
+ *
+ *     If current temperature is higher than factory temperature, driver must
+ *     increase gain (lower gain table idx), and vice verse.
+ *
+ *     Temperature affects gain differently for different channels:
+ *
+ *     2.4 GHz all channels:  3.5 degrees per half-dB step
+ *     5 GHz channels 34-43:  4.5 degrees per half-dB step
+ *     5 GHz channels >= 44:  4.0 degrees per half-dB step
+ *
+ *     NOTE:  Temperature can increase rapidly when transmitting, especially
+ *            with heavy traffic at high txpowers.  Driver should update
+ *            temperature calculations often under these conditions to
+ *            maintain strong txpower in the face of rising temperature.
+ *
+ *
+ * 7)  Find difference between current power supply voltage indicator
+ *     (from "initialize alive") and factory-measured power supply voltage
+ *     indicator (EEPROM).
+ *
+ *     If the current voltage is higher (indicator is lower) than factory
+ *     voltage, gain should be reduced (gain table idx increased) by:
+ *
+ *     (eeprom - current) / 7
+ *
+ *     If the current voltage is lower (indicator is higher) than factory
+ *     voltage, gain should be increased (gain table idx decreased) by:
+ *
+ *     2 * (current - eeprom) / 7
+ *
+ *     If number of idx steps in either direction turns out to be > 2,
+ *     something is wrong ... just use 0.
+ *
+ *     NOTE:  Voltage compensation is independent of band/channel.
+ *
+ *     NOTE:  "Initialize" uCode measures current voltage, which is assumed
+ *            to be constant after this initial measurement.  Voltage
+ *            compensation for txpower (number of steps in gain table)
+ *            may be calculated once and used until the next uCode bootload.
+ *
+ *
+ * 8)  If setting up txpowers for MIMO rates (rate idxes 8-15, 24-31),
+ *     adjust txpower for each transmitter chain, so txpower is balanced
+ *     between the two chains.  There are 5 pairs of tx_atten[group][chain]
+ *     values in "initialize alive", one pair for each of 5 channel ranges:
+ *
+ *     Group 0:  5 GHz channel 34-43
+ *     Group 1:  5 GHz channel 44-70
+ *     Group 2:  5 GHz channel 71-124
+ *     Group 3:  5 GHz channel 125-200
+ *     Group 4:  2.4 GHz all channels
+ *
+ *     Add the tx_atten[group][chain] value to the idx for the target chain.
+ *     The values are signed, but are in pairs of 0 and a non-negative number,
+ *     so as to reduce gain (if necessary) of the "hotter" channel.  This
+ *     avoids any need to double-check for regulatory compliance after
+ *     this step.
+ *
+ *
+ * 9)  If setting up for a CCK rate, lower the gain by adding a CCK compensation
+ *     value to the idx:
+ *
+ *     Hardware rev B:  9 steps (4.5 dB)
+ *     Hardware rev C:  5 steps (2.5 dB)
+ *
+ *     Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
+ *     bits [3:2], 1 = B, 2 = C.
+ *
+ *     NOTE:  This compensation is in addition to any saturation backoff that
+ *            might have been applied in an earlier step.
+ *
+ *
+ * 10) Select the gain table, based on band (2.4 vs 5 GHz).
+ *
+ *     Limit the adjusted idx to stay within the table!
+ *
+ *
+ * 11) Read gain table entries for DSP and radio gain, place into appropriate
+ *     location(s) in command (struct il4965_txpowertable_cmd).
+ */
+
+/**
+ * When MIMO is used (2 transmitters operating simultaneously), driver should
+ * limit each transmitter to deliver a max of 3 dB below the regulatory limit
+ * for the device.  That is, use half power for each transmitter, so total
+ * txpower is within regulatory limits.
+ *
+ * The value "6" represents number of steps in gain table to reduce power 3 dB.
+ * Each step is 1/2 dB.
+ */
+#define IL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6)
+
+/**
+ * CCK gain compensation.
+ *
+ * When calculating txpowers for CCK, after making sure that the target power
+ * is within regulatory and saturation limits, driver must additionally
+ * back off gain by adding these values to the gain table idx.
+ *
+ * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
+ * bits [3:2], 1 = B, 2 = C.
+ */
+#define IL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
+#define IL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
+
+/*
+ * 4965 power supply voltage compensation for txpower
+ */
+#define TX_POWER_IL_VOLTAGE_CODES_PER_03V   (7)
+
+/**
+ * Gain tables.
+ *
+ * The following tables contain pair of values for setting txpower, i.e.
+ * gain settings for the output of the device's digital signal processor (DSP),
+ * and for the analog gain structure of the transmitter.
+ *
+ * Each entry in the gain tables represents a step of 1/2 dB.  Note that these
+ * are *relative* steps, not indications of absolute output power.  Output
+ * power varies with temperature, voltage, and channel frequency, and also
+ * requires consideration of average power (to satisfy regulatory constraints),
+ * and peak power (to avoid distortion of the output signal).
+ *
+ * Each entry contains two values:
+ * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
+ *     linear value that multiplies the output of the digital signal processor,
+ *     before being sent to the analog radio.
+ * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
+ *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
+ *
+ * EEPROM contains factory calibration data for txpower.  This maps actual
+ * measured txpower levels to gain settings in the "well known" tables
+ * below ("well-known" means here that both factory calibration *and* the
+ * driver work with the same table).
+ *
+ * There are separate tables for 2.4 GHz and 5 GHz bands.  The 5 GHz table
+ * has an extension (into negative idxes), in case the driver needs to
+ * boost power setting for high device temperatures (higher than would be
+ * present during factory calibration).  A 5 Ghz EEPROM idx of "40"
+ * corresponds to the 49th entry in the table used by the driver.
+ */
+#define MIN_TX_GAIN_IDX                (0)     /* highest gain, lowest idx, 2.4 */
+#define MIN_TX_GAIN_IDX_52GHZ_EXT      (-9)    /* highest gain, lowest idx, 5 */
+
+/**
+ * 2.4 GHz gain table
+ *
+ * Index    Dsp gain   Radio gain
+ *   0        110         0x3f      (highest gain)
+ *   1        104         0x3f
+ *   2         98         0x3f
+ *   3        110         0x3e
+ *   4        104         0x3e
+ *   5         98         0x3e
+ *   6        110         0x3d
+ *   7        104         0x3d
+ *   8         98         0x3d
+ *   9        110         0x3c
+ *  10        104         0x3c
+ *  11         98         0x3c
+ *  12        110         0x3b
+ *  13        104         0x3b
+ *  14         98         0x3b
+ *  15        110         0x3a
+ *  16        104         0x3a
+ *  17         98         0x3a
+ *  18        110         0x39
+ *  19        104         0x39
+ *  20         98         0x39
+ *  21        110         0x38
+ *  22        104         0x38
+ *  23         98         0x38
+ *  24        110         0x37
+ *  25        104         0x37
+ *  26         98         0x37
+ *  27        110         0x36
+ *  28        104         0x36
+ *  29         98         0x36
+ *  30        110         0x35
+ *  31        104         0x35
+ *  32         98         0x35
+ *  33        110         0x34
+ *  34        104         0x34
+ *  35         98         0x34
+ *  36        110         0x33
+ *  37        104         0x33
+ *  38         98         0x33
+ *  39        110         0x32
+ *  40        104         0x32
+ *  41         98         0x32
+ *  42        110         0x31
+ *  43        104         0x31
+ *  44         98         0x31
+ *  45        110         0x30
+ *  46        104         0x30
+ *  47         98         0x30
+ *  48        110          0x6
+ *  49        104          0x6
+ *  50         98          0x6
+ *  51        110          0x5
+ *  52        104          0x5
+ *  53         98          0x5
+ *  54        110          0x4
+ *  55        104          0x4
+ *  56         98          0x4
+ *  57        110          0x3
+ *  58        104          0x3
+ *  59         98          0x3
+ *  60        110          0x2
+ *  61        104          0x2
+ *  62         98          0x2
+ *  63        110          0x1
+ *  64        104          0x1
+ *  65         98          0x1
+ *  66        110          0x0
+ *  67        104          0x0
+ *  68         98          0x0
+ *  69         97            0
+ *  70         96            0
+ *  71         95            0
+ *  72         94            0
+ *  73         93            0
+ *  74         92            0
+ *  75         91            0
+ *  76         90            0
+ *  77         89            0
+ *  78         88            0
+ *  79         87            0
+ *  80         86            0
+ *  81         85            0
+ *  82         84            0
+ *  83         83            0
+ *  84         82            0
+ *  85         81            0
+ *  86         80            0
+ *  87         79            0
+ *  88         78            0
+ *  89         77            0
+ *  90         76            0
+ *  91         75            0
+ *  92         74            0
+ *  93         73            0
+ *  94         72            0
+ *  95         71            0
+ *  96         70            0
+ *  97         69            0
+ *  98         68            0
+ */
+
+/**
+ * 5 GHz gain table
+ *
+ * Index    Dsp gain   Radio gain
+ *  -9               123         0x3F      (highest gain)
+ *  -8               117         0x3F
+ *  -7        110         0x3F
+ *  -6        104         0x3F
+ *  -5         98         0x3F
+ *  -4        110         0x3E
+ *  -3        104         0x3E
+ *  -2         98         0x3E
+ *  -1        110         0x3D
+ *   0        104         0x3D
+ *   1         98         0x3D
+ *   2        110         0x3C
+ *   3        104         0x3C
+ *   4         98         0x3C
+ *   5        110         0x3B
+ *   6        104         0x3B
+ *   7         98         0x3B
+ *   8        110         0x3A
+ *   9        104         0x3A
+ *  10         98         0x3A
+ *  11        110         0x39
+ *  12        104         0x39
+ *  13         98         0x39
+ *  14        110         0x38
+ *  15        104         0x38
+ *  16         98         0x38
+ *  17        110         0x37
+ *  18        104         0x37
+ *  19         98         0x37
+ *  20        110         0x36
+ *  21        104         0x36
+ *  22         98         0x36
+ *  23        110         0x35
+ *  24        104         0x35
+ *  25         98         0x35
+ *  26        110         0x34
+ *  27        104         0x34
+ *  28         98         0x34
+ *  29        110         0x33
+ *  30        104         0x33
+ *  31         98         0x33
+ *  32        110         0x32
+ *  33        104         0x32
+ *  34         98         0x32
+ *  35        110         0x31
+ *  36        104         0x31
+ *  37         98         0x31
+ *  38        110         0x30
+ *  39        104         0x30
+ *  40         98         0x30
+ *  41        110         0x25
+ *  42        104         0x25
+ *  43         98         0x25
+ *  44        110         0x24
+ *  45        104         0x24
+ *  46         98         0x24
+ *  47        110         0x23
+ *  48        104         0x23
+ *  49         98         0x23
+ *  50        110         0x22
+ *  51        104         0x18
+ *  52         98         0x18
+ *  53        110         0x17
+ *  54        104         0x17
+ *  55         98         0x17
+ *  56        110         0x16
+ *  57        104         0x16
+ *  58         98         0x16
+ *  59        110         0x15
+ *  60        104         0x15
+ *  61         98         0x15
+ *  62        110         0x14
+ *  63        104         0x14
+ *  64         98         0x14
+ *  65        110         0x13
+ *  66        104         0x13
+ *  67         98         0x13
+ *  68        110         0x12
+ *  69        104         0x08
+ *  70         98         0x08
+ *  71        110         0x07
+ *  72        104         0x07
+ *  73         98         0x07
+ *  74        110         0x06
+ *  75        104         0x06
+ *  76         98         0x06
+ *  77        110         0x05
+ *  78        104         0x05
+ *  79         98         0x05
+ *  80        110         0x04
+ *  81        104         0x04
+ *  82         98         0x04
+ *  83        110         0x03
+ *  84        104         0x03
+ *  85         98         0x03
+ *  86        110         0x02
+ *  87        104         0x02
+ *  88         98         0x02
+ *  89        110         0x01
+ *  90        104         0x01
+ *  91         98         0x01
+ *  92        110         0x00
+ *  93        104         0x00
+ *  94         98         0x00
+ *  95         93         0x00
+ *  96         88         0x00
+ *  97         83         0x00
+ *  98         78         0x00
+ */
+
+/**
+ * Sanity checks and default values for EEPROM regulatory levels.
+ * If EEPROM values fall outside MIN/MAX range, use default values.
+ *
+ * Regulatory limits refer to the maximum average txpower allowed by
+ * regulatory agencies in the geographies in which the device is meant
+ * to be operated.  These limits are SKU-specific (i.e. geography-specific),
+ * and channel-specific; each channel has an individual regulatory limit
+ * listed in the EEPROM.
+ *
+ * Units are in half-dBm (i.e. "34" means 17 dBm).
+ */
+#define IL_TX_POWER_DEFAULT_REGULATORY_24   (34)
+#define IL_TX_POWER_DEFAULT_REGULATORY_52   (34)
+#define IL_TX_POWER_REGULATORY_MIN          (0)
+#define IL_TX_POWER_REGULATORY_MAX          (34)
+
+/**
+ * Sanity checks and default values for EEPROM saturation levels.
+ * If EEPROM values fall outside MIN/MAX range, use default values.
+ *
+ * Saturation is the highest level that the output power amplifier can produce
+ * without significant clipping distortion.  This is a "peak" power level.
+ * Different types of modulation (i.e. various "rates", and OFDM vs. CCK)
+ * require differing amounts of backoff, relative to their average power output,
+ * in order to avoid clipping distortion.
+ *
+ * Driver must make sure that it is violating neither the saturation limit,
+ * nor the regulatory limit, when calculating Tx power settings for various
+ * rates.
+ *
+ * Units are in half-dBm (i.e. "38" means 19 dBm).
+ */
+#define IL_TX_POWER_DEFAULT_SATURATION_24   (38)
+#define IL_TX_POWER_DEFAULT_SATURATION_52   (38)
+#define IL_TX_POWER_SATURATION_MIN          (20)
+#define IL_TX_POWER_SATURATION_MAX          (50)
+
+/**
+ * Channel groups used for Tx Attenuation calibration (MIMO tx channel balance)
+ * and thermal Txpower calibration.
+ *
+ * When calculating txpower, driver must compensate for current device
+ * temperature; higher temperature requires higher gain.  Driver must calculate
+ * current temperature (see "4965 temperature calculation"), then compare vs.
+ * factory calibration temperature in EEPROM; if current temperature is higher
+ * than factory temperature, driver must *increase* gain by proportions shown
+ * in table below.  If current temperature is lower than factory, driver must
+ * *decrease* gain.
+ *
+ * Different frequency ranges require different compensation, as shown below.
+ */
+/* Group 0, 5.2 GHz ch 34-43:  4.5 degrees per 1/2 dB. */
+#define CALIB_IL_TX_ATTEN_GR1_FCH 34
+#define CALIB_IL_TX_ATTEN_GR1_LCH 43
+
+/* Group 1, 5.3 GHz ch 44-70:  4.0 degrees per 1/2 dB. */
+#define CALIB_IL_TX_ATTEN_GR2_FCH 44
+#define CALIB_IL_TX_ATTEN_GR2_LCH 70
+
+/* Group 2, 5.5 GHz ch 71-124:  4.0 degrees per 1/2 dB. */
+#define CALIB_IL_TX_ATTEN_GR3_FCH 71
+#define CALIB_IL_TX_ATTEN_GR3_LCH 124
+
+/* Group 3, 5.7 GHz ch 125-200:  4.0 degrees per 1/2 dB. */
+#define CALIB_IL_TX_ATTEN_GR4_FCH 125
+#define CALIB_IL_TX_ATTEN_GR4_LCH 200
+
+/* Group 4, 2.4 GHz all channels:  3.5 degrees per 1/2 dB. */
+#define CALIB_IL_TX_ATTEN_GR5_FCH 1
+#define CALIB_IL_TX_ATTEN_GR5_LCH 20
+
+enum {
+       CALIB_CH_GROUP_1 = 0,
+       CALIB_CH_GROUP_2 = 1,
+       CALIB_CH_GROUP_3 = 2,
+       CALIB_CH_GROUP_4 = 3,
+       CALIB_CH_GROUP_5 = 4,
+       CALIB_CH_GROUP_MAX
+};
+
+/********************* END TXPOWER *****************************************/
+
+/**
+ * Tx/Rx Queues
+ *
+ * Most communication between driver and 4965 is via queues of data buffers.
+ * For example, all commands that the driver issues to device's embedded
+ * controller (uCode) are via the command queue (one of the Tx queues).  All
+ * uCode command responses/replies/notifications, including Rx frames, are
+ * conveyed from uCode to driver via the Rx queue.
+ *
+ * Most support for these queues, including handshake support, resides in
+ * structures in host DRAM, shared between the driver and the device.  When
+ * allocating this memory, the driver must make sure that data written by
+ * the host CPU updates DRAM immediately (and does not get "stuck" in CPU's
+ * cache memory), so DRAM and cache are consistent, and the device can
+ * immediately see changes made by the driver.
+ *
+ * 4965 supports up to 16 DRAM-based Tx queues, and services these queues via
+ * up to 7 DMA channels (FIFOs).  Each Tx queue is supported by a circular array
+ * in DRAM containing 256 Transmit Frame Descriptors (TFDs).
+ */
+#define IL49_NUM_FIFOS 7
+#define IL49_CMD_FIFO_NUM      4
+#define IL49_NUM_QUEUES        16
+#define IL49_NUM_AMPDU_QUEUES  8
+
+/**
+ * struct il4965_schedq_bc_tbl
+ *
+ * Byte Count table
+ *
+ * Each Tx queue uses a byte-count table containing 320 entries:
+ * one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that
+ * duplicate the first 64 entries (to avoid wrap-around within a Tx win;
+ * max Tx win is 64 TFDs).
+ *
+ * When driver sets up a new TFD, it must also enter the total byte count
+ * of the frame to be transmitted into the corresponding entry in the byte
+ * count table for the chosen Tx queue.  If the TFD idx is 0-63, the driver
+ * must duplicate the byte count entry in corresponding idx 256-319.
+ *
+ * padding puts each byte count table on a 1024-byte boundary;
+ * 4965 assumes tables are separated by 1024 bytes.
+ */
+struct il4965_scd_bc_tbl {
+       __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
+       u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
+} __packed;
+
+#define IL4965_RTC_INST_LOWER_BOUND            (0x000000)
+
+/* RSSI to dBm */
+#define IL4965_RSSI_OFFSET     44
+
+/* PCI registers */
+#define PCI_CFG_RETRY_TIMEOUT  0x041
+
+/* PCI register values */
+#define PCI_CFG_LINK_CTRL_VAL_L0S_EN   0x01
+#define PCI_CFG_LINK_CTRL_VAL_L1_EN    0x02
+
+#define IL4965_DEFAULT_TX_RETRY  15
+
+/* EEPROM */
+#define IL4965_FIRST_AMPDU_QUEUE       10
+
+/* Calibration */
+void il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp);
+void il4965_sensitivity_calibration(struct il_priv *il, void *resp);
+void il4965_init_sensitivity(struct il_priv *il);
+void il4965_reset_run_time_calib(struct il_priv *il);
+void il4965_calib_free_results(struct il_priv *il);
+
+/* Debug */
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+ssize_t il4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+                                  size_t count, loff_t *ppos);
+ssize_t il4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+                                  size_t count, loff_t *ppos);
+ssize_t il4965_ucode_general_stats_read(struct file *file,
+                                       char __user *user_buf, size_t count,
+                                       loff_t *ppos);
+#endif
+
+/****************************/
+/* Flow Handler Definitions */
+/****************************/
+
+/**
+ * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
+ * Addresses are offsets from device's PCI hardware base address.
+ */
+#define FH49_MEM_LOWER_BOUND                   (0x1000)
+#define FH49_MEM_UPPER_BOUND                   (0x2000)
+
+/**
+ * Keep-Warm (KW) buffer base address.
+ *
+ * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the
+ * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency
+ * DRAM access when 4965 is Txing or Rxing.  The dummy accesses prevent host
+ * from going into a power-savings mode that would cause higher DRAM latency,
+ * and possible data over/under-runs, before all Tx/Rx is complete.
+ *
+ * Driver loads FH49_KW_MEM_ADDR_REG with the physical address (bits 35:4)
+ * of the buffer, which must be 4K aligned.  Once this is set up, the 4965
+ * automatically invokes keep-warm accesses when normal accesses might not
+ * be sufficient to maintain fast DRAM response.
+ *
+ * Bit fields:
+ *  31-0:  Keep-warm buffer physical base address [35:4], must be 4K aligned
+ */
+#define FH49_KW_MEM_ADDR_REG                (FH49_MEM_LOWER_BOUND + 0x97C)
+
+/**
+ * TFD Circular Buffers Base (CBBC) addresses
+ *
+ * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident
+ * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)
+ * (see struct il_tfd_frame).  These 16 pointer registers are offset by 0x04
+ * bytes from one another.  Each TFD circular buffer in DRAM must be 256-byte
+ * aligned (address bits 0-7 must be 0).
+ *
+ * Bit fields in each pointer register:
+ *  27-0: TFD CB physical base address [35:8], must be 256-byte aligned
+ */
+#define FH49_MEM_CBBC_LOWER_BOUND          (FH49_MEM_LOWER_BOUND + 0x9D0)
+#define FH49_MEM_CBBC_UPPER_BOUND          (FH49_MEM_LOWER_BOUND + 0xA10)
+
+/* Find TFD CB base pointer for given queue (range 0-15). */
+#define FH49_MEM_CBBC_QUEUE(x)  (FH49_MEM_CBBC_LOWER_BOUND + (x) * 0x4)
+
+/**
+ * Rx SRAM Control and Status Registers (RSCSR)
+ *
+ * These registers provide handshake between driver and 4965 for the Rx queue
+ * (this queue handles *all* command responses, notifications, Rx data, etc.
+ * sent from 4965 uCode to host driver).  Unlike Tx, there is only one Rx
+ * queue, and only one Rx DMA/FIFO channel.  Also unlike Tx, which can
+ * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer
+ * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1
+ * mapping between RBDs and RBs.
+ *
+ * Driver must allocate host DRAM memory for the following, and set the
+ * physical address of each into 4965 registers:
+ *
+ * 1)  Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256
+ *     entries (although any power of 2, up to 4096, is selectable by driver).
+ *     Each entry (1 dword) points to a receive buffer (RB) of consistent size
+ *     (typically 4K, although 8K or 16K are also selectable by driver).
+ *     Driver sets up RB size and number of RBDs in the CB via Rx config
+ *     register FH49_MEM_RCSR_CHNL0_CONFIG_REG.
+ *
+ *     Bit fields within one RBD:
+ *     27-0:  Receive Buffer physical address bits [35:8], 256-byte aligned
+ *
+ *     Driver sets physical address [35:8] of base of RBD circular buffer
+ *     into FH49_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].
+ *
+ * 2)  Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers
+ *     (RBs) have been filled, via a "write pointer", actually the idx of
+ *     the RB's corresponding RBD within the circular buffer.  Driver sets
+ *     physical address [35:4] into FH49_RSCSR_CHNL0_STTS_WPTR_REG [31:0].
+ *
+ *     Bit fields in lower dword of Rx status buffer (upper dword not used
+ *     by driver; see struct il4965_shared, val0):
+ *     31-12:  Not used by driver
+ *     11- 0:  Index of last filled Rx buffer descriptor
+ *             (4965 writes, driver reads this value)
+ *
+ * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must
+ * enter pointers to these RBs into contiguous RBD circular buffer entries,
+ * and update the 4965's "write" idx register,
+ * FH49_RSCSR_CHNL0_RBDCB_WPTR_REG.
+ *
+ * This "write" idx corresponds to the *next* RBD that the driver will make
+ * available, i.e. one RBD past the tail of the ready-to-fill RBDs within
+ * the circular buffer.  This value should initially be 0 (before preparing any
+ * RBs), should be 8 after preparing the first 8 RBs (for example), and must
+ * wrap back to 0 at the end of the circular buffer (but don't wrap before
+ * "read" idx has advanced past 1!  See below).
+ * NOTE:  4965 EXPECTS THE WRITE IDX TO BE INCREMENTED IN MULTIPLES OF 8.
+ *
+ * As the 4965 fills RBs (referenced from contiguous RBDs within the circular
+ * buffer), it updates the Rx status buffer in host DRAM, 2) described above,
+ * to tell the driver the idx of the latest filled RBD.  The driver must
+ * read this "read" idx from DRAM after receiving an Rx interrupt from 4965.
+ *
+ * The driver must also internally keep track of a third idx, which is the
+ * next RBD to process.  When receiving an Rx interrupt, driver should process
+ * all filled but unprocessed RBs up to, but not including, the RB
+ * corresponding to the "read" idx.  For example, if "read" idx becomes "1",
+ * driver may process the RB pointed to by RBD 0.  Depending on volume of
+ * traffic, there may be many RBs to process.
+ *
+ * If read idx == write idx, 4965 thinks there is no room to put new data.
+ * Due to this, the maximum number of filled RBs is 255, instead of 256.  To
+ * be safe, make sure that there is a gap of at least 2 RBDs between "write"
+ * and "read" idxes; that is, make sure that there are no more than 254
+ * buffers waiting to be filled.
+ */
+#define FH49_MEM_RSCSR_LOWER_BOUND     (FH49_MEM_LOWER_BOUND + 0xBC0)
+#define FH49_MEM_RSCSR_UPPER_BOUND     (FH49_MEM_LOWER_BOUND + 0xC00)
+#define FH49_MEM_RSCSR_CHNL0           (FH49_MEM_RSCSR_LOWER_BOUND)
+
+/**
+ * Physical base address of 8-byte Rx Status buffer.
+ * Bit fields:
+ *  31-0: Rx status buffer physical base address [35:4], must 16-byte aligned.
+ */
+#define FH49_RSCSR_CHNL0_STTS_WPTR_REG (FH49_MEM_RSCSR_CHNL0)
+
+/**
+ * Physical base address of Rx Buffer Descriptor Circular Buffer.
+ * Bit fields:
+ *  27-0:  RBD CD physical base address [35:8], must be 256-byte aligned.
+ */
+#define FH49_RSCSR_CHNL0_RBDCB_BASE_REG        (FH49_MEM_RSCSR_CHNL0 + 0x004)
+
+/**
+ * Rx write pointer (idx, really!).
+ * Bit fields:
+ *  11-0:  Index of driver's most recent prepared-to-be-filled RBD, + 1.
+ *         NOTE:  For 256-entry circular buffer, use only bits [7:0].
+ */
+#define FH49_RSCSR_CHNL0_RBDCB_WPTR_REG        (FH49_MEM_RSCSR_CHNL0 + 0x008)
+#define FH49_RSCSR_CHNL0_WPTR        (FH49_RSCSR_CHNL0_RBDCB_WPTR_REG)
+
+/**
+ * Rx Config/Status Registers (RCSR)
+ * Rx Config Reg for channel 0 (only channel used)
+ *
+ * Driver must initialize FH49_MEM_RCSR_CHNL0_CONFIG_REG as follows for
+ * normal operation (see bit fields).
+ *
+ * Clearing FH49_MEM_RCSR_CHNL0_CONFIG_REG to 0 turns off Rx DMA.
+ * Driver should poll FH49_MEM_RSSR_RX_STATUS_REG      for
+ * FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (bit 24) before continuing.
+ *
+ * Bit fields:
+ * 31-30: Rx DMA channel enable: '00' off/pause, '01' pause at end of frame,
+ *        '10' operate normally
+ * 29-24: reserved
+ * 23-20: # RBDs in circular buffer = 2^value; use "8" for 256 RBDs (normal),
+ *        min "5" for 32 RBDs, max "12" for 4096 RBDs.
+ * 19-18: reserved
+ * 17-16: size of each receive buffer; '00' 4K (normal), '01' 8K,
+ *        '10' 12K, '11' 16K.
+ * 15-14: reserved
+ * 13-12: IRQ destination; '00' none, '01' host driver (normal operation)
+ * 11- 4: timeout for closing Rx buffer and interrupting host (units 32 usec)
+ *        typical value 0x10 (about 1/2 msec)
+ *  3- 0: reserved
+ */
+#define FH49_MEM_RCSR_LOWER_BOUND      (FH49_MEM_LOWER_BOUND + 0xC00)
+#define FH49_MEM_RCSR_UPPER_BOUND      (FH49_MEM_LOWER_BOUND + 0xCC0)
+#define FH49_MEM_RCSR_CHNL0            (FH49_MEM_RCSR_LOWER_BOUND)
+
+#define FH49_MEM_RCSR_CHNL0_CONFIG_REG (FH49_MEM_RCSR_CHNL0)
+
+#define FH49_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0)  /* bits 4-11 */
+#define FH49_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK   (0x00001000)  /* bits 12 */
+#define FH49_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK (0x00008000)        /* bit 15 */
+#define FH49_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MSK   (0x00030000)   /* bits 16-17 */
+#define FH49_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000)  /* bits 20-23 */
+#define FH49_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31 */
+
+#define FH49_RCSR_RX_CONFIG_RBDCB_SIZE_POS     (20)
+#define FH49_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS   (4)
+#define RX_RB_TIMEOUT  (0x10)
+
+#define FH49_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL         (0x00000000)
+#define FH49_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL     (0x40000000)
+#define FH49_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL        (0x80000000)
+
+#define FH49_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K    (0x00000000)
+#define FH49_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K    (0x00010000)
+#define FH49_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K   (0x00020000)
+#define FH49_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K   (0x00030000)
+
+#define FH49_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY              (0x00000004)
+#define FH49_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL    (0x00000000)
+#define FH49_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL  (0x00001000)
+
+/**
+ * Rx Shared Status Registers (RSSR)
+ *
+ * After stopping Rx DMA channel (writing 0 to
+ * FH49_MEM_RCSR_CHNL0_CONFIG_REG), driver must poll
+ * FH49_MEM_RSSR_RX_STATUS_REG until Rx channel is idle.
+ *
+ * Bit fields:
+ *  24:  1 = Channel 0 is idle
+ *
+ * FH49_MEM_RSSR_SHARED_CTRL_REG and FH49_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV
+ * contain default values that should not be altered by the driver.
+ */
+#define FH49_MEM_RSSR_LOWER_BOUND           (FH49_MEM_LOWER_BOUND + 0xC40)
+#define FH49_MEM_RSSR_UPPER_BOUND           (FH49_MEM_LOWER_BOUND + 0xD00)
+
+#define FH49_MEM_RSSR_SHARED_CTRL_REG       (FH49_MEM_RSSR_LOWER_BOUND)
+#define FH49_MEM_RSSR_RX_STATUS_REG    (FH49_MEM_RSSR_LOWER_BOUND + 0x004)
+#define FH49_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV\
+                                       (FH49_MEM_RSSR_LOWER_BOUND + 0x008)
+
+#define FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE    (0x01000000)
+
+#define FH49_MEM_TFDIB_REG1_ADDR_BITSHIFT      28
+
+/* TFDB  Area - TFDs buffer table */
+#define FH49_MEM_TFDIB_DRAM_ADDR_LSB_MSK      (0xFFFFFFFF)
+#define FH49_TFDIB_LOWER_BOUND       (FH49_MEM_LOWER_BOUND + 0x900)
+#define FH49_TFDIB_UPPER_BOUND       (FH49_MEM_LOWER_BOUND + 0x958)
+#define FH49_TFDIB_CTRL0_REG(_chnl)  (FH49_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
+#define FH49_TFDIB_CTRL1_REG(_chnl)  (FH49_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
+
+/**
+ * Transmit DMA Channel Control/Status Registers (TCSR)
+ *
+ * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels
+ * supported in hardware (don't confuse these with the 16 Tx queues in DRAM,
+ * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes.
+ *
+ * To use a Tx DMA channel, driver must initialize its
+ * FH49_TCSR_CHNL_TX_CONFIG_REG(chnl) with:
+ *
+ * FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ * FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL
+ *
+ * All other bits should be 0.
+ *
+ * Bit fields:
+ * 31-30: Tx DMA channel enable: '00' off/pause, '01' pause at end of frame,
+ *        '10' operate normally
+ * 29- 4: Reserved, set to "0"
+ *     3: Enable internal DMA requests (1, normal operation), disable (0)
+ *  2- 0: Reserved, set to "0"
+ */
+#define FH49_TCSR_LOWER_BOUND  (FH49_MEM_LOWER_BOUND + 0xD00)
+#define FH49_TCSR_UPPER_BOUND  (FH49_MEM_LOWER_BOUND + 0xE60)
+
+/* Find Control/Status reg for given Tx DMA/FIFO channel */
+#define FH49_TCSR_CHNL_NUM                            (7)
+#define FH50_TCSR_CHNL_NUM                            (8)
+
+/* TCSR: tx_config register values */
+#define FH49_TCSR_CHNL_TX_CONFIG_REG(_chnl)    \
+               (FH49_TCSR_LOWER_BOUND + 0x20 * (_chnl))
+#define FH49_TCSR_CHNL_TX_CREDIT_REG(_chnl)    \
+               (FH49_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x4)
+#define FH49_TCSR_CHNL_TX_BUF_STS_REG(_chnl)   \
+               (FH49_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x8)
+
+#define FH49_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF               (0x00000000)
+#define FH49_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRV               (0x00000001)
+
+#define FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE (0x00000000)
+#define FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE  (0x00000008)
+
+#define FH49_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT    (0x00000000)
+#define FH49_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD   (0x00100000)
+#define FH49_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD    (0x00200000)
+
+#define FH49_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT     (0x00000000)
+#define FH49_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD    (0x00400000)
+#define FH49_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD     (0x00800000)
+
+#define FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE     (0x00000000)
+#define FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF (0x40000000)
+#define FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE    (0x80000000)
+
+#define FH49_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY   (0x00000000)
+#define FH49_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT    (0x00002000)
+#define FH49_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID   (0x00000003)
+
+#define FH49_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM               (20)
+#define FH49_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX               (12)
+
+/**
+ * Tx Shared Status Registers (TSSR)
+ *
+ * After stopping Tx DMA channel (writing 0 to
+ * FH49_TCSR_CHNL_TX_CONFIG_REG(chnl)), driver must poll
+ * FH49_TSSR_TX_STATUS_REG until selected Tx channel is idle
+ * (channel's buffers empty | no pending requests).
+ *
+ * Bit fields:
+ * 31-24:  1 = Channel buffers empty (channel 7:0)
+ * 23-16:  1 = No pending requests (channel 7:0)
+ */
+#define FH49_TSSR_LOWER_BOUND          (FH49_MEM_LOWER_BOUND + 0xEA0)
+#define FH49_TSSR_UPPER_BOUND          (FH49_MEM_LOWER_BOUND + 0xEC0)
+
+#define FH49_TSSR_TX_STATUS_REG                (FH49_TSSR_LOWER_BOUND + 0x010)
+
+/**
+ * Bit fields for TSSR(Tx Shared Status & Control) error status register:
+ * 31:  Indicates an address error when accessed to internal memory
+ *     uCode/driver must write "1" in order to clear this flag
+ * 30:  Indicates that Host did not send the expected number of dwords to FH
+ *     uCode/driver must write "1" in order to clear this flag
+ * 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA
+ *     command was received from the scheduler while the TRB was already full
+ *     with previous command
+ *     uCode/driver must write "1" in order to clear this flag
+ * 7-0: Each status bit indicates a channel's TxCredit error. When an error
+ *     bit is set, it indicates that the FH has received a full indication
+ *     from the RTC TxFIFO and the current value of the TxCredit counter was
+ *     not equal to zero. This mean that the credit mechanism was not
+ *     synchronized to the TxFIFO status
+ *     uCode/driver must write "1" in order to clear this flag
+ */
+#define FH49_TSSR_TX_ERROR_REG         (FH49_TSSR_LOWER_BOUND + 0x018)
+
+#define FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16)
+
+/* Tx service channels */
+#define FH49_SRVC_CHNL         (9)
+#define FH49_SRVC_LOWER_BOUND  (FH49_MEM_LOWER_BOUND + 0x9C8)
+#define FH49_SRVC_UPPER_BOUND  (FH49_MEM_LOWER_BOUND + 0x9D0)
+#define FH49_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \
+               (FH49_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4)
+
+#define FH49_TX_CHICKEN_BITS_REG       (FH49_MEM_LOWER_BOUND + 0xE98)
+/* Instruct FH to increment the retry count of a packet when
+ * it is brought from the memory to TX-FIFO
+ */
+#define FH49_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002)
+
+/* Keep Warm Size */
+#define IL_KW_SIZE 0x1000      /* 4k */
+
+#endif /* __il_4965_h__ */
index aef65cd47661e39a62106b232eccb8054b382411..05bd375cb845b73fbf94401ba57bfc50c59d448d 100644 (file)
@@ -1,4 +1,4 @@
-config IWLWIFI_LEGACY
+config IWLEGACY
        tristate
        select FW_LOADER
        select NEW_LEDS
@@ -7,13 +7,13 @@ config IWLWIFI_LEGACY
        select MAC80211_LEDS
 
 menu "Debugging Options"
-       depends on IWLWIFI_LEGACY
+       depends on IWLEGACY
 
-config IWLWIFI_LEGACY_DEBUG
-       bool "Enable full debugging output in 4965 and 3945 drivers"
-       depends on IWLWIFI_LEGACY
+config IWLEGACY_DEBUG
+       bool "Enable full debugging output in iwlegacy (iwl 3945/4965) drivers"
+       depends on IWLEGACY
        ---help---
-         This option will enable debug tracing output for the iwlwifilegacy
+         This option will enable debug tracing output for the iwlegacy
          drivers.
 
          This will result in the kernel module being ~100k larger.  You can
@@ -29,43 +29,26 @@ config IWLWIFI_LEGACY_DEBUG
                  % echo 0x43fff > /sys/class/net/wlan0/device/debug_level
 
          You can find the list of debug mask values in:
-                 drivers/net/wireless/iwlwifilegacy/iwl-debug.h
+                 drivers/net/wireless/iwlegacy/common.h
 
          If this is your first time using this driver, you should say Y here
          as the debug information can assist others in helping you resolve
          any problems you may encounter.
 
-config IWLWIFI_LEGACY_DEBUGFS
-        bool "4965 and 3945 debugfs support"
-        depends on IWLWIFI_LEGACY && MAC80211_DEBUGFS
+config IWLEGACY_DEBUGFS
+        bool "iwlegacy (iwl 3945/4965) debugfs support"
+        depends on IWLEGACY && MAC80211_DEBUGFS
         ---help---
-         Enable creation of debugfs files for the iwlwifilegacy drivers. This
+         Enable creation of debugfs files for the iwlegacy drivers. This
          is a low-impact option that allows getting insight into the
          driver's state at runtime.
 
-config IWLWIFI_LEGACY_DEVICE_TRACING
-       bool "iwlwifilegacy legacy device access tracing"
-       depends on IWLWIFI_LEGACY
-       depends on EVENT_TRACING
-       help
-         Say Y here to trace all commands, including TX frames and IO
-         accesses, sent to the device. If you say yes, iwlwifilegacy will
-         register with the ftrace framework for event tracing and dump
-         all this information to the ringbuffer, you may need to
-         increase the ringbuffer size. See the ftrace documentation
-         for more information.
-
-         When tracing is not enabled, this option still has some
-         (though rather small) overhead.
-
-         If unsure, say Y so we can help you better when problems
-         occur.
 endmenu
 
 config IWL4965
        tristate "Intel Wireless WiFi 4965AGN (iwl4965)"
        depends on PCI && MAC80211
-       select IWLWIFI_LEGACY
+       select IWLEGACY
        ---help---
          This option enables support for
 
@@ -93,7 +76,7 @@ config IWL4965
 config IWL3945
        tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
        depends on PCI && MAC80211
-       select IWLWIFI_LEGACY
+       select IWLEGACY
        ---help---
          Select to build the driver supporting the:
 
index d56aeb38c211ef13d2e78387749b46179a6e85be..c985a01a07314a4e90284f36bb622fab3be05cdd 100644 (file)
@@ -1,25 +1,17 @@
-obj-$(CONFIG_IWLWIFI_LEGACY)   += iwl-legacy.o
-iwl-legacy-objs                := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
-iwl-legacy-objs                += iwl-rx.o iwl-tx.o iwl-sta.o
-iwl-legacy-objs                += iwl-scan.o iwl-led.o
-iwl-legacy-$(CONFIG_IWLWIFI_LEGACY_DEBUGFS) += iwl-debugfs.o
-iwl-legacy-$(CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING) += iwl-devtrace.o
+obj-$(CONFIG_IWLEGACY) += iwlegacy.o
+iwlegacy-objs          := common.o
+iwlegacy-$(CONFIG_IWLEGACY_DEBUGFS) += debug.o
 
-iwl-legacy-objs += $(iwl-legacy-m)
-
-CFLAGS_iwl-devtrace.o := -I$(src)
+iwlegacy-objs += $(iwlegacy-m)
 
 # 4965
 obj-$(CONFIG_IWL4965)  += iwl4965.o
-iwl4965-objs           := iwl-4965.o iwl4965-base.o iwl-4965-rs.o iwl-4965-led.o
-iwl4965-objs           += iwl-4965-ucode.o iwl-4965-tx.o
-iwl4965-objs           += iwl-4965-lib.o iwl-4965-rx.o iwl-4965-calib.o
-iwl4965-objs           += iwl-4965-sta.o iwl-4965-eeprom.o
-iwl4965-$(CONFIG_IWLWIFI_LEGACY_DEBUGFS) += iwl-4965-debugfs.o
+iwl4965-objs           := 4965.o 4965-mac.o 4965-rs.o 4965-calib.o
+iwl4965-$(CONFIG_IWLEGACY_DEBUGFS) += 4965-debug.o
 
 # 3945
 obj-$(CONFIG_IWL3945)  += iwl3945.o
-iwl3945-objs           := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
-iwl3945-$(CONFIG_IWLWIFI_LEGACY_DEBUGFS) += iwl-3945-debugfs.o
+iwl3945-objs           := 3945-mac.o 3945.o 3945-rs.o
+iwl3945-$(CONFIG_IWLEGACY_DEBUGFS) += 3945-debug.o
 
 ccflags-y += -D__CHECK_ENDIAN__
similarity index 79%
rename from drivers/net/wireless/iwlegacy/iwl-commands.h
rename to drivers/net/wireless/iwlegacy/commands.h
index 89904054473fe850e4e567f7f262a138cdac7dc0..25dd7d28d022c3e5e3ad74759e841c2b9de87f7b 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  *****************************************************************************/
-/*
- * Please use this file (iwl-commands.h) only for uCode API definitions.
- * Please use iwl-xxxx-hw.h for hardware-related definitions.
- * Please use iwl-dev.h for driver implementation definitions.
- */
 
-#ifndef __iwl_legacy_commands_h__
-#define __iwl_legacy_commands_h__
+#ifndef __il_commands_h__
+#define __il_commands_h__
 
-struct iwl_priv;
+#include <linux/ieee80211.h>
 
-/* uCode version contains 4 values: Major/Minor/API/Serial */
-#define IWL_UCODE_MAJOR(ver)   (((ver) & 0xFF000000) >> 24)
-#define IWL_UCODE_MINOR(ver)   (((ver) & 0x00FF0000) >> 16)
-#define IWL_UCODE_API(ver)     (((ver) & 0x0000FF00) >> 8)
-#define IWL_UCODE_SERIAL(ver)  ((ver) & 0x000000FF)
+struct il_priv;
 
+/* uCode version contains 4 values: Major/Minor/API/Serial */
+#define IL_UCODE_MAJOR(ver)    (((ver) & 0xFF000000) >> 24)
+#define IL_UCODE_MINOR(ver)    (((ver) & 0x00FF0000) >> 16)
+#define IL_UCODE_API(ver)      (((ver) & 0x0000FF00) >> 8)
+#define IL_UCODE_SERIAL(ver)   ((ver) & 0x000000FF)
 
 /* Tx rates */
-#define IWL_CCK_RATES  4
-#define IWL_OFDM_RATES 8
-#define IWL_MAX_RATES  (IWL_CCK_RATES + IWL_OFDM_RATES)
+#define IL_CCK_RATES   4
+#define IL_OFDM_RATES  8
+#define IL_MAX_RATES   (IL_CCK_RATES + IL_OFDM_RATES)
 
 enum {
-       REPLY_ALIVE = 0x1,
-       REPLY_ERROR = 0x2,
+       N_ALIVE = 0x1,
+       N_ERROR = 0x2,
 
        /* RXON and QOS commands */
-       REPLY_RXON = 0x10,
-       REPLY_RXON_ASSOC = 0x11,
-       REPLY_QOS_PARAM = 0x13,
-       REPLY_RXON_TIMING = 0x14,
+       C_RXON = 0x10,
+       C_RXON_ASSOC = 0x11,
+       C_QOS_PARAM = 0x13,
+       C_RXON_TIMING = 0x14,
 
        /* Multi-Station support */
-       REPLY_ADD_STA = 0x18,
-       REPLY_REMOVE_STA = 0x19,
+       C_ADD_STA = 0x18,
+       C_REM_STA = 0x19,
 
        /* Security */
-       REPLY_WEPKEY = 0x20,
+       C_WEPKEY = 0x20,
 
        /* RX, TX, LEDs */
-       REPLY_3945_RX = 0x1b,           /* 3945 only */
-       REPLY_TX = 0x1c,
-       REPLY_RATE_SCALE = 0x47,        /* 3945 only */
-       REPLY_LEDS_CMD = 0x48,
-       REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */
+       N_3945_RX = 0x1b,       /* 3945 only */
+       C_TX = 0x1c,
+       C_RATE_SCALE = 0x47,    /* 3945 only */
+       C_LEDS = 0x48,
+       C_TX_LINK_QUALITY_CMD = 0x4e,   /* for 4965 */
 
        /* 802.11h related */
-       REPLY_CHANNEL_SWITCH = 0x72,
-       CHANNEL_SWITCH_NOTIFICATION = 0x73,
-       REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74,
-       SPECTRUM_MEASURE_NOTIFICATION = 0x75,
+       C_CHANNEL_SWITCH = 0x72,
+       N_CHANNEL_SWITCH = 0x73,
+       C_SPECTRUM_MEASUREMENT = 0x74,
+       N_SPECTRUM_MEASUREMENT = 0x75,
 
        /* Power Management */
-       POWER_TABLE_CMD = 0x77,
-       PM_SLEEP_NOTIFICATION = 0x7A,
-       PM_DEBUG_STATISTIC_NOTIFIC = 0x7B,
+       C_POWER_TBL = 0x77,
+       N_PM_SLEEP = 0x7A,
+       N_PM_DEBUG_STATS = 0x7B,
 
        /* 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,
+       C_SCAN = 0x80,
+       C_SCAN_ABORT = 0x81,
+       N_SCAN_START = 0x82,
+       N_SCAN_RESULTS = 0x83,
+       N_SCAN_COMPLETE = 0x84,
 
        /* IBSS/AP commands */
-       BEACON_NOTIFICATION = 0x90,
-       REPLY_TX_BEACON = 0x91,
+       N_BEACON = 0x90,
+       C_TX_BEACON = 0x91,
 
        /* Miscellaneous commands */
-       REPLY_TX_PWR_TABLE_CMD = 0x97,
+       C_TX_PWR_TBL = 0x97,
 
        /* Bluetooth device coexistence config command */
-       REPLY_BT_CONFIG = 0x9b,
+       C_BT_CONFIG = 0x9b,
 
        /* Statistics */
-       REPLY_STATISTICS_CMD = 0x9c,
-       STATISTICS_NOTIFICATION = 0x9d,
+       C_STATS = 0x9c,
+       N_STATS = 0x9d,
 
        /* RF-KILL commands and notifications */
-       CARD_STATE_NOTIFICATION = 0xa1,
+       N_CARD_STATE = 0xa1,
 
        /* Missed beacons notification */
-       MISSED_BEACONS_NOTIFICATION = 0xa2,
+       N_MISSED_BEACONS = 0xa2,
 
-       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_RX = 0xc3,
-       REPLY_COMPRESSED_BA = 0xc5,
+       C_CT_KILL_CONFIG = 0xa4,
+       C_SENSITIVITY = 0xa8,
+       C_PHY_CALIBRATION = 0xb0,
+       N_RX_PHY = 0xc0,
+       N_RX_MPDU = 0xc1,
+       N_RX = 0xc3,
+       N_COMPRESSED_BA = 0xc5,
 
-       REPLY_MAX = 0xff
+       IL_CN_MAX = 0xff
 };
 
 /******************************************************************************
@@ -163,25 +159,25 @@ enum {
  *
  *****************************************************************************/
 
-/* iwl_cmd_header flags value */
-#define IWL_CMD_FAILED_MSK 0x40
+/* il_cmd_header flags value */
+#define IL_CMD_FAILED_MSK 0x40
 
 #define SEQ_TO_QUEUE(s)        (((s) >> 8) & 0x1f)
 #define QUEUE_TO_SEQ(q)        (((q) & 0x1f) << 8)
-#define SEQ_TO_INDEX(s)        ((s) & 0xff)
-#define INDEX_TO_SEQ(i)        ((i) & 0xff)
+#define SEQ_TO_IDX(s)  ((s) & 0xff)
+#define IDX_TO_SEQ(i)  ((i) & 0xff)
 #define SEQ_HUGE_FRAME cpu_to_le16(0x4000)
 #define SEQ_RX_FRAME   cpu_to_le16(0x8000)
 
 /**
- * struct iwl_cmd_header
+ * struct il_cmd_header
  *
  * This header format appears in the beginning of each command sent from the
  * driver, and each response/notification received from uCode.
  */
-struct iwl_cmd_header {
-       u8 cmd;         /* Command ID:  REPLY_RXON, etc. */
-       u8 flags;       /* 0:5 reserved, 6 abort, 7 internal */
+struct il_cmd_header {
+       u8 cmd;                 /* Command ID:  C_RXON, etc. */
+       u8 flags;               /* 0:5 reserved, 6 abort, 7 internal */
        /*
         * The driver sets up the sequence number to values of its choosing.
         * uCode does not use this value, but passes it back to the driver
@@ -192,29 +188,28 @@ struct iwl_cmd_header {
         * There is one exception:  uCode sets bit 15 when it originates
         * the response/notification, i.e. when the response/notification
         * is not a direct response to a command sent by the driver.  For
-        * example, uCode issues REPLY_3945_RX when it sends a received frame
+        * example, uCode issues N_3945_RX when it sends a received frame
         * to the driver; it is not a direct response to any driver command.
         *
         * The Linux driver uses the following format:
         *
-        *  0:7         tfd index - position within TX queue
-        *  8:12        TX queue id
-        *  13          reserved
-        *  14          huge - driver sets this to indicate command is in the
-        *              'huge' storage at the end of the command buffers
-        *  15          unsolicited RX or uCode-originated notification
-       */
+        *  0:7         tfd idx - position within TX queue
+        *  8:12        TX queue id
+        *  13          reserved
+        *  14          huge - driver sets this to indicate command is in the
+        *              'huge' storage at the end of the command buffers
+        *  15          unsolicited RX or uCode-originated notification
+        */
        __le16 sequence;
 
        /* command or response/notification data follows immediately */
        u8 data[0];
 } __packed;
 
-
 /**
- * struct iwl3945_tx_power
+ * struct il3945_tx_power
  *
- * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH
+ * Used in C_TX_PWR_TBL, C_SCAN, C_CHANNEL_SWITCH
  *
  * Each entry contains two values:
  * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
@@ -223,21 +218,21 @@ struct iwl_cmd_header {
  * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
  *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
  *
- * Driver obtains values from struct iwl3945_tx_power power_gain_table[][].
+ * Driver obtains values from struct il3945_tx_power power_gain_table[][].
  */
-struct iwl3945_tx_power {
+struct il3945_tx_power {
        u8 tx_gain;             /* gain for analog radio */
        u8 dsp_atten;           /* gain for DSP */
 } __packed;
 
 /**
- * struct iwl3945_power_per_rate
+ * struct il3945_power_per_rate
  *
- * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ * Used in C_TX_PWR_TBL, C_CHANNEL_SWITCH
  */
-struct iwl3945_power_per_rate {
+struct il3945_power_per_rate {
        u8 rate;                /* plcp */
-       struct iwl3945_tx_power tpc;
+       struct il3945_tx_power tpc;
        u8 reserved;
 } __packed;
 
@@ -245,10 +240,10 @@ struct iwl3945_power_per_rate {
  * iwl4965 rate_n_flags bit fields
  *
  * rate_n_flags format is used in following iwl4965 commands:
- *  REPLY_RX (response only)
- *  REPLY_RX_MPDU (response only)
- *  REPLY_TX (both command and response)
- *  REPLY_TX_LINK_QUALITY_CMD
+ *  N_RX (response only)
+ *  N_RX_MPDU (response only)
+ *  C_TX (both command and response)
+ *  C_TX_LINK_QUALITY_CMD
  *
  * High-throughput (HT) rate format for bits 7:0 (bit 8 must be "1"):
  *  2-0:  0)   6 Mbps
@@ -326,17 +321,17 @@ struct iwl3945_power_per_rate {
 #define RATE_MCS_ANT_ABC_MSK   (RATE_MCS_ANT_AB_MSK | RATE_MCS_ANT_C_MSK)
 #define RATE_ANT_NUM 3
 
-#define POWER_TABLE_NUM_ENTRIES                        33
-#define POWER_TABLE_NUM_HT_OFDM_ENTRIES                32
-#define POWER_TABLE_CCK_ENTRY                  32
+#define POWER_TBL_NUM_ENTRIES                  33
+#define POWER_TBL_NUM_HT_OFDM_ENTRIES          32
+#define POWER_TBL_CCK_ENTRY                    32
 
-#define IWL_PWR_NUM_HT_OFDM_ENTRIES            24
-#define IWL_PWR_CCK_ENTRIES                    2
+#define IL_PWR_NUM_HT_OFDM_ENTRIES             24
+#define IL_PWR_CCK_ENTRIES                     2
 
 /**
- * union iwl4965_tx_power_dual_stream
+ * union il4965_tx_power_dual_stream
  *
- * Host format used for REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ * Host format used for C_TX_PWR_TBL, C_CHANNEL_SWITCH
  * Use __le32 version (struct tx_power_dual_stream) when building command.
  *
  * Driver provides radio gain and DSP attenuation settings to device in pairs,
@@ -347,9 +342,9 @@ struct iwl3945_power_per_rate {
  * For MIMO rates, one value may be different from the other,
  * in order to balance the Tx output between the two transmitters.
  *
- * See more details in doc for TXPOWER in iwl-4965-hw.h.
+ * See more details in doc for TXPOWER in 4965.h.
  */
-union iwl4965_tx_power_dual_stream {
+union il4965_tx_power_dual_stream {
        struct {
                u8 radio_tx_gain[2];
                u8 dsp_predis_atten[2];
@@ -360,21 +355,21 @@ union iwl4965_tx_power_dual_stream {
 /**
  * struct tx_power_dual_stream
  *
- * Table entries in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ * Table entries in C_TX_PWR_TBL, C_CHANNEL_SWITCH
  *
- * Same format as iwl_tx_power_dual_stream, but __le32
+ * Same format as il_tx_power_dual_stream, but __le32
  */
 struct tx_power_dual_stream {
        __le32 dw;
 } __packed;
 
 /**
- * struct iwl4965_tx_power_db
+ * struct il4965_tx_power_db
  *
- * Entire table within REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ * Entire table within C_TX_PWR_TBL, C_CHANNEL_SWITCH
  */
-struct iwl4965_tx_power_db {
-       struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES];
+struct il4965_tx_power_db {
+       struct tx_power_dual_stream power_tbl[POWER_TBL_NUM_ENTRIES];
 } __packed;
 
 /******************************************************************************
@@ -387,7 +382,7 @@ struct iwl4965_tx_power_db {
 #define INITIALIZE_SUBTYPE    (9)
 
 /*
- * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command)
+ * ("Initialize") N_ALIVE = 0x1 (response only, not a command)
  *
  * uCode issues this "initialize alive" notification once the initialization
  * uCode image has completed its work, and is ready to load the runtime image.
@@ -410,7 +405,7 @@ struct iwl4965_tx_power_db {
  * 3)  Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation,
  *     for each of 5 frequency ranges.
  */
-struct iwl_init_alive_resp {
+struct il_init_alive_resp {
        u8 ucode_minor;
        u8 ucode_major;
        __le16 reserved1;
@@ -433,9 +428,8 @@ struct iwl_init_alive_resp {
                                 * 2 Tx chains */
 } __packed;
 
-
 /**
- * REPLY_ALIVE = 0x1 (response only, not a command)
+ * N_ALIVE = 0x1 (response only, not a command)
  *
  * uCode issues this "alive" notification once the runtime image is ready
  * to receive commands from the driver.  This is the *second* "alive"
@@ -454,7 +448,7 @@ struct iwl_init_alive_resp {
  *     __le32 log_size;     log capacity (in number of entries)
  *     __le32 type;         (1) timestamp with each entry, (0) no timestamp
  *     __le32 wraps;        # times uCode has wrapped to top of circular buffer
- *      __le32 write_index;  next circular buffer entry that uCode would fill
+ *      __le32 write_idx;  next circular buffer entry that uCode would fill
  *
  *     The header is followed by the circular buffer of log entries.  Entries
  *     with timestamps have the following format:
@@ -511,13 +505,13 @@ struct iwl_init_alive_resp {
  * The Linux driver can print both logs to the system log when a uCode error
  * occurs.
  */
-struct iwl_alive_resp {
+struct il_alive_resp {
        u8 ucode_minor;
        u8 ucode_major;
        __le16 reserved1;
        u8 sw_rev[8];
        u8 ver_type;
-       u8 ver_subtype;                 /* not "9" for runtime alive */
+       u8 ver_subtype;         /* not "9" for runtime alive */
        __le16 reserved2;
        __le32 log_event_table_ptr;     /* SRAM address for event log */
        __le32 error_event_table_ptr;   /* SRAM address for error log */
@@ -526,9 +520,9 @@ struct iwl_alive_resp {
 } __packed;
 
 /*
- * REPLY_ERROR = 0x2 (response only, not a command)
+ * N_ERROR = 0x2 (response only, not a command)
  */
-struct iwl_error_resp {
+struct il_error_resp {
        __le32 error_type;
        u8 cmd_id;
        u8 reserved1;
@@ -554,7 +548,6 @@ enum {
        RXON_DEV_TYPE_SNIFFER = 6,
 };
 
-
 #define RXON_RX_CHAIN_DRIVER_FORCE_MSK         cpu_to_le16(0x1 << 0)
 #define RXON_RX_CHAIN_DRIVER_FORCE_POS         (0)
 #define RXON_RX_CHAIN_VALID_MSK                        cpu_to_le16(0x7 << 1)
@@ -593,7 +586,6 @@ enum {
 * (according to ON_AIR deassertion) */
 #define RXON_FLG_TSF2HOST_MSK           cpu_to_le32(1 << 15)
 
-
 /* HT flags */
 #define RXON_FLG_CTRL_CHANNEL_LOC_POS          (22)
 #define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK       cpu_to_le32(0x1 << 22)
@@ -640,7 +632,7 @@ enum {
 #define RXON_FILTER_BCON_AWARE_MSK      cpu_to_le32(1 << 6)
 
 /**
- * REPLY_RXON = 0x10 (command, has simple generic response)
+ * C_RXON = 0x10 (command, has simple generic response)
  *
  * RXON tunes the radio tuner to a service channel, and sets up a number
  * of parameters that are used primarily for Rx, but also for Tx operations.
@@ -653,11 +645,11 @@ enum {
  *        channel.
  *
  * NOTE:  All RXONs wipe clean the internal txpower table.  Driver must
- *        issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10),
+ *        issue a new C_TX_PWR_TBL after each C_RXON (0x10),
  *        regardless of whether RXON_FILTER_ASSOC_MSK is set.
  */
 
-struct iwl3945_rxon_cmd {
+struct il3945_rxon_cmd {
        u8 node_addr[6];
        __le16 reserved1;
        u8 bssid_addr[6];
@@ -676,7 +668,7 @@ struct iwl3945_rxon_cmd {
        __le16 reserved5;
 } __packed;
 
-struct iwl4965_rxon_cmd {
+struct il4965_rxon_cmd {
        u8 node_addr[6];
        __le16 reserved1;
        u8 bssid_addr[6];
@@ -699,7 +691,7 @@ struct iwl4965_rxon_cmd {
 /* Create a common rxon cmd which will be typecast into the 3945 or 4965
  * specific rxon cmd, depending on where it is called from.
  */
-struct iwl_legacy_rxon_cmd {
+struct il_rxon_cmd {
        u8 node_addr[6];
        __le16 reserved1;
        u8 bssid_addr[6];
@@ -721,11 +713,10 @@ struct iwl_legacy_rxon_cmd {
        u8 reserved5;
 } __packed;
 
-
 /*
- * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
+ * C_RXON_ASSOC = 0x11 (command, has simple generic response)
  */
-struct iwl3945_rxon_assoc_cmd {
+struct il3945_rxon_assoc_cmd {
        __le32 flags;
        __le32 filter_flags;
        u8 ofdm_basic_rates;
@@ -733,7 +724,7 @@ struct iwl3945_rxon_assoc_cmd {
        __le16 reserved;
 } __packed;
 
-struct iwl4965_rxon_assoc_cmd {
+struct il4965_rxon_assoc_cmd {
        __le32 flags;
        __le32 filter_flags;
        u8 ofdm_basic_rates;
@@ -744,17 +735,17 @@ struct iwl4965_rxon_assoc_cmd {
        __le16 reserved;
 } __packed;
 
-#define IWL_CONN_MAX_LISTEN_INTERVAL   10
-#define IWL_MAX_UCODE_BEACON_INTERVAL  4 /* 4096 */
-#define IWL39_MAX_UCODE_BEACON_INTERVAL        1 /* 1024 */
+#define IL_CONN_MAX_LISTEN_INTERVAL    10
+#define IL_MAX_UCODE_BEACON_INTERVAL   4       /* 4096 */
+#define IL39_MAX_UCODE_BEACON_INTERVAL 1       /* 1024 */
 
 /*
- * REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
+ * C_RXON_TIMING = 0x14 (command, has simple generic response)
  */
-struct iwl_rxon_time_cmd {
+struct il_rxon_time_cmd {
        __le64 timestamp;
        __le16 beacon_interval;
-       __le16 atim_window;
+       __le16 atim_win;
        __le32 beacon_init_val;
        __le16 listen_interval;
        u8 dtim_period;
@@ -762,32 +753,32 @@ struct iwl_rxon_time_cmd {
 } __packed;
 
 /*
- * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
+ * C_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
  */
-struct iwl3945_channel_switch_cmd {
+struct il3945_channel_switch_cmd {
        u8 band;
        u8 expect_beacon;
        __le16 channel;
        __le32 rxon_flags;
        __le32 rxon_filter_flags;
        __le32 switch_time;
-       struct iwl3945_power_per_rate power[IWL_MAX_RATES];
+       struct il3945_power_per_rate power[IL_MAX_RATES];
 } __packed;
 
-struct iwl4965_channel_switch_cmd {
+struct il4965_channel_switch_cmd {
        u8 band;
        u8 expect_beacon;
        __le16 channel;
        __le32 rxon_flags;
        __le32 rxon_filter_flags;
        __le32 switch_time;
-       struct iwl4965_tx_power_db tx_power;
+       struct il4965_tx_power_db tx_power;
 } __packed;
 
 /*
- * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
+ * N_CHANNEL_SWITCH = 0x73 (notification only, not a command)
  */
-struct iwl_csa_notification {
+struct il_csa_notification {
        __le16 band;
        __le16 channel;
        __le32 status;          /* 0 - OK, 1 - fail */
@@ -800,22 +791,22 @@ struct iwl_csa_notification {
  *****************************************************************************/
 
 /**
- * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM
- * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd
+ * struct il_ac_qos -- QOS timing params for C_QOS_PARAM
+ * One for each of 4 EDCA access categories in struct il_qosparam_cmd
  *
- * @cw_min: Contention window, start value in numbers of slots.
+ * @cw_min: Contention win, start value in numbers of slots.
  *          Should be a power-of-2, minus 1.  Device's default is 0x0f.
- * @cw_max: Contention window, max value in numbers of slots.
+ * @cw_max: Contention win, max value in numbers of slots.
  *          Should be a power-of-2, minus 1.  Device's default is 0x3f.
  * @aifsn:  Number of slots in Arbitration Interframe Space (before
  *          performing random backoff timing prior to Tx).  Device default 1.
  * @edca_txop:  Length of Tx opportunity, in uSecs.  Device default is 0.
  *
- * Device will automatically increase contention window by (2*CW) + 1 for each
+ * Device will automatically increase contention win by (2*CW) + 1 for each
  * transmission retry.  Device uses cw_max as a bit mask, ANDed with new CW
  * value, to cap the CW value.
  */
-struct iwl_ac_qos {
+struct il_ac_qos {
        __le16 cw_min;
        __le16 cw_max;
        u8 aifsn;
@@ -832,14 +823,14 @@ struct iwl_ac_qos {
 #define AC_NUM                4
 
 /*
- * REPLY_QOS_PARAM = 0x13 (command, has simple generic response)
+ * C_QOS_PARAM = 0x13 (command, has simple generic response)
  *
  * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs
  * 0: Background, 1: Best Effort, 2: Video, 3: Voice.
  */
-struct iwl_qosparam_cmd {
+struct il_qosparam_cmd {
        __le32 qos_flags;
-       struct iwl_ac_qos ac[AC_NUM];
+       struct il_ac_qos ac[AC_NUM];
 } __packed;
 
 /******************************************************************************
@@ -852,15 +843,15 @@ struct iwl_qosparam_cmd {
  */
 
 /* Special, dedicated locations within device's station table */
-#define        IWL_AP_ID               0
-#define        IWL_STA_ID              2
-#define        IWL3945_BROADCAST_ID    24
-#define IWL3945_STATION_COUNT  25
-#define IWL4965_BROADCAST_ID   31
-#define        IWL4965_STATION_COUNT   32
+#define        IL_AP_ID                0
+#define        IL_STA_ID               2
+#define        IL3945_BROADCAST_ID     24
+#define IL3945_STATION_COUNT   25
+#define IL4965_BROADCAST_ID    31
+#define        IL4965_STATION_COUNT    32
 
-#define        IWL_STATION_COUNT       32      /* MAX(3945,4965)*/
-#define        IWL_INVALID_STATION     255
+#define        IL_STATION_COUNT        32      /* MAX(3945,4965) */
+#define        IL_INVALID_STATION      255
 
 #define STA_FLG_TX_RATE_MSK            cpu_to_le32(1 << 2)
 #define STA_FLG_PWR_SAVE_MSK           cpu_to_le32(1 << 8)
@@ -901,11 +892,11 @@ struct iwl_qosparam_cmd {
 #define STA_MODIFY_DELBA_TID_MSK       0x10
 #define STA_MODIFY_SLEEP_TX_COUNT_MSK  0x20
 
-/* Receiver address (actually, Rx station's index into station table),
+/* Receiver address (actually, Rx station's idx into station table),
  * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */
 #define BUILD_RAxTID(sta_id, tid)      (((sta_id) << 4) + (tid))
 
-struct iwl4965_keyinfo {
+struct il4965_keyinfo {
        __le16 key_flags;
        u8 tkip_rx_tsc_byte2;   /* TSC[2] for key mix ph1 detection */
        u8 reserved1;
@@ -918,12 +909,12 @@ struct iwl4965_keyinfo {
 /**
  * struct sta_id_modify
  * @addr[ETH_ALEN]: station's MAC address
- * @sta_id: index of station in uCode's station table
+ * @sta_id: idx of station in uCode's station table
  * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change
  *
- * Driver selects unused table index when adding new station,
- * or the index to a pre-existing station entry when modifying that station.
- * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP).
+ * Driver selects unused table idx when adding new station,
+ * or the idx to a pre-existing station entry when modifying that station.
+ * Some idxes have special purposes (IL_AP_ID, idx 0, is for AP).
  *
  * modify_mask flags select which parameters to modify vs. leave alone.
  */
@@ -936,15 +927,15 @@ struct sta_id_modify {
 } __packed;
 
 /*
- * REPLY_ADD_STA = 0x18 (command)
+ * C_ADD_STA = 0x18 (command)
  *
  * The device contains an internal table of per-station information,
  * with info on security keys, aggregation parameters, and Tx rates for
  * initial Tx attempt and any retries (4965 devices uses
- * REPLY_TX_LINK_QUALITY_CMD,
- * 3945 uses REPLY_RATE_SCALE to set up rate tables).
+ * C_TX_LINK_QUALITY_CMD,
+ * 3945 uses C_RATE_SCALE to set up rate tables).
  *
- * REPLY_ADD_STA sets up the table entry for one station, either creating
+ * C_ADD_STA sets up the table entry for one station, either creating
  * a new entry, or modifying a pre-existing one.
  *
  * NOTE:  RXON command (without "associated" bit set) wipes the station table
@@ -954,20 +945,20 @@ struct sta_id_modify {
  *        their own txpower/rate setup data).
  *
  *        When getting started on a new channel, driver must set up the
- *        IWL_BROADCAST_ID entry (last entry in the table).  For a client
+ *        IL_BROADCAST_ID entry (last entry in the table).  For a client
  *        station in a BSS, once an AP is selected, driver sets up the AP STA
- *        in the IWL_AP_ID entry (1st entry in the table).  BROADCAST and AP
+ *        in the IL_AP_ID entry (1st entry in the table).  BROADCAST and AP
  *        are all that are needed for a BSS client station.  If the device is
  *        used as AP, or in an IBSS network, driver must set up station table
- *        entries for all STAs in network, starting with index IWL_STA_ID.
+ *        entries for all STAs in network, starting with idx IL_STA_ID.
  */
 
-struct iwl3945_addsta_cmd {
+struct il3945_addsta_cmd {
        u8 mode;                /* 1: modify existing, 0: add new station */
        u8 reserved[3];
        struct sta_id_modify sta;
-       struct iwl4965_keyinfo key;
-       __le32 station_flags;           /* STA_FLG_* */
+       struct il4965_keyinfo key;
+       __le32 station_flags;   /* STA_FLG_* */
        __le32 station_flags_msk;       /* STA_FLG_* */
 
        /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
@@ -990,12 +981,12 @@ struct iwl3945_addsta_cmd {
        __le16 add_immediate_ba_ssn;
 } __packed;
 
-struct iwl4965_addsta_cmd {
+struct il4965_addsta_cmd {
        u8 mode;                /* 1: modify existing, 0: add new station */
        u8 reserved[3];
        struct sta_id_modify sta;
-       struct iwl4965_keyinfo key;
-       __le32 station_flags;           /* STA_FLG_* */
+       struct il4965_keyinfo key;
+       __le32 station_flags;   /* STA_FLG_* */
        __le32 station_flags_msk;       /* STA_FLG_* */
 
        /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
@@ -1003,7 +994,7 @@ struct iwl4965_addsta_cmd {
         * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
        __le16 tid_disable_tx;
 
-       __le16  reserved1;
+       __le16 reserved1;
 
        /* TID for which to add block-ack support.
         * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
@@ -1028,12 +1019,12 @@ struct iwl4965_addsta_cmd {
 } __packed;
 
 /* Wrapper struct for 3945 and 4965 addsta_cmd structures */
-struct iwl_legacy_addsta_cmd {
+struct il_addsta_cmd {
        u8 mode;                /* 1: modify existing, 0: add new station */
        u8 reserved[3];
        struct sta_id_modify sta;
-       struct iwl4965_keyinfo key;
-       __le32 station_flags;           /* STA_FLG_* */
+       struct il4965_keyinfo key;
+       __le32 station_flags;   /* STA_FLG_* */
        __le32 station_flags_msk;       /* STA_FLG_* */
 
        /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
@@ -1041,7 +1032,7 @@ struct iwl_legacy_addsta_cmd {
         * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
        __le16 tid_disable_tx;
 
-       __le16  rate_n_flags;           /* 3945 only */
+       __le16 rate_n_flags;    /* 3945 only */
 
        /* TID for which to add block-ack support.
         * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
@@ -1065,51 +1056,50 @@ struct iwl_legacy_addsta_cmd {
        __le16 reserved2;
 } __packed;
 
-
 #define ADD_STA_SUCCESS_MSK            0x1
-#define ADD_STA_NO_ROOM_IN_TABLE       0x2
+#define ADD_STA_NO_ROOM_IN_TBL 0x2
 #define ADD_STA_NO_BLOCK_ACK_RESOURCE  0x4
 #define ADD_STA_MODIFY_NON_EXIST_STA   0x8
 /*
- * REPLY_ADD_STA = 0x18 (response)
+ * C_ADD_STA = 0x18 (response)
  */
-struct iwl_add_sta_resp {
-       u8 status;      /* ADD_STA_* */
+struct il_add_sta_resp {
+       u8 status;              /* ADD_STA_* */
 } __packed;
 
 #define REM_STA_SUCCESS_MSK              0x1
 /*
- *  REPLY_REM_STA = 0x19 (response)
+ *  C_REM_STA = 0x19 (response)
  */
-struct iwl_rem_sta_resp {
+struct il_rem_sta_resp {
        u8 status;
 } __packed;
 
 /*
- *  REPLY_REM_STA = 0x19 (command)
+ *  C_REM_STA = 0x19 (command)
  */
-struct iwl_rem_sta_cmd {
-       u8 num_sta;     /* number of removed stations */
+struct il_rem_sta_cmd {
+       u8 num_sta;             /* number of removed stations */
        u8 reserved[3];
-       u8 addr[ETH_ALEN]; /* MAC addr of the first station */
+       u8 addr[ETH_ALEN];      /* MAC addr of the first station */
        u8 reserved2[2];
 } __packed;
 
-#define IWL_TX_FIFO_BK_MSK             cpu_to_le32(BIT(0))
-#define IWL_TX_FIFO_BE_MSK             cpu_to_le32(BIT(1))
-#define IWL_TX_FIFO_VI_MSK             cpu_to_le32(BIT(2))
-#define IWL_TX_FIFO_VO_MSK             cpu_to_le32(BIT(3))
-#define IWL_AGG_TX_QUEUE_MSK           cpu_to_le32(0xffc00)
+#define IL_TX_FIFO_BK_MSK              cpu_to_le32(BIT(0))
+#define IL_TX_FIFO_BE_MSK              cpu_to_le32(BIT(1))
+#define IL_TX_FIFO_VI_MSK              cpu_to_le32(BIT(2))
+#define IL_TX_FIFO_VO_MSK              cpu_to_le32(BIT(3))
+#define IL_AGG_TX_QUEUE_MSK            cpu_to_le32(0xffc00)
 
-#define IWL_DROP_SINGLE                0
-#define IWL_DROP_SELECTED      1
-#define IWL_DROP_ALL           2
+#define IL_DROP_SINGLE         0
+#define IL_DROP_SELECTED       1
+#define IL_DROP_ALL            2
 
 /*
  * REPLY_WEP_KEY = 0x20
  */
-struct iwl_wep_key {
-       u8 key_index;
+struct il_wep_key {
+       u8 key_idx;
        u8 key_offset;
        u8 reserved1[2];
        u8 key_size;
@@ -1117,12 +1107,12 @@ struct iwl_wep_key {
        u8 key[16];
 } __packed;
 
-struct iwl_wep_cmd {
+struct il_wep_cmd {
        u8 num_keys;
        u8 global_key_type;
        u8 flags;
        u8 reserved;
-       struct iwl_wep_key key[0];
+       struct il_wep_key key[0];
 } __packed;
 
 #define WEP_KEY_WEP_TYPE 1
@@ -1168,8 +1158,7 @@ struct iwl_wep_cmd {
 #define RX_MPDU_RES_STATUS_TTAK_OK     (1 << 7)
 #define RX_MPDU_RES_STATUS_DEC_DONE_MSK        (0x800)
 
-
-struct iwl3945_rx_frame_stats {
+struct il3945_rx_frame_stats {
        u8 phy_count;
        u8 id;
        u8 rssi;
@@ -1179,7 +1168,7 @@ struct iwl3945_rx_frame_stats {
        u8 payload[0];
 } __packed;
 
-struct iwl3945_rx_frame_hdr {
+struct il3945_rx_frame_hdr {
        __le16 channel;
        __le16 phy_flags;
        u8 reserved1;
@@ -1188,73 +1177,71 @@ struct iwl3945_rx_frame_hdr {
        u8 payload[0];
 } __packed;
 
-struct iwl3945_rx_frame_end {
+struct il3945_rx_frame_end {
        __le32 status;
        __le64 timestamp;
        __le32 beacon_timestamp;
 } __packed;
 
 /*
- * REPLY_3945_RX = 0x1b (response only, not a command)
+ * N_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 iwl3945_rx_frame {
-       struct iwl3945_rx_frame_stats stats;
-       struct iwl3945_rx_frame_hdr hdr;
-       struct iwl3945_rx_frame_end end;
+struct il3945_rx_frame {
+       struct il3945_rx_frame_stats stats;
+       struct il3945_rx_frame_hdr hdr;
+       struct il3945_rx_frame_end end;
 } __packed;
 
-#define IWL39_RX_FRAME_SIZE    (4 + sizeof(struct iwl3945_rx_frame))
+#define IL39_RX_FRAME_SIZE     (4 + sizeof(struct il3945_rx_frame))
 
 /* Fixed (non-configurable) rx data from phy */
 
-#define IWL49_RX_RES_PHY_CNT 14
-#define IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET     (4)
-#define IWL49_RX_PHY_FLAGS_ANTENNAE_MASK       (0x70)
-#define IWL49_AGC_DB_MASK                      (0x3f80)        /* MASK(7,13) */
-#define IWL49_AGC_DB_POS                       (7)
-struct iwl4965_rx_non_cfg_phy {
+#define IL49_RX_RES_PHY_CNT 14
+#define IL49_RX_PHY_FLAGS_ANTENNAE_OFFSET      (4)
+#define IL49_RX_PHY_FLAGS_ANTENNAE_MASK        (0x70)
+#define IL49_AGC_DB_MASK                       (0x3f80)        /* MASK(7,13) */
+#define IL49_AGC_DB_POS                        (7)
+struct il4965_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];
 } __packed;
 
-
 /*
- * REPLY_RX = 0xc3 (response only, not a command)
+ * N_RX = 0xc3 (response only, not a command)
  * Used only for legacy (non 11n) frames.
  */
-struct iwl_rx_phy_res {
-       u8 non_cfg_phy_cnt;     /* non configurable DSP phy data byte count */
+struct il_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 */
+       __le32 beacon_time_stamp;       /* beacon at on-air rise */
        __le16 phy_flags;       /* general phy flags: band, modulation, ... */
        __le16 channel;         /* channel number */
-       u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */
+       u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */
        __le32 rate_n_flags;    /* RATE_MCS_* */
        __le16 byte_count;      /* frame's byte-count */
        __le16 frame_time;      /* frame's time on the air */
 } __packed;
 
-struct iwl_rx_mpdu_res_start {
+struct il_rx_mpdu_res_start {
        __le16 byte_count;
        __le16 reserved;
 } __packed;
 
-
 /******************************************************************************
  * (5)
  * Tx Commands & Responses:
  *
- * Driver must place each REPLY_TX command into one of the prioritized Tx
+ * Driver must place each C_TX command into one of the prioritized Tx
  * queues in host DRAM, shared between driver and device (see comments for
  * SCD registers and Tx/Rx Queues).  When the device's Tx scheduler and uCode
  * are preparing to transmit, the device pulls the Tx command over the PCI
@@ -1264,18 +1251,18 @@ struct iwl_rx_mpdu_res_start {
  * uCode handles all timing and protocol related to control frames
  * (RTS/CTS/ACK), based on flags in the Tx command.  uCode and Tx scheduler
  * handle reception of block-acks; uCode updates the host driver via
- * REPLY_COMPRESSED_BA.
+ * N_COMPRESSED_BA.
  *
  * uCode handles retrying Tx when an ACK is expected but not received.
  * This includes trying lower data rates than the one requested in the Tx
- * command, as set up by the REPLY_RATE_SCALE (for 3945) or
- * REPLY_TX_LINK_QUALITY_CMD (4965).
+ * command, as set up by the C_RATE_SCALE (for 3945) or
+ * C_TX_LINK_QUALITY_CMD (4965).
  *
- * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD.
+ * Driver sets up transmit power for various rates via C_TX_PWR_TBL.
  * This command must be executed after every RXON command, before Tx can occur.
  *****************************************************************************/
 
-/* REPLY_TX Tx flags field */
+/* C_TX Tx flags field */
 
 /*
  * 1: Use Request-To-Send protocol before this frame.
@@ -1296,8 +1283,8 @@ struct iwl_rx_mpdu_res_start {
 #define TX_CMD_FLG_ACK_MSK cpu_to_le32(1 << 3)
 
 /* For 4965 devices:
- * 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD).
- *    Tx command's initial_rate_index indicates first rate to try;
+ * 1: Use rate scale table (see C_TX_LINK_QUALITY_CMD).
+ *    Tx command's initial_rate_idx indicates first rate to try;
  *    uCode walks through table for additional Tx attempts.
  * 0: Use Tx rate/MCS from Tx command's rate_n_flags field.
  *    This rate will be used for all Tx attempts; it will not be scaled. */
@@ -1322,7 +1309,7 @@ struct iwl_rx_mpdu_res_start {
 /* 1: uCode overrides sequence control field in MAC header.
  * 0: Driver provides sequence control field in MAC header.
  * Set this for management frames, non-QOS data frames, non-unicast frames,
- * and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */
+ * and also in Tx command embedded in C_SCAN for active scans. */
 #define TX_CMD_FLG_SEQ_CTL_MSK cpu_to_le32(1 << 13)
 
 /* 1: This frame is non-last MPDU; more fragments are coming.
@@ -1349,7 +1336,6 @@ struct iwl_rx_mpdu_res_start {
 /* HCCA-AP - disable duration overwriting. */
 #define TX_CMD_FLG_DUR_MSK cpu_to_le32(1 << 25)
 
-
 /*
  * TX command security control
  */
@@ -1369,10 +1355,10 @@ struct iwl_rx_mpdu_res_start {
 #define TKIP_ICV_LEN 4
 
 /*
- * REPLY_TX = 0x1c (command)
+ * C_TX = 0x1c (command)
  */
 
-struct iwl3945_tx_cmd {
+struct il3945_tx_cmd {
        /*
         * MPDU byte count:
         * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
@@ -1434,9 +1420,9 @@ struct iwl3945_tx_cmd {
 } __packed;
 
 /*
- * REPLY_TX = 0x1c (response)
+ * C_TX = 0x1c (response)
  */
-struct iwl3945_tx_resp {
+struct il3945_tx_resp {
        u8 failure_rts;
        u8 failure_frame;
        u8 bt_kill_count;
@@ -1445,19 +1431,18 @@ struct iwl3945_tx_resp {
        __le32 status;          /* TX status */
 } __packed;
 
-
 /*
  * 4965 uCode updates these Tx attempt count values in host DRAM.
  * Used for managing Tx retries when expecting block-acks.
  * Driver should set these fields to 0.
  */
-struct iwl_dram_scratch {
+struct il_dram_scratch {
        u8 try_cnt;             /* Tx attempts */
        u8 bt_kill_cnt;         /* Tx attempts blocked by Bluetooth device */
        __le16 reserved;
 } __packed;
 
-struct iwl_tx_cmd {
+struct il_tx_cmd {
        /*
         * MPDU byte count:
         * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
@@ -1481,7 +1466,7 @@ struct iwl_tx_cmd {
 
        /* uCode may modify this field of the Tx command (in host DRAM!).
         * Driver must also set dram_lsb_ptr and dram_msb_ptr in this cmd. */
-       struct iwl_dram_scratch scratch;
+       struct il_dram_scratch scratch;
 
        /* Rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is cleared. */
        __le32 rate_n_flags;    /* RATE_MCS_* */
@@ -1493,13 +1478,13 @@ struct iwl_tx_cmd {
        u8 sec_ctl;             /* TX_CMD_SEC_* */
 
        /*
-        * Index into rate table (see REPLY_TX_LINK_QUALITY_CMD) for initial
+        * Index into rate table (see C_TX_LINK_QUALITY_CMD) for initial
         * Tx attempt, if TX_CMD_FLG_STA_RATE_MSK is set.  Normally "0" for
         * data frames, this field may be used to selectively reduce initial
         * rate (via non-0 value) for special frames (e.g. management), while
         * still supporting rate scaling for all frames.
         */
-       u8 initial_rate_index;
+       u8 initial_rate_idx;
        u8 reserved;
        u8 key[16];
        __le16 next_frame_flags;
@@ -1628,12 +1613,12 @@ enum {
 };
 
 enum {
-       TX_STATUS_MSK = 0x000000ff,             /* bits 0:7 */
+       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_RESERVED = 0x00780000,       /* bits 19:22 */
        TX_POWER_PA_DETECT_MSK = 0x7f800000,    /* bits 23:30 */
        TX_ABORT_REQUIRED_MSK = 0x80000000,     /* bits 31:31 */
 };
@@ -1671,7 +1656,7 @@ enum {
 #define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000
 
 /*
- * REPLY_TX = 0x1c (response)
+ * C_TX = 0x1c (response)
  *
  * This response may be in one of two slightly different formats, indicated
  * by the frame_count field:
@@ -1697,7 +1682,7 @@ struct agg_tx_status {
        __le16 sequence;
 } __packed;
 
-struct iwl4965_tx_resp {
+struct il4965_tx_resp {
        u8 frame_count;         /* 1 no aggregation, >1 aggregation */
        u8 bt_kill_count;       /* # blocked by bluetooth (unused for agg) */
        u8 failure_rts;         /* # failures due to unsuccessful RTS */
@@ -1730,16 +1715,16 @@ struct iwl4965_tx_resp {
         */
        union {
                __le32 status;
-               struct agg_tx_status agg_status[0]; /* for each agg frame */
+               struct agg_tx_status agg_status[0];     /* for each agg frame */
        } u;
 } __packed;
 
 /*
- * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
+ * N_COMPRESSED_BA = 0xc5 (response only, not a command)
  *
  * Reports Block-Acknowledge from recipient station
  */
-struct iwl_compressed_ba_resp {
+struct il_compressed_ba_resp {
        __le32 sta_addr_lo32;
        __le16 sta_addr_hi16;
        __le16 reserved;
@@ -1754,30 +1739,29 @@ struct iwl_compressed_ba_resp {
 } __packed;
 
 /*
- * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response)
+ * C_TX_PWR_TBL = 0x97 (command, has simple generic response)
  *
- * See details under "TXPOWER" in iwl-4965-hw.h.
+ * See details under "TXPOWER" in 4965.h.
  */
 
-struct iwl3945_txpowertable_cmd {
+struct il3945_txpowertable_cmd {
        u8 band;                /* 0: 5 GHz, 1: 2.4 GHz */
        u8 reserved;
        __le16 channel;
-       struct iwl3945_power_per_rate power[IWL_MAX_RATES];
+       struct il3945_power_per_rate power[IL_MAX_RATES];
 } __packed;
 
-struct iwl4965_txpowertable_cmd {
+struct il4965_txpowertable_cmd {
        u8 band;                /* 0: 5 GHz, 1: 2.4 GHz */
        u8 reserved;
        __le16 channel;
-       struct iwl4965_tx_power_db tx_power;
+       struct il4965_tx_power_db tx_power;
 } __packed;
 
-
 /**
- * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response
+ * struct il3945_rate_scaling_cmd - Rate Scaling Command & Response
  *
- * REPLY_RATE_SCALE = 0x47 (command, has simple generic response)
+ * C_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
@@ -1786,22 +1770,21 @@ struct iwl4965_txpowertable_cmd {
  *
  * 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
+ * when passed through ofdm_basic_rates on the C_RXON
  * command would be bit 0 (1 << 0)
  */
-struct iwl3945_rate_scaling_info {
+struct il3945_rate_scaling_info {
        __le16 rate_n_flags;
        u8 try_cnt;
-       u8 next_rate_index;
+       u8 next_rate_idx;
 } __packed;
 
-struct iwl3945_rate_scaling_cmd {
+struct il3945_rate_scaling_cmd {
        u8 table_id;
        u8 reserved[3];
-       struct iwl3945_rate_scaling_info table[IWL_MAX_RATES];
+       struct il3945_rate_scaling_info table[IL_MAX_RATES];
 } __packed;
 
-
 /*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */
 #define  LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK   (1 << 0)
 
@@ -1816,28 +1799,27 @@ struct iwl3945_rate_scaling_cmd {
 #define  LINK_QUAL_ANT_B_MSK (1 << 1)
 #define  LINK_QUAL_ANT_MSK   (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK)
 
-
 /**
- * struct iwl_link_qual_general_params
+ * struct il_link_qual_general_params
  *
- * Used in REPLY_TX_LINK_QUALITY_CMD
+ * Used in C_TX_LINK_QUALITY_CMD
  */
-struct iwl_link_qual_general_params {
+struct il_link_qual_general_params {
        u8 flags;
 
-       /* No entries at or above this (driver chosen) index contain MIMO */
+       /* No entries at or above this (driver chosen) idx contain MIMO */
        u8 mimo_delimiter;
 
        /* Best single antenna to use for single stream (legacy, SISO). */
        u8 single_stream_ant_msk;       /* LINK_QUAL_ANT_* */
 
        /* Best antennas to use for MIMO (unused for 4965, assumes both). */
-       u8 dual_stream_ant_msk;         /* LINK_QUAL_ANT_* */
+       u8 dual_stream_ant_msk; /* LINK_QUAL_ANT_* */
 
        /*
         * If driver needs to use different initial rates for different
         * EDCA QOS access categories (as implemented by tx fifos 0-3),
-        * this table will set that up, by indicating the indexes in the
+        * this table will set that up, by indicating the idxes in the
         * rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table at which to start.
         * Otherwise, driver should set all entries to 0.
         *
@@ -1845,10 +1827,10 @@ struct iwl_link_qual_general_params {
         * 0 = Background, 1 = Best Effort (normal), 2 = Video, 3 = Voice
         * TX FIFOs above 3 use same value (typically 0) as TX FIFO 3.
         */
-       u8 start_rate_index[LINK_QUAL_AC_NUM];
+       u8 start_rate_idx[LINK_QUAL_AC_NUM];
 } __packed;
 
-#define LINK_QUAL_AGG_TIME_LIMIT_DEF   (4000) /* 4 milliseconds */
+#define LINK_QUAL_AGG_TIME_LIMIT_DEF   (4000)  /* 4 milliseconds */
 #define LINK_QUAL_AGG_TIME_LIMIT_MAX   (8000)
 #define LINK_QUAL_AGG_TIME_LIMIT_MIN   (100)
 
@@ -1861,11 +1843,11 @@ struct iwl_link_qual_general_params {
 #define LINK_QUAL_AGG_FRAME_LIMIT_MIN  (0)
 
 /**
- * struct iwl_link_qual_agg_params
+ * struct il_link_qual_agg_params
  *
- * Used in REPLY_TX_LINK_QUALITY_CMD
+ * Used in C_TX_LINK_QUALITY_CMD
  */
-struct iwl_link_qual_agg_params {
+struct il_link_qual_agg_params {
 
        /*
         *Maximum number of uSec in aggregation.
@@ -1892,9 +1874,9 @@ struct iwl_link_qual_agg_params {
 } __packed;
 
 /*
- * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
+ * C_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
  *
- * For 4965 devices only; 3945 uses REPLY_RATE_SCALE.
+ * For 4965 devices only; 3945 uses C_RATE_SCALE.
  *
  * Each station in the 4965 device's internal station table has its own table
  * of 16
@@ -1903,13 +1885,13 @@ struct iwl_link_qual_agg_params {
  * one station.
  *
  * NOTE:  Station must already be in 4965 device's station table.
- *       Use REPLY_ADD_STA.
+ *       Use C_ADD_STA.
  *
  * The rate scaling procedures described below work well.  Of course, other
  * procedures are possible, and may work better for particular environments.
  *
  *
- * FILLING THE RATE TABLE
+ * FILLING THE RATE TBL
  *
  * Given a particular initial rate and mode, as determined by the rate
  * scaling algorithm described below, the Linux driver uses the following
@@ -1948,13 +1930,13 @@ struct iwl_link_qual_agg_params {
  * speculative mode as the new current active mode.
  *
  * Each history set contains, separately for each possible rate, data for a
- * sliding window of the 62 most recent tx attempts at that rate.  The data
+ * sliding win of the 62 most recent tx attempts at that rate.  The data
  * includes a shifting bitmap of success(1)/failure(0), and sums of successful
  * and attempted frames, from which the driver can additionally calculate a
  * success ratio (success / attempted) and number of failures
- * (attempted - success), and control the size of the window (attempted).
+ * (attempted - success), and control the size of the win (attempted).
  * The driver uses the bit map to remove successes from the success sum, as
- * the oldest tx attempts fall out of the window.
+ * the oldest tx attempts fall out of the win.
  *
  * When the 4965 device makes multiple tx attempts for a given frame, each
  * attempt might be at a different rate, and have different modulation
@@ -1966,7 +1948,7 @@ struct iwl_link_qual_agg_params {
  *
  * When using block-ack (aggregation), all frames are transmitted at the same
  * rate, since there is no per-attempt acknowledgment from the destination
- * station.  The Tx response struct iwl_tx_resp indicates the Tx rate in
+ * station.  The Tx response struct il_tx_resp indicates the Tx rate in
  * rate_n_flags field.  After receiving a block-ack, the driver can update
  * history for the entire block all at once.
  *
@@ -2016,8 +1998,8 @@ struct iwl_link_qual_agg_params {
  *         good performance; higher rate is sure to have poorer success.
  *
  * 6)  Re-evaluate the rate after each tx frame.  If working with block-
- *     acknowledge, history and statistics may be calculated for the entire
- *     block (including prior history that fits within the history windows),
+ *     acknowledge, history and stats may be calculated for the entire
+ *     block (including prior history that fits within the history wins),
  *     before re-evaluation.
  *
  * FINDING BEST STARTING MODULATION MODE:
@@ -2079,22 +2061,22 @@ struct iwl_link_qual_agg_params {
  * legacy), and then repeat the search process.
  *
  */
-struct iwl_link_quality_cmd {
+struct il_link_quality_cmd {
 
        /* Index of destination/recipient station in uCode's station table */
        u8 sta_id;
        u8 reserved1;
        __le16 control;         /* not used */
-       struct iwl_link_qual_general_params general_params;
-       struct iwl_link_qual_agg_params agg_params;
+       struct il_link_qual_general_params general_params;
+       struct il_link_qual_agg_params agg_params;
 
        /*
-        * Rate info; when using rate-scaling, Tx command's initial_rate_index
-        * specifies 1st Tx rate attempted, via index into this table.
+        * Rate info; when using rate-scaling, Tx command's initial_rate_idx
+        * specifies 1st Tx rate attempted, via idx into this table.
         * 4965 devices works its way through table when retrying Tx.
         */
        struct {
-               __le32 rate_n_flags;    /* RATE_MCS_*, IWL_RATE_* */
+               __le32 rate_n_flags;    /* RATE_MCS_*, RATE_* */
        } rs_table[LINK_QUAL_MAX_RETRY_NUM];
        __le32 reserved2;
 } __packed;
@@ -2117,13 +2099,13 @@ struct iwl_link_quality_cmd {
 #define BT_MAX_KILL_DEF (0x5)
 
 /*
- * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
+ * C_BT_CONFIG = 0x9b (command, has simple generic response)
  *
  * 3945 and 4965 devices support hardware handshake with Bluetooth device on
  * same platform.  Bluetooth device alerts wireless device when it will Tx;
  * wireless device can delay or kill its own Tx to accommodate.
  */
-struct iwl_bt_cmd {
+struct il_bt_cmd {
        u8 flags;
        u8 lead_time;
        u8 max_kill;
@@ -2132,7 +2114,6 @@ struct iwl_bt_cmd {
        __le32 kill_cts_mask;
 } __packed;
 
-
 /******************************************************************************
  * (6)
  * Spectrum Management (802.11h) Commands, Responses, Notifications:
@@ -2150,18 +2131,18 @@ struct iwl_bt_cmd {
                                 RXON_FILTER_ASSOC_MSK           | \
                                 RXON_FILTER_BCON_AWARE_MSK)
 
-struct iwl_measure_channel {
+struct il_measure_channel {
        __le32 duration;        /* measurement duration in extended beacon
                                 * format */
        u8 channel;             /* channel to measure */
-       u8 type;                /* see enum iwl_measure_type */
+       u8 type;                /* see enum il_measure_type */
        __le16 reserved;
 } __packed;
 
 /*
- * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command)
+ * C_SPECTRUM_MEASUREMENT = 0x74 (command)
  */
-struct iwl_spectrum_cmd {
+struct il_spectrum_cmd {
        __le16 len;             /* number of bytes starting from token */
        u8 token;               /* token id */
        u8 id;                  /* measurement id -- 0 or 1 */
@@ -2174,13 +2155,13 @@ struct iwl_spectrum_cmd {
        __le32 filter_flags;    /* rxon filter flags */
        __le16 channel_count;   /* minimum 1, maximum 10 */
        __le16 reserved3;
-       struct iwl_measure_channel channels[10];
+       struct il_measure_channel channels[10];
 } __packed;
 
 /*
- * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response)
+ * C_SPECTRUM_MEASUREMENT = 0x74 (response)
  */
-struct iwl_spectrum_resp {
+struct il_spectrum_resp {
        u8 token;
        u8 id;                  /* id of the prior command replaced, or 0xff */
        __le16 status;          /* 0 - command will be handled
@@ -2188,57 +2169,57 @@ struct iwl_spectrum_resp {
                                 *     measurement) */
 } __packed;
 
-enum iwl_measurement_state {
-       IWL_MEASUREMENT_START = 0,
-       IWL_MEASUREMENT_STOP = 1,
+enum il_measurement_state {
+       IL_MEASUREMENT_START = 0,
+       IL_MEASUREMENT_STOP = 1,
 };
 
-enum iwl_measurement_status {
-       IWL_MEASUREMENT_OK = 0,
-       IWL_MEASUREMENT_CONCURRENT = 1,
-       IWL_MEASUREMENT_CSA_CONFLICT = 2,
-       IWL_MEASUREMENT_TGH_CONFLICT = 3,
+enum il_measurement_status {
+       IL_MEASUREMENT_OK = 0,
+       IL_MEASUREMENT_CONCURRENT = 1,
+       IL_MEASUREMENT_CSA_CONFLICT = 2,
+       IL_MEASUREMENT_TGH_CONFLICT = 3,
        /* 4-5 reserved */
-       IWL_MEASUREMENT_STOPPED = 6,
-       IWL_MEASUREMENT_TIMEOUT = 7,
-       IWL_MEASUREMENT_PERIODIC_FAILED = 8,
+       IL_MEASUREMENT_STOPPED = 6,
+       IL_MEASUREMENT_TIMEOUT = 7,
+       IL_MEASUREMENT_PERIODIC_FAILED = 8,
 };
 
 #define NUM_ELEMENTS_IN_HISTOGRAM 8
 
-struct iwl_measurement_histogram {
+struct il_measurement_histogram {
        __le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 0.8usec counts */
        __le32 cck[NUM_ELEMENTS_IN_HISTOGRAM];  /* in 1usec counts */
 } __packed;
 
 /* clear channel availability counters */
-struct iwl_measurement_cca_counters {
+struct il_measurement_cca_counters {
        __le32 ofdm;
        __le32 cck;
 } __packed;
 
-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),
+enum il_measure_type {
+       IL_MEASURE_BASIC = (1 << 0),
+       IL_MEASURE_CHANNEL_LOAD = (1 << 1),
+       IL_MEASURE_HISTOGRAM_RPI = (1 << 2),
+       IL_MEASURE_HISTOGRAM_NOISE = (1 << 3),
+       IL_MEASURE_FRAME = (1 << 4),
        /* bits 5:6 are reserved */
-       IWL_MEASURE_IDLE = (1 << 7),
+       IL_MEASURE_IDLE = (1 << 7),
 };
 
 /*
- * SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command)
+ * N_SPECTRUM_MEASUREMENT = 0x75 (notification only, not a command)
  */
-struct iwl_spectrum_notification {
+struct il_spectrum_notification {
        u8 id;                  /* measurement id -- 0 or 1 */
        u8 token;
-       u8 channel_index;       /* index in measurement channel list */
+       u8 channel_idx;         /* idx 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 type;                /* see enum il_measurement_type */
        u8 reserved1;
        /* NOTE:  cca_ofdm, cca_cck, basic_type, and histogram are only only
         * valid if applicable for measurement type requested. */
@@ -2248,9 +2229,9 @@ struct iwl_spectrum_notification {
        u8 basic_type;          /* 0 - bss, 1 - ofdm preamble, 2 -
                                 * unidentified */
        u8 reserved2[3];
-       struct iwl_measurement_histogram histogram;
+       struct il_measurement_histogram histogram;
        __le32 stop_time;       /* lower 32-bits of TSF */
-       __le32 status;          /* see iwl_measurement_status */
+       __le32 status;          /* see il_measurement_status */
 } __packed;
 
 /******************************************************************************
@@ -2260,10 +2241,10 @@ struct iwl_spectrum_notification {
  *****************************************************************************/
 
 /**
- * struct iwl_powertable_cmd - Power Table Command
+ * struct il_powertable_cmd - Power Table Command
  * @flags: See below:
  *
- * POWER_TABLE_CMD = 0x77 (command, has simple generic response)
+ * C_POWER_TBL = 0x77 (command, has simple generic response)
  *
  * PM allow:
  *   bit 0 - '0' Driver not allow power management
@@ -2290,38 +2271,38 @@ struct iwl_spectrum_notification {
  *              '10' force xtal sleep
  *              '11' Illegal set
  *
- * NOTE: if sleep_interval[SLEEP_INTRVL_TABLE_SIZE-1] > DTIM period then
+ * NOTE: if sleep_interval[SLEEP_INTRVL_TBL_SIZE-1] > DTIM period then
  * ucode assume sleep over DTIM is allowed and we don't need to wake up
  * for every DTIM.
  */
-#define IWL_POWER_VEC_SIZE 5
+#define IL_POWER_VEC_SIZE 5
 
-#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK       cpu_to_le16(BIT(0))
-#define IWL_POWER_PCI_PM_MSK                   cpu_to_le16(BIT(3))
+#define IL_POWER_DRIVER_ALLOW_SLEEP_MSK        cpu_to_le16(BIT(0))
+#define IL_POWER_PCI_PM_MSK                    cpu_to_le16(BIT(3))
 
-struct iwl3945_powertable_cmd {
+struct il3945_powertable_cmd {
        __le16 flags;
        u8 reserved[2];
        __le32 rx_data_timeout;
        __le32 tx_data_timeout;
-       __le32 sleep_interval[IWL_POWER_VEC_SIZE];
+       __le32 sleep_interval[IL_POWER_VEC_SIZE];
 } __packed;
 
-struct iwl_powertable_cmd {
+struct il_powertable_cmd {
        __le16 flags;
-       u8 keep_alive_seconds;          /* 3945 reserved */
-       u8 debug_flags;                 /* 3945 reserved */
+       u8 keep_alive_seconds;  /* 3945 reserved */
+       u8 debug_flags;         /* 3945 reserved */
        __le32 rx_data_timeout;
        __le32 tx_data_timeout;
-       __le32 sleep_interval[IWL_POWER_VEC_SIZE];
+       __le32 sleep_interval[IL_POWER_VEC_SIZE];
        __le32 keep_alive_beacons;
 } __packed;
 
 /*
- * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
+ * N_PM_SLEEP = 0x7A (notification only, not a command)
  * all devices identical.
  */
-struct iwl_sleep_notification {
+struct il_sleep_notification {
        u8 pm_sleep_mode;
        u8 pm_wakeup_src;
        __le16 reserved;
@@ -2332,23 +2313,23 @@ struct iwl_sleep_notification {
 
 /* Sleep states.  all devices 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,
+       IL_PM_NO_SLEEP = 0,
+       IL_PM_SLP_MAC = 1,
+       IL_PM_SLP_FULL_MAC_UNASSOCIATE = 2,
+       IL_PM_SLP_FULL_MAC_CARD_STATE = 3,
+       IL_PM_SLP_PHY = 4,
+       IL_PM_SLP_REPENT = 5,
+       IL_PM_WAKEUP_BY_TIMER = 6,
+       IL_PM_WAKEUP_BY_DRIVER = 7,
+       IL_PM_WAKEUP_BY_RFKILL = 8,
        /* 3 reserved */
-       IWL_PM_NUM_OF_MODES = 12,
+       IL_PM_NUM_OF_MODES = 12,
 };
 
 /*
- * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command)
+ * N_CARD_STATE = 0xa1 (notification only, not a command)
  */
-struct iwl_card_state_notif {
+struct il_card_state_notif {
        __le32 flags;
 } __packed;
 
@@ -2357,11 +2338,11 @@ struct iwl_card_state_notif {
 #define CT_CARD_DISABLED   0x04
 #define RXON_CARD_DISABLED 0x10
 
-struct iwl_ct_kill_config {
-       __le32   reserved;
-       __le32   critical_temperature_M;
-       __le32   critical_temperature_R;
-}  __packed;
+struct il_ct_kill_config {
+       __le32 reserved;
+       __le32 critical_temperature_M;
+       __le32 critical_temperature_R;
+} __packed;
 
 /******************************************************************************
  * (8)
@@ -2373,7 +2354,7 @@ struct iwl_ct_kill_config {
 #define SCAN_CHANNEL_TYPE_ACTIVE  cpu_to_le32(1)
 
 /**
- * struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table
+ * struct il_scan_channel - entry in C_SCAN channel table
  *
  * One for each channel in the scan list.
  * Each channel can independently select:
@@ -2383,7 +2364,7 @@ struct iwl_ct_kill_config {
  *     quiet_plcp_th, good_CRC_th)
  *
  * To avoid uCode errors, make sure the following are true (see comments
- * under struct iwl_scan_cmd about max_out_time and quiet_time):
+ * under struct il_scan_cmd about max_out_time and quiet_time):
  * 1)  If using passive_dwell (i.e. passive_dwell != 0):
  *     active_dwell <= passive_dwell (< max_out_time if max_out_time != 0)
  * 2)  quiet_time <= active_dwell
@@ -2391,7 +2372,7 @@ struct iwl_ct_kill_config {
  *     passive_dwell < max_out_time
  *     active_dwell < max_out_time
  */
-struct iwl3945_scan_channel {
+struct il3945_scan_channel {
        /*
         * type is defined as:
         * 0:0 1 = active, 0 = passive
@@ -2400,16 +2381,16 @@ struct iwl3945_scan_channel {
         * 5:7 reserved
         */
        u8 type;
-       u8 channel;     /* band is selected by iwl3945_scan_cmd "flags" field */
-       struct iwl3945_tx_power tpc;
+       u8 channel;             /* band is selected by il3945_scan_cmd "flags" field */
+       struct il3945_tx_power tpc;
        __le16 active_dwell;    /* in 1024-uSec TU (time units), typ 5-50 */
        __le16 passive_dwell;   /* in 1024-uSec TU (time units), typ 20-500 */
 } __packed;
 
 /* set number of direct probes u8 type */
-#define IWL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1))))
+#define IL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1))))
 
-struct iwl_scan_channel {
+struct il_scan_channel {
        /*
         * type is defined as:
         * 0:0 1 = active, 0 = passive
@@ -2418,7 +2399,7 @@ struct iwl_scan_channel {
         * 21:31 reserved
         */
        __le32 type;
-       __le16 channel; /* band is selected by iwl_scan_cmd "flags" field */
+       __le16 channel;         /* band is selected by il_scan_cmd "flags" field */
        u8 tx_gain;             /* gain for analog radio */
        u8 dsp_atten;           /* gain for DSP */
        __le16 active_dwell;    /* in 1024-uSec TU (time units), typ 5-50 */
@@ -2426,17 +2407,17 @@ struct iwl_scan_channel {
 } __packed;
 
 /* set number of direct probes __le32 type */
-#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
+#define IL_SCAN_PROBE_MASK(n)  cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
 
 /**
- * struct iwl_ssid_ie - directed scan network information element
+ * struct il_ssid_ie - directed scan network information element
  *
- * Up to 20 of these may appear in REPLY_SCAN_CMD (Note: Only 4 are in
- * 3945 SCAN api), selected by "type" bit field in struct iwl_scan_channel;
+ * Up to 20 of these may appear in C_SCAN (Note: Only 4 are in
+ * 3945 SCAN api), selected by "type" bit field in struct il_scan_channel;
  * each channel may select different ssids from among the 20 (4) entries.
  * SSID IEs get transmitted in reverse order of entry.
  */
-struct iwl_ssid_ie {
+struct il_ssid_ie {
        u8 id;
        u8 len;
        u8 ssid[32];
@@ -2445,14 +2426,14 @@ struct iwl_ssid_ie {
 #define PROBE_OPTION_MAX_3945          4
 #define PROBE_OPTION_MAX               20
 #define TX_CMD_LIFE_TIME_INFINITE      cpu_to_le32(0xFFFFFFFF)
-#define IWL_GOOD_CRC_TH_DISABLED       0
-#define IWL_GOOD_CRC_TH_DEFAULT                cpu_to_le16(1)
-#define IWL_GOOD_CRC_TH_NEVER          cpu_to_le16(0xffff)
-#define IWL_MAX_SCAN_SIZE 1024
-#define IWL_MAX_CMD_SIZE 4096
+#define IL_GOOD_CRC_TH_DISABLED        0
+#define IL_GOOD_CRC_TH_DEFAULT         cpu_to_le16(1)
+#define IL_GOOD_CRC_TH_NEVER           cpu_to_le16(0xffff)
+#define IL_MAX_SCAN_SIZE 1024
+#define IL_MAX_CMD_SIZE 4096
 
 /*
- * REPLY_SCAN_CMD = 0x80 (command)
+ * C_SCAN = 0x80 (command)
  *
  * The hardware scan command is very powerful; the driver can set it up to
  * maintain (relatively) normal network traffic while doing a scan in the
@@ -2501,10 +2482,10 @@ struct iwl_ssid_ie {
  * Driver must use separate scan commands for 2.4 vs. 5 GHz bands.
  *
  * To avoid uCode errors, see timing restrictions described under
- * struct iwl_scan_channel.
+ * struct il_scan_channel.
  */
 
-struct iwl3945_scan_cmd {
+struct il3945_scan_cmd {
        __le16 len;
        u8 reserved0;
        u8 channel_count;       /* # channels in channel list */
@@ -2525,10 +2506,10 @@ struct iwl3945_scan_cmd {
 
        /* For active scans (set to all-0s for passive scans).
         * Does not include payload.  Must specify Tx rate; no rate scaling. */
-       struct iwl3945_tx_cmd tx_cmd;
+       struct il3945_tx_cmd tx_cmd;
 
        /* For directed active scans (set to all-0s otherwise) */
-       struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945];
+       struct il_ssid_ie direct_scan[PROBE_OPTION_MAX_3945];
 
        /*
         * Probe request frame, followed by channel list.
@@ -2538,17 +2519,17 @@ struct iwl3945_scan_cmd {
         * Number of channels in list is specified by channel_count.
         * Each channel in list is of type:
         *
-        * struct iwl3945_scan_channel channels[0];
+        * struct il3945_scan_channel channels[0];
         *
         * NOTE:  Only one band of channels can be scanned per pass.  You
         * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
-        * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
+        * for one scan to complete (i.e. receive N_SCAN_COMPLETE)
         * before requesting another scan.
         */
        u8 data[0];
 } __packed;
 
-struct iwl_scan_cmd {
+struct il_scan_cmd {
        __le16 len;
        u8 reserved0;
        u8 channel_count;       /* # channels in channel list */
@@ -2569,10 +2550,10 @@ struct iwl_scan_cmd {
 
        /* For active scans (set to all-0s for passive scans).
         * Does not include payload.  Must specify Tx rate; no rate scaling. */
-       struct iwl_tx_cmd tx_cmd;
+       struct il_tx_cmd tx_cmd;
 
        /* For directed active scans (set to all-0s otherwise) */
-       struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
+       struct il_ssid_ie direct_scan[PROBE_OPTION_MAX];
 
        /*
         * Probe request frame, followed by channel list.
@@ -2582,11 +2563,11 @@ struct iwl_scan_cmd {
         * Number of channels in list is specified by channel_count.
         * Each channel in list is of type:
         *
-        * struct iwl_scan_channel channels[0];
+        * struct il_scan_channel channels[0];
         *
         * NOTE:  Only one band of channels can be scanned per pass.  You
         * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
-        * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
+        * for one scan to complete (i.e. receive N_SCAN_COMPLETE)
         * before requesting another scan.
         */
        u8 data[0];
@@ -2598,16 +2579,16 @@ struct iwl_scan_cmd {
 #define ABORT_STATUS            0x2
 
 /*
- * REPLY_SCAN_CMD = 0x80 (response)
+ * C_SCAN = 0x80 (response)
  */
-struct iwl_scanreq_notification {
+struct il_scanreq_notification {
        __le32 status;          /* 1: okay, 2: cannot fulfill request */
 } __packed;
 
 /*
- * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command)
+ * N_SCAN_START = 0x82 (notification only, not a command)
  */
-struct iwl_scanstart_notification {
+struct il_scanstart_notification {
        __le32 tsf_low;
        __le32 tsf_high;
        __le32 beacon_timer;
@@ -2620,30 +2601,30 @@ struct iwl_scanstart_notification {
 #define  SCAN_OWNER_STATUS 0x1
 #define  MEASURE_OWNER_STATUS 0x2
 
-#define IWL_PROBE_STATUS_OK            0
-#define IWL_PROBE_STATUS_TX_FAILED     BIT(0)
+#define IL_PROBE_STATUS_OK             0
+#define IL_PROBE_STATUS_TX_FAILED      BIT(0)
 /* error statuses combined with TX_FAILED */
-#define IWL_PROBE_STATUS_FAIL_TTL      BIT(1)
-#define IWL_PROBE_STATUS_FAIL_BT       BIT(2)
+#define IL_PROBE_STATUS_FAIL_TTL       BIT(1)
+#define IL_PROBE_STATUS_FAIL_BT        BIT(2)
 
-#define NUMBER_OF_STATISTICS 1 /* first __le32 is good CRC */
+#define NUMBER_OF_STATS 1      /* first __le32 is good CRC */
 /*
- * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command)
+ * N_SCAN_RESULTS = 0x83 (notification only, not a command)
  */
-struct iwl_scanresults_notification {
+struct il_scanresults_notification {
        u8 channel;
        u8 band;
        u8 probe_status;
-       u8 num_probe_not_sent; /* not enough time to send */
+       u8 num_probe_not_sent;  /* not enough time to send */
        __le32 tsf_low;
        __le32 tsf_high;
-       __le32 statistics[NUMBER_OF_STATISTICS];
+       __le32 stats[NUMBER_OF_STATS];
 } __packed;
 
 /*
- * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command)
+ * N_SCAN_COMPLETE = 0x84 (notification only, not a command)
  */
-struct iwl_scancomplete_notification {
+struct il_scancomplete_notification {
        u8 scanned_channels;
        u8 status;
        u8 last_channel;
@@ -2651,50 +2632,49 @@ struct iwl_scancomplete_notification {
        __le32 tsf_high;
 } __packed;
 
-
 /******************************************************************************
  * (9)
  * IBSS/AP Commands and Notifications:
  *
  *****************************************************************************/
 
-enum iwl_ibss_manager {
-       IWL_NOT_IBSS_MANAGER = 0,
-       IWL_IBSS_MANAGER = 1,
+enum il_ibss_manager {
+       IL_NOT_IBSS_MANAGER = 0,
+       IL_IBSS_MANAGER = 1,
 };
 
 /*
- * BEACON_NOTIFICATION = 0x90 (notification only, not a command)
+ * N_BEACON = 0x90 (notification only, not a command)
  */
 
-struct iwl3945_beacon_notif {
-       struct iwl3945_tx_resp beacon_notify_hdr;
+struct il3945_beacon_notif {
+       struct il3945_tx_resp beacon_notify_hdr;
        __le32 low_tsf;
        __le32 high_tsf;
        __le32 ibss_mgr_status;
 } __packed;
 
-struct iwl4965_beacon_notif {
-       struct iwl4965_tx_resp beacon_notify_hdr;
+struct il4965_beacon_notif {
+       struct il4965_tx_resp beacon_notify_hdr;
        __le32 low_tsf;
        __le32 high_tsf;
        __le32 ibss_mgr_status;
 } __packed;
 
 /*
- * REPLY_TX_BEACON = 0x91 (command, has simple generic response)
+ * C_TX_BEACON= 0x91 (command, has simple generic response)
  */
 
-struct iwl3945_tx_beacon_cmd {
-       struct iwl3945_tx_cmd tx;
+struct il3945_tx_beacon_cmd {
+       struct il3945_tx_cmd tx;
        __le16 tim_idx;
        u8 tim_size;
        u8 reserved1;
        struct ieee80211_hdr frame[0];  /* beacon frame */
 } __packed;
 
-struct iwl_tx_beacon_cmd {
-       struct iwl_tx_cmd tx;
+struct il_tx_beacon_cmd {
+       struct il_tx_cmd tx;
        __le16 tim_idx;
        u8 tim_size;
        u8 reserved1;
@@ -2707,7 +2687,7 @@ struct iwl_tx_beacon_cmd {
  *
  *****************************************************************************/
 
-#define IWL_TEMP_CONVERT 260
+#define IL_TEMP_CONVERT 260
 
 #define SUP_RATE_11A_MAX_NUM_CHANNELS  8
 #define SUP_RATE_11B_MAX_NUM_CHANNELS  4
@@ -2727,9 +2707,9 @@ struct rate_histogram {
        } failed;
 } __packed;
 
-/* statistics command response */
+/* stats command response */
 
-struct iwl39_statistics_rx_phy {
+struct iwl39_stats_rx_phy {
        __le32 ina_cnt;
        __le32 fina_cnt;
        __le32 plcp_err;
@@ -2747,7 +2727,7 @@ struct iwl39_statistics_rx_phy {
        __le32 sent_cts_cnt;
 } __packed;
 
-struct iwl39_statistics_rx_non_phy {
+struct iwl39_stats_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
@@ -2758,13 +2738,13 @@ struct iwl39_statistics_rx_non_phy {
                                         * our serving channel */
 } __packed;
 
-struct iwl39_statistics_rx {
-       struct iwl39_statistics_rx_phy ofdm;
-       struct iwl39_statistics_rx_phy cck;
-       struct iwl39_statistics_rx_non_phy general;
+struct iwl39_stats_rx {
+       struct iwl39_stats_rx_phy ofdm;
+       struct iwl39_stats_rx_phy cck;
+       struct iwl39_stats_rx_non_phy general;
 } __packed;
 
-struct iwl39_statistics_tx {
+struct iwl39_stats_tx {
        __le32 preamble_cnt;
        __le32 rx_detected_cnt;
        __le32 bt_prio_defer_cnt;
@@ -2776,31 +2756,31 @@ struct iwl39_statistics_tx {
        __le32 actual_ack_cnt;
 } __packed;
 
-struct statistics_dbg {
+struct stats_dbg {
        __le32 burst_check;
        __le32 burst_count;
        __le32 wait_for_silence_timeout_cnt;
        __le32 reserved[3];
 } __packed;
 
-struct iwl39_statistics_div {
+struct iwl39_stats_div {
        __le32 tx_on_a;
        __le32 tx_on_b;
        __le32 exec_time;
        __le32 probe_time;
 } __packed;
 
-struct iwl39_statistics_general {
+struct iwl39_stats_general {
        __le32 temperature;
-       struct statistics_dbg dbg;
+       struct stats_dbg dbg;
        __le32 sleep_time;
        __le32 slots_out;
        __le32 slots_idle;
        __le32 ttl_timestamp;
-       struct iwl39_statistics_div div;
+       struct iwl39_stats_div div;
 } __packed;
 
-struct statistics_rx_phy {
+struct stats_rx_phy {
        __le32 ina_cnt;
        __le32 fina_cnt;
        __le32 plcp_err;
@@ -2823,7 +2803,7 @@ struct statistics_rx_phy {
        __le32 reserved3;
 } __packed;
 
-struct statistics_rx_ht_phy {
+struct stats_rx_ht_phy {
        __le32 plcp_err;
        __le32 overrun_err;
        __le32 early_overrun_err;
@@ -2838,7 +2818,7 @@ struct statistics_rx_ht_phy {
 
 #define INTERFERENCE_DATA_AVAILABLE      cpu_to_le32(1)
 
-struct statistics_rx_non_phy {
+struct stats_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
@@ -2852,15 +2832,15 @@ struct statistics_rx_non_phy {
        __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 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 in uSec */
+       __le32 channel_load;    /* counts RX Enable time in uSec */
        __le32 dsp_false_alarms;        /* DSP false alarm (both OFDM
                                         * and CCK) counter */
        __le32 beacon_rssi_a;
@@ -2871,28 +2851,28 @@ struct statistics_rx_non_phy {
        __le32 beacon_energy_c;
 } __packed;
 
-struct statistics_rx {
-       struct statistics_rx_phy ofdm;
-       struct statistics_rx_phy cck;
-       struct statistics_rx_non_phy general;
-       struct statistics_rx_ht_phy ofdm_ht;
+struct stats_rx {
+       struct stats_rx_phy ofdm;
+       struct stats_rx_phy cck;
+       struct stats_rx_non_phy general;
+       struct stats_rx_ht_phy ofdm_ht;
 } __packed;
 
 /**
- * struct statistics_tx_power - current tx power
+ * struct stats_tx_power - current tx power
  *
  * @ant_a: current tx power on chain a in 1/2 dB step
  * @ant_b: current tx power on chain b in 1/2 dB step
  * @ant_c: current tx power on chain c in 1/2 dB step
  */
-struct statistics_tx_power {
+struct stats_tx_power {
        u8 ant_a;
        u8 ant_b;
        u8 ant_c;
        u8 reserved;
 } __packed;
 
-struct statistics_tx_non_phy_agg {
+struct stats_tx_non_phy_agg {
        __le32 ba_timeout;
        __le32 ba_reschedule_frames;
        __le32 scd_query_agg_frame_cnt;
@@ -2905,7 +2885,7 @@ struct statistics_tx_non_phy_agg {
        __le32 rx_ba_rsp_cnt;
 } __packed;
 
-struct statistics_tx {
+struct stats_tx {
        __le32 preamble_cnt;
        __le32 rx_detected_cnt;
        __le32 bt_prio_defer_cnt;
@@ -2920,13 +2900,12 @@ struct statistics_tx {
        __le32 burst_abort_missing_next_frame_cnt;
        __le32 cts_timeout_collision;
        __le32 ack_or_ba_timeout_collision;
-       struct statistics_tx_non_phy_agg agg;
+       struct stats_tx_non_phy_agg agg;
 
        __le32 reserved1;
 } __packed;
 
-
-struct statistics_div {
+struct stats_div {
        __le32 tx_on_a;
        __le32 tx_on_b;
        __le32 exec_time;
@@ -2935,14 +2914,14 @@ struct statistics_div {
        __le32 reserved2;
 } __packed;
 
-struct statistics_general_common {
-       __le32 temperature;   /* radio temperature */
-       struct statistics_dbg dbg;
+struct stats_general_common {
+       __le32 temperature;     /* radio temperature */
+       struct stats_dbg dbg;
        __le32 sleep_time;
        __le32 slots_out;
        __le32 slots_idle;
        __le32 ttl_timestamp;
-       struct statistics_div div;
+       struct stats_div div;
        __le32 rx_enable_counter;
        /*
         * num_of_sos_states:
@@ -2952,73 +2931,73 @@ struct statistics_general_common {
        __le32 num_of_sos_states;
 } __packed;
 
-struct statistics_general {
-       struct statistics_general_common common;
+struct stats_general {
+       struct stats_general_common common;
        __le32 reserved2;
        __le32 reserved3;
 } __packed;
 
-#define UCODE_STATISTICS_CLEAR_MSK             (0x1 << 0)
-#define UCODE_STATISTICS_FREQUENCY_MSK         (0x1 << 1)
-#define UCODE_STATISTICS_NARROW_BAND_MSK       (0x1 << 2)
+#define UCODE_STATS_CLEAR_MSK          (0x1 << 0)
+#define UCODE_STATS_FREQUENCY_MSK              (0x1 << 1)
+#define UCODE_STATS_NARROW_BAND_MSK    (0x1 << 2)
 
 /*
- * REPLY_STATISTICS_CMD = 0x9c,
+ * C_STATS = 0x9c,
  * all devices identical.
  *
- * This command triggers an immediate response containing uCode statistics.
- * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below.
+ * This command triggers an immediate response containing uCode stats.
+ * The response is in the same format as N_STATS 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).
+ * internal copy of the stats (counters) after issuing the response.
+ * This flag does not affect N_STATSs 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.
+ * N_STATSs after received beacons (see below).  This flag
+ * does not affect the response to the C_STATS 0x9c itself.
  */
-#define IWL_STATS_CONF_CLEAR_STATS cpu_to_le32(0x1)    /* see above */
-#define IWL_STATS_CONF_DISABLE_NOTIF cpu_to_le32(0x2)/* see above */
-struct iwl_statistics_cmd {
-       __le32 configuration_flags;     /* IWL_STATS_CONF_* */
+#define IL_STATS_CONF_CLEAR_STATS cpu_to_le32(0x1)     /* see above */
+#define IL_STATS_CONF_DISABLE_NOTIF cpu_to_le32(0x2)   /* see above */
+struct il_stats_cmd {
+       __le32 configuration_flags;     /* IL_STATS_CONF_* */
 } __packed;
 
 /*
- * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)
+ * N_STATS = 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.
+ * C_STATS 0x9c, above.
  *
  * Statistics counters continue to increment beacon after beacon, but are
- * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD
+ * cleared when changing channels or when driver issues C_STATS
  * 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
+ * uCode also issues this notification during scans.  uCode clears stats
+ * appropriately so that each notification contains stats for only the
  * one channel that has just been scanned.
  */
-#define STATISTICS_REPLY_FLG_BAND_24G_MSK         cpu_to_le32(0x2)
-#define STATISTICS_REPLY_FLG_HT40_MODE_MSK        cpu_to_le32(0x8)
+#define STATS_REPLY_FLG_BAND_24G_MSK         cpu_to_le32(0x2)
+#define STATS_REPLY_FLG_HT40_MODE_MSK        cpu_to_le32(0x8)
 
-struct iwl3945_notif_statistics {
+struct il3945_notif_stats {
        __le32 flag;
-       struct iwl39_statistics_rx rx;
-       struct iwl39_statistics_tx tx;
-       struct iwl39_statistics_general general;
+       struct iwl39_stats_rx rx;
+       struct iwl39_stats_tx tx;
+       struct iwl39_stats_general general;
 } __packed;
 
-struct iwl_notif_statistics {
+struct il_notif_stats {
        __le32 flag;
-       struct statistics_rx rx;
-       struct statistics_tx tx;
-       struct statistics_general general;
+       struct stats_rx rx;
+       struct stats_tx tx;
+       struct stats_general general;
 } __packed;
 
 /*
- * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command)
+ * N_MISSED_BEACONS = 0xa2 (notification only, not a command)
  *
- * uCode send MISSED_BEACONS_NOTIFICATION to driver when detect beacon missed
+ * uCode send N_MISSED_BEACONS to driver when detect beacon missed
  * in regardless of how many missed beacons, which mean when driver receive the
  * notification, inside the command, it can find all the beacons information
  * which include number of total missed beacons, number of consecutive missed
@@ -3035,18 +3014,17 @@ struct iwl_notif_statistics {
  *
  */
 
-#define IWL_MISSED_BEACON_THRESHOLD_MIN        (1)
-#define IWL_MISSED_BEACON_THRESHOLD_DEF        (5)
-#define IWL_MISSED_BEACON_THRESHOLD_MAX        IWL_MISSED_BEACON_THRESHOLD_DEF
+#define IL_MISSED_BEACON_THRESHOLD_MIN (1)
+#define IL_MISSED_BEACON_THRESHOLD_DEF (5)
+#define IL_MISSED_BEACON_THRESHOLD_MAX IL_MISSED_BEACON_THRESHOLD_DEF
 
-struct iwl_missed_beacon_notif {
+struct il_missed_beacon_notif {
        __le32 consecutive_missed_beacons;
        __le32 total_missed_becons;
        __le32 num_expected_beacons;
        __le32 num_recvd_beacons;
 } __packed;
 
-
 /******************************************************************************
  * (11)
  * Rx Calibration Commands:
@@ -3062,7 +3040,7 @@ struct iwl_missed_beacon_notif {
  *****************************************************************************/
 
 /**
- * SENSITIVITY_CMD = 0xa8 (command, has simple generic response)
+ * C_SENSITIVITY = 0xa8 (command, has simple generic response)
  *
  * This command sets up the Rx signal detector for a sensitivity level that
  * is high enough to lock onto all signals within the associated network,
@@ -3076,12 +3054,12 @@ struct iwl_missed_beacon_notif {
  * time listening, not transmitting).  Driver must adjust sensitivity so that
  * the ratio of actual false alarms to actual Rx time falls within this range.
  *
- * While associated, uCode delivers STATISTICS_NOTIFICATIONs after each
+ * While associated, uCode delivers N_STATSs after each
  * received beacon.  These provide information to the driver to analyze the
- * sensitivity.  Don't analyze statistics that come in from scanning, or any
- * other non-associated-network source.  Pertinent statistics include:
+ * sensitivity.  Don't analyze stats that come in from scanning, or any
+ * other non-associated-network source.  Pertinent stats include:
  *
- * From "general" statistics (struct statistics_rx_non_phy):
+ * From "general" stats (struct stats_rx_non_phy):
  *
  * (beacon_energy_[abc] & 0x0FF00) >> 8 (unsigned, higher value is lower level)
  *   Measure of energy of desired signal.  Used for establishing a level
@@ -3094,7 +3072,7 @@ struct iwl_missed_beacon_notif {
  *   uSecs of actual Rx time during beacon period (varies according to
  *   how much time was spent transmitting).
  *
- * From "cck" and "ofdm" statistics (struct statistics_rx_phy), separately:
+ * From "cck" and "ofdm" stats (struct stats_rx_phy), separately:
  *
  * false_alarm_cnt
  *   Signal locks abandoned early (before phy-level header).
@@ -3111,15 +3089,15 @@ struct iwl_missed_beacon_notif {
  *
  * Total number of false alarms = false_alarms + plcp_errs
  *
- * For OFDM, adjust the following table entries in struct iwl_sensitivity_cmd
+ * For OFDM, adjust the following table entries in struct il_sensitivity_cmd
  * (notice that the start points for OFDM are at or close to settings for
  * maximum sensitivity):
  *
  *                                             START  /  MIN  /  MAX
- *   HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX          90   /   85  /  120
- *   HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX     170   /  170  /  210
- *   HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX         105   /  105  /  140
- *   HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX     220   /  220  /  270
+ *   HD_AUTO_CORR32_X1_TH_ADD_MIN_IDX          90   /   85  /  120
+ *   HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX     170   /  170  /  210
+ *   HD_AUTO_CORR32_X4_TH_ADD_MIN_IDX         105   /  105  /  140
+ *   HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX     220   /  220  /  270
  *
  *   If actual rate of OFDM false alarms (+ plcp_errors) is too high
  *   (greater than 50 for each 204.8 msecs listening), reduce sensitivity
@@ -3152,30 +3130,30 @@ struct iwl_missed_beacon_notif {
  *        Reset this to 0 at the first beacon period that falls within the
  *        "good" range (5 to 50 false alarms per 204.8 milliseconds rx).
  *
- * Then, adjust the following CCK table entries in struct iwl_sensitivity_cmd
+ * Then, adjust the following CCK table entries in struct il_sensitivity_cmd
  * (notice that the start points for CCK are at maximum sensitivity):
  *
  *                                             START  /  MIN  /  MAX
- *   HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX         125   /  125  /  200
- *   HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX     200   /  200  /  400
- *   HD_MIN_ENERGY_CCK_DET_INDEX                100   /    0  /  100
+ *   HD_AUTO_CORR40_X4_TH_ADD_MIN_IDX         125   /  125  /  200
+ *   HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX     200   /  200  /  400
+ *   HD_MIN_ENERGY_CCK_DET_IDX                100   /    0  /  100
  *
  *   If actual rate of CCK false alarms (+ plcp_errors) is too high
  *   (greater than 50 for each 204.8 msecs listening), method for reducing
  *   sensitivity is:
  *
- *   1)  *Add* 3 to value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX,
+ *   1)  *Add* 3 to value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX,
  *       up to max 400.
  *
- *   2)  If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is < 160,
+ *   2)  If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_IDX is < 160,
  *       sensitivity has been reduced a significant amount; bring it up to
  *       a moderate 161.  Otherwise, *add* 3, up to max 200.
  *
- *   3)  a)  If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is > 160,
+ *   3)  a)  If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_IDX is > 160,
  *       sensitivity has been reduced only a moderate or small amount;
- *       *subtract* 2 from value in HD_MIN_ENERGY_CCK_DET_INDEX,
+ *       *subtract* 2 from value in HD_MIN_ENERGY_CCK_DET_IDX,
  *       down to min 0.  Otherwise (if gain has been significantly reduced),
- *       don't change the HD_MIN_ENERGY_CCK_DET_INDEX value.
+ *       don't change the HD_MIN_ENERGY_CCK_DET_IDX value.
  *
  *       b)  Save a snapshot of the "silence reference".
  *
@@ -3191,13 +3169,13 @@ struct iwl_missed_beacon_notif {
  *
  *   Method for increasing sensitivity:
  *
- *   1)  *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX,
+ *   1)  *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_IDX,
  *       down to min 125.
  *
- *   2)  *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX,
+ *   2)  *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX,
  *       down to min 200.
  *
- *   3)  *Add* 2 to value in HD_MIN_ENERGY_CCK_DET_INDEX, up to max 100.
+ *   3)  *Add* 2 to value in HD_MIN_ENERGY_CCK_DET_IDX, up to max 100.
  *
  *   If actual rate of CCK false alarms (+ plcp_errors) is within good range
  *   (between 5 and 50 for each 204.8 msecs listening):
@@ -3206,57 +3184,56 @@ struct iwl_missed_beacon_notif {
  *
  *   2)  If previous beacon had too many CCK false alarms (+ plcp_errors),
  *       give some extra margin to energy threshold by *subtracting* 8
- *       from value in HD_MIN_ENERGY_CCK_DET_INDEX.
+ *       from value in HD_MIN_ENERGY_CCK_DET_IDX.
  *
  *   For all cases (too few, too many, good range), make sure that the CCK
  *   detection threshold (energy) is below the energy level for robust
  *   detection over the past 10 beacon periods, the "Max cck energy".
  *   Lower values mean higher energy; this means making sure that the value
- *   in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy".
+ *   in HD_MIN_ENERGY_CCK_DET_IDX is at or *above* "Max cck energy".
  *
  */
 
 /*
- * Table entries in SENSITIVITY_CMD (struct iwl_sensitivity_cmd)
- */
-#define HD_TABLE_SIZE  (11)    /* number of entries */
-#define HD_MIN_ENERGY_CCK_DET_INDEX                 (0)        /* table indexes */
-#define HD_MIN_ENERGY_OFDM_DET_INDEX                (1)
-#define HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX          (2)
-#define HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX      (3)
-#define HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX      (4)
-#define HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX          (5)
-#define HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX      (6)
-#define HD_BARKER_CORR_TH_ADD_MIN_INDEX             (7)
-#define HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX         (8)
-#define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX          (9)
-#define HD_OFDM_ENERGY_TH_IN_INDEX                  (10)
-
-/* Control field in struct iwl_sensitivity_cmd */
-#define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE  cpu_to_le16(0)
-#define SENSITIVITY_CMD_CONTROL_WORK_TABLE     cpu_to_le16(1)
+ * Table entries in C_SENSITIVITY (struct il_sensitivity_cmd)
+ */
+#define HD_TBL_SIZE  (11)      /* number of entries */
+#define HD_MIN_ENERGY_CCK_DET_IDX                 (0)  /* table idxes */
+#define HD_MIN_ENERGY_OFDM_DET_IDX                (1)
+#define HD_AUTO_CORR32_X1_TH_ADD_MIN_IDX          (2)
+#define HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX      (3)
+#define HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX      (4)
+#define HD_AUTO_CORR32_X4_TH_ADD_MIN_IDX          (5)
+#define HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX      (6)
+#define HD_BARKER_CORR_TH_ADD_MIN_IDX             (7)
+#define HD_BARKER_CORR_TH_ADD_MIN_MRC_IDX         (8)
+#define HD_AUTO_CORR40_X4_TH_ADD_MIN_IDX          (9)
+#define HD_OFDM_ENERGY_TH_IN_IDX                  (10)
+
+/* Control field in struct il_sensitivity_cmd */
+#define C_SENSITIVITY_CONTROL_DEFAULT_TBL      cpu_to_le16(0)
+#define C_SENSITIVITY_CONTROL_WORK_TBL cpu_to_le16(1)
 
 /**
- * struct iwl_sensitivity_cmd
+ * struct il_sensitivity_cmd
  * @control:  (1) updates working table, (0) updates default table
- * @table:  energy threshold values, use HD_* as index into table
+ * @table:  energy threshold values, use HD_* as idx into table
  *
  * Always use "1" in "control" to update uCode's working table and DSP.
  */
-struct iwl_sensitivity_cmd {
-       __le16 control;                 /* always use "1" */
-       __le16 table[HD_TABLE_SIZE];    /* use HD_* as index */
+struct il_sensitivity_cmd {
+       __le16 control;         /* always use "1" */
+       __le16 table[HD_TBL_SIZE];      /* use HD_* as idx */
 } __packed;
 
-
 /**
- * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response)
+ * C_PHY_CALIBRATION = 0xb0 (command, has simple generic response)
  *
  * This command sets the relative gains of 4965 device's 3 radio receiver chains.
  *
  * After the first association, driver should accumulate signal and noise
- * statistics from the STATISTICS_NOTIFICATIONs that follow the first 20
- * beacons from the associated network (don't collect statistics that come
+ * stats from the N_STATSs that follow the first 20
+ * beacons from the associated network (don't collect stats that come
  * in from scanning, or any other non-network source).
  *
  * DISCONNECTED ANTENNA:
@@ -3264,7 +3241,7 @@ struct iwl_sensitivity_cmd {
  * Driver should determine which antennas are actually connected, by comparing
  * average beacon signal levels for the 3 Rx chains.  Accumulate (add) the
  * following values over 20 beacons, one accumulator for each of the chains
- * a/b/c, from struct statistics_rx_non_phy:
+ * a/b/c, from struct stats_rx_non_phy:
  *
  * beacon_rssi_[abc] & 0x0FF (unsigned, units in dB)
  *
@@ -3283,7 +3260,7 @@ struct iwl_sensitivity_cmd {
  * to antennas, see above) for gain, by comparing the average signal levels
  * detected during the silence after each beacon (background noise).
  * Accumulate (add) the following values over 20 beacons, one accumulator for
- * each of the chains a/b/c, from struct statistics_rx_non_phy:
+ * each of the chains a/b/c, from struct stats_rx_non_phy:
  *
  * beacon_silence_rssi_[abc] & 0x0FF (unsigned, units in dB)
  *
@@ -3294,7 +3271,7 @@ struct iwl_sensitivity_cmd {
  * (accum_noise[i] - accum_noise[reference]) / 30
  *
  * The "30" adjusts the dB in the 20 accumulated samples to units of 1.5 dB.
- * For use in diff_gain_[abc] fields of struct iwl_calibration_cmd, the
+ * For use in diff_gain_[abc] fields of struct il_calibration_cmd, the
  * driver should limit the difference results to a range of 0-3 (0-4.5 dB),
  * and set bit 2 to indicate "reduce gain".  The value for the reference
  * (weakest) chain should be "0".
@@ -3306,24 +3283,24 @@ struct iwl_sensitivity_cmd {
 
 /* Phy calibration command for series */
 /* The default calibrate table size if not specified by firmware */
-#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE    18
+#define IL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE     18
 enum {
-       IWL_PHY_CALIBRATE_DIFF_GAIN_CMD         = 7,
-       IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 19,
+       IL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
+       IL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 19,
 };
 
-#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE         (253)
+#define IL_MAX_PHY_CALIBRATE_TBL_SIZE          (253)
 
-struct iwl_calib_hdr {
+struct il_calib_hdr {
        u8 op_code;
        u8 first_group;
        u8 groups_num;
        u8 data_valid;
 } __packed;
 
-/* IWL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
-struct iwl_calib_diff_gain_cmd {
-       struct iwl_calib_hdr hdr;
+/* IL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
+struct il_calib_diff_gain_cmd {
+       struct il_calib_hdr hdr;
        s8 diff_gain_a;         /* see above */
        s8 diff_gain_b;
        s8 diff_gain_c;
@@ -3338,12 +3315,12 @@ struct iwl_calib_diff_gain_cmd {
 
 /*
  * LEDs Command & Response
- * REPLY_LEDS_CMD = 0x48 (command, has simple generic response)
+ * C_LEDS = 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 {
+struct il_led_cmd {
        __le32 interval;        /* "interval" in uSec */
        u8 id;                  /* 1: Activity, 2: Link, 3: Tech */
        u8 off;                 /* # intervals off while blinking;
@@ -3353,14 +3330,15 @@ struct iwl_led_cmd {
        u8 reserved;
 } __packed;
 
-
 /******************************************************************************
  * (13)
  * Union of all expected notifications/responses:
  *
  *****************************************************************************/
 
-struct iwl_rx_packet {
+#define IL_RX_FRAME_SIZE_MSK   0x00003fff
+
+struct il_rx_pkt {
        /*
         * The first 4 bytes of the RX frame header contain both the RX frame
         * size and some flags.
@@ -3372,27 +3350,27 @@ struct iwl_rx_packet {
         * 13-00: RX frame size
         */
        __le32 len_n_flags;
-       struct iwl_cmd_header hdr;
+       struct il_cmd_header hdr;
        union {
-               struct iwl3945_rx_frame rx_frame;
-               struct iwl3945_tx_resp tx_resp;
-               struct iwl3945_beacon_notif beacon_status;
-
-               struct iwl_alive_resp alive_frame;
-               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_add_sta_resp add_sta;
-               struct iwl_rem_sta_resp rem_sta;
-               struct iwl_sleep_notification sleep_notif;
-               struct iwl_spectrum_resp spectrum;
-               struct iwl_notif_statistics stats;
-               struct iwl_compressed_ba_resp compressed_ba;
-               struct iwl_missed_beacon_notif missed_beacon;
+               struct il3945_rx_frame rx_frame;
+               struct il3945_tx_resp tx_resp;
+               struct il3945_beacon_notif beacon_status;
+
+               struct il_alive_resp alive_frame;
+               struct il_spectrum_notification spectrum_notif;
+               struct il_csa_notification csa_notif;
+               struct il_error_resp err_resp;
+               struct il_card_state_notif card_state_notif;
+               struct il_add_sta_resp add_sta;
+               struct il_rem_sta_resp rem_sta;
+               struct il_sleep_notification sleep_notif;
+               struct il_spectrum_resp spectrum;
+               struct il_notif_stats stats;
+               struct il_compressed_ba_resp compressed_ba;
+               struct il_missed_beacon_notif missed_beacon;
                __le32 status;
                u8 raw[0];
        } u;
 } __packed;
 
-#endif                         /* __iwl_legacy_commands_h__ */
+#endif /* __il_commands_h__ */
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
new file mode 100644 (file)
index 0000000..7e2924f
--- /dev/null
@@ -0,0 +1,5707 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/lockdep.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <net/mac80211.h>
+
+#include "common.h"
+
+const char *
+il_get_cmd_string(u8 cmd)
+{
+       switch (cmd) {
+               IL_CMD(N_ALIVE);
+               IL_CMD(N_ERROR);
+               IL_CMD(C_RXON);
+               IL_CMD(C_RXON_ASSOC);
+               IL_CMD(C_QOS_PARAM);
+               IL_CMD(C_RXON_TIMING);
+               IL_CMD(C_ADD_STA);
+               IL_CMD(C_REM_STA);
+               IL_CMD(C_WEPKEY);
+               IL_CMD(N_3945_RX);
+               IL_CMD(C_TX);
+               IL_CMD(C_RATE_SCALE);
+               IL_CMD(C_LEDS);
+               IL_CMD(C_TX_LINK_QUALITY_CMD);
+               IL_CMD(C_CHANNEL_SWITCH);
+               IL_CMD(N_CHANNEL_SWITCH);
+               IL_CMD(C_SPECTRUM_MEASUREMENT);
+               IL_CMD(N_SPECTRUM_MEASUREMENT);
+               IL_CMD(C_POWER_TBL);
+               IL_CMD(N_PM_SLEEP);
+               IL_CMD(N_PM_DEBUG_STATS);
+               IL_CMD(C_SCAN);
+               IL_CMD(C_SCAN_ABORT);
+               IL_CMD(N_SCAN_START);
+               IL_CMD(N_SCAN_RESULTS);
+               IL_CMD(N_SCAN_COMPLETE);
+               IL_CMD(N_BEACON);
+               IL_CMD(C_TX_BEACON);
+               IL_CMD(C_TX_PWR_TBL);
+               IL_CMD(C_BT_CONFIG);
+               IL_CMD(C_STATS);
+               IL_CMD(N_STATS);
+               IL_CMD(N_CARD_STATE);
+               IL_CMD(N_MISSED_BEACONS);
+               IL_CMD(C_CT_KILL_CONFIG);
+               IL_CMD(C_SENSITIVITY);
+               IL_CMD(C_PHY_CALIBRATION);
+               IL_CMD(N_RX_PHY);
+               IL_CMD(N_RX_MPDU);
+               IL_CMD(N_RX);
+               IL_CMD(N_COMPRESSED_BA);
+       default:
+               return "UNKNOWN";
+
+       }
+}
+EXPORT_SYMBOL(il_get_cmd_string);
+
+#define HOST_COMPLETE_TIMEOUT (HZ / 2)
+
+static void
+il_generic_cmd_callback(struct il_priv *il, struct il_device_cmd *cmd,
+                       struct il_rx_pkt *pkt)
+{
+       if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
+               IL_ERR("Bad return from %s (0x%08X)\n",
+                      il_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+               return;
+       }
+#ifdef CONFIG_IWLEGACY_DEBUG
+       switch (cmd->hdr.cmd) {
+       case C_TX_LINK_QUALITY_CMD:
+       case C_SENSITIVITY:
+               D_HC_DUMP("back from %s (0x%08X)\n",
+                         il_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+               break;
+       default:
+               D_HC("back from %s (0x%08X)\n", il_get_cmd_string(cmd->hdr.cmd),
+                    pkt->hdr.flags);
+       }
+#endif
+}
+
+static int
+il_send_cmd_async(struct il_priv *il, struct il_host_cmd *cmd)
+{
+       int ret;
+
+       BUG_ON(!(cmd->flags & CMD_ASYNC));
+
+       /* An asynchronous command can not expect an SKB to be set. */
+       BUG_ON(cmd->flags & CMD_WANT_SKB);
+
+       /* Assign a generic callback if one is not provided */
+       if (!cmd->callback)
+               cmd->callback = il_generic_cmd_callback;
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return -EBUSY;
+
+       ret = il_enqueue_hcmd(il, cmd);
+       if (ret < 0) {
+               IL_ERR("Error sending %s: enqueue_hcmd failed: %d\n",
+                      il_get_cmd_string(cmd->id), ret);
+               return ret;
+       }
+       return 0;
+}
+
+int
+il_send_cmd_sync(struct il_priv *il, struct il_host_cmd *cmd)
+{
+       int cmd_idx;
+       int ret;
+
+       lockdep_assert_held(&il->mutex);
+
+       BUG_ON(cmd->flags & CMD_ASYNC);
+
+       /* A synchronous command can not have a callback set. */
+       BUG_ON(cmd->callback);
+
+       D_INFO("Attempting to send sync command %s\n",
+              il_get_cmd_string(cmd->id));
+
+       set_bit(S_HCMD_ACTIVE, &il->status);
+       D_INFO("Setting HCMD_ACTIVE for command %s\n",
+              il_get_cmd_string(cmd->id));
+
+       cmd_idx = il_enqueue_hcmd(il, cmd);
+       if (cmd_idx < 0) {
+               ret = cmd_idx;
+               IL_ERR("Error sending %s: enqueue_hcmd failed: %d\n",
+                      il_get_cmd_string(cmd->id), ret);
+               goto out;
+       }
+
+       ret = wait_event_timeout(il->wait_command_queue,
+                                !test_bit(S_HCMD_ACTIVE, &il->status),
+                                HOST_COMPLETE_TIMEOUT);
+       if (!ret) {
+               if (test_bit(S_HCMD_ACTIVE, &il->status)) {
+                       IL_ERR("Error sending %s: time out after %dms.\n",
+                              il_get_cmd_string(cmd->id),
+                              jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+
+                       clear_bit(S_HCMD_ACTIVE, &il->status);
+                       D_INFO("Clearing HCMD_ACTIVE for command %s\n",
+                              il_get_cmd_string(cmd->id));
+                       ret = -ETIMEDOUT;
+                       goto cancel;
+               }
+       }
+
+       if (test_bit(S_RF_KILL_HW, &il->status)) {
+               IL_ERR("Command %s aborted: RF KILL Switch\n",
+                      il_get_cmd_string(cmd->id));
+               ret = -ECANCELED;
+               goto fail;
+       }
+       if (test_bit(S_FW_ERROR, &il->status)) {
+               IL_ERR("Command %s failed: FW Error\n",
+                      il_get_cmd_string(cmd->id));
+               ret = -EIO;
+               goto fail;
+       }
+       if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
+               IL_ERR("Error: Response NULL in '%s'\n",
+                      il_get_cmd_string(cmd->id));
+               ret = -EIO;
+               goto cancel;
+       }
+
+       ret = 0;
+       goto out;
+
+cancel:
+       if (cmd->flags & CMD_WANT_SKB) {
+               /*
+                * 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).
+                */
+               il->txq[il->cmd_queue].meta[cmd_idx].flags &= ~CMD_WANT_SKB;
+       }
+fail:
+       if (cmd->reply_page) {
+               il_free_pages(il, cmd->reply_page);
+               cmd->reply_page = 0;
+       }
+out:
+       return ret;
+}
+EXPORT_SYMBOL(il_send_cmd_sync);
+
+int
+il_send_cmd(struct il_priv *il, struct il_host_cmd *cmd)
+{
+       if (cmd->flags & CMD_ASYNC)
+               return il_send_cmd_async(il, cmd);
+
+       return il_send_cmd_sync(il, cmd);
+}
+EXPORT_SYMBOL(il_send_cmd);
+
+int
+il_send_cmd_pdu(struct il_priv *il, u8 id, u16 len, const void *data)
+{
+       struct il_host_cmd cmd = {
+               .id = id,
+               .len = len,
+               .data = data,
+       };
+
+       return il_send_cmd_sync(il, &cmd);
+}
+EXPORT_SYMBOL(il_send_cmd_pdu);
+
+int
+il_send_cmd_pdu_async(struct il_priv *il, u8 id, u16 len, const void *data,
+                     void (*callback) (struct il_priv *il,
+                                       struct il_device_cmd *cmd,
+                                       struct il_rx_pkt *pkt))
+{
+       struct il_host_cmd cmd = {
+               .id = id,
+               .len = len,
+               .data = data,
+       };
+
+       cmd.flags |= CMD_ASYNC;
+       cmd.callback = callback;
+
+       return il_send_cmd_async(il, &cmd);
+}
+EXPORT_SYMBOL(il_send_cmd_pdu_async);
+
+/* default: IL_LED_BLINK(0) using blinking idx table */
+static int led_mode;
+module_param(led_mode, int, S_IRUGO);
+MODULE_PARM_DESC(led_mode,
+                "0=system default, " "1=On(RF On)/Off(RF Off), 2=blinking");
+
+/* Throughput          OFF time(ms)    ON time (ms)
+ *     >300                    25              25
+ *     >200 to 300             40              40
+ *     >100 to 200             55              55
+ *     >70 to 100              65              65
+ *     >50 to 70               75              75
+ *     >20 to 50               85              85
+ *     >10 to 20               95              95
+ *     >5 to 10                110             110
+ *     >1 to 5                 130             130
+ *     >0 to 1                 167             167
+ *     <=0                                     SOLID ON
+ */
+static const struct ieee80211_tpt_blink il_blink[] = {
+       {.throughput = 0,               .blink_time = 334},
+       {.throughput = 1 * 1024 - 1,    .blink_time = 260},
+       {.throughput = 5 * 1024 - 1,    .blink_time = 220},
+       {.throughput = 10 * 1024 - 1,   .blink_time = 190},
+       {.throughput = 20 * 1024 - 1,   .blink_time = 170},
+       {.throughput = 50 * 1024 - 1,   .blink_time = 150},
+       {.throughput = 70 * 1024 - 1,   .blink_time = 130},
+       {.throughput = 100 * 1024 - 1,  .blink_time = 110},
+       {.throughput = 200 * 1024 - 1,  .blink_time = 80},
+       {.throughput = 300 * 1024 - 1,  .blink_time = 50},
+};
+
+/*
+ * Adjust led blink rate to compensate on a MAC Clock difference on every HW
+ * Led blink rate analysis showed an average deviation of 0% on 3945,
+ * 5% on 4965 HW.
+ * Need to compensate on the led on/off time per HW according to the deviation
+ * to achieve the desired led frequency
+ * The calculation is: (100-averageDeviation)/100 * blinkTime
+ * For code efficiency the calculation will be:
+ *     compensation = (100 - averageDeviation) * 64 / 100
+ *     NewBlinkTime = (compensation * BlinkTime) / 64
+ */
+static inline u8
+il_blink_compensation(struct il_priv *il, u8 time, u16 compensation)
+{
+       if (!compensation) {
+               IL_ERR("undefined blink compensation: "
+                      "use pre-defined blinking time\n");
+               return time;
+       }
+
+       return (u8) ((time * compensation) >> 6);
+}
+
+/* Set led pattern command */
+static int
+il_led_cmd(struct il_priv *il, unsigned long on, unsigned long off)
+{
+       struct il_led_cmd led_cmd = {
+               .id = IL_LED_LINK,
+               .interval = IL_DEF_LED_INTRVL
+       };
+       int ret;
+
+       if (!test_bit(S_READY, &il->status))
+               return -EBUSY;
+
+       if (il->blink_on == on && il->blink_off == off)
+               return 0;
+
+       if (off == 0) {
+               /* led is SOLID_ON */
+               on = IL_LED_SOLID;
+       }
+
+       D_LED("Led blink time compensation=%u\n",
+             il->cfg->base_params->led_compensation);
+       led_cmd.on =
+           il_blink_compensation(il, on,
+                                 il->cfg->base_params->led_compensation);
+       led_cmd.off =
+           il_blink_compensation(il, off,
+                                 il->cfg->base_params->led_compensation);
+
+       ret = il->cfg->ops->led->cmd(il, &led_cmd);
+       if (!ret) {
+               il->blink_on = on;
+               il->blink_off = off;
+       }
+       return ret;
+}
+
+static void
+il_led_brightness_set(struct led_classdev *led_cdev,
+                     enum led_brightness brightness)
+{
+       struct il_priv *il = container_of(led_cdev, struct il_priv, led);
+       unsigned long on = 0;
+
+       if (brightness > 0)
+               on = IL_LED_SOLID;
+
+       il_led_cmd(il, on, 0);
+}
+
+static int
+il_led_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on,
+                unsigned long *delay_off)
+{
+       struct il_priv *il = container_of(led_cdev, struct il_priv, led);
+
+       return il_led_cmd(il, *delay_on, *delay_off);
+}
+
+void
+il_leds_init(struct il_priv *il)
+{
+       int mode = led_mode;
+       int ret;
+
+       if (mode == IL_LED_DEFAULT)
+               mode = il->cfg->led_mode;
+
+       il->led.name =
+           kasprintf(GFP_KERNEL, "%s-led", wiphy_name(il->hw->wiphy));
+       il->led.brightness_set = il_led_brightness_set;
+       il->led.blink_set = il_led_blink_set;
+       il->led.max_brightness = 1;
+
+       switch (mode) {
+       case IL_LED_DEFAULT:
+               WARN_ON(1);
+               break;
+       case IL_LED_BLINK:
+               il->led.default_trigger =
+                   ieee80211_create_tpt_led_trigger(il->hw,
+                                                    IEEE80211_TPT_LEDTRIG_FL_CONNECTED,
+                                                    il_blink,
+                                                    ARRAY_SIZE(il_blink));
+               break;
+       case IL_LED_RF_STATE:
+               il->led.default_trigger = ieee80211_get_radio_led_name(il->hw);
+               break;
+       }
+
+       ret = led_classdev_register(&il->pci_dev->dev, &il->led);
+       if (ret) {
+               kfree(il->led.name);
+               return;
+       }
+
+       il->led_registered = true;
+}
+EXPORT_SYMBOL(il_leds_init);
+
+void
+il_leds_exit(struct il_priv *il)
+{
+       if (!il->led_registered)
+               return;
+
+       led_classdev_unregister(&il->led);
+       kfree(il->led.name);
+}
+EXPORT_SYMBOL(il_leds_exit);
+
+/************************** EEPROM BANDS ****************************
+ *
+ * The il_eeprom_band definitions below provide the mapping from the
+ * EEPROM contents to the specific channel number supported for each
+ * band.
+ *
+ * For example, il_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 il->channel_info_24/52 and il->channel_map_24/52
+ *
+ * channel_map_24/52 provides the idx 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 */
+const u8 il_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 il_eeprom_band_2[] = { /* 4915-5080MHz */
+       183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
+};
+
+static const u8 il_eeprom_band_3[] = { /* 5170-5320MHz */
+       34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+};
+
+static const u8 il_eeprom_band_4[] = { /* 5500-5700MHz */
+       100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+};
+
+static const u8 il_eeprom_band_5[] = { /* 5725-5825MHz */
+       145, 149, 153, 157, 161, 165
+};
+
+static const u8 il_eeprom_band_6[] = { /* 2.4 ht40 channel */
+       1, 2, 3, 4, 5, 6, 7
+};
+
+static const u8 il_eeprom_band_7[] = { /* 5.2 ht40 channel */
+       36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
+};
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+******************************************************************************/
+
+static int
+il_eeprom_verify_signature(struct il_priv *il)
+{
+       u32 gp = _il_rd(il, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
+       int ret = 0;
+
+       D_EEPROM("EEPROM signature=0x%08x\n", gp);
+       switch (gp) {
+       case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K:
+       case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K:
+               break;
+       default:
+               IL_ERR("bad EEPROM signature," "EEPROM_GP=0x%08x\n", gp);
+               ret = -ENOENT;
+               break;
+       }
+       return ret;
+}
+
+const u8 *
+il_eeprom_query_addr(const struct il_priv *il, size_t offset)
+{
+       BUG_ON(offset >= il->cfg->base_params->eeprom_size);
+       return &il->eeprom[offset];
+}
+EXPORT_SYMBOL(il_eeprom_query_addr);
+
+u16
+il_eeprom_query16(const struct il_priv *il, size_t offset)
+{
+       if (!il->eeprom)
+               return 0;
+       return (u16) il->eeprom[offset] | ((u16) il->eeprom[offset + 1] << 8);
+}
+EXPORT_SYMBOL(il_eeprom_query16);
+
+/**
+ * il_eeprom_init - read EEPROM contents
+ *
+ * Load the EEPROM contents from adapter into il->eeprom
+ *
+ * NOTE:  This routine uses the non-debug IO access functions.
+ */
+int
+il_eeprom_init(struct il_priv *il)
+{
+       __le16 *e;
+       u32 gp = _il_rd(il, CSR_EEPROM_GP);
+       int sz;
+       int ret;
+       u16 addr;
+
+       /* allocate eeprom */
+       sz = il->cfg->base_params->eeprom_size;
+       D_EEPROM("NVM size = %d\n", sz);
+       il->eeprom = kzalloc(sz, GFP_KERNEL);
+       if (!il->eeprom) {
+               ret = -ENOMEM;
+               goto alloc_err;
+       }
+       e = (__le16 *) il->eeprom;
+
+       il->cfg->ops->lib->apm_ops.init(il);
+
+       ret = il_eeprom_verify_signature(il);
+       if (ret < 0) {
+               IL_ERR("EEPROM not found, EEPROM_GP=0x%08x\n", gp);
+               ret = -ENOENT;
+               goto err;
+       }
+
+       /* Make sure driver (instead of uCode) is allowed to read EEPROM */
+       ret = il->cfg->ops->lib->eeprom_ops.acquire_semaphore(il);
+       if (ret < 0) {
+               IL_ERR("Failed to acquire EEPROM semaphore.\n");
+               ret = -ENOENT;
+               goto err;
+       }
+
+       /* eeprom is an array of 16bit values */
+       for (addr = 0; addr < sz; addr += sizeof(u16)) {
+               u32 r;
+
+               _il_wr(il, CSR_EEPROM_REG,
+                      CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+
+               ret =
+                   _il_poll_bit(il, CSR_EEPROM_REG,
+                                CSR_EEPROM_REG_READ_VALID_MSK,
+                                CSR_EEPROM_REG_READ_VALID_MSK,
+                                IL_EEPROM_ACCESS_TIMEOUT);
+               if (ret < 0) {
+                       IL_ERR("Time out reading EEPROM[%d]\n", addr);
+                       goto done;
+               }
+               r = _il_rd(il, CSR_EEPROM_REG);
+               e[addr / 2] = cpu_to_le16(r >> 16);
+       }
+
+       D_EEPROM("NVM Type: %s, version: 0x%x\n", "EEPROM",
+                il_eeprom_query16(il, EEPROM_VERSION));
+
+       ret = 0;
+done:
+       il->cfg->ops->lib->eeprom_ops.release_semaphore(il);
+
+err:
+       if (ret)
+               il_eeprom_free(il);
+       /* Reset chip to save power until we load uCode during "up". */
+       il_apm_stop(il);
+alloc_err:
+       return ret;
+}
+EXPORT_SYMBOL(il_eeprom_init);
+
+void
+il_eeprom_free(struct il_priv *il)
+{
+       kfree(il->eeprom);
+       il->eeprom = NULL;
+}
+EXPORT_SYMBOL(il_eeprom_free);
+
+static void
+il_init_band_reference(const struct il_priv *il, int eep_band,
+                      int *eeprom_ch_count,
+                      const struct il_eeprom_channel **eeprom_ch_info,
+                      const u8 **eeprom_ch_idx)
+{
+       u32 offset =
+           il->cfg->ops->lib->eeprom_ops.regulatory_bands[eep_band - 1];
+       switch (eep_band) {
+       case 1:         /* 2.4GHz band */
+               *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_1);
+               *eeprom_ch_info =
+                   (struct il_eeprom_channel *)il_eeprom_query_addr(il,
+                                                                    offset);
+               *eeprom_ch_idx = il_eeprom_band_1;
+               break;
+       case 2:         /* 4.9GHz band */
+               *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_2);
+               *eeprom_ch_info =
+                   (struct il_eeprom_channel *)il_eeprom_query_addr(il,
+                                                                    offset);
+               *eeprom_ch_idx = il_eeprom_band_2;
+               break;
+       case 3:         /* 5.2GHz band */
+               *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_3);
+               *eeprom_ch_info =
+                   (struct il_eeprom_channel *)il_eeprom_query_addr(il,
+                                                                    offset);
+               *eeprom_ch_idx = il_eeprom_band_3;
+               break;
+       case 4:         /* 5.5GHz band */
+               *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_4);
+               *eeprom_ch_info =
+                   (struct il_eeprom_channel *)il_eeprom_query_addr(il,
+                                                                    offset);
+               *eeprom_ch_idx = il_eeprom_band_4;
+               break;
+       case 5:         /* 5.7GHz band */
+               *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_5);
+               *eeprom_ch_info =
+                   (struct il_eeprom_channel *)il_eeprom_query_addr(il,
+                                                                    offset);
+               *eeprom_ch_idx = il_eeprom_band_5;
+               break;
+       case 6:         /* 2.4GHz ht40 channels */
+               *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_6);
+               *eeprom_ch_info =
+                   (struct il_eeprom_channel *)il_eeprom_query_addr(il,
+                                                                    offset);
+               *eeprom_ch_idx = il_eeprom_band_6;
+               break;
+       case 7:         /* 5 GHz ht40 channels */
+               *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_7);
+               *eeprom_ch_info =
+                   (struct il_eeprom_channel *)il_eeprom_query_addr(il,
+                                                                    offset);
+               *eeprom_ch_idx = il_eeprom_band_7;
+               break;
+       default:
+               BUG();
+       }
+}
+
+#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
+                           ? # x " " : "")
+/**
+ * il_mod_ht40_chan_info - Copy ht40 channel info into driver's il.
+ *
+ * Does not set up a command, or touch hardware.
+ */
+static int
+il_mod_ht40_chan_info(struct il_priv *il, enum ieee80211_band band, u16 channel,
+                     const struct il_eeprom_channel *eeprom_ch,
+                     u8 clear_ht40_extension_channel)
+{
+       struct il_channel_info *ch_info;
+
+       ch_info =
+           (struct il_channel_info *)il_get_channel_info(il, band, channel);
+
+       if (!il_is_channel_valid(ch_info))
+               return -1;
+
+       D_EEPROM("HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
+                " Ad-Hoc %ssupported\n", ch_info->channel,
+                il_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(DFS), eeprom_ch->flags,
+                eeprom_ch->max_power_avg,
+                ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) &&
+                 !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? "" : "not ");
+
+       ch_info->ht40_eeprom = *eeprom_ch;
+       ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
+       ch_info->ht40_flags = eeprom_ch->flags;
+       if (eeprom_ch->flags & EEPROM_CHANNEL_VALID)
+               ch_info->ht40_extension_channel &=
+                   ~clear_ht40_extension_channel;
+
+       return 0;
+}
+
+#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
+                           ? # x " " : "")
+
+/**
+ * il_init_channel_map - Set up driver's info for all possible channels
+ */
+int
+il_init_channel_map(struct il_priv *il)
+{
+       int eeprom_ch_count = 0;
+       const u8 *eeprom_ch_idx = NULL;
+       const struct il_eeprom_channel *eeprom_ch_info = NULL;
+       int band, ch;
+       struct il_channel_info *ch_info;
+
+       if (il->channel_count) {
+               D_EEPROM("Channel map already initialized.\n");
+               return 0;
+       }
+
+       D_EEPROM("Initializing regulatory info from EEPROM\n");
+
+       il->channel_count =
+           ARRAY_SIZE(il_eeprom_band_1) + ARRAY_SIZE(il_eeprom_band_2) +
+           ARRAY_SIZE(il_eeprom_band_3) + ARRAY_SIZE(il_eeprom_band_4) +
+           ARRAY_SIZE(il_eeprom_band_5);
+
+       D_EEPROM("Parsing data for %d channels.\n", il->channel_count);
+
+       il->channel_info =
+           kzalloc(sizeof(struct il_channel_info) * il->channel_count,
+                   GFP_KERNEL);
+       if (!il->channel_info) {
+               IL_ERR("Could not allocate channel_info\n");
+               il->channel_count = 0;
+               return -ENOMEM;
+       }
+
+       ch_info = il->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++) {
+
+               il_init_band_reference(il, band, &eeprom_ch_count,
+                                      &eeprom_ch_info, &eeprom_ch_idx);
+
+               /* Loop through each band adding each of the channels */
+               for (ch = 0; ch < eeprom_ch_count; ch++) {
+                       ch_info->channel = eeprom_ch_idx[ch];
+                       ch_info->band =
+                           (band ==
+                            1) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+
+                       /* 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;
+                       /* First write that ht40 is not enabled, and then enable
+                        * one by one */
+                       ch_info->ht40_extension_channel =
+                           IEEE80211_CHAN_NO_HT40;
+
+                       if (!(il_is_channel_valid(ch_info))) {
+                               D_EEPROM("Ch. %d Flags %x [%sGHz] - "
+                                        "No traffic\n", ch_info->channel,
+                                        ch_info->flags,
+                                        il_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;
+
+                       D_EEPROM("Ch. %d [%sGHz] " "%s%s%s%s%s%s(0x%02x %ddBm):"
+                                " Ad-Hoc %ssupported\n", ch_info->channel,
+                                il_is_channel_a_band(ch_info) ? "5.2" : "2.4",
+                                CHECK_AND_PRINT_I(VALID),
+                                CHECK_AND_PRINT_I(IBSS),
+                                CHECK_AND_PRINT_I(ACTIVE),
+                                CHECK_AND_PRINT_I(RADAR),
+                                CHECK_AND_PRINT_I(WIDE),
+                                CHECK_AND_PRINT_I(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 ");
+
+                       ch_info++;
+               }
+       }
+
+       /* Check if we do have HT40 channels */
+       if (il->cfg->ops->lib->eeprom_ops.regulatory_bands[5] ==
+           EEPROM_REGULATORY_BAND_NO_HT40 &&
+           il->cfg->ops->lib->eeprom_ops.regulatory_bands[6] ==
+           EEPROM_REGULATORY_BAND_NO_HT40)
+               return 0;
+
+       /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
+       for (band = 6; band <= 7; band++) {
+               enum ieee80211_band ieeeband;
+
+               il_init_band_reference(il, band, &eeprom_ch_count,
+                                      &eeprom_ch_info, &eeprom_ch_idx);
+
+               /* EEPROM band 6 is 2.4, band 7 is 5 GHz */
+               ieeeband =
+                   (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+
+               /* Loop through each band adding each of the channels */
+               for (ch = 0; ch < eeprom_ch_count; ch++) {
+                       /* Set up driver's info for lower half */
+                       il_mod_ht40_chan_info(il, ieeeband, eeprom_ch_idx[ch],
+                                             &eeprom_ch_info[ch],
+                                             IEEE80211_CHAN_NO_HT40PLUS);
+
+                       /* Set up driver's info for upper half */
+                       il_mod_ht40_chan_info(il, ieeeband,
+                                             eeprom_ch_idx[ch] + 4,
+                                             &eeprom_ch_info[ch],
+                                             IEEE80211_CHAN_NO_HT40MINUS);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(il_init_channel_map);
+
+/*
+ * il_free_channel_map - undo allocations in il_init_channel_map
+ */
+void
+il_free_channel_map(struct il_priv *il)
+{
+       kfree(il->channel_info);
+       il->channel_count = 0;
+}
+EXPORT_SYMBOL(il_free_channel_map);
+
+/**
+ * il_get_channel_info - Find driver's ilate channel info
+ *
+ * Based on band and channel number.
+ */
+const struct il_channel_info *
+il_get_channel_info(const struct il_priv *il, enum ieee80211_band band,
+                   u16 channel)
+{
+       int i;
+
+       switch (band) {
+       case IEEE80211_BAND_5GHZ:
+               for (i = 14; i < il->channel_count; i++) {
+                       if (il->channel_info[i].channel == channel)
+                               return &il->channel_info[i];
+               }
+               break;
+       case IEEE80211_BAND_2GHZ:
+               if (channel >= 1 && channel <= 14)
+                       return &il->channel_info[channel - 1];
+               break;
+       default:
+               BUG();
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL(il_get_channel_info);
+
+/*
+ * Setting power level allows the card to go to sleep when not busy.
+ *
+ * We calculate a sleep command based on the required latency, which
+ * we get from mac80211. In order to handle thermal throttling, we can
+ * also use pre-defined power levels.
+ */
+
+/*
+ * This defines the old power levels. They are still used by default
+ * (level 1) and for thermal throttle (levels 3 through 5)
+ */
+
+struct il_power_vec_entry {
+       struct il_powertable_cmd cmd;
+       u8 no_dtim;             /* number of skip dtim */
+};
+
+static void
+il_power_sleep_cam_cmd(struct il_priv *il, struct il_powertable_cmd *cmd)
+{
+       memset(cmd, 0, sizeof(*cmd));
+
+       if (il->power_data.pci_pm)
+               cmd->flags |= IL_POWER_PCI_PM_MSK;
+
+       D_POWER("Sleep command for CAM\n");
+}
+
+static int
+il_set_power(struct il_priv *il, struct il_powertable_cmd *cmd)
+{
+       D_POWER("Sending power/sleep command\n");
+       D_POWER("Flags value = 0x%08X\n", cmd->flags);
+       D_POWER("Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
+       D_POWER("Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
+       D_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 il_send_cmd_pdu(il, C_POWER_TBL,
+                              sizeof(struct il_powertable_cmd), cmd);
+}
+
+int
+il_power_set_mode(struct il_priv *il, struct il_powertable_cmd *cmd, bool force)
+{
+       int ret;
+       bool update_chains;
+
+       lockdep_assert_held(&il->mutex);
+
+       /* Don't update the RX chain when chain noise calibration is running */
+       update_chains = il->chain_noise_data.state == IL_CHAIN_NOISE_DONE ||
+           il->chain_noise_data.state == IL_CHAIN_NOISE_ALIVE;
+
+       if (!memcmp(&il->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
+               return 0;
+
+       if (!il_is_ready_rf(il))
+               return -EIO;
+
+       /* scan complete use sleep_power_next, need to be updated */
+       memcpy(&il->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
+       if (test_bit(S_SCANNING, &il->status) && !force) {
+               D_INFO("Defer power set mode while scanning\n");
+               return 0;
+       }
+
+       if (cmd->flags & IL_POWER_DRIVER_ALLOW_SLEEP_MSK)
+               set_bit(S_POWER_PMI, &il->status);
+
+       ret = il_set_power(il, cmd);
+       if (!ret) {
+               if (!(cmd->flags & IL_POWER_DRIVER_ALLOW_SLEEP_MSK))
+                       clear_bit(S_POWER_PMI, &il->status);
+
+               if (il->cfg->ops->lib->update_chain_flags && update_chains)
+                       il->cfg->ops->lib->update_chain_flags(il);
+               else if (il->cfg->ops->lib->update_chain_flags)
+                       D_POWER("Cannot update the power, chain noise "
+                               "calibration running: %d\n",
+                               il->chain_noise_data.state);
+
+               memcpy(&il->power_data.sleep_cmd, cmd, sizeof(*cmd));
+       } else
+               IL_ERR("set power fail, ret = %d", ret);
+
+       return ret;
+}
+
+int
+il_power_update_mode(struct il_priv *il, bool force)
+{
+       struct il_powertable_cmd cmd;
+
+       il_power_sleep_cam_cmd(il, &cmd);
+       return il_power_set_mode(il, &cmd, force);
+}
+EXPORT_SYMBOL(il_power_update_mode);
+
+/* initialize to default */
+void
+il_power_initialize(struct il_priv *il)
+{
+       u16 lctl = il_pcie_link_ctl(il);
+
+       il->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+
+       il->power_data.debug_sleep_level_override = -1;
+
+       memset(&il->power_data.sleep_cmd, 0, sizeof(il->power_data.sleep_cmd));
+}
+EXPORT_SYMBOL(il_power_initialize);
+
+/* 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 IL_ACTIVE_DWELL_TIME_24    (30)        /* all times in msec */
+#define IL_ACTIVE_DWELL_TIME_52    (20)
+
+#define IL_ACTIVE_DWELL_FACTOR_24GHZ (3)
+#define IL_ACTIVE_DWELL_FACTOR_52GHZ (2)
+
+/* 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 IL_PASSIVE_DWELL_TIME_24   (20)        /* all times in msec */
+#define IL_PASSIVE_DWELL_TIME_52   (10)
+#define IL_PASSIVE_DWELL_BASE      (100)
+#define IL_CHANNEL_TUNE_TIME       5
+
+static int
+il_send_scan_abort(struct il_priv *il)
+{
+       int ret;
+       struct il_rx_pkt *pkt;
+       struct il_host_cmd cmd = {
+               .id = C_SCAN_ABORT,
+               .flags = CMD_WANT_SKB,
+       };
+
+       /* Exit instantly with error when device is not ready
+        * to receive scan abort command or it does not perform
+        * hardware scan currently */
+       if (!test_bit(S_READY, &il->status) ||
+           !test_bit(S_GEO_CONFIGURED, &il->status) ||
+           !test_bit(S_SCAN_HW, &il->status) ||
+           test_bit(S_FW_ERROR, &il->status) ||
+           test_bit(S_EXIT_PENDING, &il->status))
+               return -EIO;
+
+       ret = il_send_cmd_sync(il, &cmd);
+       if (ret)
+               return ret;
+
+       pkt = (struct il_rx_pkt *)cmd.reply_page;
+       if (pkt->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. */
+               D_SCAN("SCAN_ABORT ret %d.\n", pkt->u.status);
+               ret = -EIO;
+       }
+
+       il_free_pages(il, cmd.reply_page);
+       return ret;
+}
+
+static void
+il_complete_scan(struct il_priv *il, bool aborted)
+{
+       /* check if scan was requested from mac80211 */
+       if (il->scan_request) {
+               D_SCAN("Complete scan in mac80211\n");
+               ieee80211_scan_completed(il->hw, aborted);
+       }
+
+       il->scan_vif = NULL;
+       il->scan_request = NULL;
+}
+
+void
+il_force_scan_end(struct il_priv *il)
+{
+       lockdep_assert_held(&il->mutex);
+
+       if (!test_bit(S_SCANNING, &il->status)) {
+               D_SCAN("Forcing scan end while not scanning\n");
+               return;
+       }
+
+       D_SCAN("Forcing scan end\n");
+       clear_bit(S_SCANNING, &il->status);
+       clear_bit(S_SCAN_HW, &il->status);
+       clear_bit(S_SCAN_ABORTING, &il->status);
+       il_complete_scan(il, true);
+}
+
+static void
+il_do_scan_abort(struct il_priv *il)
+{
+       int ret;
+
+       lockdep_assert_held(&il->mutex);
+
+       if (!test_bit(S_SCANNING, &il->status)) {
+               D_SCAN("Not performing scan to abort\n");
+               return;
+       }
+
+       if (test_and_set_bit(S_SCAN_ABORTING, &il->status)) {
+               D_SCAN("Scan abort in progress\n");
+               return;
+       }
+
+       ret = il_send_scan_abort(il);
+       if (ret) {
+               D_SCAN("Send scan abort failed %d\n", ret);
+               il_force_scan_end(il);
+       } else
+               D_SCAN("Successfully send scan abort\n");
+}
+
+/**
+ * il_scan_cancel - Cancel any currently executing HW scan
+ */
+int
+il_scan_cancel(struct il_priv *il)
+{
+       D_SCAN("Queuing abort scan\n");
+       queue_work(il->workqueue, &il->abort_scan);
+       return 0;
+}
+EXPORT_SYMBOL(il_scan_cancel);
+
+/**
+ * il_scan_cancel_timeout - Cancel any currently executing HW scan
+ * @ms: amount of time to wait (in milliseconds) for scan to abort
+ *
+ */
+int
+il_scan_cancel_timeout(struct il_priv *il, unsigned long ms)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(ms);
+
+       lockdep_assert_held(&il->mutex);
+
+       D_SCAN("Scan cancel timeout\n");
+
+       il_do_scan_abort(il);
+
+       while (time_before_eq(jiffies, timeout)) {
+               if (!test_bit(S_SCAN_HW, &il->status))
+                       break;
+               msleep(20);
+       }
+
+       return test_bit(S_SCAN_HW, &il->status);
+}
+EXPORT_SYMBOL(il_scan_cancel_timeout);
+
+/* Service response to C_SCAN (0x80) */
+static void
+il_hdl_scan(struct il_priv *il, struct il_rx_buf *rxb)
+{
+#ifdef CONFIG_IWLEGACY_DEBUG
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_scanreq_notification *notif =
+           (struct il_scanreq_notification *)pkt->u.raw;
+
+       D_SCAN("Scan request status = 0x%x\n", notif->status);
+#endif
+}
+
+/* Service N_SCAN_START (0x82) */
+static void
+il_hdl_scan_start(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_scanstart_notification *notif =
+           (struct il_scanstart_notification *)pkt->u.raw;
+       il->scan_start_tsf = le32_to_cpu(notif->tsf_low);
+       D_SCAN("Scan start: " "%d [802.11%s] "
+              "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", notif->channel,
+              notif->band ? "bg" : "a", le32_to_cpu(notif->tsf_high),
+              le32_to_cpu(notif->tsf_low), notif->status, notif->beacon_timer);
+}
+
+/* Service N_SCAN_RESULTS (0x83) */
+static void
+il_hdl_scan_results(struct il_priv *il, struct il_rx_buf *rxb)
+{
+#ifdef CONFIG_IWLEGACY_DEBUG
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_scanresults_notification *notif =
+           (struct il_scanresults_notification *)pkt->u.raw;
+
+       D_SCAN("Scan ch.res: " "%d [802.11%s] " "(TSF: 0x%08X:%08X) - %d "
+              "elapsed=%lu usec\n", notif->channel, notif->band ? "bg" : "a",
+              le32_to_cpu(notif->tsf_high), le32_to_cpu(notif->tsf_low),
+              le32_to_cpu(notif->stats[0]),
+              le32_to_cpu(notif->tsf_low) - il->scan_start_tsf);
+#endif
+}
+
+/* Service N_SCAN_COMPLETE (0x84) */
+static void
+il_hdl_scan_complete(struct il_priv *il, struct il_rx_buf *rxb)
+{
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
+#endif
+
+       D_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(S_SCAN_HW, &il->status);
+
+       D_SCAN("Scan on %sGHz took %dms\n",
+              (il->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
+              jiffies_to_msecs(jiffies - il->scan_start));
+
+       queue_work(il->workqueue, &il->scan_completed);
+}
+
+void
+il_setup_rx_scan_handlers(struct il_priv *il)
+{
+       /* scan handlers */
+       il->handlers[C_SCAN] = il_hdl_scan;
+       il->handlers[N_SCAN_START] = il_hdl_scan_start;
+       il->handlers[N_SCAN_RESULTS] = il_hdl_scan_results;
+       il->handlers[N_SCAN_COMPLETE] = il_hdl_scan_complete;
+}
+EXPORT_SYMBOL(il_setup_rx_scan_handlers);
+
+inline u16
+il_get_active_dwell_time(struct il_priv *il, enum ieee80211_band band,
+                        u8 n_probes)
+{
+       if (band == IEEE80211_BAND_5GHZ)
+               return IL_ACTIVE_DWELL_TIME_52 +
+                   IL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1);
+       else
+               return IL_ACTIVE_DWELL_TIME_24 +
+                   IL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
+}
+EXPORT_SYMBOL(il_get_active_dwell_time);
+
+u16
+il_get_passive_dwell_time(struct il_priv *il, enum ieee80211_band band,
+                         struct ieee80211_vif *vif)
+{
+       struct il_rxon_context *ctx = &il->ctx;
+       u16 value;
+
+       u16 passive =
+           (band ==
+            IEEE80211_BAND_2GHZ) ? IL_PASSIVE_DWELL_BASE +
+           IL_PASSIVE_DWELL_TIME_24 : IL_PASSIVE_DWELL_BASE +
+           IL_PASSIVE_DWELL_TIME_52;
+
+       if (il_is_any_associated(il)) {
+               /*
+                * If we're associated, we clamp the maximum passive
+                * dwell time to be 98% of the smallest beacon interval
+                * (minus 2 * channel tune time)
+                */
+               value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
+               if (value > IL_PASSIVE_DWELL_BASE || !value)
+                       value = IL_PASSIVE_DWELL_BASE;
+               value = (value * 98) / 100 - IL_CHANNEL_TUNE_TIME * 2;
+               passive = min(value, passive);
+       }
+
+       return passive;
+}
+EXPORT_SYMBOL(il_get_passive_dwell_time);
+
+void
+il_init_scan_params(struct il_priv *il)
+{
+       u8 ant_idx = fls(il->hw_params.valid_tx_ant) - 1;
+       if (!il->scan_tx_ant[IEEE80211_BAND_5GHZ])
+               il->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
+       if (!il->scan_tx_ant[IEEE80211_BAND_2GHZ])
+               il->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
+}
+EXPORT_SYMBOL(il_init_scan_params);
+
+static int
+il_scan_initiate(struct il_priv *il, struct ieee80211_vif *vif)
+{
+       int ret;
+
+       lockdep_assert_held(&il->mutex);
+
+       if (WARN_ON(!il->cfg->ops->utils->request_scan))
+               return -EOPNOTSUPP;
+
+       cancel_delayed_work(&il->scan_check);
+
+       if (!il_is_ready_rf(il)) {
+               IL_WARN("Request scan called when driver not ready.\n");
+               return -EIO;
+       }
+
+       if (test_bit(S_SCAN_HW, &il->status)) {
+               D_SCAN("Multiple concurrent scan requests in parallel.\n");
+               return -EBUSY;
+       }
+
+       if (test_bit(S_SCAN_ABORTING, &il->status)) {
+               D_SCAN("Scan request while abort pending.\n");
+               return -EBUSY;
+       }
+
+       D_SCAN("Starting scan...\n");
+
+       set_bit(S_SCANNING, &il->status);
+       il->scan_start = jiffies;
+
+       ret = il->cfg->ops->utils->request_scan(il, vif);
+       if (ret) {
+               clear_bit(S_SCANNING, &il->status);
+               return ret;
+       }
+
+       queue_delayed_work(il->workqueue, &il->scan_check,
+                          IL_SCAN_CHECK_WATCHDOG);
+
+       return 0;
+}
+
+int
+il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+              struct cfg80211_scan_request *req)
+{
+       struct il_priv *il = hw->priv;
+       int ret;
+
+       D_MAC80211("enter\n");
+
+       if (req->n_channels == 0)
+               return -EINVAL;
+
+       mutex_lock(&il->mutex);
+
+       if (test_bit(S_SCANNING, &il->status)) {
+               D_SCAN("Scan already in progress.\n");
+               ret = -EAGAIN;
+               goto out_unlock;
+       }
+
+       /* mac80211 will only ask for one band at a time */
+       il->scan_request = req;
+       il->scan_vif = vif;
+       il->scan_band = req->channels[0]->band;
+
+       ret = il_scan_initiate(il, vif);
+
+       D_MAC80211("leave\n");
+
+out_unlock:
+       mutex_unlock(&il->mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL(il_mac_hw_scan);
+
+static void
+il_bg_scan_check(struct work_struct *data)
+{
+       struct il_priv *il =
+           container_of(data, struct il_priv, scan_check.work);
+
+       D_SCAN("Scan check work\n");
+
+       /* Since we are here firmware does not finish scan and
+        * most likely is in bad shape, so we don't bother to
+        * send abort command, just force scan complete to mac80211 */
+       mutex_lock(&il->mutex);
+       il_force_scan_end(il);
+       mutex_unlock(&il->mutex);
+}
+
+/**
+ * il_fill_probe_req - fill in all required fields and IE for probe request
+ */
+
+u16
+il_fill_probe_req(struct il_priv *il, struct ieee80211_mgmt *frame,
+                 const u8 *ta, const u8 *ies, int ie_len, int left)
+{
+       int len = 0;
+       u8 *pos = NULL;
+
+       /* Make sure there is enough space for the probe request,
+        * two mandatory IEs and the data */
+       left -= 24;
+       if (left < 0)
+               return 0;
+
+       frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
+       memcpy(frame->da, il_bcast_addr, ETH_ALEN);
+       memcpy(frame->sa, ta, ETH_ALEN);
+       memcpy(frame->bssid, il_bcast_addr, ETH_ALEN);
+       frame->seq_ctrl = 0;
+
+       len += 24;
+
+       /* ...next IE... */
+       pos = &frame->u.probe_req.variable[0];
+
+       /* fill in our indirect SSID IE */
+       left -= 2;
+       if (left < 0)
+               return 0;
+       *pos++ = WLAN_EID_SSID;
+       *pos++ = 0;
+
+       len += 2;
+
+       if (WARN_ON(left < ie_len))
+               return len;
+
+       if (ies && ie_len) {
+               memcpy(pos, ies, ie_len);
+               len += ie_len;
+       }
+
+       return (u16) len;
+}
+EXPORT_SYMBOL(il_fill_probe_req);
+
+static void
+il_bg_abort_scan(struct work_struct *work)
+{
+       struct il_priv *il = container_of(work, struct il_priv, abort_scan);
+
+       D_SCAN("Abort scan work\n");
+
+       /* We keep scan_check work queued in case when firmware will not
+        * report back scan completed notification */
+       mutex_lock(&il->mutex);
+       il_scan_cancel_timeout(il, 200);
+       mutex_unlock(&il->mutex);
+}
+
+static void
+il_bg_scan_completed(struct work_struct *work)
+{
+       struct il_priv *il = container_of(work, struct il_priv, scan_completed);
+       bool aborted;
+
+       D_SCAN("Completed scan.\n");
+
+       cancel_delayed_work(&il->scan_check);
+
+       mutex_lock(&il->mutex);
+
+       aborted = test_and_clear_bit(S_SCAN_ABORTING, &il->status);
+       if (aborted)
+               D_SCAN("Aborted scan completed.\n");
+
+       if (!test_and_clear_bit(S_SCANNING, &il->status)) {
+               D_SCAN("Scan already completed.\n");
+               goto out_settings;
+       }
+
+       il_complete_scan(il, aborted);
+
+out_settings:
+       /* Can we still talk to firmware ? */
+       if (!il_is_ready_rf(il))
+               goto out;
+
+       /*
+        * We do not commit power settings while scan is pending,
+        * do it now if the settings changed.
+        */
+       il_power_set_mode(il, &il->power_data.sleep_cmd_next, false);
+       il_set_tx_power(il, il->tx_power_next, false);
+
+       il->cfg->ops->utils->post_scan(il);
+
+out:
+       mutex_unlock(&il->mutex);
+}
+
+void
+il_setup_scan_deferred_work(struct il_priv *il)
+{
+       INIT_WORK(&il->scan_completed, il_bg_scan_completed);
+       INIT_WORK(&il->abort_scan, il_bg_abort_scan);
+       INIT_DELAYED_WORK(&il->scan_check, il_bg_scan_check);
+}
+EXPORT_SYMBOL(il_setup_scan_deferred_work);
+
+void
+il_cancel_scan_deferred_work(struct il_priv *il)
+{
+       cancel_work_sync(&il->abort_scan);
+       cancel_work_sync(&il->scan_completed);
+
+       if (cancel_delayed_work_sync(&il->scan_check)) {
+               mutex_lock(&il->mutex);
+               il_force_scan_end(il);
+               mutex_unlock(&il->mutex);
+       }
+}
+EXPORT_SYMBOL(il_cancel_scan_deferred_work);
+
+/* il->sta_lock must be held */
+static void
+il_sta_ucode_activate(struct il_priv *il, u8 sta_id)
+{
+
+       if (!(il->stations[sta_id].used & IL_STA_DRIVER_ACTIVE))
+               IL_ERR("ACTIVATE a non DRIVER active station id %u addr %pM\n",
+                      sta_id, il->stations[sta_id].sta.sta.addr);
+
+       if (il->stations[sta_id].used & IL_STA_UCODE_ACTIVE) {
+               D_ASSOC("STA id %u addr %pM already present"
+                       " in uCode (according to driver)\n", sta_id,
+                       il->stations[sta_id].sta.sta.addr);
+       } else {
+               il->stations[sta_id].used |= IL_STA_UCODE_ACTIVE;
+               D_ASSOC("Added STA id %u addr %pM to uCode\n", sta_id,
+                       il->stations[sta_id].sta.sta.addr);
+       }
+}
+
+static int
+il_process_add_sta_resp(struct il_priv *il, struct il_addsta_cmd *addsta,
+                       struct il_rx_pkt *pkt, bool sync)
+{
+       u8 sta_id = addsta->sta.sta_id;
+       unsigned long flags;
+       int ret = -EIO;
+
+       if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
+               IL_ERR("Bad return from C_ADD_STA (0x%08X)\n", pkt->hdr.flags);
+               return ret;
+       }
+
+       D_INFO("Processing response for adding station %u\n", sta_id);
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+
+       switch (pkt->u.add_sta.status) {
+       case ADD_STA_SUCCESS_MSK:
+               D_INFO("C_ADD_STA PASSED\n");
+               il_sta_ucode_activate(il, sta_id);
+               ret = 0;
+               break;
+       case ADD_STA_NO_ROOM_IN_TBL:
+               IL_ERR("Adding station %d failed, no room in table.\n", sta_id);
+               break;
+       case ADD_STA_NO_BLOCK_ACK_RESOURCE:
+               IL_ERR("Adding station %d failed, no block ack resource.\n",
+                      sta_id);
+               break;
+       case ADD_STA_MODIFY_NON_EXIST_STA:
+               IL_ERR("Attempting to modify non-existing station %d\n",
+                      sta_id);
+               break;
+       default:
+               D_ASSOC("Received C_ADD_STA:(0x%08X)\n", pkt->u.add_sta.status);
+               break;
+       }
+
+       D_INFO("%s station id %u addr %pM\n",
+              il->stations[sta_id].sta.mode ==
+              STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", sta_id,
+              il->stations[sta_id].sta.sta.addr);
+
+       /*
+        * XXX: The MAC address in the command buffer is often changed from
+        * the original sent to the device. That is, the MAC address
+        * written to the command buffer often is not the same MAC address
+        * read from the command buffer when the command returns. This
+        * issue has not yet been resolved and this debugging is left to
+        * observe the problem.
+        */
+       D_INFO("%s station according to cmd buffer %pM\n",
+              il->stations[sta_id].sta.mode ==
+              STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", addsta->sta.addr);
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return ret;
+}
+
+static void
+il_add_sta_callback(struct il_priv *il, struct il_device_cmd *cmd,
+                   struct il_rx_pkt *pkt)
+{
+       struct il_addsta_cmd *addsta = (struct il_addsta_cmd *)cmd->cmd.payload;
+
+       il_process_add_sta_resp(il, addsta, pkt, false);
+
+}
+
+int
+il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags)
+{
+       struct il_rx_pkt *pkt = NULL;
+       int ret = 0;
+       u8 data[sizeof(*sta)];
+       struct il_host_cmd cmd = {
+               .id = C_ADD_STA,
+               .flags = flags,
+               .data = data,
+       };
+       u8 sta_id __maybe_unused = sta->sta.sta_id;
+
+       D_INFO("Adding sta %u (%pM) %ssynchronously\n", sta_id, sta->sta.addr,
+              flags & CMD_ASYNC ? "a" : "");
+
+       if (flags & CMD_ASYNC)
+               cmd.callback = il_add_sta_callback;
+       else {
+               cmd.flags |= CMD_WANT_SKB;
+               might_sleep();
+       }
+
+       cmd.len = il->cfg->ops->utils->build_addsta_hcmd(sta, data);
+       ret = il_send_cmd(il, &cmd);
+
+       if (ret || (flags & CMD_ASYNC))
+               return ret;
+
+       if (ret == 0) {
+               pkt = (struct il_rx_pkt *)cmd.reply_page;
+               ret = il_process_add_sta_resp(il, sta, pkt, true);
+       }
+       il_free_pages(il, cmd.reply_page);
+
+       return ret;
+}
+EXPORT_SYMBOL(il_send_add_sta);
+
+static void
+il_set_ht_add_station(struct il_priv *il, u8 idx, struct ieee80211_sta *sta,
+                     struct il_rxon_context *ctx)
+{
+       struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
+       __le32 sta_flags;
+       u8 mimo_ps_mode;
+
+       if (!sta || !sta_ht_inf->ht_supported)
+               goto done;
+
+       mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
+       D_ASSOC("spatial multiplexing power save mode: %s\n",
+               (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ? "static" :
+               (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? "dynamic" :
+               "disabled");
+
+       sta_flags = il->stations[idx].sta.station_flags;
+
+       sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
+
+       switch (mimo_ps_mode) {
+       case WLAN_HT_CAP_SM_PS_STATIC:
+               sta_flags |= STA_FLG_MIMO_DIS_MSK;
+               break;
+       case WLAN_HT_CAP_SM_PS_DYNAMIC:
+               sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
+               break;
+       case WLAN_HT_CAP_SM_PS_DISABLED:
+               break;
+       default:
+               IL_WARN("Invalid MIMO PS mode %d\n", mimo_ps_mode);
+               break;
+       }
+
+       sta_flags |=
+           cpu_to_le32((u32) sta_ht_inf->
+                       ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
+
+       sta_flags |=
+           cpu_to_le32((u32) sta_ht_inf->
+                       ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
+
+       if (il_is_ht40_tx_allowed(il, ctx, &sta->ht_cap))
+               sta_flags |= STA_FLG_HT40_EN_MSK;
+       else
+               sta_flags &= ~STA_FLG_HT40_EN_MSK;
+
+       il->stations[idx].sta.station_flags = sta_flags;
+done:
+       return;
+}
+
+/**
+ * il_prep_station - Prepare station information for addition
+ *
+ * should be called with sta_lock held
+ */
+u8
+il_prep_station(struct il_priv *il, struct il_rxon_context *ctx,
+               const u8 *addr, bool is_ap, struct ieee80211_sta *sta)
+{
+       struct il_station_entry *station;
+       int i;
+       u8 sta_id = IL_INVALID_STATION;
+       u16 rate;
+
+       if (is_ap)
+               sta_id = ctx->ap_sta_id;
+       else if (is_broadcast_ether_addr(addr))
+               sta_id = ctx->bcast_sta_id;
+       else
+               for (i = IL_STA_ID; i < il->hw_params.max_stations; i++) {
+                       if (!compare_ether_addr
+                           (il->stations[i].sta.sta.addr, addr)) {
+                               sta_id = i;
+                               break;
+                       }
+
+                       if (!il->stations[i].used &&
+                           sta_id == IL_INVALID_STATION)
+                               sta_id = i;
+               }
+
+       /*
+        * These two conditions have the same outcome, but keep them
+        * separate
+        */
+       if (unlikely(sta_id == IL_INVALID_STATION))
+               return sta_id;
+
+       /*
+        * uCode is not able to deal with multiple requests to add a
+        * station. Keep track if one is in progress so that we do not send
+        * another.
+        */
+       if (il->stations[sta_id].used & IL_STA_UCODE_INPROGRESS) {
+               D_INFO("STA %d already in process of being added.\n", sta_id);
+               return sta_id;
+       }
+
+       if ((il->stations[sta_id].used & IL_STA_DRIVER_ACTIVE) &&
+           (il->stations[sta_id].used & IL_STA_UCODE_ACTIVE) &&
+           !compare_ether_addr(il->stations[sta_id].sta.sta.addr, addr)) {
+               D_ASSOC("STA %d (%pM) already added, not adding again.\n",
+                       sta_id, addr);
+               return sta_id;
+       }
+
+       station = &il->stations[sta_id];
+       station->used = IL_STA_DRIVER_ACTIVE;
+       D_ASSOC("Add STA to driver ID %d: %pM\n", sta_id, addr);
+       il->num_stations++;
+
+       /* Set up the C_ADD_STA command to send to device */
+       memset(&station->sta, 0, sizeof(struct il_addsta_cmd));
+       memcpy(station->sta.sta.addr, addr, ETH_ALEN);
+       station->sta.mode = 0;
+       station->sta.sta.sta_id = sta_id;
+       station->sta.station_flags = ctx->station_flags;
+       station->ctxid = ctx->ctxid;
+
+       if (sta) {
+               struct il_station_priv_common *sta_priv;
+
+               sta_priv = (void *)sta->drv_priv;
+               sta_priv->ctx = ctx;
+       }
+
+       /*
+        * OK to call unconditionally, since local stations (IBSS BSSID
+        * STA and broadcast STA) pass in a NULL sta, and mac80211
+        * doesn't allow HT IBSS.
+        */
+       il_set_ht_add_station(il, sta_id, sta, ctx);
+
+       /* 3945 only */
+       rate = (il->band == IEEE80211_BAND_5GHZ) ? RATE_6M_PLCP : RATE_1M_PLCP;
+       /* Turn on both antennas for the station... */
+       station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK);
+
+       return sta_id;
+
+}
+EXPORT_SYMBOL_GPL(il_prep_station);
+
+#define STA_WAIT_TIMEOUT (HZ/2)
+
+/**
+ * il_add_station_common -
+ */
+int
+il_add_station_common(struct il_priv *il, struct il_rxon_context *ctx,
+                     const u8 *addr, bool is_ap, struct ieee80211_sta *sta,
+                     u8 *sta_id_r)
+{
+       unsigned long flags_spin;
+       int ret = 0;
+       u8 sta_id;
+       struct il_addsta_cmd sta_cmd;
+
+       *sta_id_r = 0;
+       spin_lock_irqsave(&il->sta_lock, flags_spin);
+       sta_id = il_prep_station(il, ctx, addr, is_ap, sta);
+       if (sta_id == IL_INVALID_STATION) {
+               IL_ERR("Unable to prepare station %pM for addition\n", addr);
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+               return -EINVAL;
+       }
+
+       /*
+        * uCode is not able to deal with multiple requests to add a
+        * station. Keep track if one is in progress so that we do not send
+        * another.
+        */
+       if (il->stations[sta_id].used & IL_STA_UCODE_INPROGRESS) {
+               D_INFO("STA %d already in process of being added.\n", sta_id);
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+               return -EEXIST;
+       }
+
+       if ((il->stations[sta_id].used & IL_STA_DRIVER_ACTIVE) &&
+           (il->stations[sta_id].used & IL_STA_UCODE_ACTIVE)) {
+               D_ASSOC("STA %d (%pM) already added, not adding again.\n",
+                       sta_id, addr);
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+               return -EEXIST;
+       }
+
+       il->stations[sta_id].used |= IL_STA_UCODE_INPROGRESS;
+       memcpy(&sta_cmd, &il->stations[sta_id].sta,
+              sizeof(struct il_addsta_cmd));
+       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+
+       /* Add station to device's station table */
+       ret = il_send_add_sta(il, &sta_cmd, CMD_SYNC);
+       if (ret) {
+               spin_lock_irqsave(&il->sta_lock, flags_spin);
+               IL_ERR("Adding station %pM failed.\n",
+                      il->stations[sta_id].sta.sta.addr);
+               il->stations[sta_id].used &= ~IL_STA_DRIVER_ACTIVE;
+               il->stations[sta_id].used &= ~IL_STA_UCODE_INPROGRESS;
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+       }
+       *sta_id_r = sta_id;
+       return ret;
+}
+EXPORT_SYMBOL(il_add_station_common);
+
+/**
+ * il_sta_ucode_deactivate - deactivate ucode status for a station
+ *
+ * il->sta_lock must be held
+ */
+static void
+il_sta_ucode_deactivate(struct il_priv *il, u8 sta_id)
+{
+       /* Ucode must be active and driver must be non active */
+       if ((il->stations[sta_id].
+            used & (IL_STA_UCODE_ACTIVE | IL_STA_DRIVER_ACTIVE)) !=
+           IL_STA_UCODE_ACTIVE)
+               IL_ERR("removed non active STA %u\n", sta_id);
+
+       il->stations[sta_id].used &= ~IL_STA_UCODE_ACTIVE;
+
+       memset(&il->stations[sta_id], 0, sizeof(struct il_station_entry));
+       D_ASSOC("Removed STA %u\n", sta_id);
+}
+
+static int
+il_send_remove_station(struct il_priv *il, const u8 * addr, int sta_id,
+                      bool temporary)
+{
+       struct il_rx_pkt *pkt;
+       int ret;
+
+       unsigned long flags_spin;
+       struct il_rem_sta_cmd rm_sta_cmd;
+
+       struct il_host_cmd cmd = {
+               .id = C_REM_STA,
+               .len = sizeof(struct il_rem_sta_cmd),
+               .flags = CMD_SYNC,
+               .data = &rm_sta_cmd,
+       };
+
+       memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
+       rm_sta_cmd.num_sta = 1;
+       memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN);
+
+       cmd.flags |= CMD_WANT_SKB;
+
+       ret = il_send_cmd(il, &cmd);
+
+       if (ret)
+               return ret;
+
+       pkt = (struct il_rx_pkt *)cmd.reply_page;
+       if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
+               IL_ERR("Bad return from C_REM_STA (0x%08X)\n", pkt->hdr.flags);
+               ret = -EIO;
+       }
+
+       if (!ret) {
+               switch (pkt->u.rem_sta.status) {
+               case REM_STA_SUCCESS_MSK:
+                       if (!temporary) {
+                               spin_lock_irqsave(&il->sta_lock, flags_spin);
+                               il_sta_ucode_deactivate(il, sta_id);
+                               spin_unlock_irqrestore(&il->sta_lock,
+                                                      flags_spin);
+                       }
+                       D_ASSOC("C_REM_STA PASSED\n");
+                       break;
+               default:
+                       ret = -EIO;
+                       IL_ERR("C_REM_STA failed\n");
+                       break;
+               }
+       }
+       il_free_pages(il, cmd.reply_page);
+
+       return ret;
+}
+
+/**
+ * il_remove_station - Remove driver's knowledge of station.
+ */
+int
+il_remove_station(struct il_priv *il, const u8 sta_id, const u8 * addr)
+{
+       unsigned long flags;
+
+       if (!il_is_ready(il)) {
+               D_INFO("Unable to remove station %pM, device not ready.\n",
+                      addr);
+               /*
+                * It is typical for stations to be removed when we are
+                * going down. Return success since device will be down
+                * soon anyway
+                */
+               return 0;
+       }
+
+       D_ASSOC("Removing STA from driver:%d  %pM\n", sta_id, addr);
+
+       if (WARN_ON(sta_id == IL_INVALID_STATION))
+               return -EINVAL;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+
+       if (!(il->stations[sta_id].used & IL_STA_DRIVER_ACTIVE)) {
+               D_INFO("Removing %pM but non DRIVER active\n", addr);
+               goto out_err;
+       }
+
+       if (!(il->stations[sta_id].used & IL_STA_UCODE_ACTIVE)) {
+               D_INFO("Removing %pM but non UCODE active\n", addr);
+               goto out_err;
+       }
+
+       if (il->stations[sta_id].used & IL_STA_LOCAL) {
+               kfree(il->stations[sta_id].lq);
+               il->stations[sta_id].lq = NULL;
+       }
+
+       il->stations[sta_id].used &= ~IL_STA_DRIVER_ACTIVE;
+
+       il->num_stations--;
+
+       BUG_ON(il->num_stations < 0);
+
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+
+       return il_send_remove_station(il, addr, sta_id, false);
+out_err:
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(il_remove_station);
+
+/**
+ * il_clear_ucode_stations - clear ucode station table bits
+ *
+ * This function clears all the bits in the driver indicating
+ * which stations are active in the ucode. Call when something
+ * other than explicit station management would cause this in
+ * the ucode, e.g. unassociated RXON.
+ */
+void
+il_clear_ucode_stations(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       int i;
+       unsigned long flags_spin;
+       bool cleared = false;
+
+       D_INFO("Clearing ucode stations in driver\n");
+
+       spin_lock_irqsave(&il->sta_lock, flags_spin);
+       for (i = 0; i < il->hw_params.max_stations; i++) {
+               if (ctx && ctx->ctxid != il->stations[i].ctxid)
+                       continue;
+
+               if (il->stations[i].used & IL_STA_UCODE_ACTIVE) {
+                       D_INFO("Clearing ucode active for station %d\n", i);
+                       il->stations[i].used &= ~IL_STA_UCODE_ACTIVE;
+                       cleared = true;
+               }
+       }
+       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+
+       if (!cleared)
+               D_INFO("No active stations found to be cleared\n");
+}
+EXPORT_SYMBOL(il_clear_ucode_stations);
+
+/**
+ * il_restore_stations() - Restore driver known stations to device
+ *
+ * All stations considered active by driver, but not present in ucode, is
+ * restored.
+ *
+ * Function sleeps.
+ */
+void
+il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       struct il_addsta_cmd sta_cmd;
+       struct il_link_quality_cmd lq;
+       unsigned long flags_spin;
+       int i;
+       bool found = false;
+       int ret;
+       bool send_lq;
+
+       if (!il_is_ready(il)) {
+               D_INFO("Not ready yet, not restoring any stations.\n");
+               return;
+       }
+
+       D_ASSOC("Restoring all known stations ... start.\n");
+       spin_lock_irqsave(&il->sta_lock, flags_spin);
+       for (i = 0; i < il->hw_params.max_stations; i++) {
+               if (ctx->ctxid != il->stations[i].ctxid)
+                       continue;
+               if ((il->stations[i].used & IL_STA_DRIVER_ACTIVE) &&
+                   !(il->stations[i].used & IL_STA_UCODE_ACTIVE)) {
+                       D_ASSOC("Restoring sta %pM\n",
+                               il->stations[i].sta.sta.addr);
+                       il->stations[i].sta.mode = 0;
+                       il->stations[i].used |= IL_STA_UCODE_INPROGRESS;
+                       found = true;
+               }
+       }
+
+       for (i = 0; i < il->hw_params.max_stations; i++) {
+               if ((il->stations[i].used & IL_STA_UCODE_INPROGRESS)) {
+                       memcpy(&sta_cmd, &il->stations[i].sta,
+                              sizeof(struct il_addsta_cmd));
+                       send_lq = false;
+                       if (il->stations[i].lq) {
+                               memcpy(&lq, il->stations[i].lq,
+                                      sizeof(struct il_link_quality_cmd));
+                               send_lq = true;
+                       }
+                       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+                       ret = il_send_add_sta(il, &sta_cmd, CMD_SYNC);
+                       if (ret) {
+                               spin_lock_irqsave(&il->sta_lock, flags_spin);
+                               IL_ERR("Adding station %pM failed.\n",
+                                      il->stations[i].sta.sta.addr);
+                               il->stations[i].used &= ~IL_STA_DRIVER_ACTIVE;
+                               il->stations[i].used &=
+                                   ~IL_STA_UCODE_INPROGRESS;
+                               spin_unlock_irqrestore(&il->sta_lock,
+                                                      flags_spin);
+                       }
+                       /*
+                        * Rate scaling has already been initialized, send
+                        * current LQ command
+                        */
+                       if (send_lq)
+                               il_send_lq_cmd(il, ctx, &lq, CMD_SYNC, true);
+                       spin_lock_irqsave(&il->sta_lock, flags_spin);
+                       il->stations[i].used &= ~IL_STA_UCODE_INPROGRESS;
+               }
+       }
+
+       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+       if (!found)
+               D_INFO("Restoring all known stations"
+                      " .... no stations to be restored.\n");
+       else
+               D_INFO("Restoring all known stations" " .... complete.\n");
+}
+EXPORT_SYMBOL(il_restore_stations);
+
+int
+il_get_free_ucode_key_idx(struct il_priv *il)
+{
+       int i;
+
+       for (i = 0; i < il->sta_key_max_num; i++)
+               if (!test_and_set_bit(i, &il->ucode_key_table))
+                       return i;
+
+       return WEP_INVALID_OFFSET;
+}
+EXPORT_SYMBOL(il_get_free_ucode_key_idx);
+
+void
+il_dealloc_bcast_stations(struct il_priv *il)
+{
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       for (i = 0; i < il->hw_params.max_stations; i++) {
+               if (!(il->stations[i].used & IL_STA_BCAST))
+                       continue;
+
+               il->stations[i].used &= ~IL_STA_UCODE_ACTIVE;
+               il->num_stations--;
+               BUG_ON(il->num_stations < 0);
+               kfree(il->stations[i].lq);
+               il->stations[i].lq = NULL;
+       }
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+}
+EXPORT_SYMBOL_GPL(il_dealloc_bcast_stations);
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+static void
+il_dump_lq_cmd(struct il_priv *il, struct il_link_quality_cmd *lq)
+{
+       int i;
+       D_RATE("lq station id 0x%x\n", lq->sta_id);
+       D_RATE("lq ant 0x%X 0x%X\n", lq->general_params.single_stream_ant_msk,
+              lq->general_params.dual_stream_ant_msk);
+
+       for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+               D_RATE("lq idx %d 0x%X\n", i, lq->rs_table[i].rate_n_flags);
+}
+#else
+static inline void
+il_dump_lq_cmd(struct il_priv *il, struct il_link_quality_cmd *lq)
+{
+}
+#endif
+
+/**
+ * il_is_lq_table_valid() - Test one aspect of LQ cmd for validity
+ *
+ * It sometimes happens when a HT rate has been in use and we
+ * loose connectivity with AP then mac80211 will first tell us that the
+ * current channel is not HT anymore before removing the station. In such a
+ * scenario the RXON flags will be updated to indicate we are not
+ * communicating HT anymore, but the LQ command may still contain HT rates.
+ * Test for this to prevent driver from sending LQ command between the time
+ * RXON flags are updated and when LQ command is updated.
+ */
+static bool
+il_is_lq_table_valid(struct il_priv *il, struct il_rxon_context *ctx,
+                    struct il_link_quality_cmd *lq)
+{
+       int i;
+
+       if (ctx->ht.enabled)
+               return true;
+
+       D_INFO("Channel %u is not an HT channel\n", ctx->active.channel);
+       for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+               if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) {
+                       D_INFO("idx %d of LQ expects HT channel\n", i);
+                       return false;
+               }
+       }
+       return true;
+}
+
+/**
+ * il_send_lq_cmd() - Send link quality command
+ * @init: This command is sent as part of station initialization right
+ *        after station has been added.
+ *
+ * The link quality command is sent as the last step of station creation.
+ * This is the special case in which init is set and we call a callback in
+ * this case to clear the state indicating that station creation is in
+ * progress.
+ */
+int
+il_send_lq_cmd(struct il_priv *il, struct il_rxon_context *ctx,
+              struct il_link_quality_cmd *lq, u8 flags, bool init)
+{
+       int ret = 0;
+       unsigned long flags_spin;
+
+       struct il_host_cmd cmd = {
+               .id = C_TX_LINK_QUALITY_CMD,
+               .len = sizeof(struct il_link_quality_cmd),
+               .flags = flags,
+               .data = lq,
+       };
+
+       if (WARN_ON(lq->sta_id == IL_INVALID_STATION))
+               return -EINVAL;
+
+       spin_lock_irqsave(&il->sta_lock, flags_spin);
+       if (!(il->stations[lq->sta_id].used & IL_STA_DRIVER_ACTIVE)) {
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+               return -EINVAL;
+       }
+       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+
+       il_dump_lq_cmd(il, lq);
+       BUG_ON(init && (cmd.flags & CMD_ASYNC));
+
+       if (il_is_lq_table_valid(il, ctx, lq))
+               ret = il_send_cmd(il, &cmd);
+       else
+               ret = -EINVAL;
+
+       if (cmd.flags & CMD_ASYNC)
+               return ret;
+
+       if (init) {
+               D_INFO("init LQ command complete,"
+                      " clearing sta addition status for sta %d\n",
+                      lq->sta_id);
+               spin_lock_irqsave(&il->sta_lock, flags_spin);
+               il->stations[lq->sta_id].used &= ~IL_STA_UCODE_INPROGRESS;
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+       }
+       return ret;
+}
+EXPORT_SYMBOL(il_send_lq_cmd);
+
+int
+il_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                 struct ieee80211_sta *sta)
+{
+       struct il_priv *il = hw->priv;
+       struct il_station_priv_common *sta_common = (void *)sta->drv_priv;
+       int ret;
+
+       D_INFO("received request to remove station %pM\n", sta->addr);
+       mutex_lock(&il->mutex);
+       D_INFO("proceeding to remove station %pM\n", sta->addr);
+       ret = il_remove_station(il, sta_common->sta_id, sta->addr);
+       if (ret)
+               IL_ERR("Error removing station %pM\n", sta->addr);
+       mutex_unlock(&il->mutex);
+       return ret;
+}
+EXPORT_SYMBOL(il_mac_sta_remove);
+
+/************************** RX-FUNCTIONS ****************************/
+/*
+ * Rx theory of operation
+ *
+ * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
+ * each of which point to Receive Buffers to be filled by the NIC.  These get
+ * used not only for Rx frames, but for any command response or notification
+ * from the NIC.  The driver and NIC manage the Rx buffers by means
+ * of idxes into the circular buffer.
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two idx registers for managing the Rx buffers.
+ *
+ * The READ idx 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 idx is managed by the firmware once the card is enabled.
+ *
+ * The WRITE idx 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
+ * IDX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer, it will advance the READ idx
+ * and fire the RX interrupt.  The driver can then query the READ idx and
+ * process as many packets as possible, moving the WRITE idx 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 iwl->rxq->rx_free.  When
+ *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ *   to replenish the iwl->rxq->rx_free.
+ * + In il_rx_replenish (scheduled) if 'processed' != 'read' then the
+ *   iwl->rxq is replenished and the READ IDX is updated (updating the
+ *   'processed' and 'read' driver idxes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ *   detached from the iwl->rxq.  The driver 'processed' idx is updated.
+ * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
+ *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
+ *   IDX is not incremented and iwl->status(RX_STALLED) is set.  If there
+ *   were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * il_rx_queue_alloc()   Allocates rx_free
+ * il_rx_replenish()     Replenishes rx_free list from rx_used, and calls
+ *                            il_rx_queue_restock
+ * il_rx_queue_restock() Moves available buffers from rx_free into Rx
+ *                            queue, updates firmware pointers, and updates
+ *                            the WRITE idx.  If insufficient rx_free buffers
+ *                            are available, schedules il_rx_replenish
+ *
+ * -- enable interrupts --
+ * ISR - il_rx()         Detach il_rx_bufs from pool up to the
+ *                            READ IDX, detaching the SKB from the pool.
+ *                            Moves the packet buffer from queue to rx_used.
+ *                            Calls il_rx_queue_restock to refill any empty
+ *                            slots.
+ * ...
+ *
+ */
+
+/**
+ * il_rx_queue_space - Return number of free slots available in queue.
+ */
+int
+il_rx_queue_space(const struct il_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;
+}
+EXPORT_SYMBOL(il_rx_queue_space);
+
+/**
+ * il_rx_queue_update_write_ptr - Update the write pointer for the RX queue
+ */
+void
+il_rx_queue_update_write_ptr(struct il_priv *il, struct il_rx_queue *q)
+{
+       unsigned long flags;
+       u32 rx_wrt_ptr_reg = il->hw_params.rx_wrt_ptr_reg;
+       u32 reg;
+
+       spin_lock_irqsave(&q->lock, flags);
+
+       if (q->need_update == 0)
+               goto exit_unlock;
+
+       /* If power-saving is in use, make sure device is awake */
+       if (test_bit(S_POWER_PMI, &il->status)) {
+               reg = _il_rd(il, CSR_UCODE_DRV_GP1);
+
+               if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+                       D_INFO("Rx queue requesting wakeup," " GP1 = 0x%x\n",
+                              reg);
+                       il_set_bit(il, CSR_GP_CNTRL,
+                                  CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+                       goto exit_unlock;
+               }
+
+               q->write_actual = (q->write & ~0x7);
+               il_wr(il, rx_wrt_ptr_reg, q->write_actual);
+
+               /* Else device is assumed to be awake */
+       } else {
+               /* Device expects a multiple of 8 */
+               q->write_actual = (q->write & ~0x7);
+               il_wr(il, rx_wrt_ptr_reg, q->write_actual);
+       }
+
+       q->need_update = 0;
+
+exit_unlock:
+       spin_unlock_irqrestore(&q->lock, flags);
+}
+EXPORT_SYMBOL(il_rx_queue_update_write_ptr);
+
+int
+il_rx_queue_alloc(struct il_priv *il)
+{
+       struct il_rx_queue *rxq = &il->rxq;
+       struct device *dev = &il->pci_dev->dev;
+       int i;
+
+       spin_lock_init(&rxq->lock);
+       INIT_LIST_HEAD(&rxq->rx_free);
+       INIT_LIST_HEAD(&rxq->rx_used);
+
+       /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
+       rxq->bd =
+           dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma,
+                              GFP_KERNEL);
+       if (!rxq->bd)
+               goto err_bd;
+
+       rxq->rb_stts =
+           dma_alloc_coherent(dev, sizeof(struct il_rb_status),
+                              &rxq->rb_stts_dma, GFP_KERNEL);
+       if (!rxq->rb_stts)
+               goto err_rb;
+
+       /* 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->write_actual = 0;
+       rxq->free_count = 0;
+       rxq->need_update = 0;
+       return 0;
+
+err_rb:
+       dma_free_coherent(&il->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+                         rxq->bd_dma);
+err_bd:
+       return -ENOMEM;
+}
+EXPORT_SYMBOL(il_rx_queue_alloc);
+
+void
+il_hdl_spectrum_measurement(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_spectrum_notification *report = &(pkt->u.spectrum_notif);
+
+       if (!report->state) {
+               D_11H("Spectrum Measure Notification: Start\n");
+               return;
+       }
+
+       memcpy(&il->measure_report, report, sizeof(*report));
+       il->measurement_status |= MEASUREMENT_READY;
+}
+EXPORT_SYMBOL(il_hdl_spectrum_measurement);
+
+/*
+ * returns non-zero if packet should be dropped
+ */
+int
+il_set_decrypted_flag(struct il_priv *il, struct ieee80211_hdr *hdr,
+                     u32 decrypt_res, struct ieee80211_rx_status *stats)
+{
+       u16 fc = le16_to_cpu(hdr->frame_control);
+
+       /*
+        * All contexts have the same setting here due to it being
+        * a module parameter, so OK to check any context.
+        */
+       if (il->ctx.active.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
+               return 0;
+
+       if (!(fc & IEEE80211_FCTL_PROTECTED))
+               return 0;
+
+       D_RX("decrypt_res:0x%x\n", decrypt_res);
+       switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
+       case RX_RES_STATUS_SEC_TYPE_TKIP:
+               /* The uCode has got a bad phase 1 Key, pushes the packet.
+                * Decryption will be done in SW. */
+               if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+                   RX_RES_STATUS_BAD_KEY_TTAK)
+                       break;
+
+       case RX_RES_STATUS_SEC_TYPE_WEP:
+               if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+                   RX_RES_STATUS_BAD_ICV_MIC) {
+                       /* bad ICV, the packet is destroyed since the
+                        * decryption is inplace, drop it */
+                       D_RX("Packet destroyed\n");
+                       return -1;
+               }
+       case RX_RES_STATUS_SEC_TYPE_CCMP:
+               if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+                   RX_RES_STATUS_DECRYPT_OK) {
+                       D_RX("hw decrypt successfully!!!\n");
+                       stats->flag |= RX_FLAG_DECRYPTED;
+               }
+               break;
+
+       default:
+               break;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(il_set_decrypted_flag);
+
+/**
+ * il_txq_update_write_ptr - Send new write idx to hardware
+ */
+void
+il_txq_update_write_ptr(struct il_priv *il, struct il_tx_queue *txq)
+{
+       u32 reg = 0;
+       int txq_id = txq->q.id;
+
+       if (txq->need_update == 0)
+               return;
+
+       /* if we're trying to save power */
+       if (test_bit(S_POWER_PMI, &il->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 = _il_rd(il, CSR_UCODE_DRV_GP1);
+
+               if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+                       D_INFO("Tx queue %d requesting wakeup," " GP1 = 0x%x\n",
+                              txq_id, reg);
+                       il_set_bit(il, CSR_GP_CNTRL,
+                                  CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+                       return;
+               }
+
+               il_wr(il, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8));
+
+               /*
+                * 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
+               _il_wr(il, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8));
+       txq->need_update = 0;
+}
+EXPORT_SYMBOL(il_txq_update_write_ptr);
+
+/**
+ * il_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
+ */
+void
+il_tx_queue_unmap(struct il_priv *il, int txq_id)
+{
+       struct il_tx_queue *txq = &il->txq[txq_id];
+       struct il_queue *q = &txq->q;
+
+       if (q->n_bd == 0)
+               return;
+
+       while (q->write_ptr != q->read_ptr) {
+               il->cfg->ops->lib->txq_free_tfd(il, txq);
+               q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd);
+       }
+}
+EXPORT_SYMBOL(il_tx_queue_unmap);
+
+/**
+ * il_tx_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+void
+il_tx_queue_free(struct il_priv *il, int txq_id)
+{
+       struct il_tx_queue *txq = &il->txq[txq_id];
+       struct device *dev = &il->pci_dev->dev;
+       int i;
+
+       il_tx_queue_unmap(il, txq_id);
+
+       /* De-alloc array of command/tx buffers */
+       for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
+               kfree(txq->cmd[i]);
+
+       /* De-alloc circular buffer of TFDs */
+       if (txq->q.n_bd)
+               dma_free_coherent(dev, il->hw_params.tfd_size * txq->q.n_bd,
+                                 txq->tfds, txq->q.dma_addr);
+
+       /* De-alloc array of per-TFD driver data */
+       kfree(txq->txb);
+       txq->txb = NULL;
+
+       /* deallocate arrays */
+       kfree(txq->cmd);
+       kfree(txq->meta);
+       txq->cmd = NULL;
+       txq->meta = NULL;
+
+       /* 0-fill queue descriptor structure */
+       memset(txq, 0, sizeof(*txq));
+}
+EXPORT_SYMBOL(il_tx_queue_free);
+
+/**
+ * il_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
+ */
+void
+il_cmd_queue_unmap(struct il_priv *il)
+{
+       struct il_tx_queue *txq = &il->txq[il->cmd_queue];
+       struct il_queue *q = &txq->q;
+       int i;
+
+       if (q->n_bd == 0)
+               return;
+
+       while (q->read_ptr != q->write_ptr) {
+               i = il_get_cmd_idx(q, q->read_ptr, 0);
+
+               if (txq->meta[i].flags & CMD_MAPPED) {
+                       pci_unmap_single(il->pci_dev,
+                                        dma_unmap_addr(&txq->meta[i], mapping),
+                                        dma_unmap_len(&txq->meta[i], len),
+                                        PCI_DMA_BIDIRECTIONAL);
+                       txq->meta[i].flags = 0;
+               }
+
+               q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd);
+       }
+
+       i = q->n_win;
+       if (txq->meta[i].flags & CMD_MAPPED) {
+               pci_unmap_single(il->pci_dev,
+                                dma_unmap_addr(&txq->meta[i], mapping),
+                                dma_unmap_len(&txq->meta[i], len),
+                                PCI_DMA_BIDIRECTIONAL);
+               txq->meta[i].flags = 0;
+       }
+}
+EXPORT_SYMBOL(il_cmd_queue_unmap);
+
+/**
+ * il_cmd_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+void
+il_cmd_queue_free(struct il_priv *il)
+{
+       struct il_tx_queue *txq = &il->txq[il->cmd_queue];
+       struct device *dev = &il->pci_dev->dev;
+       int i;
+
+       il_cmd_queue_unmap(il);
+
+       /* De-alloc array of command/tx buffers */
+       for (i = 0; i <= TFD_CMD_SLOTS; i++)
+               kfree(txq->cmd[i]);
+
+       /* De-alloc circular buffer of TFDs */
+       if (txq->q.n_bd)
+               dma_free_coherent(dev, il->hw_params.tfd_size * txq->q.n_bd,
+                                 txq->tfds, txq->q.dma_addr);
+
+       /* deallocate arrays */
+       kfree(txq->cmd);
+       kfree(txq->meta);
+       txq->cmd = NULL;
+       txq->meta = NULL;
+
+       /* 0-fill queue descriptor structure */
+       memset(txq, 0, sizeof(*txq));
+}
+EXPORT_SYMBOL(il_cmd_queue_free);
+
+/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
+ * DMA services
+ *
+ * Theory of operation
+ *
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill.  Driver and device exchange status of each
+ * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
+ *
+ * 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.
+ *
+ * See more detailed info in 4965.h.
+ ***************************************************/
+
+int
+il_queue_space(const struct il_queue *q)
+{
+       int s = q->read_ptr - q->write_ptr;
+
+       if (q->read_ptr > q->write_ptr)
+               s -= q->n_bd;
+
+       if (s <= 0)
+               s += q->n_win;
+       /* keep some reserve to not confuse empty and full situations */
+       s -= 2;
+       if (s < 0)
+               s = 0;
+       return s;
+}
+EXPORT_SYMBOL(il_queue_space);
+
+
+/**
+ * il_queue_init - Initialize queue's high/low-water and read/write idxes
+ */
+static int
+il_queue_init(struct il_priv *il, struct il_queue *q, int count, int slots_num,
+             u32 id)
+{
+       q->n_bd = count;
+       q->n_win = slots_num;
+       q->id = id;
+
+       /* count must be power-of-two size, otherwise il_queue_inc_wrap
+        * and il_queue_dec_wrap are broken. */
+       BUG_ON(!is_power_of_2(count));
+
+       /* slots_num must be power-of-two size, otherwise
+        * il_get_cmd_idx is broken. */
+       BUG_ON(!is_power_of_2(slots_num));
+
+       q->low_mark = q->n_win / 4;
+       if (q->low_mark < 4)
+               q->low_mark = 4;
+
+       q->high_mark = q->n_win / 8;
+       if (q->high_mark < 2)
+               q->high_mark = 2;
+
+       q->write_ptr = q->read_ptr = 0;
+
+       return 0;
+}
+
+/**
+ * il_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
+ */
+static int
+il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id)
+{
+       struct device *dev = &il->pci_dev->dev;
+       size_t tfd_sz = il->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
+
+       /* Driver ilate data, only for Tx (not command) queues,
+        * not shared with device. */
+       if (id != il->cmd_queue) {
+               txq->txb =
+                   kzalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX,
+                           GFP_KERNEL);
+               if (!txq->txb) {
+                       IL_ERR("kmalloc for auxiliary BD "
+                              "structures failed\n");
+                       goto error;
+               }
+       } else {
+               txq->txb = NULL;
+       }
+
+       /* Circular buffer of transmit frame descriptors (TFDs),
+        * shared with device */
+       txq->tfds =
+           dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, GFP_KERNEL);
+       if (!txq->tfds) {
+               IL_ERR("pci_alloc_consistent(%zd) failed\n", tfd_sz);
+               goto error;
+       }
+       txq->q.id = id;
+
+       return 0;
+
+error:
+       kfree(txq->txb);
+       txq->txb = NULL;
+
+       return -ENOMEM;
+}
+
+/**
+ * il_tx_queue_init - Allocate and initialize one tx/cmd queue
+ */
+int
+il_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq, int slots_num,
+                u32 txq_id)
+{
+       int i, len;
+       int ret;
+       int actual_slots = slots_num;
+
+       /*
+        * Alloc buffer array for commands (Tx or other types of commands).
+        * For the command queue (#4/#9), allocate command space + one big
+        * command for scan, since scan command is very huge; the system will
+        * not have two scans at the same time, so only one is needed.
+        * For normal Tx queues (all other queues), no super-size command
+        * space is needed.
+        */
+       if (txq_id == il->cmd_queue)
+               actual_slots++;
+
+       txq->meta =
+           kzalloc(sizeof(struct il_cmd_meta) * actual_slots, GFP_KERNEL);
+       txq->cmd =
+           kzalloc(sizeof(struct il_device_cmd *) * actual_slots, GFP_KERNEL);
+
+       if (!txq->meta || !txq->cmd)
+               goto out_free_arrays;
+
+       len = sizeof(struct il_device_cmd);
+       for (i = 0; i < actual_slots; i++) {
+               /* only happens for cmd queue */
+               if (i == slots_num)
+                       len = IL_MAX_CMD_SIZE;
+
+               txq->cmd[i] = kmalloc(len, GFP_KERNEL);
+               if (!txq->cmd[i])
+                       goto err;
+       }
+
+       /* Alloc driver data array and TFD circular buffer */
+       ret = il_tx_queue_alloc(il, txq, txq_id);
+       if (ret)
+               goto err;
+
+       txq->need_update = 0;
+
+       /*
+        * For the default queues 0-3, set up the swq_id
+        * already -- all others need to get one later
+        * (if they need one at all).
+        */
+       if (txq_id < 4)
+               il_set_swq_id(txq, txq_id, txq_id);
+
+       /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+        * il_queue_inc_wrap and il_queue_dec_wrap are broken. */
+       BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+       /* Initialize queue's high/low-water marks, and head/tail idxes */
+       il_queue_init(il, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+
+       /* Tell device where to find queue */
+       il->cfg->ops->lib->txq_init(il, txq);
+
+       return 0;
+err:
+       for (i = 0; i < actual_slots; i++)
+               kfree(txq->cmd[i]);
+out_free_arrays:
+       kfree(txq->meta);
+       kfree(txq->cmd);
+
+       return -ENOMEM;
+}
+EXPORT_SYMBOL(il_tx_queue_init);
+
+void
+il_tx_queue_reset(struct il_priv *il, struct il_tx_queue *txq, int slots_num,
+                 u32 txq_id)
+{
+       int actual_slots = slots_num;
+
+       if (txq_id == il->cmd_queue)
+               actual_slots++;
+
+       memset(txq->meta, 0, sizeof(struct il_cmd_meta) * actual_slots);
+
+       txq->need_update = 0;
+
+       /* Initialize queue's high/low-water marks, and head/tail idxes */
+       il_queue_init(il, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+
+       /* Tell device where to find queue */
+       il->cfg->ops->lib->txq_init(il, txq);
+}
+EXPORT_SYMBOL(il_tx_queue_reset);
+
+/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
+
+/**
+ * il_enqueue_hcmd - enqueue a uCode command
+ * @il: device ilate 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 idx (> 0) of command in the
+ * command queue.
+ */
+int
+il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd)
+{
+       struct il_tx_queue *txq = &il->txq[il->cmd_queue];
+       struct il_queue *q = &txq->q;
+       struct il_device_cmd *out_cmd;
+       struct il_cmd_meta *out_meta;
+       dma_addr_t phys_addr;
+       unsigned long flags;
+       int len;
+       u32 idx;
+       u16 fix_size;
+
+       cmd->len = il->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
+       fix_size = (u16) (cmd->len + sizeof(out_cmd->hdr));
+
+       /* 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
+        * Also, check to see if command buffer should not exceed the size
+        * of device_cmd and max_cmd_size. */
+       BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
+              !(cmd->flags & CMD_SIZE_HUGE));
+       BUG_ON(fix_size > IL_MAX_CMD_SIZE);
+
+       if (il_is_rfkill(il) || il_is_ctkill(il)) {
+               IL_WARN("Not sending command - %s KILL\n",
+                       il_is_rfkill(il) ? "RF" : "CT");
+               return -EIO;
+       }
+
+       spin_lock_irqsave(&il->hcmd_lock, flags);
+
+       if (il_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
+               spin_unlock_irqrestore(&il->hcmd_lock, flags);
+
+               IL_ERR("Restarting adapter due to command queue full\n");
+               queue_work(il->workqueue, &il->restart);
+               return -ENOSPC;
+       }
+
+       idx = il_get_cmd_idx(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
+       out_cmd = txq->cmd[idx];
+       out_meta = &txq->meta[idx];
+
+       if (WARN_ON(out_meta->flags & CMD_MAPPED)) {
+               spin_unlock_irqrestore(&il->hcmd_lock, flags);
+               return -ENOSPC;
+       }
+
+       memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
+       out_meta->flags = cmd->flags | CMD_MAPPED;
+       if (cmd->flags & CMD_WANT_SKB)
+               out_meta->source = cmd;
+       if (cmd->flags & CMD_ASYNC)
+               out_meta->callback = cmd->callback;
+
+       out_cmd->hdr.cmd = cmd->id;
+       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(il->cmd_queue) | IDX_TO_SEQ(q->write_ptr));
+       if (cmd->flags & CMD_SIZE_HUGE)
+               out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
+       len = sizeof(struct il_device_cmd);
+       if (idx == TFD_CMD_SLOTS)
+               len = IL_MAX_CMD_SIZE;
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+       switch (out_cmd->hdr.cmd) {
+       case C_TX_LINK_QUALITY_CMD:
+       case C_SENSITIVITY:
+               D_HC_DUMP("Sending command %s (#%x), seq: 0x%04X, "
+                         "%d bytes at %d[%d]:%d\n",
+                         il_get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd,
+                         le16_to_cpu(out_cmd->hdr.sequence), fix_size,
+                         q->write_ptr, idx, il->cmd_queue);
+               break;
+       default:
+               D_HC("Sending command %s (#%x), seq: 0x%04X, "
+                    "%d bytes at %d[%d]:%d\n",
+                    il_get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd,
+                    le16_to_cpu(out_cmd->hdr.sequence), fix_size, q->write_ptr,
+                    idx, il->cmd_queue);
+       }
+#endif
+       txq->need_update = 1;
+
+       if (il->cfg->ops->lib->txq_update_byte_cnt_tbl)
+               /* Set up entry in queue's byte count circular buffer */
+               il->cfg->ops->lib->txq_update_byte_cnt_tbl(il, txq, 0);
+
+       phys_addr =
+           pci_map_single(il->pci_dev, &out_cmd->hdr, fix_size,
+                          PCI_DMA_BIDIRECTIONAL);
+       dma_unmap_addr_set(out_meta, mapping, phys_addr);
+       dma_unmap_len_set(out_meta, len, fix_size);
+
+       il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, fix_size,
+                                                1, U32_PAD(cmd->len));
+
+       /* Increment and update queue's write idx */
+       q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);
+       il_txq_update_write_ptr(il, txq);
+
+       spin_unlock_irqrestore(&il->hcmd_lock, flags);
+       return idx;
+}
+
+/**
+ * il_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
+ *
+ * When FW advances 'R' idx, all entries between old and new 'R' idx
+ * need to be reclaimed. As result, some free space forms.  If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+static void
+il_hcmd_queue_reclaim(struct il_priv *il, int txq_id, int idx, int cmd_idx)
+{
+       struct il_tx_queue *txq = &il->txq[txq_id];
+       struct il_queue *q = &txq->q;
+       int nfreed = 0;
+
+       if (idx >= q->n_bd || il_queue_used(q, idx) == 0) {
+               IL_ERR("Read idx for DMA queue txq id (%d), idx %d, "
+                      "is out of range [0-%d] %d %d.\n", txq_id, idx, q->n_bd,
+                      q->write_ptr, q->read_ptr);
+               return;
+       }
+
+       for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+            q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+               if (nfreed++ > 0) {
+                       IL_ERR("HCMD skipped: idx (%d) %d %d\n", idx,
+                              q->write_ptr, q->read_ptr);
+                       queue_work(il->workqueue, &il->restart);
+               }
+
+       }
+}
+
+/**
+ * il_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
+ */
+void
+il_tx_cmd_complete(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+       int txq_id = SEQ_TO_QUEUE(sequence);
+       int idx = SEQ_TO_IDX(sequence);
+       int cmd_idx;
+       bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
+       struct il_device_cmd *cmd;
+       struct il_cmd_meta *meta;
+       struct il_tx_queue *txq = &il->txq[il->cmd_queue];
+       unsigned long flags;
+
+       /* 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 (WARN
+           (txq_id != il->cmd_queue,
+            "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
+            txq_id, il->cmd_queue, sequence, il->txq[il->cmd_queue].q.read_ptr,
+            il->txq[il->cmd_queue].q.write_ptr)) {
+               il_print_hex_error(il, pkt, 32);
+               return;
+       }
+
+       cmd_idx = il_get_cmd_idx(&txq->q, idx, huge);
+       cmd = txq->cmd[cmd_idx];
+       meta = &txq->meta[cmd_idx];
+
+       txq->time_stamp = jiffies;
+
+       pci_unmap_single(il->pci_dev, dma_unmap_addr(meta, mapping),
+                        dma_unmap_len(meta, len), PCI_DMA_BIDIRECTIONAL);
+
+       /* Input error checking is done when commands are added to queue. */
+       if (meta->flags & CMD_WANT_SKB) {
+               meta->source->reply_page = (unsigned long)rxb_addr(rxb);
+               rxb->page = NULL;
+       } else if (meta->callback)
+               meta->callback(il, cmd, pkt);
+
+       spin_lock_irqsave(&il->hcmd_lock, flags);
+
+       il_hcmd_queue_reclaim(il, txq_id, idx, cmd_idx);
+
+       if (!(meta->flags & CMD_ASYNC)) {
+               clear_bit(S_HCMD_ACTIVE, &il->status);
+               D_INFO("Clearing HCMD_ACTIVE for command %s\n",
+                      il_get_cmd_string(cmd->hdr.cmd));
+               wake_up(&il->wait_command_queue);
+       }
+
+       /* Mark as unmapped */
+       meta->flags = 0;
+
+       spin_unlock_irqrestore(&il->hcmd_lock, flags);
+}
+EXPORT_SYMBOL(il_tx_cmd_complete);
+
+MODULE_DESCRIPTION("iwl-legacy: common functions for 3945 and 4965");
+MODULE_VERSION(IWLWIFI_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+MODULE_LICENSE("GPL");
+
+/*
+ * set bt_coex_active to true, uCode will do kill/defer
+ * every time the priority line is asserted (BT is sending signals on the
+ * priority line in the PCIx).
+ * set bt_coex_active to false, uCode will ignore the BT activity and
+ * perform the normal operation
+ *
+ * User might experience transmit issue on some platform due to WiFi/BT
+ * co-exist problem. The possible behaviors are:
+ *   Able to scan and finding all the available AP
+ *   Not able to associate with any AP
+ * On those platforms, WiFi communication can be restored by set
+ * "bt_coex_active" module parameter to "false"
+ *
+ * default: bt_coex_active = true (BT_COEX_ENABLE)
+ */
+static bool bt_coex_active = true;
+module_param(bt_coex_active, bool, S_IRUGO);
+MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
+
+u32 il_debug_level;
+EXPORT_SYMBOL(il_debug_level);
+
+const u8 il_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+EXPORT_SYMBOL(il_bcast_addr);
+
+/* This function both allocates and initializes hw and il. */
+struct ieee80211_hw *
+il_alloc_all(struct il_cfg *cfg)
+{
+       struct il_priv *il;
+       /* mac80211 allocates memory for this device instance, including
+        *   space for this driver's ilate structure */
+       struct ieee80211_hw *hw;
+
+       hw = ieee80211_alloc_hw(sizeof(struct il_priv),
+                               cfg->ops->ieee80211_ops);
+       if (hw == NULL) {
+               pr_err("%s: Can not allocate network device\n", cfg->name);
+               goto out;
+       }
+
+       il = hw->priv;
+       il->hw = hw;
+
+out:
+       return hw;
+}
+EXPORT_SYMBOL(il_alloc_all);
+
+#define MAX_BIT_RATE_40_MHZ 150        /* Mbps */
+#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
+static void
+il_init_ht_hw_capab(const struct il_priv *il,
+                   struct ieee80211_sta_ht_cap *ht_info,
+                   enum ieee80211_band band)
+{
+       u16 max_bit_rate = 0;
+       u8 rx_chains_num = il->hw_params.rx_chains_num;
+       u8 tx_chains_num = il->hw_params.tx_chains_num;
+
+       ht_info->cap = 0;
+       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+
+       ht_info->ht_supported = true;
+
+       ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
+       max_bit_rate = MAX_BIT_RATE_20_MHZ;
+       if (il->hw_params.ht40_channel & BIT(band)) {
+               ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+               ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
+               ht_info->mcs.rx_mask[4] = 0x01;
+               max_bit_rate = MAX_BIT_RATE_40_MHZ;
+       }
+
+       if (il->cfg->mod_params->amsdu_size_8K)
+               ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
+
+       ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
+       ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
+
+       ht_info->mcs.rx_mask[0] = 0xFF;
+       if (rx_chains_num >= 2)
+               ht_info->mcs.rx_mask[1] = 0xFF;
+       if (rx_chains_num >= 3)
+               ht_info->mcs.rx_mask[2] = 0xFF;
+
+       /* Highest supported Rx data rate */
+       max_bit_rate *= rx_chains_num;
+       WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
+       ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
+
+       /* Tx MCS capabilities */
+       ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+       if (tx_chains_num != rx_chains_num) {
+               ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
+               ht_info->mcs.tx_params |=
+                   ((tx_chains_num -
+                     1) << IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
+       }
+}
+
+/**
+ * il_init_geos - Initialize mac80211's geo/channel info based from eeprom
+ */
+int
+il_init_geos(struct il_priv *il)
+{
+       struct il_channel_info *ch;
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *channels;
+       struct ieee80211_channel *geo_ch;
+       struct ieee80211_rate *rates;
+       int i = 0;
+       s8 max_tx_power = 0;
+
+       if (il->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
+           il->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
+               D_INFO("Geography modes already initialized.\n");
+               set_bit(S_GEO_CONFIGURED, &il->status);
+               return 0;
+       }
+
+       channels =
+           kzalloc(sizeof(struct ieee80211_channel) * il->channel_count,
+                   GFP_KERNEL);
+       if (!channels)
+               return -ENOMEM;
+
+       rates =
+           kzalloc((sizeof(struct ieee80211_rate) * RATE_COUNT_LEGACY),
+                   GFP_KERNEL);
+       if (!rates) {
+               kfree(channels);
+               return -ENOMEM;
+       }
+
+       /* 5.2GHz channels start after the 2.4GHz channels */
+       sband = &il->bands[IEEE80211_BAND_5GHZ];
+       sband->channels = &channels[ARRAY_SIZE(il_eeprom_band_1)];
+       /* just OFDM */
+       sband->bitrates = &rates[IL_FIRST_OFDM_RATE];
+       sband->n_bitrates = RATE_COUNT_LEGACY - IL_FIRST_OFDM_RATE;
+
+       if (il->cfg->sku & IL_SKU_N)
+               il_init_ht_hw_capab(il, &sband->ht_cap, IEEE80211_BAND_5GHZ);
+
+       sband = &il->bands[IEEE80211_BAND_2GHZ];
+       sband->channels = channels;
+       /* OFDM & CCK */
+       sband->bitrates = rates;
+       sband->n_bitrates = RATE_COUNT_LEGACY;
+
+       if (il->cfg->sku & IL_SKU_N)
+               il_init_ht_hw_capab(il, &sband->ht_cap, IEEE80211_BAND_2GHZ);
+
+       il->ieee_channels = channels;
+       il->ieee_rates = rates;
+
+       for (i = 0; i < il->channel_count; i++) {
+               ch = &il->channel_info[i];
+
+               if (!il_is_channel_valid(ch))
+                       continue;
+
+               sband = &il->bands[ch->band];
+
+               geo_ch = &sband->channels[sband->n_channels++];
+
+               geo_ch->center_freq =
+                   ieee80211_channel_to_frequency(ch->channel, ch->band);
+               geo_ch->max_power = ch->max_power_avg;
+               geo_ch->max_antenna_gain = 0xff;
+               geo_ch->hw_value = ch->channel;
+
+               if (il_is_channel_valid(ch)) {
+                       if (!(ch->flags & EEPROM_CHANNEL_IBSS))
+                               geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
+
+                       if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
+                               geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+
+                       if (ch->flags & EEPROM_CHANNEL_RADAR)
+                               geo_ch->flags |= IEEE80211_CHAN_RADAR;
+
+                       geo_ch->flags |= ch->ht40_extension_channel;
+
+                       if (ch->max_power_avg > max_tx_power)
+                               max_tx_power = ch->max_power_avg;
+               } else {
+                       geo_ch->flags |= IEEE80211_CHAN_DISABLED;
+               }
+
+               D_INFO("Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", ch->channel,
+                      geo_ch->center_freq,
+                      il_is_channel_a_band(ch) ? "5.2" : "2.4",
+                      geo_ch->
+                      flags & IEEE80211_CHAN_DISABLED ? "restricted" : "valid",
+                      geo_ch->flags);
+       }
+
+       il->tx_power_device_lmt = max_tx_power;
+       il->tx_power_user_lmt = max_tx_power;
+       il->tx_power_next = max_tx_power;
+
+       if (il->bands[IEEE80211_BAND_5GHZ].n_channels == 0 &&
+           (il->cfg->sku & IL_SKU_A)) {
+               IL_INFO("Incorrectly detected BG card as ABG. "
+                       "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
+                       il->pci_dev->device, il->pci_dev->subsystem_device);
+               il->cfg->sku &= ~IL_SKU_A;
+       }
+
+       IL_INFO("Tunable channels: %d 802.11bg, %d 802.11a channels\n",
+               il->bands[IEEE80211_BAND_2GHZ].n_channels,
+               il->bands[IEEE80211_BAND_5GHZ].n_channels);
+
+       set_bit(S_GEO_CONFIGURED, &il->status);
+
+       return 0;
+}
+EXPORT_SYMBOL(il_init_geos);
+
+/*
+ * il_free_geos - undo allocations in il_init_geos
+ */
+void
+il_free_geos(struct il_priv *il)
+{
+       kfree(il->ieee_channels);
+       kfree(il->ieee_rates);
+       clear_bit(S_GEO_CONFIGURED, &il->status);
+}
+EXPORT_SYMBOL(il_free_geos);
+
+static bool
+il_is_channel_extension(struct il_priv *il, enum ieee80211_band band,
+                       u16 channel, u8 extension_chan_offset)
+{
+       const struct il_channel_info *ch_info;
+
+       ch_info = il_get_channel_info(il, band, channel);
+       if (!il_is_channel_valid(ch_info))
+               return false;
+
+       if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
+               return !(ch_info->
+                        ht40_extension_channel & IEEE80211_CHAN_NO_HT40PLUS);
+       else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
+               return !(ch_info->
+                        ht40_extension_channel & IEEE80211_CHAN_NO_HT40MINUS);
+
+       return false;
+}
+
+bool
+il_is_ht40_tx_allowed(struct il_priv *il, struct il_rxon_context *ctx,
+                     struct ieee80211_sta_ht_cap *ht_cap)
+{
+       if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
+               return false;
+
+       /*
+        * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
+        * the bit will not set if it is pure 40MHz case
+        */
+       if (ht_cap && !ht_cap->ht_supported)
+               return false;
+
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+       if (il->disable_ht40)
+               return false;
+#endif
+
+       return il_is_channel_extension(il, il->band,
+                                      le16_to_cpu(ctx->staging.channel),
+                                      ctx->ht.extension_chan_offset);
+}
+EXPORT_SYMBOL(il_is_ht40_tx_allowed);
+
+static u16
+il_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
+{
+       u16 new_val;
+       u16 beacon_factor;
+
+       /*
+        * If mac80211 hasn't given us a beacon interval, program
+        * the default into the device.
+        */
+       if (!beacon_val)
+               return DEFAULT_BEACON_INTERVAL;
+
+       /*
+        * If the beacon interval we obtained from the peer
+        * is too large, we'll have to wake up more often
+        * (and in IBSS case, we'll beacon too much)
+        *
+        * For example, if max_beacon_val is 4096, and the
+        * requested beacon interval is 7000, we'll have to
+        * use 3500 to be able to wake up on the beacons.
+        *
+        * This could badly influence beacon detection stats.
+        */
+
+       beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val;
+       new_val = beacon_val / beacon_factor;
+
+       if (!new_val)
+               new_val = max_beacon_val;
+
+       return new_val;
+}
+
+int
+il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       u64 tsf;
+       s32 interval_tm, rem;
+       struct ieee80211_conf *conf = NULL;
+       u16 beacon_int;
+       struct ieee80211_vif *vif = ctx->vif;
+
+       conf = &il->hw->conf;
+
+       lockdep_assert_held(&il->mutex);
+
+       memset(&ctx->timing, 0, sizeof(struct il_rxon_time_cmd));
+
+       ctx->timing.timestamp = cpu_to_le64(il->timestamp);
+       ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval);
+
+       beacon_int = vif ? vif->bss_conf.beacon_int : 0;
+
+       /*
+        * TODO: For IBSS we need to get atim_win from mac80211,
+        *       for now just always use 0
+        */
+       ctx->timing.atim_win = 0;
+
+       beacon_int =
+           il_adjust_beacon_interval(beacon_int,
+                                     il->hw_params.max_beacon_itrvl *
+                                     TIME_UNIT);
+       ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
+
+       tsf = il->timestamp;    /* tsf is modifed by do_div: copy it */
+       interval_tm = beacon_int * TIME_UNIT;
+       rem = do_div(tsf, interval_tm);
+       ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
+
+       ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ? : 1) : 1;
+
+       D_ASSOC("beacon interval %d beacon timer %d beacon tim %d\n",
+               le16_to_cpu(ctx->timing.beacon_interval),
+               le32_to_cpu(ctx->timing.beacon_init_val),
+               le16_to_cpu(ctx->timing.atim_win));
+
+       return il_send_cmd_pdu(il, ctx->rxon_timing_cmd, sizeof(ctx->timing),
+                              &ctx->timing);
+}
+EXPORT_SYMBOL(il_send_rxon_timing);
+
+void
+il_set_rxon_hwcrypto(struct il_priv *il, struct il_rxon_context *ctx,
+                    int hw_decrypt)
+{
+       struct il_rxon_cmd *rxon = &ctx->staging;
+
+       if (hw_decrypt)
+               rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
+       else
+               rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
+
+}
+EXPORT_SYMBOL(il_set_rxon_hwcrypto);
+
+/* validate RXON structure is valid */
+int
+il_check_rxon_cmd(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       struct il_rxon_cmd *rxon = &ctx->staging;
+       bool error = false;
+
+       if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
+               if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) {
+                       IL_WARN("check 2.4G: wrong narrow\n");
+                       error = true;
+               }
+               if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) {
+                       IL_WARN("check 2.4G: wrong radar\n");
+                       error = true;
+               }
+       } else {
+               if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) {
+                       IL_WARN("check 5.2G: not short slot!\n");
+                       error = true;
+               }
+               if (rxon->flags & RXON_FLG_CCK_MSK) {
+                       IL_WARN("check 5.2G: CCK!\n");
+                       error = true;
+               }
+       }
+       if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) {
+               IL_WARN("mac/bssid mcast!\n");
+               error = true;
+       }
+
+       /* make sure basic rates 6Mbps and 1Mbps are supported */
+       if ((rxon->ofdm_basic_rates & RATE_6M_MASK) == 0 &&
+           (rxon->cck_basic_rates & RATE_1M_MASK) == 0) {
+               IL_WARN("neither 1 nor 6 are basic\n");
+               error = true;
+       }
+
+       if (le16_to_cpu(rxon->assoc_id) > 2007) {
+               IL_WARN("aid > 2007\n");
+               error = true;
+       }
+
+       if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) ==
+           (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) {
+               IL_WARN("CCK and short slot\n");
+               error = true;
+       }
+
+       if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) ==
+           (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) {
+               IL_WARN("CCK and auto detect");
+               error = true;
+       }
+
+       if ((rxon->
+            flags & (RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK)) ==
+           RXON_FLG_TGG_PROTECT_MSK) {
+               IL_WARN("TGg but no auto-detect\n");
+               error = true;
+       }
+
+       if (error)
+               IL_WARN("Tuning to channel %d\n", le16_to_cpu(rxon->channel));
+
+       if (error) {
+               IL_ERR("Invalid RXON\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(il_check_rxon_cmd);
+
+/**
+ * il_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
+ * @il: staging_rxon is compared to active_rxon
+ *
+ * If the RXON structure is changing enough to require a new tune,
+ * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
+ * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
+ */
+int
+il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       const struct il_rxon_cmd *staging = &ctx->staging;
+       const struct il_rxon_cmd *active = &ctx->active;
+
+#define CHK(cond)                                                      \
+       if ((cond)) {                                                   \
+               D_INFO("need full RXON - " #cond "\n"); \
+               return 1;                                               \
+       }
+
+#define CHK_NEQ(c1, c2)                                                \
+       if ((c1) != (c2)) {                                     \
+               D_INFO("need full RXON - "      \
+                              #c1 " != " #c2 " - %d != %d\n",  \
+                              (c1), (c2));                     \
+               return 1;                                       \
+       }
+
+       /* These items are only settable from the full RXON command */
+       CHK(!il_is_associated_ctx(ctx));
+       CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr));
+       CHK(compare_ether_addr(staging->node_addr, active->node_addr));
+       CHK(compare_ether_addr
+           (staging->wlap_bssid_addr, active->wlap_bssid_addr));
+       CHK_NEQ(staging->dev_type, active->dev_type);
+       CHK_NEQ(staging->channel, active->channel);
+       CHK_NEQ(staging->air_propagation, active->air_propagation);
+       CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates,
+               active->ofdm_ht_single_stream_basic_rates);
+       CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates,
+               active->ofdm_ht_dual_stream_basic_rates);
+       CHK_NEQ(staging->assoc_id, active->assoc_id);
+
+       /* 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 */
+       CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK,
+               active->flags & RXON_FLG_BAND_24G_MSK);
+
+       /* Check if we are switching association toggle */
+       CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK,
+               active->filter_flags & RXON_FILTER_ASSOC_MSK);
+
+#undef CHK
+#undef CHK_NEQ
+
+       return 0;
+}
+EXPORT_SYMBOL(il_full_rxon_required);
+
+u8
+il_get_lowest_plcp(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       /*
+        * Assign the lowest rate -- should really get this from
+        * the beacon skb from mac80211.
+        */
+       if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
+               return RATE_1M_PLCP;
+       else
+               return RATE_6M_PLCP;
+}
+EXPORT_SYMBOL(il_get_lowest_plcp);
+
+static void
+_il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf,
+               struct il_rxon_context *ctx)
+{
+       struct il_rxon_cmd *rxon = &ctx->staging;
+
+       if (!ctx->ht.enabled) {
+               rxon->flags &=
+                   ~(RXON_FLG_CHANNEL_MODE_MSK |
+                     RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | RXON_FLG_HT40_PROT_MSK
+                     | RXON_FLG_HT_PROT_MSK);
+               return;
+       }
+
+       rxon->flags |=
+           cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS);
+
+       /* Set up channel bandwidth:
+        * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
+       /* clear the HT channel mode before set the mode */
+       rxon->flags &=
+           ~(RXON_FLG_CHANNEL_MODE_MSK | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
+       if (il_is_ht40_tx_allowed(il, ctx, NULL)) {
+               /* pure ht40 */
+               if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
+                       rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
+                       /* Note: control channel is opposite of extension channel */
+                       switch (ctx->ht.extension_chan_offset) {
+                       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+                               rxon->flags &=
+                                   ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+                               break;
+                       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                               rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+                               break;
+                       }
+               } else {
+                       /* Note: control channel is opposite of extension channel */
+                       switch (ctx->ht.extension_chan_offset) {
+                       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+                               rxon->flags &=
+                                   ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
+                               rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
+                               break;
+                       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                               rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+                               rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
+                               break;
+                       case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+                       default:
+                               /* channel location only valid if in Mixed mode */
+                               IL_ERR("invalid extension channel offset\n");
+                               break;
+                       }
+               }
+       } else {
+               rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
+       }
+
+       if (il->cfg->ops->hcmd->set_rxon_chain)
+               il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
+
+       D_ASSOC("rxon flags 0x%X operation mode :0x%X "
+               "extension channel offset 0x%x\n", le32_to_cpu(rxon->flags),
+               ctx->ht.protection, ctx->ht.extension_chan_offset);
+}
+
+void
+il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf)
+{
+       _il_set_rxon_ht(il, ht_conf, &il->ctx);
+}
+EXPORT_SYMBOL(il_set_rxon_ht);
+
+/* Return valid, unused, channel for a passive scan to reset the RF */
+u8
+il_get_single_channel_number(struct il_priv *il, enum ieee80211_band band)
+{
+       const struct il_channel_info *ch_info;
+       int i;
+       u8 channel = 0;
+       u8 min, max;
+
+       if (band == IEEE80211_BAND_5GHZ) {
+               min = 14;
+               max = il->channel_count;
+       } else {
+               min = 0;
+               max = 14;
+       }
+
+       for (i = min; i < max; i++) {
+               channel = il->channel_info[i].channel;
+               if (channel == le16_to_cpu(il->ctx.staging.channel))
+                       continue;
+
+               ch_info = il_get_channel_info(il, band, channel);
+               if (il_is_channel_valid(ch_info))
+                       break;
+       }
+
+       return channel;
+}
+EXPORT_SYMBOL(il_get_single_channel_number);
+
+/**
+ * il_set_rxon_channel - Set the band and channel values in staging RXON
+ * @ch: requested channel as a pointer to struct ieee80211_channel
+
+ * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
+ * in the staging RXON flag structure based on the ch->band
+ */
+int
+il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch,
+                   struct il_rxon_context *ctx)
+{
+       enum ieee80211_band band = ch->band;
+       u16 channel = ch->hw_value;
+
+       if (le16_to_cpu(ctx->staging.channel) == channel && il->band == band)
+               return 0;
+
+       ctx->staging.channel = cpu_to_le16(channel);
+       if (band == IEEE80211_BAND_5GHZ)
+               ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
+       else
+               ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
+
+       il->band = band;
+
+       D_INFO("Staging channel set to %d [%d]\n", channel, band);
+
+       return 0;
+}
+EXPORT_SYMBOL(il_set_rxon_channel);
+
+void
+il_set_flags_for_band(struct il_priv *il, struct il_rxon_context *ctx,
+                     enum ieee80211_band band, struct ieee80211_vif *vif)
+{
+       if (band == IEEE80211_BAND_5GHZ) {
+               ctx->staging.flags &=
+                   ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK |
+                     RXON_FLG_CCK_MSK);
+               ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+       } else {
+               /* Copied from il_post_associate() */
+               if (vif && vif->bss_conf.use_short_slot)
+                       ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+               else
+                       ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+
+               ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
+               ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
+               ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
+       }
+}
+EXPORT_SYMBOL(il_set_flags_for_band);
+
+/*
+ * initialize rxon structure with default values from eeprom
+ */
+void
+il_connection_init_rx_config(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       const struct il_channel_info *ch_info;
+
+       memset(&ctx->staging, 0, sizeof(ctx->staging));
+
+       if (!ctx->vif) {
+               ctx->staging.dev_type = ctx->unused_devtype;
+       } else
+               switch (ctx->vif->type) {
+
+               case NL80211_IFTYPE_STATION:
+                       ctx->staging.dev_type = ctx->station_devtype;
+                       ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
+                       break;
+
+               case NL80211_IFTYPE_ADHOC:
+                       ctx->staging.dev_type = ctx->ibss_devtype;
+                       ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
+                       ctx->staging.filter_flags =
+                           RXON_FILTER_BCON_AWARE_MSK |
+                           RXON_FILTER_ACCEPT_GRP_MSK;
+                       break;
+
+               default:
+                       IL_ERR("Unsupported interface type %d\n",
+                              ctx->vif->type);
+                       break;
+               }
+
+#if 0
+       /* TODO:  Figure out when short_preamble would be set and cache from
+        * that */
+       if (!hw_to_local(il->hw)->short_preamble)
+               ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+       else
+               ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+#endif
+
+       ch_info =
+           il_get_channel_info(il, il->band, le16_to_cpu(ctx->active.channel));
+
+       if (!ch_info)
+               ch_info = &il->channel_info[0];
+
+       ctx->staging.channel = cpu_to_le16(ch_info->channel);
+       il->band = ch_info->band;
+
+       il_set_flags_for_band(il, ctx, il->band, ctx->vif);
+
+       ctx->staging.ofdm_basic_rates =
+           (IL_OFDM_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF;
+       ctx->staging.cck_basic_rates =
+           (IL_CCK_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF;
+
+       /* clear both MIX and PURE40 mode flag */
+       ctx->staging.flags &=
+           ~(RXON_FLG_CHANNEL_MODE_MIXED | RXON_FLG_CHANNEL_MODE_PURE_40);
+       if (ctx->vif)
+               memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
+
+       ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
+       ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
+}
+EXPORT_SYMBOL(il_connection_init_rx_config);
+
+void
+il_set_rate(struct il_priv *il)
+{
+       const struct ieee80211_supported_band *hw = NULL;
+       struct ieee80211_rate *rate;
+       int i;
+
+       hw = il_get_hw_mode(il, il->band);
+       if (!hw) {
+               IL_ERR("Failed to set rate: unable to get hw mode\n");
+               return;
+       }
+
+       il->active_rate = 0;
+
+       for (i = 0; i < hw->n_bitrates; i++) {
+               rate = &(hw->bitrates[i]);
+               if (rate->hw_value < RATE_COUNT_LEGACY)
+                       il->active_rate |= (1 << rate->hw_value);
+       }
+
+       D_RATE("Set active_rate = %0x\n", il->active_rate);
+
+       il->ctx.staging.cck_basic_rates =
+           (IL_CCK_BASIC_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF;
+
+       il->ctx.staging.ofdm_basic_rates =
+           (IL_OFDM_BASIC_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF;
+}
+EXPORT_SYMBOL(il_set_rate);
+
+void
+il_chswitch_done(struct il_priv *il, bool is_success)
+{
+       struct il_rxon_context *ctx = &il->ctx;
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       if (test_and_clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status))
+               ieee80211_chswitch_done(ctx->vif, is_success);
+}
+EXPORT_SYMBOL(il_chswitch_done);
+
+void
+il_hdl_csa(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_csa_notification *csa = &(pkt->u.csa_notif);
+
+       struct il_rxon_context *ctx = &il->ctx;
+       struct il_rxon_cmd *rxon = (void *)&ctx->active;
+
+       if (!test_bit(S_CHANNEL_SWITCH_PENDING, &il->status))
+               return;
+
+       if (!le32_to_cpu(csa->status) && csa->channel == il->switch_channel) {
+               rxon->channel = csa->channel;
+               ctx->staging.channel = csa->channel;
+               D_11H("CSA notif: channel %d\n", le16_to_cpu(csa->channel));
+               il_chswitch_done(il, true);
+       } else {
+               IL_ERR("CSA notif (fail) : channel %d\n",
+                      le16_to_cpu(csa->channel));
+               il_chswitch_done(il, false);
+       }
+}
+EXPORT_SYMBOL(il_hdl_csa);
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+void
+il_print_rx_config_cmd(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       struct il_rxon_cmd *rxon = &ctx->staging;
+
+       D_RADIO("RX CONFIG:\n");
+       il_print_hex_dump(il, IL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+       D_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
+       D_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
+       D_RADIO("u32 filter_flags: 0x%08x\n", le32_to_cpu(rxon->filter_flags));
+       D_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type);
+       D_RADIO("u8 ofdm_basic_rates: 0x%02x\n", rxon->ofdm_basic_rates);
+       D_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
+       D_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr);
+       D_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
+       D_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
+}
+EXPORT_SYMBOL(il_print_rx_config_cmd);
+#endif
+/**
+ * il_irq_handle_error - called for HW or SW error interrupt from card
+ */
+void
+il_irq_handle_error(struct il_priv *il)
+{
+       /* Set the FW error flag -- cleared on il_down */
+       set_bit(S_FW_ERROR, &il->status);
+
+       /* Cancel currently queued command. */
+       clear_bit(S_HCMD_ACTIVE, &il->status);
+
+       IL_ERR("Loaded firmware version: %s\n", il->hw->wiphy->fw_version);
+
+       il->cfg->ops->lib->dump_nic_error_log(il);
+       if (il->cfg->ops->lib->dump_fh)
+               il->cfg->ops->lib->dump_fh(il, NULL, false);
+#ifdef CONFIG_IWLEGACY_DEBUG
+       if (il_get_debug_level(il) & IL_DL_FW_ERRORS)
+               il_print_rx_config_cmd(il, &il->ctx);
+#endif
+
+       wake_up(&il->wait_command_queue);
+
+       /* Keep the restart process from trying to send host
+        * commands by clearing the INIT status bit */
+       clear_bit(S_READY, &il->status);
+
+       if (!test_bit(S_EXIT_PENDING, &il->status)) {
+               IL_DBG(IL_DL_FW_ERRORS,
+                      "Restarting adapter due to uCode error.\n");
+
+               if (il->cfg->mod_params->restart_fw)
+                       queue_work(il->workqueue, &il->restart);
+       }
+}
+EXPORT_SYMBOL(il_irq_handle_error);
+
+static int
+il_apm_stop_master(struct il_priv *il)
+{
+       int ret = 0;
+
+       /* stop device's busmaster DMA activity */
+       il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+
+       ret =
+           _il_poll_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
+                        CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
+       if (ret)
+               IL_WARN("Master Disable Timed Out, 100 usec\n");
+
+       D_INFO("stop master\n");
+
+       return ret;
+}
+
+void
+il_apm_stop(struct il_priv *il)
+{
+       D_INFO("Stop card, put in low power state\n");
+
+       /* Stop device's DMA activity */
+       il_apm_stop_master(il);
+
+       /* Reset the entire device */
+       il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+
+       udelay(10);
+
+       /*
+        * Clear "initialization complete" bit to move adapter from
+        * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
+        */
+       il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+}
+EXPORT_SYMBOL(il_apm_stop);
+
+/*
+ * Start up NIC's basic functionality after it has been reset
+ * (e.g. after platform boot, or shutdown via il_apm_stop())
+ * NOTE:  This does not load uCode nor start the embedded processor
+ */
+int
+il_apm_init(struct il_priv *il)
+{
+       int ret = 0;
+       u16 lctl;
+
+       D_INFO("Init card's basic functions\n");
+
+       /*
+        * Use "set_bit" below rather than "write", to preserve any hardware
+        * bits already set by default after reset.
+        */
+
+       /* Disable L0S exit timer (platform NMI Work/Around) */
+       il_set_bit(il, CSR_GIO_CHICKEN_BITS,
+                  CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+
+       /*
+        * Disable L0s without affecting L1;
+        *  don't wait for ICH L0s (ICH bug W/A)
+        */
+       il_set_bit(il, CSR_GIO_CHICKEN_BITS,
+                  CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
+
+       /* Set FH wait threshold to maximum (HW error during stress W/A) */
+       il_set_bit(il, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);
+
+       /*
+        * Enable HAP INTA (interrupt from management bus) to
+        * wake device's PCI Express link L1a -> L0s
+        * NOTE:  This is no-op for 3945 (non-existent bit)
+        */
+       il_set_bit(il, CSR_HW_IF_CONFIG_REG,
+                  CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
+
+       /*
+        * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
+        * Check if BIOS (or OS) enabled L1-ASPM on this device.
+        * If so (likely), disable L0S, so device moves directly L0->L1;
+        *    costs negligible amount of power savings.
+        * If not (unlikely), enable L0S, so there is at least some
+        *    power savings, even without L1.
+        */
+       if (il->cfg->base_params->set_l0s) {
+               lctl = il_pcie_link_ctl(il);
+               if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
+                   PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+                       /* L1-ASPM enabled; disable(!) L0S  */
+                       il_set_bit(il, CSR_GIO_REG,
+                                  CSR_GIO_REG_VAL_L0S_ENABLED);
+                       D_POWER("L1 Enabled; Disabling L0S\n");
+               } else {
+                       /* L1-ASPM disabled; enable(!) L0S */
+                       il_clear_bit(il, CSR_GIO_REG,
+                                    CSR_GIO_REG_VAL_L0S_ENABLED);
+                       D_POWER("L1 Disabled; Enabling L0S\n");
+               }
+       }
+
+       /* Configure analog phase-lock-loop before activating to D0A */
+       if (il->cfg->base_params->pll_cfg_val)
+               il_set_bit(il, CSR_ANA_PLL_CFG,
+                          il->cfg->base_params->pll_cfg_val);
+
+       /*
+        * Set "initialization complete" bit to move adapter from
+        * D0U* --> D0A* (powered-up active) state.
+        */
+       il_set_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+       /*
+        * Wait for clock stabilization; once stabilized, access to
+        * device-internal resources is supported, e.g. il_wr_prph()
+        * and accesses to uCode SRAM.
+        */
+       ret =
+           _il_poll_bit(il, CSR_GP_CNTRL,
+                        CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+                        CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+       if (ret < 0) {
+               D_INFO("Failed to init the card\n");
+               goto out;
+       }
+
+       /*
+        * Enable DMA and BSM (if used) clocks, wait for them to stabilize.
+        * BSM (Boostrap State Machine) is only in 3945 and 4965.
+        *
+        * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
+        * do not disable clocks.  This preserves any hardware bits already
+        * set by default in "CLK_CTRL_REG" after reset.
+        */
+       if (il->cfg->base_params->use_bsm)
+               il_wr_prph(il, APMG_CLK_EN_REG,
+                          APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
+       else
+               il_wr_prph(il, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+       udelay(20);
+
+       /* Disable L1-Active */
+       il_set_bits_prph(il, APMG_PCIDEV_STT_REG,
+                        APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+
+out:
+       return ret;
+}
+EXPORT_SYMBOL(il_apm_init);
+
+int
+il_set_tx_power(struct il_priv *il, s8 tx_power, bool force)
+{
+       int ret;
+       s8 prev_tx_power;
+       bool defer;
+       struct il_rxon_context *ctx = &il->ctx;
+
+       lockdep_assert_held(&il->mutex);
+
+       if (il->tx_power_user_lmt == tx_power && !force)
+               return 0;
+
+       if (!il->cfg->ops->lib->send_tx_power)
+               return -EOPNOTSUPP;
+
+       /* 0 dBm mean 1 milliwatt */
+       if (tx_power < 0) {
+               IL_WARN("Requested user TXPOWER %d below 1 mW.\n", tx_power);
+               return -EINVAL;
+       }
+
+       if (tx_power > il->tx_power_device_lmt) {
+               IL_WARN("Requested user TXPOWER %d above upper limit %d.\n",
+                       tx_power, il->tx_power_device_lmt);
+               return -EINVAL;
+       }
+
+       if (!il_is_ready_rf(il))
+               return -EIO;
+
+       /* scan complete and commit_rxon use tx_power_next value,
+        * it always need to be updated for newest request */
+       il->tx_power_next = tx_power;
+
+       /* do not set tx power when scanning or channel changing */
+       defer = test_bit(S_SCANNING, &il->status) ||
+           memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
+       if (defer && !force) {
+               D_INFO("Deferring tx power set\n");
+               return 0;
+       }
+
+       prev_tx_power = il->tx_power_user_lmt;
+       il->tx_power_user_lmt = tx_power;
+
+       ret = il->cfg->ops->lib->send_tx_power(il);
+
+       /* if fail to set tx_power, restore the orig. tx power */
+       if (ret) {
+               il->tx_power_user_lmt = prev_tx_power;
+               il->tx_power_next = prev_tx_power;
+       }
+       return ret;
+}
+EXPORT_SYMBOL(il_set_tx_power);
+
+void
+il_send_bt_config(struct il_priv *il)
+{
+       struct il_bt_cmd bt_cmd = {
+               .lead_time = BT_LEAD_TIME_DEF,
+               .max_kill = BT_MAX_KILL_DEF,
+               .kill_ack_mask = 0,
+               .kill_cts_mask = 0,
+       };
+
+       if (!bt_coex_active)
+               bt_cmd.flags = BT_COEX_DISABLE;
+       else
+               bt_cmd.flags = BT_COEX_ENABLE;
+
+       D_INFO("BT coex %s\n",
+              (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
+
+       if (il_send_cmd_pdu(il, C_BT_CONFIG, sizeof(struct il_bt_cmd), &bt_cmd))
+               IL_ERR("failed to send BT Coex Config\n");
+}
+EXPORT_SYMBOL(il_send_bt_config);
+
+int
+il_send_stats_request(struct il_priv *il, u8 flags, bool clear)
+{
+       struct il_stats_cmd stats_cmd = {
+               .configuration_flags = clear ? IL_STATS_CONF_CLEAR_STATS : 0,
+       };
+
+       if (flags & CMD_ASYNC)
+               return il_send_cmd_pdu_async(il, C_STATS, sizeof(struct il_stats_cmd),
+                                            &stats_cmd, NULL);
+       else
+               return il_send_cmd_pdu(il, C_STATS, sizeof(struct il_stats_cmd),
+                                      &stats_cmd);
+}
+EXPORT_SYMBOL(il_send_stats_request);
+
+void
+il_hdl_pm_sleep(struct il_priv *il, struct il_rx_buf *rxb)
+{
+#ifdef CONFIG_IWLEGACY_DEBUG
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       struct il_sleep_notification *sleep = &(pkt->u.sleep_notif);
+       D_RX("sleep mode: %d, src: %d\n",
+            sleep->pm_sleep_mode, sleep->pm_wakeup_src);
+#endif
+}
+EXPORT_SYMBOL(il_hdl_pm_sleep);
+
+void
+il_hdl_pm_debug_stats(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+       u32 len = le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK;
+       D_RADIO("Dumping %d bytes of unhandled notification for %s:\n", len,
+               il_get_cmd_string(pkt->hdr.cmd));
+       il_print_hex_dump(il, IL_DL_RADIO, pkt->u.raw, len);
+}
+EXPORT_SYMBOL(il_hdl_pm_debug_stats);
+
+void
+il_hdl_error(struct il_priv *il, struct il_rx_buf *rxb)
+{
+       struct il_rx_pkt *pkt = rxb_addr(rxb);
+
+       IL_ERR("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),
+              il_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));
+}
+EXPORT_SYMBOL(il_hdl_error);
+
+void
+il_clear_isr_stats(struct il_priv *il)
+{
+       memset(&il->isr_stats, 0, sizeof(il->isr_stats));
+}
+
+int
+il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
+              const struct ieee80211_tx_queue_params *params)
+{
+       struct il_priv *il = hw->priv;
+       unsigned long flags;
+       int q;
+
+       D_MAC80211("enter\n");
+
+       if (!il_is_ready_rf(il)) {
+               D_MAC80211("leave - RF not ready\n");
+               return -EIO;
+       }
+
+       if (queue >= AC_NUM) {
+               D_MAC80211("leave - queue >= AC_NUM %d\n", queue);
+               return 0;
+       }
+
+       q = AC_NUM - 1 - queue;
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       il->ctx.qos_data.def_qos_parm.ac[q].cw_min =
+           cpu_to_le16(params->cw_min);
+       il->ctx.qos_data.def_qos_parm.ac[q].cw_max =
+           cpu_to_le16(params->cw_max);
+       il->ctx.qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
+       il->ctx.qos_data.def_qos_parm.ac[q].edca_txop =
+           cpu_to_le16((params->txop * 32));
+
+       il->ctx.qos_data.def_qos_parm.ac[q].reserved1 = 0;
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       D_MAC80211("leave\n");
+       return 0;
+}
+EXPORT_SYMBOL(il_mac_conf_tx);
+
+int
+il_mac_tx_last_beacon(struct ieee80211_hw *hw)
+{
+       struct il_priv *il = hw->priv;
+
+       return il->ibss_manager == IL_IBSS_MANAGER;
+}
+EXPORT_SYMBOL_GPL(il_mac_tx_last_beacon);
+
+static int
+il_set_mode(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       il_connection_init_rx_config(il, ctx);
+
+       if (il->cfg->ops->hcmd->set_rxon_chain)
+               il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
+
+       return il_commit_rxon(il, ctx);
+}
+
+static int
+il_setup_interface(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       struct ieee80211_vif *vif = ctx->vif;
+       int err;
+
+       lockdep_assert_held(&il->mutex);
+
+       /*
+        * This variable will be correct only when there's just
+        * a single context, but all code using it is for hardware
+        * that supports only one context.
+        */
+       il->iw_mode = vif->type;
+
+       ctx->is_active = true;
+
+       err = il_set_mode(il, ctx);
+       if (err) {
+               if (!ctx->always_active)
+                       ctx->is_active = false;
+               return err;
+       }
+
+       return 0;
+}
+
+int
+il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct il_priv *il = hw->priv;
+       struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
+       int err;
+       u32 modes;
+
+       D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr);
+
+       mutex_lock(&il->mutex);
+
+       if (!il_is_ready_rf(il)) {
+               IL_WARN("Try to add interface when device not ready\n");
+               err = -EINVAL;
+               goto out;
+       }
+
+       /* check if busy context is exclusive */
+       if (il->ctx.vif &&
+           (il->ctx.exclusive_interface_modes & BIT(il->ctx.vif->type))) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       modes = il->ctx.interface_modes | il->ctx.exclusive_interface_modes;
+       if (!(modes & BIT(vif->type))) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
+       vif_priv->ctx = &il->ctx;
+       il->ctx.vif = vif;
+
+       err = il_setup_interface(il, &il->ctx);
+       if (err) {
+               il->ctx.vif = NULL;
+               il->iw_mode = NL80211_IFTYPE_STATION;
+       }
+
+out:
+       mutex_unlock(&il->mutex);
+
+       D_MAC80211("leave\n");
+       return err;
+}
+EXPORT_SYMBOL(il_mac_add_interface);
+
+static void
+il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif,
+                     bool mode_change)
+{
+       struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
+
+       lockdep_assert_held(&il->mutex);
+
+       if (il->scan_vif == vif) {
+               il_scan_cancel_timeout(il, 200);
+               il_force_scan_end(il);
+       }
+
+       if (!mode_change) {
+               il_set_mode(il, ctx);
+               if (!ctx->always_active)
+                       ctx->is_active = false;
+       }
+}
+
+void
+il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct il_priv *il = hw->priv;
+       struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
+
+       D_MAC80211("enter\n");
+
+       mutex_lock(&il->mutex);
+
+       WARN_ON(ctx->vif != vif);
+       ctx->vif = NULL;
+
+       il_teardown_interface(il, vif, false);
+
+       memset(il->bssid, 0, ETH_ALEN);
+       mutex_unlock(&il->mutex);
+
+       D_MAC80211("leave\n");
+
+}
+EXPORT_SYMBOL(il_mac_remove_interface);
+
+int
+il_alloc_txq_mem(struct il_priv *il)
+{
+       if (!il->txq)
+               il->txq =
+                   kzalloc(sizeof(struct il_tx_queue) *
+                           il->cfg->base_params->num_of_queues, GFP_KERNEL);
+       if (!il->txq) {
+               IL_ERR("Not enough memory for txq\n");
+               return -ENOMEM;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(il_alloc_txq_mem);
+
+void
+il_txq_mem(struct il_priv *il)
+{
+       kfree(il->txq);
+       il->txq = NULL;
+}
+EXPORT_SYMBOL(il_txq_mem);
+
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+
+#define IL_TRAFFIC_DUMP_SIZE   (IL_TRAFFIC_ENTRY_SIZE * IL_TRAFFIC_ENTRIES)
+
+void
+il_reset_traffic_log(struct il_priv *il)
+{
+       il->tx_traffic_idx = 0;
+       il->rx_traffic_idx = 0;
+       if (il->tx_traffic)
+               memset(il->tx_traffic, 0, IL_TRAFFIC_DUMP_SIZE);
+       if (il->rx_traffic)
+               memset(il->rx_traffic, 0, IL_TRAFFIC_DUMP_SIZE);
+}
+
+int
+il_alloc_traffic_mem(struct il_priv *il)
+{
+       u32 traffic_size = IL_TRAFFIC_DUMP_SIZE;
+
+       if (il_debug_level & IL_DL_TX) {
+               if (!il->tx_traffic) {
+                       il->tx_traffic = kzalloc(traffic_size, GFP_KERNEL);
+                       if (!il->tx_traffic)
+                               return -ENOMEM;
+               }
+       }
+       if (il_debug_level & IL_DL_RX) {
+               if (!il->rx_traffic) {
+                       il->rx_traffic = kzalloc(traffic_size, GFP_KERNEL);
+                       if (!il->rx_traffic)
+                               return -ENOMEM;
+               }
+       }
+       il_reset_traffic_log(il);
+       return 0;
+}
+EXPORT_SYMBOL(il_alloc_traffic_mem);
+
+void
+il_free_traffic_mem(struct il_priv *il)
+{
+       kfree(il->tx_traffic);
+       il->tx_traffic = NULL;
+
+       kfree(il->rx_traffic);
+       il->rx_traffic = NULL;
+}
+EXPORT_SYMBOL(il_free_traffic_mem);
+
+void
+il_dbg_log_tx_data_frame(struct il_priv *il, u16 length,
+                        struct ieee80211_hdr *header)
+{
+       __le16 fc;
+       u16 len;
+
+       if (likely(!(il_debug_level & IL_DL_TX)))
+               return;
+
+       if (!il->tx_traffic)
+               return;
+
+       fc = header->frame_control;
+       if (ieee80211_is_data(fc)) {
+               len =
+                   (length >
+                    IL_TRAFFIC_ENTRY_SIZE) ? IL_TRAFFIC_ENTRY_SIZE : length;
+               memcpy((il->tx_traffic +
+                       (il->tx_traffic_idx * IL_TRAFFIC_ENTRY_SIZE)), header,
+                      len);
+               il->tx_traffic_idx =
+                   (il->tx_traffic_idx + 1) % IL_TRAFFIC_ENTRIES;
+       }
+}
+EXPORT_SYMBOL(il_dbg_log_tx_data_frame);
+
+void
+il_dbg_log_rx_data_frame(struct il_priv *il, u16 length,
+                        struct ieee80211_hdr *header)
+{
+       __le16 fc;
+       u16 len;
+
+       if (likely(!(il_debug_level & IL_DL_RX)))
+               return;
+
+       if (!il->rx_traffic)
+               return;
+
+       fc = header->frame_control;
+       if (ieee80211_is_data(fc)) {
+               len =
+                   (length >
+                    IL_TRAFFIC_ENTRY_SIZE) ? IL_TRAFFIC_ENTRY_SIZE : length;
+               memcpy((il->rx_traffic +
+                       (il->rx_traffic_idx * IL_TRAFFIC_ENTRY_SIZE)), header,
+                      len);
+               il->rx_traffic_idx =
+                   (il->rx_traffic_idx + 1) % IL_TRAFFIC_ENTRIES;
+       }
+}
+EXPORT_SYMBOL(il_dbg_log_rx_data_frame);
+
+const char *
+il_get_mgmt_string(int cmd)
+{
+       switch (cmd) {
+               IL_CMD(MANAGEMENT_ASSOC_REQ);
+               IL_CMD(MANAGEMENT_ASSOC_RESP);
+               IL_CMD(MANAGEMENT_REASSOC_REQ);
+               IL_CMD(MANAGEMENT_REASSOC_RESP);
+               IL_CMD(MANAGEMENT_PROBE_REQ);
+               IL_CMD(MANAGEMENT_PROBE_RESP);
+               IL_CMD(MANAGEMENT_BEACON);
+               IL_CMD(MANAGEMENT_ATIM);
+               IL_CMD(MANAGEMENT_DISASSOC);
+               IL_CMD(MANAGEMENT_AUTH);
+               IL_CMD(MANAGEMENT_DEAUTH);
+               IL_CMD(MANAGEMENT_ACTION);
+       default:
+               return "UNKNOWN";
+
+       }
+}
+
+const char *
+il_get_ctrl_string(int cmd)
+{
+       switch (cmd) {
+               IL_CMD(CONTROL_BACK_REQ);
+               IL_CMD(CONTROL_BACK);
+               IL_CMD(CONTROL_PSPOLL);
+               IL_CMD(CONTROL_RTS);
+               IL_CMD(CONTROL_CTS);
+               IL_CMD(CONTROL_ACK);
+               IL_CMD(CONTROL_CFEND);
+               IL_CMD(CONTROL_CFENDACK);
+       default:
+               return "UNKNOWN";
+
+       }
+}
+
+void
+il_clear_traffic_stats(struct il_priv *il)
+{
+       memset(&il->tx_stats, 0, sizeof(struct traffic_stats));
+       memset(&il->rx_stats, 0, sizeof(struct traffic_stats));
+}
+
+/*
+ * if CONFIG_IWLEGACY_DEBUGFS defined,
+ * il_update_stats function will
+ * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass
+ * Use debugFs to display the rx/rx_stats
+ * if CONFIG_IWLEGACY_DEBUGFS not being defined, then no MGMT and CTRL
+ * information will be recorded, but DATA pkt still will be recorded
+ * for the reason of il_led.c need to control the led blinking based on
+ * number of tx and rx data.
+ *
+ */
+void
+il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len)
+{
+       struct traffic_stats *stats;
+
+       if (is_tx)
+               stats = &il->tx_stats;
+       else
+               stats = &il->rx_stats;
+
+       if (ieee80211_is_mgmt(fc)) {
+               switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+               case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+                       stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
+                       stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+                       stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
+                       stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
+                       stats->mgmt[MANAGEMENT_PROBE_REQ]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+                       stats->mgmt[MANAGEMENT_PROBE_RESP]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_BEACON):
+                       stats->mgmt[MANAGEMENT_BEACON]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_ATIM):
+                       stats->mgmt[MANAGEMENT_ATIM]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+                       stats->mgmt[MANAGEMENT_DISASSOC]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_AUTH):
+                       stats->mgmt[MANAGEMENT_AUTH]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+                       stats->mgmt[MANAGEMENT_DEAUTH]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_ACTION):
+                       stats->mgmt[MANAGEMENT_ACTION]++;
+                       break;
+               }
+       } else if (ieee80211_is_ctl(fc)) {
+               switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+               case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
+                       stats->ctrl[CONTROL_BACK_REQ]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_BACK):
+                       stats->ctrl[CONTROL_BACK]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
+                       stats->ctrl[CONTROL_PSPOLL]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_RTS):
+                       stats->ctrl[CONTROL_RTS]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_CTS):
+                       stats->ctrl[CONTROL_CTS]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_ACK):
+                       stats->ctrl[CONTROL_ACK]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_CFEND):
+                       stats->ctrl[CONTROL_CFEND]++;
+                       break;
+               case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
+                       stats->ctrl[CONTROL_CFENDACK]++;
+                       break;
+               }
+       } else {
+               /* data */
+               stats->data_cnt++;
+               stats->data_bytes += len;
+       }
+}
+EXPORT_SYMBOL(il_update_stats);
+#endif
+
+int
+il_force_reset(struct il_priv *il, bool external)
+{
+       struct il_force_reset *force_reset;
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return -EINVAL;
+
+       force_reset = &il->force_reset;
+       force_reset->reset_request_count++;
+       if (!external) {
+               if (force_reset->last_force_reset_jiffies &&
+                   time_after(force_reset->last_force_reset_jiffies +
+                              force_reset->reset_duration, jiffies)) {
+                       D_INFO("force reset rejected\n");
+                       force_reset->reset_reject_count++;
+                       return -EAGAIN;
+               }
+       }
+       force_reset->reset_success_count++;
+       force_reset->last_force_reset_jiffies = jiffies;
+
+       /*
+        * if the request is from external(ex: debugfs),
+        * then always perform the request in regardless the module
+        * parameter setting
+        * if the request is from internal (uCode error or driver
+        * detect failure), then fw_restart module parameter
+        * need to be check before performing firmware reload
+        */
+
+       if (!external && !il->cfg->mod_params->restart_fw) {
+               D_INFO("Cancel firmware reload based on "
+                      "module parameter setting\n");
+               return 0;
+       }
+
+       IL_ERR("On demand firmware reload\n");
+
+       /* Set the FW error flag -- cleared on il_down */
+       set_bit(S_FW_ERROR, &il->status);
+       wake_up(&il->wait_command_queue);
+       /*
+        * Keep the restart process from trying to send host
+        * commands by clearing the INIT status bit
+        */
+       clear_bit(S_READY, &il->status);
+       queue_work(il->workqueue, &il->restart);
+
+       return 0;
+}
+
+int
+il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                       enum nl80211_iftype newtype, bool newp2p)
+{
+       struct il_priv *il = hw->priv;
+       struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
+       u32 modes;
+       int err;
+
+       newtype = ieee80211_iftype_p2p(newtype, newp2p);
+
+       mutex_lock(&il->mutex);
+
+       if (!ctx->vif || !il_is_ready_rf(il)) {
+               /*
+                * Huh? But wait ... this can maybe happen when
+                * we're in the middle of a firmware restart!
+                */
+               err = -EBUSY;
+               goto out;
+       }
+
+       modes = ctx->interface_modes | ctx->exclusive_interface_modes;
+       if (!(modes & BIT(newtype))) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
+       if ((il->ctx.exclusive_interface_modes & BIT(il->ctx.vif->type)) ||
+           (il->ctx.exclusive_interface_modes & BIT(newtype))) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       /* success */
+       il_teardown_interface(il, vif, true);
+       vif->type = newtype;
+       vif->p2p = newp2p;
+       err = il_setup_interface(il, ctx);
+       WARN_ON(err);
+       /*
+        * We've switched internally, but submitting to the
+        * device may have failed for some reason. Mask this
+        * error, because otherwise mac80211 will not switch
+        * (and set the interface type back) and we'll be
+        * out of sync with it.
+        */
+       err = 0;
+
+out:
+       mutex_unlock(&il->mutex);
+       return err;
+}
+EXPORT_SYMBOL(il_mac_change_interface);
+
+/*
+ * On every watchdog tick we check (latest) time stamp. If it does not
+ * change during timeout period and queue is not empty we reset firmware.
+ */
+static int
+il_check_stuck_queue(struct il_priv *il, int cnt)
+{
+       struct il_tx_queue *txq = &il->txq[cnt];
+       struct il_queue *q = &txq->q;
+       unsigned long timeout;
+       int ret;
+
+       if (q->read_ptr == q->write_ptr) {
+               txq->time_stamp = jiffies;
+               return 0;
+       }
+
+       timeout =
+           txq->time_stamp +
+           msecs_to_jiffies(il->cfg->base_params->wd_timeout);
+
+       if (time_after(jiffies, timeout)) {
+               IL_ERR("Queue %d stuck for %u ms.\n", q->id,
+                      il->cfg->base_params->wd_timeout);
+               ret = il_force_reset(il, false);
+               return (ret == -EAGAIN) ? 0 : 1;
+       }
+
+       return 0;
+}
+
+/*
+ * Making watchdog tick be a quarter of timeout assure we will
+ * discover the queue hung between timeout and 1.25*timeout
+ */
+#define IL_WD_TICK(timeout) ((timeout) / 4)
+
+/*
+ * Watchdog timer callback, we check each tx queue for stuck, if if hung
+ * we reset the firmware. If everything is fine just rearm the timer.
+ */
+void
+il_bg_watchdog(unsigned long data)
+{
+       struct il_priv *il = (struct il_priv *)data;
+       int cnt;
+       unsigned long timeout;
+
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       timeout = il->cfg->base_params->wd_timeout;
+       if (timeout == 0)
+               return;
+
+       /* monitor and check for stuck cmd queue */
+       if (il_check_stuck_queue(il, il->cmd_queue))
+               return;
+
+       /* monitor and check for other stuck queues */
+       if (il_is_any_associated(il)) {
+               for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
+                       /* skip as we already checked the command queue */
+                       if (cnt == il->cmd_queue)
+                               continue;
+                       if (il_check_stuck_queue(il, cnt))
+                               return;
+               }
+       }
+
+       mod_timer(&il->watchdog,
+                 jiffies + msecs_to_jiffies(IL_WD_TICK(timeout)));
+}
+EXPORT_SYMBOL(il_bg_watchdog);
+
+void
+il_setup_watchdog(struct il_priv *il)
+{
+       unsigned int timeout = il->cfg->base_params->wd_timeout;
+
+       if (timeout)
+               mod_timer(&il->watchdog,
+                         jiffies + msecs_to_jiffies(IL_WD_TICK(timeout)));
+       else
+               del_timer(&il->watchdog);
+}
+EXPORT_SYMBOL(il_setup_watchdog);
+
+/*
+ * extended beacon time format
+ * time in usec will be changed into a 32-bit value in extended:internal format
+ * the extended part is the beacon counts
+ * the internal part is the time in usec within one beacon interval
+ */
+u32
+il_usecs_to_beacons(struct il_priv *il, u32 usec, u32 beacon_interval)
+{
+       u32 quot;
+       u32 rem;
+       u32 interval = beacon_interval * TIME_UNIT;
+
+       if (!interval || !usec)
+               return 0;
+
+       quot =
+           (usec /
+            interval) & (il_beacon_time_mask_high(il,
+                                                  il->hw_params.
+                                                  beacon_time_tsf_bits) >> il->
+                         hw_params.beacon_time_tsf_bits);
+       rem =
+           (usec % interval) & il_beacon_time_mask_low(il,
+                                                       il->hw_params.
+                                                       beacon_time_tsf_bits);
+
+       return (quot << il->hw_params.beacon_time_tsf_bits) + rem;
+}
+EXPORT_SYMBOL(il_usecs_to_beacons);
+
+/* base is usually what we get from ucode with each received frame,
+ * the same as HW timer counter counting down
+ */
+__le32
+il_add_beacon_time(struct il_priv *il, u32 base, u32 addon,
+                  u32 beacon_interval)
+{
+       u32 base_low = base & il_beacon_time_mask_low(il,
+                                                     il->hw_params.
+                                                     beacon_time_tsf_bits);
+       u32 addon_low = addon & il_beacon_time_mask_low(il,
+                                                       il->hw_params.
+                                                       beacon_time_tsf_bits);
+       u32 interval = beacon_interval * TIME_UNIT;
+       u32 res = (base & il_beacon_time_mask_high(il,
+                                                  il->hw_params.
+                                                  beacon_time_tsf_bits)) +
+           (addon & il_beacon_time_mask_high(il,
+                                             il->hw_params.
+                                             beacon_time_tsf_bits));
+
+       if (base_low > addon_low)
+               res += base_low - addon_low;
+       else if (base_low < addon_low) {
+               res += interval + base_low - addon_low;
+               res += (1 << il->hw_params.beacon_time_tsf_bits);
+       } else
+               res += (1 << il->hw_params.beacon_time_tsf_bits);
+
+       return cpu_to_le32(res);
+}
+EXPORT_SYMBOL(il_add_beacon_time);
+
+#ifdef CONFIG_PM
+
+int
+il_pci_suspend(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct il_priv *il = pci_get_drvdata(pdev);
+
+       /*
+        * This function is called when system goes into suspend state
+        * mac80211 will call il_mac_stop() from the mac80211 suspend function
+        * first but since il_mac_stop() has no knowledge of who the caller is,
+        * it will not call apm_ops.stop() to stop the DMA operation.
+        * Calling apm_ops.stop here to make sure we stop the DMA.
+        */
+       il_apm_stop(il);
+
+       return 0;
+}
+EXPORT_SYMBOL(il_pci_suspend);
+
+int
+il_pci_resume(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct il_priv *il = pci_get_drvdata(pdev);
+       bool hw_rfkill = false;
+
+       /*
+        * We disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state.
+        */
+       pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+       il_enable_interrupts(il);
+
+       if (!(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+               hw_rfkill = true;
+
+       if (hw_rfkill)
+               set_bit(S_RF_KILL_HW, &il->status);
+       else
+               clear_bit(S_RF_KILL_HW, &il->status);
+
+       wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rfkill);
+
+       return 0;
+}
+EXPORT_SYMBOL(il_pci_resume);
+
+const struct dev_pm_ops il_pm_ops = {
+       .suspend = il_pci_suspend,
+       .resume = il_pci_resume,
+       .freeze = il_pci_suspend,
+       .thaw = il_pci_resume,
+       .poweroff = il_pci_suspend,
+       .restore = il_pci_resume,
+};
+EXPORT_SYMBOL(il_pm_ops);
+
+#endif /* CONFIG_PM */
+
+static void
+il_update_qos(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       if (test_bit(S_EXIT_PENDING, &il->status))
+               return;
+
+       if (!ctx->is_active)
+               return;
+
+       ctx->qos_data.def_qos_parm.qos_flags = 0;
+
+       if (ctx->qos_data.qos_active)
+               ctx->qos_data.def_qos_parm.qos_flags |=
+                   QOS_PARAM_FLG_UPDATE_EDCA_MSK;
+
+       if (ctx->ht.enabled)
+               ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
+
+       D_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+             ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags);
+
+       il_send_cmd_pdu_async(il, ctx->qos_cmd, sizeof(struct il_qosparam_cmd),
+                             &ctx->qos_data.def_qos_parm, NULL);
+}
+
+/**
+ * il_mac_config - mac80211 config callback
+ */
+int
+il_mac_config(struct ieee80211_hw *hw, u32 changed)
+{
+       struct il_priv *il = hw->priv;
+       const struct il_channel_info *ch_info;
+       struct ieee80211_conf *conf = &hw->conf;
+       struct ieee80211_channel *channel = conf->channel;
+       struct il_ht_config *ht_conf = &il->current_ht_config;
+       struct il_rxon_context *ctx = &il->ctx;
+       unsigned long flags = 0;
+       int ret = 0;
+       u16 ch;
+       int scan_active = 0;
+       bool ht_changed = false;
+
+       if (WARN_ON(!il->cfg->ops->legacy))
+               return -EOPNOTSUPP;
+
+       mutex_lock(&il->mutex);
+
+       D_MAC80211("enter to channel %d changed 0x%X\n", channel->hw_value,
+                  changed);
+
+       if (unlikely(test_bit(S_SCANNING, &il->status))) {
+               scan_active = 1;
+               D_MAC80211("scan active\n");
+       }
+
+       if (changed &
+           (IEEE80211_CONF_CHANGE_SMPS | IEEE80211_CONF_CHANGE_CHANNEL)) {
+               /* mac80211 uses static for non-HT which is what we want */
+               il->current_ht_config.smps = conf->smps_mode;
+
+               /*
+                * Recalculate chain counts.
+                *
+                * If monitor mode is enabled then mac80211 will
+                * set up the SM PS mode to OFF if an HT channel is
+                * configured.
+                */
+               if (il->cfg->ops->hcmd->set_rxon_chain)
+                       il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx);
+       }
+
+       /* during scanning mac80211 will delay channel setting until
+        * scan finish with changed = 0
+        */
+       if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
+
+               if (scan_active)
+                       goto set_ch_out;
+
+               ch = channel->hw_value;
+               ch_info = il_get_channel_info(il, channel->band, ch);
+               if (!il_is_channel_valid(ch_info)) {
+                       D_MAC80211("leave - invalid channel\n");
+                       ret = -EINVAL;
+                       goto set_ch_out;
+               }
+
+               if (il->iw_mode == NL80211_IFTYPE_ADHOC &&
+                   !il_is_channel_ibss(ch_info)) {
+                       D_MAC80211("leave - not IBSS channel\n");
+                       ret = -EINVAL;
+                       goto set_ch_out;
+               }
+
+               spin_lock_irqsave(&il->lock, flags);
+
+               /* Configure HT40 channels */
+               if (ctx->ht.enabled != conf_is_ht(conf)) {
+                       ctx->ht.enabled = conf_is_ht(conf);
+                       ht_changed = true;
+               }
+               if (ctx->ht.enabled) {
+                       if (conf_is_ht40_minus(conf)) {
+                               ctx->ht.extension_chan_offset =
+                                   IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+                               ctx->ht.is_40mhz = true;
+                       } else if (conf_is_ht40_plus(conf)) {
+                               ctx->ht.extension_chan_offset =
+                                   IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+                               ctx->ht.is_40mhz = true;
+                       } else {
+                               ctx->ht.extension_chan_offset =
+                                   IEEE80211_HT_PARAM_CHA_SEC_NONE;
+                               ctx->ht.is_40mhz = false;
+                       }
+               } else
+                       ctx->ht.is_40mhz = false;
+
+               /*
+                * Default to no protection. Protection mode will
+                * later be set from BSS config in il_ht_conf
+                */
+               ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
+
+               /* if we are switching from ht to 2.4 clear flags
+                * from any ht related info since 2.4 does not
+                * support ht */
+               if ((le16_to_cpu(ctx->staging.channel) != ch))
+                       ctx->staging.flags = 0;
+
+               il_set_rxon_channel(il, channel, ctx);
+               il_set_rxon_ht(il, ht_conf);
+
+               il_set_flags_for_band(il, ctx, channel->band, ctx->vif);
+
+               spin_unlock_irqrestore(&il->lock, flags);
+
+               if (il->cfg->ops->legacy->update_bcast_stations)
+                       ret = il->cfg->ops->legacy->update_bcast_stations(il);
+
+set_ch_out:
+               /* The list of supported rates and rate mask can be different
+                * for each band; since the band may have changed, reset
+                * the rate mask to what mac80211 lists */
+               il_set_rate(il);
+       }
+
+       if (changed & (IEEE80211_CONF_CHANGE_PS | IEEE80211_CONF_CHANGE_IDLE)) {
+               ret = il_power_update_mode(il, false);
+               if (ret)
+                       D_MAC80211("Error setting sleep level\n");
+       }
+
+       if (changed & IEEE80211_CONF_CHANGE_POWER) {
+               D_MAC80211("TX Power old=%d new=%d\n", il->tx_power_user_lmt,
+                          conf->power_level);
+
+               il_set_tx_power(il, conf->power_level, false);
+       }
+
+       if (!il_is_ready(il)) {
+               D_MAC80211("leave - not ready\n");
+               goto out;
+       }
+
+       if (scan_active)
+               goto out;
+
+       if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
+               il_commit_rxon(il, ctx);
+       else
+               D_INFO("Not re-sending same RXON configuration.\n");
+       if (ht_changed)
+               il_update_qos(il, ctx);
+
+out:
+       D_MAC80211("leave\n");
+       mutex_unlock(&il->mutex);
+       return ret;
+}
+EXPORT_SYMBOL(il_mac_config);
+
+void
+il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct il_priv *il = hw->priv;
+       unsigned long flags;
+       struct il_rxon_context *ctx = &il->ctx;
+
+       if (WARN_ON(!il->cfg->ops->legacy))
+               return;
+
+       mutex_lock(&il->mutex);
+       D_MAC80211("enter\n");
+
+       spin_lock_irqsave(&il->lock, flags);
+       memset(&il->current_ht_config, 0, sizeof(struct il_ht_config));
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       /* new association get rid of ibss beacon skb */
+       if (il->beacon_skb)
+               dev_kfree_skb(il->beacon_skb);
+
+       il->beacon_skb = NULL;
+
+       il->timestamp = 0;
+
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       il_scan_cancel_timeout(il, 100);
+       if (!il_is_ready_rf(il)) {
+               D_MAC80211("leave - not ready\n");
+               mutex_unlock(&il->mutex);
+               return;
+       }
+
+       /* we are restarting association process
+        * clear RXON_FILTER_ASSOC_MSK bit
+        */
+       ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+       il_commit_rxon(il, ctx);
+
+       il_set_rate(il);
+
+       mutex_unlock(&il->mutex);
+
+       D_MAC80211("leave\n");
+}
+EXPORT_SYMBOL(il_mac_reset_tsf);
+
+static void
+il_ht_conf(struct il_priv *il, struct ieee80211_vif *vif)
+{
+       struct il_ht_config *ht_conf = &il->current_ht_config;
+       struct ieee80211_sta *sta;
+       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+       struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
+
+       D_ASSOC("enter:\n");
+
+       if (!ctx->ht.enabled)
+               return;
+
+       ctx->ht.protection =
+           bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
+       ctx->ht.non_gf_sta_present =
+           !!(bss_conf->
+              ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+
+       ht_conf->single_chain_sufficient = false;
+
+       switch (vif->type) {
+       case NL80211_IFTYPE_STATION:
+               rcu_read_lock();
+               sta = ieee80211_find_sta(vif, bss_conf->bssid);
+               if (sta) {
+                       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+                       int maxstreams;
+
+                       maxstreams =
+                           (ht_cap->mcs.
+                            tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+                           >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+                       maxstreams += 1;
+
+                       if (ht_cap->mcs.rx_mask[1] == 0 &&
+                           ht_cap->mcs.rx_mask[2] == 0)
+                               ht_conf->single_chain_sufficient = true;
+                       if (maxstreams <= 1)
+                               ht_conf->single_chain_sufficient = true;
+               } else {
+                       /*
+                        * If at all, this can only happen through a race
+                        * when the AP disconnects us while we're still
+                        * setting up the connection, in that case mac80211
+                        * will soon tell us about that.
+                        */
+                       ht_conf->single_chain_sufficient = true;
+               }
+               rcu_read_unlock();
+               break;
+       case NL80211_IFTYPE_ADHOC:
+               ht_conf->single_chain_sufficient = true;
+               break;
+       default:
+               break;
+       }
+
+       D_ASSOC("leave\n");
+}
+
+static inline void
+il_set_no_assoc(struct il_priv *il, struct ieee80211_vif *vif)
+{
+       struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
+
+       /*
+        * inform the ucode that there is no longer an
+        * association and that no more packets should be
+        * sent
+        */
+       ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+       ctx->staging.assoc_id = 0;
+       il_commit_rxon(il, ctx);
+}
+
+static void
+il_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct il_priv *il = hw->priv;
+       unsigned long flags;
+       __le64 timestamp;
+       struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
+
+       if (!skb)
+               return;
+
+       D_MAC80211("enter\n");
+
+       lockdep_assert_held(&il->mutex);
+
+       if (!il->beacon_ctx) {
+               IL_ERR("update beacon but no beacon context!\n");
+               dev_kfree_skb(skb);
+               return;
+       }
+
+       spin_lock_irqsave(&il->lock, flags);
+
+       if (il->beacon_skb)
+               dev_kfree_skb(il->beacon_skb);
+
+       il->beacon_skb = skb;
+
+       timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+       il->timestamp = le64_to_cpu(timestamp);
+
+       D_MAC80211("leave\n");
+       spin_unlock_irqrestore(&il->lock, flags);
+
+       if (!il_is_ready_rf(il)) {
+               D_MAC80211("leave - RF not ready\n");
+               return;
+       }
+
+       il->cfg->ops->legacy->post_associate(il);
+}
+
+void
+il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                       struct ieee80211_bss_conf *bss_conf, u32 changes)
+{
+       struct il_priv *il = hw->priv;
+       struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
+       int ret;
+
+       if (WARN_ON(!il->cfg->ops->legacy))
+               return;
+
+       D_MAC80211("changes = 0x%X\n", changes);
+
+       mutex_lock(&il->mutex);
+
+       if (!il_is_alive(il)) {
+               mutex_unlock(&il->mutex);
+               return;
+       }
+
+       if (changes & BSS_CHANGED_QOS) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&il->lock, flags);
+               ctx->qos_data.qos_active = bss_conf->qos;
+               il_update_qos(il, ctx);
+               spin_unlock_irqrestore(&il->lock, flags);
+       }
+
+       if (changes & BSS_CHANGED_BEACON_ENABLED) {
+               /*
+                * the add_interface code must make sure we only ever
+                * have a single interface that could be beaconing at
+                * any time.
+                */
+               if (vif->bss_conf.enable_beacon)
+                       il->beacon_ctx = ctx;
+               else
+                       il->beacon_ctx = NULL;
+       }
+
+       if (changes & BSS_CHANGED_BSSID) {
+               D_MAC80211("BSSID %pM\n", bss_conf->bssid);
+
+               /*
+                * If there is currently a HW scan going on in the
+                * background then we need to cancel it else the RXON
+                * below/in post_associate will fail.
+                */
+               if (il_scan_cancel_timeout(il, 100)) {
+                       IL_WARN("Aborted scan still in progress after 100ms\n");
+                       D_MAC80211("leaving - scan abort failed.\n");
+                       mutex_unlock(&il->mutex);
+                       return;
+               }
+
+               /* mac80211 only sets assoc when in STATION mode */
+               if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
+                       memcpy(ctx->staging.bssid_addr, bss_conf->bssid,
+                              ETH_ALEN);
+
+                       /* currently needed in a few places */
+                       memcpy(il->bssid, bss_conf->bssid, ETH_ALEN);
+               } else {
+                       ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+               }
+
+       }
+
+       /*
+        * This needs to be after setting the BSSID in case
+        * mac80211 decides to do both changes at once because
+        * it will invoke post_associate.
+        */
+       if (vif->type == NL80211_IFTYPE_ADHOC && (changes & BSS_CHANGED_BEACON))
+               il_beacon_update(hw, vif);
+
+       if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+               D_MAC80211("ERP_PREAMBLE %d\n", bss_conf->use_short_preamble);
+               if (bss_conf->use_short_preamble)
+                       ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+               else
+                       ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+       }
+
+       if (changes & BSS_CHANGED_ERP_CTS_PROT) {
+               D_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot);
+               if (bss_conf->use_cts_prot && il->band != IEEE80211_BAND_5GHZ)
+                       ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
+               else
+                       ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+               if (bss_conf->use_cts_prot)
+                       ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+               else
+                       ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
+       }
+
+       if (changes & BSS_CHANGED_BASIC_RATES) {
+               /* XXX use this information
+                *
+                * To do that, remove code from il_set_rate() and put something
+                * like this here:
+                *
+                if (A-band)
+                ctx->staging.ofdm_basic_rates =
+                bss_conf->basic_rates;
+                else
+                ctx->staging.ofdm_basic_rates =
+                bss_conf->basic_rates >> 4;
+                ctx->staging.cck_basic_rates =
+                bss_conf->basic_rates & 0xF;
+                */
+       }
+
+       if (changes & BSS_CHANGED_HT) {
+               il_ht_conf(il, vif);
+
+               if (il->cfg->ops->hcmd->set_rxon_chain)
+                       il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
+       }
+
+       if (changes & BSS_CHANGED_ASSOC) {
+               D_MAC80211("ASSOC %d\n", bss_conf->assoc);
+               if (bss_conf->assoc) {
+                       il->timestamp = bss_conf->timestamp;
+
+                       if (!il_is_rfkill(il))
+                               il->cfg->ops->legacy->post_associate(il);
+               } else
+                       il_set_no_assoc(il, vif);
+       }
+
+       if (changes && il_is_associated_ctx(ctx) && bss_conf->aid) {
+               D_MAC80211("Changes (%#x) while associated\n", changes);
+               ret = il_send_rxon_assoc(il, ctx);
+               if (!ret) {
+                       /* Sync active_rxon with latest change. */
+                       memcpy((void *)&ctx->active, &ctx->staging,
+                              sizeof(struct il_rxon_cmd));
+               }
+       }
+
+       if (changes & BSS_CHANGED_BEACON_ENABLED) {
+               if (vif->bss_conf.enable_beacon) {
+                       memcpy(ctx->staging.bssid_addr, bss_conf->bssid,
+                              ETH_ALEN);
+                       memcpy(il->bssid, bss_conf->bssid, ETH_ALEN);
+                       il->cfg->ops->legacy->config_ap(il);
+               } else
+                       il_set_no_assoc(il, vif);
+       }
+
+       if (changes & BSS_CHANGED_IBSS) {
+               ret =
+                   il->cfg->ops->legacy->manage_ibss_station(il, vif,
+                                                             bss_conf->
+                                                             ibss_joined);
+               if (ret)
+                       IL_ERR("failed to %s IBSS station %pM\n",
+                              bss_conf->ibss_joined ? "add" : "remove",
+                              bss_conf->bssid);
+       }
+
+       mutex_unlock(&il->mutex);
+
+       D_MAC80211("leave\n");
+}
+EXPORT_SYMBOL(il_mac_bss_info_changed);
+
+irqreturn_t
+il_isr(int irq, void *data)
+{
+       struct il_priv *il = data;
+       u32 inta, inta_mask;
+       u32 inta_fh;
+       unsigned long flags;
+       if (!il)
+               return IRQ_NONE;
+
+       spin_lock_irqsave(&il->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 = _il_rd(il, CSR_INT_MASK);   /* just for debug */
+       _il_wr(il, CSR_INT_MASK, 0x00000000);
+
+       /* Discover which interrupts are active/pending */
+       inta = _il_rd(il, CSR_INT);
+       inta_fh = _il_rd(il, 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) {
+               D_ISR("Ignore interrupt, inta == 0, inta_fh == 0\n");
+               goto none;
+       }
+
+       if (inta == 0xFFFFFFFF || (inta & 0xFFFFFFF0) == 0xa5a5a5a0) {
+               /* Hardware disappeared. It might have already raised
+                * an interrupt */
+               IL_WARN("HARDWARE GONE?? INTA == 0x%08x\n", inta);
+               goto unplugged;
+       }
+
+       D_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask,
+             inta_fh);
+
+       inta &= ~CSR_INT_BIT_SCD;
+
+       /* il_irq_tasklet() will service interrupts and re-enable them */
+       if (likely(inta || inta_fh))
+               tasklet_schedule(&il->irq_tasklet);
+
+unplugged:
+       spin_unlock_irqrestore(&il->lock, flags);
+       return IRQ_HANDLED;
+
+none:
+       /* re-enable interrupts here since we don't have anything to service. */
+       /* only Re-enable if disabled by irq */
+       if (test_bit(S_INT_ENABLED, &il->status))
+               il_enable_interrupts(il);
+       spin_unlock_irqrestore(&il->lock, flags);
+       return IRQ_NONE;
+}
+EXPORT_SYMBOL(il_isr);
+
+/*
+ *  il_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
+ *  function.
+ */
+void
+il_tx_cmd_protection(struct il_priv *il, struct ieee80211_tx_info *info,
+                    __le16 fc, __le32 *tx_flags)
+{
+       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+               *tx_flags |= TX_CMD_FLG_RTS_MSK;
+               *tx_flags &= ~TX_CMD_FLG_CTS_MSK;
+               *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+
+               if (!ieee80211_is_mgmt(fc))
+                       return;
+
+               switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+               case cpu_to_le16(IEEE80211_STYPE_AUTH):
+               case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+               case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+               case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+                       *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+                       *tx_flags |= TX_CMD_FLG_CTS_MSK;
+                       break;
+               }
+       } else if (info->control.rates[0].
+                  flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+               *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+               *tx_flags |= TX_CMD_FLG_CTS_MSK;
+               *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+       }
+}
+EXPORT_SYMBOL(il_tx_cmd_protection);
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
new file mode 100644 (file)
index 0000000..1bc0b02
--- /dev/null
@@ -0,0 +1,3424 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#ifndef __il_core_h__
+#define __il_core_h__
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>         /* for struct pci_device_id */
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/wait.h>
+#include <net/mac80211.h>
+#include <net/ieee80211_radiotap.h>
+
+#include "commands.h"
+#include "csr.h"
+#include "prph.h"
+
+struct il_host_cmd;
+struct il_cmd;
+struct il_tx_queue;
+
+#define IL_ERR(f, a...) dev_err(&il->pci_dev->dev, f, ## a)
+#define IL_WARN(f, a...) dev_warn(&il->pci_dev->dev, f, ## a)
+#define IL_INFO(f, a...) dev_info(&il->pci_dev->dev, f, ## a)
+
+#define RX_QUEUE_SIZE                         256
+#define RX_QUEUE_MASK                         255
+#define RX_QUEUE_SIZE_LOG                     8
+
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 64
+#define RX_LOW_WATERMARK 8
+
+#define U32_PAD(n)             ((4-(n))&0x3)
+
+/* CT-KILL constants */
+#define CT_KILL_THRESHOLD_LEGACY   110 /* in Celsius */
+
+/* Default noise level to report when noise measurement is not available.
+ *   This may be because we're:
+ *   1)  Not associated (4965, no beacon stats being sent to driver)
+ *   2)  Scanning (noise measurement does not apply to associated channel)
+ *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
+ * Use default noise value of -127 ... this is below the range of measurable
+ *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
+ *   Also, -127 works better than 0 when averaging frames with/without
+ *   noise info (e.g. averaging might be done in app); measured dBm values are
+ *   always negative ... using a negative value as the default keeps all
+ *   averages within an s8's (used in some apps) range of negative values. */
+#define IL_NOISE_MEAS_NOT_AVAILABLE (-127)
+
+/*
+ * RTS threshold here is total size [2347] minus 4 FCS bytes
+ * Per spec:
+ *   a value of 0 means RTS on all data/management packets
+ *   a value > max MSDU size means no RTS
+ * else RTS for data/management frames where MPDU is larger
+ *   than RTS value.
+ */
+#define DEFAULT_RTS_THRESHOLD     2347U
+#define MIN_RTS_THRESHOLD         0U
+#define MAX_RTS_THRESHOLD         2347U
+#define MAX_MSDU_SIZE            2304U
+#define MAX_MPDU_SIZE            2346U
+#define DEFAULT_BEACON_INTERVAL   100U
+#define        DEFAULT_SHORT_RETRY_LIMIT 7U
+#define        DEFAULT_LONG_RETRY_LIMIT  4U
+
+struct il_rx_buf {
+       dma_addr_t page_dma;
+       struct page *page;
+       struct list_head list;
+};
+
+#define rxb_addr(r) page_address(r->page)
+
+/* defined below */
+struct il_device_cmd;
+
+struct il_cmd_meta {
+       /* only for SYNC commands, iff the reply skb is wanted */
+       struct il_host_cmd *source;
+       /*
+        * only for ASYNC commands
+        * (which is somewhat stupid -- look at common.c for instance
+        * which duplicates a bunch of code because the callback isn't
+        * invoked for SYNC commands, if it were and its result passed
+        * through it would be simpler...)
+        */
+       void (*callback) (struct il_priv *il, struct il_device_cmd *cmd,
+                         struct il_rx_pkt *pkt);
+
+       /* The CMD_SIZE_HUGE flag bit indicates that the command
+        * structure is stored at the end of the shared queue memory. */
+       u32 flags;
+
+        DEFINE_DMA_UNMAP_ADDR(mapping);
+        DEFINE_DMA_UNMAP_LEN(len);
+};
+
+/*
+ * Generic queue structure
+ *
+ * Contains common data for Rx and Tx queues
+ */
+struct il_queue {
+       int n_bd;               /* number of BDs in this queue */
+       int write_ptr;          /* 1-st empty entry (idx) host_w */
+       int read_ptr;           /* last used entry (idx) host_r */
+       /* use for monitoring and recovering the stuck queue */
+       dma_addr_t dma_addr;    /* physical addr for BD's */
+       int n_win;              /* safe queue win */
+       u32 id;
+       int low_mark;           /* low watermark, resume queue if free
+                                * space more than this */
+       int high_mark;          /* high watermark, stop queue if free
+                                * space less than this */
+};
+
+/* One for each TFD */
+struct il_tx_info {
+       struct sk_buff *skb;
+       struct il_rxon_context *ctx;
+};
+
+/**
+ * struct il_tx_queue - Tx Queue for DMA
+ * @q: generic Rx/Tx queue descriptor
+ * @bd: base of circular buffer of TFDs
+ * @cmd: array of command/TX buffer pointers
+ * @meta: array of meta data for each command/tx buffer
+ * @dma_addr_cmd: physical address of cmd/tx buffer array
+ * @txb: array of per-TFD driver data
+ * @time_stamp: time (in jiffies) of last read_ptr change
+ * @need_update: indicates need to update read/write idx
+ * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
+ *
+ * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
+ * descriptors) and required locking structures.
+ */
+#define TFD_TX_CMD_SLOTS 256
+#define TFD_CMD_SLOTS 32
+
+struct il_tx_queue {
+       struct il_queue q;
+       void *tfds;
+       struct il_device_cmd **cmd;
+       struct il_cmd_meta *meta;
+       struct il_tx_info *txb;
+       unsigned long time_stamp;
+       u8 need_update;
+       u8 sched_retry;
+       u8 active;
+       u8 swq_id;
+};
+
+/*
+ * EEPROM access time values:
+ *
+ * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG.
+ * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
+ * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
+ * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
+ */
+#define IL_EEPROM_ACCESS_TIMEOUT       5000    /* uSec */
+
+#define IL_EEPROM_SEM_TIMEOUT          10      /* microseconds */
+#define IL_EEPROM_SEM_RETRY_LIMIT      1000    /* number of attempts (not time) */
+
+/*
+ * Regulatory channel usage flags in EEPROM struct il4965_eeprom_channel.flags.
+ *
+ * IBSS and/or AP operation is allowed *only* on those channels with
+ * (VALID && IBSS && ACTIVE && !RADAR).  This restriction is in place because
+ * RADAR detection is not supported by the 4965 driver, but is a
+ * requirement for establishing a new network for legal operation on channels
+ * requiring RADAR detection or restricting ACTIVE scanning.
+ *
+ * NOTE:  "WIDE" flag does not indicate anything about "HT40" 40 MHz channels.
+ *        It only indicates that 20 MHz channel use is supported; HT40 channel
+ *        usage is indicated by a separate set of regulatory flags for each
+ *        HT40 channel pair.
+ *
+ * NOTE:  Using a channel inappropriately will result in a uCode error!
+ */
+#define IL_NUM_TX_CALIB_GROUPS 5
+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), /* 20 MHz channel okay */
+       /* Bit 6 Reserved (was Narrow Channel) */
+       EEPROM_CHANNEL_DFS = (1 << 7),  /* dynamic freq selection candidate */
+};
+
+/* SKU Capabilities */
+/* 3945 only */
+#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE                (1 << 0)
+#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
+
+/* *regulatory* channel data format in eeprom, one for each channel.
+ * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */
+struct il_eeprom_channel {
+       u8 flags;               /* EEPROM_CHANNEL_* flags copied from EEPROM */
+       s8 max_power_avg;       /* max power (dBm) on this chnl, limit 31 */
+} __packed;
+
+/* 3945 Specific */
+#define EEPROM_3945_EEPROM_VERSION     (0x2f)
+
+/* 4965 has two radio transmitters (and 3 radio receivers) */
+#define EEPROM_TX_POWER_TX_CHAINS      (2)
+
+/* 4965 has room for up to 8 sets of txpower calibration data */
+#define EEPROM_TX_POWER_BANDS          (8)
+
+/* 4965 factory calibration measures txpower gain settings for
+ * each of 3 target output levels */
+#define EEPROM_TX_POWER_MEASUREMENTS   (3)
+
+/* 4965 Specific */
+/* 4965 driver does not work with txpower calibration version < 5 */
+#define EEPROM_4965_TX_POWER_VERSION    (5)
+#define EEPROM_4965_EEPROM_VERSION     (0x2f)
+#define EEPROM_4965_CALIB_VERSION_OFFSET       (2*0xB6)        /* 2 bytes */
+#define EEPROM_4965_CALIB_TXPOWER_OFFSET       (2*0xE8)        /* 48  bytes */
+#define EEPROM_4965_BOARD_REVISION             (2*0x4F)        /* 2 bytes */
+#define EEPROM_4965_BOARD_PBA                  (2*0x56+1)      /* 9 bytes */
+
+/* 2.4 GHz */
+extern const u8 il_eeprom_band_1[14];
+
+/*
+ * factory calibration data for one txpower level, on one channel,
+ * measured on one of the 2 tx chains (radio transmitter and associated
+ * antenna).  EEPROM contains:
+ *
+ * 1)  Temperature (degrees Celsius) of device when measurement was made.
+ *
+ * 2)  Gain table idx used to achieve the target measurement power.
+ *     This refers to the "well-known" gain tables (see 4965.h).
+ *
+ * 3)  Actual measured output power, in half-dBm ("34" = 17 dBm).
+ *
+ * 4)  RF power amplifier detector level measurement (not used).
+ */
+struct il_eeprom_calib_measure {
+       u8 temperature;         /* Device temperature (Celsius) */
+       u8 gain_idx;            /* Index into gain table */
+       u8 actual_pow;          /* Measured RF output power, half-dBm */
+       s8 pa_det;              /* Power amp detector level (not used) */
+} __packed;
+
+/*
+ * measurement set for one channel.  EEPROM contains:
+ *
+ * 1)  Channel number measured
+ *
+ * 2)  Measurements for each of 3 power levels for each of 2 radio transmitters
+ *     (a.k.a. "tx chains") (6 measurements altogether)
+ */
+struct il_eeprom_calib_ch_info {
+       u8 ch_num;
+       struct il_eeprom_calib_measure
+           measurements[EEPROM_TX_POWER_TX_CHAINS]
+           [EEPROM_TX_POWER_MEASUREMENTS];
+} __packed;
+
+/*
+ * txpower subband info.
+ *
+ * For each frequency subband, EEPROM contains the following:
+ *
+ * 1)  First and last channels within range of the subband.  "0" values
+ *     indicate that this sample set is not being used.
+ *
+ * 2)  Sample measurement sets for 2 channels close to the range endpoints.
+ */
+struct il_eeprom_calib_subband_info {
+       u8 ch_from;             /* channel number of lowest channel in subband */
+       u8 ch_to;               /* channel number of highest channel in subband */
+       struct il_eeprom_calib_ch_info ch1;
+       struct il_eeprom_calib_ch_info ch2;
+} __packed;
+
+/*
+ * txpower calibration info.  EEPROM contains:
+ *
+ * 1)  Factory-measured saturation power levels (maximum levels at which
+ *     tx power amplifier can output a signal without too much distortion).
+ *     There is one level for 2.4 GHz band and one for 5 GHz band.  These
+ *     values apply to all channels within each of the bands.
+ *
+ * 2)  Factory-measured power supply voltage level.  This is assumed to be
+ *     constant (i.e. same value applies to all channels/bands) while the
+ *     factory measurements are being made.
+ *
+ * 3)  Up to 8 sets of factory-measured txpower calibration values.
+ *     These are for different frequency ranges, since txpower gain
+ *     characteristics of the analog radio circuitry vary with frequency.
+ *
+ *     Not all sets need to be filled with data;
+ *     struct il_eeprom_calib_subband_info contains range of channels
+ *     (0 if unused) for each set of data.
+ */
+struct il_eeprom_calib_info {
+       u8 saturation_power24;  /* half-dBm (e.g. "34" = 17 dBm) */
+       u8 saturation_power52;  /* half-dBm */
+       __le16 voltage;         /* signed */
+       struct il_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS];
+} __packed;
+
+/* General */
+#define EEPROM_DEVICE_ID                    (2*0x08)   /* 2 bytes */
+#define EEPROM_MAC_ADDRESS                  (2*0x15)   /* 6  bytes */
+#define EEPROM_BOARD_REVISION               (2*0x35)   /* 2  bytes */
+#define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1) /* 9  bytes */
+#define EEPROM_VERSION                      (2*0x44)   /* 2  bytes */
+#define EEPROM_SKU_CAP                      (2*0x45)   /* 2  bytes */
+#define EEPROM_OEM_MODE                     (2*0x46)   /* 2  bytes */
+#define EEPROM_WOWLAN_MODE                  (2*0x47)   /* 2  bytes */
+#define EEPROM_RADIO_CONFIG                 (2*0x48)   /* 2  bytes */
+#define EEPROM_NUM_MAC_ADDRESS              (2*0x4C)   /* 2  bytes */
+
+/* The following masks are to be applied on EEPROM_RADIO_CONFIG */
+#define EEPROM_RF_CFG_TYPE_MSK(x)   (x & 0x3)  /* bits 0-1   */
+#define EEPROM_RF_CFG_STEP_MSK(x)   ((x >> 2)  & 0x3)  /* bits 2-3   */
+#define EEPROM_RF_CFG_DASH_MSK(x)   ((x >> 4)  & 0x3)  /* bits 4-5   */
+#define EEPROM_RF_CFG_PNUM_MSK(x)   ((x >> 6)  & 0x3)  /* bits 6-7   */
+#define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8)  & 0xF)  /* bits 8-11  */
+#define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF)  /* bits 12-15 */
+
+#define EEPROM_3945_RF_CFG_TYPE_MAX  0x0
+#define EEPROM_4965_RF_CFG_TYPE_MAX  0x1
+
+/*
+ * Per-channel regulatory data.
+ *
+ * Each channel that *might* be supported by iwl has a fixed location
+ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
+ * txpower (MSB).
+ *
+ * Entries immediately below are for 20 MHz channel width.  HT40 (40 MHz)
+ * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
+ *
+ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ */
+#define EEPROM_REGULATORY_SKU_ID            (2*0x60)   /* 4  bytes */
+#define EEPROM_REGULATORY_BAND_1            (2*0x62)   /* 2  bytes */
+#define EEPROM_REGULATORY_BAND_1_CHANNELS   (2*0x63)   /* 28 bytes */
+
+/*
+ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
+ * 5.0 GHz channels 7, 8, 11, 12, 16
+ * (4915-5080MHz) (none of these is ever supported)
+ */
+#define EEPROM_REGULATORY_BAND_2            (2*0x71)   /* 2  bytes */
+#define EEPROM_REGULATORY_BAND_2_CHANNELS   (2*0x72)   /* 26 bytes */
+
+/*
+ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+ * (5170-5320MHz)
+ */
+#define EEPROM_REGULATORY_BAND_3            (2*0x7F)   /* 2  bytes */
+#define EEPROM_REGULATORY_BAND_3_CHANNELS   (2*0x80)   /* 24 bytes */
+
+/*
+ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+ * (5500-5700MHz)
+ */
+#define EEPROM_REGULATORY_BAND_4            (2*0x8C)   /* 2  bytes */
+#define EEPROM_REGULATORY_BAND_4_CHANNELS   (2*0x8D)   /* 22 bytes */
+
+/*
+ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+ * (5725-5825MHz)
+ */
+#define EEPROM_REGULATORY_BAND_5            (2*0x98)   /* 2  bytes */
+#define EEPROM_REGULATORY_BAND_5_CHANNELS   (2*0x99)   /* 12 bytes */
+
+/*
+ * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
+ *
+ * The channel listed is the center of the lower 20 MHz half of the channel.
+ * The overall center frequency is actually 2 channels (10 MHz) above that,
+ * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away
+ * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5,
+ * and the overall HT40 channel width centers on channel 3.
+ *
+ * NOTE:  The RXON command uses 20 MHz channel numbers to specify the
+ *        control channel to which to tune.  RXON also specifies whether the
+ *        control channel is the upper or lower half of a HT40 channel.
+ *
+ * NOTE:  4965 does not support HT40 channels on 2.4 GHz.
+ */
+#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0)  /* 14 bytes */
+
+/*
+ * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64),
+ * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
+ */
+#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8)  /* 22 bytes */
+
+#define EEPROM_REGULATORY_BAND_NO_HT40                 (0)
+
+struct il_eeprom_ops {
+       const u32 regulatory_bands[7];
+       int (*acquire_semaphore) (struct il_priv *il);
+       void (*release_semaphore) (struct il_priv *il);
+};
+
+int il_eeprom_init(struct il_priv *il);
+void il_eeprom_free(struct il_priv *il);
+const u8 *il_eeprom_query_addr(const struct il_priv *il, size_t offset);
+u16 il_eeprom_query16(const struct il_priv *il, size_t offset);
+int il_init_channel_map(struct il_priv *il);
+void il_free_channel_map(struct il_priv *il);
+const struct il_channel_info *il_get_channel_info(const struct il_priv *il,
+                                                 enum ieee80211_band band,
+                                                 u16 channel);
+
+#define IL_NUM_SCAN_RATES         (2)
+
+struct il4965_channel_tgd_info {
+       u8 type;
+       s8 max_power;
+};
+
+struct il4965_channel_tgh_info {
+       s64 last_radar_time;
+};
+
+#define IL4965_MAX_RATE (33)
+
+struct il3945_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[IL_MAX_RATES];
+};
+
+/* 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 idx must also be set. */
+struct il3945_channel_power_info {
+       struct il3945_tx_power tpc;     /* actual radio and DSP gain settings */
+       s8 power_table_idx;     /* actual (compenst'd) idx into gain table */
+       s8 base_power_idx;      /* gain idx for power at factory temp. */
+       s8 requested_power;     /* power (dBm) requested for this chnl/rate */
+};
+
+/* current scan Tx power values to use, one for each scan rate for each
+ * channel. */
+struct il3945_scan_power_info {
+       struct il3945_tx_power tpc;     /* actual radio and DSP gain settings */
+       s8 power_table_idx;     /* actual (compenst'd) idx into gain table */
+       s8 requested_power;     /* scan pwr (dBm) requested for chnl/rate */
+};
+
+/*
+ * 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!
+ */
+struct il_channel_info {
+       struct il4965_channel_tgd_info tgd;
+       struct il4965_channel_tgh_info tgh;
+       struct il_eeprom_channel eeprom;        /* EEPROM regulatory limit */
+       struct il_eeprom_channel ht40_eeprom;   /* EEPROM regulatory limit for
+                                                * HT40 channel */
+
+       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) limit */
+       s8 min_power;           /* always 0 */
+       s8 scan_power;          /* (dBm) regul. eeprom, direct scans, any rate */
+
+       u8 group_idx;           /* 0-4, maps channel to group1/2/3/4/5 */
+       u8 band_idx;            /* 0-4, maps channel to band1/2/3/4/5 */
+       enum ieee80211_band band;
+
+       /* HT40 channel info */
+       s8 ht40_max_power_avg;  /* (dBm) regul. eeprom, normal Tx, any rate */
+       u8 ht40_flags;          /* flags copied from EEPROM */
+       u8 ht40_extension_channel;      /* HT_IE_EXT_CHANNEL_* */
+
+       /* 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 (idxes). */
+       struct il3945_channel_power_info power_info[IL4965_MAX_RATE];
+
+       /* Radio/DSP gain settings for each scan rate, for directed scans. */
+       struct il3945_scan_power_info scan_pwr_info[IL_NUM_SCAN_RATES];
+};
+
+#define IL_TX_FIFO_BK          0       /* shared */
+#define IL_TX_FIFO_BE          1
+#define IL_TX_FIFO_VI          2       /* shared */
+#define IL_TX_FIFO_VO          3
+#define IL_TX_FIFO_UNUSED      -1
+
+/* Minimum number of queues. MAX_NUM is defined in hw specific files.
+ * Set the minimum to accommodate the 4 standard TX queues, 1 command
+ * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */
+#define IL_MIN_NUM_QUEUES      10
+
+#define IL_DEFAULT_CMD_QUEUE_NUM       4
+
+#define IEEE80211_DATA_LEN              2304
+#define IEEE80211_4ADDR_LEN             30
+#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+struct il_frame {
+       union {
+               struct ieee80211_hdr frame;
+               struct il_tx_beacon_cmd beacon;
+               u8 raw[IEEE80211_FRAME_LEN];
+               u8 cmd[360];
+       } u;
+       struct list_head list;
+};
+
+#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
+#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
+
+enum {
+       CMD_SYNC = 0,
+       CMD_SIZE_NORMAL = 0,
+       CMD_NO_SKB = 0,
+       CMD_SIZE_HUGE = (1 << 0),
+       CMD_ASYNC = (1 << 1),
+       CMD_WANT_SKB = (1 << 2),
+       CMD_MAPPED = (1 << 3),
+};
+
+#define DEF_CMD_PAYLOAD_SIZE 320
+
+/**
+ * struct il_device_cmd
+ *
+ * For allocation of the command and tx queues, this establishes the overall
+ * size of the largest command we send to uCode, except for a scan command
+ * (which is relatively huge; space is allocated separately).
+ */
+struct il_device_cmd {
+       struct il_cmd_header hdr;       /* uCode API */
+       union {
+               u32 flags;
+               u8 val8;
+               u16 val16;
+               u32 val32;
+               struct il_tx_cmd tx;
+               u8 payload[DEF_CMD_PAYLOAD_SIZE];
+       } __packed cmd;
+} __packed;
+
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct il_device_cmd))
+
+struct il_host_cmd {
+       const void *data;
+       unsigned long reply_page;
+       void (*callback) (struct il_priv *il, struct il_device_cmd *cmd,
+                         struct il_rx_pkt *pkt);
+       u32 flags;
+       u16 len;
+       u8 id;
+};
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
+
+/**
+ * struct il_rx_queue - Rx queue
+ * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
+ * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
+ * @read: Shared idx to newest available Rx buffer
+ * @write: Shared idx to oldest written Rx packet
+ * @free_count: Number of pre-allocated buffers in rx_free
+ * @rx_free: list of free SKBs for use
+ * @rx_used: List of Rx buffers with no SKB
+ * @need_update: flag to indicate we need to update read/write idx
+ * @rb_stts: driver's pointer to receive buffer status
+ * @rb_stts_dma: bus address of receive buffer status
+ *
+ * NOTE:  rx_free and rx_used are used as a FIFO for il_rx_bufs
+ */
+struct il_rx_queue {
+       __le32 *bd;
+       dma_addr_t bd_dma;
+       struct il_rx_buf pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+       struct il_rx_buf *queue[RX_QUEUE_SIZE];
+       u32 read;
+       u32 write;
+       u32 free_count;
+       u32 write_actual;
+       struct list_head rx_free;
+       struct list_head rx_used;
+       int need_update;
+       struct il_rb_status *rb_stts;
+       dma_addr_t rb_stts_dma;
+       spinlock_t lock;
+};
+
+#define IL_SUPPORTED_RATES_IE_LEN         8
+
+#define MAX_TID_COUNT        9
+
+#define IL_INVALID_RATE     0xFF
+#define IL_INVALID_VALUE    -1
+
+/**
+ * struct il_ht_agg -- aggregation status while waiting for block-ack
+ * @txq_id: Tx queue used for Tx attempt
+ * @frame_count: # frames attempted by Tx command
+ * @wait_for_ba: Expect block-ack before next Tx reply
+ * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx win
+ * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx win
+ * @bitmap1: High order, one bit for each frame pending ACK in Tx win
+ * @rate_n_flags: Rate at which Tx was attempted
+ *
+ * If C_TX indicates that aggregation was attempted, driver must wait
+ * for block ack (N_COMPRESSED_BA).  This struct stores tx reply info
+ * until block ack arrives.
+ */
+struct il_ht_agg {
+       u16 txq_id;
+       u16 frame_count;
+       u16 wait_for_ba;
+       u16 start_idx;
+       u64 bitmap;
+       u32 rate_n_flags;
+#define IL_AGG_OFF 0
+#define IL_AGG_ON 1
+#define IL_EMPTYING_HW_QUEUE_ADDBA 2
+#define IL_EMPTYING_HW_QUEUE_DELBA 3
+       u8 state;
+};
+
+struct il_tid_data {
+       u16 seq_number;         /* 4965 only */
+       u16 tfds_in_queue;
+       struct il_ht_agg agg;
+};
+
+struct il_hw_key {
+       u32 cipher;
+       int keylen;
+       u8 keyidx;
+       u8 key[32];
+};
+
+union il_ht_rate_supp {
+       u16 rates;
+       struct {
+               u8 siso_rate;
+               u8 mimo_rate;
+       };
+};
+
+#define CFG_HT_RX_AMPDU_FACTOR_8K   (0x0)
+#define CFG_HT_RX_AMPDU_FACTOR_16K  (0x1)
+#define CFG_HT_RX_AMPDU_FACTOR_32K  (0x2)
+#define CFG_HT_RX_AMPDU_FACTOR_64K  (0x3)
+#define CFG_HT_RX_AMPDU_FACTOR_DEF  CFG_HT_RX_AMPDU_FACTOR_64K
+#define CFG_HT_RX_AMPDU_FACTOR_MAX  CFG_HT_RX_AMPDU_FACTOR_64K
+#define CFG_HT_RX_AMPDU_FACTOR_MIN  CFG_HT_RX_AMPDU_FACTOR_8K
+
+/*
+ * Maximal MPDU density for TX aggregation
+ * 4 - 2us density
+ * 5 - 4us density
+ * 6 - 8us density
+ * 7 - 16us density
+ */
+#define CFG_HT_MPDU_DENSITY_2USEC   (0x4)
+#define CFG_HT_MPDU_DENSITY_4USEC   (0x5)
+#define CFG_HT_MPDU_DENSITY_8USEC   (0x6)
+#define CFG_HT_MPDU_DENSITY_16USEC  (0x7)
+#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
+#define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC
+#define CFG_HT_MPDU_DENSITY_MIN     (0x1)
+
+struct il_ht_config {
+       bool single_chain_sufficient;
+       enum ieee80211_smps_mode smps;  /* current smps mode */
+};
+
+/* QoS structures */
+struct il_qos_info {
+       int qos_active;
+       struct il_qosparam_cmd def_qos_parm;
+};
+
+/*
+ * Structure should be accessed with sta_lock held. When station addition
+ * is in progress (IL_STA_UCODE_INPROGRESS) it is possible to access only
+ * the commands (il_addsta_cmd and il_link_quality_cmd) without
+ * sta_lock held.
+ */
+struct il_station_entry {
+       struct il_addsta_cmd sta;
+       struct il_tid_data tid[MAX_TID_COUNT];
+       u8 used, ctxid;
+       struct il_hw_key keyinfo;
+       struct il_link_quality_cmd *lq;
+};
+
+struct il_station_priv_common {
+       struct il_rxon_context *ctx;
+       u8 sta_id;
+};
+
+/**
+ * struct il_vif_priv - driver's ilate per-interface information
+ *
+ * When mac80211 allocates a virtual interface, it can allocate
+ * space for us to put data into.
+ */
+struct il_vif_priv {
+       struct il_rxon_context *ctx;
+       u8 ibss_bssid_sta_id;
+};
+
+/* one for each uCode image (inst/data, boot/init/runtime) */
+struct fw_desc {
+       void *v_addr;           /* access by driver */
+       dma_addr_t p_addr;      /* access by card's busmaster DMA */
+       u32 len;                /* bytes */
+};
+
+/* uCode file layout */
+struct il_ucode_header {
+       __le32 ver;             /* major/minor/API/serial */
+       struct {
+               __le32 inst_size;       /* bytes of runtime code */
+               __le32 data_size;       /* bytes of runtime data */
+               __le32 init_size;       /* bytes of init code */
+               __le32 init_data_size;  /* bytes of init data */
+               __le32 boot_size;       /* bytes of bootstrap code */
+               u8 data[0];     /* in same order as sizes */
+       } v1;
+};
+
+struct il4965_ibss_seq {
+       u8 mac[ETH_ALEN];
+       u16 seq_num;
+       u16 frag_num;
+       unsigned long packet_time;
+       struct list_head list;
+};
+
+struct il_sensitivity_ranges {
+       u16 min_nrg_cck;
+       u16 max_nrg_cck;
+
+       u16 nrg_th_cck;
+       u16 nrg_th_ofdm;
+
+       u16 auto_corr_min_ofdm;
+       u16 auto_corr_min_ofdm_mrc;
+       u16 auto_corr_min_ofdm_x1;
+       u16 auto_corr_min_ofdm_mrc_x1;
+
+       u16 auto_corr_max_ofdm;
+       u16 auto_corr_max_ofdm_mrc;
+       u16 auto_corr_max_ofdm_x1;
+       u16 auto_corr_max_ofdm_mrc_x1;
+
+       u16 auto_corr_max_cck;
+       u16 auto_corr_max_cck_mrc;
+       u16 auto_corr_min_cck;
+       u16 auto_corr_min_cck_mrc;
+
+       u16 barker_corr_th_min;
+       u16 barker_corr_th_min_mrc;
+       u16 nrg_th_cca;
+};
+
+#define KELVIN_TO_CELSIUS(x) ((x)-273)
+#define CELSIUS_TO_KELVIN(x) ((x)+273)
+
+/**
+ * struct il_hw_params
+ * @max_txq_num: Max # Tx queues supported
+ * @dma_chnl_num: Number of Tx DMA/FIFO channels
+ * @scd_bc_tbls_size: size of scheduler byte count tables
+ * @tfd_size: TFD size
+ * @tx/rx_chains_num: Number of TX/RX chains
+ * @valid_tx/rx_ant: usable antennas
+ * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
+ * @max_rxq_log: Log-base-2 of max_rxq_size
+ * @rx_page_order: Rx buffer page order
+ * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
+ * @max_stations:
+ * @ht40_channel: is 40MHz width possible in band 2.4
+ * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
+ * @sw_crypto: 0 for hw, 1 for sw
+ * @max_xxx_size: for ucode uses
+ * @ct_kill_threshold: temperature threshold
+ * @beacon_time_tsf_bits: number of valid tsf bits for beacon time
+ * @struct il_sensitivity_ranges: range of sensitivity values
+ */
+struct il_hw_params {
+       u8 max_txq_num;
+       u8 dma_chnl_num;
+       u16 scd_bc_tbls_size;
+       u32 tfd_size;
+       u8 tx_chains_num;
+       u8 rx_chains_num;
+       u8 valid_tx_ant;
+       u8 valid_rx_ant;
+       u16 max_rxq_size;
+       u16 max_rxq_log;
+       u32 rx_page_order;
+       u32 rx_wrt_ptr_reg;
+       u8 max_stations;
+       u8 ht40_channel;
+       u8 max_beacon_itrvl;    /* in 1024 ms */
+       u32 max_inst_size;
+       u32 max_data_size;
+       u32 max_bsm_size;
+       u32 ct_kill_threshold;  /* value in hw-dependent units */
+       u16 beacon_time_tsf_bits;
+       const struct il_sensitivity_ranges *sens;
+};
+
+/******************************************************************************
+ *
+ * Functions implemented in core module which are forward declared here
+ * for use by iwl-[4-5].c
+ *
+ * NOTE:  The implementation of these functions are not hardware specific
+ * which is why they are in the core module files.
+ *
+ * Naming convention --
+ * il_         <-- Is part of iwlwifi
+ * iwlXXXX_     <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
+ * il4965_bg_      <-- Called from work queue context
+ * il4965_mac_     <-- mac80211 callback
+ *
+ ****************************************************************************/
+extern void il4965_update_chain_flags(struct il_priv *il);
+extern const u8 il_bcast_addr[ETH_ALEN];
+extern int il_queue_space(const struct il_queue *q);
+static inline int
+il_queue_used(const struct il_queue *q, int i)
+{
+       return q->write_ptr >= q->read_ptr ? (i >= q->read_ptr &&
+                                             i < q->write_ptr) : !(i <
+                                                                   q->read_ptr
+                                                                   && i >=
+                                                                   q->
+                                                                   write_ptr);
+}
+
+static inline u8
+il_get_cmd_idx(struct il_queue *q, u32 idx, int is_huge)
+{
+       /*
+        * This is for init calibration result and scan command which
+        * required buffer > TFD_MAX_PAYLOAD_SIZE,
+        * the big buffer at end of command array
+        */
+       if (is_huge)
+               return q->n_win;        /* must be power of 2 */
+
+       /* Otherwise, use normal size buffers */
+       return idx & (q->n_win - 1);
+}
+
+struct il_dma_ptr {
+       dma_addr_t dma;
+       void *addr;
+       size_t size;
+};
+
+#define IL_OPERATION_MODE_AUTO     0
+#define IL_OPERATION_MODE_HT_ONLY  1
+#define IL_OPERATION_MODE_MIXED    2
+#define IL_OPERATION_MODE_20MHZ    3
+
+#define IL_TX_CRC_SIZE 4
+#define IL_TX_DELIMITER_SIZE 4
+
+#define TX_POWER_IL_ILLEGAL_VOLTAGE -10000
+
+/* Sensitivity and chain noise calibration */
+#define INITIALIZATION_VALUE           0xFFFF
+#define IL4965_CAL_NUM_BEACONS         20
+#define IL_CAL_NUM_BEACONS             16
+#define MAXIMUM_ALLOWED_PATHLOSS       15
+
+#define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3
+
+#define MAX_FA_OFDM  50
+#define MIN_FA_OFDM  5
+#define MAX_FA_CCK   50
+#define MIN_FA_CCK   5
+
+#define AUTO_CORR_STEP_OFDM       1
+
+#define AUTO_CORR_STEP_CCK     3
+#define AUTO_CORR_MAX_TH_CCK   160
+
+#define NRG_DIFF               2
+#define NRG_STEP_CCK           2
+#define NRG_MARGIN             8
+#define MAX_NUMBER_CCK_NO_FA 100
+
+#define AUTO_CORR_CCK_MIN_VAL_DEF    (125)
+
+#define CHAIN_A             0
+#define CHAIN_B             1
+#define CHAIN_C             2
+#define CHAIN_NOISE_DELTA_GAIN_INIT_VAL 4
+#define ALL_BAND_FILTER                        0xFF00
+#define IN_BAND_FILTER                 0xFF
+#define MIN_AVERAGE_NOISE_MAX_VALUE    0xFFFFFFFF
+
+#define NRG_NUM_PREV_STAT_L     20
+#define NUM_RX_CHAINS           3
+
+enum il4965_false_alarm_state {
+       IL_FA_TOO_MANY = 0,
+       IL_FA_TOO_FEW = 1,
+       IL_FA_GOOD_RANGE = 2,
+};
+
+enum il4965_chain_noise_state {
+       IL_CHAIN_NOISE_ALIVE = 0,       /* must be 0 */
+       IL_CHAIN_NOISE_ACCUMULATE,
+       IL_CHAIN_NOISE_CALIBRATED,
+       IL_CHAIN_NOISE_DONE,
+};
+
+enum il4965_calib_enabled_state {
+       IL_CALIB_DISABLED = 0,  /* must be 0 */
+       IL_CALIB_ENABLED = 1,
+};
+
+/*
+ * enum il_calib
+ * defines the order in which results of initial calibrations
+ * should be sent to the runtime uCode
+ */
+enum il_calib {
+       IL_CALIB_MAX,
+};
+
+/* Opaque calibration results */
+struct il_calib_result {
+       void *buf;
+       size_t buf_len;
+};
+
+enum ucode_type {
+       UCODE_NONE = 0,
+       UCODE_INIT,
+       UCODE_RT
+};
+
+/* Sensitivity calib data */
+struct il_sensitivity_data {
+       u32 auto_corr_ofdm;
+       u32 auto_corr_ofdm_mrc;
+       u32 auto_corr_ofdm_x1;
+       u32 auto_corr_ofdm_mrc_x1;
+       u32 auto_corr_cck;
+       u32 auto_corr_cck_mrc;
+
+       u32 last_bad_plcp_cnt_ofdm;
+       u32 last_fa_cnt_ofdm;
+       u32 last_bad_plcp_cnt_cck;
+       u32 last_fa_cnt_cck;
+
+       u32 nrg_curr_state;
+       u32 nrg_prev_state;
+       u32 nrg_value[10];
+       u8 nrg_silence_rssi[NRG_NUM_PREV_STAT_L];
+       u32 nrg_silence_ref;
+       u32 nrg_energy_idx;
+       u32 nrg_silence_idx;
+       u32 nrg_th_cck;
+       s32 nrg_auto_corr_silence_diff;
+       u32 num_in_cck_no_fa;
+       u32 nrg_th_ofdm;
+
+       u16 barker_corr_th_min;
+       u16 barker_corr_th_min_mrc;
+       u16 nrg_th_cca;
+};
+
+/* Chain noise (differential Rx gain) calib data */
+struct il_chain_noise_data {
+       u32 active_chains;
+       u32 chain_noise_a;
+       u32 chain_noise_b;
+       u32 chain_noise_c;
+       u32 chain_signal_a;
+       u32 chain_signal_b;
+       u32 chain_signal_c;
+       u16 beacon_count;
+       u8 disconn_array[NUM_RX_CHAINS];
+       u8 delta_gain_code[NUM_RX_CHAINS];
+       u8 radio_write;
+       u8 state;
+};
+
+#define        EEPROM_SEM_TIMEOUT 10   /* milliseconds */
+#define EEPROM_SEM_RETRY_LIMIT 1000    /* number of attempts (not time) */
+
+#define IL_TRAFFIC_ENTRIES     (256)
+#define IL_TRAFFIC_ENTRY_SIZE  (64)
+
+enum {
+       MEASUREMENT_READY = (1 << 0),
+       MEASUREMENT_ACTIVE = (1 << 1),
+};
+
+/* interrupt stats */
+struct isr_stats {
+       u32 hw;
+       u32 sw;
+       u32 err_code;
+       u32 sch;
+       u32 alive;
+       u32 rfkill;
+       u32 ctkill;
+       u32 wakeup;
+       u32 rx;
+       u32 handlers[IL_CN_MAX];
+       u32 tx;
+       u32 unhandled;
+};
+
+/* management stats */
+enum il_mgmt_stats {
+       MANAGEMENT_ASSOC_REQ = 0,
+       MANAGEMENT_ASSOC_RESP,
+       MANAGEMENT_REASSOC_REQ,
+       MANAGEMENT_REASSOC_RESP,
+       MANAGEMENT_PROBE_REQ,
+       MANAGEMENT_PROBE_RESP,
+       MANAGEMENT_BEACON,
+       MANAGEMENT_ATIM,
+       MANAGEMENT_DISASSOC,
+       MANAGEMENT_AUTH,
+       MANAGEMENT_DEAUTH,
+       MANAGEMENT_ACTION,
+       MANAGEMENT_MAX,
+};
+/* control stats */
+enum il_ctrl_stats {
+       CONTROL_BACK_REQ = 0,
+       CONTROL_BACK,
+       CONTROL_PSPOLL,
+       CONTROL_RTS,
+       CONTROL_CTS,
+       CONTROL_ACK,
+       CONTROL_CFEND,
+       CONTROL_CFENDACK,
+       CONTROL_MAX,
+};
+
+struct traffic_stats {
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+       u32 mgmt[MANAGEMENT_MAX];
+       u32 ctrl[CONTROL_MAX];
+       u32 data_cnt;
+       u64 data_bytes;
+#endif
+};
+
+/*
+ * host interrupt timeout value
+ * used with setting interrupt coalescing timer
+ * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
+ *
+ * default interrupt coalescing timer is 64 x 32 = 2048 usecs
+ * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
+ */
+#define IL_HOST_INT_TIMEOUT_MAX        (0xFF)
+#define IL_HOST_INT_TIMEOUT_DEF        (0x40)
+#define IL_HOST_INT_TIMEOUT_MIN        (0x0)
+#define IL_HOST_INT_CALIB_TIMEOUT_MAX  (0xFF)
+#define IL_HOST_INT_CALIB_TIMEOUT_DEF  (0x10)
+#define IL_HOST_INT_CALIB_TIMEOUT_MIN  (0x0)
+
+#define IL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
+
+/* TX queue watchdog timeouts in mSecs */
+#define IL_DEF_WD_TIMEOUT      (2000)
+#define IL_LONG_WD_TIMEOUT     (10000)
+#define IL_MAX_WD_TIMEOUT      (120000)
+
+struct il_force_reset {
+       int reset_request_count;
+       int reset_success_count;
+       int reset_reject_count;
+       unsigned long reset_duration;
+       unsigned long last_force_reset_jiffies;
+};
+
+/* extend beacon time format bit shifting  */
+/*
+ * for _3945 devices
+ * bits 31:24 - extended
+ * bits 23:0  - interval
+ */
+#define IL3945_EXT_BEACON_TIME_POS     24
+/*
+ * for _4965 devices
+ * bits 31:22 - extended
+ * bits 21:0  - interval
+ */
+#define IL4965_EXT_BEACON_TIME_POS     22
+
+struct il_rxon_context {
+       struct ieee80211_vif *vif;
+
+       const u8 *ac_to_fifo;
+       const u8 *ac_to_queue;
+       u8 mcast_queue;
+
+       /*
+        * We could use the vif to indicate active, but we
+        * also need it to be active during disabling when
+        * we already removed the vif for type setting.
+        */
+       bool always_active, is_active;
+
+       bool ht_need_multiple_chains;
+
+       int ctxid;
+
+       u32 interface_modes, exclusive_interface_modes;
+       u8 unused_devtype, ap_devtype, ibss_devtype, station_devtype;
+
+       /*
+        * We declare this const so it can only be
+        * changed via explicit cast within the
+        * routines that actually update the physical
+        * hardware.
+        */
+       const struct il_rxon_cmd active;
+       struct il_rxon_cmd staging;
+
+       struct il_rxon_time_cmd timing;
+
+       struct il_qos_info qos_data;
+
+       u8 bcast_sta_id, ap_sta_id;
+
+       u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd;
+       u8 qos_cmd;
+       u8 wep_key_cmd;
+
+       struct il_wep_key wep_keys[WEP_KEYS_MAX];
+       u8 key_mapping_keys;
+
+       __le32 station_flags;
+
+       struct {
+               bool non_gf_sta_present;
+               u8 protection;
+               bool enabled, is_40mhz;
+               u8 extension_chan_offset;
+       } ht;
+};
+
+struct il_power_mgr {
+       struct il_powertable_cmd sleep_cmd;
+       struct il_powertable_cmd sleep_cmd_next;
+       int debug_sleep_level_override;
+       bool pci_pm;
+};
+
+struct il_priv {
+
+       /* ieee device used by generic ieee processing code */
+       struct ieee80211_hw *hw;
+       struct ieee80211_channel *ieee_channels;
+       struct ieee80211_rate *ieee_rates;
+       struct il_cfg *cfg;
+
+       /* temporary frame storage list */
+       struct list_head free_frames;
+       int frames_count;
+
+       enum ieee80211_band band;
+       int alloc_rxb_page;
+
+       void (*handlers[IL_CN_MAX]) (struct il_priv *il,
+                                    struct il_rx_buf *rxb);
+
+       struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+
+       /* spectrum measurement report caching */
+       struct il_spectrum_notification measure_report;
+       u8 measurement_status;
+
+       /* ucode beacon time */
+       u32 ucode_beacon_time;
+       int missed_beacon_threshold;
+
+       /* track IBSS manager (last beacon) status */
+       u32 ibss_manager;
+
+       /* force reset */
+       struct il_force_reset force_reset;
+
+       /* we allocate array of il_channel_info for NIC's valid channels.
+        *    Access via channel # using indirect idx array */
+       struct il_channel_info *channel_info;   /* channel info array */
+       u8 channel_count;       /* # of channels */
+
+       /* thermal calibration */
+       s32 temperature;        /* degrees Kelvin */
+       s32 last_temperature;
+
+       /* init calibration results */
+       struct il_calib_result calib_results[IL_CALIB_MAX];
+
+       /* Scan related variables */
+       unsigned long scan_start;
+       unsigned long scan_start_tsf;
+       void *scan_cmd;
+       enum ieee80211_band scan_band;
+       struct cfg80211_scan_request *scan_request;
+       struct ieee80211_vif *scan_vif;
+       u8 scan_tx_ant[IEEE80211_NUM_BANDS];
+       u8 mgmt_tx_ant;
+
+       /* spinlock */
+       spinlock_t lock;        /* protect general shared data */
+       spinlock_t hcmd_lock;   /* protect hcmd */
+       spinlock_t reg_lock;    /* protect hw register access */
+       struct mutex mutex;
+
+       /* basic pci-network driver stuff */
+       struct pci_dev *pci_dev;
+
+       /* pci hardware address support */
+       void __iomem *hw_base;
+       u32 hw_rev;
+       u32 hw_wa_rev;
+       u8 rev_id;
+
+       /* command queue number */
+       u8 cmd_queue;
+
+       /* max number of station keys */
+       u8 sta_key_max_num;
+
+       /* EEPROM MAC addresses */
+       struct mac_address addresses[1];
+
+       /* uCode images, save to reload in case of failure */
+       int fw_idx;             /* firmware we're trying to load */
+       u32 ucode_ver;          /* version of ucode, copy of
+                                  il_ucode.ver */
+       struct fw_desc ucode_code;      /* runtime inst */
+       struct fw_desc ucode_data;      /* runtime data original */
+       struct fw_desc ucode_data_backup;       /* runtime data save/restore */
+       struct fw_desc ucode_init;      /* initialization inst */
+       struct fw_desc ucode_init_data; /* initialization data */
+       struct fw_desc ucode_boot;      /* bootstrap inst */
+       enum ucode_type ucode_type;
+       u8 ucode_write_complete;        /* the image write is complete */
+       char firmware_name[25];
+
+       struct il_rxon_context ctx;
+
+       __le16 switch_channel;
+
+       /* 1st responses from initialize and runtime uCode images.
+        * _4965's initialize alive response contains some calibration data. */
+       struct il_init_alive_resp card_alive_init;
+       struct il_alive_resp card_alive;
+
+       u16 active_rate;
+
+       u8 start_calib;
+       struct il_sensitivity_data sensitivity_data;
+       struct il_chain_noise_data chain_noise_data;
+       __le16 sensitivity_tbl[HD_TBL_SIZE];
+
+       struct il_ht_config current_ht_config;
+
+       /* Rate scaling data */
+       u8 retry_rate;
+
+       wait_queue_head_t wait_command_queue;
+
+       int activity_timer_active;
+
+       /* Rx and Tx DMA processing queues */
+       struct il_rx_queue rxq;
+       struct il_tx_queue *txq;
+       unsigned long txq_ctx_active_msk;
+       struct il_dma_ptr kw;   /* keep warm address */
+       struct il_dma_ptr scd_bc_tbls;
+
+       u32 scd_base_addr;      /* scheduler sram base address */
+
+       unsigned long status;
+
+       /* counts mgmt, ctl, and data packets */
+       struct traffic_stats tx_stats;
+       struct traffic_stats rx_stats;
+
+       /* counts interrupts */
+       struct isr_stats isr_stats;
+
+       struct il_power_mgr power_data;
+
+       /* context information */
+       u8 bssid[ETH_ALEN];     /* used only on 3945 but filled by core */
+
+       /* station table variables */
+
+       /* Note: if lock and sta_lock are needed, lock must be acquired first */
+       spinlock_t sta_lock;
+       int num_stations;
+       struct il_station_entry stations[IL_STATION_COUNT];
+       unsigned long ucode_key_table;
+
+       /* queue refcounts */
+#define IL_MAX_HW_QUEUES       32
+       unsigned long queue_stopped[BITS_TO_LONGS(IL_MAX_HW_QUEUES)];
+       /* for each AC */
+       atomic_t queue_stop_count[4];
+
+       /* Indication if ieee80211_ops->open has been called */
+       u8 is_open;
+
+       u8 mac80211_registered;
+
+       /* eeprom -- this is in the card's little endian byte order */
+       u8 *eeprom;
+       struct il_eeprom_calib_info *calib_info;
+
+       enum nl80211_iftype iw_mode;
+
+       /* Last Rx'd beacon timestamp */
+       u64 timestamp;
+
+       union {
+#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE)
+               struct {
+                       void *shared_virt;
+                       dma_addr_t shared_phys;
+
+                       struct delayed_work thermal_periodic;
+                       struct delayed_work rfkill_poll;
+
+                       struct il3945_notif_stats stats;
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+                       struct il3945_notif_stats accum_stats;
+                       struct il3945_notif_stats delta_stats;
+                       struct il3945_notif_stats max_delta;
+#endif
+
+                       u32 sta_supp_rates;
+                       int last_rx_rssi;       /* From Rx packet stats */
+
+                       /* Rx'd packet timing information */
+                       u32 last_beacon_time;
+                       u64 last_tsf;
+
+                       /*
+                        * each calibration channel group in the
+                        * EEPROM has a derived clip setting for
+                        * each rate.
+                        */
+                       const struct il3945_clip_group clip_groups[5];
+
+               } _3945;
+#endif
+#if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)
+               struct {
+                       struct il_rx_phy_res last_phy_res;
+                       bool last_phy_res_valid;
+
+                       struct completion firmware_loading_complete;
+
+                       /*
+                        * chain noise reset and gain commands are the
+                        * two extra calibration commands follows the standard
+                        * phy calibration commands
+                        */
+                       u8 phy_calib_chain_noise_reset_cmd;
+                       u8 phy_calib_chain_noise_gain_cmd;
+
+                       struct il_notif_stats stats;
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+                       struct il_notif_stats accum_stats;
+                       struct il_notif_stats delta_stats;
+                       struct il_notif_stats max_delta;
+#endif
+
+               } _4965;
+#endif
+       };
+
+       struct il_hw_params hw_params;
+
+       u32 inta_mask;
+
+       struct workqueue_struct *workqueue;
+
+       struct work_struct restart;
+       struct work_struct scan_completed;
+       struct work_struct rx_replenish;
+       struct work_struct abort_scan;
+
+       struct il_rxon_context *beacon_ctx;
+       struct sk_buff *beacon_skb;
+
+       struct work_struct tx_flush;
+
+       struct tasklet_struct irq_tasklet;
+
+       struct delayed_work init_alive_start;
+       struct delayed_work alive_start;
+       struct delayed_work scan_check;
+
+       /* TX Power */
+       s8 tx_power_user_lmt;
+       s8 tx_power_device_lmt;
+       s8 tx_power_next;
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+       /* debugging info */
+       u32 debug_level;        /* per device debugging will override global
+                                  il_debug_level if set */
+#endif                         /* CONFIG_IWLEGACY_DEBUG */
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+       /* debugfs */
+       u16 tx_traffic_idx;
+       u16 rx_traffic_idx;
+       u8 *tx_traffic;
+       u8 *rx_traffic;
+       struct dentry *debugfs_dir;
+       u32 dbgfs_sram_offset, dbgfs_sram_len;
+       bool disable_ht40;
+#endif                         /* CONFIG_IWLEGACY_DEBUGFS */
+
+       struct work_struct txpower_work;
+       u32 disable_sens_cal;
+       u32 disable_chain_noise_cal;
+       u32 disable_tx_power_cal;
+       struct work_struct run_time_calib_work;
+       struct timer_list stats_periodic;
+       struct timer_list watchdog;
+       bool hw_ready;
+
+       struct led_classdev led;
+       unsigned long blink_on, blink_off;
+       bool led_registered;
+};                             /*il_priv */
+
+static inline void
+il_txq_ctx_activate(struct il_priv *il, int txq_id)
+{
+       set_bit(txq_id, &il->txq_ctx_active_msk);
+}
+
+static inline void
+il_txq_ctx_deactivate(struct il_priv *il, int txq_id)
+{
+       clear_bit(txq_id, &il->txq_ctx_active_msk);
+}
+
+static inline struct ieee80211_hdr *
+il_tx_queue_get_hdr(struct il_priv *il, int txq_id, int idx)
+{
+       if (il->txq[txq_id].txb[idx].skb)
+               return (struct ieee80211_hdr *)il->txq[txq_id].txb[idx].skb->
+                   data;
+       return NULL;
+}
+
+static inline struct il_rxon_context *
+il_rxon_ctx_from_vif(struct ieee80211_vif *vif)
+{
+       struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
+
+       return vif_priv->ctx;
+}
+
+#define for_each_context(il, _ctx) \
+       for (_ctx = &il->ctx; _ctx == &il->ctx; _ctx++)
+
+static inline int
+il_is_associated(struct il_priv *il)
+{
+       return (il->ctx.active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+}
+
+static inline int
+il_is_any_associated(struct il_priv *il)
+{
+       return il_is_associated(il);
+}
+
+static inline int
+il_is_associated_ctx(struct il_rxon_context *ctx)
+{
+       return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+}
+
+static inline int
+il_is_channel_valid(const struct il_channel_info *ch_info)
+{
+       if (ch_info == NULL)
+               return 0;
+       return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
+}
+
+static inline int
+il_is_channel_radar(const struct il_channel_info *ch_info)
+{
+       return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
+}
+
+static inline u8
+il_is_channel_a_band(const struct il_channel_info *ch_info)
+{
+       return ch_info->band == IEEE80211_BAND_5GHZ;
+}
+
+static inline int
+il_is_channel_passive(const struct il_channel_info *ch)
+{
+       return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
+}
+
+static inline int
+il_is_channel_ibss(const struct il_channel_info *ch)
+{
+       return (ch->flags & EEPROM_CHANNEL_IBSS) ? 1 : 0;
+}
+
+static inline void
+__il_free_pages(struct il_priv *il, struct page *page)
+{
+       __free_pages(page, il->hw_params.rx_page_order);
+       il->alloc_rxb_page--;
+}
+
+static inline void
+il_free_pages(struct il_priv *il, unsigned long page)
+{
+       free_pages(page, il->hw_params.rx_page_order);
+       il->alloc_rxb_page--;
+}
+
+#define IWLWIFI_VERSION "in-tree:"
+#define DRV_COPYRIGHT  "Copyright(c) 2003-2011 Intel Corporation"
+#define DRV_AUTHOR     "<ilw@linux.intel.com>"
+
+#define IL_PCI_DEVICE(dev, subdev, cfg) \
+       .vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
+       .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
+       .driver_data = (kernel_ulong_t)&(cfg)
+
+#define TIME_UNIT              1024
+
+#define IL_SKU_G       0x1
+#define IL_SKU_A       0x2
+#define IL_SKU_N       0x8
+
+#define IL_CMD(x) case x: return #x
+
+/* Size of one Rx buffer in host DRAM */
+#define IL_RX_BUF_SIZE_3K (3 * 1000)   /* 3945 only */
+#define IL_RX_BUF_SIZE_4K (4 * 1024)
+#define IL_RX_BUF_SIZE_8K (8 * 1024)
+
+struct il_hcmd_ops {
+       int (*rxon_assoc) (struct il_priv *il, struct il_rxon_context *ctx);
+       int (*commit_rxon) (struct il_priv *il, struct il_rxon_context *ctx);
+       void (*set_rxon_chain) (struct il_priv *il,
+                               struct il_rxon_context *ctx);
+};
+
+struct il_hcmd_utils_ops {
+       u16(*get_hcmd_size) (u8 cmd_id, u16 len);
+       u16(*build_addsta_hcmd) (const struct il_addsta_cmd *cmd, u8 *data);
+       int (*request_scan) (struct il_priv *il, struct ieee80211_vif *vif);
+       void (*post_scan) (struct il_priv *il);
+};
+
+struct il_apm_ops {
+       int (*init) (struct il_priv *il);
+       void (*config) (struct il_priv *il);
+};
+
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+struct il_debugfs_ops {
+       ssize_t(*rx_stats_read) (struct file *file, char __user *user_buf,
+                                size_t count, loff_t *ppos);
+       ssize_t(*tx_stats_read) (struct file *file, char __user *user_buf,
+                                size_t count, loff_t *ppos);
+       ssize_t(*general_stats_read) (struct file *file,
+                                     char __user *user_buf, size_t count,
+                                     loff_t *ppos);
+};
+#endif
+
+struct il_temp_ops {
+       void (*temperature) (struct il_priv *il);
+};
+
+struct il_lib_ops {
+       /* set hw dependent parameters */
+       int (*set_hw_params) (struct il_priv *il);
+       /* Handling TX */
+       void (*txq_update_byte_cnt_tbl) (struct il_priv *il,
+                                        struct il_tx_queue *txq,
+                                        u16 byte_cnt);
+       int (*txq_attach_buf_to_tfd) (struct il_priv *il,
+                                     struct il_tx_queue *txq, dma_addr_t addr,
+                                     u16 len, u8 reset, u8 pad);
+       void (*txq_free_tfd) (struct il_priv *il, struct il_tx_queue *txq);
+       int (*txq_init) (struct il_priv *il, struct il_tx_queue *txq);
+       /* setup Rx handler */
+       void (*handler_setup) (struct il_priv *il);
+       /* alive notification after init uCode load */
+       void (*init_alive_start) (struct il_priv *il);
+       /* check validity of rtc data address */
+       int (*is_valid_rtc_data_addr) (u32 addr);
+       /* 1st ucode load */
+       int (*load_ucode) (struct il_priv *il);
+
+       void (*dump_nic_error_log) (struct il_priv *il);
+       int (*dump_fh) (struct il_priv *il, char **buf, bool display);
+       int (*set_channel_switch) (struct il_priv *il,
+                                  struct ieee80211_channel_switch *ch_switch);
+       /* power management */
+       struct il_apm_ops apm_ops;
+
+       /* power */
+       int (*send_tx_power) (struct il_priv *il);
+       void (*update_chain_flags) (struct il_priv *il);
+
+       /* eeprom operations */
+       struct il_eeprom_ops eeprom_ops;
+
+       /* temperature */
+       struct il_temp_ops temp_ops;
+
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+       struct il_debugfs_ops debugfs_ops;
+#endif
+
+};
+
+struct il_led_ops {
+       int (*cmd) (struct il_priv *il, struct il_led_cmd *led_cmd);
+};
+
+struct il_legacy_ops {
+       void (*post_associate) (struct il_priv *il);
+       void (*config_ap) (struct il_priv *il);
+       /* station management */
+       int (*update_bcast_stations) (struct il_priv *il);
+       int (*manage_ibss_station) (struct il_priv *il,
+                                   struct ieee80211_vif *vif, bool add);
+};
+
+struct il_ops {
+       const struct il_lib_ops *lib;
+       const struct il_hcmd_ops *hcmd;
+       const struct il_hcmd_utils_ops *utils;
+       const struct il_led_ops *led;
+       const struct il_nic_ops *nic;
+       const struct il_legacy_ops *legacy;
+       const struct ieee80211_ops *ieee80211_ops;
+};
+
+struct il_mod_params {
+       int sw_crypto;          /* def: 0 = using hardware encryption */
+       int disable_hw_scan;    /* def: 0 = use h/w scan */
+       int num_of_queues;      /* def: HW dependent */
+       int disable_11n;        /* def: 0 = 11n capabilities enabled */
+       int amsdu_size_8K;      /* def: 1 = enable 8K amsdu size */
+       int antenna;            /* def: 0 = both antennas (use diversity) */
+       int restart_fw;         /* def: 1 = restart firmware */
+};
+
+/*
+ * @led_compensation: compensate on the led on/off time per HW according
+ *     to the deviation to achieve the desired led frequency.
+ *     The detail algorithm is described in common.c
+ * @chain_noise_num_beacons: number of beacons used to compute chain noise
+ * @wd_timeout: TX queues watchdog timeout
+ * @temperature_kelvin: temperature report by uCode in kelvin
+ * @ucode_tracing: support ucode continuous tracing
+ * @sensitivity_calib_by_driver: driver has the capability to perform
+ *     sensitivity calibration operation
+ * @chain_noise_calib_by_driver: driver has the capability to perform
+ *     chain noise calibration operation
+ */
+struct il_base_params {
+       int eeprom_size;
+       int num_of_queues;      /* def: HW dependent */
+       int num_of_ampdu_queues;        /* def: HW dependent */
+       /* for il_apm_init() */
+       u32 pll_cfg_val;
+       bool set_l0s;
+       bool use_bsm;
+
+       u16 led_compensation;
+       int chain_noise_num_beacons;
+       unsigned int wd_timeout;
+       bool temperature_kelvin;
+       const bool ucode_tracing;
+       const bool sensitivity_calib_by_driver;
+       const bool chain_noise_calib_by_driver;
+};
+
+#define IL_LED_SOLID 11
+#define IL_DEF_LED_INTRVL cpu_to_le32(1000)
+
+#define IL_LED_ACTIVITY       (0<<1)
+#define IL_LED_LINK           (1<<1)
+
+/*
+ * LED mode
+ *    IL_LED_DEFAULT:  use device default
+ *    IL_LED_RF_STATE: turn LED on/off based on RF state
+ *                     LED ON  = RF ON
+ *                     LED OFF = RF OFF
+ *    IL_LED_BLINK:    adjust led blink rate based on blink table
+ */
+enum il_led_mode {
+       IL_LED_DEFAULT,
+       IL_LED_RF_STATE,
+       IL_LED_BLINK,
+};
+
+void il_leds_init(struct il_priv *il);
+void il_leds_exit(struct il_priv *il);
+
+/**
+ * struct il_cfg
+ * @fw_name_pre: Firmware filename prefix. The api version and extension
+ *     (.ucode) will be added to filename before loading from disk. The
+ *     filename is constructed as fw_name_pre<api>.ucode.
+ * @ucode_api_max: Highest version of uCode API supported by driver.
+ * @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @scan_antennas: available antenna for scan operation
+ * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
+ *
+ * We enable the driver to be backward compatible wrt API version. The
+ * driver specifies which APIs it supports (with @ucode_api_max being the
+ * highest and @ucode_api_min the lowest). Firmware will only be loaded if
+ * it has a supported API version. The firmware's API version will be
+ * stored in @il_priv, enabling the driver to make runtime changes based
+ * on firmware version used.
+ *
+ * For example,
+ * if (IL_UCODE_API(il->ucode_ver) >= 2) {
+ *     Driver interacts with Firmware API version >= 2.
+ * } else {
+ *     Driver interacts with Firmware API version 1.
+ * }
+ *
+ * The ideal usage of this infrastructure is to treat a new ucode API
+ * release as a new hardware revision. That is, through utilizing the
+ * il_hcmd_utils_ops etc. we accommodate different command structures
+ * and flows between hardware versions as well as their API
+ * versions.
+ *
+ */
+struct il_cfg {
+       /* params specific to an individual device within a device family */
+       const char *name;
+       const char *fw_name_pre;
+       const unsigned int ucode_api_max;
+       const unsigned int ucode_api_min;
+       u8 valid_tx_ant;
+       u8 valid_rx_ant;
+       unsigned int sku;
+       u16 eeprom_ver;
+       u16 eeprom_calib_ver;
+       const struct il_ops *ops;
+       /* module based parameters which can be set from modprobe cmd */
+       const struct il_mod_params *mod_params;
+       /* params not likely to change within a device family */
+       struct il_base_params *base_params;
+       /* params likely to change within a device family */
+       u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
+       enum il_led_mode led_mode;
+};
+
+/***************************
+ *   L i b                 *
+ ***************************/
+
+struct ieee80211_hw *il_alloc_all(struct il_cfg *cfg);
+int il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                  u16 queue, const struct ieee80211_tx_queue_params *params);
+int il_mac_tx_last_beacon(struct ieee80211_hw *hw);
+
+void il_set_rxon_hwcrypto(struct il_priv *il, struct il_rxon_context *ctx,
+                         int hw_decrypt);
+int il_check_rxon_cmd(struct il_priv *il, struct il_rxon_context *ctx);
+int il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx);
+int il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch,
+                       struct il_rxon_context *ctx);
+void il_set_flags_for_band(struct il_priv *il, struct il_rxon_context *ctx,
+                          enum ieee80211_band band, struct ieee80211_vif *vif);
+u8 il_get_single_channel_number(struct il_priv *il, enum ieee80211_band band);
+void il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf);
+bool il_is_ht40_tx_allowed(struct il_priv *il, struct il_rxon_context *ctx,
+                          struct ieee80211_sta_ht_cap *ht_cap);
+void il_connection_init_rx_config(struct il_priv *il,
+                                 struct il_rxon_context *ctx);
+void il_set_rate(struct il_priv *il);
+int il_set_decrypted_flag(struct il_priv *il, struct ieee80211_hdr *hdr,
+                         u32 decrypt_res, struct ieee80211_rx_status *stats);
+void il_irq_handle_error(struct il_priv *il);
+int il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void il_mac_remove_interface(struct ieee80211_hw *hw,
+                            struct ieee80211_vif *vif);
+int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                           enum nl80211_iftype newtype, bool newp2p);
+int il_alloc_txq_mem(struct il_priv *il);
+void il_txq_mem(struct il_priv *il);
+
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+int il_alloc_traffic_mem(struct il_priv *il);
+void il_free_traffic_mem(struct il_priv *il);
+void il_reset_traffic_log(struct il_priv *il);
+void il_dbg_log_tx_data_frame(struct il_priv *il, u16 length,
+                             struct ieee80211_hdr *header);
+void il_dbg_log_rx_data_frame(struct il_priv *il, u16 length,
+                             struct ieee80211_hdr *header);
+const char *il_get_mgmt_string(int cmd);
+const char *il_get_ctrl_string(int cmd);
+void il_clear_traffic_stats(struct il_priv *il);
+void il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len);
+#else
+static inline int
+il_alloc_traffic_mem(struct il_priv *il)
+{
+       return 0;
+}
+
+static inline void
+il_free_traffic_mem(struct il_priv *il)
+{
+}
+
+static inline void
+il_reset_traffic_log(struct il_priv *il)
+{
+}
+
+static inline void
+il_dbg_log_tx_data_frame(struct il_priv *il, u16 length,
+                        struct ieee80211_hdr *header)
+{
+}
+
+static inline void
+il_dbg_log_rx_data_frame(struct il_priv *il, u16 length,
+                        struct ieee80211_hdr *header)
+{
+}
+
+static inline void
+il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len)
+{
+}
+#endif
+/*****************************************************
+ * RX handlers.
+ * **************************************************/
+void il_hdl_pm_sleep(struct il_priv *il, struct il_rx_buf *rxb);
+void il_hdl_pm_debug_stats(struct il_priv *il, struct il_rx_buf *rxb);
+void il_hdl_error(struct il_priv *il, struct il_rx_buf *rxb);
+
+/*****************************************************
+* RX
+******************************************************/
+void il_cmd_queue_unmap(struct il_priv *il);
+void il_cmd_queue_free(struct il_priv *il);
+int il_rx_queue_alloc(struct il_priv *il);
+void il_rx_queue_update_write_ptr(struct il_priv *il, struct il_rx_queue *q);
+int il_rx_queue_space(const struct il_rx_queue *q);
+void il_tx_cmd_complete(struct il_priv *il, struct il_rx_buf *rxb);
+/* Handlers */
+void il_hdl_spectrum_measurement(struct il_priv *il, struct il_rx_buf *rxb);
+void il_recover_from_stats(struct il_priv *il, struct il_rx_pkt *pkt);
+void il_chswitch_done(struct il_priv *il, bool is_success);
+void il_hdl_csa(struct il_priv *il, struct il_rx_buf *rxb);
+
+/* TX helpers */
+
+/*****************************************************
+* TX
+******************************************************/
+void il_txq_update_write_ptr(struct il_priv *il, struct il_tx_queue *txq);
+int il_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq, int slots_num,
+                    u32 txq_id);
+void il_tx_queue_reset(struct il_priv *il, struct il_tx_queue *txq,
+                      int slots_num, u32 txq_id);
+void il_tx_queue_unmap(struct il_priv *il, int txq_id);
+void il_tx_queue_free(struct il_priv *il, int txq_id);
+void il_setup_watchdog(struct il_priv *il);
+/*****************************************************
+ * TX power
+ ****************************************************/
+int il_set_tx_power(struct il_priv *il, s8 tx_power, bool force);
+
+/*******************************************************************************
+ * Rate
+ ******************************************************************************/
+
+u8 il_get_lowest_plcp(struct il_priv *il, struct il_rxon_context *ctx);
+
+/*******************************************************************************
+ * Scanning
+ ******************************************************************************/
+void il_init_scan_params(struct il_priv *il);
+int il_scan_cancel(struct il_priv *il);
+int il_scan_cancel_timeout(struct il_priv *il, unsigned long ms);
+void il_force_scan_end(struct il_priv *il);
+int il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                  struct cfg80211_scan_request *req);
+void il_internal_short_hw_scan(struct il_priv *il);
+int il_force_reset(struct il_priv *il, bool external);
+u16 il_fill_probe_req(struct il_priv *il, struct ieee80211_mgmt *frame,
+                     const u8 *ta, const u8 *ie, int ie_len, int left);
+void il_setup_rx_scan_handlers(struct il_priv *il);
+u16 il_get_active_dwell_time(struct il_priv *il, enum ieee80211_band band,
+                            u8 n_probes);
+u16 il_get_passive_dwell_time(struct il_priv *il, enum ieee80211_band band,
+                             struct ieee80211_vif *vif);
+void il_setup_scan_deferred_work(struct il_priv *il);
+void il_cancel_scan_deferred_work(struct il_priv *il);
+
+/* 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 IL_ACTIVE_QUIET_TIME       cpu_to_le16(10)     /* msec */
+#define IL_PLCP_QUIET_THRESH       cpu_to_le16(1)      /* packets */
+
+#define IL_SCAN_CHECK_WATCHDOG         (HZ * 7)
+
+/*****************************************************
+ *   S e n d i n g     H o s t     C o m m a n d s   *
+ *****************************************************/
+
+const char *il_get_cmd_string(u8 cmd);
+int __must_check il_send_cmd_sync(struct il_priv *il, struct il_host_cmd *cmd);
+int il_send_cmd(struct il_priv *il, struct il_host_cmd *cmd);
+int __must_check il_send_cmd_pdu(struct il_priv *il, u8 id, u16 len,
+                                const void *data);
+int il_send_cmd_pdu_async(struct il_priv *il, u8 id, u16 len, const void *data,
+                         void (*callback) (struct il_priv *il,
+                                           struct il_device_cmd *cmd,
+                                           struct il_rx_pkt *pkt));
+
+int il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd);
+
+/*****************************************************
+ * PCI                                              *
+ *****************************************************/
+
+static inline u16
+il_pcie_link_ctl(struct il_priv *il)
+{
+       int pos;
+       u16 pci_lnk_ctl;
+       pos = pci_pcie_cap(il->pci_dev);
+       pci_read_config_word(il->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+       return pci_lnk_ctl;
+}
+
+void il_bg_watchdog(unsigned long data);
+u32 il_usecs_to_beacons(struct il_priv *il, u32 usec, u32 beacon_interval);
+__le32 il_add_beacon_time(struct il_priv *il, u32 base, u32 addon,
+                         u32 beacon_interval);
+
+#ifdef CONFIG_PM
+int il_pci_suspend(struct device *device);
+int il_pci_resume(struct device *device);
+extern const struct dev_pm_ops il_pm_ops;
+
+#define IL_LEGACY_PM_OPS       (&il_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define IL_LEGACY_PM_OPS       NULL
+
+#endif /* !CONFIG_PM */
+
+/*****************************************************
+*  Error Handling Debugging
+******************************************************/
+void il4965_dump_nic_error_log(struct il_priv *il);
+#ifdef CONFIG_IWLEGACY_DEBUG
+void il_print_rx_config_cmd(struct il_priv *il, struct il_rxon_context *ctx);
+#else
+static inline void
+il_print_rx_config_cmd(struct il_priv *il, struct il_rxon_context *ctx)
+{
+}
+#endif
+
+void il_clear_isr_stats(struct il_priv *il);
+
+/*****************************************************
+*  GEOS
+******************************************************/
+int il_init_geos(struct il_priv *il);
+void il_free_geos(struct il_priv *il);
+
+/*************** DRIVER STATUS FUNCTIONS   *****/
+
+#define S_HCMD_ACTIVE  0       /* host command in progress */
+/* 1 is unused (used to be S_HCMD_SYNC_ACTIVE) */
+#define S_INT_ENABLED  2
+#define S_RF_KILL_HW   3
+#define S_CT_KILL              4
+#define S_INIT         5
+#define S_ALIVE                6
+#define S_READY                7
+#define S_TEMPERATURE  8
+#define S_GEO_CONFIGURED       9
+#define S_EXIT_PENDING 10
+#define S_STATS                12
+#define S_SCANNING             13
+#define S_SCAN_ABORTING        14
+#define S_SCAN_HW              15
+#define S_POWER_PMI    16
+#define S_FW_ERROR             17
+#define S_CHANNEL_SWITCH_PENDING 18
+
+static inline int
+il_is_ready(struct il_priv *il)
+{
+       /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
+        * set but EXIT_PENDING is not */
+       return test_bit(S_READY, &il->status) &&
+           test_bit(S_GEO_CONFIGURED, &il->status) &&
+           !test_bit(S_EXIT_PENDING, &il->status);
+}
+
+static inline int
+il_is_alive(struct il_priv *il)
+{
+       return test_bit(S_ALIVE, &il->status);
+}
+
+static inline int
+il_is_init(struct il_priv *il)
+{
+       return test_bit(S_INIT, &il->status);
+}
+
+static inline int
+il_is_rfkill_hw(struct il_priv *il)
+{
+       return test_bit(S_RF_KILL_HW, &il->status);
+}
+
+static inline int
+il_is_rfkill(struct il_priv *il)
+{
+       return il_is_rfkill_hw(il);
+}
+
+static inline int
+il_is_ctkill(struct il_priv *il)
+{
+       return test_bit(S_CT_KILL, &il->status);
+}
+
+static inline int
+il_is_ready_rf(struct il_priv *il)
+{
+
+       if (il_is_rfkill(il))
+               return 0;
+
+       return il_is_ready(il);
+}
+
+extern void il_send_bt_config(struct il_priv *il);
+extern int il_send_stats_request(struct il_priv *il, u8 flags, bool clear);
+void il_apm_stop(struct il_priv *il);
+int il_apm_init(struct il_priv *il);
+
+int il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx);
+static inline int
+il_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       return il->cfg->ops->hcmd->rxon_assoc(il, ctx);
+}
+
+static inline int
+il_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx)
+{
+       return il->cfg->ops->hcmd->commit_rxon(il, ctx);
+}
+
+static inline const struct ieee80211_supported_band *
+il_get_hw_mode(struct il_priv *il, enum ieee80211_band band)
+{
+       return il->hw->wiphy->bands[band];
+}
+
+/* mac80211 handlers */
+int il_mac_config(struct ieee80211_hw *hw, u32 changed);
+void il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                            struct ieee80211_bss_conf *bss_conf, u32 changes);
+void il_tx_cmd_protection(struct il_priv *il, struct ieee80211_tx_info *info,
+                         __le16 fc, __le32 *tx_flags);
+
+irqreturn_t il_isr(int irq, void *data);
+
+#include <linux/io.h>
+
+static inline void
+_il_write8(struct il_priv *il, u32 ofs, u8 val)
+{
+       iowrite8(val, il->hw_base + ofs);
+}
+#define il_write8(il, ofs, val) _il_write8(il, ofs, val)
+
+static inline void
+_il_wr(struct il_priv *il, u32 ofs, u32 val)
+{
+       iowrite32(val, il->hw_base + ofs);
+}
+
+static inline u32
+_il_rd(struct il_priv *il, u32 ofs)
+{
+       return ioread32(il->hw_base + ofs);
+}
+
+#define IL_POLL_INTERVAL 10    /* microseconds */
+static inline int
+_il_poll_bit(struct il_priv *il, u32 addr, u32 bits, u32 mask, int timeout)
+{
+       int t = 0;
+
+       do {
+               if ((_il_rd(il, addr) & mask) == (bits & mask))
+                       return t;
+               udelay(IL_POLL_INTERVAL);
+               t += IL_POLL_INTERVAL;
+       } while (t < timeout);
+
+       return -ETIMEDOUT;
+}
+
+static inline void
+_il_set_bit(struct il_priv *il, u32 reg, u32 mask)
+{
+       _il_wr(il, reg, _il_rd(il, reg) | mask);
+}
+
+static inline void
+il_set_bit(struct il_priv *p, u32 r, u32 m)
+{
+       unsigned long reg_flags;
+
+       spin_lock_irqsave(&p->reg_lock, reg_flags);
+       _il_set_bit(p, r, m);
+       spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
+
+static inline void
+_il_clear_bit(struct il_priv *il, u32 reg, u32 mask)
+{
+       _il_wr(il, reg, _il_rd(il, reg) & ~mask);
+}
+
+static inline void
+il_clear_bit(struct il_priv *p, u32 r, u32 m)
+{
+       unsigned long reg_flags;
+
+       spin_lock_irqsave(&p->reg_lock, reg_flags);
+       _il_clear_bit(p, r, m);
+       spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
+
+static inline int
+_il_grab_nic_access(struct il_priv *il)
+{
+       int ret;
+       u32 val;
+
+       /* this bit wakes up the NIC */
+       _il_set_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+       /*
+        * These bits say the device is running, and should keep running for
+        * at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
+        * but they do not indicate that embedded SRAM is restored yet;
+        * 3945 and 4965 have volatile SRAM, and must save/restore contents
+        * to/from host DRAM when sleeping/waking for power-saving.
+        * Each direction takes approximately 1/4 millisecond; with this
+        * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
+        * series of register accesses are expected (e.g. reading Event Log),
+        * to keep device from sleeping.
+        *
+        * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
+        * SRAM is okay/restored.  We don't check that here because this call
+        * is just for hardware register access; but GP1 MAC_SLEEP check is a
+        * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
+        *
+        */
+       ret =
+           _il_poll_bit(il, 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), 15000);
+       if (ret < 0) {
+               val = _il_rd(il, CSR_GP_CNTRL);
+               IL_ERR("MAC is in deep sleep!.  CSR_GP_CNTRL = 0x%08X\n", val);
+               _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static inline void
+_il_release_nic_access(struct il_priv *il)
+{
+       _il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+}
+
+static inline u32
+il_rd(struct il_priv *il, u32 reg)
+{
+       u32 value;
+       unsigned long reg_flags;
+
+       spin_lock_irqsave(&il->reg_lock, reg_flags);
+       _il_grab_nic_access(il);
+       value = _il_rd(il, reg);
+       _il_release_nic_access(il);
+       spin_unlock_irqrestore(&il->reg_lock, reg_flags);
+       return value;
+
+}
+
+static inline void
+il_wr(struct il_priv *il, u32 reg, u32 value)
+{
+       unsigned long reg_flags;
+
+       spin_lock_irqsave(&il->reg_lock, reg_flags);
+       if (!_il_grab_nic_access(il)) {
+               _il_wr(il, reg, value);
+               _il_release_nic_access(il);
+       }
+       spin_unlock_irqrestore(&il->reg_lock, reg_flags);
+}
+
+static inline void
+il_write_reg_buf(struct il_priv *il, u32 reg, u32 len, u32 * values)
+{
+       u32 count = sizeof(u32);
+
+       if (il != NULL && values != NULL) {
+               for (; 0 < len; len -= count, reg += count, values++)
+                       il_wr(il, reg, *values);
+       }
+}
+
+static inline int
+il_poll_bit(struct il_priv *il, u32 addr, u32 mask, int timeout)
+{
+       int t = 0;
+
+       do {
+               if ((il_rd(il, addr) & mask) == mask)
+                       return t;
+               udelay(IL_POLL_INTERVAL);
+               t += IL_POLL_INTERVAL;
+       } while (t < timeout);
+
+       return -ETIMEDOUT;
+}
+
+static inline u32
+_il_rd_prph(struct il_priv *il, u32 reg)
+{
+       _il_wr(il, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+       rmb();
+       return _il_rd(il, HBUS_TARG_PRPH_RDAT);
+}
+
+static inline u32
+il_rd_prph(struct il_priv *il, u32 reg)
+{
+       unsigned long reg_flags;
+       u32 val;
+
+       spin_lock_irqsave(&il->reg_lock, reg_flags);
+       _il_grab_nic_access(il);
+       val = _il_rd_prph(il, reg);
+       _il_release_nic_access(il);
+       spin_unlock_irqrestore(&il->reg_lock, reg_flags);
+       return val;
+}
+
+static inline void
+_il_wr_prph(struct il_priv *il, u32 addr, u32 val)
+{
+       _il_wr(il, HBUS_TARG_PRPH_WADDR, ((addr & 0x0000FFFF) | (3 << 24)));
+       wmb();
+       _il_wr(il, HBUS_TARG_PRPH_WDAT, val);
+}
+
+static inline void
+il_wr_prph(struct il_priv *il, u32 addr, u32 val)
+{
+       unsigned long reg_flags;
+
+       spin_lock_irqsave(&il->reg_lock, reg_flags);
+       if (!_il_grab_nic_access(il)) {
+               _il_wr_prph(il, addr, val);
+               _il_release_nic_access(il);
+       }
+       spin_unlock_irqrestore(&il->reg_lock, reg_flags);
+}
+
+#define _il_set_bits_prph(il, reg, mask) \
+_il_wr_prph(il, reg, (_il_rd_prph(il, reg) | mask))
+
+static inline void
+il_set_bits_prph(struct il_priv *il, u32 reg, u32 mask)
+{
+       unsigned long reg_flags;
+
+       spin_lock_irqsave(&il->reg_lock, reg_flags);
+       _il_grab_nic_access(il);
+       _il_set_bits_prph(il, reg, mask);
+       _il_release_nic_access(il);
+       spin_unlock_irqrestore(&il->reg_lock, reg_flags);
+}
+
+#define _il_set_bits_mask_prph(il, reg, bits, mask) \
+_il_wr_prph(il, reg,                           \
+                ((_il_rd_prph(il, reg) & mask) | bits))
+
+static inline void
+il_set_bits_mask_prph(struct il_priv *il, u32 reg, u32 bits, u32 mask)
+{
+       unsigned long reg_flags;
+
+       spin_lock_irqsave(&il->reg_lock, reg_flags);
+       _il_grab_nic_access(il);
+       _il_set_bits_mask_prph(il, reg, bits, mask);
+       _il_release_nic_access(il);
+       spin_unlock_irqrestore(&il->reg_lock, reg_flags);
+}
+
+static inline void
+il_clear_bits_prph(struct il_priv *il, u32 reg, u32 mask)
+{
+       unsigned long reg_flags;
+       u32 val;
+
+       spin_lock_irqsave(&il->reg_lock, reg_flags);
+       _il_grab_nic_access(il);
+       val = _il_rd_prph(il, reg);
+       _il_wr_prph(il, reg, (val & ~mask));
+       _il_release_nic_access(il);
+       spin_unlock_irqrestore(&il->reg_lock, reg_flags);
+}
+
+static inline u32
+il_read_targ_mem(struct il_priv *il, u32 addr)
+{
+       unsigned long reg_flags;
+       u32 value;
+
+       spin_lock_irqsave(&il->reg_lock, reg_flags);
+       _il_grab_nic_access(il);
+
+       _il_wr(il, HBUS_TARG_MEM_RADDR, addr);
+       rmb();
+       value = _il_rd(il, HBUS_TARG_MEM_RDAT);
+
+       _il_release_nic_access(il);
+       spin_unlock_irqrestore(&il->reg_lock, reg_flags);
+       return value;
+}
+
+static inline void
+il_write_targ_mem(struct il_priv *il, u32 addr, u32 val)
+{
+       unsigned long reg_flags;
+
+       spin_lock_irqsave(&il->reg_lock, reg_flags);
+       if (!_il_grab_nic_access(il)) {
+               _il_wr(il, HBUS_TARG_MEM_WADDR, addr);
+               wmb();
+               _il_wr(il, HBUS_TARG_MEM_WDAT, val);
+               _il_release_nic_access(il);
+       }
+       spin_unlock_irqrestore(&il->reg_lock, reg_flags);
+}
+
+static inline void
+il_write_targ_mem_buf(struct il_priv *il, u32 addr, u32 len, u32 * values)
+{
+       unsigned long reg_flags;
+
+       spin_lock_irqsave(&il->reg_lock, reg_flags);
+       if (!_il_grab_nic_access(il)) {
+               _il_wr(il, HBUS_TARG_MEM_WADDR, addr);
+               wmb();
+               for (; 0 < len; len -= sizeof(u32), values++)
+                       _il_wr(il, HBUS_TARG_MEM_WDAT, *values);
+
+               _il_release_nic_access(il);
+       }
+       spin_unlock_irqrestore(&il->reg_lock, reg_flags);
+}
+
+#define HW_KEY_DYNAMIC 0
+#define HW_KEY_DEFAULT 1
+
+#define IL_STA_DRIVER_ACTIVE BIT(0)    /* driver entry is active */
+#define IL_STA_UCODE_ACTIVE  BIT(1)    /* ucode entry is active */
+#define IL_STA_UCODE_INPROGRESS  BIT(2)        /* ucode entry is in process of
+                                          being activated */
+#define IL_STA_LOCAL BIT(3)    /* station state not directed by mac80211;
+                                  (this is for the IBSS BSSID stations) */
+#define IL_STA_BCAST BIT(4)    /* this station is the special bcast station */
+
+void il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx);
+void il_clear_ucode_stations(struct il_priv *il, struct il_rxon_context *ctx);
+void il_dealloc_bcast_stations(struct il_priv *il);
+int il_get_free_ucode_key_idx(struct il_priv *il);
+int il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags);
+int il_add_station_common(struct il_priv *il, struct il_rxon_context *ctx,
+                         const u8 *addr, bool is_ap,
+                         struct ieee80211_sta *sta, u8 *sta_id_r);
+int il_remove_station(struct il_priv *il, const u8 sta_id, const u8 * addr);
+int il_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                     struct ieee80211_sta *sta);
+
+u8 il_prep_station(struct il_priv *il, struct il_rxon_context *ctx,
+                  const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
+
+int il_send_lq_cmd(struct il_priv *il, struct il_rxon_context *ctx,
+                  struct il_link_quality_cmd *lq, u8 flags, bool init);
+
+/**
+ * il_clear_driver_stations - clear knowledge of all stations from driver
+ * @il: iwl il struct
+ *
+ * This is called during il_down() to make sure that in the case
+ * we're coming there from a hardware restart mac80211 will be
+ * able to reconfigure stations -- if we're getting there in the
+ * normal down flow then the stations will already be cleared.
+ */
+static inline void
+il_clear_driver_stations(struct il_priv *il)
+{
+       unsigned long flags;
+       struct il_rxon_context *ctx = &il->ctx;
+
+       spin_lock_irqsave(&il->sta_lock, flags);
+       memset(il->stations, 0, sizeof(il->stations));
+       il->num_stations = 0;
+
+       il->ucode_key_table = 0;
+
+       /*
+        * Remove all key information that is not stored as part
+        * of station information since mac80211 may not have had
+        * a chance to remove all the keys. When device is
+        * reconfigured by mac80211 after an error all keys will
+        * be reconfigured.
+        */
+       memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
+       ctx->key_mapping_keys = 0;
+
+       spin_unlock_irqrestore(&il->sta_lock, flags);
+}
+
+static inline int
+il_sta_id(struct ieee80211_sta *sta)
+{
+       if (WARN_ON(!sta))
+               return IL_INVALID_STATION;
+
+       return ((struct il_station_priv_common *)sta->drv_priv)->sta_id;
+}
+
+/**
+ * il_sta_id_or_broadcast - return sta_id or broadcast sta
+ * @il: iwl il
+ * @context: the current context
+ * @sta: mac80211 station
+ *
+ * In certain circumstances mac80211 passes a station pointer
+ * that may be %NULL, for example during TX or key setup. In
+ * that case, we need to use the broadcast station, so this
+ * inline wraps that pattern.
+ */
+static inline int
+il_sta_id_or_broadcast(struct il_priv *il, struct il_rxon_context *context,
+                      struct ieee80211_sta *sta)
+{
+       int sta_id;
+
+       if (!sta)
+               return context->bcast_sta_id;
+
+       sta_id = il_sta_id(sta);
+
+       /*
+        * mac80211 should not be passing a partially
+        * initialised station!
+        */
+       WARN_ON(sta_id == IL_INVALID_STATION);
+
+       return sta_id;
+}
+
+/**
+ * il_queue_inc_wrap - increment queue idx, wrap back to beginning
+ * @idx -- current idx
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int
+il_queue_inc_wrap(int idx, int n_bd)
+{
+       return ++idx & (n_bd - 1);
+}
+
+/**
+ * il_queue_dec_wrap - decrement queue idx, wrap back to end
+ * @idx -- current idx
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int
+il_queue_dec_wrap(int idx, int n_bd)
+{
+       return --idx & (n_bd - 1);
+}
+
+/* TODO: Move fw_desc functions to iwl-pci.ko */
+static inline void
+il_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
+{
+       if (desc->v_addr)
+               dma_free_coherent(&pci_dev->dev, desc->len, desc->v_addr,
+                                 desc->p_addr);
+       desc->v_addr = NULL;
+       desc->len = 0;
+}
+
+static inline int
+il_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
+{
+       if (!desc->len) {
+               desc->v_addr = NULL;
+               return -EINVAL;
+       }
+
+       desc->v_addr =
+           dma_alloc_coherent(&pci_dev->dev, desc->len, &desc->p_addr,
+                              GFP_KERNEL);
+       return (desc->v_addr != NULL) ? 0 : -ENOMEM;
+}
+
+/*
+ * we have 8 bits used like this:
+ *
+ * 7 6 5 4 3 2 1 0
+ * | | | | | | | |
+ * | | | | | | +-+-------- AC queue (0-3)
+ * | | | | | |
+ * | +-+-+-+-+------------ HW queue ID
+ * |
+ * +---------------------- unused
+ */
+static inline void
+il_set_swq_id(struct il_tx_queue *txq, u8 ac, u8 hwq)
+{
+       BUG_ON(ac > 3);         /* only have 2 bits */
+       BUG_ON(hwq > 31);       /* only use 5 bits */
+
+       txq->swq_id = (hwq << 2) | ac;
+}
+
+static inline void
+il_wake_queue(struct il_priv *il, struct il_tx_queue *txq)
+{
+       u8 queue = txq->swq_id;
+       u8 ac = queue & 3;
+       u8 hwq = (queue >> 2) & 0x1f;
+
+       if (test_and_clear_bit(hwq, il->queue_stopped))
+               if (atomic_dec_return(&il->queue_stop_count[ac]) <= 0)
+                       ieee80211_wake_queue(il->hw, ac);
+}
+
+static inline void
+il_stop_queue(struct il_priv *il, struct il_tx_queue *txq)
+{
+       u8 queue = txq->swq_id;
+       u8 ac = queue & 3;
+       u8 hwq = (queue >> 2) & 0x1f;
+
+       if (!test_and_set_bit(hwq, il->queue_stopped))
+               if (atomic_inc_return(&il->queue_stop_count[ac]) > 0)
+                       ieee80211_stop_queue(il->hw, ac);
+}
+
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
+#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
+#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
+
+static inline void
+il_disable_interrupts(struct il_priv *il)
+{
+       clear_bit(S_INT_ENABLED, &il->status);
+
+       /* disable interrupts from uCode/NIC to host */
+       _il_wr(il, CSR_INT_MASK, 0x00000000);
+
+       /* acknowledge/clear/reset any interrupts still pending
+        * from uCode or flow handler (Rx/Tx DMA) */
+       _il_wr(il, CSR_INT, 0xffffffff);
+       _il_wr(il, CSR_FH_INT_STATUS, 0xffffffff);
+}
+
+static inline void
+il_enable_rfkill_int(struct il_priv *il)
+{
+       _il_wr(il, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+}
+
+static inline void
+il_enable_interrupts(struct il_priv *il)
+{
+       set_bit(S_INT_ENABLED, &il->status);
+       _il_wr(il, CSR_INT_MASK, il->inta_mask);
+}
+
+/**
+ * il_beacon_time_mask_low - mask of lower 32 bit of beacon time
+ * @il -- pointer to il_priv data structure
+ * @tsf_bits -- number of bits need to shift for masking)
+ */
+static inline u32
+il_beacon_time_mask_low(struct il_priv *il, u16 tsf_bits)
+{
+       return (1 << tsf_bits) - 1;
+}
+
+/**
+ * il_beacon_time_mask_high - mask of higher 32 bit of beacon time
+ * @il -- pointer to il_priv data structure
+ * @tsf_bits -- number of bits need to shift for masking)
+ */
+static inline u32
+il_beacon_time_mask_high(struct il_priv *il, u16 tsf_bits)
+{
+       return ((1 << (32 - tsf_bits)) - 1) << tsf_bits;
+}
+
+/**
+ * struct il_rb_status - reseve buffer status host memory mapped FH registers
+ *
+ * @closed_rb_num [0:11] - Indicates the idx of the RB which was closed
+ * @closed_fr_num [0:11] - Indicates the idx of the RX Frame which was closed
+ * @finished_rb_num [0:11] - Indicates the idx of the current RB
+ *                          in which the last frame was written to
+ * @finished_fr_num [0:11] - Indicates the idx of the RX Frame
+ *                          which was transferred
+ */
+struct il_rb_status {
+       __le16 closed_rb_num;
+       __le16 closed_fr_num;
+       __le16 finished_rb_num;
+       __le16 finished_fr_nam;
+       __le32 __unused;        /* 3945 only */
+} __packed;
+
+#define TFD_QUEUE_SIZE_MAX      (256)
+#define TFD_QUEUE_SIZE_BC_DUP  (64)
+#define TFD_QUEUE_BC_SIZE      (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
+#define IL_TX_DMA_MASK        DMA_BIT_MASK(36)
+#define IL_NUM_OF_TBS          20
+
+static inline u8
+il_get_dma_hi_addr(dma_addr_t addr)
+{
+       return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
+}
+
+/**
+ * struct il_tfd_tb transmit buffer descriptor within transmit frame descriptor
+ *
+ * This structure contains dma address and length of transmission address
+ *
+ * @lo: low [31:0] portion of the dma address of TX buffer every even is
+ *     unaligned on 16 bit boundary
+ * @hi_n_len: 0-3 [35:32] portion of dma
+ *           4-15 length of the tx buffer
+ */
+struct il_tfd_tb {
+       __le32 lo;
+       __le16 hi_n_len;
+} __packed;
+
+/**
+ * struct il_tfd
+ *
+ * Transmit Frame Descriptor (TFD)
+ *
+ * @ __reserved1[3] reserved
+ * @ num_tbs 0-4 number of active tbs
+ *          5   reserved
+ *          6-7 padding (not used)
+ * @ tbs[20]   transmit frame buffer descriptors
+ * @ __pad     padding
+ *
+ * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
+ * Both driver and device share these circular buffers, each of which must be
+ * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
+ *
+ * Driver must indicate the physical address of the base of each
+ * circular buffer via the FH49_MEM_CBBC_QUEUE registers.
+ *
+ * Each TFD contains pointer/size information for up to 20 data buffers
+ * in host DRAM.  These buffers collectively contain the (one) frame described
+ * by the TFD.  Each buffer must be a single contiguous block of memory within
+ * itself, but buffers may be scattered in host DRAM.  Each buffer has max size
+ * of (4K - 4).  The concatenates all of a TFD's buffers into a single
+ * Tx frame, up to 8 KBytes in size.
+ *
+ * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
+ */
+struct il_tfd {
+       u8 __reserved1[3];
+       u8 num_tbs;
+       struct il_tfd_tb tbs[IL_NUM_OF_TBS];
+       __le32 __pad;
+} __packed;
+/* PCI registers */
+#define PCI_CFG_RETRY_TIMEOUT  0x041
+
+/* PCI register values */
+#define PCI_CFG_LINK_CTRL_VAL_L0S_EN   0x01
+#define PCI_CFG_LINK_CTRL_VAL_L1_EN    0x02
+
+struct il_rate_info {
+       u8 plcp;                /* uCode API:  RATE_6M_PLCP, etc. */
+       u8 plcp_siso;           /* uCode API:  RATE_SISO_6M_PLCP, etc. */
+       u8 plcp_mimo2;          /* uCode API:  RATE_MIMO2_6M_PLCP, etc. */
+       u8 ieee;                /* MAC header:  RATE_6M_IEEE, etc. */
+       u8 prev_ieee;           /* previous rate in IEEE speeds */
+       u8 next_ieee;           /* next rate in IEEE speeds */
+       u8 prev_rs;             /* previous rate used in rs algo */
+       u8 next_rs;             /* next rate used in rs algo */
+       u8 prev_rs_tgg;         /* previous rate used in TGG rs algo */
+       u8 next_rs_tgg;         /* next rate used in TGG rs algo */
+};
+
+struct il3945_rate_info {
+       u8 plcp;                /* uCode API:  RATE_6M_PLCP, etc. */
+       u8 ieee;                /* MAC header:  RATE_6M_IEEE, etc. */
+       u8 prev_ieee;           /* previous rate in IEEE speeds */
+       u8 next_ieee;           /* next rate in IEEE speeds */
+       u8 prev_rs;             /* previous rate used in rs algo */
+       u8 next_rs;             /* next rate used in rs algo */
+       u8 prev_rs_tgg;         /* previous rate used in TGG rs algo */
+       u8 next_rs_tgg;         /* next rate used in TGG rs algo */
+       u8 table_rs_idx;        /* idx in rate scale table cmd */
+       u8 prev_table_rs;       /* prev in rate table cmd */
+};
+
+/*
+ * These serve as idxes into
+ * struct il_rate_info il_rates[RATE_COUNT];
+ */
+enum {
+       RATE_1M_IDX = 0,
+       RATE_2M_IDX,
+       RATE_5M_IDX,
+       RATE_11M_IDX,
+       RATE_6M_IDX,
+       RATE_9M_IDX,
+       RATE_12M_IDX,
+       RATE_18M_IDX,
+       RATE_24M_IDX,
+       RATE_36M_IDX,
+       RATE_48M_IDX,
+       RATE_54M_IDX,
+       RATE_60M_IDX,
+       RATE_COUNT,
+       RATE_COUNT_LEGACY = RATE_COUNT - 1,     /* Excluding 60M */
+       RATE_COUNT_3945 = RATE_COUNT - 1,
+       RATE_INVM_IDX = RATE_COUNT,
+       RATE_INVALID = RATE_COUNT,
+};
+
+enum {
+       RATE_6M_IDX_TBL = 0,
+       RATE_9M_IDX_TBL,
+       RATE_12M_IDX_TBL,
+       RATE_18M_IDX_TBL,
+       RATE_24M_IDX_TBL,
+       RATE_36M_IDX_TBL,
+       RATE_48M_IDX_TBL,
+       RATE_54M_IDX_TBL,
+       RATE_1M_IDX_TBL,
+       RATE_2M_IDX_TBL,
+       RATE_5M_IDX_TBL,
+       RATE_11M_IDX_TBL,
+       RATE_INVM_IDX_TBL = RATE_INVM_IDX - 1,
+};
+
+enum {
+       IL_FIRST_OFDM_RATE = RATE_6M_IDX,
+       IL39_LAST_OFDM_RATE = RATE_54M_IDX,
+       IL_LAST_OFDM_RATE = RATE_60M_IDX,
+       IL_FIRST_CCK_RATE = RATE_1M_IDX,
+       IL_LAST_CCK_RATE = RATE_11M_IDX,
+};
+
+/* #define vs. enum to keep from defaulting to 'large integer' */
+#define        RATE_6M_MASK   (1 << RATE_6M_IDX)
+#define        RATE_9M_MASK   (1 << RATE_9M_IDX)
+#define        RATE_12M_MASK  (1 << RATE_12M_IDX)
+#define        RATE_18M_MASK  (1 << RATE_18M_IDX)
+#define        RATE_24M_MASK  (1 << RATE_24M_IDX)
+#define        RATE_36M_MASK  (1 << RATE_36M_IDX)
+#define        RATE_48M_MASK  (1 << RATE_48M_IDX)
+#define        RATE_54M_MASK  (1 << RATE_54M_IDX)
+#define RATE_60M_MASK  (1 << RATE_60M_IDX)
+#define        RATE_1M_MASK   (1 << RATE_1M_IDX)
+#define        RATE_2M_MASK   (1 << RATE_2M_IDX)
+#define        RATE_5M_MASK   (1 << RATE_5M_IDX)
+#define        RATE_11M_MASK  (1 << RATE_11M_IDX)
+
+/* uCode API values for legacy bit rates, both OFDM and CCK */
+enum {
+       RATE_6M_PLCP = 13,
+       RATE_9M_PLCP = 15,
+       RATE_12M_PLCP = 5,
+       RATE_18M_PLCP = 7,
+       RATE_24M_PLCP = 9,
+       RATE_36M_PLCP = 11,
+       RATE_48M_PLCP = 1,
+       RATE_54M_PLCP = 3,
+       RATE_60M_PLCP = 3,      /*FIXME:RS:should be removed */
+       RATE_1M_PLCP = 10,
+       RATE_2M_PLCP = 20,
+       RATE_5M_PLCP = 55,
+       RATE_11M_PLCP = 110,
+       /*FIXME:RS:add RATE_LEGACY_INVM_PLCP = 0, */
+};
+
+/* uCode API values for OFDM high-throughput (HT) bit rates */
+enum {
+       RATE_SISO_6M_PLCP = 0,
+       RATE_SISO_12M_PLCP = 1,
+       RATE_SISO_18M_PLCP = 2,
+       RATE_SISO_24M_PLCP = 3,
+       RATE_SISO_36M_PLCP = 4,
+       RATE_SISO_48M_PLCP = 5,
+       RATE_SISO_54M_PLCP = 6,
+       RATE_SISO_60M_PLCP = 7,
+       RATE_MIMO2_6M_PLCP = 0x8,
+       RATE_MIMO2_12M_PLCP = 0x9,
+       RATE_MIMO2_18M_PLCP = 0xa,
+       RATE_MIMO2_24M_PLCP = 0xb,
+       RATE_MIMO2_36M_PLCP = 0xc,
+       RATE_MIMO2_48M_PLCP = 0xd,
+       RATE_MIMO2_54M_PLCP = 0xe,
+       RATE_MIMO2_60M_PLCP = 0xf,
+       RATE_SISO_INVM_PLCP,
+       RATE_MIMO2_INVM_PLCP = RATE_SISO_INVM_PLCP,
+};
+
+/* MAC header values for bit rates */
+enum {
+       RATE_6M_IEEE = 12,
+       RATE_9M_IEEE = 18,
+       RATE_12M_IEEE = 24,
+       RATE_18M_IEEE = 36,
+       RATE_24M_IEEE = 48,
+       RATE_36M_IEEE = 72,
+       RATE_48M_IEEE = 96,
+       RATE_54M_IEEE = 108,
+       RATE_60M_IEEE = 120,
+       RATE_1M_IEEE = 2,
+       RATE_2M_IEEE = 4,
+       RATE_5M_IEEE = 11,
+       RATE_11M_IEEE = 22,
+};
+
+#define IL_CCK_BASIC_RATES_MASK    \
+       (RATE_1M_MASK          | \
+       RATE_2M_MASK)
+
+#define IL_CCK_RATES_MASK          \
+       (IL_CCK_BASIC_RATES_MASK  | \
+       RATE_5M_MASK          | \
+       RATE_11M_MASK)
+
+#define IL_OFDM_BASIC_RATES_MASK   \
+       (RATE_6M_MASK         | \
+       RATE_12M_MASK         | \
+       RATE_24M_MASK)
+
+#define IL_OFDM_RATES_MASK         \
+       (IL_OFDM_BASIC_RATES_MASK | \
+       RATE_9M_MASK          | \
+       RATE_18M_MASK         | \
+       RATE_36M_MASK         | \
+       RATE_48M_MASK         | \
+       RATE_54M_MASK)
+
+#define IL_BASIC_RATES_MASK         \
+       (IL_OFDM_BASIC_RATES_MASK | \
+        IL_CCK_BASIC_RATES_MASK)
+
+#define RATES_MASK ((1 << RATE_COUNT) - 1)
+#define RATES_MASK_3945 ((1 << RATE_COUNT_3945) - 1)
+
+#define IL_INVALID_VALUE    -1
+
+#define IL_MIN_RSSI_VAL                 -100
+#define IL_MAX_RSSI_VAL                    0
+
+/* These values specify how many Tx frame attempts before
+ * searching for a new modulation mode */
+#define IL_LEGACY_FAILURE_LIMIT        160
+#define IL_LEGACY_SUCCESS_LIMIT        480
+#define IL_LEGACY_TBL_COUNT            160
+
+#define IL_NONE_LEGACY_FAILURE_LIMIT   400
+#define IL_NONE_LEGACY_SUCCESS_LIMIT   4500
+#define IL_NONE_LEGACY_TBL_COUNT       1500
+
+/* Success ratio (ACKed / attempted tx frames) values (perfect is 128 * 100) */
+#define IL_RS_GOOD_RATIO               12800   /* 100% */
+#define RATE_SCALE_SWITCH              10880   /*  85% */
+#define RATE_HIGH_TH           10880   /*  85% */
+#define RATE_INCREASE_TH               6400    /*  50% */
+#define RATE_DECREASE_TH               1920    /*  15% */
+
+/* possible actions when in legacy mode */
+#define IL_LEGACY_SWITCH_ANTENNA1      0
+#define IL_LEGACY_SWITCH_ANTENNA2      1
+#define IL_LEGACY_SWITCH_SISO          2
+#define IL_LEGACY_SWITCH_MIMO2_AB      3
+#define IL_LEGACY_SWITCH_MIMO2_AC      4
+#define IL_LEGACY_SWITCH_MIMO2_BC      5
+
+/* possible actions when in siso mode */
+#define IL_SISO_SWITCH_ANTENNA1        0
+#define IL_SISO_SWITCH_ANTENNA2        1
+#define IL_SISO_SWITCH_MIMO2_AB        2
+#define IL_SISO_SWITCH_MIMO2_AC        3
+#define IL_SISO_SWITCH_MIMO2_BC        4
+#define IL_SISO_SWITCH_GI              5
+
+/* possible actions when in mimo mode */
+#define IL_MIMO2_SWITCH_ANTENNA1       0
+#define IL_MIMO2_SWITCH_ANTENNA2       1
+#define IL_MIMO2_SWITCH_SISO_A         2
+#define IL_MIMO2_SWITCH_SISO_B         3
+#define IL_MIMO2_SWITCH_SISO_C         4
+#define IL_MIMO2_SWITCH_GI             5
+
+#define IL_MAX_SEARCH IL_MIMO2_SWITCH_GI
+
+#define IL_ACTION_LIMIT                3       /* # possible actions */
+
+#define LQ_SIZE                2       /* 2 mode tables:  "Active" and "Search" */
+
+/* load per tid defines for A-MPDU activation */
+#define IL_AGG_TPT_THREHOLD    0
+#define IL_AGG_LOAD_THRESHOLD  10
+#define IL_AGG_ALL_TID         0xff
+#define TID_QUEUE_CELL_SPACING 50      /*mS */
+#define TID_QUEUE_MAX_SIZE     20
+#define TID_ROUND_VALUE                5       /* mS */
+#define TID_MAX_LOAD_COUNT     8
+
+#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
+#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
+
+extern const struct il_rate_info il_rates[RATE_COUNT];
+
+enum il_table_type {
+       LQ_NONE,
+       LQ_G,                   /* legacy types */
+       LQ_A,
+       LQ_SISO,                /* high-throughput types */
+       LQ_MIMO2,
+       LQ_MAX,
+};
+
+#define is_legacy(tbl) ((tbl) == LQ_G || (tbl) == LQ_A)
+#define is_siso(tbl) ((tbl) == LQ_SISO)
+#define is_mimo2(tbl) ((tbl) == LQ_MIMO2)
+#define is_mimo(tbl) (is_mimo2(tbl))
+#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl))
+#define is_a_band(tbl) ((tbl) == LQ_A)
+#define is_g_and(tbl) ((tbl) == LQ_G)
+
+#define        ANT_NONE        0x0
+#define        ANT_A           BIT(0)
+#define        ANT_B           BIT(1)
+#define        ANT_AB          (ANT_A | ANT_B)
+#define ANT_C          BIT(2)
+#define        ANT_AC          (ANT_A | ANT_C)
+#define ANT_BC         (ANT_B | ANT_C)
+#define ANT_ABC                (ANT_AB | ANT_C)
+
+#define IL_MAX_MCS_DISPLAY_SIZE        12
+
+struct il_rate_mcs_info {
+       char mbps[IL_MAX_MCS_DISPLAY_SIZE];
+       char mcs[IL_MAX_MCS_DISPLAY_SIZE];
+};
+
+/**
+ * struct il_rate_scale_data -- tx success history for one rate
+ */
+struct il_rate_scale_data {
+       u64 data;               /* bitmap of successful frames */
+       s32 success_counter;    /* number of frames successful */
+       s32 success_ratio;      /* per-cent * 128  */
+       s32 counter;            /* number of frames attempted */
+       s32 average_tpt;        /* success ratio * expected throughput */
+       unsigned long stamp;
+};
+
+/**
+ * struct il_scale_tbl_info -- tx params and success history for all rates
+ *
+ * There are two of these in struct il_lq_sta,
+ * one for "active", and one for "search".
+ */
+struct il_scale_tbl_info {
+       enum il_table_type lq_type;
+       u8 ant_type;
+       u8 is_SGI;              /* 1 = short guard interval */
+       u8 is_ht40;             /* 1 = 40 MHz channel width */
+       u8 is_dup;              /* 1 = duplicated data streams */
+       u8 action;              /* change modulation; IL_[LEGACY/SISO/MIMO]_SWITCH_* */
+       u8 max_search;          /* maximun number of tables we can search */
+       s32 *expected_tpt;      /* throughput metrics; expected_tpt_G, etc. */
+       u32 current_rate;       /* rate_n_flags, uCode API format */
+       struct il_rate_scale_data win[RATE_COUNT];      /* rate histories */
+};
+
+struct il_traffic_load {
+       unsigned long time_stamp;       /* age of the oldest stats */
+       u32 packet_count[TID_QUEUE_MAX_SIZE];   /* packet count in this time
+                                                * slice */
+       u32 total;              /* total num of packets during the
+                                * last TID_MAX_TIME_DIFF */
+       u8 queue_count;         /* number of queues that has
+                                * been used since the last cleanup */
+       u8 head;                /* start of the circular buffer */
+};
+
+/**
+ * struct il_lq_sta -- driver's rate scaling ilate structure
+ *
+ * Pointer to this gets passed back and forth between driver and mac80211.
+ */
+struct il_lq_sta {
+       u8 active_tbl;          /* idx of active table, range 0-1 */
+       u8 enable_counter;      /* indicates HT mode */
+       u8 stay_in_tbl;         /* 1: disallow, 0: allow search for new mode */
+       u8 search_better_tbl;   /* 1: currently trying alternate mode */
+       s32 last_tpt;
+
+       /* The following determine when to search for a new mode */
+       u32 table_count_limit;
+       u32 max_failure_limit;  /* # failed frames before new search */
+       u32 max_success_limit;  /* # successful frames before new search */
+       u32 table_count;
+       u32 total_failed;       /* total failed frames, any/all rates */
+       u32 total_success;      /* total successful frames, any/all rates */
+       u64 flush_timer;        /* time staying in mode before new search */
+
+       u8 action_counter;      /* # mode-switch actions tried */
+       u8 is_green;
+       u8 is_dup;
+       enum ieee80211_band band;
+
+       /* The following are bitmaps of rates; RATE_6M_MASK, etc. */
+       u32 supp_rates;
+       u16 active_legacy_rate;
+       u16 active_siso_rate;
+       u16 active_mimo2_rate;
+       s8 max_rate_idx;        /* Max rate set by user */
+       u8 missed_rate_counter;
+
+       struct il_link_quality_cmd lq;
+       struct il_scale_tbl_info lq_info[LQ_SIZE];      /* "active", "search" */
+       struct il_traffic_load load[TID_MAX_LOAD_COUNT];
+       u8 tx_agg_tid_en;
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct dentry *rs_sta_dbgfs_scale_table_file;
+       struct dentry *rs_sta_dbgfs_stats_table_file;
+       struct dentry *rs_sta_dbgfs_rate_scale_data_file;
+       struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
+       u32 dbg_fixed_rate;
+#endif
+       struct il_priv *drv;
+
+       /* used to be in sta_info */
+       int last_txrate_idx;
+       /* last tx rate_n_flags */
+       u32 last_rate_n_flags;
+       /* packets destined for this STA are aggregated */
+       u8 is_agg;
+};
+
+/*
+ * il_station_priv: Driver's ilate station information
+ *
+ * When mac80211 creates a station it reserves some space (hw->sta_data_size)
+ * in the structure for use by driver. This structure is places in that
+ * space.
+ *
+ * The common struct MUST be first because it is shared between
+ * 3945 and 4965!
+ */
+struct il_station_priv {
+       struct il_station_priv_common common;
+       struct il_lq_sta lq_sta;
+       atomic_t pending_frames;
+       bool client;
+       bool asleep;
+};
+
+static inline u8
+il4965_num_of_ant(u8 m)
+{
+       return !!(m & ANT_A) + !!(m & ANT_B) + !!(m & ANT_C);
+}
+
+static inline u8
+il4965_first_antenna(u8 mask)
+{
+       if (mask & ANT_A)
+               return ANT_A;
+       if (mask & ANT_B)
+               return ANT_B;
+       return ANT_C;
+}
+
+/**
+ * il3945_rate_scale_init - Initialize the rate scale table based on assoc info
+ *
+ * The specific throughput table used is based on the type of network
+ * the associated with, including A, B, G, and G w/ TGG protection
+ */
+extern void il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+
+/* Initialize station's rate scaling information after adding station */
+extern void il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta,
+                               u8 sta_id);
+extern void il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta,
+                               u8 sta_id);
+
+/**
+ * il_rate_control_register - Register the rate control algorithm callbacks
+ *
+ * Since the rate control algorithm is hardware specific, there is no need
+ * or reason to place it as a stand alone module.  The driver can call
+ * il_rate_control_register in order to register the rate control callbacks
+ * with the mac80211 subsystem.  This should be performed prior to calling
+ * ieee80211_register_hw
+ *
+ */
+extern int il4965_rate_control_register(void);
+extern int il3945_rate_control_register(void);
+
+/**
+ * il_rate_control_unregister - Unregister the rate control callbacks
+ *
+ * This should be called after calling ieee80211_unregister_hw, but before
+ * the driver is unloaded.
+ */
+extern void il4965_rate_control_unregister(void);
+extern void il3945_rate_control_unregister(void);
+
+extern int il_power_update_mode(struct il_priv *il, bool force);
+extern void il_power_initialize(struct il_priv *il);
+
+extern u32 il_debug_level;
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+/*
+ * il_get_debug_level: Return active debug level for device
+ *
+ * Using sysfs it is possible to set per device debug level. This debug
+ * level will be used if set, otherwise the global debug level which can be
+ * set via module parameter is used.
+ */
+static inline u32
+il_get_debug_level(struct il_priv *il)
+{
+       if (il->debug_level)
+               return il->debug_level;
+       else
+               return il_debug_level;
+}
+#else
+static inline u32
+il_get_debug_level(struct il_priv *il)
+{
+       return il_debug_level;
+}
+#endif
+
+#define il_print_hex_error(il, p, len)                                 \
+do {                                                                   \
+       print_hex_dump(KERN_ERR, "iwl data: ",                          \
+                      DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);           \
+} while (0)
+
+#ifdef CONFIG_IWLEGACY_DEBUG
+#define IL_DBG(level, fmt, args...)                                    \
+do {                                                                   \
+       if (il_get_debug_level(il) & level)                             \
+               dev_printk(KERN_ERR, &il->hw->wiphy->dev,               \
+                        "%c %s " fmt, in_interrupt() ? 'I' : 'U',      \
+                       __func__ , ## args);                            \
+} while (0)
+
+#define il_print_hex_dump(il, level, p, len)                           \
+do {                                                                   \
+       if (il_get_debug_level(il) & level)                             \
+               print_hex_dump(KERN_DEBUG, "iwl data: ",                \
+                              DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);   \
+} while (0)
+
+#else
+#define IL_DBG(level, fmt, args...)
+static inline void
+il_print_hex_dump(struct il_priv *il, int level, const void *p, u32 len)
+{
+}
+#endif /* CONFIG_IWLEGACY_DEBUG */
+
+#ifdef CONFIG_IWLEGACY_DEBUGFS
+int il_dbgfs_register(struct il_priv *il, const char *name);
+void il_dbgfs_unregister(struct il_priv *il);
+#else
+static inline int
+il_dbgfs_register(struct il_priv *il, const char *name)
+{
+       return 0;
+}
+
+static inline void
+il_dbgfs_unregister(struct il_priv *il)
+{
+}
+#endif /* CONFIG_IWLEGACY_DEBUGFS */
+
+/*
+ * 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 IL_DL_xxxx VALUE
+ *
+ * where xxxx should be the name of the classification (for example, WEP).
+ *
+ * You then need to either add a IL_xxxx_DEBUG() macro definition for your
+ * classification, or use IL_DBG(IL_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * The active debug levels can be accessed via files
+ *
+ *     /sys/module/iwl4965/parameters/debug
+ *     /sys/module/iwl3945/parameters/debug
+ *     /sys/class/net/wlan0/device/debug_level
+ *
+ * when CONFIG_IWLEGACY_DEBUG=y.
+ */
+
+/* 0x0000000F - 0x00000001 */
+#define IL_DL_INFO             (1 << 0)
+#define IL_DL_MAC80211         (1 << 1)
+#define IL_DL_HCMD             (1 << 2)
+#define IL_DL_STATE            (1 << 3)
+/* 0x000000F0 - 0x00000010 */
+#define IL_DL_MACDUMP          (1 << 4)
+#define IL_DL_HCMD_DUMP                (1 << 5)
+#define IL_DL_EEPROM           (1 << 6)
+#define IL_DL_RADIO            (1 << 7)
+/* 0x00000F00 - 0x00000100 */
+#define IL_DL_POWER            (1 << 8)
+#define IL_DL_TEMP             (1 << 9)
+#define IL_DL_NOTIF            (1 << 10)
+#define IL_DL_SCAN             (1 << 11)
+/* 0x0000F000 - 0x00001000 */
+#define IL_DL_ASSOC            (1 << 12)
+#define IL_DL_DROP             (1 << 13)
+#define IL_DL_TXPOWER          (1 << 14)
+#define IL_DL_AP               (1 << 15)
+/* 0x000F0000 - 0x00010000 */
+#define IL_DL_FW               (1 << 16)
+#define IL_DL_RF_KILL          (1 << 17)
+#define IL_DL_FW_ERRORS                (1 << 18)
+#define IL_DL_LED              (1 << 19)
+/* 0x00F00000 - 0x00100000 */
+#define IL_DL_RATE             (1 << 20)
+#define IL_DL_CALIB            (1 << 21)
+#define IL_DL_WEP              (1 << 22)
+#define IL_DL_TX               (1 << 23)
+/* 0x0F000000 - 0x01000000 */
+#define IL_DL_RX               (1 << 24)
+#define IL_DL_ISR              (1 << 25)
+#define IL_DL_HT               (1 << 26)
+/* 0xF0000000 - 0x10000000 */
+#define IL_DL_11H              (1 << 28)
+#define IL_DL_STATS            (1 << 29)
+#define IL_DL_TX_REPLY         (1 << 30)
+#define IL_DL_QOS              (1 << 31)
+
+#define D_INFO(f, a...)                IL_DBG(IL_DL_INFO, f, ## a)
+#define D_MAC80211(f, a...)    IL_DBG(IL_DL_MAC80211, f, ## a)
+#define D_MACDUMP(f, a...)     IL_DBG(IL_DL_MACDUMP, f, ## a)
+#define D_TEMP(f, a...)                IL_DBG(IL_DL_TEMP, f, ## a)
+#define D_SCAN(f, a...)                IL_DBG(IL_DL_SCAN, f, ## a)
+#define D_RX(f, a...)          IL_DBG(IL_DL_RX, f, ## a)
+#define D_TX(f, a...)          IL_DBG(IL_DL_TX, f, ## a)
+#define D_ISR(f, a...)         IL_DBG(IL_DL_ISR, f, ## a)
+#define D_LED(f, a...)         IL_DBG(IL_DL_LED, f, ## a)
+#define D_WEP(f, a...)         IL_DBG(IL_DL_WEP, f, ## a)
+#define D_HC(f, a...)          IL_DBG(IL_DL_HCMD, f, ## a)
+#define D_HC_DUMP(f, a...)     IL_DBG(IL_DL_HCMD_DUMP, f, ## a)
+#define D_EEPROM(f, a...)      IL_DBG(IL_DL_EEPROM, f, ## a)
+#define D_CALIB(f, a...)       IL_DBG(IL_DL_CALIB, f, ## a)
+#define D_FW(f, a...)          IL_DBG(IL_DL_FW, f, ## a)
+#define D_RF_KILL(f, a...)     IL_DBG(IL_DL_RF_KILL, f, ## a)
+#define D_DROP(f, a...)                IL_DBG(IL_DL_DROP, f, ## a)
+#define D_AP(f, a...)          IL_DBG(IL_DL_AP, f, ## a)
+#define D_TXPOWER(f, a...)     IL_DBG(IL_DL_TXPOWER, f, ## a)
+#define D_RATE(f, a...)                IL_DBG(IL_DL_RATE, f, ## a)
+#define D_NOTIF(f, a...)       IL_DBG(IL_DL_NOTIF, f, ## a)
+#define D_ASSOC(f, a...)       IL_DBG(IL_DL_ASSOC, f, ## a)
+#define D_HT(f, a...)          IL_DBG(IL_DL_HT, f, ## a)
+#define D_STATS(f, a...)       IL_DBG(IL_DL_STATS, f, ## a)
+#define D_TX_REPLY(f, a...)    IL_DBG(IL_DL_TX_REPLY, f, ## a)
+#define D_QOS(f, a...)         IL_DBG(IL_DL_QOS, f, ## a)
+#define D_RADIO(f, a...)       IL_DBG(IL_DL_RADIO, f, ## a)
+#define D_POWER(f, a...)       IL_DBG(IL_DL_POWER, f, ## a)
+#define D_11H(f, a...)         IL_DBG(IL_DL_11H, f, ## a)
+
+#endif /* __il_core_h__ */
similarity index 84%
rename from drivers/net/wireless/iwlegacy/iwl-csr.h
rename to drivers/net/wireless/iwlegacy/csr.h
index 668a9616c269450f800360587f16f2ab5b0e67c4..9138e15004faa38ded8865c0b66fe276930c406e 100644 (file)
@@ -60,8 +60,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  *****************************************************************************/
-#ifndef __iwl_legacy_csr_h__
-#define __iwl_legacy_csr_h__
+#ifndef __il_csr_h__
+#define __il_csr_h__
 /*
  * CSR (control and status registers)
  *
@@ -70,9 +70,9 @@
  * low power states due to driver-invoked device resets
  * (e.g. CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes.
  *
- * Use iwl_write32() and iwl_read32() family to access these registers;
+ * Use _il_wr() and _il_rd() family to access these registers;
  * these provide simple PCI bus access, without waking up the MAC.
- * Do not use iwl_legacy_write_direct32() family for these registers;
+ * Do not use il_wr() family for these registers;
  * no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ.
  * The MAC (uCode processor, etc.) does not need to be powered up for accessing
  * the CSR registers.
  */
 #define 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_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)
 
-/* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */
+/* 2nd byte of CSR_INT_COALESCING, not accessible via _il_wr()! */
 #define CSR_INT_PERIODIC_REG   (CSR_BASE+0x005)
 
 /*
 
 #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A  (0x00080000)
 #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM        (0x00200000)
-#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY     (0x00400000) /* PCI_OWN_SEM */
-#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */
-#define CSR_HW_IF_CONFIG_REG_PREPARE             (0x08000000) /* WAKE_ME */
+#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY     (0x00400000)    /* PCI_OWN_SEM */
+#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */
+#define CSR_HW_IF_CONFIG_REG_PREPARE             (0x08000000)  /* WAKE_ME */
 
-#define CSR_INT_PERIODIC_DIS                   (0x00) /* disable periodic int*/
-#define CSR_INT_PERIODIC_ENA                   (0xFF) /* 255*32 usec ~ 8 msec*/
+#define CSR_INT_PERIODIC_DIS                   (0x00)  /* disable periodic int */
+#define CSR_INT_PERIODIC_ENA                   (0xFF)  /* 255*32 usec ~ 8 msec */
 
 /* 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_RX_PERIODIC         (1 << 28) /* Rx periodic */
-#define CSR_INT_BIT_FH_TX        (1 << 27) /* Tx DMA FH_INT[1:0] */
-#define CSR_INT_BIT_SCD          (1 << 26) /* TXQ pointer advanced */
-#define CSR_INT_BIT_SW_ERR       (1 << 25) /* uCode error */
-#define CSR_INT_BIT_RF_KILL      (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
-#define CSR_INT_BIT_CT_KILL      (1 << 6)  /* Critical temp (chip too hot) rfkill */
-#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_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_RX_PERIODIC         (1 << 28)      /* Rx periodic */
+#define CSR_INT_BIT_FH_TX        (1 << 27)     /* Tx DMA FH_INT[1:0] */
+#define CSR_INT_BIT_SCD          (1 << 26)     /* TXQ pointer advanced */
+#define CSR_INT_BIT_SW_ERR       (1 << 25)     /* uCode error */
+#define CSR_INT_BIT_RF_KILL      (1 << 7)      /* HW RFKILL switch GP_CNTRL[27] toggled */
+#define CSR_INT_BIT_CT_KILL      (1 << 6)      /* Critical temp (chip too hot) rfkill */
+#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_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 CSR39_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 CSR39_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_BIT_ERR       (1 << 31)     /* Error */
+#define CSR_FH_INT_BIT_HI_PRIOR  (1 << 30)     /* High priority Rx, bypass coalescing */
+#define CSR39_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 CSR39_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 CSR39_FH_INT_RX_MASK   (CSR_FH_INT_BIT_HI_PRIOR | \
                                 CSR39_FH_INT_BIT_RX_CHNL2 | \
                                 CSR_FH_INT_BIT_RX_CHNL1 | \
                                 CSR_FH_INT_BIT_RX_CHNL0)
 
-
 #define CSR39_FH_INT_TX_MASK   (CSR39_FH_INT_BIT_TX_CHNL6 | \
                                 CSR_FH_INT_BIT_TX_CHNL1 | \
                                 CSR_FH_INT_BIT_TX_CHNL0)
 #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)
 #define CSR_EEPROM_REG_MSK_DATA                (0xFFFF0000)
 
 /* EEPROM GP */
-#define CSR_EEPROM_GP_VALID_MSK                (0x00000007) /* signature */
+#define CSR_EEPROM_GP_VALID_MSK                (0x00000007)    /* signature */
 #define CSR_EEPROM_GP_IF_OWNER_MSK     (0x00000180)
 #define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K                (0x00000002)
 #define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K                (0x00000004)
 
 /* GP REG */
-#define CSR_GP_REG_POWER_SAVE_STATUS_MSK            (0x03000000) /* bit 24/25 */
+#define CSR_GP_REG_POWER_SAVE_STATUS_MSK            (0x03000000)       /* bit 24/25 */
 #define CSR_GP_REG_NO_POWER_SAVE            (0x00000000)
 #define CSR_GP_REG_MAC_POWER_SAVE           (0x01000000)
 #define CSR_GP_REG_PHY_POWER_SAVE           (0x02000000)
 #define CSR_GP_REG_POWER_SAVE_ERROR         (0x03000000)
 
-
 /* CSR GIO */
 #define CSR_GIO_REG_VAL_L0S_ENABLED    (0x00000002)
 
 /* HPET MEM debug */
 #define CSR_DBG_HPET_MEM_REG_VAL       (0xFFFF0000)
 
-/* DRAM INT TABLE */
+/* DRAM INT TBL */
 #define CSR_DRAM_INT_TBL_ENABLE                (1 << 31)
 #define CSR_DRAM_INIT_TBL_WRAP_CHECK   (1 << 27)
 
  * to indirectly access device's internal memory or registers that
  * may be powered-down.
  *
- * Use iwl_legacy_write_direct32()/iwl_legacy_read_direct32() family
+ * Use il_wr()/il_rd() family
  * for these registers;
  * host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
  * to make sure the MAC (uCode processor, etc.) is powered up for accessing
  * internal resources.
  *
- * Do not use iwl_write32()/iwl_read32() family to access these registers;
+ * Do not use _il_wr()/_il_rd() family to access these registers;
  * these provide only simple PCI bus access, without waking up the MAC.
  */
 #define HBUS_BASE      (0x400)
 #define HBUS_TARG_PRPH_RDAT     (HBUS_BASE+0x050)
 
 /*
- * Per-Tx-queue write pointer (index, really!)
- * Indicates index to next TFD that driver will fill (1 past latest filled).
+ * Per-Tx-queue write pointer (idx, really!)
+ * Indicates idx to next TFD that driver will fill (1 past latest filled).
  * Bit usage:
- *  0-7:  queue write index
+ *  0-7:  queue write idx
  * 11-8:  queue selector
  */
 #define HBUS_TARG_WRPTR         (HBUS_BASE+0x060)
 
-#endif /* !__iwl_legacy_csr_h__ */
+#endif /* !__il_csr_h__ */
diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c
new file mode 100644 (file)
index 0000000..b1b8926
--- /dev/null
@@ -0,0 +1,1411 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+#include <linux/ieee80211.h>
+#include <linux/export.h>
+#include <net/mac80211.h>
+
+#include "common.h"
+
+/* create and remove of files */
+#define DEBUGFS_ADD_FILE(name, parent, mode) do {                      \
+       if (!debugfs_create_file(#name, mode, parent, il,               \
+                        &il_dbgfs_##name##_ops))               \
+               goto err;                                               \
+} while (0)
+
+#define DEBUGFS_ADD_BOOL(name, parent, ptr) do {                       \
+       struct dentry *__tmp;                                           \
+       __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR,           \
+                                   parent, ptr);                       \
+       if (IS_ERR(__tmp) || !__tmp)                                    \
+               goto err;                                               \
+} while (0)
+
+#define DEBUGFS_ADD_X32(name, parent, ptr) do {                                \
+       struct dentry *__tmp;                                           \
+       __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR,            \
+                                  parent, ptr);                        \
+       if (IS_ERR(__tmp) || !__tmp)                                    \
+               goto err;                                               \
+} while (0)
+
+/* file operation */
+#define DEBUGFS_READ_FUNC(name)                                         \
+static ssize_t il_dbgfs_##name##_read(struct file *file,               \
+                                       char __user *user_buf,          \
+                                       size_t count, loff_t *ppos);
+
+#define DEBUGFS_WRITE_FUNC(name)                                        \
+static ssize_t il_dbgfs_##name##_write(struct file *file,              \
+                                       const char __user *user_buf,    \
+                                       size_t count, loff_t *ppos);
+
+static int
+il_dbgfs_open_file_generic(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+#define DEBUGFS_READ_FILE_OPS(name)                            \
+       DEBUGFS_READ_FUNC(name);                                \
+static const struct file_operations il_dbgfs_##name##_ops = {  \
+       .read = il_dbgfs_##name##_read,                         \
+       .open = il_dbgfs_open_file_generic,                     \
+       .llseek = generic_file_llseek,                          \
+};
+
+#define DEBUGFS_WRITE_FILE_OPS(name)                           \
+       DEBUGFS_WRITE_FUNC(name);                               \
+static const struct file_operations il_dbgfs_##name##_ops = {  \
+       .write = il_dbgfs_##name##_write,                       \
+       .open = il_dbgfs_open_file_generic,                     \
+       .llseek = generic_file_llseek,                          \
+};
+
+#define DEBUGFS_READ_WRITE_FILE_OPS(name)                      \
+       DEBUGFS_READ_FUNC(name);                                \
+       DEBUGFS_WRITE_FUNC(name);                               \
+static const struct file_operations il_dbgfs_##name##_ops = {  \
+       .write = il_dbgfs_##name##_write,                       \
+       .read = il_dbgfs_##name##_read,                         \
+       .open = il_dbgfs_open_file_generic,                     \
+       .llseek = generic_file_llseek,                          \
+};
+
+static ssize_t
+il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count,
+                      loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       char *buf;
+       int pos = 0;
+
+       int cnt;
+       ssize_t ret;
+       const size_t bufsz =
+           100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+       pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
+       for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
+                             il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]);
+       }
+       pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
+       for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
+                             il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]);
+       }
+       pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
+                     il->tx_stats.data_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
+                     il->tx_stats.data_bytes);
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_clear_traffic_stats_write(struct file *file,
+                                  const char __user *user_buf, size_t count,
+                                  loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       u32 clear_flag;
+       char buf[8];
+       int buf_size;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%x", &clear_flag) != 1)
+               return -EFAULT;
+       il_clear_traffic_stats(il);
+
+       return count;
+}
+
+static ssize_t
+il_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count,
+                      loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       char *buf;
+       int pos = 0;
+       int cnt;
+       ssize_t ret;
+       const size_t bufsz =
+           100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
+       for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
+                             il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]);
+       }
+       pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
+       for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
+                             il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]);
+       }
+       pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
+                     il->rx_stats.data_cnt);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
+                     il->rx_stats.data_bytes);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+#define BYTE1_MASK 0x000000ff;
+#define BYTE2_MASK 0x0000ffff;
+#define BYTE3_MASK 0x00ffffff;
+static ssize_t
+il_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count,
+                  loff_t *ppos)
+{
+       u32 val;
+       char *buf;
+       ssize_t ret;
+       int i;
+       int pos = 0;
+       struct il_priv *il = file->private_data;
+       size_t bufsz;
+
+       /* default is to dump the entire data segment */
+       if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) {
+               il->dbgfs_sram_offset = 0x800000;
+               if (il->ucode_type == UCODE_INIT)
+                       il->dbgfs_sram_len = il->ucode_init_data.len;
+               else
+                       il->dbgfs_sram_len = il->ucode_data.len;
+       }
+       bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10;
+       buf = kmalloc(bufsz, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
+                     il->dbgfs_sram_len);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
+                     il->dbgfs_sram_offset);
+       for (i = il->dbgfs_sram_len; i > 0; i -= 4) {
+               val =
+                   il_read_targ_mem(il,
+                                    il->dbgfs_sram_offset +
+                                    il->dbgfs_sram_len - i);
+               if (i < 4) {
+                       switch (i) {
+                       case 1:
+                               val &= BYTE1_MASK;
+                               break;
+                       case 2:
+                               val &= BYTE2_MASK;
+                               break;
+                       case 3:
+                               val &= BYTE3_MASK;
+                               break;
+                       }
+               }
+               if (!(i % 16))
+                       pos += scnprintf(buf + pos, bufsz - pos, "\n");
+               pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
+       }
+       pos += scnprintf(buf + pos, bufsz - pos, "\n");
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_sram_write(struct file *file, const char __user *user_buf,
+                   size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       char buf[64];
+       int buf_size;
+       u32 offset, len;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+
+       if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
+               il->dbgfs_sram_offset = offset;
+               il->dbgfs_sram_len = len;
+       } else {
+               il->dbgfs_sram_offset = 0;
+               il->dbgfs_sram_len = 0;
+       }
+
+       return count;
+}
+
+static ssize_t
+il_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count,
+                      loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       struct il_station_entry *station;
+       int max_sta = il->hw_params.max_stations;
+       char *buf;
+       int i, j, pos = 0;
+       ssize_t ret;
+       /* Add 30 for initial string */
+       const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations);
+
+       buf = kmalloc(bufsz, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
+                     il->num_stations);
+
+       for (i = 0; i < max_sta; i++) {
+               station = &il->stations[i];
+               if (!station->used)
+                       continue;
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "station %d - addr: %pM, flags: %#x\n", i,
+                             station->sta.sta.addr,
+                             station->sta.station_flags_msk);
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "TID\tseq_num\ttxq_id\tframes\ttfds\t");
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "start_idx\tbitmap\t\t\trate_n_flags\n");
+
+               for (j = 0; j < MAX_TID_COUNT; j++) {
+                       pos +=
+                           scnprintf(buf + pos, bufsz - pos,
+                                     "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
+                                     j, station->tid[j].seq_number,
+                                     station->tid[j].agg.txq_id,
+                                     station->tid[j].agg.frame_count,
+                                     station->tid[j].tfds_in_queue,
+                                     station->tid[j].agg.start_idx,
+                                     station->tid[j].agg.bitmap,
+                                     station->tid[j].agg.rate_n_flags);
+
+                       if (station->tid[j].agg.wait_for_ba)
+                               pos +=
+                                   scnprintf(buf + pos, bufsz - pos,
+                                             " - waitforba");
+                       pos += scnprintf(buf + pos, bufsz - pos, "\n");
+               }
+
+               pos += scnprintf(buf + pos, bufsz - pos, "\n");
+       }
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count,
+                 loff_t *ppos)
+{
+       ssize_t ret;
+       struct il_priv *il = file->private_data;
+       int pos = 0, ofs = 0, buf_size = 0;
+       const u8 *ptr;
+       char *buf;
+       u16 eeprom_ver;
+       size_t eeprom_len = il->cfg->base_params->eeprom_size;
+       buf_size = 4 * eeprom_len + 256;
+
+       if (eeprom_len % 16) {
+               IL_ERR("NVM size is not multiple of 16.\n");
+               return -ENODATA;
+       }
+
+       ptr = il->eeprom;
+       if (!ptr) {
+               IL_ERR("Invalid EEPROM memory\n");
+               return -ENOMEM;
+       }
+
+       /* 4 characters for byte 0xYY */
+       buf = kzalloc(buf_size, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+       eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION);
+       pos +=
+           scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n",
+                     eeprom_ver);
+       for (ofs = 0; ofs < eeprom_len; ofs += 16) {
+               pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
+               hex_dump_to_buffer(ptr + ofs, 16, 16, 2, buf + pos,
+                                  buf_size - pos, 0);
+               pos += strlen(buf + pos);
+               if (buf_size - pos > 0)
+                       buf[pos++] = '\n';
+       }
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
+                      loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       struct ieee80211_channel *channels = NULL;
+       const struct ieee80211_supported_band *supp_band = NULL;
+       int pos = 0, i, bufsz = PAGE_SIZE;
+       char *buf;
+       ssize_t ret;
+
+       if (!test_bit(S_GEO_CONFIGURED, &il->status))
+               return -EAGAIN;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ);
+       if (supp_band) {
+               channels = supp_band->channels;
+
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "Displaying %d channels in 2.4GHz band 802.11bg):\n",
+                             supp_band->n_channels);
+
+               for (i = 0; i < supp_band->n_channels; i++)
+                       pos +=
+                           scnprintf(buf + pos, bufsz - pos,
+                                     "%d: %ddBm: BSS%s%s, %s.\n",
+                                     channels[i].hw_value,
+                                     channels[i].max_power,
+                                     channels[i].
+                                     flags & IEEE80211_CHAN_RADAR ?
+                                     " (IEEE 802.11h required)" : "",
+                                     ((channels[i].
+                                       flags & IEEE80211_CHAN_NO_IBSS) ||
+                                      (channels[i].
+                                       flags & IEEE80211_CHAN_RADAR)) ? "" :
+                                     ", IBSS",
+                                     channels[i].
+                                     flags & IEEE80211_CHAN_PASSIVE_SCAN ?
+                                     "passive only" : "active/passive");
+       }
+       supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ);
+       if (supp_band) {
+               channels = supp_band->channels;
+
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "Displaying %d channels in 5.2GHz band (802.11a)\n",
+                             supp_band->n_channels);
+
+               for (i = 0; i < supp_band->n_channels; i++)
+                       pos +=
+                           scnprintf(buf + pos, bufsz - pos,
+                                     "%d: %ddBm: BSS%s%s, %s.\n",
+                                     channels[i].hw_value,
+                                     channels[i].max_power,
+                                     channels[i].
+                                     flags & IEEE80211_CHAN_RADAR ?
+                                     " (IEEE 802.11h required)" : "",
+                                     ((channels[i].
+                                       flags & IEEE80211_CHAN_NO_IBSS) ||
+                                      (channels[i].
+                                       flags & IEEE80211_CHAN_RADAR)) ? "" :
+                                     ", IBSS",
+                                     channels[i].
+                                     flags & IEEE80211_CHAN_PASSIVE_SCAN ?
+                                     "passive only" : "active/passive");
+       }
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count,
+                    loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       char buf[512];
+       int pos = 0;
+       const size_t bufsz = sizeof(buf);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n",
+                     test_bit(S_HCMD_ACTIVE, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n",
+                     test_bit(S_INT_ENABLED, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_RF_KILL_HW:\t %d\n",
+                     test_bit(S_RF_KILL_HW, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n",
+                     test_bit(S_CT_KILL, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n",
+                     test_bit(S_INIT, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n",
+                     test_bit(S_ALIVE, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n",
+                     test_bit(S_READY, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n",
+                     test_bit(S_TEMPERATURE, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n",
+                     test_bit(S_GEO_CONFIGURED, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n",
+                     test_bit(S_EXIT_PENDING, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n",
+                     test_bit(S_STATS, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n",
+                     test_bit(S_SCANNING, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n",
+                     test_bit(S_SCAN_ABORTING, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n",
+                     test_bit(S_SCAN_HW, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n",
+                     test_bit(S_POWER_PMI, &il->status));
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n",
+                     test_bit(S_FW_ERROR, &il->status));
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t
+il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count,
+                       loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       int cnt = 0;
+       char *buf;
+       int bufsz = 24 * 64;    /* 24 items * 64 char per item */
+       ssize_t ret;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n");
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
+                     il->isr_stats.hw);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
+                     il->isr_stats.sw);
+       if (il->isr_stats.sw || il->isr_stats.hw) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "\tLast Restarting Code:  0x%X\n",
+                             il->isr_stats.err_code);
+       }
+#ifdef CONFIG_IWLEGACY_DEBUG
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
+                     il->isr_stats.sch);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
+                     il->isr_stats.alive);
+#endif
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "HW RF KILL switch toggled:\t %u\n",
+                     il->isr_stats.rfkill);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
+                     il->isr_stats.ctkill);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
+                     il->isr_stats.wakeup);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n",
+                     il->isr_stats.rx);
+       for (cnt = 0; cnt < IL_CN_MAX; cnt++) {
+               if (il->isr_stats.handlers[cnt] > 0)
+                       pos +=
+                           scnprintf(buf + pos, bufsz - pos,
+                                     "\tRx handler[%36s]:\t\t %u\n",
+                                     il_get_cmd_string(cnt),
+                                     il->isr_stats.handlers[cnt]);
+       }
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
+                     il->isr_stats.tx);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
+                     il->isr_stats.unhandled);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf,
+                        size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       char buf[8];
+       int buf_size;
+       u32 reset_flag;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%x", &reset_flag) != 1)
+               return -EFAULT;
+       if (reset_flag == 0)
+               il_clear_isr_stats(il);
+
+       return count;
+}
+
+static ssize_t
+il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count,
+                 loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       struct il_rxon_context *ctx = &il->ctx;
+       int pos = 0, i;
+       char buf[256];
+       const size_t bufsz = sizeof(buf);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n", ctx->ctxid);
+       for (i = 0; i < AC_NUM; i++) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "\tcw_min\tcw_max\taifsn\ttxop\n");
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "AC[%d]\t%u\t%u\t%u\t%u\n", i,
+                             ctx->qos_data.def_qos_parm.ac[i].cw_min,
+                             ctx->qos_data.def_qos_parm.ac[i].cw_max,
+                             ctx->qos_data.def_qos_parm.ac[i].aifsn,
+                             ctx->qos_data.def_qos_parm.ac[i].edca_txop);
+       }
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t
+il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf,
+                           size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       char buf[8];
+       int buf_size;
+       int ht40;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%d", &ht40) != 1)
+               return -EFAULT;
+       if (!il_is_any_associated(il))
+               il->disable_ht40 = ht40 ? true : false;
+       else {
+               IL_ERR("Sta associated with AP - "
+                      "Change to 40MHz channel support is not allowed\n");
+               return -EINVAL;
+       }
+
+       return count;
+}
+
+static ssize_t
+il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf,
+                          size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       char buf[100];
+       int pos = 0;
+       const size_t bufsz = sizeof(buf);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n",
+                     il->disable_ht40 ? "Disabled" : "Enabled");
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+DEBUGFS_READ_WRITE_FILE_OPS(sram);
+DEBUGFS_READ_FILE_OPS(nvm);
+DEBUGFS_READ_FILE_OPS(stations);
+DEBUGFS_READ_FILE_OPS(channels);
+DEBUGFS_READ_FILE_OPS(status);
+DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
+DEBUGFS_READ_FILE_OPS(qos);
+DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
+
+static ssize_t
+il_dbgfs_traffic_log_read(struct file *file, char __user *user_buf,
+                         size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       int pos = 0, ofs = 0;
+       int cnt = 0, entry;
+       struct il_tx_queue *txq;
+       struct il_queue *q;
+       struct il_rx_queue *rxq = &il->rxq;
+       char *buf;
+       int bufsz =
+           ((IL_TRAFFIC_ENTRIES * IL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
+           (il->cfg->base_params->num_of_queues * 32 * 8) + 400;
+       const u8 *ptr;
+       ssize_t ret;
+
+       if (!il->txq) {
+               IL_ERR("txq not ready\n");
+               return -EAGAIN;
+       }
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate buffer\n");
+               return -ENOMEM;
+       }
+       pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
+       for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
+               txq = &il->txq[cnt];
+               q = &txq->q;
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "q[%d]: read_ptr: %u, write_ptr: %u\n", cnt,
+                             q->read_ptr, q->write_ptr);
+       }
+       if (il->tx_traffic && (il_debug_level & IL_DL_TX)) {
+               ptr = il->tx_traffic;
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, "Tx Traffic idx: %u\n",
+                             il->tx_traffic_idx);
+               for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) {
+                       for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16;
+                            entry++, ofs += 16) {
+                               pos +=
+                                   scnprintf(buf + pos, bufsz - pos, "0x%.4x ",
+                                             ofs);
+                               hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+                                                  buf + pos, bufsz - pos, 0);
+                               pos += strlen(buf + pos);
+                               if (bufsz - pos > 0)
+                                       buf[pos++] = '\n';
+                       }
+               }
+       }
+
+       pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "read: %u, write: %u\n",
+                     rxq->read, rxq->write);
+
+       if (il->rx_traffic && (il_debug_level & IL_DL_RX)) {
+               ptr = il->rx_traffic;
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, "Rx Traffic idx: %u\n",
+                             il->rx_traffic_idx);
+               for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) {
+                       for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16;
+                            entry++, ofs += 16) {
+                               pos +=
+                                   scnprintf(buf + pos, bufsz - pos, "0x%.4x ",
+                                             ofs);
+                               hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+                                                  buf + pos, bufsz - pos, 0);
+                               pos += strlen(buf + pos);
+                               if (bufsz - pos > 0)
+                                       buf[pos++] = '\n';
+                       }
+               }
+       }
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_traffic_log_write(struct file *file, const char __user *user_buf,
+                          size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       char buf[8];
+       int buf_size;
+       int traffic_log;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%d", &traffic_log) != 1)
+               return -EFAULT;
+       if (traffic_log == 0)
+               il_reset_traffic_log(il);
+
+       return count;
+}
+
+static ssize_t
+il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count,
+                      loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       struct il_tx_queue *txq;
+       struct il_queue *q;
+       char *buf;
+       int pos = 0;
+       int cnt;
+       int ret;
+       const size_t bufsz =
+           sizeof(char) * 64 * il->cfg->base_params->num_of_queues;
+
+       if (!il->txq) {
+               IL_ERR("txq not ready\n");
+               return -EAGAIN;
+       }
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
+               txq = &il->txq[cnt];
+               q = &txq->q;
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "hwq %.2d: read=%u write=%u stop=%d"
+                             " swq_id=%#.2x (ac %d/hwq %d)\n", cnt,
+                             q->read_ptr, q->write_ptr,
+                             !!test_bit(cnt, il->queue_stopped),
+                             txq->swq_id, txq->swq_id & 3,
+                             (txq->swq_id >> 2) & 0x1f);
+               if (cnt >= 4)
+                       continue;
+               /* for the ACs, display the stop count too */
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "        stop-count: %d\n",
+                             atomic_read(&il->queue_stop_count[cnt]));
+       }
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count,
+                      loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       struct il_rx_queue *rxq = &il->rxq;
+       char buf[256];
+       int pos = 0;
+       const size_t bufsz = sizeof(buf);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read);
+       pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
+                     rxq->free_count);
+       if (rxq->rb_stts) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
+                             le16_to_cpu(rxq->rb_stts->
+                                         closed_rb_num) & 0x0FFF);
+       } else {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos,
+                             "closed_rb_num: Not Allocated\n");
+       }
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t
+il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       return il->cfg->ops->lib->debugfs_ops.rx_stats_read(file, user_buf,
+                                                           count, ppos);
+}
+
+static ssize_t
+il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       return il->cfg->ops->lib->debugfs_ops.tx_stats_read(file, user_buf,
+                                                           count, ppos);
+}
+
+static ssize_t
+il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       return il->cfg->ops->lib->debugfs_ops.general_stats_read(file, user_buf,
+                                                                count, ppos);
+}
+
+static ssize_t
+il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf,
+                         size_t count, loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       int cnt = 0;
+       char *buf;
+       int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100;
+       ssize_t ret;
+       struct il_sensitivity_data *data;
+
+       data = &il->sensitivity_data;
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
+                     data->auto_corr_ofdm);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n",
+                     data->auto_corr_ofdm_mrc);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
+                     data->auto_corr_ofdm_x1);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n",
+                     data->auto_corr_ofdm_mrc_x1);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
+                     data->auto_corr_cck);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
+                     data->auto_corr_cck_mrc);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "last_bad_plcp_cnt_ofdm:\t\t %u\n",
+                     data->last_bad_plcp_cnt_ofdm);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
+                     data->last_fa_cnt_ofdm);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n",
+                     data->last_bad_plcp_cnt_cck);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
+                     data->last_fa_cnt_cck);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
+                     data->nrg_curr_state);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
+                     data->nrg_prev_state);
+       pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
+       for (cnt = 0; cnt < 10; cnt++) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, " %u",
+                             data->nrg_value[cnt]);
+       }
+       pos += scnprintf(buf + pos, bufsz - pos, "\n");
+       pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
+       for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, " %u",
+                             data->nrg_silence_rssi[cnt]);
+       }
+       pos += scnprintf(buf + pos, bufsz - pos, "\n");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
+                     data->nrg_silence_ref);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
+                     data->nrg_energy_idx);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
+                     data->nrg_silence_idx);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
+                     data->nrg_th_cck);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "nrg_auto_corr_silence_diff:\t %u\n",
+                     data->nrg_auto_corr_silence_diff);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
+                     data->num_in_cck_no_fa);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
+                     data->nrg_th_ofdm);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf,
+                         size_t count, loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       int cnt = 0;
+       char *buf;
+       int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100;
+       ssize_t ret;
+       struct il_chain_noise_data *data;
+
+       data = &il->chain_noise_data;
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IL_ERR("Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
+                     data->active_chains);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
+                     data->chain_noise_a);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
+                     data->chain_noise_b);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
+                     data->chain_noise_c);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
+                     data->chain_signal_a);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
+                     data->chain_signal_b);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
+                     data->chain_signal_c);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
+                     data->beacon_count);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
+       for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, " %u",
+                             data->disconn_array[cnt]);
+       }
+       pos += scnprintf(buf + pos, bufsz - pos, "\n");
+       pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
+       for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
+               pos +=
+                   scnprintf(buf + pos, bufsz - pos, " %u",
+                             data->delta_gain_code[cnt]);
+       }
+       pos += scnprintf(buf + pos, bufsz - pos, "\n");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
+                     data->radio_write);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
+                     data->state);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       char buf[60];
+       int pos = 0;
+       const size_t bufsz = sizeof(buf);
+       u32 pwrsave_status;
+
+       pwrsave_status =
+           _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK;
+
+       pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "%s\n",
+                     (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
+                     (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
+                     (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
+                     "error");
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t
+il_dbgfs_clear_ucode_stats_write(struct file *file,
+                                const char __user *user_buf, size_t count,
+                                loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       char buf[8];
+       int buf_size;
+       int clear;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%d", &clear) != 1)
+               return -EFAULT;
+
+       /* make request to uCode to retrieve stats information */
+       mutex_lock(&il->mutex);
+       il_send_stats_request(il, CMD_SYNC, true);
+       mutex_unlock(&il->mutex);
+
+       return count;
+}
+
+static ssize_t
+il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf,
+                        size_t count, loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       int len = 0;
+       char buf[20];
+
+       len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->ctx.active.flags));
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t
+il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       int len = 0;
+       char buf[20];
+
+       len =
+           sprintf(buf, "0x%04X\n", le32_to_cpu(il->ctx.active.filter_flags));
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t
+il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count,
+                    loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       char *buf;
+       int pos = 0;
+       ssize_t ret = -EFAULT;
+
+       if (il->cfg->ops->lib->dump_fh) {
+               ret = pos = il->cfg->ops->lib->dump_fh(il, &buf, true);
+               if (buf) {
+                       ret =
+                           simple_read_from_buffer(user_buf, count, ppos, buf,
+                                                   pos);
+                       kfree(buf);
+               }
+       }
+
+       return ret;
+}
+
+static ssize_t
+il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf,
+                           size_t count, loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       char buf[12];
+       const size_t bufsz = sizeof(buf);
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "%d\n",
+                     il->missed_beacon_threshold);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t
+il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct il_priv *il = file->private_data;
+       char buf[8];
+       int buf_size;
+       int missed;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%d", &missed) != 1)
+               return -EINVAL;
+
+       if (missed < IL_MISSED_BEACON_THRESHOLD_MIN ||
+           missed > IL_MISSED_BEACON_THRESHOLD_MAX)
+               il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
+       else
+               il->missed_beacon_threshold = missed;
+
+       return count;
+}
+
+static ssize_t
+il_dbgfs_force_reset_read(struct file *file, char __user *user_buf,
+                         size_t count, loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       int pos = 0;
+       char buf[300];
+       const size_t bufsz = sizeof(buf);
+       struct il_force_reset *force_reset;
+
+       force_reset = &il->force_reset;
+
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n",
+                     force_reset->reset_request_count);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "\tnumber of reset request success: %d\n",
+                     force_reset->reset_success_count);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos,
+                     "\tnumber of reset request reject: %d\n",
+                     force_reset->reset_reject_count);
+       pos +=
+           scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n",
+                     force_reset->reset_duration);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t
+il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf,
+                          size_t count, loff_t *ppos)
+{
+
+       int ret;
+       struct il_priv *il = file->private_data;
+
+       ret = il_force_reset(il, true);
+
+       return ret ? ret : count;
+}
+
+static ssize_t
+il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf,
+                         size_t count, loff_t *ppos)
+{
+
+       struct il_priv *il = file->private_data;
+       char buf[8];
+       int buf_size;
+       int timeout;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%d", &timeout) != 1)
+               return -EINVAL;
+       if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT)
+               timeout = IL_DEF_WD_TIMEOUT;
+
+       il->cfg->base_params->wd_timeout = timeout;
+       il_setup_watchdog(il);
+       return count;
+}
+
+DEBUGFS_READ_FILE_OPS(rx_stats);
+DEBUGFS_READ_FILE_OPS(tx_stats);
+DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
+DEBUGFS_READ_FILE_OPS(rx_queue);
+DEBUGFS_READ_FILE_OPS(tx_queue);
+DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
+DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
+DEBUGFS_READ_FILE_OPS(ucode_general_stats);
+DEBUGFS_READ_FILE_OPS(sensitivity);
+DEBUGFS_READ_FILE_OPS(chain_noise);
+DEBUGFS_READ_FILE_OPS(power_save_status);
+DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats);
+DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats);
+DEBUGFS_READ_FILE_OPS(fh_reg);
+DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
+DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
+DEBUGFS_READ_FILE_OPS(rxon_flags);
+DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
+DEBUGFS_WRITE_FILE_OPS(wd_timeout);
+
+/*
+ * Create the debugfs files and directories
+ *
+ */
+int
+il_dbgfs_register(struct il_priv *il, const char *name)
+{
+       struct dentry *phyd = il->hw->wiphy->debugfsdir;
+       struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
+
+       dir_drv = debugfs_create_dir(name, phyd);
+       if (!dir_drv)
+               return -ENOMEM;
+
+       il->debugfs_dir = dir_drv;
+
+       dir_data = debugfs_create_dir("data", dir_drv);
+       if (!dir_data)
+               goto err;
+       dir_rf = debugfs_create_dir("rf", dir_drv);
+       if (!dir_rf)
+               goto err;
+       dir_debug = debugfs_create_dir("debug", dir_drv);
+       if (!dir_debug)
+               goto err;
+
+       DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
+       DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
+       DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
+       DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
+       DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
+       DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
+       DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
+       DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
+       DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
+       DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR);
+       DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR);
+       DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
+       DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
+       DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
+
+       if (il->cfg->base_params->sensitivity_calib_by_driver)
+               DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
+       if (il->cfg->base_params->chain_noise_calib_by_driver)
+               DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
+       DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
+       DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
+       if (il->cfg->base_params->sensitivity_calib_by_driver)
+               DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
+                                &il->disable_sens_cal);
+       if (il->cfg->base_params->chain_noise_calib_by_driver)
+               DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
+                                &il->disable_chain_noise_cal);
+       DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal);
+       return 0;
+
+err:
+       IL_ERR("Can't create the debugfs directory\n");
+       il_dbgfs_unregister(il);
+       return -ENOMEM;
+}
+EXPORT_SYMBOL(il_dbgfs_register);
+
+/**
+ * Remove the debugfs files and directories
+ *
+ */
+void
+il_dbgfs_unregister(struct il_priv *il)
+{
+       if (!il->debugfs_dir)
+               return;
+
+       debugfs_remove_recursive(il->debugfs_dir);
+       il->debugfs_dir = NULL;
+}
+EXPORT_SYMBOL(il_dbgfs_unregister);
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.c
deleted file mode 100644 (file)
index cfabb38..0000000
+++ /dev/null
@@ -1,523 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include "iwl-3945-debugfs.h"
-
-
-static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
-{
-       int p = 0;
-
-       p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
-                      le32_to_cpu(priv->_3945.statistics.flag));
-       if (le32_to_cpu(priv->_3945.statistics.flag) &
-                       UCODE_STATISTICS_CLEAR_MSK)
-               p += scnprintf(buf + p, bufsz - p,
-                              "\tStatistics have been cleared\n");
-       p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
-                      (le32_to_cpu(priv->_3945.statistics.flag) &
-                       UCODE_STATISTICS_FREQUENCY_MSK)
-                       ? "2.4 GHz" : "5.2 GHz");
-       p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
-                      (le32_to_cpu(priv->_3945.statistics.flag) &
-                       UCODE_STATISTICS_NARROW_BAND_MSK)
-                       ? "enabled" : "disabled");
-       return p;
-}
-
-ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
-                                   char __user *user_buf,
-                                   size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       char *buf;
-       int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 +
-                   sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400;
-       ssize_t ret;
-       struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm,
-                                       *max_ofdm;
-       struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
-       struct iwl39_statistics_rx_non_phy *general, *accum_general;
-       struct iwl39_statistics_rx_non_phy *delta_general, *max_general;
-
-       if (!iwl_legacy_is_alive(priv))
-               return -EAGAIN;
-
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       /*
-        * The statistic information display here is based on
-        * the last statistics notification from uCode
-        * might not reflect the current uCode activity
-        */
-       ofdm = &priv->_3945.statistics.rx.ofdm;
-       cck = &priv->_3945.statistics.rx.cck;
-       general = &priv->_3945.statistics.rx.general;
-       accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm;
-       accum_cck = &priv->_3945.accum_statistics.rx.cck;
-       accum_general = &priv->_3945.accum_statistics.rx.general;
-       delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm;
-       delta_cck = &priv->_3945.delta_statistics.rx.cck;
-       delta_general = &priv->_3945.delta_statistics.rx.general;
-       max_ofdm = &priv->_3945.max_delta.rx.ofdm;
-       max_cck = &priv->_3945.max_delta.rx.cck;
-       max_general = &priv->_3945.max_delta.rx.general;
-
-       pos += iwl3945_statistics_flag(priv, buf, bufsz);
-       pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-                        "acumulative       delta         max\n",
-                        "Statistics_Rx - OFDM:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
-                        accum_ofdm->ina_cnt,
-                        delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "fina_cnt:",
-                        le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
-                        delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n", "plcp_err:",
-                        le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
-                        delta_ofdm->plcp_err, max_ofdm->plcp_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",  "crc32_err:",
-                        le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
-                        delta_ofdm->crc32_err, max_ofdm->crc32_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:",
-                        le32_to_cpu(ofdm->overrun_err),
-                        accum_ofdm->overrun_err, delta_ofdm->overrun_err,
-                        max_ofdm->overrun_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "early_overrun_err:",
-                        le32_to_cpu(ofdm->early_overrun_err),
-                        accum_ofdm->early_overrun_err,
-                        delta_ofdm->early_overrun_err,
-                        max_ofdm->early_overrun_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "crc32_good:", le32_to_cpu(ofdm->crc32_good),
-                        accum_ofdm->crc32_good, delta_ofdm->crc32_good,
-                        max_ofdm->crc32_good);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:",
-                        le32_to_cpu(ofdm->false_alarm_cnt),
-                        accum_ofdm->false_alarm_cnt,
-                        delta_ofdm->false_alarm_cnt,
-                        max_ofdm->false_alarm_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "fina_sync_err_cnt:",
-                        le32_to_cpu(ofdm->fina_sync_err_cnt),
-                        accum_ofdm->fina_sync_err_cnt,
-                        delta_ofdm->fina_sync_err_cnt,
-                        max_ofdm->fina_sync_err_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "sfd_timeout:",
-                        le32_to_cpu(ofdm->sfd_timeout),
-                        accum_ofdm->sfd_timeout,
-                        delta_ofdm->sfd_timeout,
-                        max_ofdm->sfd_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "fina_timeout:",
-                        le32_to_cpu(ofdm->fina_timeout),
-                        accum_ofdm->fina_timeout,
-                        delta_ofdm->fina_timeout,
-                        max_ofdm->fina_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "unresponded_rts:",
-                        le32_to_cpu(ofdm->unresponded_rts),
-                        accum_ofdm->unresponded_rts,
-                        delta_ofdm->unresponded_rts,
-                        max_ofdm->unresponded_rts);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "rxe_frame_lmt_ovrun:",
-                        le32_to_cpu(ofdm->rxe_frame_limit_overrun),
-                        accum_ofdm->rxe_frame_limit_overrun,
-                        delta_ofdm->rxe_frame_limit_overrun,
-                        max_ofdm->rxe_frame_limit_overrun);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "sent_ack_cnt:",
-                        le32_to_cpu(ofdm->sent_ack_cnt),
-                        accum_ofdm->sent_ack_cnt,
-                        delta_ofdm->sent_ack_cnt,
-                        max_ofdm->sent_ack_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "sent_cts_cnt:",
-                        le32_to_cpu(ofdm->sent_cts_cnt),
-                        accum_ofdm->sent_cts_cnt,
-                        delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-                        "acumulative       delta         max\n",
-                        "Statistics_Rx - CCK:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "ina_cnt:",
-                        le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
-                        delta_cck->ina_cnt, max_cck->ina_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "fina_cnt:",
-                        le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
-                        delta_cck->fina_cnt, max_cck->fina_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "plcp_err:",
-                        le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
-                        delta_cck->plcp_err, max_cck->plcp_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "crc32_err:",
-                        le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
-                        delta_cck->crc32_err, max_cck->crc32_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "overrun_err:",
-                        le32_to_cpu(cck->overrun_err),
-                        accum_cck->overrun_err,
-                        delta_cck->overrun_err, max_cck->overrun_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "early_overrun_err:",
-                        le32_to_cpu(cck->early_overrun_err),
-                        accum_cck->early_overrun_err,
-                        delta_cck->early_overrun_err,
-                        max_cck->early_overrun_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "crc32_good:",
-                        le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
-                        delta_cck->crc32_good,
-                        max_cck->crc32_good);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "false_alarm_cnt:",
-                        le32_to_cpu(cck->false_alarm_cnt),
-                        accum_cck->false_alarm_cnt,
-                        delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "fina_sync_err_cnt:",
-                        le32_to_cpu(cck->fina_sync_err_cnt),
-                        accum_cck->fina_sync_err_cnt,
-                        delta_cck->fina_sync_err_cnt,
-                        max_cck->fina_sync_err_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "sfd_timeout:",
-                        le32_to_cpu(cck->sfd_timeout),
-                        accum_cck->sfd_timeout,
-                        delta_cck->sfd_timeout, max_cck->sfd_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "fina_timeout:",
-                        le32_to_cpu(cck->fina_timeout),
-                        accum_cck->fina_timeout,
-                        delta_cck->fina_timeout, max_cck->fina_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "unresponded_rts:",
-                        le32_to_cpu(cck->unresponded_rts),
-                        accum_cck->unresponded_rts,
-                        delta_cck->unresponded_rts,
-                        max_cck->unresponded_rts);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "rxe_frame_lmt_ovrun:",
-                        le32_to_cpu(cck->rxe_frame_limit_overrun),
-                        accum_cck->rxe_frame_limit_overrun,
-                        delta_cck->rxe_frame_limit_overrun,
-                        max_cck->rxe_frame_limit_overrun);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "sent_ack_cnt:",
-                        le32_to_cpu(cck->sent_ack_cnt),
-                        accum_cck->sent_ack_cnt,
-                        delta_cck->sent_ack_cnt,
-                        max_cck->sent_ack_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "sent_cts_cnt:",
-                        le32_to_cpu(cck->sent_cts_cnt),
-                        accum_cck->sent_cts_cnt,
-                        delta_cck->sent_cts_cnt,
-                        max_cck->sent_cts_cnt);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-                        "acumulative       delta         max\n",
-                        "Statistics_Rx - GENERAL:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "bogus_cts:",
-                        le32_to_cpu(general->bogus_cts),
-                        accum_general->bogus_cts,
-                        delta_general->bogus_cts, max_general->bogus_cts);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "bogus_ack:",
-                        le32_to_cpu(general->bogus_ack),
-                        accum_general->bogus_ack,
-                        delta_general->bogus_ack, max_general->bogus_ack);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "non_bssid_frames:",
-                        le32_to_cpu(general->non_bssid_frames),
-                        accum_general->non_bssid_frames,
-                        delta_general->non_bssid_frames,
-                        max_general->non_bssid_frames);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "filtered_frames:",
-                        le32_to_cpu(general->filtered_frames),
-                        accum_general->filtered_frames,
-                        delta_general->filtered_frames,
-                        max_general->filtered_frames);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "non_channel_beacons:",
-                        le32_to_cpu(general->non_channel_beacons),
-                        accum_general->non_channel_beacons,
-                        delta_general->non_channel_beacons,
-                        max_general->non_channel_beacons);
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
-                                   char __user *user_buf,
-                                   size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       char *buf;
-       int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250;
-       ssize_t ret;
-       struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
-
-       if (!iwl_legacy_is_alive(priv))
-               return -EAGAIN;
-
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       /*
-        * The statistic information display here is based on
-        * the last statistics notification from uCode
-        * might not reflect the current uCode activity
-        */
-       tx = &priv->_3945.statistics.tx;
-       accum_tx = &priv->_3945.accum_statistics.tx;
-       delta_tx = &priv->_3945.delta_statistics.tx;
-       max_tx = &priv->_3945.max_delta.tx;
-       pos += iwl3945_statistics_flag(priv, buf, bufsz);
-       pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-                        "acumulative       delta         max\n",
-                        "Statistics_Tx:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "preamble:",
-                        le32_to_cpu(tx->preamble_cnt),
-                        accum_tx->preamble_cnt,
-                        delta_tx->preamble_cnt, max_tx->preamble_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "rx_detected_cnt:",
-                        le32_to_cpu(tx->rx_detected_cnt),
-                        accum_tx->rx_detected_cnt,
-                        delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "bt_prio_defer_cnt:",
-                        le32_to_cpu(tx->bt_prio_defer_cnt),
-                        accum_tx->bt_prio_defer_cnt,
-                        delta_tx->bt_prio_defer_cnt,
-                        max_tx->bt_prio_defer_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "bt_prio_kill_cnt:",
-                        le32_to_cpu(tx->bt_prio_kill_cnt),
-                        accum_tx->bt_prio_kill_cnt,
-                        delta_tx->bt_prio_kill_cnt,
-                        max_tx->bt_prio_kill_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "few_bytes_cnt:",
-                        le32_to_cpu(tx->few_bytes_cnt),
-                        accum_tx->few_bytes_cnt,
-                        delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "cts_timeout:",
-                        le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
-                        delta_tx->cts_timeout, max_tx->cts_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "ack_timeout:",
-                        le32_to_cpu(tx->ack_timeout),
-                        accum_tx->ack_timeout,
-                        delta_tx->ack_timeout, max_tx->ack_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "expected_ack_cnt:",
-                        le32_to_cpu(tx->expected_ack_cnt),
-                        accum_tx->expected_ack_cnt,
-                        delta_tx->expected_ack_cnt,
-                        max_tx->expected_ack_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "actual_ack_cnt:",
-                        le32_to_cpu(tx->actual_ack_cnt),
-                        accum_tx->actual_ack_cnt,
-                        delta_tx->actual_ack_cnt,
-                        max_tx->actual_ack_cnt);
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-ssize_t iwl3945_ucode_general_stats_read(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       char *buf;
-       int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300;
-       ssize_t ret;
-       struct iwl39_statistics_general *general, *accum_general;
-       struct iwl39_statistics_general *delta_general, *max_general;
-       struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
-       struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div;
-
-       if (!iwl_legacy_is_alive(priv))
-               return -EAGAIN;
-
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       /*
-        * The statistic information display here is based on
-        * the last statistics notification from uCode
-        * might not reflect the current uCode activity
-        */
-       general = &priv->_3945.statistics.general;
-       dbg = &priv->_3945.statistics.general.dbg;
-       div = &priv->_3945.statistics.general.div;
-       accum_general = &priv->_3945.accum_statistics.general;
-       delta_general = &priv->_3945.delta_statistics.general;
-       max_general = &priv->_3945.max_delta.general;
-       accum_dbg = &priv->_3945.accum_statistics.general.dbg;
-       delta_dbg = &priv->_3945.delta_statistics.general.dbg;
-       max_dbg = &priv->_3945.max_delta.general.dbg;
-       accum_div = &priv->_3945.accum_statistics.general.div;
-       delta_div = &priv->_3945.delta_statistics.general.div;
-       max_div = &priv->_3945.max_delta.general.div;
-       pos += iwl3945_statistics_flag(priv, buf, bufsz);
-       pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-                        "acumulative       delta         max\n",
-                        "Statistics_General:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "burst_check:",
-                        le32_to_cpu(dbg->burst_check),
-                        accum_dbg->burst_check,
-                        delta_dbg->burst_check, max_dbg->burst_check);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "burst_count:",
-                        le32_to_cpu(dbg->burst_count),
-                        accum_dbg->burst_count,
-                        delta_dbg->burst_count, max_dbg->burst_count);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "sleep_time:",
-                        le32_to_cpu(general->sleep_time),
-                        accum_general->sleep_time,
-                        delta_general->sleep_time, max_general->sleep_time);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "slots_out:",
-                        le32_to_cpu(general->slots_out),
-                        accum_general->slots_out,
-                        delta_general->slots_out, max_general->slots_out);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "slots_idle:",
-                        le32_to_cpu(general->slots_idle),
-                        accum_general->slots_idle,
-                        delta_general->slots_idle, max_general->slots_idle);
-       pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
-                        le32_to_cpu(general->ttl_timestamp));
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "tx_on_a:",
-                        le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
-                        delta_div->tx_on_a, max_div->tx_on_a);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "tx_on_b:",
-                        le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
-                        delta_div->tx_on_b, max_div->tx_on_b);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "exec_time:",
-                        le32_to_cpu(div->exec_time), accum_div->exec_time,
-                        delta_div->exec_time, max_div->exec_time);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        "  %-30s %10u  %10u  %10u  %10u\n",
-                        "probe_time:",
-                        le32_to_cpu(div->probe_time), accum_div->probe_time,
-                        delta_div->probe_time, max_div->probe_time);
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.h b/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.h
deleted file mode 100644 (file)
index 8fef4b3..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-debug.h"
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
-                                   size_t count, loff_t *ppos);
-ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
-                                   size_t count, loff_t *ppos);
-ssize_t iwl3945_ucode_general_stats_read(struct file *file,
-                                        char __user *user_buf, size_t count,
-                                        loff_t *ppos);
-#else
-static ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
-                                          char __user *user_buf, size_t count,
-                                          loff_t *ppos)
-{
-       return 0;
-}
-static ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
-                                          char __user *user_buf, size_t count,
-                                          loff_t *ppos)
-{
-       return 0;
-}
-static ssize_t iwl3945_ucode_general_stats_read(struct file *file,
-                                               char __user *user_buf,
-                                               size_t count, loff_t *ppos)
-{
-       return 0;
-}
-#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-fh.h b/drivers/net/wireless/iwlegacy/iwl-3945-fh.h
deleted file mode 100644 (file)
index 836c991..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/******************************************************************************
- *
- * 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 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 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_3945_fh_h__
-#define __iwl_3945_fh_h__
-
-/************************************/
-/* iwl3945 Flow Handler Definitions */
-/************************************/
-
-/**
- * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
- * Addresses are offsets from device's PCI hardware base address.
- */
-#define FH39_MEM_LOWER_BOUND                   (0x0800)
-#define FH39_MEM_UPPER_BOUND                   (0x1000)
-
-#define FH39_CBCC_TABLE                (FH39_MEM_LOWER_BOUND + 0x140)
-#define FH39_TFDB_TABLE                (FH39_MEM_LOWER_BOUND + 0x180)
-#define FH39_RCSR_TABLE                (FH39_MEM_LOWER_BOUND + 0x400)
-#define FH39_RSSR_TABLE                (FH39_MEM_LOWER_BOUND + 0x4c0)
-#define FH39_TCSR_TABLE                (FH39_MEM_LOWER_BOUND + 0x500)
-#define FH39_TSSR_TABLE                (FH39_MEM_LOWER_BOUND + 0x680)
-
-/* TFDB (Transmit Frame Buffer Descriptor) */
-#define FH39_TFDB(_ch, buf)                    (FH39_TFDB_TABLE + \
-                                                ((_ch) * 2 + (buf)) * 0x28)
-#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch)       (FH39_TFDB_TABLE + 0x50 * (_ch))
-
-/* CBCC channel is [0,2] */
-#define FH39_CBCC(_ch)         (FH39_CBCC_TABLE + (_ch) * 0x8)
-#define FH39_CBCC_CTRL(_ch)    (FH39_CBCC(_ch) + 0x00)
-#define FH39_CBCC_BASE(_ch)    (FH39_CBCC(_ch) + 0x04)
-
-/* RCSR channel is [0,2] */
-#define FH39_RCSR(_ch)                 (FH39_RCSR_TABLE + (_ch) * 0x40)
-#define FH39_RCSR_CONFIG(_ch)          (FH39_RCSR(_ch) + 0x00)
-#define FH39_RCSR_RBD_BASE(_ch)                (FH39_RCSR(_ch) + 0x04)
-#define FH39_RCSR_WPTR(_ch)            (FH39_RCSR(_ch) + 0x20)
-#define FH39_RCSR_RPTR_ADDR(_ch)       (FH39_RCSR(_ch) + 0x24)
-
-#define FH39_RSCSR_CHNL0_WPTR          (FH39_RCSR_WPTR(0))
-
-/* RSSR */
-#define FH39_RSSR_CTRL                 (FH39_RSSR_TABLE + 0x000)
-#define FH39_RSSR_STATUS               (FH39_RSSR_TABLE + 0x004)
-
-/* TCSR */
-#define FH39_TCSR(_ch)                 (FH39_TCSR_TABLE + (_ch) * 0x20)
-#define FH39_TCSR_CONFIG(_ch)          (FH39_TCSR(_ch) + 0x00)
-#define FH39_TCSR_CREDIT(_ch)          (FH39_TCSR(_ch) + 0x04)
-#define FH39_TCSR_BUFF_STTS(_ch)       (FH39_TCSR(_ch) + 0x08)
-
-/* TSSR */
-#define FH39_TSSR_CBB_BASE        (FH39_TSSR_TABLE + 0x000)
-#define FH39_TSSR_MSG_CONFIG      (FH39_TSSR_TABLE + 0x008)
-#define FH39_TSSR_TX_STATUS       (FH39_TSSR_TABLE + 0x010)
-
-
-/* DBM */
-
-#define FH39_SRVC_CHNL                            (6)
-
-#define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE     (20)
-#define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH      (4)
-
-#define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN    (0x08000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE        (0x80000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE           (0x20000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128          (0x01000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST          (0x00001000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH                        (0x00000000)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF               (0x00000000)
-#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER            (0x00000001)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL     (0x00000000)
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL      (0x00000008)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD            (0x00200000)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT             (0x00000000)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE             (0x00000000)
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE            (0x80000000)
-
-#define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID           (0x00004000)
-
-#define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR            (0x00000001)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON       (0xFF000000)
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON       (0x00FF0000)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B     (0x00000400)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON                (0x00000100)
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON                (0x00000080)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH      (0x00000020)
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH            (0x00000005)
-
-#define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch)    (BIT(_ch) << 24)
-#define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch)   (BIT(_ch) << 16)
-
-#define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \
-       (FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \
-        FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch))
-
-#define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE                    (0x01000000)
-
-struct iwl3945_tfd_tb {
-       __le32 addr;
-       __le32 len;
-} __packed;
-
-struct iwl3945_tfd {
-       __le32 control_flags;
-       struct iwl3945_tfd_tb tbs[4];
-       u8 __pad[28];
-} __packed;
-
-
-#endif /* __iwl_3945_fh_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-hw.h b/drivers/net/wireless/iwlegacy/iwl-3945-hw.h
deleted file mode 100644 (file)
index 5c3a68d..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-/******************************************************************************
- *
- * 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 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 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.
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-3945-hw.h) only for hardware-related definitions.
- * Please use iwl-commands.h for uCode API definitions.
- * Please use iwl-3945.h for driver implementation definitions.
- */
-
-#ifndef __iwl_3945_hw__
-#define __iwl_3945_hw__
-
-#include "iwl-eeprom.h"
-
-/* RSSI to dBm */
-#define IWL39_RSSI_OFFSET      95
-
-/*
- * EEPROM related constants, enums, and structures.
- */
-#define EEPROM_SKU_CAP_OP_MODE_MRC                      (1 << 7)
-
-/*
- * 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.
- * DO NOT ALTER THIS STRUCTURE!!!
- */
-struct iwl3945_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 */
-} __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 iwl3945_eeprom_txpower_group {
-       struct iwl3945_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) */
-} __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 iwl3945_eeprom_temperature_corr {
-       u32 Ta;
-       u32 Tb;
-       u32 Tc;
-       u32 Td;
-       u32 Te;
-} __packed;
-
-/*
- * EEPROM map
- */
-struct iwl3945_eeprom {
-       u8 reserved0[16];
-       u16 device_id;  /* abs.ofs: 16 */
-       u8 reserved1[2];
-       u16 pmc;                /* abs.ofs: 20 */
-       u8 reserved2[20];
-       u8 mac_address[6];      /* abs.ofs: 42 */
-       u8 reserved3[58];
-       u16 board_revision;     /* abs.ofs: 106 */
-       u8 reserved4[11];
-       u8 board_pba_number[9]; /* abs.ofs: 119 */
-       u8 reserved5[8];
-       u16 version;            /* abs.ofs: 136 */
-       u8 sku_cap;             /* abs.ofs: 138 */
-       u8 leds_mode;           /* abs.ofs: 139 */
-       u16 oem_mode;
-       u16 wowlan_mode;        /* abs.ofs: 142 */
-       u16 leds_time_interval; /* abs.ofs: 144 */
-       u8 leds_off_time;       /* abs.ofs: 146 */
-       u8 leds_on_time;        /* abs.ofs: 147 */
-       u8 almgor_m_version;    /* abs.ofs: 148 */
-       u8 antenna_switch_type; /* abs.ofs: 149 */
-       u8 reserved6[42];
-       u8 sku_id[4];           /* abs.ofs: 192 */
-
-/*
- * Per-channel regulatory data.
- *
- * Each channel that *might* be supported by 3945 has a fixed location
- * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
- * txpower (MSB).
- *
- * Entries immediately below are for 20 MHz channel width.
- *
- * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
- */
-       u16 band_1_count;       /* abs.ofs: 196 */
-       struct iwl_eeprom_channel band_1_channels[14];  /* abs.ofs: 198 */
-
-/*
- * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
- * 5.0 GHz channels 7, 8, 11, 12, 16
- * (4915-5080MHz) (none of these is ever supported)
- */
-       u16 band_2_count;       /* abs.ofs: 226 */
-       struct iwl_eeprom_channel band_2_channels[13];  /* abs.ofs: 228 */
-
-/*
- * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
- * (5170-5320MHz)
- */
-       u16 band_3_count;       /* abs.ofs: 254 */
-       struct iwl_eeprom_channel band_3_channels[12];  /* abs.ofs: 256 */
-
-/*
- * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
- * (5500-5700MHz)
- */
-       u16 band_4_count;       /* abs.ofs: 280 */
-       struct iwl_eeprom_channel band_4_channels[11];  /* abs.ofs: 282 */
-
-/*
- * 5.7 GHz channels 145, 149, 153, 157, 161, 165
- * (5725-5825MHz)
- */
-       u16 band_5_count;       /* abs.ofs: 304 */
-       struct iwl_eeprom_channel band_5_channels[6];  /* abs.ofs: 306 */
-
-       u8 reserved9[194];
-
-/*
- * 3945 Txpower calibration data.
- */
-#define IWL_NUM_TX_CALIB_GROUPS 5
-       struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
-/* abs.ofs: 512 */
-       struct iwl3945_eeprom_temperature_corr corrections;  /* abs.ofs: 832 */
-       u8 reserved16[172];     /* fill out to full 1024 byte block */
-} __packed;
-
-#define IWL3945_EEPROM_IMG_SIZE 1024
-
-/* End of EEPROM */
-
-#define PCI_CFG_REV_ID_BIT_BASIC_SKU                (0x40)     /* bit 6    */
-#define PCI_CFG_REV_ID_BIT_RTP                      (0x80)     /* bit 7    */
-
-/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
-#define IWL39_NUM_QUEUES        5
-#define IWL39_CMD_QUEUE_NUM    4
-
-#define IWL_DEFAULT_TX_RETRY  15
-
-/*********************************************/
-
-#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
-
-#define U32_PAD(n)             ((4-(n))&0x3)
-
-#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)
-
-/* Sizes and addresses for instruction and data memory (SRAM) in
- * 3945's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
-#define IWL39_RTC_INST_LOWER_BOUND             (0x000000)
-#define IWL39_RTC_INST_UPPER_BOUND             (0x014000)
-
-#define IWL39_RTC_DATA_LOWER_BOUND             (0x800000)
-#define IWL39_RTC_DATA_UPPER_BOUND             (0x808000)
-
-#define IWL39_RTC_INST_SIZE (IWL39_RTC_INST_UPPER_BOUND - \
-                               IWL39_RTC_INST_LOWER_BOUND)
-#define IWL39_RTC_DATA_SIZE (IWL39_RTC_DATA_UPPER_BOUND - \
-                               IWL39_RTC_DATA_LOWER_BOUND)
-
-#define IWL39_MAX_INST_SIZE IWL39_RTC_INST_SIZE
-#define IWL39_MAX_DATA_SIZE IWL39_RTC_DATA_SIZE
-
-/* Size of uCode instruction memory in bootstrap state machine */
-#define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE
-
-static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
-{
-       return (addr >= IWL39_RTC_DATA_LOWER_BOUND) &&
-              (addr < IWL39_RTC_DATA_UPPER_BOUND);
-}
-
-/* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE
- * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */
-struct iwl3945_shared {
-       __le32 tx_base_ptr[8];
-} __packed;
-
-static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags)
-{
-       return le16_to_cpu(rate_n_flags) & 0xFF;
-}
-
-static inline u16 iwl3945_hw_get_rate_n_flags(__le16 rate_n_flags)
-{
-       return le16_to_cpu(rate_n_flags);
-}
-
-static inline __le16 iwl3945_hw_set_rate_n_flags(u8 rate, u16 flags)
-{
-       return cpu_to_le16((u16)rate|flags);
-}
-#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-led.c b/drivers/net/wireless/iwlegacy/iwl-3945-led.c
deleted file mode 100644 (file)
index 7a7f0f3..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.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 <net/mac80211.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include "iwl-commands.h"
-#include "iwl-3945.h"
-#include "iwl-core.h"
-#include "iwl-dev.h"
-#include "iwl-3945-led.h"
-
-
-/* Send led command */
-static int iwl3945_send_led_cmd(struct iwl_priv *priv,
-                               struct iwl_led_cmd *led_cmd)
-{
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_LEDS_CMD,
-               .len = sizeof(struct iwl_led_cmd),
-               .data = led_cmd,
-               .flags = CMD_ASYNC,
-               .callback = NULL,
-       };
-
-       return iwl_legacy_send_cmd(priv, &cmd);
-}
-
-const struct iwl_led_ops iwl3945_led_ops = {
-       .cmd = iwl3945_send_led_cmd,
-};
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-led.h b/drivers/net/wireless/iwlegacy/iwl-3945-led.h
deleted file mode 100644 (file)
index 9671627..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_3945_led_h__
-#define __iwl_3945_led_h__
-
-extern const struct iwl_led_ops iwl3945_led_ops;
-
-#endif /* __iwl_3945_led_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-rs.c b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
deleted file mode 100644 (file)
index 8faeaf2..0000000
+++ /dev/null
@@ -1,996 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2005 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <net/mac80211.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-
-#include <linux/workqueue.h>
-
-#include "iwl-commands.h"
-#include "iwl-3945.h"
-#include "iwl-sta.h"
-
-#define RS_NAME "iwl-3945-rs"
-
-static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = {
-       7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
-};
-
-static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT_3945] = {
-       7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
-};
-
-static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT_3945] = {
-       0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
-};
-
-static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = {
-       7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-struct iwl3945_tpt_entry {
-       s8 min_rssi;
-       u8 index;
-};
-
-static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
-       {-60, IWL_RATE_54M_INDEX},
-       {-64, IWL_RATE_48M_INDEX},
-       {-72, IWL_RATE_36M_INDEX},
-       {-80, IWL_RATE_24M_INDEX},
-       {-84, IWL_RATE_18M_INDEX},
-       {-85, IWL_RATE_12M_INDEX},
-       {-87, IWL_RATE_9M_INDEX},
-       {-89, IWL_RATE_6M_INDEX}
-};
-
-static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
-       {-60, IWL_RATE_54M_INDEX},
-       {-64, IWL_RATE_48M_INDEX},
-       {-68, IWL_RATE_36M_INDEX},
-       {-80, IWL_RATE_24M_INDEX},
-       {-84, IWL_RATE_18M_INDEX},
-       {-85, IWL_RATE_12M_INDEX},
-       {-86, IWL_RATE_11M_INDEX},
-       {-88, IWL_RATE_5M_INDEX},
-       {-90, IWL_RATE_2M_INDEX},
-       {-92, IWL_RATE_1M_INDEX}
-};
-
-#define IWL_RATE_MAX_WINDOW          62
-#define IWL_RATE_FLUSH         (3*HZ)
-#define IWL_RATE_WIN_FLUSH       (HZ/2)
-#define IWL39_RATE_HIGH_TH          11520
-#define IWL_SUCCESS_UP_TH         8960
-#define IWL_SUCCESS_DOWN_TH      10880
-#define IWL_RATE_MIN_FAILURE_TH       6
-#define IWL_RATE_MIN_SUCCESS_TH       8
-#define IWL_RATE_DECREASE_TH       1920
-#define IWL_RATE_RETRY_TH           15
-
-static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
-{
-       u32 index = 0;
-       u32 table_size = 0;
-       struct iwl3945_tpt_entry *tpt_table = NULL;
-
-       if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
-               rssi = IWL_MIN_RSSI_VAL;
-
-       switch (band) {
-       case IEEE80211_BAND_2GHZ:
-               tpt_table = iwl3945_tpt_table_g;
-               table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
-               break;
-
-       case IEEE80211_BAND_5GHZ:
-               tpt_table = iwl3945_tpt_table_a;
-               table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
-               break;
-
-       default:
-               BUG();
-               break;
-       }
-
-       while ((index < table_size) && (rssi < tpt_table[index].min_rssi))
-               index++;
-
-       index = min(index, (table_size - 1));
-
-       return tpt_table[index].index;
-}
-
-static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
-{
-       window->data = 0;
-       window->success_counter = 0;
-       window->success_ratio = -1;
-       window->counter = 0;
-       window->average_tpt = IWL_INVALID_VALUE;
-       window->stamp = 0;
-}
-
-/**
- * iwl3945_rate_scale_flush_windows - flush out the rate scale windows
- *
- * Returns the number of windows that have gathered data but were
- * not flushed.  If there were any that were not flushed, then
- * reschedule the rate flushing routine.
- */
-static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
-{
-       int unflushed = 0;
-       int i;
-       unsigned long flags;
-       struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-
-       /*
-        * For each rate, if we have collected data on that rate
-        * and it has been more than IWL_RATE_WIN_FLUSH
-        * since we flushed, clear out the gathered statistics
-        */
-       for (i = 0; i < IWL_RATE_COUNT_3945; i++) {
-               if (!rs_sta->win[i].counter)
-                       continue;
-
-               spin_lock_irqsave(&rs_sta->lock, flags);
-               if (time_after(jiffies, rs_sta->win[i].stamp +
-                              IWL_RATE_WIN_FLUSH)) {
-                       IWL_DEBUG_RATE(priv, "flushing %d samples of rate "
-                                      "index %d\n",
-                                      rs_sta->win[i].counter, i);
-                       iwl3945_clear_window(&rs_sta->win[i]);
-               } else
-                       unflushed++;
-               spin_unlock_irqrestore(&rs_sta->lock, flags);
-       }
-
-       return unflushed;
-}
-
-#define IWL_RATE_FLUSH_MAX              5000   /* msec */
-#define IWL_RATE_FLUSH_MIN              50     /* msec */
-#define IWL_AVERAGE_PACKETS             1500
-
-static void iwl3945_bg_rate_scale_flush(unsigned long data)
-{
-       struct iwl3945_rs_sta *rs_sta = (void *)data;
-       struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-       int unflushed = 0;
-       unsigned long flags;
-       u32 packet_count, duration, pps;
-
-       IWL_DEBUG_RATE(priv, "enter\n");
-
-       unflushed = iwl3945_rate_scale_flush_windows(rs_sta);
-
-       spin_lock_irqsave(&rs_sta->lock, flags);
-
-       /* Number of packets Rx'd since last time this timer ran */
-       packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
-
-       rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
-
-       if (unflushed) {
-               duration =
-                   jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
-
-               IWL_DEBUG_RATE(priv, "Tx'd %d packets in %dms\n",
-                              packet_count, duration);
-
-               /* Determine packets per second */
-               if (duration)
-                       pps = (packet_count * 1000) / duration;
-               else
-                       pps = 0;
-
-               if (pps) {
-                       duration = (IWL_AVERAGE_PACKETS * 1000) / pps;
-                       if (duration < IWL_RATE_FLUSH_MIN)
-                               duration = IWL_RATE_FLUSH_MIN;
-                       else if (duration > IWL_RATE_FLUSH_MAX)
-                               duration = IWL_RATE_FLUSH_MAX;
-               } else
-                       duration = IWL_RATE_FLUSH_MAX;
-
-               rs_sta->flush_time = msecs_to_jiffies(duration);
-
-               IWL_DEBUG_RATE(priv, "new flush period: %d msec ave %d\n",
-                              duration, packet_count);
-
-               mod_timer(&rs_sta->rate_scale_flush, jiffies +
-                         rs_sta->flush_time);
-
-               rs_sta->last_partial_flush = jiffies;
-       } else {
-               rs_sta->flush_time = IWL_RATE_FLUSH;
-               rs_sta->flush_pending = 0;
-       }
-       /* If there weren't any unflushed entries, we don't schedule the timer
-        * to run again */
-
-       rs_sta->last_flush = jiffies;
-
-       spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-       IWL_DEBUG_RATE(priv, "leave\n");
-}
-
-/**
- * iwl3945_collect_tx_data - Update the success/failure sliding window
- *
- * We keep a sliding window of the last 64 packets transmitted
- * at this rate.  window->data contains the bitmask of successful
- * packets.
- */
-static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
-                               struct iwl3945_rate_scale_data *window,
-                               int success, int retries, int index)
-{
-       unsigned long flags;
-       s32 fail_count;
-       struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-
-       if (!retries) {
-               IWL_DEBUG_RATE(priv, "leave: retries == 0 -- should be at least 1\n");
-               return;
-       }
-
-       spin_lock_irqsave(&rs_sta->lock, flags);
-
-       /*
-        * Keep track of only the latest 62 tx frame attempts in this rate's
-        * history window; anything older isn't really relevant any more.
-        * If we have filled up the sliding window, drop the oldest attempt;
-        * if the oldest attempt (highest bit in bitmap) shows "success",
-        * subtract "1" from the success counter (this is the main reason
-        * we keep these bitmaps!).
-        * */
-       while (retries > 0) {
-               if (window->counter >= IWL_RATE_MAX_WINDOW) {
-
-                       /* remove earliest */
-                       window->counter = IWL_RATE_MAX_WINDOW - 1;
-
-                       if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) {
-                               window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1));
-                               window->success_counter--;
-                       }
-               }
-
-               /* Increment frames-attempted counter */
-               window->counter++;
-
-               /* Shift bitmap by one frame (throw away oldest history),
-                * OR in "1", and increment "success" if this
-                * frame was successful. */
-               window->data <<= 1;
-               if (success > 0) {
-                       window->success_counter++;
-                       window->data |= 0x1;
-                       success--;
-               }
-
-               retries--;
-       }
-
-       /* Calculate current success ratio, avoid divide-by-0! */
-       if (window->counter > 0)
-               window->success_ratio = 128 * (100 * window->success_counter)
-                                       / window->counter;
-       else
-               window->success_ratio = IWL_INVALID_VALUE;
-
-       fail_count = window->counter - window->success_counter;
-
-       /* Calculate average throughput, if we have enough history. */
-       if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
-           (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
-               window->average_tpt = ((window->success_ratio *
-                               rs_sta->expected_tpt[index] + 64) / 128);
-       else
-               window->average_tpt = IWL_INVALID_VALUE;
-
-       /* Tag this window as having been updated */
-       window->stamp = jiffies;
-
-       spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-}
-
-/*
- * Called after adding a new station to initialize rate scaling
- */
-void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id)
-{
-       struct ieee80211_hw *hw = priv->hw;
-       struct ieee80211_conf *conf = &priv->hw->conf;
-       struct iwl3945_sta_priv *psta;
-       struct iwl3945_rs_sta *rs_sta;
-       struct ieee80211_supported_band *sband;
-       int i;
-
-       IWL_DEBUG_INFO(priv, "enter\n");
-       if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
-               goto out;
-
-       psta = (struct iwl3945_sta_priv *) sta->drv_priv;
-       rs_sta = &psta->rs_sta;
-       sband = hw->wiphy->bands[conf->channel->band];
-
-       rs_sta->priv = priv;
-
-       rs_sta->start_rate = IWL_RATE_INVALID;
-
-       /* default to just 802.11b */
-       rs_sta->expected_tpt = iwl3945_expected_tpt_b;
-
-       rs_sta->last_partial_flush = jiffies;
-       rs_sta->last_flush = jiffies;
-       rs_sta->flush_time = IWL_RATE_FLUSH;
-       rs_sta->last_tx_packets = 0;
-
-       rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
-       rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush;
-
-       for (i = 0; i < IWL_RATE_COUNT_3945; i++)
-               iwl3945_clear_window(&rs_sta->win[i]);
-
-       /* TODO: what is a good starting rate for STA? About middle? Maybe not
-        * the lowest or the highest rate.. Could consider using RSSI from
-        * previous packets? Need to have IEEE 802.1X auth succeed immediately
-        * after assoc.. */
-
-       for (i = sband->n_bitrates - 1; i >= 0; i--) {
-               if (sta->supp_rates[sband->band] & (1 << i)) {
-                       rs_sta->last_txrate_idx = i;
-                       break;
-               }
-       }
-
-       priv->_3945.sta_supp_rates = sta->supp_rates[sband->band];
-       /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
-       if (sband->band == IEEE80211_BAND_5GHZ) {
-               rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
-               priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates <<
-                                               IWL_FIRST_OFDM_RATE;
-       }
-
-out:
-       priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
-
-       IWL_DEBUG_INFO(priv, "leave\n");
-}
-
-static void *iwl3945_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
-{
-       return hw->priv;
-}
-
-/* rate scale requires free function to be implemented */
-static void iwl3945_rs_free(void *priv)
-{
-       return;
-}
-
-static void *iwl3945_rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)
-{
-       struct iwl3945_rs_sta *rs_sta;
-       struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
-       struct iwl_priv *priv __maybe_unused = iwl_priv;
-
-       IWL_DEBUG_RATE(priv, "enter\n");
-
-       rs_sta = &psta->rs_sta;
-
-       spin_lock_init(&rs_sta->lock);
-       init_timer(&rs_sta->rate_scale_flush);
-
-       IWL_DEBUG_RATE(priv, "leave\n");
-
-       return rs_sta;
-}
-
-static void iwl3945_rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta,
-                       void *priv_sta)
-{
-       struct iwl3945_rs_sta *rs_sta = priv_sta;
-
-       /*
-        * Be careful not to use any members of iwl3945_rs_sta (like trying
-        * to use iwl_priv to print out debugging) since it may not be fully
-        * initialized at this point.
-        */
-       del_timer_sync(&rs_sta->rate_scale_flush);
-}
-
-
-/**
- * iwl3945_rs_tx_status - Update rate control values based on Tx results
- *
- * NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by
- * the hardware for each rate.
- */
-static void iwl3945_rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband,
-                        struct ieee80211_sta *sta, void *priv_sta,
-                        struct sk_buff *skb)
-{
-       s8 retries = 0, current_count;
-       int scale_rate_index, first_index, last_index;
-       unsigned long flags;
-       struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
-       struct iwl3945_rs_sta *rs_sta = priv_sta;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
-       IWL_DEBUG_RATE(priv, "enter\n");
-
-       retries = info->status.rates[0].count;
-       /* Sanity Check for retries */
-       if (retries > IWL_RATE_RETRY_TH)
-               retries = IWL_RATE_RETRY_TH;
-
-       first_index = sband->bitrates[info->status.rates[0].idx].hw_value;
-       if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) {
-               IWL_DEBUG_RATE(priv, "leave: Rate out of bounds: %d\n", first_index);
-               return;
-       }
-
-       if (!priv_sta) {
-               IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n");
-               return;
-       }
-
-       /* Treat uninitialized rate scaling data same as non-existing. */
-       if (!rs_sta->priv) {
-               IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n");
-               return;
-       }
-
-
-       rs_sta->tx_packets++;
-
-       scale_rate_index = first_index;
-       last_index = first_index;
-
-       /*
-        * Update the window for each rate.  We determine which rates
-        * were Tx'd based on the total number of retries vs. the number
-        * of retries configured for each rate -- currently set to the
-        * priv value 'retry_rate' vs. rate specific
-        *
-        * On exit from this while loop last_index indicates the rate
-        * at which the frame was finally transmitted (or failed if no
-        * ACK)
-        */
-       while (retries > 1) {
-               if ((retries - 1) < priv->retry_rate) {
-                       current_count = (retries - 1);
-                       last_index = scale_rate_index;
-               } else {
-                       current_count = priv->retry_rate;
-                       last_index = iwl3945_rs_next_rate(priv,
-                                                        scale_rate_index);
-               }
-
-               /* Update this rate accounting for as many retries
-                * as was used for it (per current_count) */
-               iwl3945_collect_tx_data(rs_sta,
-                                   &rs_sta->win[scale_rate_index],
-                                   0, current_count, scale_rate_index);
-               IWL_DEBUG_RATE(priv, "Update rate %d for %d retries.\n",
-                              scale_rate_index, current_count);
-
-               retries -= current_count;
-
-               scale_rate_index = last_index;
-       }
-
-
-       /* Update the last index window with success/failure based on ACK */
-       IWL_DEBUG_RATE(priv, "Update rate %d with %s.\n",
-                      last_index,
-                      (info->flags & IEEE80211_TX_STAT_ACK) ?
-                      "success" : "failure");
-       iwl3945_collect_tx_data(rs_sta,
-                           &rs_sta->win[last_index],
-                           info->flags & IEEE80211_TX_STAT_ACK, 1, last_index);
-
-       /* We updated the rate scale window -- if its been more than
-        * flush_time since the last run, schedule the flush
-        * again */
-       spin_lock_irqsave(&rs_sta->lock, flags);
-
-       if (!rs_sta->flush_pending &&
-           time_after(jiffies, rs_sta->last_flush +
-                      rs_sta->flush_time)) {
-
-               rs_sta->last_partial_flush = jiffies;
-               rs_sta->flush_pending = 1;
-               mod_timer(&rs_sta->rate_scale_flush,
-                         jiffies + rs_sta->flush_time);
-       }
-
-       spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-       IWL_DEBUG_RATE(priv, "leave\n");
-}
-
-static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
-                                u8 index, u16 rate_mask, enum ieee80211_band band)
-{
-       u8 high = IWL_RATE_INVALID;
-       u8 low = IWL_RATE_INVALID;
-       struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-
-       /* 802.11A walks to the next literal adjacent rate in
-        * the rate table */
-       if (unlikely(band == IEEE80211_BAND_5GHZ)) {
-               int i;
-               u32 mask;
-
-               /* Find the previous rate that is in the rate mask */
-               i = index - 1;
-               for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
-                       if (rate_mask & mask) {
-                               low = i;
-                               break;
-                       }
-               }
-
-               /* Find the next rate that is in the rate mask */
-               i = index + 1;
-               for (mask = (1 << i); i < IWL_RATE_COUNT_3945;
-                    i++, mask <<= 1) {
-                       if (rate_mask & mask) {
-                               high = i;
-                               break;
-                       }
-               }
-
-               return (high << 8) | low;
-       }
-
-       low = index;
-       while (low != IWL_RATE_INVALID) {
-               if (rs_sta->tgg)
-                       low = iwl3945_rates[low].prev_rs_tgg;
-               else
-                       low = iwl3945_rates[low].prev_rs;
-               if (low == IWL_RATE_INVALID)
-                       break;
-               if (rate_mask & (1 << low))
-                       break;
-               IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low);
-       }
-
-       high = index;
-       while (high != IWL_RATE_INVALID) {
-               if (rs_sta->tgg)
-                       high = iwl3945_rates[high].next_rs_tgg;
-               else
-                       high = iwl3945_rates[high].next_rs;
-               if (high == IWL_RATE_INVALID)
-                       break;
-               if (rate_mask & (1 << high))
-                       break;
-               IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high);
-       }
-
-       return (high << 8) | low;
-}
-
-/**
- * iwl3945_rs_get_rate - find the rate for the requested packet
- *
- * Returns the ieee80211_rate structure allocated by the driver.
- *
- * The rate control algorithm has no internal mapping between hw_mode's
- * rate ordering and the rate ordering used by the rate control algorithm.
- *
- * The rate control algorithm uses a single table of rates that goes across
- * the entire A/B/G spectrum vs. being limited to just one particular
- * hw_mode.
- *
- * As such, we can't convert the index obtained below into the hw_mode's
- * rate table and must reference the driver allocated rate table
- *
- */
-static void iwl3945_rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
-                       void *priv_sta, struct ieee80211_tx_rate_control *txrc)
-{
-       struct ieee80211_supported_band *sband = txrc->sband;
-       struct sk_buff *skb = txrc->skb;
-       u8 low = IWL_RATE_INVALID;
-       u8 high = IWL_RATE_INVALID;
-       u16 high_low;
-       int index;
-       struct iwl3945_rs_sta *rs_sta = priv_sta;
-       struct iwl3945_rate_scale_data *window = NULL;
-       int current_tpt = IWL_INVALID_VALUE;
-       int low_tpt = IWL_INVALID_VALUE;
-       int high_tpt = IWL_INVALID_VALUE;
-       u32 fail_count;
-       s8 scale_action = 0;
-       unsigned long flags;
-       u16 rate_mask;
-       s8 max_rate_idx = -1;
-       struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
-       IWL_DEBUG_RATE(priv, "enter\n");
-
-       /* Treat uninitialized rate scaling data same as non-existing. */
-       if (rs_sta && !rs_sta->priv) {
-               IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n");
-               priv_sta = NULL;
-       }
-
-       if (rate_control_send_low(sta, priv_sta, txrc))
-               return;
-
-       rate_mask = sta->supp_rates[sband->band];
-
-       /* get user max rate if set */
-       max_rate_idx = txrc->max_rate_idx;
-       if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1))
-               max_rate_idx += IWL_FIRST_OFDM_RATE;
-       if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT))
-               max_rate_idx = -1;
-
-       index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);
-
-       if (sband->band == IEEE80211_BAND_5GHZ)
-               rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
-
-       spin_lock_irqsave(&rs_sta->lock, flags);
-
-       /* for recent assoc, choose best rate regarding
-        * to rssi value
-        */
-       if (rs_sta->start_rate != IWL_RATE_INVALID) {
-               if (rs_sta->start_rate < index &&
-                  (rate_mask & (1 << rs_sta->start_rate)))
-                       index = rs_sta->start_rate;
-               rs_sta->start_rate = IWL_RATE_INVALID;
-       }
-
-       /* force user max rate if set by user */
-       if ((max_rate_idx != -1) && (max_rate_idx < index)) {
-               if (rate_mask & (1 << max_rate_idx))
-                       index = max_rate_idx;
-       }
-
-       window = &(rs_sta->win[index]);
-
-       fail_count = window->counter - window->success_counter;
-
-       if (((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
-            (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
-               spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-               IWL_DEBUG_RATE(priv, "Invalid average_tpt on rate %d: "
-                              "counter: %d, success_counter: %d, "
-                              "expected_tpt is %sNULL\n",
-                              index,
-                              window->counter,
-                              window->success_counter,
-                              rs_sta->expected_tpt ? "not " : "");
-
-          /* Can't calculate this yet; not enough history */
-               window->average_tpt = IWL_INVALID_VALUE;
-               goto out;
-
-       }
-
-       current_tpt = window->average_tpt;
-
-       high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
-                                            sband->band);
-       low = high_low & 0xff;
-       high = (high_low >> 8) & 0xff;
-
-       /* If user set max rate, dont allow higher than user constrain */
-       if ((max_rate_idx != -1) && (max_rate_idx < high))
-               high = IWL_RATE_INVALID;
-
-       /* Collect Measured throughputs of adjacent rates */
-       if (low != IWL_RATE_INVALID)
-               low_tpt = rs_sta->win[low].average_tpt;
-
-       if (high != IWL_RATE_INVALID)
-               high_tpt = rs_sta->win[high].average_tpt;
-
-       spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-       scale_action = 0;
-
-       /* Low success ratio , need to drop the rate */
-       if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
-               IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n");
-               scale_action = -1;
-       /* No throughput measured yet for adjacent rates,
-        * try increase */
-       } else if ((low_tpt == IWL_INVALID_VALUE) &&
-                  (high_tpt == IWL_INVALID_VALUE)) {
-
-               if (high != IWL_RATE_INVALID && window->success_ratio >= IWL_RATE_INCREASE_TH)
-                       scale_action = 1;
-               else if (low != IWL_RATE_INVALID)
-                       scale_action = 0;
-
-       /* Both adjacent throughputs are measured, but neither one has
-        * better throughput; we're using the best rate, don't change
-        * it! */
-       } else if ((low_tpt != IWL_INVALID_VALUE) &&
-                (high_tpt != IWL_INVALID_VALUE) &&
-                (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
-
-               IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < "
-                              "current_tpt [%d]\n",
-                              low_tpt, high_tpt, current_tpt);
-               scale_action = 0;
-
-       /* At least one of the rates has better throughput */
-       } else {
-               if (high_tpt != IWL_INVALID_VALUE) {
-
-                       /* High rate has better throughput, Increase
-                        * rate */
-                       if (high_tpt > current_tpt &&
-                               window->success_ratio >= IWL_RATE_INCREASE_TH)
-                               scale_action = 1;
-                       else {
-                               IWL_DEBUG_RATE(priv,
-                                   "decrease rate because of high tpt\n");
-                               scale_action = 0;
-                       }
-               } else if (low_tpt != IWL_INVALID_VALUE) {
-                       if (low_tpt > current_tpt) {
-                               IWL_DEBUG_RATE(priv,
-                                   "decrease rate because of low tpt\n");
-                               scale_action = -1;
-                       } else if (window->success_ratio >= IWL_RATE_INCREASE_TH) {
-                               /* Lower rate has better
-                                * throughput,decrease rate */
-                               scale_action = 1;
-                       }
-               }
-       }
-
-       /* Sanity check; asked for decrease, but success rate or throughput
-        * has been good at old rate.  Don't change it. */
-       if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
-                   ((window->success_ratio > IWL_RATE_HIGH_TH) ||
-                    (current_tpt > (100 * rs_sta->expected_tpt[low]))))
-               scale_action = 0;
-
-       switch (scale_action) {
-       case -1:
-
-               /* Decrese rate */
-               if (low != IWL_RATE_INVALID)
-                       index = low;
-               break;
-
-       case 1:
-               /* Increase rate */
-               if (high != IWL_RATE_INVALID)
-                       index = high;
-
-               break;
-
-       case 0:
-       default:
-               /* No change */
-               break;
-       }
-
-       IWL_DEBUG_RATE(priv, "Selected %d (action %d) - low %d high %d\n",
-                      index, scale_action, low, high);
-
- out:
-
-       if (sband->band == IEEE80211_BAND_5GHZ) {
-               if (WARN_ON_ONCE(index < IWL_FIRST_OFDM_RATE))
-                       index = IWL_FIRST_OFDM_RATE;
-               rs_sta->last_txrate_idx = index;
-               info->control.rates[0].idx = index - IWL_FIRST_OFDM_RATE;
-       } else {
-               rs_sta->last_txrate_idx = index;
-               info->control.rates[0].idx = rs_sta->last_txrate_idx;
-       }
-
-       IWL_DEBUG_RATE(priv, "leave: %d\n", index);
-}
-
-#ifdef CONFIG_MAC80211_DEBUGFS
-static int iwl3945_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
-static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file,
-                                                 char __user *user_buf,
-                                                 size_t count, loff_t *ppos)
-{
-       char *buff;
-       int desc = 0;
-       int j;
-       ssize_t ret;
-       struct iwl3945_rs_sta *lq_sta = file->private_data;
-
-       buff = kmalloc(1024, GFP_KERNEL);
-       if (!buff)
-               return -ENOMEM;
-
-       desc += sprintf(buff + desc, "tx packets=%d last rate index=%d\n"
-                       "rate=0x%X flush time %d\n",
-                       lq_sta->tx_packets,
-                       lq_sta->last_txrate_idx,
-                       lq_sta->start_rate, jiffies_to_msecs(lq_sta->flush_time));
-       for (j = 0; j < IWL_RATE_COUNT_3945; j++) {
-               desc += sprintf(buff+desc,
-                               "counter=%d success=%d %%=%d\n",
-                               lq_sta->win[j].counter,
-                               lq_sta->win[j].success_counter,
-                               lq_sta->win[j].success_ratio);
-       }
-       ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
-       kfree(buff);
-       return ret;
-}
-
-static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
-       .read = iwl3945_sta_dbgfs_stats_table_read,
-       .open = iwl3945_open_file_generic,
-       .llseek = default_llseek,
-};
-
-static void iwl3945_add_debugfs(void *priv, void *priv_sta,
-                               struct dentry *dir)
-{
-       struct iwl3945_rs_sta *lq_sta = priv_sta;
-
-       lq_sta->rs_sta_dbgfs_stats_table_file =
-               debugfs_create_file("rate_stats_table", 0600, dir,
-               lq_sta, &rs_sta_dbgfs_stats_table_ops);
-
-}
-
-static void iwl3945_remove_debugfs(void *priv, void *priv_sta)
-{
-       struct iwl3945_rs_sta *lq_sta = priv_sta;
-       debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
-}
-#endif
-
-/*
- * Initialization of rate scaling information is done by driver after
- * the station is added. Since mac80211 calls this function before a
- * station is added we ignore it.
- */
-static void iwl3945_rs_rate_init_stub(void *priv_r,
-                               struct ieee80211_supported_band *sband,
-                             struct ieee80211_sta *sta, void *priv_sta)
-{
-}
-
-static struct rate_control_ops rs_ops = {
-       .module = NULL,
-       .name = RS_NAME,
-       .tx_status = iwl3945_rs_tx_status,
-       .get_rate = iwl3945_rs_get_rate,
-       .rate_init = iwl3945_rs_rate_init_stub,
-       .alloc = iwl3945_rs_alloc,
-       .free = iwl3945_rs_free,
-       .alloc_sta = iwl3945_rs_alloc_sta,
-       .free_sta = iwl3945_rs_free_sta,
-#ifdef CONFIG_MAC80211_DEBUGFS
-       .add_sta_debugfs = iwl3945_add_debugfs,
-       .remove_sta_debugfs = iwl3945_remove_debugfs,
-#endif
-
-};
-void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
-{
-       struct iwl_priv *priv = hw->priv;
-       s32 rssi = 0;
-       unsigned long flags;
-       struct iwl3945_rs_sta *rs_sta;
-       struct ieee80211_sta *sta;
-       struct iwl3945_sta_priv *psta;
-
-       IWL_DEBUG_RATE(priv, "enter\n");
-
-       rcu_read_lock();
-
-       sta = ieee80211_find_sta(priv->contexts[IWL_RXON_CTX_BSS].vif,
-                                priv->stations[sta_id].sta.sta.addr);
-       if (!sta) {
-               IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n");
-               rcu_read_unlock();
-               return;
-       }
-
-       psta = (void *) sta->drv_priv;
-       rs_sta = &psta->rs_sta;
-
-       spin_lock_irqsave(&rs_sta->lock, flags);
-
-       rs_sta->tgg = 0;
-       switch (priv->band) {
-       case IEEE80211_BAND_2GHZ:
-               /* TODO: this always does G, not a regression */
-               if (priv->contexts[IWL_RXON_CTX_BSS].active.flags &
-                                               RXON_FLG_TGG_PROTECT_MSK) {
-                       rs_sta->tgg = 1;
-                       rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
-               } else
-                       rs_sta->expected_tpt = iwl3945_expected_tpt_g;
-               break;
-
-       case IEEE80211_BAND_5GHZ:
-               rs_sta->expected_tpt = iwl3945_expected_tpt_a;
-               break;
-       case IEEE80211_NUM_BANDS:
-               BUG();
-               break;
-       }
-
-       spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-       rssi = priv->_3945.last_rx_rssi;
-       if (rssi == 0)
-               rssi = IWL_MIN_RSSI_VAL;
-
-       IWL_DEBUG_RATE(priv, "Network RSSI: %d\n", rssi);
-
-       rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
-
-       IWL_DEBUG_RATE(priv, "leave: rssi %d assign rate index: "
-                      "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
-                      iwl3945_rates[rs_sta->start_rate].plcp);
-       rcu_read_unlock();
-}
-
-int iwl3945_rate_control_register(void)
-{
-       return ieee80211_rate_control_register(&rs_ops);
-}
-
-void iwl3945_rate_control_unregister(void)
-{
-       ieee80211_rate_control_unregister(&rs_ops);
-}
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
deleted file mode 100644 (file)
index f7c0a74..0000000
+++ /dev/null
@@ -1,2741 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/firmware.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-#include <net/mac80211.h>
-
-#include "iwl-fh.h"
-#include "iwl-3945-fh.h"
-#include "iwl-commands.h"
-#include "iwl-sta.h"
-#include "iwl-3945.h"
-#include "iwl-eeprom.h"
-#include "iwl-core.h"
-#include "iwl-helpers.h"
-#include "iwl-led.h"
-#include "iwl-3945-led.h"
-#include "iwl-3945-debugfs.h"
-
-#define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
-       [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,   \
-                                   IWL_RATE_##r##M_IEEE,   \
-                                   IWL_RATE_##ip##M_INDEX, \
-                                   IWL_RATE_##in##M_INDEX, \
-                                   IWL_RATE_##rp##M_INDEX, \
-                                   IWL_RATE_##rn##M_INDEX, \
-                                   IWL_RATE_##pp##M_INDEX, \
-                                   IWL_RATE_##np##M_INDEX, \
-                                   IWL_RATE_##r##M_INDEX_TABLE, \
-                                   IWL_RATE_##ip##M_INDEX_TABLE }
-
-/*
- * Parameter order:
- *   rate, prev rate, next rate, prev tgg rate, next tgg rate
- *
- * If there isn't a valid next or previous rate then INV is used which
- * maps to IWL_RATE_INVALID
- *
- */
-const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = {
-       IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2),    /*  1mbps */
-       IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5),          /*  2mbps */
-       IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11),        /*5.5mbps */
-       IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18),      /* 11mbps */
-       IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11),        /*  6mbps */
-       IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11),       /*  9mbps */
-       IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18),   /* 12mbps */
-       IWL_DECLARE_RATE_INFO(18, 12, 24, 12, 24, 11, 24),   /* 18mbps */
-       IWL_DECLARE_RATE_INFO(24, 18, 36, 18, 36, 18, 36),   /* 24mbps */
-       IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48),   /* 36mbps */
-       IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54),   /* 48mbps */
-       IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */
-};
-
-static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
-{
-       u8 rate = iwl3945_rates[rate_index].prev_ieee;
-
-       if (rate == IWL_RATE_INVALID)
-               rate = rate_index;
-       return rate;
-}
-
-/* 1 = enable the iwl3945_disable_events() function */
-#define IWL_EVT_DISABLE (0)
-#define IWL_EVT_DISABLE_SIZE (1532/32)
-
-/**
- * iwl3945_disable_events - Disable selected events in uCode event log
- *
- * Disable an event by writing "1"s into "disable"
- *   bitmap in SRAM.  Bit position corresponds to Event # (id/type).
- *   Default values of 0 enable uCode events to be logged.
- * Use for only special debugging.  This function is just a placeholder as-is,
- *   you'll need to provide the special bits! ...
- *   ... and set IWL_EVT_DISABLE to 1. */
-void iwl3945_disable_events(struct iwl_priv *priv)
-{
-       int i;
-       u32 base;               /* SRAM address of event log header */
-       u32 disable_ptr;        /* SRAM address of event-disable bitmap array */
-       u32 array_size;         /* # of u32 entries in array */
-       static const u32 evt_disable[IWL_EVT_DISABLE_SIZE] = {
-               0x00000000,     /*   31 -    0  Event id numbers */
-               0x00000000,     /*   63 -   32 */
-               0x00000000,     /*   95 -   64 */
-               0x00000000,     /*  127 -   96 */
-               0x00000000,     /*  159 -  128 */
-               0x00000000,     /*  191 -  160 */
-               0x00000000,     /*  223 -  192 */
-               0x00000000,     /*  255 -  224 */
-               0x00000000,     /*  287 -  256 */
-               0x00000000,     /*  319 -  288 */
-               0x00000000,     /*  351 -  320 */
-               0x00000000,     /*  383 -  352 */
-               0x00000000,     /*  415 -  384 */
-               0x00000000,     /*  447 -  416 */
-               0x00000000,     /*  479 -  448 */
-               0x00000000,     /*  511 -  480 */
-               0x00000000,     /*  543 -  512 */
-               0x00000000,     /*  575 -  544 */
-               0x00000000,     /*  607 -  576 */
-               0x00000000,     /*  639 -  608 */
-               0x00000000,     /*  671 -  640 */
-               0x00000000,     /*  703 -  672 */
-               0x00000000,     /*  735 -  704 */
-               0x00000000,     /*  767 -  736 */
-               0x00000000,     /*  799 -  768 */
-               0x00000000,     /*  831 -  800 */
-               0x00000000,     /*  863 -  832 */
-               0x00000000,     /*  895 -  864 */
-               0x00000000,     /*  927 -  896 */
-               0x00000000,     /*  959 -  928 */
-               0x00000000,     /*  991 -  960 */
-               0x00000000,     /* 1023 -  992 */
-               0x00000000,     /* 1055 - 1024 */
-               0x00000000,     /* 1087 - 1056 */
-               0x00000000,     /* 1119 - 1088 */
-               0x00000000,     /* 1151 - 1120 */
-               0x00000000,     /* 1183 - 1152 */
-               0x00000000,     /* 1215 - 1184 */
-               0x00000000,     /* 1247 - 1216 */
-               0x00000000,     /* 1279 - 1248 */
-               0x00000000,     /* 1311 - 1280 */
-               0x00000000,     /* 1343 - 1312 */
-               0x00000000,     /* 1375 - 1344 */
-               0x00000000,     /* 1407 - 1376 */
-               0x00000000,     /* 1439 - 1408 */
-               0x00000000,     /* 1471 - 1440 */
-               0x00000000,     /* 1503 - 1472 */
-       };
-
-       base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-       if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-               IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
-               return;
-       }
-
-       disable_ptr = iwl_legacy_read_targ_mem(priv, base + (4 * sizeof(u32)));
-       array_size = iwl_legacy_read_targ_mem(priv, base + (5 * sizeof(u32)));
-
-       if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) {
-               IWL_DEBUG_INFO(priv, "Disabling selected uCode log events at 0x%x\n",
-                              disable_ptr);
-               for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++)
-                       iwl_legacy_write_targ_mem(priv,
-                                          disable_ptr + (i * sizeof(u32)),
-                                          evt_disable[i]);
-
-       } else {
-               IWL_DEBUG_INFO(priv, "Selected uCode log events may be disabled\n");
-               IWL_DEBUG_INFO(priv, "  by writing \"1\"s into disable bitmap\n");
-               IWL_DEBUG_INFO(priv, "  in SRAM at 0x%x, size %d u32s\n",
-                              disable_ptr, array_size);
-       }
-
-}
-
-static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
-{
-       int idx;
-
-       for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++)
-               if (iwl3945_rates[idx].plcp == plcp)
-                       return idx;
-       return -1;
-}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-#define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x
-
-static const char *iwl3945_get_tx_fail_reason(u32 status)
-{
-       switch (status & TX_STATUS_MSK) {
-       case TX_3945_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";
-}
-#else
-static inline const char *iwl3945_get_tx_fail_reason(u32 status)
-{
-       return "";
-}
-#endif
-
-/*
- * get ieee prev rate from rate scale table.
- * for A and B mode we need to overright prev
- * value
- */
-int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
-{
-       int next_rate = iwl3945_get_prev_ieee_rate(rate);
-
-       switch (priv->band) {
-       case IEEE80211_BAND_5GHZ:
-               if (rate == IWL_RATE_12M_INDEX)
-                       next_rate = IWL_RATE_9M_INDEX;
-               else if (rate == IWL_RATE_6M_INDEX)
-                       next_rate = IWL_RATE_6M_INDEX;
-               break;
-       case IEEE80211_BAND_2GHZ:
-               if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
-                   iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
-                       if (rate == IWL_RATE_11M_INDEX)
-                               next_rate = IWL_RATE_5M_INDEX;
-               }
-               break;
-
-       default:
-               break;
-       }
-
-       return next_rate;
-}
-
-
-/**
- * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
- *
- * 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 the stack that feeds us.
- */
-static void iwl3945_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;
-       struct iwl_tx_info *tx_info;
-
-       BUG_ON(txq_id == IWL39_CMD_QUEUE_NUM);
-
-       for (index = iwl_legacy_queue_inc_wrap(index, q->n_bd);
-               q->read_ptr != index;
-               q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-
-               tx_info = &txq->txb[txq->q.read_ptr];
-               ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
-               tx_info->skb = NULL;
-               priv->cfg->ops->lib->txq_free_tfd(priv, txq);
-       }
-
-       if (iwl_legacy_queue_space(q) > q->low_mark && (txq_id >= 0) &&
-                       (txq_id != IWL39_CMD_QUEUE_NUM) &&
-                       priv->mac80211_registered)
-               iwl_legacy_wake_queue(priv, txq);
-}
-
-/**
- * iwl3945_rx_reply_tx - Handle Tx response
- */
-static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       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_info *info;
-       struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-       u32  status = le32_to_cpu(tx_resp->status);
-       int rate_idx;
-       int fail;
-
-       if ((index >= txq->q.n_bd) || (iwl_legacy_queue_used(&txq->q, index) == 0)) {
-               IWL_ERR(priv, "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.write_ptr,
-                         txq->q.read_ptr);
-               return;
-       }
-
-       txq->time_stamp = jiffies;
-       info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
-       ieee80211_tx_info_clear_status(info);
-
-       /* Fill the MRR chain with some info about on-chip retransmissions */
-       rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
-       if (info->band == IEEE80211_BAND_5GHZ)
-               rate_idx -= IWL_FIRST_OFDM_RATE;
-
-       fail = tx_resp->failure_frame;
-
-       info->status.rates[0].idx = rate_idx;
-       info->status.rates[0].count = fail + 1; /* add final attempt */
-
-       /* tx_status->rts_retry_count = tx_resp->failure_rts; */
-       info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
-                               IEEE80211_TX_STAT_ACK : 0;
-
-       IWL_DEBUG_TX(priv, "Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
-                       txq_id, iwl3945_get_tx_fail_reason(status), status,
-                       tx_resp->rate, tx_resp->failure_frame);
-
-       IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index);
-       iwl3945_tx_queue_reclaim(priv, txq_id, index);
-
-       if (status & TX_ABORT_REQUIRED_MSK)
-               IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
-}
-
-
-
-/*****************************************************************************
- *
- * Intel PRO/Wireless 3945ABG/BG Network Connection
- *
- *  RX handler implementations
- *
- *****************************************************************************/
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-static void iwl3945_accumulative_statistics(struct iwl_priv *priv,
-                                           __le32 *stats)
-{
-       int i;
-       __le32 *prev_stats;
-       u32 *accum_stats;
-       u32 *delta, *max_delta;
-
-       prev_stats = (__le32 *)&priv->_3945.statistics;
-       accum_stats = (u32 *)&priv->_3945.accum_statistics;
-       delta = (u32 *)&priv->_3945.delta_statistics;
-       max_delta = (u32 *)&priv->_3945.max_delta;
-
-       for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics);
-            i += sizeof(__le32), stats++, prev_stats++, delta++,
-            max_delta++, accum_stats++) {
-               if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
-                       *delta = (le32_to_cpu(*stats) -
-                               le32_to_cpu(*prev_stats));
-                       *accum_stats += *delta;
-                       if (*delta > *max_delta)
-                               *max_delta = *delta;
-               }
-       }
-
-       /* reset accumulative statistics for "no-counter" type statistics */
-       priv->_3945.accum_statistics.general.temperature =
-               priv->_3945.statistics.general.temperature;
-       priv->_3945.accum_statistics.general.ttl_timestamp =
-               priv->_3945.statistics.general.ttl_timestamp;
-}
-#endif
-
-void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
-               struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-       IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
-                    (int)sizeof(struct iwl3945_notif_statistics),
-                    le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-       iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
-#endif
-
-       memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
-}
-
-void iwl3945_reply_statistics(struct iwl_priv *priv,
-                             struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       __le32 *flag = (__le32 *)&pkt->u.raw;
-
-       if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) {
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-               memset(&priv->_3945.accum_statistics, 0,
-                       sizeof(struct iwl3945_notif_statistics));
-               memset(&priv->_3945.delta_statistics, 0,
-                       sizeof(struct iwl3945_notif_statistics));
-               memset(&priv->_3945.max_delta, 0,
-                       sizeof(struct iwl3945_notif_statistics));
-#endif
-               IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
-       }
-       iwl3945_hw_rx_statistics(priv, rxb);
-}
-
-
-/******************************************************************************
- *
- * Misc. internal state and helper functions
- *
- ******************************************************************************/
-
-/* This is necessary only for a number of statistics, see the caller. */
-static int iwl3945_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 NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source    | BSSID */
-               /* packets to our IBSS update information */
-               return !compare_ether_addr(header->addr3, priv->bssid);
-       case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
-               /* packets to our IBSS update information */
-               return !compare_ether_addr(header->addr2, priv->bssid);
-       default:
-               return 1;
-       }
-}
-
-static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
-                                  struct iwl_rx_mem_buffer *rxb,
-                                  struct ieee80211_rx_status *stats)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
-       struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-       struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-       u16 len = le16_to_cpu(rx_hdr->len);
-       struct sk_buff *skb;
-       __le16 fc = hdr->frame_control;
-
-       /* We received data from the HW, so stop the watchdog */
-       if (unlikely(len + IWL39_RX_FRAME_SIZE >
-                    PAGE_SIZE << priv->hw_params.rx_page_order)) {
-               IWL_DEBUG_DROP(priv, "Corruption detected!\n");
-               return;
-       }
-
-       /* We only process data packets if the interface is open */
-       if (unlikely(!priv->is_open)) {
-               IWL_DEBUG_DROP_LIMIT(priv,
-                       "Dropping packet while interface is not open.\n");
-               return;
-       }
-
-       skb = dev_alloc_skb(128);
-       if (!skb) {
-               IWL_ERR(priv, "dev_alloc_skb failed\n");
-               return;
-       }
-
-       if (!iwl3945_mod_params.sw_crypto)
-               iwl_legacy_set_decrypted_flag(priv,
-                                      (struct ieee80211_hdr *)rxb_addr(rxb),
-                                      le32_to_cpu(rx_end->status), stats);
-
-       skb_add_rx_frag(skb, 0, rxb->page,
-                       (void *)rx_hdr->payload - (void *)pkt, len);
-
-       iwl_legacy_update_stats(priv, false, fc, len);
-       memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-
-       ieee80211_rx(priv->hw, skb);
-       priv->alloc_rxb_page--;
-       rxb->page = NULL;
-}
-
-#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-
-static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
-{
-       struct ieee80211_hdr *header;
-       struct ieee80211_rx_status rx_status;
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
-       struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-       struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-       u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg);
-       u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff);
-       u8 network_packet;
-
-       rx_status.flag = 0;
-       rx_status.mactime = le64_to_cpu(rx_end->timestamp);
-       rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-                               IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-       rx_status.freq =
-               ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel),
-                                              rx_status.band);
-
-       rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
-       if (rx_status.band == IEEE80211_BAND_5GHZ)
-               rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
-
-       rx_status.antenna = (le16_to_cpu(rx_hdr->phy_flags) &
-                                       RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
-
-       /* set the preamble flag if appropriate */
-       if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-               rx_status.flag |= RX_FLAG_SHORTPRE;
-
-       if ((unlikely(rx_stats->phy_count > 20))) {
-               IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
-                               rx_stats->phy_count);
-               return;
-       }
-
-       if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR)
-           || !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
-               IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", rx_end->status);
-               return;
-       }
-
-
-
-       /* Convert 3945's rssi indicator to dBm */
-       rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET;
-
-       IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n",
-                       rx_status.signal, rx_stats_sig_avg,
-                       rx_stats_noise_diff);
-
-       header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
-
-       network_packet = iwl3945_is_network_packet(priv, header);
-
-       IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n",
-                             network_packet ? '*' : ' ',
-                             le16_to_cpu(rx_hdr->channel),
-                             rx_status.signal, rx_status.signal,
-                             rx_status.rate_idx);
-
-       iwl_legacy_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len),
-                                               header);
-
-       if (network_packet) {
-               priv->_3945.last_beacon_time =
-                       le32_to_cpu(rx_end->beacon_timestamp);
-               priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
-               priv->_3945.last_rx_rssi = rx_status.signal;
-       }
-
-       iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
-}
-
-int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-                                    struct iwl_tx_queue *txq,
-                                    dma_addr_t addr, u16 len, u8 reset, u8 pad)
-{
-       int count;
-       struct iwl_queue *q;
-       struct iwl3945_tfd *tfd, *tfd_tmp;
-
-       q = &txq->q;
-       tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
-       tfd = &tfd_tmp[q->write_ptr];
-
-       if (reset)
-               memset(tfd, 0, sizeof(*tfd));
-
-       count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
-
-       if ((count >= NUM_TFD_CHUNKS) || (count < 0)) {
-               IWL_ERR(priv, "Error can not send more than %d chunks\n",
-                         NUM_TFD_CHUNKS);
-               return -EINVAL;
-       }
-
-       tfd->tbs[count].addr = cpu_to_le32(addr);
-       tfd->tbs[count].len = cpu_to_le32(len);
-
-       count++;
-
-       tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(count) |
-                                        TFD_CTL_PAD_SET(pad));
-
-       return 0;
-}
-
-/**
- * iwl3945_hw_txq_free_tfd - Free one TFD, those at index [txq->q.read_ptr]
- *
- * Does NOT advance any indexes
- */
-void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-       struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
-       int index = txq->q.read_ptr;
-       struct iwl3945_tfd *tfd = &tfd_tmp[index];
-       struct pci_dev *dev = priv->pci_dev;
-       int i;
-       int counter;
-
-       /* sanity check */
-       counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
-       if (counter > NUM_TFD_CHUNKS) {
-               IWL_ERR(priv, "Too many chunks: %i\n", counter);
-               /* @todo issue fatal error, it is quite serious situation */
-               return;
-       }
-
-       /* Unmap tx_cmd */
-       if (counter)
-               pci_unmap_single(dev,
-                               dma_unmap_addr(&txq->meta[index], mapping),
-                               dma_unmap_len(&txq->meta[index], len),
-                               PCI_DMA_TODEVICE);
-
-       /* unmap chunks if any */
-
-       for (i = 1; i < counter; i++)
-               pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr),
-                        le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE);
-
-       /* free SKB */
-       if (txq->txb) {
-               struct sk_buff *skb;
-
-               skb = txq->txb[txq->q.read_ptr].skb;
-
-               /* can be called from irqs-disabled context */
-               if (skb) {
-                       dev_kfree_skb_any(skb);
-                       txq->txb[txq->q.read_ptr].skb = NULL;
-               }
-       }
-}
-
-/**
- * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
- *
-*/
-void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
-                                 struct iwl_device_cmd *cmd,
-                                 struct ieee80211_tx_info *info,
-                                 struct ieee80211_hdr *hdr,
-                                 int sta_id, int tx_id)
-{
-       u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
-       u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945);
-       u16 rate_mask;
-       int rate;
-       u8 rts_retry_limit;
-       u8 data_retry_limit;
-       __le32 tx_flags;
-       __le16 fc = hdr->frame_control;
-       struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-
-       rate = iwl3945_rates[rate_index].plcp;
-       tx_flags = tx_cmd->tx_flags;
-
-       /* We need to figure out how to get the sta->supp_rates while
-        * in this running context */
-       rate_mask = IWL_RATES_MASK_3945;
-
-       /* Set retry limit on DATA packets and Probe Responses*/
-       if (ieee80211_is_probe_resp(fc))
-               data_retry_limit = 3;
-       else
-               data_retry_limit = IWL_DEFAULT_TX_RETRY;
-       tx_cmd->data_retry_limit = data_retry_limit;
-
-       if (tx_id >= IWL39_CMD_QUEUE_NUM)
-               rts_retry_limit = 3;
-       else
-               rts_retry_limit = 7;
-
-       if (data_retry_limit < rts_retry_limit)
-               rts_retry_limit = data_retry_limit;
-       tx_cmd->rts_retry_limit = rts_retry_limit;
-
-       tx_cmd->rate = rate;
-       tx_cmd->tx_flags = tx_flags;
-
-       /* OFDM */
-       tx_cmd->supp_rates[0] =
-          ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF;
-
-       /* CCK */
-       tx_cmd->supp_rates[1] = (rate_mask & 0xF);
-
-       IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
-                      "cck/ofdm mask: 0x%x/0x%x\n", sta_id,
-                      tx_cmd->rate, le32_to_cpu(tx_cmd->tx_flags),
-                      tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]);
-}
-
-static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate)
-{
-       unsigned long flags_spin;
-       struct iwl_station_entry *station;
-
-       if (sta_id == IWL_INVALID_STATION)
-               return IWL_INVALID_STATION;
-
-       spin_lock_irqsave(&priv->sta_lock, flags_spin);
-       station = &priv->stations[sta_id];
-
-       station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
-       station->sta.rate_n_flags = cpu_to_le16(tx_rate);
-       station->sta.mode = STA_CONTROL_MODIFY_MSK;
-       iwl_legacy_send_add_sta(priv, &station->sta, CMD_ASYNC);
-       spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-
-       IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n",
-                       sta_id, tx_rate);
-       return sta_id;
-}
-
-static void iwl3945_set_pwr_vmain(struct iwl_priv *priv)
-{
-/*
- * (for documentation purposes)
- * to set power to V_AUX, do
-
-               if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) {
-                       iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-                                       APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
-                                       ~APMG_PS_CTRL_MSK_PWR_SRC);
-
-                       iwl_poll_bit(priv, CSR_GPIO_IN,
-                                    CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
-                                    CSR_GPIO_IN_BIT_AUX_POWER, 5000);
-               }
- */
-
-       iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-                       APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
-                       ~APMG_PS_CTRL_MSK_PWR_SRC);
-
-       iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
-                    CSR_GPIO_IN_BIT_AUX_POWER, 5000);  /* uS */
-}
-
-static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-       iwl_legacy_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->bd_dma);
-       iwl_legacy_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0),
-                                       rxq->rb_stts_dma);
-       iwl_legacy_write_direct32(priv, FH39_RCSR_WPTR(0), 0);
-       iwl_legacy_write_direct32(priv, FH39_RCSR_CONFIG(0),
-               FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
-               FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
-               FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
-               FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 |
-               (RX_QUEUE_SIZE_LOG << FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) |
-               FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST |
-               (1 << FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) |
-               FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
-
-       /* fake read to flush all prev I/O */
-       iwl_legacy_read_direct32(priv, FH39_RSSR_CTRL);
-
-       return 0;
-}
-
-static int iwl3945_tx_reset(struct iwl_priv *priv)
-{
-
-       /* bypass mode */
-       iwl_legacy_write_prph(priv, ALM_SCD_MODE_REG, 0x2);
-
-       /* RA 0 is active */
-       iwl_legacy_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01);
-
-       /* all 6 fifo are active */
-       iwl_legacy_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f);
-
-       iwl_legacy_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000);
-       iwl_legacy_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002);
-       iwl_legacy_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004);
-       iwl_legacy_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005);
-
-       iwl_legacy_write_direct32(priv, FH39_TSSR_CBB_BASE,
-                            priv->_3945.shared_phys);
-
-       iwl_legacy_write_direct32(priv, FH39_TSSR_MSG_CONFIG,
-               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
-               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
-               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
-               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON |
-               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON |
-               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
-               FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
-
-
-       return 0;
-}
-
-/**
- * iwl3945_txq_ctx_reset - Reset TX queue context
- *
- * Destroys all DMA structures and initialize them again
- */
-static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
-{
-       int rc;
-       int txq_id, slots_num;
-
-       iwl3945_hw_txq_ctx_free(priv);
-
-       /* allocate tx queue structure */
-       rc = iwl_legacy_alloc_txq_mem(priv);
-       if (rc)
-               return rc;
-
-       /* Tx CMD queue */
-       rc = iwl3945_tx_reset(priv);
-       if (rc)
-               goto error;
-
-       /* Tx queue(s) */
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-               slots_num = (txq_id == IWL39_CMD_QUEUE_NUM) ?
-                               TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-               rc = iwl_legacy_tx_queue_init(priv, &priv->txq[txq_id],
-                                               slots_num, txq_id);
-               if (rc) {
-                       IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
-                       goto error;
-               }
-       }
-
-       return rc;
-
- error:
-       iwl3945_hw_txq_ctx_free(priv);
-       return rc;
-}
-
-
-/*
- * Start up 3945's basic functionality after it has been reset
- * (e.g. after platform boot, or shutdown via iwl_legacy_apm_stop())
- * NOTE:  This does not load uCode nor start the embedded processor
- */
-static int iwl3945_apm_init(struct iwl_priv *priv)
-{
-       int ret = iwl_legacy_apm_init(priv);
-
-       /* Clear APMG (NIC's internal power management) interrupts */
-       iwl_legacy_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
-       iwl_legacy_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF);
-
-       /* Reset radio chip */
-       iwl_legacy_set_bits_prph(priv, APMG_PS_CTRL_REG,
-                               APMG_PS_CTRL_VAL_RESET_REQ);
-       udelay(5);
-       iwl_legacy_clear_bits_prph(priv, APMG_PS_CTRL_REG,
-                               APMG_PS_CTRL_VAL_RESET_REQ);
-
-       return ret;
-}
-
-static void iwl3945_nic_config(struct iwl_priv *priv)
-{
-       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-       unsigned long flags;
-       u8 rev_id = priv->pci_dev->revision;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       /* Determine HW type */
-       IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
-
-       if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
-               IWL_DEBUG_INFO(priv, "RTP type\n");
-       else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
-               IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n");
-               iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                           CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
-       } else {
-               IWL_DEBUG_INFO(priv, "3945 RADIO-MM type\n");
-               iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                           CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
-       }
-
-       if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) {
-               IWL_DEBUG_INFO(priv, "SKU OP mode is mrc\n");
-               iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                           CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
-       } else
-               IWL_DEBUG_INFO(priv, "SKU OP mode is basic\n");
-
-       if ((eeprom->board_revision & 0xF0) == 0xD0) {
-               IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n",
-                              eeprom->board_revision);
-               iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                           CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
-       } else {
-               IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n",
-                              eeprom->board_revision);
-               iwl_legacy_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-                             CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
-       }
-
-       if (eeprom->almgor_m_version <= 1) {
-               iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                           CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
-               IWL_DEBUG_INFO(priv, "Card M type A version is 0x%X\n",
-                              eeprom->almgor_m_version);
-       } else {
-               IWL_DEBUG_INFO(priv, "Card M type B version is 0x%X\n",
-                              eeprom->almgor_m_version);
-               iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                           CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE)
-               IWL_DEBUG_RF_KILL(priv, "SW RF KILL supported in EEPROM.\n");
-
-       if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE)
-               IWL_DEBUG_RF_KILL(priv, "HW RF KILL supported in EEPROM.\n");
-}
-
-int iwl3945_hw_nic_init(struct iwl_priv *priv)
-{
-       int rc;
-       unsigned long flags;
-       struct iwl_rx_queue *rxq = &priv->rxq;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->cfg->ops->lib->apm_ops.init(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       iwl3945_set_pwr_vmain(priv);
-
-       priv->cfg->ops->lib->apm_ops.config(priv);
-
-       /* Allocate the RX queue, or reset if it is already allocated */
-       if (!rxq->bd) {
-               rc = iwl_legacy_rx_queue_alloc(priv);
-               if (rc) {
-                       IWL_ERR(priv, "Unable to initialize Rx queue\n");
-                       return -ENOMEM;
-               }
-       } else
-               iwl3945_rx_queue_reset(priv, rxq);
-
-       iwl3945_rx_replenish(priv);
-
-       iwl3945_rx_init(priv, rxq);
-
-
-       /* Look at using this instead:
-       rxq->need_update = 1;
-       iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
-       */
-
-       iwl_legacy_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7);
-
-       rc = iwl3945_txq_ctx_reset(priv);
-       if (rc)
-               return rc;
-
-       set_bit(STATUS_INIT, &priv->status);
-
-       return 0;
-}
-
-/**
- * iwl3945_hw_txq_ctx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
-{
-       int txq_id;
-
-       /* Tx queues */
-       if (priv->txq)
-               for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
-                    txq_id++)
-                       if (txq_id == IWL39_CMD_QUEUE_NUM)
-                               iwl_legacy_cmd_queue_free(priv);
-                       else
-                               iwl_legacy_tx_queue_free(priv, txq_id);
-
-       /* free tx queue structure */
-       iwl_legacy_txq_mem(priv);
-}
-
-void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
-{
-       int txq_id;
-
-       /* stop SCD */
-       iwl_legacy_write_prph(priv, ALM_SCD_MODE_REG, 0);
-       iwl_legacy_write_prph(priv, ALM_SCD_TXFACT_REG, 0);
-
-       /* reset TFD queues */
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-               iwl_legacy_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0);
-               iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS,
-                               FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
-                               1000);
-       }
-
-       iwl3945_hw_txq_ctx_free(priv);
-}
-
-/**
- * iwl3945_hw_reg_adjust_power_by_temp
- * return index delta into power gain settings table
-*/
-static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
-{
-       return (new_reading - old_reading) * (-11) / 100;
-}
-
-/**
- * iwl3945_hw_reg_temp_out_of_range - Keep temperature in sane range
- */
-static inline int iwl3945_hw_reg_temp_out_of_range(int temperature)
-{
-       return ((temperature < -260) || (temperature > 25)) ? 1 : 0;
-}
-
-int iwl3945_hw_get_temperature(struct iwl_priv *priv)
-{
-       return iwl_read32(priv, CSR_UCODE_DRV_GP2);
-}
-
-/**
- * iwl3945_hw_reg_txpower_get_temperature
- * get the current temperature by reading from NIC
-*/
-static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv)
-{
-       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-       int temperature;
-
-       temperature = iwl3945_hw_get_temperature(priv);
-
-       /* driver's okay range is -260 to +25.
-        *   human readable okay range is 0 to +285 */
-       IWL_DEBUG_INFO(priv, "Temperature: %d\n", temperature + IWL_TEMP_CONVERT);
-
-       /* handle insane temp reading */
-       if (iwl3945_hw_reg_temp_out_of_range(temperature)) {
-               IWL_ERR(priv, "Error bad temperature value  %d\n", temperature);
-
-               /* if really really hot(?),
-                *   substitute the 3rd band/group's temp measured at factory */
-               if (priv->last_temperature > 100)
-                       temperature = eeprom->groups[2].temperature;
-               else /* else use most recent "sane" value from driver */
-                       temperature = priv->last_temperature;
-       }
-
-       return temperature;     /* raw, not "human readable" */
-}
-
-/* Adjust Txpower only if temperature variance is greater than threshold.
- *
- * Both are lower than older versions' 9 degrees */
-#define IWL_TEMPERATURE_LIMIT_TIMER   6
-
-/**
- * iwl3945_is_temp_calib_needed - determines if new calibration is needed
- *
- * records new temperature in tx_mgr->temperature.
- * replaces tx_mgr->last_temperature *only* if calib needed
- *    (assumes caller will actually do the calibration!). */
-static int iwl3945_is_temp_calib_needed(struct iwl_priv *priv)
-{
-       int temp_diff;
-
-       priv->temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
-       temp_diff = priv->temperature - priv->last_temperature;
-
-       /* get absolute value */
-       if (temp_diff < 0) {
-               IWL_DEBUG_POWER(priv, "Getting cooler, delta %d,\n", temp_diff);
-               temp_diff = -temp_diff;
-       } else if (temp_diff == 0)
-               IWL_DEBUG_POWER(priv, "Same temp,\n");
-       else
-               IWL_DEBUG_POWER(priv, "Getting warmer, delta %d,\n", temp_diff);
-
-       /* if we don't need calibration, *don't* update last_temperature */
-       if (temp_diff < IWL_TEMPERATURE_LIMIT_TIMER) {
-               IWL_DEBUG_POWER(priv, "Timed thermal calib not needed\n");
-               return 0;
-       }
-
-       IWL_DEBUG_POWER(priv, "Timed thermal calib needed\n");
-
-       /* assume that caller will actually do calib ...
-        *   update the "last temperature" value */
-       priv->last_temperature = priv->temperature;
-       return 1;
-}
-
-#define IWL_MAX_GAIN_ENTRIES 78
-#define IWL_CCK_FROM_OFDM_POWER_DIFF  -5
-#define IWL_CCK_FROM_OFDM_INDEX_DIFF (10)
-
-/* radio and DSP power table, each step is 1/2 dB.
- * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */
-static struct iwl3945_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = {
-       {
-        {251, 127},            /* 2.4 GHz, highest power */
-        {251, 127},
-        {251, 127},
-        {251, 127},
-        {251, 125},
-        {251, 110},
-        {251, 105},
-        {251, 98},
-        {187, 125},
-        {187, 115},
-        {187, 108},
-        {187, 99},
-        {243, 119},
-        {243, 111},
-        {243, 105},
-        {243, 97},
-        {243, 92},
-        {211, 106},
-        {211, 100},
-        {179, 120},
-        {179, 113},
-        {179, 107},
-        {147, 125},
-        {147, 119},
-        {147, 112},
-        {147, 106},
-        {147, 101},
-        {147, 97},
-        {147, 91},
-        {115, 107},
-        {235, 121},
-        {235, 115},
-        {235, 109},
-        {203, 127},
-        {203, 121},
-        {203, 115},
-        {203, 108},
-        {203, 102},
-        {203, 96},
-        {203, 92},
-        {171, 110},
-        {171, 104},
-        {171, 98},
-        {139, 116},
-        {227, 125},
-        {227, 119},
-        {227, 113},
-        {227, 107},
-        {227, 101},
-        {227, 96},
-        {195, 113},
-        {195, 106},
-        {195, 102},
-        {195, 95},
-        {163, 113},
-        {163, 106},
-        {163, 102},
-        {163, 95},
-        {131, 113},
-        {131, 106},
-        {131, 102},
-        {131, 95},
-        {99, 113},
-        {99, 106},
-        {99, 102},
-        {99, 95},
-        {67, 113},
-        {67, 106},
-        {67, 102},
-        {67, 95},
-        {35, 113},
-        {35, 106},
-        {35, 102},
-        {35, 95},
-        {3, 113},
-        {3, 106},
-        {3, 102},
-        {3, 95} },             /* 2.4 GHz, lowest power */
-       {
-        {251, 127},            /* 5.x GHz, highest power */
-        {251, 120},
-        {251, 114},
-        {219, 119},
-        {219, 101},
-        {187, 113},
-        {187, 102},
-        {155, 114},
-        {155, 103},
-        {123, 117},
-        {123, 107},
-        {123, 99},
-        {123, 92},
-        {91, 108},
-        {59, 125},
-        {59, 118},
-        {59, 109},
-        {59, 102},
-        {59, 96},
-        {59, 90},
-        {27, 104},
-        {27, 98},
-        {27, 92},
-        {115, 118},
-        {115, 111},
-        {115, 104},
-        {83, 126},
-        {83, 121},
-        {83, 113},
-        {83, 105},
-        {83, 99},
-        {51, 118},
-        {51, 111},
-        {51, 104},
-        {51, 98},
-        {19, 116},
-        {19, 109},
-        {19, 102},
-        {19, 98},
-        {19, 93},
-        {171, 113},
-        {171, 107},
-        {171, 99},
-        {139, 120},
-        {139, 113},
-        {139, 107},
-        {139, 99},
-        {107, 120},
-        {107, 113},
-        {107, 107},
-        {107, 99},
-        {75, 120},
-        {75, 113},
-        {75, 107},
-        {75, 99},
-        {43, 120},
-        {43, 113},
-        {43, 107},
-        {43, 99},
-        {11, 120},
-        {11, 113},
-        {11, 107},
-        {11, 99},
-        {131, 107},
-        {131, 99},
-        {99, 120},
-        {99, 113},
-        {99, 107},
-        {99, 99},
-        {67, 120},
-        {67, 113},
-        {67, 107},
-        {67, 99},
-        {35, 120},
-        {35, 113},
-        {35, 107},
-        {35, 99},
-        {3, 120} }             /* 5.x GHz, lowest power */
-};
-
-static inline u8 iwl3945_hw_reg_fix_power_index(int index)
-{
-       if (index < 0)
-               return 0;
-       if (index >= IWL_MAX_GAIN_ENTRIES)
-               return IWL_MAX_GAIN_ENTRIES - 1;
-       return (u8) index;
-}
-
-/* Kick off thermal recalibration check every 60 seconds */
-#define REG_RECALIB_PERIOD (60)
-
-/**
- * iwl3945_hw_reg_set_scan_power - Set Tx power for scan probe requests
- *
- * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK)
- * or 6 Mbit (OFDM) rates.
- */
-static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
-                              s32 rate_index, const s8 *clip_pwrs,
-                              struct iwl_channel_info *ch_info,
-                              int band_index)
-{
-       struct iwl3945_scan_power_info *scan_power_info;
-       s8 power;
-       u8 power_index;
-
-       scan_power_info = &ch_info->scan_pwr_info[scan_tbl_index];
-
-       /* use this channel group's 6Mbit clipping/saturation pwr,
-        *   but cap at regulatory scan power restriction (set during init
-        *   based on eeprom channel data) for this channel.  */
-       power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]);
-
-       power = min(power, priv->tx_power_user_lmt);
-       scan_power_info->requested_power = power;
-
-       /* find difference between new scan *power* and current "normal"
-        *   Tx *power* for 6Mb.  Use this difference (x2) to adjust the
-        *   current "normal" temperature-compensated Tx power *index* for
-        *   this rate (1Mb or 6Mb) to yield new temp-compensated scan power
-        *   *index*. */
-       power_index = ch_info->power_info[rate_index].power_table_index
-           - (power - ch_info->power_info
-              [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2;
-
-       /* store reference index that we use when adjusting *all* scan
-        *   powers.  So we can accommodate user (all channel) or spectrum
-        *   management (single channel) power changes "between" temperature
-        *   feedback compensation procedures.
-        * don't force fit this reference index into gain table; it may be a
-        *   negative number.  This will help avoid errors when we're at
-        *   the lower bounds (highest gains, for warmest temperatures)
-        *   of the table. */
-
-       /* don't exceed table bounds for "real" setting */
-       power_index = iwl3945_hw_reg_fix_power_index(power_index);
-
-       scan_power_info->power_table_index = power_index;
-       scan_power_info->tpc.tx_gain =
-           power_gain_table[band_index][power_index].tx_gain;
-       scan_power_info->tpc.dsp_atten =
-           power_gain_table[band_index][power_index].dsp_atten;
-}
-
-/**
- * iwl3945_send_tx_power - fill in Tx Power command with gain settings
- *
- * Configures power settings for all rates for the current channel,
- * using values from channel info struct, and send to NIC
- */
-static int iwl3945_send_tx_power(struct iwl_priv *priv)
-{
-       int rate_idx, i;
-       const struct iwl_channel_info *ch_info = NULL;
-       struct iwl3945_txpowertable_cmd txpower = {
-               .channel = priv->contexts[IWL_RXON_CTX_BSS].active.channel,
-       };
-       u16 chan;
-
-       if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
-                     "TX Power requested while scanning!\n"))
-               return -EAGAIN;
-
-       chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
-
-       txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
-       ch_info = iwl_legacy_get_channel_info(priv, priv->band, chan);
-       if (!ch_info) {
-               IWL_ERR(priv,
-                       "Failed to get channel info for channel %d [%d]\n",
-                       chan, priv->band);
-               return -EINVAL;
-       }
-
-       if (!iwl_legacy_is_channel_valid(ch_info)) {
-               IWL_DEBUG_POWER(priv, "Not calling TX_PWR_TABLE_CMD on "
-                               "non-Tx channel.\n");
-               return 0;
-       }
-
-       /* fill cmd with power settings for all rates for current channel */
-       /* Fill OFDM rate */
-       for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0;
-            rate_idx <= IWL39_LAST_OFDM_RATE; rate_idx++, i++) {
-
-               txpower.power[i].tpc = ch_info->power_info[i].tpc;
-               txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
-
-               IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
-                               le16_to_cpu(txpower.channel),
-                               txpower.band,
-                               txpower.power[i].tpc.tx_gain,
-                               txpower.power[i].tpc.dsp_atten,
-                               txpower.power[i].rate);
-       }
-       /* Fill CCK rates */
-       for (rate_idx = IWL_FIRST_CCK_RATE;
-            rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) {
-               txpower.power[i].tpc = ch_info->power_info[i].tpc;
-               txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
-
-               IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
-                               le16_to_cpu(txpower.channel),
-                               txpower.band,
-                               txpower.power[i].tpc.tx_gain,
-                               txpower.power[i].tpc.dsp_atten,
-                               txpower.power[i].rate);
-       }
-
-       return iwl_legacy_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
-                               sizeof(struct iwl3945_txpowertable_cmd),
-                               &txpower);
-
-}
-
-/**
- * iwl3945_hw_reg_set_new_power - Configures power tables at new levels
- * @ch_info: Channel to update.  Uses power_info.requested_power.
- *
- * Replace requested_power and base_power_index ch_info fields for
- * one channel.
- *
- * Called if user or spectrum management changes power preferences.
- * Takes into account h/w and modulation limitations (clip power).
- *
- * This does *not* send anything to NIC, just sets up ch_info for one channel.
- *
- * NOTE: reg_compensate_for_temperature_dif() *must* be run after this to
- *      properly fill out the scan powers, and actual h/w gain settings,
- *      and send changes to NIC
- */
-static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv,
-                            struct iwl_channel_info *ch_info)
-{
-       struct iwl3945_channel_power_info *power_info;
-       int power_changed = 0;
-       int i;
-       const s8 *clip_pwrs;
-       int power;
-
-       /* Get this chnlgrp's rate-to-max/clip-powers table */
-       clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
-
-       /* Get this channel's rate-to-current-power settings table */
-       power_info = ch_info->power_info;
-
-       /* update OFDM Txpower settings */
-       for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE;
-            i++, ++power_info) {
-               int delta_idx;
-
-               /* limit new power to be no more than h/w capability */
-               power = min(ch_info->curr_txpow, clip_pwrs[i]);
-               if (power == power_info->requested_power)
-                       continue;
-
-               /* find difference between old and new requested powers,
-                *    update base (non-temp-compensated) power index */
-               delta_idx = (power - power_info->requested_power) * 2;
-               power_info->base_power_index -= delta_idx;
-
-               /* save new requested power value */
-               power_info->requested_power = power;
-
-               power_changed = 1;
-       }
-
-       /* update CCK Txpower settings, based on OFDM 12M setting ...
-        *    ... all CCK power settings for a given channel are the *same*. */
-       if (power_changed) {
-               power =
-                   ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
-                   requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF;
-
-               /* do all CCK rates' iwl3945_channel_power_info structures */
-               for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) {
-                       power_info->requested_power = power;
-                       power_info->base_power_index =
-                           ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
-                           base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF;
-                       ++power_info;
-               }
-       }
-
-       return 0;
-}
-
-/**
- * iwl3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel
- *
- * NOTE: Returned power limit may be less (but not more) than requested,
- *      based strictly on regulatory (eeprom and spectrum mgt) limitations
- *      (no consideration for h/w clipping limitations).
- */
-static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
-{
-       s8 max_power;
-
-#if 0
-       /* if we're using TGd limits, use lower of TGd or EEPROM */
-       if (ch_info->tgd_data.max_power != 0)
-               max_power = min(ch_info->tgd_data.max_power,
-                               ch_info->eeprom.max_power_avg);
-
-       /* else just use EEPROM limits */
-       else
-#endif
-               max_power = ch_info->eeprom.max_power_avg;
-
-       return min(max_power, ch_info->max_power_avg);
-}
-
-/**
- * iwl3945_hw_reg_comp_txpower_temp - Compensate for temperature
- *
- * Compensate txpower settings of *all* channels for temperature.
- * This only accounts for the difference between current temperature
- *   and the factory calibration temperatures, and bases the new settings
- *   on the channel's base_power_index.
- *
- * If RxOn is "associated", this sends the new Txpower to NIC!
- */
-static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
-{
-       struct iwl_channel_info *ch_info = NULL;
-       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-       int delta_index;
-       const s8 *clip_pwrs; /* array of h/w max power levels for each rate */
-       u8 a_band;
-       u8 rate_index;
-       u8 scan_tbl_index;
-       u8 i;
-       int ref_temp;
-       int temperature = priv->temperature;
-
-       if (priv->disable_tx_power_cal ||
-           test_bit(STATUS_SCANNING, &priv->status)) {
-               /* do not perform tx power calibration */
-               return 0;
-       }
-       /* set up new Tx power info for each and every channel, 2.4 and 5.x */
-       for (i = 0; i < priv->channel_count; i++) {
-               ch_info = &priv->channel_info[i];
-               a_band = iwl_legacy_is_channel_a_band(ch_info);
-
-               /* Get this chnlgrp's factory calibration temperature */
-               ref_temp = (s16)eeprom->groups[ch_info->group_index].
-                   temperature;
-
-               /* get power index adjustment based on current and factory
-                * temps */
-               delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
-                                                             ref_temp);
-
-               /* set tx power value for all rates, OFDM and CCK */
-               for (rate_index = 0; rate_index < IWL_RATE_COUNT_3945;
-                    rate_index++) {
-                       int power_idx =
-                           ch_info->power_info[rate_index].base_power_index;
-
-                       /* temperature compensate */
-                       power_idx += delta_index;
-
-                       /* stay within table range */
-                       power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
-                       ch_info->power_info[rate_index].
-                           power_table_index = (u8) power_idx;
-                       ch_info->power_info[rate_index].tpc =
-                           power_gain_table[a_band][power_idx];
-               }
-
-               /* Get this chnlgrp's rate-to-max/clip-powers table */
-               clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
-
-               /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
-               for (scan_tbl_index = 0;
-                    scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
-                       s32 actual_index = (scan_tbl_index == 0) ?
-                           IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
-                       iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
-                                          actual_index, clip_pwrs,
-                                          ch_info, a_band);
-               }
-       }
-
-       /* send Txpower command for current channel to ucode */
-       return priv->cfg->ops->lib->send_tx_power(priv);
-}
-
-int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
-{
-       struct iwl_channel_info *ch_info;
-       s8 max_power;
-       u8 a_band;
-       u8 i;
-
-       if (priv->tx_power_user_lmt == power) {
-               IWL_DEBUG_POWER(priv, "Requested Tx power same as current "
-                               "limit: %ddBm.\n", power);
-               return 0;
-       }
-
-       IWL_DEBUG_POWER(priv, "Setting upper limit clamp to %ddBm.\n", power);
-       priv->tx_power_user_lmt = power;
-
-       /* set up new Tx powers for each and every channel, 2.4 and 5.x */
-
-       for (i = 0; i < priv->channel_count; i++) {
-               ch_info = &priv->channel_info[i];
-               a_band = iwl_legacy_is_channel_a_band(ch_info);
-
-               /* find minimum power of all user and regulatory constraints
-                *    (does not consider h/w clipping limitations) */
-               max_power = iwl3945_hw_reg_get_ch_txpower_limit(ch_info);
-               max_power = min(power, max_power);
-               if (max_power != ch_info->curr_txpow) {
-                       ch_info->curr_txpow = max_power;
-
-                       /* this considers the h/w clipping limitations */
-                       iwl3945_hw_reg_set_new_power(priv, ch_info);
-               }
-       }
-
-       /* update txpower settings for all channels,
-        *   send to NIC if associated. */
-       iwl3945_is_temp_calib_needed(priv);
-       iwl3945_hw_reg_comp_txpower_temp(priv);
-
-       return 0;
-}
-
-static int iwl3945_send_rxon_assoc(struct iwl_priv *priv,
-                                  struct iwl_rxon_context *ctx)
-{
-       int rc = 0;
-       struct iwl_rx_packet *pkt;
-       struct iwl3945_rxon_assoc_cmd rxon_assoc;
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_RXON_ASSOC,
-               .len = sizeof(rxon_assoc),
-               .flags = CMD_WANT_SKB,
-               .data = &rxon_assoc,
-       };
-       const struct iwl_legacy_rxon_cmd *rxon1 = &ctx->staging;
-       const struct iwl_legacy_rxon_cmd *rxon2 = &ctx->active;
-
-       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(priv, "Using current RXON_ASSOC.  Not resending.\n");
-               return 0;
-       }
-
-       rxon_assoc.flags = ctx->staging.flags;
-       rxon_assoc.filter_flags = ctx->staging.filter_flags;
-       rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
-       rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
-       rxon_assoc.reserved = 0;
-
-       rc = iwl_legacy_send_cmd_sync(priv, &cmd);
-       if (rc)
-               return rc;
-
-       pkt = (struct iwl_rx_packet *)cmd.reply_page;
-       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
-               rc = -EIO;
-       }
-
-       iwl_legacy_free_pages(priv, cmd.reply_page);
-
-       return rc;
-}
-
-/**
- * iwl3945_commit_rxon - commit staging_rxon to hardware
- *
- * The RXON command in staging_rxon is committed 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.
- */
-int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-       /* cast away the const for active_rxon in this function */
-       struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active;
-       struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
-       int rc = 0;
-       bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return -EINVAL;
-
-       if (!iwl_legacy_is_alive(priv))
-               return -1;
-
-       /* always get timestamp with Rx frame */
-       staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
-
-       /* select antenna */
-       staging_rxon->flags &=
-           ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
-       staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
-
-       rc = iwl_legacy_check_rxon_cmd(priv, ctx);
-       if (rc) {
-               IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
-               return -EINVAL;
-       }
-
-       /* If we don't need to send a full RXON, we can use
-        * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
-        * and other flags for the current radio configuration. */
-       if (!iwl_legacy_full_rxon_required(priv,
-                       &priv->contexts[IWL_RXON_CTX_BSS])) {
-               rc = iwl_legacy_send_rxon_assoc(priv,
-                                        &priv->contexts[IWL_RXON_CTX_BSS]);
-               if (rc) {
-                       IWL_ERR(priv, "Error setting RXON_ASSOC "
-                                 "configuration (%d).\n", rc);
-                       return rc;
-               }
-
-               memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
-               /*
-                * We do not commit tx power settings while channel changing,
-                * do it now if tx power changed.
-                */
-               iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
-               return 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_legacy_is_associated(priv, IWL_RXON_CTX_BSS) && new_assoc) {
-               IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
-               active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-               /*
-                * reserved4 and 5 could have been filled by the iwlcore code.
-                * Let's clear them before pushing to the 3945.
-                */
-               active_rxon->reserved4 = 0;
-               active_rxon->reserved5 = 0;
-               rc = iwl_legacy_send_cmd_pdu(priv, REPLY_RXON,
-                                     sizeof(struct iwl3945_rxon_cmd),
-                                     &priv->contexts[IWL_RXON_CTX_BSS].active);
-
-               /* 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_ERR(priv, "Error clearing ASSOC_MSK on current "
-                                 "configuration (%d).\n", rc);
-                       return rc;
-               }
-               iwl_legacy_clear_ucode_stations(priv,
-                                        &priv->contexts[IWL_RXON_CTX_BSS]);
-               iwl_legacy_restore_stations(priv,
-                                        &priv->contexts[IWL_RXON_CTX_BSS]);
-       }
-
-       IWL_DEBUG_INFO(priv, "Sending RXON\n"
-                      "* with%s RXON_FILTER_ASSOC_MSK\n"
-                      "* channel = %d\n"
-                      "* bssid = %pM\n",
-                      (new_assoc ? "" : "out"),
-                      le16_to_cpu(staging_rxon->channel),
-                      staging_rxon->bssid_addr);
-
-       /*
-        * reserved4 and 5 could have been filled by the iwlcore code.
-        * Let's clear them before pushing to the 3945.
-        */
-       staging_rxon->reserved4 = 0;
-       staging_rxon->reserved5 = 0;
-
-       iwl_legacy_set_rxon_hwcrypto(priv, ctx, !iwl3945_mod_params.sw_crypto);
-
-       /* Apply the new configuration */
-       rc = iwl_legacy_send_cmd_pdu(priv, REPLY_RXON,
-                             sizeof(struct iwl3945_rxon_cmd),
-                             staging_rxon);
-       if (rc) {
-               IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
-               return rc;
-       }
-
-       memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
-
-       if (!new_assoc) {
-               iwl_legacy_clear_ucode_stations(priv,
-                                        &priv->contexts[IWL_RXON_CTX_BSS]);
-               iwl_legacy_restore_stations(priv,
-                                       &priv->contexts[IWL_RXON_CTX_BSS]);
-       }
-
-       /* 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_legacy_set_tx_power(priv, priv->tx_power_next, true);
-       if (rc) {
-               IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
-               return rc;
-       }
-
-       /* Init the hardware's rate fallback order based on the band */
-       rc = iwl3945_init_hw_rate_table(priv);
-       if (rc) {
-               IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-/**
- * iwl3945_reg_txpower_periodic -  called when time to check our temperature.
- *
- * -- reset periodic timer
- * -- see if temp has changed enough to warrant re-calibration ... if so:
- *     -- correct coeffs for temp (can reset temp timer)
- *     -- save this temp as "last",
- *     -- send new set of gain settings to NIC
- * NOTE:  This should continue working, even when we're not associated,
- *   so we can keep our internal table of scan powers current. */
-void iwl3945_reg_txpower_periodic(struct iwl_priv *priv)
-{
-       /* This will kick in the "brute force"
-        * iwl3945_hw_reg_comp_txpower_temp() below */
-       if (!iwl3945_is_temp_calib_needed(priv))
-               goto reschedule;
-
-       /* Set up a new set of temp-adjusted TxPowers, send to NIC.
-        * This is based *only* on current temperature,
-        * ignoring any previous power measurements */
-       iwl3945_hw_reg_comp_txpower_temp(priv);
-
- reschedule:
-       queue_delayed_work(priv->workqueue,
-                          &priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ);
-}
-
-static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
-{
-       struct iwl_priv *priv = container_of(work, struct iwl_priv,
-                                            _3945.thermal_periodic.work);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       mutex_lock(&priv->mutex);
-       iwl3945_reg_txpower_periodic(priv);
-       mutex_unlock(&priv->mutex);
-}
-
-/**
- * iwl3945_hw_reg_get_ch_grp_index - find the channel-group index (0-4)
- *                                for the channel.
- *
- * This function is used when initializing channel-info structs.
- *
- * NOTE: These channel groups do *NOT* match the bands above!
- *      These channel groups are based on factory-tested channels;
- *      on A-band, EEPROM's "group frequency" entries represent the top
- *      channel in each group 1-4.  Group 5 All B/G channels are in group 0.
- */
-static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv,
-                                      const struct iwl_channel_info *ch_info)
-{
-       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-       struct iwl3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0];
-       u8 group;
-       u16 group_index = 0;    /* based on factory calib frequencies */
-       u8 grp_channel;
-
-       /* Find the group index for the channel ... don't use index 1(?) */
-       if (iwl_legacy_is_channel_a_band(ch_info)) {
-               for (group = 1; group < 5; group++) {
-                       grp_channel = ch_grp[group].group_channel;
-                       if (ch_info->channel <= grp_channel) {
-                               group_index = group;
-                               break;
-                       }
-               }
-               /* group 4 has a few channels *above* its factory cal freq */
-               if (group == 5)
-                       group_index = 4;
-       } else
-               group_index = 0;        /* 2.4 GHz, group 0 */
-
-       IWL_DEBUG_POWER(priv, "Chnl %d mapped to grp %d\n", ch_info->channel,
-                       group_index);
-       return group_index;
-}
-
-/**
- * iwl3945_hw_reg_get_matched_power_index - Interpolate to get nominal index
- *
- * Interpolate to get nominal (i.e. at factory calibration temperature) index
- *   into radio/DSP gain settings table for requested power.
- */
-static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv,
-                                      s8 requested_power,
-                                      s32 setting_index, s32 *new_index)
-{
-       const struct iwl3945_eeprom_txpower_group *chnl_grp = NULL;
-       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-       s32 index0, index1;
-       s32 power = 2 * requested_power;
-       s32 i;
-       const struct iwl3945_eeprom_txpower_sample *samples;
-       s32 gains0, gains1;
-       s32 res;
-       s32 denominator;
-
-       chnl_grp = &eeprom->groups[setting_index];
-       samples = chnl_grp->samples;
-       for (i = 0; i < 5; i++) {
-               if (power == samples[i].power) {
-                       *new_index = samples[i].gain_index;
-                       return 0;
-               }
-       }
-
-       if (power > samples[1].power) {
-               index0 = 0;
-               index1 = 1;
-       } else if (power > samples[2].power) {
-               index0 = 1;
-               index1 = 2;
-       } else if (power > samples[3].power) {
-               index0 = 2;
-               index1 = 3;
-       } else {
-               index0 = 3;
-               index1 = 4;
-       }
-
-       denominator = (s32) samples[index1].power - (s32) samples[index0].power;
-       if (denominator == 0)
-               return -EINVAL;
-       gains0 = (s32) samples[index0].gain_index * (1 << 19);
-       gains1 = (s32) samples[index1].gain_index * (1 << 19);
-       res = gains0 + (gains1 - gains0) *
-           ((s32) power - (s32) samples[index0].power) / denominator +
-           (1 << 18);
-       *new_index = res >> 19;
-       return 0;
-}
-
-static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv)
-{
-       u32 i;
-       s32 rate_index;
-       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-       const struct iwl3945_eeprom_txpower_group *group;
-
-       IWL_DEBUG_POWER(priv, "Initializing factory calib info from EEPROM\n");
-
-       for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) {
-               s8 *clip_pwrs;  /* table of power levels for each rate */
-               s8 satur_pwr;   /* saturation power for each chnl group */
-               group = &eeprom->groups[i];
-
-               /* sanity check on factory saturation power value */
-               if (group->saturation_power < 40) {
-                       IWL_WARN(priv, "Error: saturation power is %d, "
-                                   "less than minimum expected 40\n",
-                                   group->saturation_power);
-                       return;
-               }
-
-               /*
-                * Derive requested power levels for each rate, based on
-                *   hardware capabilities (saturation power for band).
-                * Basic value is 3dB down from saturation, with further
-                *   power reductions for highest 3 data rates.  These
-                *   backoffs provide headroom for high rate modulation
-                *   power peaks, without too much distortion (clipping).
-                */
-               /* we'll fill in this array with h/w max power levels */
-               clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers;
-
-               /* divide factory saturation power by 2 to find -3dB level */
-               satur_pwr = (s8) (group->saturation_power >> 1);
-
-               /* fill in channel group's nominal powers for each rate */
-               for (rate_index = 0;
-                    rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) {
-                       switch (rate_index) {
-                       case IWL_RATE_36M_INDEX_TABLE:
-                               if (i == 0)     /* B/G */
-                                       *clip_pwrs = satur_pwr;
-                               else    /* A */
-                                       *clip_pwrs = satur_pwr - 5;
-                               break;
-                       case IWL_RATE_48M_INDEX_TABLE:
-                               if (i == 0)
-                                       *clip_pwrs = satur_pwr - 7;
-                               else
-                                       *clip_pwrs = satur_pwr - 10;
-                               break;
-                       case IWL_RATE_54M_INDEX_TABLE:
-                               if (i == 0)
-                                       *clip_pwrs = satur_pwr - 9;
-                               else
-                                       *clip_pwrs = satur_pwr - 12;
-                               break;
-                       default:
-                               *clip_pwrs = satur_pwr;
-                               break;
-                       }
-               }
-       }
-}
-
-/**
- * iwl3945_txpower_set_from_eeprom - Set channel power info based on EEPROM
- *
- * Second pass (during init) to set up priv->channel_info
- *
- * Set up Tx-power settings in our channel info database for each VALID
- * (for this geo/SKU) channel, at all Tx data rates, based on eeprom values
- * and current temperature.
- *
- * Since this is based on current temperature (at init time), these values may
- * not be valid for very long, but it gives us a starting/default point,
- * and allows us to active (i.e. using Tx) scan.
- *
- * This does *not* write values to NIC, just sets up our internal table.
- */
-int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
-{
-       struct iwl_channel_info *ch_info = NULL;
-       struct iwl3945_channel_power_info *pwr_info;
-       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-       int delta_index;
-       u8 rate_index;
-       u8 scan_tbl_index;
-       const s8 *clip_pwrs;    /* array of power levels for each rate */
-       u8 gain, dsp_atten;
-       s8 power;
-       u8 pwr_index, base_pwr_index, a_band;
-       u8 i;
-       int temperature;
-
-       /* save temperature reference,
-        *   so we can determine next time to calibrate */
-       temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
-       priv->last_temperature = temperature;
-
-       iwl3945_hw_reg_init_channel_groups(priv);
-
-       /* initialize Tx power info for each and every channel, 2.4 and 5.x */
-       for (i = 0, ch_info = priv->channel_info; i < priv->channel_count;
-            i++, ch_info++) {
-               a_band = iwl_legacy_is_channel_a_band(ch_info);
-               if (!iwl_legacy_is_channel_valid(ch_info))
-                       continue;
-
-               /* find this channel's channel group (*not* "band") index */
-               ch_info->group_index =
-                       iwl3945_hw_reg_get_ch_grp_index(priv, ch_info);
-
-               /* Get this chnlgrp's rate->max/clip-powers table */
-               clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
-
-               /* calculate power index *adjustment* value according to
-                *  diff between current temperature and factory temperature */
-               delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
-                               eeprom->groups[ch_info->group_index].
-                               temperature);
-
-               IWL_DEBUG_POWER(priv, "Delta index for channel %d: %d [%d]\n",
-                               ch_info->channel, delta_index, temperature +
-                               IWL_TEMP_CONVERT);
-
-               /* set tx power value for all OFDM rates */
-               for (rate_index = 0; rate_index < IWL_OFDM_RATES;
-                    rate_index++) {
-                       s32 uninitialized_var(power_idx);
-                       int rc;
-
-                       /* use channel group's clip-power table,
-                        *   but don't exceed channel's max power */
-                       s8 pwr = min(ch_info->max_power_avg,
-                                    clip_pwrs[rate_index]);
-
-                       pwr_info = &ch_info->power_info[rate_index];
-
-                       /* get base (i.e. at factory-measured temperature)
-                        *    power table index for this rate's power */
-                       rc = iwl3945_hw_reg_get_matched_power_index(priv, pwr,
-                                                        ch_info->group_index,
-                                                        &power_idx);
-                       if (rc) {
-                               IWL_ERR(priv, "Invalid power index\n");
-                               return rc;
-                       }
-                       pwr_info->base_power_index = (u8) power_idx;
-
-                       /* temperature compensate */
-                       power_idx += delta_index;
-
-                       /* stay within range of gain table */
-                       power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
-
-                       /* fill 1 OFDM rate's iwl3945_channel_power_info struct */
-                       pwr_info->requested_power = pwr;
-                       pwr_info->power_table_index = (u8) power_idx;
-                       pwr_info->tpc.tx_gain =
-                           power_gain_table[a_band][power_idx].tx_gain;
-                       pwr_info->tpc.dsp_atten =
-                           power_gain_table[a_band][power_idx].dsp_atten;
-               }
-
-               /* set tx power for CCK rates, based on OFDM 12 Mbit settings*/
-               pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE];
-               power = pwr_info->requested_power +
-                       IWL_CCK_FROM_OFDM_POWER_DIFF;
-               pwr_index = pwr_info->power_table_index +
-                       IWL_CCK_FROM_OFDM_INDEX_DIFF;
-               base_pwr_index = pwr_info->base_power_index +
-                       IWL_CCK_FROM_OFDM_INDEX_DIFF;
-
-               /* stay within table range */
-               pwr_index = iwl3945_hw_reg_fix_power_index(pwr_index);
-               gain = power_gain_table[a_band][pwr_index].tx_gain;
-               dsp_atten = power_gain_table[a_band][pwr_index].dsp_atten;
-
-               /* fill each CCK rate's iwl3945_channel_power_info structure
-                * NOTE:  All CCK-rate Txpwrs are the same for a given chnl!
-                * NOTE:  CCK rates start at end of OFDM rates! */
-               for (rate_index = 0;
-                    rate_index < IWL_CCK_RATES; rate_index++) {
-                       pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES];
-                       pwr_info->requested_power = power;
-                       pwr_info->power_table_index = pwr_index;
-                       pwr_info->base_power_index = base_pwr_index;
-                       pwr_info->tpc.tx_gain = gain;
-                       pwr_info->tpc.dsp_atten = dsp_atten;
-               }
-
-               /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
-               for (scan_tbl_index = 0;
-                    scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
-                       s32 actual_index = (scan_tbl_index == 0) ?
-                               IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
-                       iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
-                               actual_index, clip_pwrs, ch_info, a_band);
-               }
-       }
-
-       return 0;
-}
-
-int iwl3945_hw_rxq_stop(struct iwl_priv *priv)
-{
-       int rc;
-
-       iwl_legacy_write_direct32(priv, FH39_RCSR_CONFIG(0), 0);
-       rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS,
-                       FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-       if (rc < 0)
-               IWL_ERR(priv, "Can't stop Rx DMA.\n");
-
-       return 0;
-}
-
-int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-       int txq_id = txq->q.id;
-
-       struct iwl3945_shared *shared_data = priv->_3945.shared_virt;
-
-       shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
-
-       iwl_legacy_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0);
-       iwl_legacy_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0);
-
-       iwl_legacy_write_direct32(priv, FH39_TCSR_CONFIG(txq_id),
-               FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |
-               FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |
-               FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |
-               FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |
-               FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);
-
-       /* fake read to flush all prev. writes */
-       iwl_read32(priv, FH39_TSSR_CBB_BASE);
-
-       return 0;
-}
-
-/*
- * HCMD utils
- */
-static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len)
-{
-       switch (cmd_id) {
-       case REPLY_RXON:
-               return sizeof(struct iwl3945_rxon_cmd);
-       case POWER_TABLE_CMD:
-               return sizeof(struct iwl3945_powertable_cmd);
-       default:
-               return len;
-       }
-}
-
-
-static u16 iwl3945_build_addsta_hcmd(const struct iwl_legacy_addsta_cmd *cmd,
-                                                               u8 *data)
-{
-       struct iwl3945_addsta_cmd *addsta = (struct iwl3945_addsta_cmd *)data;
-       addsta->mode = cmd->mode;
-       memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
-       memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo));
-       addsta->station_flags = cmd->station_flags;
-       addsta->station_flags_msk = cmd->station_flags_msk;
-       addsta->tid_disable_tx = cpu_to_le16(0);
-       addsta->rate_n_flags = cmd->rate_n_flags;
-       addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
-       addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
-       addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
-
-       return (u16)sizeof(struct iwl3945_addsta_cmd);
-}
-
-static int iwl3945_add_bssid_station(struct iwl_priv *priv,
-                                    const u8 *addr, u8 *sta_id_r)
-{
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       int ret;
-       u8 sta_id;
-       unsigned long flags;
-
-       if (sta_id_r)
-               *sta_id_r = IWL_INVALID_STATION;
-
-       ret = iwl_legacy_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
-       if (ret) {
-               IWL_ERR(priv, "Unable to add station %pM\n", addr);
-               return ret;
-       }
-
-       if (sta_id_r)
-               *sta_id_r = sta_id;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].used |= IWL_STA_LOCAL;
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return 0;
-}
-static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
-                                      struct ieee80211_vif *vif, bool add)
-{
-       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-       int ret;
-
-       if (add) {
-               ret = iwl3945_add_bssid_station(priv, vif->bss_conf.bssid,
-                                               &vif_priv->ibss_bssid_sta_id);
-               if (ret)
-                       return ret;
-
-               iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id,
-                                (priv->band == IEEE80211_BAND_5GHZ) ?
-                                IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP);
-               iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id);
-
-               return 0;
-       }
-
-       return iwl_legacy_remove_station(priv, vif_priv->ibss_bssid_sta_id,
-                                 vif->bss_conf.bssid);
-}
-
-/**
- * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
- */
-int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
-{
-       int rc, i, index, prev_index;
-       struct iwl3945_rate_scaling_cmd rate_cmd = {
-               .reserved = {0, 0, 0},
-       };
-       struct iwl3945_rate_scaling_info *table = rate_cmd.table;
-
-       for (i = 0; i < ARRAY_SIZE(iwl3945_rates); i++) {
-               index = iwl3945_rates[i].table_rs_index;
-
-               table[index].rate_n_flags =
-                       iwl3945_hw_set_rate_n_flags(iwl3945_rates[i].plcp, 0);
-               table[index].try_cnt = priv->retry_rate;
-               prev_index = iwl3945_get_prev_ieee_rate(i);
-               table[index].next_rate_index =
-                               iwl3945_rates[prev_index].table_rs_index;
-       }
-
-       switch (priv->band) {
-       case IEEE80211_BAND_5GHZ:
-               IWL_DEBUG_RATE(priv, "Select A mode rate scale\n");
-               /* If one of the following CCK rates is used,
-                * have it fall back to the 6M OFDM rate */
-               for (i = IWL_RATE_1M_INDEX_TABLE;
-                       i <= IWL_RATE_11M_INDEX_TABLE; i++)
-                       table[i].next_rate_index =
-                         iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
-
-               /* Don't fall back to CCK rates */
-               table[IWL_RATE_12M_INDEX_TABLE].next_rate_index =
-                                               IWL_RATE_9M_INDEX_TABLE;
-
-               /* Don't drop out of OFDM rates */
-               table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =
-                   iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
-               break;
-
-       case IEEE80211_BAND_2GHZ:
-               IWL_DEBUG_RATE(priv, "Select B/G mode rate scale\n");
-               /* If an OFDM rate is used, have it fall back to the
-                * 1M CCK rates */
-
-               if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
-                   iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
-
-                       index = IWL_FIRST_CCK_RATE;
-                       for (i = IWL_RATE_6M_INDEX_TABLE;
-                            i <= IWL_RATE_54M_INDEX_TABLE; i++)
-                               table[i].next_rate_index =
-                                       iwl3945_rates[index].table_rs_index;
-
-                       index = IWL_RATE_11M_INDEX_TABLE;
-                       /* CCK shouldn't fall back to OFDM... */
-                       table[index].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
-               }
-               break;
-
-       default:
-               WARN_ON(1);
-               break;
-       }
-
-       /* Update the rate scaling for control frame Tx */
-       rate_cmd.table_id = 0;
-       rc = iwl_legacy_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
-                             &rate_cmd);
-       if (rc)
-               return rc;
-
-       /* Update the rate scaling for data frame Tx */
-       rate_cmd.table_id = 1;
-       return iwl_legacy_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
-                               &rate_cmd);
-}
-
-/* Called when initializing driver */
-int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
-{
-       memset((void *)&priv->hw_params, 0,
-              sizeof(struct iwl_hw_params));
-
-       priv->_3945.shared_virt =
-               dma_alloc_coherent(&priv->pci_dev->dev,
-                                  sizeof(struct iwl3945_shared),
-                                  &priv->_3945.shared_phys, GFP_KERNEL);
-       if (!priv->_3945.shared_virt) {
-               IWL_ERR(priv, "failed to allocate pci memory\n");
-               return -ENOMEM;
-       }
-
-       /* Assign number of Usable TX queues */
-       priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-
-       priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
-       priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);
-       priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
-       priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
-       priv->hw_params.max_stations = IWL3945_STATION_COUNT;
-       priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID;
-
-       priv->sta_key_max_num = STA_KEY_MAX_NUM;
-
-       priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
-       priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL;
-       priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS;
-
-       return 0;
-}
-
-unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
-                         struct iwl3945_frame *frame, u8 rate)
-{
-       struct iwl3945_tx_beacon_cmd *tx_beacon_cmd;
-       unsigned int frame_size;
-
-       tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
-       memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
-
-       tx_beacon_cmd->tx.sta_id =
-               priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
-       tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
-       frame_size = iwl3945_fill_beacon_frame(priv,
-                               tx_beacon_cmd->frame,
-                               sizeof(frame->u) - sizeof(*tx_beacon_cmd));
-
-       BUG_ON(frame_size > MAX_MPDU_SIZE);
-       tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
-
-       tx_beacon_cmd->tx.rate = rate;
-       tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK |
-                                     TX_CMD_FLG_TSF_MSK);
-
-       /* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/
-       tx_beacon_cmd->tx.supp_rates[0] =
-               (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
-
-       tx_beacon_cmd->tx.supp_rates[1] =
-               (IWL_CCK_BASIC_RATES_MASK & 0xF);
-
-       return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size;
-}
-
-void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv)
-{
-       priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
-       priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
-}
-
-void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv)
-{
-       INIT_DELAYED_WORK(&priv->_3945.thermal_periodic,
-                         iwl3945_bg_reg_txpower_periodic);
-}
-
-void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv)
-{
-       cancel_delayed_work(&priv->_3945.thermal_periodic);
-}
-
-/* check contents of special bootstrap uCode SRAM */
-static int iwl3945_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(priv, "Begin verify bsm\n");
-
-       /* verify BSM SRAM contents */
-       val = iwl_legacy_read_prph(priv, BSM_WR_DWCOUNT_REG);
-       for (reg = BSM_SRAM_LOWER_BOUND;
-            reg < BSM_SRAM_LOWER_BOUND + len;
-            reg += sizeof(u32), image++) {
-               val = iwl_legacy_read_prph(priv, reg);
-               if (val != le32_to_cpu(*image)) {
-                       IWL_ERR(priv, "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(priv, "BSM bootstrap uCode image OK\n");
-
-       return 0;
-}
-
-
-/******************************************************************************
- *
- * EEPROM related functions
- *
- ******************************************************************************/
-
-/*
- * Clear the OWNER_MSK, to establish driver (instead of uCode running on
- * embedded controller) as EEPROM reader; each read is a series of pulses
- * to/from the EEPROM chip, not a single event, so even reads could conflict
- * if they weren't arbitrated by some ownership mechanism.  Here, the driver
- * simply claims ownership, which should be safe when this function is called
- * (i.e. before loading uCode!).
- */
-static int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv)
-{
-       _iwl_legacy_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
-       return 0;
-}
-
-
-static void iwl3945_eeprom_release_semaphore(struct iwl_priv *priv)
-{
-       return;
-}
-
- /**
-  * iwl3945_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 iwl3945_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(priv, "Begin load bsm\n");
-
-       /* make sure bootstrap program is no larger than BSM's SRAM size */
-       if (len > IWL39_MAX_BSM_SIZE)
-               return -EINVAL;
-
-       /* Tell bootstrap uCode where to find the "Initialize" uCode
-       *   in host DRAM ... host DRAM physical address bits 31:0 for 3945.
-       * NOTE:  iwl3945_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;
-
-       iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-       iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-       iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
-       iwl_legacy_write_prph(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_legacy_write_prph(priv, reg_offset,
-                                         le32_to_cpu(*image));
-
-       rc = iwl3945_verify_bsm(priv);
-       if (rc)
-               return rc;
-
-       /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
-       iwl_legacy_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
-       iwl_legacy_write_prph(priv, BSM_WR_MEM_DST_REG,
-                                IWL39_RTC_INST_LOWER_BOUND);
-       iwl_legacy_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
-
-       /* Load bootstrap code into instruction SRAM now,
-        *   to prepare to load "initialize" uCode */
-       iwl_legacy_write_prph(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_legacy_read_prph(priv, BSM_WR_CTRL_REG);
-               if (!(done & BSM_WR_CTRL_REG_BIT_START))
-                       break;
-               udelay(10);
-       }
-       if (i < 100)
-               IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
-       else {
-               IWL_ERR(priv, "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_legacy_write_prph(priv, BSM_WR_CTRL_REG,
-               BSM_WR_CTRL_REG_BIT_START_EN);
-
-       return 0;
-}
-
-static struct iwl_hcmd_ops iwl3945_hcmd = {
-       .rxon_assoc = iwl3945_send_rxon_assoc,
-       .commit_rxon = iwl3945_commit_rxon,
-};
-
-static struct iwl_lib_ops iwl3945_lib = {
-       .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
-       .txq_free_tfd = iwl3945_hw_txq_free_tfd,
-       .txq_init = iwl3945_hw_tx_queue_init,
-       .load_ucode = iwl3945_load_bsm,
-       .dump_nic_error_log = iwl3945_dump_nic_error_log,
-       .apm_ops = {
-               .init = iwl3945_apm_init,
-               .config = iwl3945_nic_config,
-       },
-       .eeprom_ops = {
-               .regulatory_bands = {
-                       EEPROM_REGULATORY_BAND_1_CHANNELS,
-                       EEPROM_REGULATORY_BAND_2_CHANNELS,
-                       EEPROM_REGULATORY_BAND_3_CHANNELS,
-                       EEPROM_REGULATORY_BAND_4_CHANNELS,
-                       EEPROM_REGULATORY_BAND_5_CHANNELS,
-                       EEPROM_REGULATORY_BAND_NO_HT40,
-                       EEPROM_REGULATORY_BAND_NO_HT40,
-               },
-               .acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
-               .release_semaphore = iwl3945_eeprom_release_semaphore,
-       },
-       .send_tx_power  = iwl3945_send_tx_power,
-       .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
-
-       .debugfs_ops = {
-               .rx_stats_read = iwl3945_ucode_rx_stats_read,
-               .tx_stats_read = iwl3945_ucode_tx_stats_read,
-               .general_stats_read = iwl3945_ucode_general_stats_read,
-       },
-};
-
-static const struct iwl_legacy_ops iwl3945_legacy_ops = {
-       .post_associate = iwl3945_post_associate,
-       .config_ap = iwl3945_config_ap,
-       .manage_ibss_station = iwl3945_manage_ibss_station,
-};
-
-static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
-       .get_hcmd_size = iwl3945_get_hcmd_size,
-       .build_addsta_hcmd = iwl3945_build_addsta_hcmd,
-       .request_scan = iwl3945_request_scan,
-       .post_scan = iwl3945_post_scan,
-};
-
-static const struct iwl_ops iwl3945_ops = {
-       .lib = &iwl3945_lib,
-       .hcmd = &iwl3945_hcmd,
-       .utils = &iwl3945_hcmd_utils,
-       .led = &iwl3945_led_ops,
-       .legacy = &iwl3945_legacy_ops,
-       .ieee80211_ops = &iwl3945_hw_ops,
-};
-
-static struct iwl_base_params iwl3945_base_params = {
-       .eeprom_size = IWL3945_EEPROM_IMG_SIZE,
-       .num_of_queues = IWL39_NUM_QUEUES,
-       .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
-       .set_l0s = false,
-       .use_bsm = true,
-       .led_compensation = 64,
-       .wd_timeout = IWL_DEF_WD_TIMEOUT,
-};
-
-static struct iwl_cfg iwl3945_bg_cfg = {
-       .name = "3945BG",
-       .fw_name_pre = IWL3945_FW_PRE,
-       .ucode_api_max = IWL3945_UCODE_API_MAX,
-       .ucode_api_min = IWL3945_UCODE_API_MIN,
-       .sku = IWL_SKU_G,
-       .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
-       .ops = &iwl3945_ops,
-       .mod_params = &iwl3945_mod_params,
-       .base_params = &iwl3945_base_params,
-       .led_mode = IWL_LED_BLINK,
-};
-
-static struct iwl_cfg iwl3945_abg_cfg = {
-       .name = "3945ABG",
-       .fw_name_pre = IWL3945_FW_PRE,
-       .ucode_api_max = IWL3945_UCODE_API_MAX,
-       .ucode_api_min = IWL3945_UCODE_API_MIN,
-       .sku = IWL_SKU_A|IWL_SKU_G,
-       .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
-       .ops = &iwl3945_ops,
-       .mod_params = &iwl3945_mod_params,
-       .base_params = &iwl3945_base_params,
-       .led_mode = IWL_LED_BLINK,
-};
-
-DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
-       {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)},
-       {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)},
-       {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)},
-       {IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)},
-       {IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)},
-       {IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)},
-       {0}
-};
-
-MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids);
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.h b/drivers/net/wireless/iwlegacy/iwl-3945.h
deleted file mode 100644 (file)
index b118b59..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-3945.h) for driver implementation definitions.
- * Please use iwl-3945-commands.h for uCode API definitions.
- * Please use iwl-3945-hw.h for hardware-related definitions.
- */
-
-#ifndef __iwl_3945_h__
-#define __iwl_3945_h__
-
-#include <linux/pci.h> /* for struct pci_device_id */
-#include <linux/kernel.h>
-#include <net/ieee80211_radiotap.h>
-
-/* Hardware specific file defines the PCI IDs table for that hardware module */
-extern const struct pci_device_id iwl3945_hw_card_ids[];
-
-#include "iwl-csr.h"
-#include "iwl-prph.h"
-#include "iwl-fh.h"
-#include "iwl-3945-hw.h"
-#include "iwl-debug.h"
-#include "iwl-power.h"
-#include "iwl-dev.h"
-#include "iwl-led.h"
-
-/* Highest firmware API version supported */
-#define IWL3945_UCODE_API_MAX 2
-
-/* Lowest firmware API version supported */
-#define IWL3945_UCODE_API_MIN 1
-
-#define IWL3945_FW_PRE "iwlwifi-3945-"
-#define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE #api ".ucode"
-#define IWL3945_MODULE_FIRMWARE(api) _IWL3945_MODULE_FIRMWARE(api)
-
-/* Default noise level to report when noise measurement is not available.
- *   This may be because we're:
- *   1)  Not associated (4965, no beacon statistics being sent to driver)
- *   2)  Scanning (noise measurement does not apply to associated channel)
- *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
- * Use default noise value of -127 ... this is below the range of measurable
- *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
- *   Also, -127 works better than 0 when averaging frames with/without
- *   noise info (e.g. averaging might be done in app); measured dBm values are
- *   always negative ... using a negative value as the default keeps all
- *   averages within an s8's (used in some apps) range of negative values. */
-#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
-
-/* Module parameters accessible from iwl-*.c */
-extern struct iwl_mod_params iwl3945_mod_params;
-
-struct iwl3945_rate_scale_data {
-       u64 data;
-       s32 success_counter;
-       s32 success_ratio;
-       s32 counter;
-       s32 average_tpt;
-       unsigned long stamp;
-};
-
-struct iwl3945_rs_sta {
-       spinlock_t lock;
-       struct iwl_priv *priv;
-       s32 *expected_tpt;
-       unsigned long last_partial_flush;
-       unsigned long last_flush;
-       u32 flush_time;
-       u32 last_tx_packets;
-       u32 tx_packets;
-       u8 tgg;
-       u8 flush_pending;
-       u8 start_rate;
-       struct timer_list rate_scale_flush;
-       struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945];
-#ifdef CONFIG_MAC80211_DEBUGFS
-       struct dentry *rs_sta_dbgfs_stats_table_file;
-#endif
-
-       /* used to be in sta_info */
-       int last_txrate_idx;
-};
-
-
-/*
- * The common struct MUST be first because it is shared between
- * 3945 and 4965!
- */
-struct iwl3945_sta_priv {
-       struct iwl_station_priv_common common;
-       struct iwl3945_rs_sta rs_sta;
-};
-
-enum iwl3945_antenna {
-       IWL_ANTENNA_DIVERSITY,
-       IWL_ANTENNA_MAIN,
-       IWL_ANTENNA_AUX
-};
-
-/*
- * RTS threshold here is total size [2347] minus 4 FCS bytes
- * Per spec:
- *   a value of 0 means RTS on all data/management packets
- *   a value > max MSDU size means no RTS
- * else RTS for data/management frames where MPDU is larger
- *   than RTS value.
- */
-#define DEFAULT_RTS_THRESHOLD     2347U
-#define MIN_RTS_THRESHOLD         0U
-#define MAX_RTS_THRESHOLD         2347U
-#define MAX_MSDU_SIZE            2304U
-#define MAX_MPDU_SIZE            2346U
-#define DEFAULT_BEACON_INTERVAL   100U
-#define        DEFAULT_SHORT_RETRY_LIMIT 7U
-#define        DEFAULT_LONG_RETRY_LIMIT  4U
-
-#define IWL_TX_FIFO_AC0        0
-#define IWL_TX_FIFO_AC1        1
-#define IWL_TX_FIFO_AC2        2
-#define IWL_TX_FIFO_AC3        3
-#define IWL_TX_FIFO_HCCA_1     5
-#define IWL_TX_FIFO_HCCA_2     6
-#define IWL_TX_FIFO_NONE       7
-
-#define IEEE80211_DATA_LEN              2304
-#define IEEE80211_4ADDR_LEN             30
-#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
-#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
-
-struct iwl3945_frame {
-       union {
-               struct ieee80211_hdr frame;
-               struct iwl3945_tx_beacon_cmd beacon;
-               u8 raw[IEEE80211_FRAME_LEN];
-               u8 cmd[360];
-       } u;
-       struct list_head list;
-};
-
-#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
-
-#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
-#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
-#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
-
-#define IWL_SUPPORTED_RATES_IE_LEN         8
-
-#define SCAN_INTERVAL 100
-
-#define MAX_TID_COUNT        9
-
-#define IWL_INVALID_RATE     0xFF
-#define IWL_INVALID_VALUE    -1
-
-#define STA_PS_STATUS_WAKE             0
-#define STA_PS_STATUS_SLEEP            1
-
-struct iwl3945_ibss_seq {
-       u8 mac[ETH_ALEN];
-       u16 seq_num;
-       u16 frag_num;
-       unsigned long packet_time;
-       struct list_head list;
-};
-
-#define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\
-                      x->u.rx_frame.stats.payload + \
-                      x->u.rx_frame.stats.phy_count))
-#define IWL_RX_END(x) ((struct iwl3945_rx_frame_end *)(\
-                      IWL_RX_HDR(x)->payload + \
-                      le16_to_cpu(IWL_RX_HDR(x)->len)))
-#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
-#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
-
-
-/******************************************************************************
- *
- * Functions implemented in iwl3945-base.c which are forward declared here
- * for use by iwl-*.c
- *
- *****************************************************************************/
-extern int iwl3945_calc_db_from_ratio(int sig_ratio);
-extern void iwl3945_rx_replenish(void *data);
-extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
-                                       struct ieee80211_hdr *hdr, int left);
-extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-                                      char **buf, bool display);
-extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
-
-/******************************************************************************
- *
- * Functions implemented in iwl-[34]*.c which are forward declared here
- * for use by iwl3945-base.c
- *
- * NOTE:  The implementation of these functions are hardware specific
- * which is why they are in the hardware specific files (vs. iwl-base.c)
- *
- * Naming convention --
- * iwl3945_         <-- Its part of iwlwifi (should be changed to iwl3945_)
- * iwl3945_hw_      <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
- * iwlXXXX_     <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
- * iwl3945_bg_      <-- Called from work queue context
- * iwl3945_mac_     <-- mac80211 callback
- *
- ****************************************************************************/
-extern void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv);
-extern void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv);
-extern void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv);
-extern int iwl3945_hw_rxq_stop(struct iwl_priv *priv);
-extern int iwl3945_hw_set_hw_params(struct iwl_priv *priv);
-extern int iwl3945_hw_nic_init(struct iwl_priv *priv);
-extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv);
-extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv);
-extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv);
-extern int iwl3945_hw_nic_reset(struct iwl_priv *priv);
-extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-                                           struct iwl_tx_queue *txq,
-                                           dma_addr_t addr, u16 len,
-                                           u8 reset, u8 pad);
-extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv,
-                                   struct iwl_tx_queue *txq);
-extern int iwl3945_hw_get_temperature(struct iwl_priv *priv);
-extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
-                               struct iwl_tx_queue *txq);
-extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
-                                struct iwl3945_frame *frame, u8 rate);
-void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
-                                 struct iwl_device_cmd *cmd,
-                                 struct ieee80211_tx_info *info,
-                                 struct ieee80211_hdr *hdr,
-                                 int sta_id, int tx_id);
-extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
-extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
-extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
-                                struct iwl_rx_mem_buffer *rxb);
-void iwl3945_reply_statistics(struct iwl_priv *priv,
-                             struct iwl_rx_mem_buffer *rxb);
-extern void iwl3945_disable_events(struct iwl_priv *priv);
-extern int iwl4965_get_temperature(const struct iwl_priv *priv);
-extern void iwl3945_post_associate(struct iwl_priv *priv);
-extern void iwl3945_config_ap(struct iwl_priv *priv);
-
-extern int iwl3945_commit_rxon(struct iwl_priv *priv,
-                              struct iwl_rxon_context *ctx);
-
-/**
- * iwl3945_hw_find_station - Find station id for a given BSSID
- * @bssid: MAC address of station ID to find
- *
- * NOTE:  This should not be hardware specific but the code has
- * not yet been merged into a single common layer for managing the
- * station tables.
- */
-extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
-
-extern struct ieee80211_ops iwl3945_hw_ops;
-
-/*
- * Forward declare iwl-3945.c functions for iwl3945-base.c
- */
-extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv);
-extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv);
-extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv);
-extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
-
-extern const struct iwl_channel_info *iwl3945_get_channel_info(
-       const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
-
-extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
-
-/* scanning */
-int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
-void iwl3945_post_scan(struct iwl_priv *priv);
-
-/* rates */
-extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
-
-/* Requires full declaration of iwl_priv before including */
-#include "iwl-io.h"
-
-#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-calib.h b/drivers/net/wireless/iwlegacy/iwl-4965-calib.h
deleted file mode 100644 (file)
index f46c80e..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/******************************************************************************
- *
- * 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) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 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_4965_calib_h__
-#define __iwl_4965_calib_h__
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-commands.h"
-
-void iwl4965_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp);
-void iwl4965_sensitivity_calibration(struct iwl_priv *priv, void *resp);
-void iwl4965_init_sensitivity(struct iwl_priv *priv);
-void iwl4965_reset_run_time_calib(struct iwl_priv *priv);
-void iwl4965_calib_free_results(struct iwl_priv *priv);
-
-#endif /* __iwl_4965_calib_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.c
deleted file mode 100644 (file)
index 1c93665..0000000
+++ /dev/null
@@ -1,774 +0,0 @@
-/******************************************************************************
-*
-* GPL LICENSE SUMMARY
-*
-* Copyright(c) 2008 - 2011 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.GPL.
-*
-* Contact Information:
-*  Intel Linux Wireless <ilw@linux.intel.com>
-* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*****************************************************************************/
-#include "iwl-4965.h"
-#include "iwl-4965-debugfs.h"
-
-static const char *fmt_value = "  %-30s %10u\n";
-static const char *fmt_table = "  %-30s %10u  %10u  %10u  %10u\n";
-static const char *fmt_header =
-       "%-32s    current  cumulative       delta         max\n";
-
-static int iwl4965_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
-{
-       int p = 0;
-       u32 flag;
-
-       flag = le32_to_cpu(priv->_4965.statistics.flag);
-
-       p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
-       if (flag & UCODE_STATISTICS_CLEAR_MSK)
-               p += scnprintf(buf + p, bufsz - p,
-               "\tStatistics have been cleared\n");
-       p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
-               (flag & UCODE_STATISTICS_FREQUENCY_MSK)
-               ? "2.4 GHz" : "5.2 GHz");
-       p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
-               (flag & UCODE_STATISTICS_NARROW_BAND_MSK)
-                ? "enabled" : "disabled");
-
-       return p;
-}
-
-ssize_t iwl4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
-                               size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       char *buf;
-       int bufsz = sizeof(struct statistics_rx_phy) * 40 +
-                   sizeof(struct statistics_rx_non_phy) * 40 +
-                   sizeof(struct statistics_rx_ht_phy) * 40 + 400;
-       ssize_t ret;
-       struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
-       struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
-       struct statistics_rx_non_phy *general, *accum_general;
-       struct statistics_rx_non_phy *delta_general, *max_general;
-       struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
-
-       if (!iwl_legacy_is_alive(priv))
-               return -EAGAIN;
-
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       /*
-        * the statistic information display here is based on
-        * the last statistics notification from uCode
-        * might not reflect the current uCode activity
-        */
-       ofdm = &priv->_4965.statistics.rx.ofdm;
-       cck = &priv->_4965.statistics.rx.cck;
-       general = &priv->_4965.statistics.rx.general;
-       ht = &priv->_4965.statistics.rx.ofdm_ht;
-       accum_ofdm = &priv->_4965.accum_statistics.rx.ofdm;
-       accum_cck = &priv->_4965.accum_statistics.rx.cck;
-       accum_general = &priv->_4965.accum_statistics.rx.general;
-       accum_ht = &priv->_4965.accum_statistics.rx.ofdm_ht;
-       delta_ofdm = &priv->_4965.delta_statistics.rx.ofdm;
-       delta_cck = &priv->_4965.delta_statistics.rx.cck;
-       delta_general = &priv->_4965.delta_statistics.rx.general;
-       delta_ht = &priv->_4965.delta_statistics.rx.ofdm_ht;
-       max_ofdm = &priv->_4965.max_delta.rx.ofdm;
-       max_cck = &priv->_4965.max_delta.rx.cck;
-       max_general = &priv->_4965.max_delta.rx.general;
-       max_ht = &priv->_4965.max_delta.rx.ofdm_ht;
-
-       pos += iwl4965_statistics_flag(priv, buf, bufsz);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_header, "Statistics_Rx - OFDM:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "ina_cnt:",
-                        le32_to_cpu(ofdm->ina_cnt),
-                        accum_ofdm->ina_cnt,
-                        delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "fina_cnt:",
-                        le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
-                        delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "plcp_err:",
-                        le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
-                        delta_ofdm->plcp_err, max_ofdm->plcp_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "crc32_err:",
-                        le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
-                        delta_ofdm->crc32_err, max_ofdm->crc32_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "overrun_err:",
-                        le32_to_cpu(ofdm->overrun_err),
-                        accum_ofdm->overrun_err, delta_ofdm->overrun_err,
-                        max_ofdm->overrun_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "early_overrun_err:",
-                        le32_to_cpu(ofdm->early_overrun_err),
-                        accum_ofdm->early_overrun_err,
-                        delta_ofdm->early_overrun_err,
-                        max_ofdm->early_overrun_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "crc32_good:",
-                        le32_to_cpu(ofdm->crc32_good),
-                        accum_ofdm->crc32_good, delta_ofdm->crc32_good,
-                        max_ofdm->crc32_good);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "false_alarm_cnt:",
-                        le32_to_cpu(ofdm->false_alarm_cnt),
-                        accum_ofdm->false_alarm_cnt,
-                        delta_ofdm->false_alarm_cnt,
-                        max_ofdm->false_alarm_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "fina_sync_err_cnt:",
-                        le32_to_cpu(ofdm->fina_sync_err_cnt),
-                        accum_ofdm->fina_sync_err_cnt,
-                        delta_ofdm->fina_sync_err_cnt,
-                        max_ofdm->fina_sync_err_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "sfd_timeout:",
-                        le32_to_cpu(ofdm->sfd_timeout),
-                        accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout,
-                        max_ofdm->sfd_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "fina_timeout:",
-                        le32_to_cpu(ofdm->fina_timeout),
-                        accum_ofdm->fina_timeout, delta_ofdm->fina_timeout,
-                        max_ofdm->fina_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "unresponded_rts:",
-                        le32_to_cpu(ofdm->unresponded_rts),
-                        accum_ofdm->unresponded_rts,
-                        delta_ofdm->unresponded_rts,
-                        max_ofdm->unresponded_rts);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "rxe_frame_lmt_ovrun:",
-                        le32_to_cpu(ofdm->rxe_frame_limit_overrun),
-                        accum_ofdm->rxe_frame_limit_overrun,
-                        delta_ofdm->rxe_frame_limit_overrun,
-                        max_ofdm->rxe_frame_limit_overrun);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "sent_ack_cnt:",
-                        le32_to_cpu(ofdm->sent_ack_cnt),
-                        accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt,
-                        max_ofdm->sent_ack_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "sent_cts_cnt:",
-                        le32_to_cpu(ofdm->sent_cts_cnt),
-                        accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt,
-                        max_ofdm->sent_cts_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "sent_ba_rsp_cnt:",
-                        le32_to_cpu(ofdm->sent_ba_rsp_cnt),
-                        accum_ofdm->sent_ba_rsp_cnt,
-                        delta_ofdm->sent_ba_rsp_cnt,
-                        max_ofdm->sent_ba_rsp_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "dsp_self_kill:",
-                        le32_to_cpu(ofdm->dsp_self_kill),
-                        accum_ofdm->dsp_self_kill,
-                        delta_ofdm->dsp_self_kill,
-                        max_ofdm->dsp_self_kill);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "mh_format_err:",
-                        le32_to_cpu(ofdm->mh_format_err),
-                        accum_ofdm->mh_format_err,
-                        delta_ofdm->mh_format_err,
-                        max_ofdm->mh_format_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "re_acq_main_rssi_sum:",
-                        le32_to_cpu(ofdm->re_acq_main_rssi_sum),
-                        accum_ofdm->re_acq_main_rssi_sum,
-                        delta_ofdm->re_acq_main_rssi_sum,
-                        max_ofdm->re_acq_main_rssi_sum);
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_header, "Statistics_Rx - CCK:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "ina_cnt:",
-                        le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
-                        delta_cck->ina_cnt, max_cck->ina_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "fina_cnt:",
-                        le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
-                        delta_cck->fina_cnt, max_cck->fina_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "plcp_err:",
-                        le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
-                        delta_cck->plcp_err, max_cck->plcp_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "crc32_err:",
-                        le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
-                        delta_cck->crc32_err, max_cck->crc32_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "overrun_err:",
-                        le32_to_cpu(cck->overrun_err),
-                        accum_cck->overrun_err, delta_cck->overrun_err,
-                        max_cck->overrun_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "early_overrun_err:",
-                        le32_to_cpu(cck->early_overrun_err),
-                        accum_cck->early_overrun_err,
-                        delta_cck->early_overrun_err,
-                        max_cck->early_overrun_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "crc32_good:",
-                        le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
-                        delta_cck->crc32_good, max_cck->crc32_good);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "false_alarm_cnt:",
-                        le32_to_cpu(cck->false_alarm_cnt),
-                        accum_cck->false_alarm_cnt,
-                        delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "fina_sync_err_cnt:",
-                        le32_to_cpu(cck->fina_sync_err_cnt),
-                        accum_cck->fina_sync_err_cnt,
-                        delta_cck->fina_sync_err_cnt,
-                        max_cck->fina_sync_err_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "sfd_timeout:",
-                        le32_to_cpu(cck->sfd_timeout),
-                        accum_cck->sfd_timeout, delta_cck->sfd_timeout,
-                        max_cck->sfd_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "fina_timeout:",
-                        le32_to_cpu(cck->fina_timeout),
-                        accum_cck->fina_timeout, delta_cck->fina_timeout,
-                        max_cck->fina_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "unresponded_rts:",
-                        le32_to_cpu(cck->unresponded_rts),
-                        accum_cck->unresponded_rts, delta_cck->unresponded_rts,
-                        max_cck->unresponded_rts);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "rxe_frame_lmt_ovrun:",
-                        le32_to_cpu(cck->rxe_frame_limit_overrun),
-                        accum_cck->rxe_frame_limit_overrun,
-                        delta_cck->rxe_frame_limit_overrun,
-                        max_cck->rxe_frame_limit_overrun);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "sent_ack_cnt:",
-                        le32_to_cpu(cck->sent_ack_cnt),
-                        accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt,
-                        max_cck->sent_ack_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "sent_cts_cnt:",
-                        le32_to_cpu(cck->sent_cts_cnt),
-                        accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt,
-                        max_cck->sent_cts_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "sent_ba_rsp_cnt:",
-                        le32_to_cpu(cck->sent_ba_rsp_cnt),
-                        accum_cck->sent_ba_rsp_cnt,
-                        delta_cck->sent_ba_rsp_cnt,
-                        max_cck->sent_ba_rsp_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "dsp_self_kill:",
-                        le32_to_cpu(cck->dsp_self_kill),
-                        accum_cck->dsp_self_kill, delta_cck->dsp_self_kill,
-                        max_cck->dsp_self_kill);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "mh_format_err:",
-                        le32_to_cpu(cck->mh_format_err),
-                        accum_cck->mh_format_err, delta_cck->mh_format_err,
-                        max_cck->mh_format_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "re_acq_main_rssi_sum:",
-                        le32_to_cpu(cck->re_acq_main_rssi_sum),
-                        accum_cck->re_acq_main_rssi_sum,
-                        delta_cck->re_acq_main_rssi_sum,
-                        max_cck->re_acq_main_rssi_sum);
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_header, "Statistics_Rx - GENERAL:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "bogus_cts:",
-                        le32_to_cpu(general->bogus_cts),
-                        accum_general->bogus_cts, delta_general->bogus_cts,
-                        max_general->bogus_cts);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "bogus_ack:",
-                        le32_to_cpu(general->bogus_ack),
-                        accum_general->bogus_ack, delta_general->bogus_ack,
-                        max_general->bogus_ack);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "non_bssid_frames:",
-                        le32_to_cpu(general->non_bssid_frames),
-                        accum_general->non_bssid_frames,
-                        delta_general->non_bssid_frames,
-                        max_general->non_bssid_frames);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "filtered_frames:",
-                        le32_to_cpu(general->filtered_frames),
-                        accum_general->filtered_frames,
-                        delta_general->filtered_frames,
-                        max_general->filtered_frames);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "non_channel_beacons:",
-                        le32_to_cpu(general->non_channel_beacons),
-                        accum_general->non_channel_beacons,
-                        delta_general->non_channel_beacons,
-                        max_general->non_channel_beacons);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "channel_beacons:",
-                        le32_to_cpu(general->channel_beacons),
-                        accum_general->channel_beacons,
-                        delta_general->channel_beacons,
-                        max_general->channel_beacons);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "num_missed_bcon:",
-                        le32_to_cpu(general->num_missed_bcon),
-                        accum_general->num_missed_bcon,
-                        delta_general->num_missed_bcon,
-                        max_general->num_missed_bcon);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "adc_rx_saturation_time:",
-                        le32_to_cpu(general->adc_rx_saturation_time),
-                        accum_general->adc_rx_saturation_time,
-                        delta_general->adc_rx_saturation_time,
-                        max_general->adc_rx_saturation_time);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "ina_detect_search_tm:",
-                        le32_to_cpu(general->ina_detection_search_time),
-                        accum_general->ina_detection_search_time,
-                        delta_general->ina_detection_search_time,
-                        max_general->ina_detection_search_time);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "beacon_silence_rssi_a:",
-                        le32_to_cpu(general->beacon_silence_rssi_a),
-                        accum_general->beacon_silence_rssi_a,
-                        delta_general->beacon_silence_rssi_a,
-                        max_general->beacon_silence_rssi_a);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "beacon_silence_rssi_b:",
-                        le32_to_cpu(general->beacon_silence_rssi_b),
-                        accum_general->beacon_silence_rssi_b,
-                        delta_general->beacon_silence_rssi_b,
-                        max_general->beacon_silence_rssi_b);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "beacon_silence_rssi_c:",
-                        le32_to_cpu(general->beacon_silence_rssi_c),
-                        accum_general->beacon_silence_rssi_c,
-                        delta_general->beacon_silence_rssi_c,
-                        max_general->beacon_silence_rssi_c);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "interference_data_flag:",
-                        le32_to_cpu(general->interference_data_flag),
-                        accum_general->interference_data_flag,
-                        delta_general->interference_data_flag,
-                        max_general->interference_data_flag);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "channel_load:",
-                        le32_to_cpu(general->channel_load),
-                        accum_general->channel_load,
-                        delta_general->channel_load,
-                        max_general->channel_load);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "dsp_false_alarms:",
-                        le32_to_cpu(general->dsp_false_alarms),
-                        accum_general->dsp_false_alarms,
-                        delta_general->dsp_false_alarms,
-                        max_general->dsp_false_alarms);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "beacon_rssi_a:",
-                        le32_to_cpu(general->beacon_rssi_a),
-                        accum_general->beacon_rssi_a,
-                        delta_general->beacon_rssi_a,
-                        max_general->beacon_rssi_a);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "beacon_rssi_b:",
-                        le32_to_cpu(general->beacon_rssi_b),
-                        accum_general->beacon_rssi_b,
-                        delta_general->beacon_rssi_b,
-                        max_general->beacon_rssi_b);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "beacon_rssi_c:",
-                        le32_to_cpu(general->beacon_rssi_c),
-                        accum_general->beacon_rssi_c,
-                        delta_general->beacon_rssi_c,
-                        max_general->beacon_rssi_c);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "beacon_energy_a:",
-                        le32_to_cpu(general->beacon_energy_a),
-                        accum_general->beacon_energy_a,
-                        delta_general->beacon_energy_a,
-                        max_general->beacon_energy_a);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "beacon_energy_b:",
-                        le32_to_cpu(general->beacon_energy_b),
-                        accum_general->beacon_energy_b,
-                        delta_general->beacon_energy_b,
-                        max_general->beacon_energy_b);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "beacon_energy_c:",
-                        le32_to_cpu(general->beacon_energy_c),
-                        accum_general->beacon_energy_c,
-                        delta_general->beacon_energy_c,
-                        max_general->beacon_energy_c);
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_header, "Statistics_Rx - OFDM_HT:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "plcp_err:",
-                        le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
-                        delta_ht->plcp_err, max_ht->plcp_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "overrun_err:",
-                        le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
-                        delta_ht->overrun_err, max_ht->overrun_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "early_overrun_err:",
-                        le32_to_cpu(ht->early_overrun_err),
-                        accum_ht->early_overrun_err,
-                        delta_ht->early_overrun_err,
-                        max_ht->early_overrun_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "crc32_good:",
-                        le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
-                        delta_ht->crc32_good, max_ht->crc32_good);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "crc32_err:",
-                        le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
-                        delta_ht->crc32_err, max_ht->crc32_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "mh_format_err:",
-                        le32_to_cpu(ht->mh_format_err),
-                        accum_ht->mh_format_err,
-                        delta_ht->mh_format_err, max_ht->mh_format_err);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg_crc32_good:",
-                        le32_to_cpu(ht->agg_crc32_good),
-                        accum_ht->agg_crc32_good,
-                        delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg_mpdu_cnt:",
-                        le32_to_cpu(ht->agg_mpdu_cnt),
-                        accum_ht->agg_mpdu_cnt,
-                        delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg_cnt:",
-                        le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
-                        delta_ht->agg_cnt, max_ht->agg_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "unsupport_mcs:",
-                        le32_to_cpu(ht->unsupport_mcs),
-                        accum_ht->unsupport_mcs,
-                        delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-ssize_t iwl4965_ucode_tx_stats_read(struct file *file,
-                               char __user *user_buf,
-                               size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       char *buf;
-       int bufsz = (sizeof(struct statistics_tx) * 48) + 250;
-       ssize_t ret;
-       struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
-
-       if (!iwl_legacy_is_alive(priv))
-               return -EAGAIN;
-
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       /* the statistic information display here is based on
-         * the last statistics notification from uCode
-         * might not reflect the current uCode activity
-         */
-       tx = &priv->_4965.statistics.tx;
-       accum_tx = &priv->_4965.accum_statistics.tx;
-       delta_tx = &priv->_4965.delta_statistics.tx;
-       max_tx = &priv->_4965.max_delta.tx;
-
-       pos += iwl4965_statistics_flag(priv, buf, bufsz);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_header, "Statistics_Tx:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "preamble:",
-                        le32_to_cpu(tx->preamble_cnt),
-                        accum_tx->preamble_cnt,
-                        delta_tx->preamble_cnt, max_tx->preamble_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "rx_detected_cnt:",
-                        le32_to_cpu(tx->rx_detected_cnt),
-                        accum_tx->rx_detected_cnt,
-                        delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "bt_prio_defer_cnt:",
-                        le32_to_cpu(tx->bt_prio_defer_cnt),
-                        accum_tx->bt_prio_defer_cnt,
-                        delta_tx->bt_prio_defer_cnt,
-                        max_tx->bt_prio_defer_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "bt_prio_kill_cnt:",
-                        le32_to_cpu(tx->bt_prio_kill_cnt),
-                        accum_tx->bt_prio_kill_cnt,
-                        delta_tx->bt_prio_kill_cnt,
-                        max_tx->bt_prio_kill_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "few_bytes_cnt:",
-                        le32_to_cpu(tx->few_bytes_cnt),
-                        accum_tx->few_bytes_cnt,
-                        delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "cts_timeout:",
-                        le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
-                        delta_tx->cts_timeout, max_tx->cts_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "ack_timeout:",
-                        le32_to_cpu(tx->ack_timeout),
-                        accum_tx->ack_timeout,
-                        delta_tx->ack_timeout, max_tx->ack_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "expected_ack_cnt:",
-                        le32_to_cpu(tx->expected_ack_cnt),
-                        accum_tx->expected_ack_cnt,
-                        delta_tx->expected_ack_cnt,
-                        max_tx->expected_ack_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "actual_ack_cnt:",
-                        le32_to_cpu(tx->actual_ack_cnt),
-                        accum_tx->actual_ack_cnt,
-                        delta_tx->actual_ack_cnt,
-                        max_tx->actual_ack_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "dump_msdu_cnt:",
-                        le32_to_cpu(tx->dump_msdu_cnt),
-                        accum_tx->dump_msdu_cnt,
-                        delta_tx->dump_msdu_cnt,
-                        max_tx->dump_msdu_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "abort_nxt_frame_mismatch:",
-                        le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
-                        accum_tx->burst_abort_next_frame_mismatch_cnt,
-                        delta_tx->burst_abort_next_frame_mismatch_cnt,
-                        max_tx->burst_abort_next_frame_mismatch_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "abort_missing_nxt_frame:",
-                        le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
-                        accum_tx->burst_abort_missing_next_frame_cnt,
-                        delta_tx->burst_abort_missing_next_frame_cnt,
-                        max_tx->burst_abort_missing_next_frame_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "cts_timeout_collision:",
-                        le32_to_cpu(tx->cts_timeout_collision),
-                        accum_tx->cts_timeout_collision,
-                        delta_tx->cts_timeout_collision,
-                        max_tx->cts_timeout_collision);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "ack_ba_timeout_collision:",
-                        le32_to_cpu(tx->ack_or_ba_timeout_collision),
-                        accum_tx->ack_or_ba_timeout_collision,
-                        delta_tx->ack_or_ba_timeout_collision,
-                        max_tx->ack_or_ba_timeout_collision);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg ba_timeout:",
-                        le32_to_cpu(tx->agg.ba_timeout),
-                        accum_tx->agg.ba_timeout,
-                        delta_tx->agg.ba_timeout,
-                        max_tx->agg.ba_timeout);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg ba_resched_frames:",
-                        le32_to_cpu(tx->agg.ba_reschedule_frames),
-                        accum_tx->agg.ba_reschedule_frames,
-                        delta_tx->agg.ba_reschedule_frames,
-                        max_tx->agg.ba_reschedule_frames);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg scd_query_agg_frame:",
-                        le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
-                        accum_tx->agg.scd_query_agg_frame_cnt,
-                        delta_tx->agg.scd_query_agg_frame_cnt,
-                        max_tx->agg.scd_query_agg_frame_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg scd_query_no_agg:",
-                        le32_to_cpu(tx->agg.scd_query_no_agg),
-                        accum_tx->agg.scd_query_no_agg,
-                        delta_tx->agg.scd_query_no_agg,
-                        max_tx->agg.scd_query_no_agg);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg scd_query_agg:",
-                        le32_to_cpu(tx->agg.scd_query_agg),
-                        accum_tx->agg.scd_query_agg,
-                        delta_tx->agg.scd_query_agg,
-                        max_tx->agg.scd_query_agg);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg scd_query_mismatch:",
-                        le32_to_cpu(tx->agg.scd_query_mismatch),
-                        accum_tx->agg.scd_query_mismatch,
-                        delta_tx->agg.scd_query_mismatch,
-                        max_tx->agg.scd_query_mismatch);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg frame_not_ready:",
-                        le32_to_cpu(tx->agg.frame_not_ready),
-                        accum_tx->agg.frame_not_ready,
-                        delta_tx->agg.frame_not_ready,
-                        max_tx->agg.frame_not_ready);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg underrun:",
-                        le32_to_cpu(tx->agg.underrun),
-                        accum_tx->agg.underrun,
-                        delta_tx->agg.underrun, max_tx->agg.underrun);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg bt_prio_kill:",
-                        le32_to_cpu(tx->agg.bt_prio_kill),
-                        accum_tx->agg.bt_prio_kill,
-                        delta_tx->agg.bt_prio_kill,
-                        max_tx->agg.bt_prio_kill);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "agg rx_ba_rsp_cnt:",
-                        le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
-                        accum_tx->agg.rx_ba_rsp_cnt,
-                        delta_tx->agg.rx_ba_rsp_cnt,
-                        max_tx->agg.rx_ba_rsp_cnt);
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-ssize_t
-iwl4965_ucode_general_stats_read(struct file *file, char __user *user_buf,
-                                    size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       char *buf;
-       int bufsz = sizeof(struct statistics_general) * 10 + 300;
-       ssize_t ret;
-       struct statistics_general_common *general, *accum_general;
-       struct statistics_general_common *delta_general, *max_general;
-       struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
-       struct statistics_div *div, *accum_div, *delta_div, *max_div;
-
-       if (!iwl_legacy_is_alive(priv))
-               return -EAGAIN;
-
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       /* the statistic information display here is based on
-         * the last statistics notification from uCode
-         * might not reflect the current uCode activity
-         */
-       general = &priv->_4965.statistics.general.common;
-       dbg = &priv->_4965.statistics.general.common.dbg;
-       div = &priv->_4965.statistics.general.common.div;
-       accum_general = &priv->_4965.accum_statistics.general.common;
-       accum_dbg = &priv->_4965.accum_statistics.general.common.dbg;
-       accum_div = &priv->_4965.accum_statistics.general.common.div;
-       delta_general = &priv->_4965.delta_statistics.general.common;
-       max_general = &priv->_4965.max_delta.general.common;
-       delta_dbg = &priv->_4965.delta_statistics.general.common.dbg;
-       max_dbg = &priv->_4965.max_delta.general.common.dbg;
-       delta_div = &priv->_4965.delta_statistics.general.common.div;
-       max_div = &priv->_4965.max_delta.general.common.div;
-
-       pos += iwl4965_statistics_flag(priv, buf, bufsz);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_header, "Statistics_General:");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_value, "temperature:",
-                        le32_to_cpu(general->temperature));
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_value, "ttl_timestamp:",
-                        le32_to_cpu(general->ttl_timestamp));
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "burst_check:",
-                        le32_to_cpu(dbg->burst_check),
-                        accum_dbg->burst_check,
-                        delta_dbg->burst_check, max_dbg->burst_check);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "burst_count:",
-                        le32_to_cpu(dbg->burst_count),
-                        accum_dbg->burst_count,
-                        delta_dbg->burst_count, max_dbg->burst_count);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "wait_for_silence_timeout_count:",
-                        le32_to_cpu(dbg->wait_for_silence_timeout_cnt),
-                        accum_dbg->wait_for_silence_timeout_cnt,
-                        delta_dbg->wait_for_silence_timeout_cnt,
-                        max_dbg->wait_for_silence_timeout_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "sleep_time:",
-                        le32_to_cpu(general->sleep_time),
-                        accum_general->sleep_time,
-                        delta_general->sleep_time, max_general->sleep_time);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "slots_out:",
-                        le32_to_cpu(general->slots_out),
-                        accum_general->slots_out,
-                        delta_general->slots_out, max_general->slots_out);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "slots_idle:",
-                        le32_to_cpu(general->slots_idle),
-                        accum_general->slots_idle,
-                        delta_general->slots_idle, max_general->slots_idle);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "tx_on_a:",
-                        le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
-                        delta_div->tx_on_a, max_div->tx_on_a);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "tx_on_b:",
-                        le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
-                        delta_div->tx_on_b, max_div->tx_on_b);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "exec_time:",
-                        le32_to_cpu(div->exec_time), accum_div->exec_time,
-                        delta_div->exec_time, max_div->exec_time);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "probe_time:",
-                        le32_to_cpu(div->probe_time), accum_div->probe_time,
-                        delta_div->probe_time, max_div->probe_time);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "rx_enable_counter:",
-                        le32_to_cpu(general->rx_enable_counter),
-                        accum_general->rx_enable_counter,
-                        delta_general->rx_enable_counter,
-                        max_general->rx_enable_counter);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                        fmt_table, "num_of_sos_states:",
-                        le32_to_cpu(general->num_of_sos_states),
-                        accum_general->num_of_sos_states,
-                        delta_general->num_of_sos_states,
-                        max_general->num_of_sos_states);
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.h b/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.h
deleted file mode 100644 (file)
index 6c8e353..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-debug.h"
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-ssize_t iwl4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
-                               size_t count, loff_t *ppos);
-ssize_t iwl4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
-                               size_t count, loff_t *ppos);
-ssize_t iwl4965_ucode_general_stats_read(struct file *file,
-                       char __user *user_buf, size_t count, loff_t *ppos);
-#else
-static ssize_t
-iwl4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
-                                      size_t count, loff_t *ppos)
-{
-       return 0;
-}
-static ssize_t
-iwl4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
-                                      size_t count, loff_t *ppos)
-{
-       return 0;
-}
-static ssize_t
-iwl4965_ucode_general_stats_read(struct file *file, char __user *user_buf,
-                                           size_t count, loff_t *ppos)
-{
-       return 0;
-}
-#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-eeprom.c b/drivers/net/wireless/iwlegacy/iwl-4965-eeprom.c
deleted file mode 100644 (file)
index cb9baab..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/******************************************************************************
- *
- * 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) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 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.
- *****************************************************************************/
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include <net/mac80211.h>
-
-#include "iwl-commands.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-debug.h"
-#include "iwl-4965.h"
-#include "iwl-io.h"
-
-/******************************************************************************
- *
- * EEPROM related functions
- *
-******************************************************************************/
-
-/*
- * The device's EEPROM semaphore prevents conflicts between driver and uCode
- * when accessing the EEPROM; each access is a series of pulses to/from the
- * EEPROM chip, not a single event, so even reads could conflict if they
- * weren't arbitrated by the semaphore.
- */
-int iwl4965_eeprom_acquire_semaphore(struct iwl_priv *priv)
-{
-       u16 count;
-       int ret;
-
-       for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
-               /* Request semaphore */
-               iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                           CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-
-               /* See if we got it */
-               ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
-                               CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
-                               CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
-                               EEPROM_SEM_TIMEOUT);
-               if (ret >= 0) {
-                       IWL_DEBUG_IO(priv,
-                               "Acquired semaphore after %d tries.\n",
-                               count+1);
-                       return ret;
-               }
-       }
-
-       return ret;
-}
-
-void iwl4965_eeprom_release_semaphore(struct iwl_priv *priv)
-{
-       iwl_legacy_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-               CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-
-}
-
-int iwl4965_eeprom_check_version(struct iwl_priv *priv)
-{
-       u16 eeprom_ver;
-       u16 calib_ver;
-
-       eeprom_ver = iwl_legacy_eeprom_query16(priv, EEPROM_VERSION);
-       calib_ver = iwl_legacy_eeprom_query16(priv,
-                       EEPROM_4965_CALIB_VERSION_OFFSET);
-
-       if (eeprom_ver < priv->cfg->eeprom_ver ||
-           calib_ver < priv->cfg->eeprom_calib_ver)
-               goto err;
-
-       IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
-                eeprom_ver, calib_ver);
-
-       return 0;
-err:
-       IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
-                 "CALIB=0x%x < 0x%x\n",
-                 eeprom_ver, priv->cfg->eeprom_ver,
-                 calib_ver,  priv->cfg->eeprom_calib_ver);
-       return -EINVAL;
-
-}
-
-void iwl4965_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
-{
-       const u8 *addr = iwl_legacy_eeprom_query_addr(priv,
-                                       EEPROM_MAC_ADDRESS);
-       memcpy(mac, addr, ETH_ALEN);
-}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-hw.h b/drivers/net/wireless/iwlegacy/iwl-4965-hw.h
deleted file mode 100644 (file)
index fc6fa28..0000000
+++ /dev/null
@@ -1,811 +0,0 @@
-/******************************************************************************
- *
- * 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 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 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.
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-4965-hw.h) only for hardware-related definitions.
- * Use iwl-commands.h for uCode API definitions.
- * Use iwl-dev.h for driver implementation definitions.
- */
-
-#ifndef __iwl_4965_hw_h__
-#define __iwl_4965_hw_h__
-
-#include "iwl-fh.h"
-
-/* EEPROM */
-#define IWL4965_EEPROM_IMG_SIZE                        1024
-
-/*
- * uCode queue management definitions ...
- * The first queue used for block-ack aggregation is #7 (4965 only).
- * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7.
- */
-#define IWL49_FIRST_AMPDU_QUEUE        7
-
-/* Sizes and addresses for instruction and data memory (SRAM) in
- * 4965's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
-#define IWL49_RTC_INST_LOWER_BOUND             (0x000000)
-#define IWL49_RTC_INST_UPPER_BOUND             (0x018000)
-
-#define IWL49_RTC_DATA_LOWER_BOUND             (0x800000)
-#define IWL49_RTC_DATA_UPPER_BOUND             (0x80A000)
-
-#define IWL49_RTC_INST_SIZE  (IWL49_RTC_INST_UPPER_BOUND - \
-                               IWL49_RTC_INST_LOWER_BOUND)
-#define IWL49_RTC_DATA_SIZE  (IWL49_RTC_DATA_UPPER_BOUND - \
-                               IWL49_RTC_DATA_LOWER_BOUND)
-
-#define IWL49_MAX_INST_SIZE IWL49_RTC_INST_SIZE
-#define IWL49_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
-
-/* Size of uCode instruction memory in bootstrap state machine */
-#define IWL49_MAX_BSM_SIZE BSM_SRAM_SIZE
-
-static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
-{
-       return (addr >= IWL49_RTC_DATA_LOWER_BOUND) &&
-              (addr < IWL49_RTC_DATA_UPPER_BOUND);
-}
-
-/********************* START TEMPERATURE *************************************/
-
-/**
- * 4965 temperature calculation.
- *
- * The driver must calculate the device temperature before calculating
- * a txpower setting (amplifier gain is temperature dependent).  The
- * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration
- * values used for the life of the driver, and one of which (R4) is the
- * real-time temperature indicator.
- *
- * uCode provides all 4 values to the driver via the "initialize alive"
- * notification (see struct iwl4965_init_alive_resp).  After the runtime uCode
- * image loads, uCode updates the R4 value via statistics notifications
- * (see STATISTICS_NOTIFICATION), which occur after each received beacon
- * when associated, or can be requested via REPLY_STATISTICS_CMD.
- *
- * NOTE:  uCode provides the R4 value as a 23-bit signed value.  Driver
- *        must sign-extend to 32 bits before applying formula below.
- *
- * Formula:
- *
- * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8
- *
- * NOTE:  The basic formula is 259 * (R4-R2) / (R3-R1).  The 97/100 is
- * an additional correction, which should be centered around 0 degrees
- * Celsius (273 degrees Kelvin).  The 8 (3 percent of 273) compensates for
- * centering the 97/100 correction around 0 degrees K.
- *
- * Add 273 to Kelvin value to find degrees Celsius, for comparing current
- * temperature with factory-measured temperatures when calculating txpower
- * settings.
- */
-#define TEMPERATURE_CALIB_KELVIN_OFFSET 8
-#define TEMPERATURE_CALIB_A_VAL 259
-
-/* Limit range of calculated temperature to be between these Kelvin values */
-#define IWL_TX_POWER_TEMPERATURE_MIN  (263)
-#define IWL_TX_POWER_TEMPERATURE_MAX  (410)
-
-#define IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(t) \
-       (((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \
-        ((t) > IWL_TX_POWER_TEMPERATURE_MAX))
-
-/********************* END TEMPERATURE ***************************************/
-
-/********************* START TXPOWER *****************************************/
-
-/**
- * 4965 txpower calculations rely on information from three sources:
- *
- *     1) EEPROM
- *     2) "initialize" alive notification
- *     3) statistics notifications
- *
- * EEPROM data consists of:
- *
- * 1)  Regulatory information (max txpower and channel usage flags) is provided
- *     separately for each channel that can possibly supported by 4965.
- *     40 MHz wide (.11n HT40) channels are listed separately from 20 MHz
- *     (legacy) channels.
- *
- *     See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom
- *     for locations in EEPROM.
- *
- * 2)  Factory txpower calibration information is provided separately for
- *     sub-bands of contiguous channels.  2.4GHz has just one sub-band,
- *     but 5 GHz has several sub-bands.
- *
- *     In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided.
- *
- *     See struct iwl4965_eeprom_calib_info (and the tree of structures
- *     contained within it) for format, and struct iwl4965_eeprom for
- *     locations in EEPROM.
- *
- * "Initialization alive" notification (see struct iwl4965_init_alive_resp)
- * consists of:
- *
- * 1)  Temperature calculation parameters.
- *
- * 2)  Power supply voltage measurement.
- *
- * 3)  Tx gain compensation to balance 2 transmitters for MIMO use.
- *
- * Statistics notifications deliver:
- *
- * 1)  Current values for temperature param R4.
- */
-
-/**
- * To calculate a txpower setting for a given desired target txpower, channel,
- * modulation bit rate, and transmitter chain (4965 has 2 transmitters to
- * support MIMO and transmit diversity), driver must do the following:
- *
- * 1)  Compare desired txpower vs. (EEPROM) regulatory limit for this channel.
- *     Do not exceed regulatory limit; reduce target txpower if necessary.
- *
- *     If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
- *     2 transmitters will be used simultaneously; driver must reduce the
- *     regulatory limit by 3 dB (half-power) for each transmitter, so the
- *     combined total output of the 2 transmitters is within regulatory limits.
- *
- *
- * 2)  Compare target txpower vs. (EEPROM) saturation txpower *reduced by
- *     backoff for this bit rate*.  Do not exceed (saturation - backoff[rate]);
- *     reduce target txpower if necessary.
- *
- *     Backoff values below are in 1/2 dB units (equivalent to steps in
- *     txpower gain tables):
- *
- *     OFDM 6 - 36 MBit:  10 steps (5 dB)
- *     OFDM 48 MBit:      15 steps (7.5 dB)
- *     OFDM 54 MBit:      17 steps (8.5 dB)
- *     OFDM 60 MBit:      20 steps (10 dB)
- *     CCK all rates:     10 steps (5 dB)
- *
- *     Backoff values apply to saturation txpower on a per-transmitter basis;
- *     when using MIMO (2 transmitters), each transmitter uses the same
- *     saturation level provided in EEPROM, and the same backoff values;
- *     no reduction (such as with regulatory txpower limits) is required.
- *
- *     Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
- *     widths and 40 Mhz (.11n HT40) channel widths; there is no separate
- *     factory measurement for ht40 channels.
- *
- *     The result of this step is the final target txpower.  The rest of
- *     the steps figure out the proper settings for the device to achieve
- *     that target txpower.
- *
- *
- * 3)  Determine (EEPROM) calibration sub band for the target channel, by
- *     comparing against first and last channels in each sub band
- *     (see struct iwl4965_eeprom_calib_subband_info).
- *
- *
- * 4)  Linearly interpolate (EEPROM) factory calibration measurement sets,
- *     referencing the 2 factory-measured (sample) channels within the sub band.
- *
- *     Interpolation is based on difference between target channel's frequency
- *     and the sample channels' frequencies.  Since channel numbers are based
- *     on frequency (5 MHz between each channel number), this is equivalent
- *     to interpolating based on channel number differences.
- *
- *     Note that the sample channels may or may not be the channels at the
- *     edges of the sub band.  The target channel may be "outside" of the
- *     span of the sampled channels.
- *
- *     Driver may choose the pair (for 2 Tx chains) of measurements (see
- *     struct iwl4965_eeprom_calib_ch_info) for which the actual measured
- *     txpower comes closest to the desired txpower.  Usually, though,
- *     the middle set of measurements is closest to the regulatory limits,
- *     and is therefore a good choice for all txpower calculations (this
- *     assumes that high accuracy is needed for maximizing legal txpower,
- *     while lower txpower configurations do not need as much accuracy).
- *
- *     Driver should interpolate both members of the chosen measurement pair,
- *     i.e. for both Tx chains (radio transmitters), unless the driver knows
- *     that only one of the chains will be used (e.g. only one tx antenna
- *     connected, but this should be unusual).  The rate scaling algorithm
- *     switches antennas to find best performance, so both Tx chains will
- *     be used (although only one at a time) even for non-MIMO transmissions.
- *
- *     Driver should interpolate factory values for temperature, gain table
- *     index, and actual power.  The power amplifier detector values are
- *     not used by the driver.
- *
- *     Sanity check:  If the target channel happens to be one of the sample
- *     channels, the results should agree with the sample channel's
- *     measurements!
- *
- *
- * 5)  Find difference between desired txpower and (interpolated)
- *     factory-measured txpower.  Using (interpolated) factory gain table index
- *     (shown elsewhere) as a starting point, adjust this index lower to
- *     increase txpower, or higher to decrease txpower, until the target
- *     txpower is reached.  Each step in the gain table is 1/2 dB.
- *
- *     For example, if factory measured txpower is 16 dBm, and target txpower
- *     is 13 dBm, add 6 steps to the factory gain index to reduce txpower
- *     by 3 dB.
- *
- *
- * 6)  Find difference between current device temperature and (interpolated)
- *     factory-measured temperature for sub-band.  Factory values are in
- *     degrees Celsius.  To calculate current temperature, see comments for
- *     "4965 temperature calculation".
- *
- *     If current temperature is higher than factory temperature, driver must
- *     increase gain (lower gain table index), and vice verse.
- *
- *     Temperature affects gain differently for different channels:
- *
- *     2.4 GHz all channels:  3.5 degrees per half-dB step
- *     5 GHz channels 34-43:  4.5 degrees per half-dB step
- *     5 GHz channels >= 44:  4.0 degrees per half-dB step
- *
- *     NOTE:  Temperature can increase rapidly when transmitting, especially
- *            with heavy traffic at high txpowers.  Driver should update
- *            temperature calculations often under these conditions to
- *            maintain strong txpower in the face of rising temperature.
- *
- *
- * 7)  Find difference between current power supply voltage indicator
- *     (from "initialize alive") and factory-measured power supply voltage
- *     indicator (EEPROM).
- *
- *     If the current voltage is higher (indicator is lower) than factory
- *     voltage, gain should be reduced (gain table index increased) by:
- *
- *     (eeprom - current) / 7
- *
- *     If the current voltage is lower (indicator is higher) than factory
- *     voltage, gain should be increased (gain table index decreased) by:
- *
- *     2 * (current - eeprom) / 7
- *
- *     If number of index steps in either direction turns out to be > 2,
- *     something is wrong ... just use 0.
- *
- *     NOTE:  Voltage compensation is independent of band/channel.
- *
- *     NOTE:  "Initialize" uCode measures current voltage, which is assumed
- *            to be constant after this initial measurement.  Voltage
- *            compensation for txpower (number of steps in gain table)
- *            may be calculated once and used until the next uCode bootload.
- *
- *
- * 8)  If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
- *     adjust txpower for each transmitter chain, so txpower is balanced
- *     between the two chains.  There are 5 pairs of tx_atten[group][chain]
- *     values in "initialize alive", one pair for each of 5 channel ranges:
- *
- *     Group 0:  5 GHz channel 34-43
- *     Group 1:  5 GHz channel 44-70
- *     Group 2:  5 GHz channel 71-124
- *     Group 3:  5 GHz channel 125-200
- *     Group 4:  2.4 GHz all channels
- *
- *     Add the tx_atten[group][chain] value to the index for the target chain.
- *     The values are signed, but are in pairs of 0 and a non-negative number,
- *     so as to reduce gain (if necessary) of the "hotter" channel.  This
- *     avoids any need to double-check for regulatory compliance after
- *     this step.
- *
- *
- * 9)  If setting up for a CCK rate, lower the gain by adding a CCK compensation
- *     value to the index:
- *
- *     Hardware rev B:  9 steps (4.5 dB)
- *     Hardware rev C:  5 steps (2.5 dB)
- *
- *     Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
- *     bits [3:2], 1 = B, 2 = C.
- *
- *     NOTE:  This compensation is in addition to any saturation backoff that
- *            might have been applied in an earlier step.
- *
- *
- * 10) Select the gain table, based on band (2.4 vs 5 GHz).
- *
- *     Limit the adjusted index to stay within the table!
- *
- *
- * 11) Read gain table entries for DSP and radio gain, place into appropriate
- *     location(s) in command (struct iwl4965_txpowertable_cmd).
- */
-
-/**
- * When MIMO is used (2 transmitters operating simultaneously), driver should
- * limit each transmitter to deliver a max of 3 dB below the regulatory limit
- * for the device.  That is, use half power for each transmitter, so total
- * txpower is within regulatory limits.
- *
- * The value "6" represents number of steps in gain table to reduce power 3 dB.
- * Each step is 1/2 dB.
- */
-#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6)
-
-/**
- * CCK gain compensation.
- *
- * When calculating txpowers for CCK, after making sure that the target power
- * is within regulatory and saturation limits, driver must additionally
- * back off gain by adding these values to the gain table index.
- *
- * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
- * bits [3:2], 1 = B, 2 = C.
- */
-#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
-#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
-
-/*
- * 4965 power supply voltage compensation for txpower
- */
-#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V   (7)
-
-/**
- * Gain tables.
- *
- * The following tables contain pair of values for setting txpower, i.e.
- * gain settings for the output of the device's digital signal processor (DSP),
- * and for the analog gain structure of the transmitter.
- *
- * Each entry in the gain tables represents a step of 1/2 dB.  Note that these
- * are *relative* steps, not indications of absolute output power.  Output
- * power varies with temperature, voltage, and channel frequency, and also
- * requires consideration of average power (to satisfy regulatory constraints),
- * and peak power (to avoid distortion of the output signal).
- *
- * Each entry contains two values:
- * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
- *     linear value that multiplies the output of the digital signal processor,
- *     before being sent to the analog radio.
- * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
- *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
- *
- * EEPROM contains factory calibration data for txpower.  This maps actual
- * measured txpower levels to gain settings in the "well known" tables
- * below ("well-known" means here that both factory calibration *and* the
- * driver work with the same table).
- *
- * There are separate tables for 2.4 GHz and 5 GHz bands.  The 5 GHz table
- * has an extension (into negative indexes), in case the driver needs to
- * boost power setting for high device temperatures (higher than would be
- * present during factory calibration).  A 5 Ghz EEPROM index of "40"
- * corresponds to the 49th entry in the table used by the driver.
- */
-#define MIN_TX_GAIN_INDEX              (0)  /* highest gain, lowest idx, 2.4 */
-#define MIN_TX_GAIN_INDEX_52GHZ_EXT    (-9) /* highest gain, lowest idx, 5 */
-
-/**
- * 2.4 GHz gain table
- *
- * Index    Dsp gain   Radio gain
- *   0        110         0x3f      (highest gain)
- *   1        104         0x3f
- *   2         98         0x3f
- *   3        110         0x3e
- *   4        104         0x3e
- *   5         98         0x3e
- *   6        110         0x3d
- *   7        104         0x3d
- *   8         98         0x3d
- *   9        110         0x3c
- *  10        104         0x3c
- *  11         98         0x3c
- *  12        110         0x3b
- *  13        104         0x3b
- *  14         98         0x3b
- *  15        110         0x3a
- *  16        104         0x3a
- *  17         98         0x3a
- *  18        110         0x39
- *  19        104         0x39
- *  20         98         0x39
- *  21        110         0x38
- *  22        104         0x38
- *  23         98         0x38
- *  24        110         0x37
- *  25        104         0x37
- *  26         98         0x37
- *  27        110         0x36
- *  28        104         0x36
- *  29         98         0x36
- *  30        110         0x35
- *  31        104         0x35
- *  32         98         0x35
- *  33        110         0x34
- *  34        104         0x34
- *  35         98         0x34
- *  36        110         0x33
- *  37        104         0x33
- *  38         98         0x33
- *  39        110         0x32
- *  40        104         0x32
- *  41         98         0x32
- *  42        110         0x31
- *  43        104         0x31
- *  44         98         0x31
- *  45        110         0x30
- *  46        104         0x30
- *  47         98         0x30
- *  48        110          0x6
- *  49        104          0x6
- *  50         98          0x6
- *  51        110          0x5
- *  52        104          0x5
- *  53         98          0x5
- *  54        110          0x4
- *  55        104          0x4
- *  56         98          0x4
- *  57        110          0x3
- *  58        104          0x3
- *  59         98          0x3
- *  60        110          0x2
- *  61        104          0x2
- *  62         98          0x2
- *  63        110          0x1
- *  64        104          0x1
- *  65         98          0x1
- *  66        110          0x0
- *  67        104          0x0
- *  68         98          0x0
- *  69         97            0
- *  70         96            0
- *  71         95            0
- *  72         94            0
- *  73         93            0
- *  74         92            0
- *  75         91            0
- *  76         90            0
- *  77         89            0
- *  78         88            0
- *  79         87            0
- *  80         86            0
- *  81         85            0
- *  82         84            0
- *  83         83            0
- *  84         82            0
- *  85         81            0
- *  86         80            0
- *  87         79            0
- *  88         78            0
- *  89         77            0
- *  90         76            0
- *  91         75            0
- *  92         74            0
- *  93         73            0
- *  94         72            0
- *  95         71            0
- *  96         70            0
- *  97         69            0
- *  98         68            0
- */
-
-/**
- * 5 GHz gain table
- *
- * Index    Dsp gain   Radio gain
- *  -9               123         0x3F      (highest gain)
- *  -8               117         0x3F
- *  -7        110         0x3F
- *  -6        104         0x3F
- *  -5         98         0x3F
- *  -4        110         0x3E
- *  -3        104         0x3E
- *  -2         98         0x3E
- *  -1        110         0x3D
- *   0        104         0x3D
- *   1         98         0x3D
- *   2        110         0x3C
- *   3        104         0x3C
- *   4         98         0x3C
- *   5        110         0x3B
- *   6        104         0x3B
- *   7         98         0x3B
- *   8        110         0x3A
- *   9        104         0x3A
- *  10         98         0x3A
- *  11        110         0x39
- *  12        104         0x39
- *  13         98         0x39
- *  14        110         0x38
- *  15        104         0x38
- *  16         98         0x38
- *  17        110         0x37
- *  18        104         0x37
- *  19         98         0x37
- *  20        110         0x36
- *  21        104         0x36
- *  22         98         0x36
- *  23        110         0x35
- *  24        104         0x35
- *  25         98         0x35
- *  26        110         0x34
- *  27        104         0x34
- *  28         98         0x34
- *  29        110         0x33
- *  30        104         0x33
- *  31         98         0x33
- *  32        110         0x32
- *  33        104         0x32
- *  34         98         0x32
- *  35        110         0x31
- *  36        104         0x31
- *  37         98         0x31
- *  38        110         0x30
- *  39        104         0x30
- *  40         98         0x30
- *  41        110         0x25
- *  42        104         0x25
- *  43         98         0x25
- *  44        110         0x24
- *  45        104         0x24
- *  46         98         0x24
- *  47        110         0x23
- *  48        104         0x23
- *  49         98         0x23
- *  50        110         0x22
- *  51        104         0x18
- *  52         98         0x18
- *  53        110         0x17
- *  54        104         0x17
- *  55         98         0x17
- *  56        110         0x16
- *  57        104         0x16
- *  58         98         0x16
- *  59        110         0x15
- *  60        104         0x15
- *  61         98         0x15
- *  62        110         0x14
- *  63        104         0x14
- *  64         98         0x14
- *  65        110         0x13
- *  66        104         0x13
- *  67         98         0x13
- *  68        110         0x12
- *  69        104         0x08
- *  70         98         0x08
- *  71        110         0x07
- *  72        104         0x07
- *  73         98         0x07
- *  74        110         0x06
- *  75        104         0x06
- *  76         98         0x06
- *  77        110         0x05
- *  78        104         0x05
- *  79         98         0x05
- *  80        110         0x04
- *  81        104         0x04
- *  82         98         0x04
- *  83        110         0x03
- *  84        104         0x03
- *  85         98         0x03
- *  86        110         0x02
- *  87        104         0x02
- *  88         98         0x02
- *  89        110         0x01
- *  90        104         0x01
- *  91         98         0x01
- *  92        110         0x00
- *  93        104         0x00
- *  94         98         0x00
- *  95         93         0x00
- *  96         88         0x00
- *  97         83         0x00
- *  98         78         0x00
- */
-
-
-/**
- * Sanity checks and default values for EEPROM regulatory levels.
- * If EEPROM values fall outside MIN/MAX range, use default values.
- *
- * Regulatory limits refer to the maximum average txpower allowed by
- * regulatory agencies in the geographies in which the device is meant
- * to be operated.  These limits are SKU-specific (i.e. geography-specific),
- * and channel-specific; each channel has an individual regulatory limit
- * listed in the EEPROM.
- *
- * Units are in half-dBm (i.e. "34" means 17 dBm).
- */
-#define IWL_TX_POWER_DEFAULT_REGULATORY_24   (34)
-#define IWL_TX_POWER_DEFAULT_REGULATORY_52   (34)
-#define IWL_TX_POWER_REGULATORY_MIN          (0)
-#define IWL_TX_POWER_REGULATORY_MAX          (34)
-
-/**
- * Sanity checks and default values for EEPROM saturation levels.
- * If EEPROM values fall outside MIN/MAX range, use default values.
- *
- * Saturation is the highest level that the output power amplifier can produce
- * without significant clipping distortion.  This is a "peak" power level.
- * Different types of modulation (i.e. various "rates", and OFDM vs. CCK)
- * require differing amounts of backoff, relative to their average power output,
- * in order to avoid clipping distortion.
- *
- * Driver must make sure that it is violating neither the saturation limit,
- * nor the regulatory limit, when calculating Tx power settings for various
- * rates.
- *
- * Units are in half-dBm (i.e. "38" means 19 dBm).
- */
-#define IWL_TX_POWER_DEFAULT_SATURATION_24   (38)
-#define IWL_TX_POWER_DEFAULT_SATURATION_52   (38)
-#define IWL_TX_POWER_SATURATION_MIN          (20)
-#define IWL_TX_POWER_SATURATION_MAX          (50)
-
-/**
- * Channel groups used for Tx Attenuation calibration (MIMO tx channel balance)
- * and thermal Txpower calibration.
- *
- * When calculating txpower, driver must compensate for current device
- * temperature; higher temperature requires higher gain.  Driver must calculate
- * current temperature (see "4965 temperature calculation"), then compare vs.
- * factory calibration temperature in EEPROM; if current temperature is higher
- * than factory temperature, driver must *increase* gain by proportions shown
- * in table below.  If current temperature is lower than factory, driver must
- * *decrease* gain.
- *
- * Different frequency ranges require different compensation, as shown below.
- */
-/* Group 0, 5.2 GHz ch 34-43:  4.5 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR1_FCH 34
-#define CALIB_IWL_TX_ATTEN_GR1_LCH 43
-
-/* Group 1, 5.3 GHz ch 44-70:  4.0 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR2_FCH 44
-#define CALIB_IWL_TX_ATTEN_GR2_LCH 70
-
-/* Group 2, 5.5 GHz ch 71-124:  4.0 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR3_FCH 71
-#define CALIB_IWL_TX_ATTEN_GR3_LCH 124
-
-/* Group 3, 5.7 GHz ch 125-200:  4.0 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR4_FCH 125
-#define CALIB_IWL_TX_ATTEN_GR4_LCH 200
-
-/* Group 4, 2.4 GHz all channels:  3.5 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR5_FCH 1
-#define CALIB_IWL_TX_ATTEN_GR5_LCH 20
-
-enum {
-       CALIB_CH_GROUP_1 = 0,
-       CALIB_CH_GROUP_2 = 1,
-       CALIB_CH_GROUP_3 = 2,
-       CALIB_CH_GROUP_4 = 3,
-       CALIB_CH_GROUP_5 = 4,
-       CALIB_CH_GROUP_MAX
-};
-
-/********************* END TXPOWER *****************************************/
-
-
-/**
- * Tx/Rx Queues
- *
- * Most communication between driver and 4965 is via queues of data buffers.
- * For example, all commands that the driver issues to device's embedded
- * controller (uCode) are via the command queue (one of the Tx queues).  All
- * uCode command responses/replies/notifications, including Rx frames, are
- * conveyed from uCode to driver via the Rx queue.
- *
- * Most support for these queues, including handshake support, resides in
- * structures in host DRAM, shared between the driver and the device.  When
- * allocating this memory, the driver must make sure that data written by
- * the host CPU updates DRAM immediately (and does not get "stuck" in CPU's
- * cache memory), so DRAM and cache are consistent, and the device can
- * immediately see changes made by the driver.
- *
- * 4965 supports up to 16 DRAM-based Tx queues, and services these queues via
- * up to 7 DMA channels (FIFOs).  Each Tx queue is supported by a circular array
- * in DRAM containing 256 Transmit Frame Descriptors (TFDs).
- */
-#define IWL49_NUM_FIFOS        7
-#define IWL49_CMD_FIFO_NUM     4
-#define IWL49_NUM_QUEUES       16
-#define IWL49_NUM_AMPDU_QUEUES 8
-
-
-/**
- * struct iwl4965_schedq_bc_tbl
- *
- * Byte Count table
- *
- * Each Tx queue uses a byte-count table containing 320 entries:
- * one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that
- * duplicate the first 64 entries (to avoid wrap-around within a Tx window;
- * max Tx window is 64 TFDs).
- *
- * When driver sets up a new TFD, it must also enter the total byte count
- * of the frame to be transmitted into the corresponding entry in the byte
- * count table for the chosen Tx queue.  If the TFD index is 0-63, the driver
- * must duplicate the byte count entry in corresponding index 256-319.
- *
- * padding puts each byte count table on a 1024-byte boundary;
- * 4965 assumes tables are separated by 1024 bytes.
- */
-struct iwl4965_scd_bc_tbl {
-       __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
-       u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
-} __packed;
-
-
-#define IWL4965_RTC_INST_LOWER_BOUND           (0x000000)
-
-/* RSSI to dBm */
-#define IWL4965_RSSI_OFFSET    44
-
-/* PCI registers */
-#define PCI_CFG_RETRY_TIMEOUT  0x041
-
-/* PCI register values */
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN   0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN    0x02
-
-#define IWL4965_DEFAULT_TX_RETRY  15
-
-/* EEPROM */
-#define IWL4965_FIRST_AMPDU_QUEUE      10
-
-
-#endif /* !__iwl_4965_hw_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-led.c b/drivers/net/wireless/iwlegacy/iwl-4965-led.c
deleted file mode 100644 (file)
index 6862fdc..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.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 <net/mac80211.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include "iwl-commands.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-4965-led.h"
-
-/* Send led command */
-static int
-iwl4965_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
-{
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_LEDS_CMD,
-               .len = sizeof(struct iwl_led_cmd),
-               .data = led_cmd,
-               .flags = CMD_ASYNC,
-               .callback = NULL,
-       };
-       u32 reg;
-
-       reg = iwl_read32(priv, CSR_LED_REG);
-       if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
-               iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
-
-       return iwl_legacy_send_cmd(priv, &cmd);
-}
-
-/* Set led register off */
-void iwl4965_led_enable(struct iwl_priv *priv)
-{
-       iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
-}
-
-const struct iwl_led_ops iwl4965_led_ops = {
-       .cmd = iwl4965_send_led_cmd,
-};
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-led.h b/drivers/net/wireless/iwlegacy/iwl-4965-led.h
deleted file mode 100644 (file)
index 5ed3615..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_4965_led_h__
-#define __iwl_4965_led_h__
-
-extern const struct iwl_led_ops iwl4965_led_ops;
-void iwl4965_led_enable(struct iwl_priv *priv);
-
-#endif /* __iwl_4965_led_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
deleted file mode 100644 (file)
index 2be6d9e..0000000
+++ /dev/null
@@ -1,1194 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-#include <linux/etherdevice.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-4965-hw.h"
-#include "iwl-4965.h"
-#include "iwl-sta.h"
-
-void iwl4965_check_abort_status(struct iwl_priv *priv,
-                           u8 frame_count, u32 status)
-{
-       if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
-               IWL_ERR(priv, "Tx flush command to flush out all frames\n");
-               if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
-                       queue_work(priv->workqueue, &priv->tx_flush);
-       }
-}
-
-/*
- * EEPROM
- */
-struct iwl_mod_params iwl4965_mod_params = {
-       .amsdu_size_8K = 1,
-       .restart_fw = 1,
-       /* the rest are 0 by default */
-};
-
-void iwl4965_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].page != NULL) {
-                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-                       __iwl_legacy_free_pages(priv, rxq->pool[i].page);
-                       rxq->pool[i].page = NULL;
-               }
-               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-       }
-
-       for (i = 0; i < RX_QUEUE_SIZE; i++)
-               rxq->queue[i] = NULL;
-
-       /* 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->write_actual = 0;
-       rxq->free_count = 0;
-       spin_unlock_irqrestore(&rxq->lock, flags);
-}
-
-int iwl4965_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-       u32 rb_size;
-       const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
-       u32 rb_timeout = 0;
-
-       if (priv->cfg->mod_params->amsdu_size_8K)
-               rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
-       else
-               rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
-
-       /* Stop Rx DMA */
-       iwl_legacy_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-
-       /* Reset driver's Rx queue write index */
-       iwl_legacy_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
-
-       /* Tell device where to find RBD circular buffer in DRAM */
-       iwl_legacy_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
-                          (u32)(rxq->bd_dma >> 8));
-
-       /* Tell device where in DRAM to update its Rx status */
-       iwl_legacy_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
-                          rxq->rb_stts_dma >> 4);
-
-       /* Enable Rx DMA
-        * Direct rx interrupts to hosts
-        * Rx buffer size 4 or 8k
-        * RB timeout 0x10
-        * 256 RBDs
-        */
-       iwl_legacy_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
-                          FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
-                          FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
-                          FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
-                          rb_size|
-                          (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
-                          (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
-
-       /* Set interrupt coalescing timer to default (2048 usecs) */
-       iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
-
-       return 0;
-}
-
-static void iwl4965_set_pwr_vmain(struct iwl_priv *priv)
-{
-/*
- * (for documentation purposes)
- * to set power to V_AUX, do:
-
-               if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
-                       iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-                                              APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
-                                              ~APMG_PS_CTRL_MSK_PWR_SRC);
- */
-
-       iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-                              APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
-                              ~APMG_PS_CTRL_MSK_PWR_SRC);
-}
-
-int iwl4965_hw_nic_init(struct iwl_priv *priv)
-{
-       unsigned long flags;
-       struct iwl_rx_queue *rxq = &priv->rxq;
-       int ret;
-
-       /* nic_init */
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->cfg->ops->lib->apm_ops.init(priv);
-
-       /* Set interrupt coalescing calibration timer to default (512 usecs) */
-       iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       iwl4965_set_pwr_vmain(priv);
-
-       priv->cfg->ops->lib->apm_ops.config(priv);
-
-       /* Allocate the RX queue, or reset if it is already allocated */
-       if (!rxq->bd) {
-               ret = iwl_legacy_rx_queue_alloc(priv);
-               if (ret) {
-                       IWL_ERR(priv, "Unable to initialize Rx queue\n");
-                       return -ENOMEM;
-               }
-       } else
-               iwl4965_rx_queue_reset(priv, rxq);
-
-       iwl4965_rx_replenish(priv);
-
-       iwl4965_rx_init(priv, rxq);
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       rxq->need_update = 1;
-       iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* Allocate or reset and init all Tx and Command queues */
-       if (!priv->txq) {
-               ret = iwl4965_txq_ctx_alloc(priv);
-               if (ret)
-                       return ret;
-       } else
-               iwl4965_txq_ctx_reset(priv);
-
-       set_bit(STATUS_INIT, &priv->status);
-
-       return 0;
-}
-
-/**
- * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
-static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl_priv *priv,
-                                         dma_addr_t dma_addr)
-{
-       return cpu_to_le32((u32)(dma_addr >> 8));
-}
-
-/**
- * iwl4965_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.
- */
-void iwl4965_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;
-
-       spin_lock_irqsave(&rxq->lock, flags);
-       while ((iwl_legacy_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
-               /* The overwritten rxb must be a used one */
-               rxb = rxq->queue[rxq->write];
-               BUG_ON(rxb && rxb->page);
-
-               /* Get next free Rx buffer, remove from free list */
-               element = rxq->rx_free.next;
-               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-               list_del(element);
-
-               /* Point to Rx buffer via next RBD in circular buffer */
-               rxq->bd[rxq->write] = iwl4965_dma_addr2rbd_ptr(priv,
-                                                             rxb->page_dma);
-               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.
-        * Increment device's write pointer in multiples of 8. */
-       if (rxq->write_actual != (rxq->write & ~0x7)) {
-               spin_lock_irqsave(&rxq->lock, flags);
-               rxq->need_update = 1;
-               spin_unlock_irqrestore(&rxq->lock, flags);
-               iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
-       }
-}
-
-/**
- * iwl4965_rx_replenish - 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 initialization)
- */
-static void iwl4965_rx_allocate(struct iwl_priv *priv, gfp_t priority)
-{
-       struct iwl_rx_queue *rxq = &priv->rxq;
-       struct list_head *element;
-       struct iwl_rx_mem_buffer *rxb;
-       struct page *page;
-       unsigned long flags;
-       gfp_t gfp_mask = priority;
-
-       while (1) {
-               spin_lock_irqsave(&rxq->lock, flags);
-               if (list_empty(&rxq->rx_used)) {
-                       spin_unlock_irqrestore(&rxq->lock, flags);
-                       return;
-               }
-               spin_unlock_irqrestore(&rxq->lock, flags);
-
-               if (rxq->free_count > RX_LOW_WATERMARK)
-                       gfp_mask |= __GFP_NOWARN;
-
-               if (priv->hw_params.rx_page_order > 0)
-                       gfp_mask |= __GFP_COMP;
-
-               /* Alloc a new receive buffer */
-               page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
-               if (!page) {
-                       if (net_ratelimit())
-                               IWL_DEBUG_INFO(priv, "alloc_pages failed, "
-                                              "order: %d\n",
-                                              priv->hw_params.rx_page_order);
-
-                       if ((rxq->free_count <= RX_LOW_WATERMARK) &&
-                           net_ratelimit())
-                               IWL_CRIT(priv,
-                                       "Failed to alloc_pages with %s. "
-                                       "Only %u free buffers remaining.\n",
-                                        priority == GFP_ATOMIC ?
-                                                "GFP_ATOMIC" : "GFP_KERNEL",
-                                        rxq->free_count);
-                       /* We don't reschedule replenish work here -- we will
-                        * call the restock method and if it still needs
-                        * more buffers it will schedule replenish */
-                       return;
-               }
-
-               spin_lock_irqsave(&rxq->lock, flags);
-
-               if (list_empty(&rxq->rx_used)) {
-                       spin_unlock_irqrestore(&rxq->lock, flags);
-                       __free_pages(page, priv->hw_params.rx_page_order);
-                       return;
-               }
-               element = rxq->rx_used.next;
-               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-               list_del(element);
-
-               spin_unlock_irqrestore(&rxq->lock, flags);
-
-               BUG_ON(rxb->page);
-               rxb->page = page;
-               /* Get physical address of the RB */
-               rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
-                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-               /* dma address must be no more than 36 bits */
-               BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
-               /* and also 256 byte aligned! */
-               BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
-
-               spin_lock_irqsave(&rxq->lock, flags);
-
-               list_add_tail(&rxb->list, &rxq->rx_free);
-               rxq->free_count++;
-               priv->alloc_rxb_page++;
-
-               spin_unlock_irqrestore(&rxq->lock, flags);
-       }
-}
-
-void iwl4965_rx_replenish(struct iwl_priv *priv)
-{
-       unsigned long flags;
-
-       iwl4965_rx_allocate(priv, GFP_KERNEL);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl4965_rx_queue_restock(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-void iwl4965_rx_replenish_now(struct iwl_priv *priv)
-{
-       iwl4965_rx_allocate(priv, GFP_ATOMIC);
-
-       iwl4965_rx_queue_restock(priv);
-}
-
-/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have its 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 iwl4965_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].page != NULL) {
-                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-                       __iwl_legacy_free_pages(priv, rxq->pool[i].page);
-                       rxq->pool[i].page = NULL;
-               }
-       }
-
-       dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-                         rxq->bd_dma);
-       dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
-                         rxq->rb_stts, rxq->rb_stts_dma);
-       rxq->bd = NULL;
-       rxq->rb_stts  = NULL;
-}
-
-int iwl4965_rxq_stop(struct iwl_priv *priv)
-{
-
-       /* stop Rx DMA */
-       iwl_legacy_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-       iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
-                           FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-
-       return 0;
-}
-
-int iwl4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
-{
-       int idx = 0;
-       int band_offset = 0;
-
-       /* HT rate format: mac80211 wants an MCS number, which is just LSB */
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
-               idx = (rate_n_flags & 0xff);
-               return idx;
-       /* Legacy rate format, search for match in table */
-       } else {
-               if (band == IEEE80211_BAND_5GHZ)
-                       band_offset = IWL_FIRST_OFDM_RATE;
-               for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
-                       if (iwlegacy_rates[idx].plcp == (rate_n_flags & 0xFF))
-                               return idx - band_offset;
-       }
-
-       return -1;
-}
-
-static int iwl4965_calc_rssi(struct iwl_priv *priv,
-                            struct iwl_rx_phy_res *rx_resp)
-{
-       /* data from PHY/DSP regarding signal strength, etc.,
-        *   contents are always there, not configurable by host.  */
-       struct iwl4965_rx_non_cfg_phy *ncphy =
-           (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
-       u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK)
-                       >> IWL49_AGC_DB_POS;
-
-       u32 valid_antennae =
-           (le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK)
-                       >> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET;
-       u8 max_rssi = 0;
-       u32 i;
-
-       /* Find max rssi among 3 possible receivers.
-        * These values are measured by the digital signal processor (DSP).
-        * They should stay fairly constant even as the signal strength varies,
-        *   if the radio's automatic gain control (AGC) is working right.
-        * AGC value (see below) will provide the "interesting" info. */
-       for (i = 0; i < 3; i++)
-               if (valid_antennae & (1 << i))
-                       max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
-
-       IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
-               ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
-               max_rssi, agc);
-
-       /* dBm = max_rssi dB - agc dB - constant.
-        * Higher AGC (higher radio gain) means lower signal. */
-       return max_rssi - agc - IWL4965_RSSI_OFFSET;
-}
-
-
-static u32 iwl4965_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
-{
-       u32 decrypt_out = 0;
-
-       if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
-                                       RX_RES_STATUS_STATION_FOUND)
-               decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
-                               RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
-
-       decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
-
-       /* packet was not encrypted */
-       if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
-                                       RX_RES_STATUS_SEC_TYPE_NONE)
-               return decrypt_out;
-
-       /* packet was encrypted with unknown alg */
-       if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
-                                       RX_RES_STATUS_SEC_TYPE_ERR)
-               return decrypt_out;
-
-       /* decryption was not done in HW */
-       if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
-                                       RX_MPDU_RES_STATUS_DEC_DONE_MSK)
-               return decrypt_out;
-
-       switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
-
-       case RX_RES_STATUS_SEC_TYPE_CCMP:
-               /* alg is CCM: check MIC only */
-               if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
-                       /* Bad MIC */
-                       decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
-               else
-                       decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-
-               break;
-
-       case RX_RES_STATUS_SEC_TYPE_TKIP:
-               if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
-                       /* Bad TTAK */
-                       decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
-                       break;
-               }
-               /* fall through if TTAK OK */
-       default:
-               if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
-                       decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
-               else
-                       decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-               break;
-       }
-
-       IWL_DEBUG_RX(priv, "decrypt_in:0x%x  decrypt_out = 0x%x\n",
-                                       decrypt_in, decrypt_out);
-
-       return decrypt_out;
-}
-
-static void iwl4965_pass_packet_to_mac80211(struct iwl_priv *priv,
-                                       struct ieee80211_hdr *hdr,
-                                       u16 len,
-                                       u32 ampdu_status,
-                                       struct iwl_rx_mem_buffer *rxb,
-                                       struct ieee80211_rx_status *stats)
-{
-       struct sk_buff *skb;
-       __le16 fc = hdr->frame_control;
-
-       /* We only process data packets if the interface is open */
-       if (unlikely(!priv->is_open)) {
-               IWL_DEBUG_DROP_LIMIT(priv,
-                   "Dropping packet while interface is not open.\n");
-               return;
-       }
-
-       /* In case of HW accelerated crypto and bad decryption, drop */
-       if (!priv->cfg->mod_params->sw_crypto &&
-           iwl_legacy_set_decrypted_flag(priv, hdr, ampdu_status, stats))
-               return;
-
-       skb = dev_alloc_skb(128);
-       if (!skb) {
-               IWL_ERR(priv, "dev_alloc_skb failed\n");
-               return;
-       }
-
-       skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
-
-       iwl_legacy_update_stats(priv, false, fc, len);
-       memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-
-       ieee80211_rx(priv->hw, skb);
-       priv->alloc_rxb_page--;
-       rxb->page = NULL;
-}
-
-/* Called for REPLY_RX (legacy ABG frames), or
- * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
-void iwl4965_rx_reply_rx(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
-{
-       struct ieee80211_hdr *header;
-       struct ieee80211_rx_status rx_status;
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_rx_phy_res *phy_res;
-       __le32 rx_pkt_status;
-       struct iwl_rx_mpdu_res_start *amsdu;
-       u32 len;
-       u32 ampdu_status;
-       u32 rate_n_flags;
-
-       /**
-        * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
-        *      REPLY_RX: physical layer info is in this buffer
-        *      REPLY_RX_MPDU_CMD: physical layer info was sent in separate
-        *              command and cached in priv->last_phy_res
-        *
-        * Here we set up local variables depending on which command is
-        * received.
-        */
-       if (pkt->hdr.cmd == REPLY_RX) {
-               phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
-               header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
-                               + phy_res->cfg_phy_cnt);
-
-               len = le16_to_cpu(phy_res->byte_count);
-               rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
-                               phy_res->cfg_phy_cnt + len);
-               ampdu_status = le32_to_cpu(rx_pkt_status);
-       } else {
-               if (!priv->_4965.last_phy_res_valid) {
-                       IWL_ERR(priv, "MPDU frame without cached PHY data\n");
-                       return;
-               }
-               phy_res = &priv->_4965.last_phy_res;
-               amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
-               header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
-               len = le16_to_cpu(amsdu->byte_count);
-               rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
-               ampdu_status = iwl4965_translate_rx_status(priv,
-                               le32_to_cpu(rx_pkt_status));
-       }
-
-       if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
-               IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
-                               phy_res->cfg_phy_cnt);
-               return;
-       }
-
-       if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
-           !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
-               IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
-                               le32_to_cpu(rx_pkt_status));
-               return;
-       }
-
-       /* This will be used in several places later */
-       rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
-
-       /* rx_status carries information about the packet to mac80211 */
-       rx_status.mactime = le64_to_cpu(phy_res->timestamp);
-       rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-                               IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-       rx_status.freq =
-               ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
-                                                       rx_status.band);
-       rx_status.rate_idx =
-               iwl4965_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
-       rx_status.flag = 0;
-
-       /* TSF isn't reliable. In order to allow smooth user experience,
-        * this W/A doesn't propagate it to the mac80211 */
-       /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
-
-       priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
-
-       /* Find max signal strength (dBm) among 3 antenna/receiver chains */
-       rx_status.signal = iwl4965_calc_rssi(priv, phy_res);
-
-       iwl_legacy_dbg_log_rx_data_frame(priv, len, header);
-       IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
-               rx_status.signal, (unsigned long long)rx_status.mactime);
-
-       /*
-        * "antenna number"
-        *
-        * It seems that the antenna field in the phy flags value
-        * is actually a bit field. This is undefined by radiotap,
-        * it wants an actual antenna number but I always get "7"
-        * for most legacy frames I receive indicating that the
-        * same frame was received on all three RX chains.
-        *
-        * I think this field should be removed in favor of a
-        * new 802.11n radiotap field "RX chains" that is defined
-        * as a bitmask.
-        */
-       rx_status.antenna =
-               (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK)
-               >> RX_RES_PHY_FLAGS_ANTENNA_POS;
-
-       /* set the preamble flag if appropriate */
-       if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-               rx_status.flag |= RX_FLAG_SHORTPRE;
-
-       /* Set up the HT phy flags */
-       if (rate_n_flags & RATE_MCS_HT_MSK)
-               rx_status.flag |= RX_FLAG_HT;
-       if (rate_n_flags & RATE_MCS_HT40_MSK)
-               rx_status.flag |= RX_FLAG_40MHZ;
-       if (rate_n_flags & RATE_MCS_SGI_MSK)
-               rx_status.flag |= RX_FLAG_SHORT_GI;
-
-       iwl4965_pass_packet_to_mac80211(priv, header, len, ampdu_status,
-                                   rxb, &rx_status);
-}
-
-/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
- * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
-void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
-                           struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       priv->_4965.last_phy_res_valid = true;
-       memcpy(&priv->_4965.last_phy_res, pkt->u.raw,
-              sizeof(struct iwl_rx_phy_res));
-}
-
-static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
-                                    struct ieee80211_vif *vif,
-                                    enum ieee80211_band band,
-                                    u8 is_active, u8 n_probes,
-                                    struct iwl_scan_channel *scan_ch)
-{
-       struct ieee80211_channel *chan;
-       const struct ieee80211_supported_band *sband;
-       const struct iwl_channel_info *ch_info;
-       u16 passive_dwell = 0;
-       u16 active_dwell = 0;
-       int added, i;
-       u16 channel;
-
-       sband = iwl_get_hw_mode(priv, band);
-       if (!sband)
-               return 0;
-
-       active_dwell = iwl_legacy_get_active_dwell_time(priv, band, n_probes);
-       passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
-       if (passive_dwell <= active_dwell)
-               passive_dwell = active_dwell + 1;
-
-       for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
-               chan = priv->scan_request->channels[i];
-
-               if (chan->band != band)
-                       continue;
-
-               channel = chan->hw_value;
-               scan_ch->channel = cpu_to_le16(channel);
-
-               ch_info = iwl_legacy_get_channel_info(priv, band, channel);
-               if (!iwl_legacy_is_channel_valid(ch_info)) {
-                       IWL_DEBUG_SCAN(priv,
-                                "Channel %d is INVALID for this band.\n",
-                                       channel);
-                       continue;
-               }
-
-               if (!is_active || iwl_legacy_is_channel_passive(ch_info) ||
-                   (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
-                       scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
-               else
-                       scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
-
-               if (n_probes)
-                       scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
-
-               scan_ch->active_dwell = cpu_to_le16(active_dwell);
-               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-
-               /* Set txpower levels to defaults */
-               scan_ch->dsp_atten = 110;
-
-               /* NOTE: if we were doing 6Mb OFDM for scans we'd use
-                * power level:
-                * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
-                */
-               if (band == IEEE80211_BAND_5GHZ)
-                       scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-               else
-                       scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-
-               IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
-                              channel, le32_to_cpu(scan_ch->type),
-                              (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
-                               "ACTIVE" : "PASSIVE",
-                              (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
-                              active_dwell : passive_dwell);
-
-               scan_ch++;
-               added++;
-       }
-
-       IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
-       return added;
-}
-
-int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_SCAN_CMD,
-               .len = sizeof(struct iwl_scan_cmd),
-               .flags = CMD_SIZE_HUGE,
-       };
-       struct iwl_scan_cmd *scan;
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       u32 rate_flags = 0;
-       u16 cmd_len;
-       u16 rx_chain = 0;
-       enum ieee80211_band band;
-       u8 n_probes = 0;
-       u8 rx_ant = priv->hw_params.valid_rx_ant;
-       u8 rate;
-       bool is_active = false;
-       int  chan_mod;
-       u8 active_chains;
-       u8 scan_tx_antennas = priv->hw_params.valid_tx_ant;
-       int ret;
-
-       lockdep_assert_held(&priv->mutex);
-
-       if (vif)
-               ctx = iwl_legacy_rxon_ctx_from_vif(vif);
-
-       if (!priv->scan_cmd) {
-               priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
-                                        IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-               if (!priv->scan_cmd) {
-                       IWL_DEBUG_SCAN(priv,
-                                      "fail to allocate memory for scan\n");
-                       return -ENOMEM;
-               }
-       }
-       scan = priv->scan_cmd;
-       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_legacy_is_any_associated(priv)) {
-               u16 interval;
-               u32 extra;
-               u32 suspend_time = 100;
-               u32 scan_suspend_time = 100;
-
-               IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-               interval = vif->bss_conf.beacon_int;
-
-               scan->suspend_time = 0;
-               scan->max_out_time = cpu_to_le32(200 * 1024);
-               if (!interval)
-                       interval = suspend_time;
-
-               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(priv, "suspend_time 0x%X beacon interval %d\n",
-                              scan_suspend_time, interval);
-       }
-
-       if (priv->scan_request->n_ssids) {
-               int i, p = 0;
-               IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
-               for (i = 0; i < priv->scan_request->n_ssids; i++) {
-                       /* always does wildcard anyway */
-                       if (!priv->scan_request->ssids[i].ssid_len)
-                               continue;
-                       scan->direct_scan[p].id = WLAN_EID_SSID;
-                       scan->direct_scan[p].len =
-                               priv->scan_request->ssids[i].ssid_len;
-                       memcpy(scan->direct_scan[p].ssid,
-                              priv->scan_request->ssids[i].ssid,
-                              priv->scan_request->ssids[i].ssid_len);
-                       n_probes++;
-                       p++;
-               }
-               is_active = true;
-       } else
-               IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
-
-       scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
-       scan->tx_cmd.sta_id = ctx->bcast_sta_id;
-       scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
-       switch (priv->scan_band) {
-       case IEEE80211_BAND_2GHZ:
-               scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
-               chan_mod = le32_to_cpu(
-                       priv->contexts[IWL_RXON_CTX_BSS].active.flags &
-                                               RXON_FLG_CHANNEL_MODE_MSK)
-                                      >> RXON_FLG_CHANNEL_MODE_POS;
-               if (chan_mod == CHANNEL_MODE_PURE_40) {
-                       rate = IWL_RATE_6M_PLCP;
-               } else {
-                       rate = IWL_RATE_1M_PLCP;
-                       rate_flags = RATE_MCS_CCK_MSK;
-               }
-               break;
-       case IEEE80211_BAND_5GHZ:
-               rate = IWL_RATE_6M_PLCP;
-               break;
-       default:
-               IWL_WARN(priv, "Invalid scan band\n");
-               return -EIO;
-       }
-
-       /*
-        * If active scanning is requested but a certain channel is
-        * marked passive, we can do active scanning if we detect
-        * transmissions.
-        *
-        * There is an issue with some firmware versions that triggers
-        * a sysassert on a "good CRC threshold" of zero (== disabled),
-        * on a radar channel even though this means that we should NOT
-        * send probes.
-        *
-        * The "good CRC threshold" is the number of frames that we
-        * need to receive during our dwell time on a channel before
-        * sending out probes -- setting this to a huge value will
-        * mean we never reach it, but at the same time work around
-        * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
-        * here instead of IWL_GOOD_CRC_TH_DISABLED.
-        */
-       scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
-                                       IWL_GOOD_CRC_TH_NEVER;
-
-       band = priv->scan_band;
-
-       if (priv->cfg->scan_rx_antennas[band])
-               rx_ant = priv->cfg->scan_rx_antennas[band];
-
-       priv->scan_tx_ant[band] = iwl4965_toggle_tx_ant(priv,
-                                               priv->scan_tx_ant[band],
-                                                   scan_tx_antennas);
-       rate_flags |= iwl4965_ant_idx_to_flags(priv->scan_tx_ant[band]);
-       scan->tx_cmd.rate_n_flags = iwl4965_hw_set_rate_n_flags(rate, rate_flags);
-
-       /* In power save mode use one chain, otherwise use all chains */
-       if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-               /* rx_ant has been set to all valid chains previously */
-               active_chains = rx_ant &
-                               ((u8)(priv->chain_noise_data.active_chains));
-               if (!active_chains)
-                       active_chains = rx_ant;
-
-               IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
-                               priv->chain_noise_data.active_chains);
-
-               rx_ant = iwl4965_first_antenna(active_chains);
-       }
-
-       /* MIMO is not used here, but value is required */
-       rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
-       rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
-       rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
-       rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
-       scan->rx_chain = cpu_to_le16(rx_chain);
-
-       cmd_len = iwl_legacy_fill_probe_req(priv,
-                                       (struct ieee80211_mgmt *)scan->data,
-                                       vif->addr,
-                                       priv->scan_request->ie,
-                                       priv->scan_request->ie_len,
-                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
-       scan->tx_cmd.len = cpu_to_le16(cmd_len);
-
-       scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
-                              RXON_FILTER_BCON_AWARE_MSK);
-
-       scan->channel_count = iwl4965_get_channels_for_scan(priv, vif, band,
-                                               is_active, n_probes,
-                                               (void *)&scan->data[cmd_len]);
-       if (scan->channel_count == 0) {
-               IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
-               return -EIO;
-       }
-
-       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);
-
-       ret = iwl_legacy_send_cmd_sync(priv, &cmd);
-       if (ret)
-               clear_bit(STATUS_SCAN_HW, &priv->status);
-
-       return ret;
-}
-
-int iwl4965_manage_ibss_station(struct iwl_priv *priv,
-                              struct ieee80211_vif *vif, bool add)
-{
-       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-
-       if (add)
-               return iwl4965_add_bssid_station(priv, vif_priv->ctx,
-                                               vif->bss_conf.bssid,
-                                               &vif_priv->ibss_bssid_sta_id);
-       return iwl_legacy_remove_station(priv, vif_priv->ibss_bssid_sta_id,
-                                 vif->bss_conf.bssid);
-}
-
-void iwl4965_free_tfds_in_queue(struct iwl_priv *priv,
-                           int sta_id, int tid, int freed)
-{
-       lockdep_assert_held(&priv->sta_lock);
-
-       if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed)
-               priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
-       else {
-               IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
-                       priv->stations[sta_id].tid[tid].tfds_in_queue,
-                       freed);
-               priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
-       }
-}
-
-#define IWL_TX_QUEUE_MSK       0xfffff
-
-static bool iwl4965_is_single_rx_stream(struct iwl_priv *priv)
-{
-       return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
-              priv->current_ht_config.single_chain_sufficient;
-}
-
-#define IWL_NUM_RX_CHAINS_MULTIPLE     3
-#define IWL_NUM_RX_CHAINS_SINGLE       2
-#define IWL_NUM_IDLE_CHAINS_DUAL       2
-#define IWL_NUM_IDLE_CHAINS_SINGLE     1
-
-/*
- * Determine how many receiver/antenna chains to use.
- *
- * More provides better reception via diversity.  Fewer saves power
- * at the expense of throughput, but only when not in powersave to
- * start with.
- *
- * MIMO (dual stream) requires at least 2, but works better with 3.
- * This does not determine *which* chains to use, just how many.
- */
-static int iwl4965_get_active_rx_chain_count(struct iwl_priv *priv)
-{
-       /* # of Rx chains to use when expecting MIMO. */
-       if (iwl4965_is_single_rx_stream(priv))
-               return IWL_NUM_RX_CHAINS_SINGLE;
-       else
-               return IWL_NUM_RX_CHAINS_MULTIPLE;
-}
-
-/*
- * When we are in power saving mode, unless device support spatial
- * multiplexing power save, use the active count for rx chain count.
- */
-static int
-iwl4965_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
-{
-       /* # Rx chains when idling, depending on SMPS mode */
-       switch (priv->current_ht_config.smps) {
-       case IEEE80211_SMPS_STATIC:
-       case IEEE80211_SMPS_DYNAMIC:
-               return IWL_NUM_IDLE_CHAINS_SINGLE;
-       case IEEE80211_SMPS_OFF:
-               return active_cnt;
-       default:
-               WARN(1, "invalid SMPS mode %d",
-                    priv->current_ht_config.smps);
-               return active_cnt;
-       }
-}
-
-/* up to 4 chains */
-static u8 iwl4965_count_chain_bitmap(u32 chain_bitmap)
-{
-       u8 res;
-       res = (chain_bitmap & BIT(0)) >> 0;
-       res += (chain_bitmap & BIT(1)) >> 1;
-       res += (chain_bitmap & BIT(2)) >> 2;
-       res += (chain_bitmap & BIT(3)) >> 3;
-       return res;
-}
-
-/**
- * iwl4965_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
- *
- * Selects how many and which Rx receivers/antennas/chains to use.
- * This should not be used for scan command ... it puts data in wrong place.
- */
-void iwl4965_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-       bool is_single = iwl4965_is_single_rx_stream(priv);
-       bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
-       u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
-       u32 active_chains;
-       u16 rx_chain;
-
-       /* Tell uCode which antennas are actually connected.
-        * Before first association, we assume all antennas are connected.
-        * Just after first association, iwl4965_chain_noise_calibration()
-        *    checks which antennas actually *are* connected. */
-       if (priv->chain_noise_data.active_chains)
-               active_chains = priv->chain_noise_data.active_chains;
-       else
-               active_chains = priv->hw_params.valid_rx_ant;
-
-       rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
-
-       /* How many receivers should we use? */
-       active_rx_cnt = iwl4965_get_active_rx_chain_count(priv);
-       idle_rx_cnt = iwl4965_get_idle_rx_chain_count(priv, active_rx_cnt);
-
-
-       /* correct rx chain count according hw settings
-        * and chain noise calibration
-        */
-       valid_rx_cnt = iwl4965_count_chain_bitmap(active_chains);
-       if (valid_rx_cnt < active_rx_cnt)
-               active_rx_cnt = valid_rx_cnt;
-
-       if (valid_rx_cnt < idle_rx_cnt)
-               idle_rx_cnt = valid_rx_cnt;
-
-       rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
-       rx_chain |= idle_rx_cnt  << RXON_RX_CHAIN_CNT_POS;
-
-       ctx->staging.rx_chain = cpu_to_le16(rx_chain);
-
-       if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
-               ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
-       else
-               ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
-
-       IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
-                       ctx->staging.rx_chain,
-                       active_rx_cnt, idle_rx_cnt);
-
-       WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
-               active_rx_cnt < idle_rx_cnt);
-}
-
-u8 iwl4965_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
-{
-       int i;
-       u8 ind = ant;
-
-       for (i = 0; i < RATE_ANT_NUM - 1; i++) {
-               ind = (ind + 1) < RATE_ANT_NUM ?  ind + 1 : 0;
-               if (valid & BIT(ind))
-                       return ind;
-       }
-       return ant;
-}
-
-static const char *iwl4965_get_fh_string(int cmd)
-{
-       switch (cmd) {
-       IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
-       IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
-       IWL_CMD(FH_RSCSR_CHNL0_WPTR);
-       IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
-       IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
-       IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
-       IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
-       IWL_CMD(FH_TSSR_TX_STATUS_REG);
-       IWL_CMD(FH_TSSR_TX_ERROR_REG);
-       default:
-               return "UNKNOWN";
-       }
-}
-
-int iwl4965_dump_fh(struct iwl_priv *priv, char **buf, bool display)
-{
-       int i;
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       int pos = 0;
-       size_t bufsz = 0;
-#endif
-       static const u32 fh_tbl[] = {
-               FH_RSCSR_CHNL0_STTS_WPTR_REG,
-               FH_RSCSR_CHNL0_RBDCB_BASE_REG,
-               FH_RSCSR_CHNL0_WPTR,
-               FH_MEM_RCSR_CHNL0_CONFIG_REG,
-               FH_MEM_RSSR_SHARED_CTRL_REG,
-               FH_MEM_RSSR_RX_STATUS_REG,
-               FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
-               FH_TSSR_TX_STATUS_REG,
-               FH_TSSR_TX_ERROR_REG
-       };
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (display) {
-               bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
-               *buf = kmalloc(bufsz, GFP_KERNEL);
-               if (!*buf)
-                       return -ENOMEM;
-               pos += scnprintf(*buf + pos, bufsz - pos,
-                               "FH register values:\n");
-               for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
-                       pos += scnprintf(*buf + pos, bufsz - pos,
-                               "  %34s: 0X%08x\n",
-                               iwl4965_get_fh_string(fh_tbl[i]),
-                               iwl_legacy_read_direct32(priv, fh_tbl[i]));
-               }
-               return pos;
-       }
-#endif
-       IWL_ERR(priv, "FH register values:\n");
-       for (i = 0; i <  ARRAY_SIZE(fh_tbl); i++) {
-               IWL_ERR(priv, "  %34s: 0X%08x\n",
-                       iwl4965_get_fh_string(fh_tbl[i]),
-                       iwl_legacy_read_direct32(priv, fh_tbl[i]));
-       }
-       return 0;
-}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
deleted file mode 100644 (file)
index 57ebe21..0000000
+++ /dev/null
@@ -1,2871 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2005 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <net/mac80211.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-
-#include <linux/workqueue.h>
-
-#include "iwl-dev.h"
-#include "iwl-sta.h"
-#include "iwl-core.h"
-#include "iwl-4965.h"
-
-#define IWL4965_RS_NAME "iwl-4965-rs"
-
-#define NUM_TRY_BEFORE_ANT_TOGGLE 1
-#define IWL_NUMBER_TRY      1
-#define IWL_HT_NUMBER_TRY   3
-
-#define IWL_RATE_MAX_WINDOW            62      /* # tx in history window */
-#define IWL_RATE_MIN_FAILURE_TH                6       /* min failures to calc tpt */
-#define IWL_RATE_MIN_SUCCESS_TH                8       /* min successes to calc tpt */
-
-/* max allowed rate miss before sync LQ cmd */
-#define IWL_MISSED_RATE_MAX            15
-/* max time to accum history 2 seconds */
-#define IWL_RATE_SCALE_FLUSH_INTVL   (3*HZ)
-
-static u8 rs_ht_to_legacy[] = {
-       IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX,
-       IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX,
-       IWL_RATE_6M_INDEX,
-       IWL_RATE_6M_INDEX, IWL_RATE_9M_INDEX,
-       IWL_RATE_12M_INDEX, IWL_RATE_18M_INDEX,
-       IWL_RATE_24M_INDEX, IWL_RATE_36M_INDEX,
-       IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX
-};
-
-static const u8 ant_toggle_lookup[] = {
-       /*ANT_NONE -> */ ANT_NONE,
-       /*ANT_A    -> */ ANT_B,
-       /*ANT_B    -> */ ANT_C,
-       /*ANT_AB   -> */ ANT_BC,
-       /*ANT_C    -> */ ANT_A,
-       /*ANT_AC   -> */ ANT_AB,
-       /*ANT_BC   -> */ ANT_AC,
-       /*ANT_ABC  -> */ ANT_ABC,
-};
-
-#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np)    \
-       [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,      \
-                                   IWL_RATE_SISO_##s##M_PLCP, \
-                                   IWL_RATE_MIMO2_##s##M_PLCP,\
-                                   IWL_RATE_##r##M_IEEE,      \
-                                   IWL_RATE_##ip##M_INDEX,    \
-                                   IWL_RATE_##in##M_INDEX,    \
-                                   IWL_RATE_##rp##M_INDEX,    \
-                                   IWL_RATE_##rn##M_INDEX,    \
-                                   IWL_RATE_##pp##M_INDEX,    \
-                                   IWL_RATE_##np##M_INDEX }
-
-/*
- * Parameter order:
- *   rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
- *
- * If there isn't a valid next or previous rate then INV is used which
- * maps to IWL_RATE_INVALID
- *
- */
-const struct iwl_rate_info iwlegacy_rates[IWL_RATE_COUNT] = {
-       IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2),    /*  1mbps */
-       IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5),          /*  2mbps */
-       IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11),        /*5.5mbps */
-       IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18),      /* 11mbps */
-       IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11),        /*  6mbps */
-       IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11),       /*  9mbps */
-       IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18),   /* 12mbps */
-       IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24),   /* 18mbps */
-       IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36),   /* 24mbps */
-       IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48),   /* 36mbps */
-       IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54),   /* 48mbps */
-       IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */
-       IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
-};
-
-static int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags)
-{
-       int idx = 0;
-
-       /* HT rate format */
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
-               idx = (rate_n_flags & 0xff);
-
-               if (idx >= IWL_RATE_MIMO2_6M_PLCP)
-                       idx = idx - IWL_RATE_MIMO2_6M_PLCP;
-
-               idx += IWL_FIRST_OFDM_RATE;
-               /* skip 9M not supported in ht*/
-               if (idx >= IWL_RATE_9M_INDEX)
-                       idx += 1;
-               if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE))
-                       return idx;
-
-       /* legacy rate format, search for match in table */
-       } else {
-               for (idx = 0; idx < ARRAY_SIZE(iwlegacy_rates); idx++)
-                       if (iwlegacy_rates[idx].plcp == (rate_n_flags & 0xFF))
-                               return idx;
-       }
-
-       return -1;
-}
-
-static void iwl4965_rs_rate_scale_perform(struct iwl_priv *priv,
-                                  struct sk_buff *skb,
-                                  struct ieee80211_sta *sta,
-                                  struct iwl_lq_sta *lq_sta);
-static void iwl4965_rs_fill_link_cmd(struct iwl_priv *priv,
-                            struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
-static void iwl4965_rs_stay_in_table(struct iwl_lq_sta *lq_sta,
-                                       bool force_search);
-
-#ifdef CONFIG_MAC80211_DEBUGFS
-static void iwl4965_rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
-                            u32 *rate_n_flags, int index);
-#else
-static void iwl4965_rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
-                            u32 *rate_n_flags, int index)
-{}
-#endif
-
-/**
- * The following tables contain the expected throughput metrics for all rates
- *
- *     1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
- *
- * where invalid entries are zeros.
- *
- * CCK rates are only valid in legacy table and will only be used in G
- * (2.4 GHz) band.
- */
-
-static s32 expected_tpt_legacy[IWL_RATE_COUNT] = {
-       7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0
-};
-
-static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = {
-       {0, 0, 0, 0, 42, 0,  76, 102, 124, 158, 183, 193, 202}, /* Norm */
-       {0, 0, 0, 0, 46, 0,  82, 110, 132, 167, 192, 202, 210}, /* SGI */
-       {0, 0, 0, 0, 48, 0,  93, 135, 176, 251, 319, 351, 381}, /* AGG */
-       {0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */
-};
-
-static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = {
-       {0, 0, 0, 0,  77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */
-       {0, 0, 0, 0,  83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */
-       {0, 0, 0, 0,  96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */
-       {0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */
-};
-
-static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
-       {0, 0, 0, 0,  74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */
-       {0, 0, 0, 0,  81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */
-       {0, 0, 0, 0,  92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */
-       {0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/
-};
-
-static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
-       {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */
-       {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */
-       {0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */
-       {0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */
-};
-
-/* mbps, mcs */
-static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
-       {  "1", "BPSK DSSS"},
-       {  "2", "QPSK DSSS"},
-       {"5.5", "BPSK CCK"},
-       { "11", "QPSK CCK"},
-       {  "6", "BPSK 1/2"},
-       {  "9", "BPSK 1/2"},
-       { "12", "QPSK 1/2"},
-       { "18", "QPSK 3/4"},
-       { "24", "16QAM 1/2"},
-       { "36", "16QAM 3/4"},
-       { "48", "64QAM 2/3"},
-       { "54", "64QAM 3/4"},
-       { "60", "64QAM 5/6"},
-};
-
-#define MCS_INDEX_PER_STREAM   (8)
-
-static inline u8 iwl4965_rs_extract_rate(u32 rate_n_flags)
-{
-       return (u8)(rate_n_flags & 0xFF);
-}
-
-static void
-iwl4965_rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
-{
-       window->data = 0;
-       window->success_counter = 0;
-       window->success_ratio = IWL_INVALID_VALUE;
-       window->counter = 0;
-       window->average_tpt = IWL_INVALID_VALUE;
-       window->stamp = 0;
-}
-
-static inline u8 iwl4965_rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
-{
-       return (ant_type & valid_antenna) == ant_type;
-}
-
-/*
- *     removes the old data from the statistics. All data that is older than
- *     TID_MAX_TIME_DIFF, will be deleted.
- */
-static void
-iwl4965_rs_tl_rm_old_stats(struct iwl_traffic_load *tl, u32 curr_time)
-{
-       /* The oldest age we want to keep */
-       u32 oldest_time = curr_time - TID_MAX_TIME_DIFF;
-
-       while (tl->queue_count &&
-              (tl->time_stamp < oldest_time)) {
-               tl->total -= tl->packet_count[tl->head];
-               tl->packet_count[tl->head] = 0;
-               tl->time_stamp += TID_QUEUE_CELL_SPACING;
-               tl->queue_count--;
-               tl->head++;
-               if (tl->head >= TID_QUEUE_MAX_SIZE)
-                       tl->head = 0;
-       }
-}
-
-/*
- *     increment traffic load value for tid and also remove
- *     any old values if passed the certain time period
- */
-static u8 iwl4965_rs_tl_add_packet(struct iwl_lq_sta *lq_data,
-                          struct ieee80211_hdr *hdr)
-{
-       u32 curr_time = jiffies_to_msecs(jiffies);
-       u32 time_diff;
-       s32 index;
-       struct iwl_traffic_load *tl = NULL;
-       u8 tid;
-
-       if (ieee80211_is_data_qos(hdr->frame_control)) {
-               u8 *qc = ieee80211_get_qos_ctl(hdr);
-               tid = qc[0] & 0xf;
-       } else
-               return MAX_TID_COUNT;
-
-       if (unlikely(tid >= TID_MAX_LOAD_COUNT))
-               return MAX_TID_COUNT;
-
-       tl = &lq_data->load[tid];
-
-       curr_time -= curr_time % TID_ROUND_VALUE;
-
-       /* Happens only for the first packet. Initialize the data */
-       if (!(tl->queue_count)) {
-               tl->total = 1;
-               tl->time_stamp = curr_time;
-               tl->queue_count = 1;
-               tl->head = 0;
-               tl->packet_count[0] = 1;
-               return MAX_TID_COUNT;
-       }
-
-       time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
-       index = time_diff / TID_QUEUE_CELL_SPACING;
-
-       /* The history is too long: remove data that is older than */
-       /* TID_MAX_TIME_DIFF */
-       if (index >= TID_QUEUE_MAX_SIZE)
-               iwl4965_rs_tl_rm_old_stats(tl, curr_time);
-
-       index = (tl->head + index) % TID_QUEUE_MAX_SIZE;
-       tl->packet_count[index] = tl->packet_count[index] + 1;
-       tl->total = tl->total + 1;
-
-       if ((index + 1) > tl->queue_count)
-               tl->queue_count = index + 1;
-
-       return tid;
-}
-
-/*
-       get the traffic load value for tid
-*/
-static u32 iwl4965_rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
-{
-       u32 curr_time = jiffies_to_msecs(jiffies);
-       u32 time_diff;
-       s32 index;
-       struct iwl_traffic_load *tl = NULL;
-
-       if (tid >= TID_MAX_LOAD_COUNT)
-               return 0;
-
-       tl = &(lq_data->load[tid]);
-
-       curr_time -= curr_time % TID_ROUND_VALUE;
-
-       if (!(tl->queue_count))
-               return 0;
-
-       time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
-       index = time_diff / TID_QUEUE_CELL_SPACING;
-
-       /* The history is too long: remove data that is older than */
-       /* TID_MAX_TIME_DIFF */
-       if (index >= TID_QUEUE_MAX_SIZE)
-               iwl4965_rs_tl_rm_old_stats(tl, curr_time);
-
-       return tl->total;
-}
-
-static int iwl4965_rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
-                                     struct iwl_lq_sta *lq_data, u8 tid,
-                                     struct ieee80211_sta *sta)
-{
-       int ret = -EAGAIN;
-       u32 load;
-
-       load = iwl4965_rs_tl_get_load(lq_data, tid);
-
-       if (load > IWL_AGG_LOAD_THRESHOLD) {
-               IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
-                               sta->addr, tid);
-               ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
-               if (ret == -EAGAIN) {
-                       /*
-                        * driver and mac80211 is out of sync
-                        * this might be cause by reloading firmware
-                        * stop the tx ba session here
-                        */
-                       IWL_ERR(priv, "Fail start Tx agg on tid: %d\n",
-                               tid);
-                       ieee80211_stop_tx_ba_session(sta, tid);
-               }
-       } else {
-               IWL_ERR(priv, "Aggregation not enabled for tid %d "
-                       "because load = %u\n", tid, load);
-       }
-       return ret;
-}
-
-static void iwl4965_rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
-                             struct iwl_lq_sta *lq_data,
-                             struct ieee80211_sta *sta)
-{
-       if (tid < TID_MAX_LOAD_COUNT)
-               iwl4965_rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
-       else
-               IWL_ERR(priv, "tid exceeds max load count: %d/%d\n",
-                       tid, TID_MAX_LOAD_COUNT);
-}
-
-static inline int iwl4965_get_iwl4965_num_of_ant_from_rate(u32 rate_n_flags)
-{
-       return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) +
-              !!(rate_n_flags & RATE_MCS_ANT_B_MSK) +
-              !!(rate_n_flags & RATE_MCS_ANT_C_MSK);
-}
-
-/*
- * Static function to get the expected throughput from an iwl_scale_tbl_info
- * that wraps a NULL pointer check
- */
-static s32
-iwl4965_get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
-{
-       if (tbl->expected_tpt)
-               return tbl->expected_tpt[rs_index];
-       return 0;
-}
-
-/**
- * iwl4965_rs_collect_tx_data - Update the success/failure sliding window
- *
- * We keep a sliding window of the last 62 packets transmitted
- * at this rate.  window->data contains the bitmask of successful
- * packets.
- */
-static int iwl4965_rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
-                             int scale_index, int attempts, int successes)
-{
-       struct iwl_rate_scale_data *window = NULL;
-       static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1));
-       s32 fail_count, tpt;
-
-       if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
-               return -EINVAL;
-
-       /* Select window for current tx bit rate */
-       window = &(tbl->win[scale_index]);
-
-       /* Get expected throughput */
-       tpt = iwl4965_get_expected_tpt(tbl, scale_index);
-
-       /*
-        * Keep track of only the latest 62 tx frame attempts in this rate's
-        * history window; anything older isn't really relevant any more.
-        * If we have filled up the sliding window, drop the oldest attempt;
-        * if the oldest attempt (highest bit in bitmap) shows "success",
-        * subtract "1" from the success counter (this is the main reason
-        * we keep these bitmaps!).
-        */
-       while (attempts > 0) {
-               if (window->counter >= IWL_RATE_MAX_WINDOW) {
-
-                       /* remove earliest */
-                       window->counter = IWL_RATE_MAX_WINDOW - 1;
-
-                       if (window->data & mask) {
-                               window->data &= ~mask;
-                               window->success_counter--;
-                       }
-               }
-
-               /* Increment frames-attempted counter */
-               window->counter++;
-
-               /* Shift bitmap by one frame to throw away oldest history */
-               window->data <<= 1;
-
-               /* Mark the most recent #successes attempts as successful */
-               if (successes > 0) {
-                       window->success_counter++;
-                       window->data |= 0x1;
-                       successes--;
-               }
-
-               attempts--;
-       }
-
-       /* Calculate current success ratio, avoid divide-by-0! */
-       if (window->counter > 0)
-               window->success_ratio = 128 * (100 * window->success_counter)
-                                       / window->counter;
-       else
-               window->success_ratio = IWL_INVALID_VALUE;
-
-       fail_count = window->counter - window->success_counter;
-
-       /* Calculate average throughput, if we have enough history. */
-       if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
-           (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
-               window->average_tpt = (window->success_ratio * tpt + 64) / 128;
-       else
-               window->average_tpt = IWL_INVALID_VALUE;
-
-       /* Tag this window as having been updated */
-       window->stamp = jiffies;
-
-       return 0;
-}
-
-/*
- * Fill uCode API rate_n_flags field, based on "search" or "active" table.
- */
-static u32 iwl4965_rate_n_flags_from_tbl(struct iwl_priv *priv,
-                                struct iwl_scale_tbl_info *tbl,
-                                int index, u8 use_green)
-{
-       u32 rate_n_flags = 0;
-
-       if (is_legacy(tbl->lq_type)) {
-               rate_n_flags = iwlegacy_rates[index].plcp;
-               if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE)
-                       rate_n_flags |= RATE_MCS_CCK_MSK;
-
-       } else if (is_Ht(tbl->lq_type)) {
-               if (index > IWL_LAST_OFDM_RATE) {
-                       IWL_ERR(priv, "Invalid HT rate index %d\n", index);
-                       index = IWL_LAST_OFDM_RATE;
-               }
-               rate_n_flags = RATE_MCS_HT_MSK;
-
-               if (is_siso(tbl->lq_type))
-                       rate_n_flags |= iwlegacy_rates[index].plcp_siso;
-               else
-                       rate_n_flags |= iwlegacy_rates[index].plcp_mimo2;
-       } else {
-               IWL_ERR(priv, "Invalid tbl->lq_type %d\n", tbl->lq_type);
-       }
-
-       rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) &
-                                                    RATE_MCS_ANT_ABC_MSK);
-
-       if (is_Ht(tbl->lq_type)) {
-               if (tbl->is_ht40) {
-                       if (tbl->is_dup)
-                               rate_n_flags |= RATE_MCS_DUP_MSK;
-                       else
-                               rate_n_flags |= RATE_MCS_HT40_MSK;
-               }
-               if (tbl->is_SGI)
-                       rate_n_flags |= RATE_MCS_SGI_MSK;
-
-               if (use_green) {
-                       rate_n_flags |= RATE_MCS_GF_MSK;
-                       if (is_siso(tbl->lq_type) && tbl->is_SGI) {
-                               rate_n_flags &= ~RATE_MCS_SGI_MSK;
-                               IWL_ERR(priv, "GF was set with SGI:SISO\n");
-                       }
-               }
-       }
-       return rate_n_flags;
-}
-
-/*
- * Interpret uCode API's rate_n_flags format,
- * fill "search" or "active" tx mode table.
- */
-static int iwl4965_rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
-                                   enum ieee80211_band band,
-                                   struct iwl_scale_tbl_info *tbl,
-                                   int *rate_idx)
-{
-       u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK);
-       u8 iwl4965_num_of_ant = iwl4965_get_iwl4965_num_of_ant_from_rate(rate_n_flags);
-       u8 mcs;
-
-       memset(tbl, 0, sizeof(struct iwl_scale_tbl_info));
-       *rate_idx = iwl4965_hwrate_to_plcp_idx(rate_n_flags);
-
-       if (*rate_idx  == IWL_RATE_INVALID) {
-               *rate_idx = -1;
-               return -EINVAL;
-       }
-       tbl->is_SGI = 0;        /* default legacy setup */
-       tbl->is_ht40 = 0;
-       tbl->is_dup = 0;
-       tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS);
-       tbl->lq_type = LQ_NONE;
-       tbl->max_search = IWL_MAX_SEARCH;
-
-       /* legacy rate format */
-       if (!(rate_n_flags & RATE_MCS_HT_MSK)) {
-               if (iwl4965_num_of_ant == 1) {
-                       if (band == IEEE80211_BAND_5GHZ)
-                               tbl->lq_type = LQ_A;
-                       else
-                               tbl->lq_type = LQ_G;
-               }
-       /* HT rate format */
-       } else {
-               if (rate_n_flags & RATE_MCS_SGI_MSK)
-                       tbl->is_SGI = 1;
-
-               if ((rate_n_flags & RATE_MCS_HT40_MSK) ||
-                   (rate_n_flags & RATE_MCS_DUP_MSK))
-                       tbl->is_ht40 = 1;
-
-               if (rate_n_flags & RATE_MCS_DUP_MSK)
-                       tbl->is_dup = 1;
-
-               mcs = iwl4965_rs_extract_rate(rate_n_flags);
-
-               /* SISO */
-               if (mcs <= IWL_RATE_SISO_60M_PLCP) {
-                       if (iwl4965_num_of_ant == 1)
-                               tbl->lq_type = LQ_SISO; /*else NONE*/
-               /* MIMO2 */
-               } else {
-                       if (iwl4965_num_of_ant == 2)
-                               tbl->lq_type = LQ_MIMO2;
-               }
-       }
-       return 0;
-}
-
-/* switch to another antenna/antennas and return 1 */
-/* if no other valid antenna found, return 0 */
-static int iwl4965_rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
-                            struct iwl_scale_tbl_info *tbl)
-{
-       u8 new_ant_type;
-
-       if (!tbl->ant_type || tbl->ant_type > ANT_ABC)
-               return 0;
-
-       if (!iwl4965_rs_is_valid_ant(valid_ant, tbl->ant_type))
-               return 0;
-
-       new_ant_type = ant_toggle_lookup[tbl->ant_type];
-
-       while ((new_ant_type != tbl->ant_type) &&
-              !iwl4965_rs_is_valid_ant(valid_ant, new_ant_type))
-               new_ant_type = ant_toggle_lookup[new_ant_type];
-
-       if (new_ant_type == tbl->ant_type)
-               return 0;
-
-       tbl->ant_type = new_ant_type;
-       *rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK;
-       *rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS;
-       return 1;
-}
-
-/**
- * Green-field mode is valid if the station supports it and
- * there are no non-GF stations present in the BSS.
- */
-static bool iwl4965_rs_use_green(struct ieee80211_sta *sta)
-{
-       struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
-
-       return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
-               !(ctx->ht.non_gf_sta_present);
-}
-
-/**
- * iwl4965_rs_get_supported_rates - get the available rates
- *
- * if management frame or broadcast frame only return
- * basic available rates.
- *
- */
-static u16 iwl4965_rs_get_supported_rates(struct iwl_lq_sta *lq_sta,
-                                 struct ieee80211_hdr *hdr,
-                                 enum iwl_table_type rate_type)
-{
-       if (is_legacy(rate_type)) {
-               return lq_sta->active_legacy_rate;
-       } else {
-               if (is_siso(rate_type))
-                       return lq_sta->active_siso_rate;
-               else
-                       return lq_sta->active_mimo2_rate;
-       }
-}
-
-static u16
-iwl4965_rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask,
-                               int rate_type)
-{
-       u8 high = IWL_RATE_INVALID;
-       u8 low = IWL_RATE_INVALID;
-
-       /* 802.11A or ht walks to the next literal adjacent rate in
-        * the rate table */
-       if (is_a_band(rate_type) || !is_legacy(rate_type)) {
-               int i;
-               u32 mask;
-
-               /* Find the previous rate that is in the rate mask */
-               i = index - 1;
-               for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
-                       if (rate_mask & mask) {
-                               low = i;
-                               break;
-                       }
-               }
-
-               /* Find the next rate that is in the rate mask */
-               i = index + 1;
-               for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) {
-                       if (rate_mask & mask) {
-                               high = i;
-                               break;
-                       }
-               }
-
-               return (high << 8) | low;
-       }
-
-       low = index;
-       while (low != IWL_RATE_INVALID) {
-               low = iwlegacy_rates[low].prev_rs;
-               if (low == IWL_RATE_INVALID)
-                       break;
-               if (rate_mask & (1 << low))
-                       break;
-               IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low);
-       }
-
-       high = index;
-       while (high != IWL_RATE_INVALID) {
-               high = iwlegacy_rates[high].next_rs;
-               if (high == IWL_RATE_INVALID)
-                       break;
-               if (rate_mask & (1 << high))
-                       break;
-               IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high);
-       }
-
-       return (high << 8) | low;
-}
-
-static u32 iwl4965_rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
-                            struct iwl_scale_tbl_info *tbl,
-                            u8 scale_index, u8 ht_possible)
-{
-       s32 low;
-       u16 rate_mask;
-       u16 high_low;
-       u8 switch_to_legacy = 0;
-       u8 is_green = lq_sta->is_green;
-       struct iwl_priv *priv = lq_sta->drv;
-
-       /* check if we need to switch from HT to legacy rates.
-        * assumption is that mandatory rates (1Mbps or 6Mbps)
-        * are always supported (spec demand) */
-       if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) {
-               switch_to_legacy = 1;
-               scale_index = rs_ht_to_legacy[scale_index];
-               if (lq_sta->band == IEEE80211_BAND_5GHZ)
-                       tbl->lq_type = LQ_A;
-               else
-                       tbl->lq_type = LQ_G;
-
-               if (iwl4965_num_of_ant(tbl->ant_type) > 1)
-                       tbl->ant_type =
-                               iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
-
-               tbl->is_ht40 = 0;
-               tbl->is_SGI = 0;
-               tbl->max_search = IWL_MAX_SEARCH;
-       }
-
-       rate_mask = iwl4965_rs_get_supported_rates(lq_sta, NULL, tbl->lq_type);
-
-       /* Mask with station rate restriction */
-       if (is_legacy(tbl->lq_type)) {
-               /* supp_rates has no CCK bits in A mode */
-               if (lq_sta->band == IEEE80211_BAND_5GHZ)
-                       rate_mask  = (u16)(rate_mask &
-                          (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
-               else
-                       rate_mask = (u16)(rate_mask & lq_sta->supp_rates);
-       }
-
-       /* If we switched from HT to legacy, check current rate */
-       if (switch_to_legacy && (rate_mask & (1 << scale_index))) {
-               low = scale_index;
-               goto out;
-       }
-
-       high_low = iwl4965_rs_get_adjacent_rate(lq_sta->drv,
-                                       scale_index, rate_mask,
-                                       tbl->lq_type);
-       low = high_low & 0xff;
-
-       if (low == IWL_RATE_INVALID)
-               low = scale_index;
-
-out:
-       return iwl4965_rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green);
-}
-
-/*
- * Simple function to compare two rate scale table types
- */
-static bool iwl4965_table_type_matches(struct iwl_scale_tbl_info *a,
-                              struct iwl_scale_tbl_info *b)
-{
-       return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
-               (a->is_SGI == b->is_SGI);
-}
-
-/*
- * mac80211 sends us Tx status
- */
-static void
-iwl4965_rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
-                        struct ieee80211_sta *sta, void *priv_sta,
-                        struct sk_buff *skb)
-{
-       int legacy_success;
-       int retries;
-       int rs_index, mac_index, i;
-       struct iwl_lq_sta *lq_sta = priv_sta;
-       struct iwl_link_quality_cmd *table;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct iwl_priv *priv = (struct iwl_priv *)priv_r;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       enum mac80211_rate_control_flags mac_flags;
-       u32 tx_rate;
-       struct iwl_scale_tbl_info tbl_type;
-       struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
-       struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
-
-       IWL_DEBUG_RATE_LIMIT(priv,
-               "get frame ack response, update rate scale window\n");
-
-       /* Treat uninitialized rate scaling data same as non-existing. */
-       if (!lq_sta) {
-               IWL_DEBUG_RATE(priv, "Station rate scaling not created yet.\n");
-               return;
-       } else if (!lq_sta->drv) {
-               IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n");
-               return;
-       }
-
-       if (!ieee80211_is_data(hdr->frame_control) ||
-           info->flags & IEEE80211_TX_CTL_NO_ACK)
-               return;
-
-       /* This packet was aggregated but doesn't carry status info */
-       if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
-           !(info->flags & IEEE80211_TX_STAT_AMPDU))
-               return;
-
-       /*
-        * Ignore this Tx frame response if its initial rate doesn't match
-        * that of latest Link Quality command.  There may be stragglers
-        * from a previous Link Quality command, but we're no longer interested
-        * in those; they're either from the "active" mode while we're trying
-        * to check "search" mode, or a prior "search" mode after we've moved
-        * to a new "search" mode (which might become the new "active" mode).
-        */
-       table = &lq_sta->lq;
-       tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
-       iwl4965_rs_get_tbl_info_from_mcs(tx_rate,
-                        priv->band, &tbl_type, &rs_index);
-       if (priv->band == IEEE80211_BAND_5GHZ)
-               rs_index -= IWL_FIRST_OFDM_RATE;
-       mac_flags = info->status.rates[0].flags;
-       mac_index = info->status.rates[0].idx;
-       /* For HT packets, map MCS to PLCP */
-       if (mac_flags & IEEE80211_TX_RC_MCS) {
-               mac_index &= RATE_MCS_CODE_MSK; /* Remove # of streams */
-               if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE))
-                       mac_index++;
-               /*
-                * mac80211 HT index is always zero-indexed; we need to move
-                * HT OFDM rates after CCK rates in 2.4 GHz band
-                */
-               if (priv->band == IEEE80211_BAND_2GHZ)
-                       mac_index += IWL_FIRST_OFDM_RATE;
-       }
-       /* Here we actually compare this rate to the latest LQ command */
-       if ((mac_index < 0) ||
-           (tbl_type.is_SGI !=
-                       !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
-           (tbl_type.is_ht40 !=
-                       !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
-           (tbl_type.is_dup !=
-                       !!(mac_flags & IEEE80211_TX_RC_DUP_DATA)) ||
-           (tbl_type.ant_type != info->antenna_sel_tx) ||
-           (!!(tx_rate & RATE_MCS_HT_MSK) !=
-                       !!(mac_flags & IEEE80211_TX_RC_MCS)) ||
-           (!!(tx_rate & RATE_MCS_GF_MSK) !=
-                       !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
-           (rs_index != mac_index)) {
-               IWL_DEBUG_RATE(priv,
-               "initial rate %d does not match %d (0x%x)\n",
-                        mac_index, rs_index, tx_rate);
-               /*
-                * Since rates mis-match, the last LQ command may have failed.
-                * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
-                * ... driver.
-                */
-               lq_sta->missed_rate_counter++;
-               if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
-                       lq_sta->missed_rate_counter = 0;
-                       iwl_legacy_send_lq_cmd(priv, ctx, &lq_sta->lq,
-                                                       CMD_ASYNC, false);
-               }
-               /* Regardless, ignore this status info for outdated rate */
-               return;
-       } else
-               /* Rate did match, so reset the missed_rate_counter */
-               lq_sta->missed_rate_counter = 0;
-
-       /* Figure out if rate scale algorithm is in active or search table */
-       if (iwl4965_table_type_matches(&tbl_type,
-                               &(lq_sta->lq_info[lq_sta->active_tbl]))) {
-               curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-               other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-       } else if (iwl4965_table_type_matches(&tbl_type,
-                               &lq_sta->lq_info[1 - lq_sta->active_tbl])) {
-               curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-               other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-       } else {
-               IWL_DEBUG_RATE(priv,
-                       "Neither active nor search matches tx rate\n");
-               tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-               IWL_DEBUG_RATE(priv, "active- lq:%x, ant:%x, SGI:%d\n",
-                       tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI);
-               tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-               IWL_DEBUG_RATE(priv, "search- lq:%x, ant:%x, SGI:%d\n",
-                       tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI);
-               IWL_DEBUG_RATE(priv, "actual- lq:%x, ant:%x, SGI:%d\n",
-                       tbl_type.lq_type, tbl_type.ant_type, tbl_type.is_SGI);
-               /*
-                * no matching table found, let's by-pass the data collection
-                * and continue to perform rate scale to find the rate table
-                */
-               iwl4965_rs_stay_in_table(lq_sta, true);
-               goto done;
-       }
-
-       /*
-        * Updating the frame history depends on whether packets were
-        * aggregated.
-        *
-        * For aggregation, all packets were transmitted at the same rate, the
-        * first index into rate scale table.
-        */
-       if (info->flags & IEEE80211_TX_STAT_AMPDU) {
-               tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
-               iwl4965_rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
-                               &rs_index);
-               iwl4965_rs_collect_tx_data(curr_tbl, rs_index,
-                                  info->status.ampdu_len,
-                                  info->status.ampdu_ack_len);
-
-               /* Update success/fail counts if not searching for new mode */
-               if (lq_sta->stay_in_tbl) {
-                       lq_sta->total_success += info->status.ampdu_ack_len;
-                       lq_sta->total_failed += (info->status.ampdu_len -
-                                       info->status.ampdu_ack_len);
-               }
-       } else {
-       /*
-        * For legacy, update frame history with for each Tx retry.
-        */
-               retries = info->status.rates[0].count - 1;
-               /* HW doesn't send more than 15 retries */
-               retries = min(retries, 15);
-
-               /* The last transmission may have been successful */
-               legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
-               /* Collect data for each rate used during failed TX attempts */
-               for (i = 0; i <= retries; ++i) {
-                       tx_rate = le32_to_cpu(table->rs_table[i].rate_n_flags);
-                       iwl4965_rs_get_tbl_info_from_mcs(tx_rate, priv->band,
-                                       &tbl_type, &rs_index);
-                       /*
-                        * Only collect stats if retried rate is in the same RS
-                        * table as active/search.
-                        */
-                       if (iwl4965_table_type_matches(&tbl_type, curr_tbl))
-                               tmp_tbl = curr_tbl;
-                       else if (iwl4965_table_type_matches(&tbl_type,
-                                                                other_tbl))
-                               tmp_tbl = other_tbl;
-                       else
-                               continue;
-                       iwl4965_rs_collect_tx_data(tmp_tbl, rs_index, 1,
-                                          i < retries ? 0 : legacy_success);
-               }
-
-               /* Update success/fail counts if not searching for new mode */
-               if (lq_sta->stay_in_tbl) {
-                       lq_sta->total_success += legacy_success;
-                       lq_sta->total_failed += retries + (1 - legacy_success);
-               }
-       }
-       /* The last TX rate is cached in lq_sta; it's set in if/else above */
-       lq_sta->last_rate_n_flags = tx_rate;
-done:
-       /* See if there's a better rate or modulation mode to try. */
-       if (sta && sta->supp_rates[sband->band])
-               iwl4965_rs_rate_scale_perform(priv, skb, sta, lq_sta);
-}
-
-/*
- * Begin a period of staying with a selected modulation mode.
- * Set "stay_in_tbl" flag to prevent any mode switches.
- * Set frame tx success limits according to legacy vs. high-throughput,
- * and reset overall (spanning all rates) tx success history statistics.
- * These control how long we stay using same modulation mode before
- * searching for a new mode.
- */
-static void iwl4965_rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy,
-                                struct iwl_lq_sta *lq_sta)
-{
-       IWL_DEBUG_RATE(priv, "we are staying in the same table\n");
-       lq_sta->stay_in_tbl = 1;        /* only place this gets set */
-       if (is_legacy) {
-               lq_sta->table_count_limit = IWL_LEGACY_TABLE_COUNT;
-               lq_sta->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT;
-               lq_sta->max_success_limit = IWL_LEGACY_SUCCESS_LIMIT;
-       } else {
-               lq_sta->table_count_limit = IWL_NONE_LEGACY_TABLE_COUNT;
-               lq_sta->max_failure_limit = IWL_NONE_LEGACY_FAILURE_LIMIT;
-               lq_sta->max_success_limit = IWL_NONE_LEGACY_SUCCESS_LIMIT;
-       }
-       lq_sta->table_count = 0;
-       lq_sta->total_failed = 0;
-       lq_sta->total_success = 0;
-       lq_sta->flush_timer = jiffies;
-       lq_sta->action_counter = 0;
-}
-
-/*
- * Find correct throughput table for given mode of modulation
- */
-static void iwl4965_rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
-                                     struct iwl_scale_tbl_info *tbl)
-{
-       /* Used to choose among HT tables */
-       s32 (*ht_tbl_pointer)[IWL_RATE_COUNT];
-
-       /* Check for invalid LQ type */
-       if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) {
-               tbl->expected_tpt = expected_tpt_legacy;
-               return;
-       }
-
-       /* Legacy rates have only one table */
-       if (is_legacy(tbl->lq_type)) {
-               tbl->expected_tpt = expected_tpt_legacy;
-               return;
-       }
-
-       /* Choose among many HT tables depending on number of streams
-        * (SISO/MIMO2), channel width (20/40), SGI, and aggregation
-        * status */
-       if (is_siso(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
-               ht_tbl_pointer = expected_tpt_siso20MHz;
-       else if (is_siso(tbl->lq_type))
-               ht_tbl_pointer = expected_tpt_siso40MHz;
-       else if (is_mimo2(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
-               ht_tbl_pointer = expected_tpt_mimo2_20MHz;
-       else /* if (is_mimo2(tbl->lq_type)) <-- must be true */
-               ht_tbl_pointer = expected_tpt_mimo2_40MHz;
-
-       if (!tbl->is_SGI && !lq_sta->is_agg)            /* Normal */
-               tbl->expected_tpt = ht_tbl_pointer[0];
-       else if (tbl->is_SGI && !lq_sta->is_agg)        /* SGI */
-               tbl->expected_tpt = ht_tbl_pointer[1];
-       else if (!tbl->is_SGI && lq_sta->is_agg)        /* AGG */
-               tbl->expected_tpt = ht_tbl_pointer[2];
-       else                                            /* AGG+SGI */
-               tbl->expected_tpt = ht_tbl_pointer[3];
-}
-
-/*
- * Find starting rate for new "search" high-throughput mode of modulation.
- * Goal is to find lowest expected rate (under perfect conditions) that is
- * above the current measured throughput of "active" mode, to give new mode
- * a fair chance to prove itself without too many challenges.
- *
- * This gets called when transitioning to more aggressive modulation
- * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive
- * (i.e. MIMO to SISO).  When moving to MIMO, bit rate will typically need
- * to decrease to match "active" throughput.  When moving from MIMO to SISO,
- * bit rate will typically need to increase, but not if performance was bad.
- */
-static s32 iwl4965_rs_get_best_rate(struct iwl_priv *priv,
-                           struct iwl_lq_sta *lq_sta,
-                           struct iwl_scale_tbl_info *tbl,     /* "search" */
-                           u16 rate_mask, s8 index)
-{
-       /* "active" values */
-       struct iwl_scale_tbl_info *active_tbl =
-           &(lq_sta->lq_info[lq_sta->active_tbl]);
-       s32 active_sr = active_tbl->win[index].success_ratio;
-       s32 active_tpt = active_tbl->expected_tpt[index];
-
-       /* expected "search" throughput */
-       s32 *tpt_tbl = tbl->expected_tpt;
-
-       s32 new_rate, high, low, start_hi;
-       u16 high_low;
-       s8 rate = index;
-
-       new_rate = high = low = start_hi = IWL_RATE_INVALID;
-
-       for (; ;) {
-               high_low = iwl4965_rs_get_adjacent_rate(priv, rate, rate_mask,
-                                               tbl->lq_type);
-
-               low = high_low & 0xff;
-               high = (high_low >> 8) & 0xff;
-
-               /*
-                * Lower the "search" bit rate, to give new "search" mode
-                * approximately the same throughput as "active" if:
-                *
-                * 1) "Active" mode has been working modestly well (but not
-                *    great), and expected "search" throughput (under perfect
-                *    conditions) at candidate rate is above the actual
-                *    measured "active" throughput (but less than expected
-                *    "active" throughput under perfect conditions).
-                * OR
-                * 2) "Active" mode has been working perfectly or very well
-                *    and expected "search" throughput (under perfect
-                *    conditions) at candidate rate is above expected
-                *    "active" throughput (under perfect conditions).
-                */
-               if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) &&
-                    ((active_sr > IWL_RATE_DECREASE_TH) &&
-                     (active_sr <= IWL_RATE_HIGH_TH) &&
-                     (tpt_tbl[rate] <= active_tpt))) ||
-                   ((active_sr >= IWL_RATE_SCALE_SWITCH) &&
-                    (tpt_tbl[rate] > active_tpt))) {
-
-                       /* (2nd or later pass)
-                        * If we've already tried to raise the rate, and are
-                        * now trying to lower it, use the higher rate. */
-                       if (start_hi != IWL_RATE_INVALID) {
-                               new_rate = start_hi;
-                               break;
-                       }
-
-                       new_rate = rate;
-
-                       /* Loop again with lower rate */
-                       if (low != IWL_RATE_INVALID)
-                               rate = low;
-
-                       /* Lower rate not available, use the original */
-                       else
-                               break;
-
-               /* Else try to raise the "search" rate to match "active" */
-               } else {
-                       /* (2nd or later pass)
-                        * If we've already tried to lower the rate, and are
-                        * now trying to raise it, use the lower rate. */
-                       if (new_rate != IWL_RATE_INVALID)
-                               break;
-
-                       /* Loop again with higher rate */
-                       else if (high != IWL_RATE_INVALID) {
-                               start_hi = high;
-                               rate = high;
-
-                       /* Higher rate not available, use the original */
-                       } else {
-                               new_rate = rate;
-                               break;
-                       }
-               }
-       }
-
-       return new_rate;
-}
-
-/*
- * Set up search table for MIMO2
- */
-static int iwl4965_rs_switch_to_mimo2(struct iwl_priv *priv,
-                            struct iwl_lq_sta *lq_sta,
-                            struct ieee80211_conf *conf,
-                            struct ieee80211_sta *sta,
-                            struct iwl_scale_tbl_info *tbl, int index)
-{
-       u16 rate_mask;
-       s32 rate;
-       s8 is_green = lq_sta->is_green;
-       struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
-
-       if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
-               return -1;
-
-       if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
-                                               == WLAN_HT_CAP_SM_PS_STATIC)
-               return -1;
-
-       /* Need both Tx chains/antennas to support MIMO */
-       if (priv->hw_params.tx_chains_num < 2)
-               return -1;
-
-       IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n");
-
-       tbl->lq_type = LQ_MIMO2;
-       tbl->is_dup = lq_sta->is_dup;
-       tbl->action = 0;
-       tbl->max_search = IWL_MAX_SEARCH;
-       rate_mask = lq_sta->active_mimo2_rate;
-
-       if (iwl_legacy_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
-               tbl->is_ht40 = 1;
-       else
-               tbl->is_ht40 = 0;
-
-       iwl4965_rs_set_expected_tpt_table(lq_sta, tbl);
-
-       rate = iwl4965_rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
-
-       IWL_DEBUG_RATE(priv, "LQ: MIMO2 best rate %d mask %X\n",
-                               rate, rate_mask);
-       if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
-               IWL_DEBUG_RATE(priv,
-                               "Can't switch with index %d rate mask %x\n",
-                                               rate, rate_mask);
-               return -1;
-       }
-       tbl->current_rate = iwl4965_rate_n_flags_from_tbl(priv,
-                                                tbl, rate, is_green);
-
-       IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n",
-                    tbl->current_rate, is_green);
-       return 0;
-}
-
-/*
- * Set up search table for SISO
- */
-static int iwl4965_rs_switch_to_siso(struct iwl_priv *priv,
-                            struct iwl_lq_sta *lq_sta,
-                            struct ieee80211_conf *conf,
-                            struct ieee80211_sta *sta,
-                            struct iwl_scale_tbl_info *tbl, int index)
-{
-       u16 rate_mask;
-       u8 is_green = lq_sta->is_green;
-       s32 rate;
-       struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
-
-       if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
-               return -1;
-
-       IWL_DEBUG_RATE(priv, "LQ: try to switch to SISO\n");
-
-       tbl->is_dup = lq_sta->is_dup;
-       tbl->lq_type = LQ_SISO;
-       tbl->action = 0;
-       tbl->max_search = IWL_MAX_SEARCH;
-       rate_mask = lq_sta->active_siso_rate;
-
-       if (iwl_legacy_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
-               tbl->is_ht40 = 1;
-       else
-               tbl->is_ht40 = 0;
-
-       if (is_green)
-               tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/
-
-       iwl4965_rs_set_expected_tpt_table(lq_sta, tbl);
-       rate = iwl4965_rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
-
-       IWL_DEBUG_RATE(priv, "LQ: get best rate %d mask %X\n", rate, rate_mask);
-       if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
-               IWL_DEBUG_RATE(priv,
-                       "can not switch with index %d rate mask %x\n",
-                            rate, rate_mask);
-               return -1;
-       }
-       tbl->current_rate = iwl4965_rate_n_flags_from_tbl(priv,
-                                               tbl, rate, is_green);
-       IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n",
-                    tbl->current_rate, is_green);
-       return 0;
-}
-
-/*
- * Try to switch to new modulation mode from legacy
- */
-static int iwl4965_rs_move_legacy_other(struct iwl_priv *priv,
-                               struct iwl_lq_sta *lq_sta,
-                               struct ieee80211_conf *conf,
-                               struct ieee80211_sta *sta,
-                               int index)
-{
-       struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-       struct iwl_scale_tbl_info *search_tbl =
-                               &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
-       struct iwl_rate_scale_data *window = &(tbl->win[index]);
-       u32 sz = (sizeof(struct iwl_scale_tbl_info) -
-                 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
-       u8 start_action;
-       u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
-       u8 tx_chains_num = priv->hw_params.tx_chains_num;
-       int ret = 0;
-       u8 update_search_tbl_counter = 0;
-
-       tbl->action = IWL_LEGACY_SWITCH_SISO;
-
-       start_action = tbl->action;
-       for (; ;) {
-               lq_sta->action_counter++;
-               switch (tbl->action) {
-               case IWL_LEGACY_SWITCH_ANTENNA1:
-               case IWL_LEGACY_SWITCH_ANTENNA2:
-                       IWL_DEBUG_RATE(priv, "LQ: Legacy toggle Antenna\n");
-
-                       if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 &&
-                                                       tx_chains_num <= 1) ||
-                           (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 &&
-                                                       tx_chains_num <= 2))
-                               break;
-
-                       /* Don't change antenna if success has been great */
-                       if (window->success_ratio >= IWL_RS_GOOD_RATIO)
-                               break;
-
-                       /* Set up search table to try other antenna */
-                       memcpy(search_tbl, tbl, sz);
-
-                       if (iwl4965_rs_toggle_antenna(valid_tx_ant,
-                               &search_tbl->current_rate, search_tbl)) {
-                               update_search_tbl_counter = 1;
-                               iwl4965_rs_set_expected_tpt_table(lq_sta,
-                                                               search_tbl);
-                               goto out;
-                       }
-                       break;
-               case IWL_LEGACY_SWITCH_SISO:
-                       IWL_DEBUG_RATE(priv, "LQ: Legacy switch to SISO\n");
-
-                       /* Set up search table to try SISO */
-                       memcpy(search_tbl, tbl, sz);
-                       search_tbl->is_SGI = 0;
-                       ret = iwl4965_rs_switch_to_siso(priv, lq_sta, conf, sta,
-                                                search_tbl, index);
-                       if (!ret) {
-                               lq_sta->action_counter = 0;
-                               goto out;
-                       }
-
-                       break;
-               case IWL_LEGACY_SWITCH_MIMO2_AB:
-               case IWL_LEGACY_SWITCH_MIMO2_AC:
-               case IWL_LEGACY_SWITCH_MIMO2_BC:
-                       IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO2\n");
-
-                       /* Set up search table to try MIMO */
-                       memcpy(search_tbl, tbl, sz);
-                       search_tbl->is_SGI = 0;
-
-                       if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB)
-                               search_tbl->ant_type = ANT_AB;
-                       else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC)
-                               search_tbl->ant_type = ANT_AC;
-                       else
-                               search_tbl->ant_type = ANT_BC;
-
-                       if (!iwl4965_rs_is_valid_ant(valid_tx_ant,
-                                               search_tbl->ant_type))
-                               break;
-
-                       ret = iwl4965_rs_switch_to_mimo2(priv, lq_sta,
-                                               conf, sta,
-                                                search_tbl, index);
-                       if (!ret) {
-                               lq_sta->action_counter = 0;
-                               goto out;
-                       }
-                       break;
-               }
-               tbl->action++;
-               if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
-                       tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
-
-               if (tbl->action == start_action)
-                       break;
-
-       }
-       search_tbl->lq_type = LQ_NONE;
-       return 0;
-
-out:
-       lq_sta->search_better_tbl = 1;
-       tbl->action++;
-       if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
-               tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
-       if (update_search_tbl_counter)
-               search_tbl->action = tbl->action;
-       return 0;
-
-}
-
-/*
- * Try to switch to new modulation mode from SISO
- */
-static int iwl4965_rs_move_siso_to_other(struct iwl_priv *priv,
-                                struct iwl_lq_sta *lq_sta,
-                                struct ieee80211_conf *conf,
-                                struct ieee80211_sta *sta, int index)
-{
-       u8 is_green = lq_sta->is_green;
-       struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-       struct iwl_scale_tbl_info *search_tbl =
-                               &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
-       struct iwl_rate_scale_data *window = &(tbl->win[index]);
-       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-       u32 sz = (sizeof(struct iwl_scale_tbl_info) -
-                 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
-       u8 start_action;
-       u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
-       u8 tx_chains_num = priv->hw_params.tx_chains_num;
-       u8 update_search_tbl_counter = 0;
-       int ret;
-
-       start_action = tbl->action;
-
-       for (;;) {
-               lq_sta->action_counter++;
-               switch (tbl->action) {
-               case IWL_SISO_SWITCH_ANTENNA1:
-               case IWL_SISO_SWITCH_ANTENNA2:
-                       IWL_DEBUG_RATE(priv, "LQ: SISO toggle Antenna\n");
-                       if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 &&
-                                               tx_chains_num <= 1) ||
-                           (tbl->action == IWL_SISO_SWITCH_ANTENNA2 &&
-                                               tx_chains_num <= 2))
-                               break;
-
-                       if (window->success_ratio >= IWL_RS_GOOD_RATIO)
-                               break;
-
-                       memcpy(search_tbl, tbl, sz);
-                       if (iwl4965_rs_toggle_antenna(valid_tx_ant,
-                                      &search_tbl->current_rate, search_tbl)) {
-                               update_search_tbl_counter = 1;
-                               goto out;
-                       }
-                       break;
-               case IWL_SISO_SWITCH_MIMO2_AB:
-               case IWL_SISO_SWITCH_MIMO2_AC:
-               case IWL_SISO_SWITCH_MIMO2_BC:
-                       IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO2\n");
-                       memcpy(search_tbl, tbl, sz);
-                       search_tbl->is_SGI = 0;
-
-                       if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB)
-                               search_tbl->ant_type = ANT_AB;
-                       else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC)
-                               search_tbl->ant_type = ANT_AC;
-                       else
-                               search_tbl->ant_type = ANT_BC;
-
-                       if (!iwl4965_rs_is_valid_ant(valid_tx_ant,
-                                                search_tbl->ant_type))
-                               break;
-
-                       ret = iwl4965_rs_switch_to_mimo2(priv, lq_sta,
-                                               conf, sta,
-                                                search_tbl, index);
-                       if (!ret)
-                               goto out;
-                       break;
-               case IWL_SISO_SWITCH_GI:
-                       if (!tbl->is_ht40 && !(ht_cap->cap &
-                                               IEEE80211_HT_CAP_SGI_20))
-                               break;
-                       if (tbl->is_ht40 && !(ht_cap->cap &
-                                               IEEE80211_HT_CAP_SGI_40))
-                               break;
-
-                       IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n");
-
-                       memcpy(search_tbl, tbl, sz);
-                       if (is_green) {
-                               if (!tbl->is_SGI)
-                                       break;
-                               else
-                                       IWL_ERR(priv,
-                                               "SGI was set in GF+SISO\n");
-                       }
-                       search_tbl->is_SGI = !tbl->is_SGI;
-                       iwl4965_rs_set_expected_tpt_table(lq_sta, search_tbl);
-                       if (tbl->is_SGI) {
-                               s32 tpt = lq_sta->last_tpt / 100;
-                               if (tpt >= search_tbl->expected_tpt[index])
-                                       break;
-                       }
-                       search_tbl->current_rate =
-                               iwl4965_rate_n_flags_from_tbl(priv, search_tbl,
-                                                     index, is_green);
-                       update_search_tbl_counter = 1;
-                       goto out;
-               }
-               tbl->action++;
-               if (tbl->action > IWL_SISO_SWITCH_GI)
-                       tbl->action = IWL_SISO_SWITCH_ANTENNA1;
-
-               if (tbl->action == start_action)
-                       break;
-       }
-       search_tbl->lq_type = LQ_NONE;
-       return 0;
-
- out:
-       lq_sta->search_better_tbl = 1;
-       tbl->action++;
-       if (tbl->action > IWL_SISO_SWITCH_GI)
-               tbl->action = IWL_SISO_SWITCH_ANTENNA1;
-       if (update_search_tbl_counter)
-               search_tbl->action = tbl->action;
-
-       return 0;
-}
-
-/*
- * Try to switch to new modulation mode from MIMO2
- */
-static int iwl4965_rs_move_mimo2_to_other(struct iwl_priv *priv,
-                                struct iwl_lq_sta *lq_sta,
-                                struct ieee80211_conf *conf,
-                                struct ieee80211_sta *sta, int index)
-{
-       s8 is_green = lq_sta->is_green;
-       struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-       struct iwl_scale_tbl_info *search_tbl =
-                               &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
-       struct iwl_rate_scale_data *window = &(tbl->win[index]);
-       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-       u32 sz = (sizeof(struct iwl_scale_tbl_info) -
-                 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
-       u8 start_action;
-       u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
-       u8 tx_chains_num = priv->hw_params.tx_chains_num;
-       u8 update_search_tbl_counter = 0;
-       int ret;
-
-       start_action = tbl->action;
-       for (;;) {
-               lq_sta->action_counter++;
-               switch (tbl->action) {
-               case IWL_MIMO2_SWITCH_ANTENNA1:
-               case IWL_MIMO2_SWITCH_ANTENNA2:
-                       IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle Antennas\n");
-
-                       if (tx_chains_num <= 2)
-                               break;
-
-                       if (window->success_ratio >= IWL_RS_GOOD_RATIO)
-                               break;
-
-                       memcpy(search_tbl, tbl, sz);
-                       if (iwl4965_rs_toggle_antenna(valid_tx_ant,
-                                      &search_tbl->current_rate, search_tbl)) {
-                               update_search_tbl_counter = 1;
-                               goto out;
-                       }
-                       break;
-               case IWL_MIMO2_SWITCH_SISO_A:
-               case IWL_MIMO2_SWITCH_SISO_B:
-               case IWL_MIMO2_SWITCH_SISO_C:
-                       IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to SISO\n");
-
-                       /* Set up new search table for SISO */
-                       memcpy(search_tbl, tbl, sz);
-
-                       if (tbl->action == IWL_MIMO2_SWITCH_SISO_A)
-                               search_tbl->ant_type = ANT_A;
-                       else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B)
-                               search_tbl->ant_type = ANT_B;
-                       else
-                               search_tbl->ant_type = ANT_C;
-
-                       if (!iwl4965_rs_is_valid_ant(valid_tx_ant,
-                                               search_tbl->ant_type))
-                               break;
-
-                       ret = iwl4965_rs_switch_to_siso(priv, lq_sta,
-                                               conf, sta,
-                                                search_tbl, index);
-                       if (!ret)
-                               goto out;
-
-                       break;
-
-               case IWL_MIMO2_SWITCH_GI:
-                       if (!tbl->is_ht40 && !(ht_cap->cap &
-                                               IEEE80211_HT_CAP_SGI_20))
-                               break;
-                       if (tbl->is_ht40 && !(ht_cap->cap &
-                                               IEEE80211_HT_CAP_SGI_40))
-                               break;
-
-                       IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n");
-
-                       /* Set up new search table for MIMO2 */
-                       memcpy(search_tbl, tbl, sz);
-                       search_tbl->is_SGI = !tbl->is_SGI;
-                       iwl4965_rs_set_expected_tpt_table(lq_sta, search_tbl);
-                       /*
-                        * If active table already uses the fastest possible
-                        * modulation (dual stream with short guard interval),
-                        * and it's working well, there's no need to look
-                        * for a better type of modulation!
-                        */
-                       if (tbl->is_SGI) {
-                               s32 tpt = lq_sta->last_tpt / 100;
-                               if (tpt >= search_tbl->expected_tpt[index])
-                                       break;
-                       }
-                       search_tbl->current_rate =
-                               iwl4965_rate_n_flags_from_tbl(priv, search_tbl,
-                                                     index, is_green);
-                       update_search_tbl_counter = 1;
-                       goto out;
-
-               }
-               tbl->action++;
-               if (tbl->action > IWL_MIMO2_SWITCH_GI)
-                       tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
-
-               if (tbl->action == start_action)
-                       break;
-       }
-       search_tbl->lq_type = LQ_NONE;
-       return 0;
- out:
-       lq_sta->search_better_tbl = 1;
-       tbl->action++;
-       if (tbl->action > IWL_MIMO2_SWITCH_GI)
-               tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
-       if (update_search_tbl_counter)
-               search_tbl->action = tbl->action;
-
-       return 0;
-
-}
-
-/*
- * Check whether we should continue using same modulation mode, or
- * begin search for a new mode, based on:
- * 1) # tx successes or failures while using this mode
- * 2) # times calling this function
- * 3) elapsed time in this mode (not used, for now)
- */
-static void
-iwl4965_rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
-{
-       struct iwl_scale_tbl_info *tbl;
-       int i;
-       int active_tbl;
-       int flush_interval_passed = 0;
-       struct iwl_priv *priv;
-
-       priv = lq_sta->drv;
-       active_tbl = lq_sta->active_tbl;
-
-       tbl = &(lq_sta->lq_info[active_tbl]);
-
-       /* If we've been disallowing search, see if we should now allow it */
-       if (lq_sta->stay_in_tbl) {
-
-               /* Elapsed time using current modulation mode */
-               if (lq_sta->flush_timer)
-                       flush_interval_passed =
-                       time_after(jiffies,
-                                       (unsigned long)(lq_sta->flush_timer +
-                                       IWL_RATE_SCALE_FLUSH_INTVL));
-
-               /*
-                * Check if we should allow search for new modulation mode.
-                * If many frames have failed or succeeded, or we've used
-                * this same modulation for a long time, allow search, and
-                * reset history stats that keep track of whether we should
-                * allow a new search.  Also (below) reset all bitmaps and
-                * stats in active history.
-                */
-               if (force_search ||
-                   (lq_sta->total_failed > lq_sta->max_failure_limit) ||
-                   (lq_sta->total_success > lq_sta->max_success_limit) ||
-                   ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer)
-                    && (flush_interval_passed))) {
-                       IWL_DEBUG_RATE(priv, "LQ: stay is expired %d %d %d\n:",
-                                    lq_sta->total_failed,
-                                    lq_sta->total_success,
-                                    flush_interval_passed);
-
-                       /* Allow search for new mode */
-                       lq_sta->stay_in_tbl = 0;        /* only place reset */
-                       lq_sta->total_failed = 0;
-                       lq_sta->total_success = 0;
-                       lq_sta->flush_timer = 0;
-
-               /*
-                * Else if we've used this modulation mode enough repetitions
-                * (regardless of elapsed time or success/failure), reset
-                * history bitmaps and rate-specific stats for all rates in
-                * active table.
-                */
-               } else {
-                       lq_sta->table_count++;
-                       if (lq_sta->table_count >=
-                           lq_sta->table_count_limit) {
-                               lq_sta->table_count = 0;
-
-                               IWL_DEBUG_RATE(priv,
-                                       "LQ: stay in table clear win\n");
-                               for (i = 0; i < IWL_RATE_COUNT; i++)
-                                       iwl4965_rs_rate_scale_clear_window(
-                                               &(tbl->win[i]));
-                       }
-               }
-
-               /* If transitioning to allow "search", reset all history
-                * bitmaps and stats in active table (this will become the new
-                * "search" table). */
-               if (!lq_sta->stay_in_tbl) {
-                       for (i = 0; i < IWL_RATE_COUNT; i++)
-                               iwl4965_rs_rate_scale_clear_window(
-                                                       &(tbl->win[i]));
-               }
-       }
-}
-
-/*
- * setup rate table in uCode
- * return rate_n_flags as used in the table
- */
-static u32 iwl4965_rs_update_rate_tbl(struct iwl_priv *priv,
-                             struct iwl_rxon_context *ctx,
-                               struct iwl_lq_sta *lq_sta,
-                               struct iwl_scale_tbl_info *tbl,
-                               int index, u8 is_green)
-{
-       u32 rate;
-
-       /* Update uCode's rate table. */
-       rate = iwl4965_rate_n_flags_from_tbl(priv, tbl, index, is_green);
-       iwl4965_rs_fill_link_cmd(priv, lq_sta, rate);
-       iwl_legacy_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
-
-       return rate;
-}
-
-/*
- * Do rate scaling and search for new modulation mode.
- */
-static void iwl4965_rs_rate_scale_perform(struct iwl_priv *priv,
-                                 struct sk_buff *skb,
-                                 struct ieee80211_sta *sta,
-                                 struct iwl_lq_sta *lq_sta)
-{
-       struct ieee80211_hw *hw = priv->hw;
-       struct ieee80211_conf *conf = &hw->conf;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       int low = IWL_RATE_INVALID;
-       int high = IWL_RATE_INVALID;
-       int index;
-       int i;
-       struct iwl_rate_scale_data *window = NULL;
-       int current_tpt = IWL_INVALID_VALUE;
-       int low_tpt = IWL_INVALID_VALUE;
-       int high_tpt = IWL_INVALID_VALUE;
-       u32 fail_count;
-       s8 scale_action = 0;
-       u16 rate_mask;
-       u8 update_lq = 0;
-       struct iwl_scale_tbl_info *tbl, *tbl1;
-       u16 rate_scale_index_msk = 0;
-       u32 rate;
-       u8 is_green = 0;
-       u8 active_tbl = 0;
-       u8 done_search = 0;
-       u16 high_low;
-       s32 sr;
-       u8 tid = MAX_TID_COUNT;
-       struct iwl_tid_data *tid_data;
-       struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
-
-       IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n");
-
-       /* Send management frames and NO_ACK data using lowest rate. */
-       /* TODO: this could probably be improved.. */
-       if (!ieee80211_is_data(hdr->frame_control) ||
-           info->flags & IEEE80211_TX_CTL_NO_ACK)
-               return;
-
-       if (!sta || !lq_sta)
-               return;
-
-       lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
-
-       tid = iwl4965_rs_tl_add_packet(lq_sta, hdr);
-       if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) {
-               tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid];
-               if (tid_data->agg.state == IWL_AGG_OFF)
-                       lq_sta->is_agg = 0;
-               else
-                       lq_sta->is_agg = 1;
-       } else
-               lq_sta->is_agg = 0;
-
-       /*
-        * Select rate-scale / modulation-mode table to work with in
-        * the rest of this function:  "search" if searching for better
-        * modulation mode, or "active" if doing rate scaling within a mode.
-        */
-       if (!lq_sta->search_better_tbl)
-               active_tbl = lq_sta->active_tbl;
-       else
-               active_tbl = 1 - lq_sta->active_tbl;
-
-       tbl = &(lq_sta->lq_info[active_tbl]);
-       if (is_legacy(tbl->lq_type))
-               lq_sta->is_green = 0;
-       else
-               lq_sta->is_green = iwl4965_rs_use_green(sta);
-       is_green = lq_sta->is_green;
-
-       /* current tx rate */
-       index = lq_sta->last_txrate_idx;
-
-       IWL_DEBUG_RATE(priv, "Rate scale index %d for type %d\n", index,
-                      tbl->lq_type);
-
-       /* rates available for this association, and for modulation mode */
-       rate_mask = iwl4965_rs_get_supported_rates(lq_sta, hdr, tbl->lq_type);
-
-       IWL_DEBUG_RATE(priv, "mask 0x%04X\n", rate_mask);
-
-       /* mask with station rate restriction */
-       if (is_legacy(tbl->lq_type)) {
-               if (lq_sta->band == IEEE80211_BAND_5GHZ)
-                       /* supp_rates has no CCK bits in A mode */
-                       rate_scale_index_msk = (u16) (rate_mask &
-                               (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
-               else
-                       rate_scale_index_msk = (u16) (rate_mask &
-                                                     lq_sta->supp_rates);
-
-       } else
-               rate_scale_index_msk = rate_mask;
-
-       if (!rate_scale_index_msk)
-               rate_scale_index_msk = rate_mask;
-
-       if (!((1 << index) & rate_scale_index_msk)) {
-               IWL_ERR(priv, "Current Rate is not valid\n");
-               if (lq_sta->search_better_tbl) {
-                       /* revert to active table if search table is not valid*/
-                       tbl->lq_type = LQ_NONE;
-                       lq_sta->search_better_tbl = 0;
-                       tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-                       /* get "active" rate info */
-                       index = iwl4965_hwrate_to_plcp_idx(tbl->current_rate);
-                       rate = iwl4965_rs_update_rate_tbl(priv, ctx, lq_sta,
-                                                 tbl, index, is_green);
-               }
-               return;
-       }
-
-       /* Get expected throughput table and history window for current rate */
-       if (!tbl->expected_tpt) {
-               IWL_ERR(priv, "tbl->expected_tpt is NULL\n");
-               return;
-       }
-
-       /* force user max rate if set by user */
-       if ((lq_sta->max_rate_idx != -1) &&
-           (lq_sta->max_rate_idx < index)) {
-               index = lq_sta->max_rate_idx;
-               update_lq = 1;
-               window = &(tbl->win[index]);
-               goto lq_update;
-       }
-
-       window = &(tbl->win[index]);
-
-       /*
-        * If there is not enough history to calculate actual average
-        * throughput, keep analyzing results of more tx frames, without
-        * changing rate or mode (bypass most of the rest of this function).
-        * Set up new rate table in uCode only if old rate is not supported
-        * in current association (use new rate found above).
-        */
-       fail_count = window->counter - window->success_counter;
-       if ((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
-                       (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) {
-               IWL_DEBUG_RATE(priv, "LQ: still below TH. succ=%d total=%d "
-                              "for index %d\n",
-                              window->success_counter, window->counter, index);
-
-               /* Can't calculate this yet; not enough history */
-               window->average_tpt = IWL_INVALID_VALUE;
-
-               /* Should we stay with this modulation mode,
-                * or search for a new one? */
-               iwl4965_rs_stay_in_table(lq_sta, false);
-
-               goto out;
-       }
-       /* Else we have enough samples; calculate estimate of
-        * actual average throughput */
-       if (window->average_tpt != ((window->success_ratio *
-                       tbl->expected_tpt[index] + 64) / 128)) {
-               IWL_ERR(priv,
-                        "expected_tpt should have been calculated by now\n");
-               window->average_tpt = ((window->success_ratio *
-                                       tbl->expected_tpt[index] + 64) / 128);
-       }
-
-       /* If we are searching for better modulation mode, check success. */
-       if (lq_sta->search_better_tbl) {
-               /* If good success, continue using the "search" mode;
-                * no need to send new link quality command, since we're
-                * continuing to use the setup that we've been trying. */
-               if (window->average_tpt > lq_sta->last_tpt) {
-
-                       IWL_DEBUG_RATE(priv, "LQ: SWITCHING TO NEW TABLE "
-                                       "suc=%d cur-tpt=%d old-tpt=%d\n",
-                                       window->success_ratio,
-                                       window->average_tpt,
-                                       lq_sta->last_tpt);
-
-                       if (!is_legacy(tbl->lq_type))
-                               lq_sta->enable_counter = 1;
-
-                       /* Swap tables; "search" becomes "active" */
-                       lq_sta->active_tbl = active_tbl;
-                       current_tpt = window->average_tpt;
-
-               /* Else poor success; go back to mode in "active" table */
-               } else {
-
-                       IWL_DEBUG_RATE(priv, "LQ: GOING BACK TO THE OLD TABLE "
-                                       "suc=%d cur-tpt=%d old-tpt=%d\n",
-                                       window->success_ratio,
-                                       window->average_tpt,
-                                       lq_sta->last_tpt);
-
-                       /* Nullify "search" table */
-                       tbl->lq_type = LQ_NONE;
-
-                       /* Revert to "active" table */
-                       active_tbl = lq_sta->active_tbl;
-                       tbl = &(lq_sta->lq_info[active_tbl]);
-
-                       /* Revert to "active" rate and throughput info */
-                       index = iwl4965_hwrate_to_plcp_idx(tbl->current_rate);
-                       current_tpt = lq_sta->last_tpt;
-
-                       /* Need to set up a new rate table in uCode */
-                       update_lq = 1;
-               }
-
-               /* Either way, we've made a decision; modulation mode
-                * search is done, allow rate adjustment next time. */
-               lq_sta->search_better_tbl = 0;
-               done_search = 1;        /* Don't switch modes below! */
-               goto lq_update;
-       }
-
-       /* (Else) not in search of better modulation mode, try for better
-        * starting rate, while staying in this mode. */
-       high_low = iwl4965_rs_get_adjacent_rate(priv, index,
-                                       rate_scale_index_msk,
-                                       tbl->lq_type);
-       low = high_low & 0xff;
-       high = (high_low >> 8) & 0xff;
-
-       /* If user set max rate, dont allow higher than user constrain */
-       if ((lq_sta->max_rate_idx != -1) &&
-           (lq_sta->max_rate_idx < high))
-               high = IWL_RATE_INVALID;
-
-       sr = window->success_ratio;
-
-       /* Collect measured throughputs for current and adjacent rates */
-       current_tpt = window->average_tpt;
-       if (low != IWL_RATE_INVALID)
-               low_tpt = tbl->win[low].average_tpt;
-       if (high != IWL_RATE_INVALID)
-               high_tpt = tbl->win[high].average_tpt;
-
-       scale_action = 0;
-
-       /* Too many failures, decrease rate */
-       if ((sr <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) {
-               IWL_DEBUG_RATE(priv,
-                       "decrease rate because of low success_ratio\n");
-               scale_action = -1;
-
-       /* No throughput measured yet for adjacent rates; try increase. */
-       } else if ((low_tpt == IWL_INVALID_VALUE) &&
-                  (high_tpt == IWL_INVALID_VALUE)) {
-
-               if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH)
-                       scale_action = 1;
-               else if (low != IWL_RATE_INVALID)
-                       scale_action = 0;
-       }
-
-       /* Both adjacent throughputs are measured, but neither one has better
-        * throughput; we're using the best rate, don't change it! */
-       else if ((low_tpt != IWL_INVALID_VALUE) &&
-                (high_tpt != IWL_INVALID_VALUE) &&
-                (low_tpt < current_tpt) &&
-                (high_tpt < current_tpt))
-               scale_action = 0;
-
-       /* At least one adjacent rate's throughput is measured,
-        * and may have better performance. */
-       else {
-               /* Higher adjacent rate's throughput is measured */
-               if (high_tpt != IWL_INVALID_VALUE) {
-                       /* Higher rate has better throughput */
-                       if (high_tpt > current_tpt &&
-                                       sr >= IWL_RATE_INCREASE_TH) {
-                               scale_action = 1;
-                       } else {
-                               scale_action = 0;
-                       }
-
-               /* Lower adjacent rate's throughput is measured */
-               } else if (low_tpt != IWL_INVALID_VALUE) {
-                       /* Lower rate has better throughput */
-                       if (low_tpt > current_tpt) {
-                               IWL_DEBUG_RATE(priv,
-                                   "decrease rate because of low tpt\n");
-                               scale_action = -1;
-                       } else if (sr >= IWL_RATE_INCREASE_TH) {
-                               scale_action = 1;
-                       }
-               }
-       }
-
-       /* Sanity check; asked for decrease, but success rate or throughput
-        * has been good at old rate.  Don't change it. */
-       if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
-                   ((sr > IWL_RATE_HIGH_TH) ||
-                    (current_tpt > (100 * tbl->expected_tpt[low]))))
-               scale_action = 0;
-
-       switch (scale_action) {
-       case -1:
-               /* Decrease starting rate, update uCode's rate table */
-               if (low != IWL_RATE_INVALID) {
-                       update_lq = 1;
-                       index = low;
-               }
-
-               break;
-       case 1:
-               /* Increase starting rate, update uCode's rate table */
-               if (high != IWL_RATE_INVALID) {
-                       update_lq = 1;
-                       index = high;
-               }
-
-               break;
-       case 0:
-               /* No change */
-       default:
-               break;
-       }
-
-       IWL_DEBUG_RATE(priv, "choose rate scale index %d action %d low %d "
-                   "high %d type %d\n",
-                    index, scale_action, low, high, tbl->lq_type);
-
-lq_update:
-       /* Replace uCode's rate table for the destination station. */
-       if (update_lq)
-               rate = iwl4965_rs_update_rate_tbl(priv, ctx, lq_sta,
-                                         tbl, index, is_green);
-
-       /* Should we stay with this modulation mode,
-        * or search for a new one? */
-        iwl4965_rs_stay_in_table(lq_sta, false);
-
-       /*
-        * Search for new modulation mode if we're:
-        * 1)  Not changing rates right now
-        * 2)  Not just finishing up a search
-        * 3)  Allowing a new search
-        */
-       if (!update_lq && !done_search &&
-               !lq_sta->stay_in_tbl && window->counter) {
-               /* Save current throughput to compare with "search" throughput*/
-               lq_sta->last_tpt = current_tpt;
-
-               /* Select a new "search" modulation mode to try.
-                * If one is found, set up the new "search" table. */
-               if (is_legacy(tbl->lq_type))
-                       iwl4965_rs_move_legacy_other(priv, lq_sta,
-                                                       conf, sta, index);
-               else if (is_siso(tbl->lq_type))
-                       iwl4965_rs_move_siso_to_other(priv, lq_sta,
-                                                       conf, sta, index);
-               else /* (is_mimo2(tbl->lq_type)) */
-                       iwl4965_rs_move_mimo2_to_other(priv, lq_sta,
-                                                       conf, sta, index);
-
-               /* If new "search" mode was selected, set up in uCode table */
-               if (lq_sta->search_better_tbl) {
-                       /* Access the "search" table, clear its history. */
-                       tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
-                       for (i = 0; i < IWL_RATE_COUNT; i++)
-                               iwl4965_rs_rate_scale_clear_window(
-                                                       &(tbl->win[i]));
-
-                       /* Use new "search" start rate */
-                       index = iwl4965_hwrate_to_plcp_idx(tbl->current_rate);
-
-                       IWL_DEBUG_RATE(priv,
-                               "Switch current  mcs: %X index: %d\n",
-                                    tbl->current_rate, index);
-                       iwl4965_rs_fill_link_cmd(priv, lq_sta,
-                                               tbl->current_rate);
-                       iwl_legacy_send_lq_cmd(priv, ctx,
-                                               &lq_sta->lq, CMD_ASYNC, false);
-               } else
-                       done_search = 1;
-       }
-
-       if (done_search && !lq_sta->stay_in_tbl) {
-               /* If the "active" (non-search) mode was legacy,
-                * and we've tried switching antennas,
-                * but we haven't been able to try HT modes (not available),
-                * stay with best antenna legacy modulation for a while
-                * before next round of mode comparisons. */
-               tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
-               if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) &&
-                   lq_sta->action_counter > tbl1->max_search) {
-                       IWL_DEBUG_RATE(priv, "LQ: STAY in legacy table\n");
-                       iwl4965_rs_set_stay_in_table(priv, 1, lq_sta);
-               }
-
-               /* If we're in an HT mode, and all 3 mode switch actions
-                * have been tried and compared, stay in this best modulation
-                * mode for a while before next round of mode comparisons. */
-               if (lq_sta->enable_counter &&
-                   (lq_sta->action_counter >= tbl1->max_search)) {
-                       if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
-                           (lq_sta->tx_agg_tid_en & (1 << tid)) &&
-                           (tid != MAX_TID_COUNT)) {
-                               tid_data =
-                                  &priv->stations[lq_sta->lq.sta_id].tid[tid];
-                               if (tid_data->agg.state == IWL_AGG_OFF) {
-                                       IWL_DEBUG_RATE(priv,
-                                                      "try to aggregate tid %d\n",
-                                                      tid);
-                                       iwl4965_rs_tl_turn_on_agg(priv, tid,
-                                                         lq_sta, sta);
-                               }
-                       }
-                       iwl4965_rs_set_stay_in_table(priv, 0, lq_sta);
-               }
-       }
-
-out:
-       tbl->current_rate = iwl4965_rate_n_flags_from_tbl(priv, tbl,
-                                                       index, is_green);
-       i = index;
-       lq_sta->last_txrate_idx = i;
-}
-
-/**
- * iwl4965_rs_initialize_lq - Initialize a station's hardware rate table
- *
- * The uCode's station table contains a table of fallback rates
- * for automatic fallback during transmission.
- *
- * NOTE: This sets up a default set of values.  These will be replaced later
- *       if the driver's iwl-4965-rs rate scaling algorithm is used, instead of
- *       rc80211_simple.
- *
- * NOTE: Run REPLY_ADD_STA command to set up station table entry, before
- *       calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
- *       which requires station table entry to exist).
- */
-static void iwl4965_rs_initialize_lq(struct iwl_priv *priv,
-                            struct ieee80211_conf *conf,
-                            struct ieee80211_sta *sta,
-                            struct iwl_lq_sta *lq_sta)
-{
-       struct iwl_scale_tbl_info *tbl;
-       int rate_idx;
-       int i;
-       u32 rate;
-       u8 use_green = iwl4965_rs_use_green(sta);
-       u8 active_tbl = 0;
-       u8 valid_tx_ant;
-       struct iwl_station_priv *sta_priv;
-       struct iwl_rxon_context *ctx;
-
-       if (!sta || !lq_sta)
-               return;
-
-       sta_priv = (void *)sta->drv_priv;
-       ctx = sta_priv->common.ctx;
-
-       i = lq_sta->last_txrate_idx;
-
-       valid_tx_ant = priv->hw_params.valid_tx_ant;
-
-       if (!lq_sta->search_better_tbl)
-               active_tbl = lq_sta->active_tbl;
-       else
-               active_tbl = 1 - lq_sta->active_tbl;
-
-       tbl = &(lq_sta->lq_info[active_tbl]);
-
-       if ((i < 0) || (i >= IWL_RATE_COUNT))
-               i = 0;
-
-       rate = iwlegacy_rates[i].plcp;
-       tbl->ant_type = iwl4965_first_antenna(valid_tx_ant);
-       rate |= tbl->ant_type << RATE_MCS_ANT_POS;
-
-       if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE)
-               rate |= RATE_MCS_CCK_MSK;
-
-       iwl4965_rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx);
-       if (!iwl4965_rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
-               iwl4965_rs_toggle_antenna(valid_tx_ant, &rate, tbl);
-
-       rate = iwl4965_rate_n_flags_from_tbl(priv, tbl, rate_idx, use_green);
-       tbl->current_rate = rate;
-       iwl4965_rs_set_expected_tpt_table(lq_sta, tbl);
-       iwl4965_rs_fill_link_cmd(NULL, lq_sta, rate);
-       priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
-       iwl_legacy_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true);
-}
-
-static void
-iwl4965_rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
-                       struct ieee80211_tx_rate_control *txrc)
-{
-
-       struct sk_buff *skb = txrc->skb;
-       struct ieee80211_supported_band *sband = txrc->sband;
-       struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct iwl_lq_sta *lq_sta = priv_sta;
-       int rate_idx;
-
-       IWL_DEBUG_RATE_LIMIT(priv, "rate scale calculate new rate for skb\n");
-
-       /* Get max rate if user set max rate */
-       if (lq_sta) {
-               lq_sta->max_rate_idx = txrc->max_rate_idx;
-               if ((sband->band == IEEE80211_BAND_5GHZ) &&
-                   (lq_sta->max_rate_idx != -1))
-                       lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE;
-               if ((lq_sta->max_rate_idx < 0) ||
-                   (lq_sta->max_rate_idx >= IWL_RATE_COUNT))
-                       lq_sta->max_rate_idx = -1;
-       }
-
-       /* Treat uninitialized rate scaling data same as non-existing. */
-       if (lq_sta && !lq_sta->drv) {
-               IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n");
-               priv_sta = NULL;
-       }
-
-       /* Send management frames and NO_ACK data using lowest rate. */
-       if (rate_control_send_low(sta, priv_sta, txrc))
-               return;
-
-       if (!lq_sta)
-               return;
-
-       rate_idx  = lq_sta->last_txrate_idx;
-
-       if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
-               rate_idx -= IWL_FIRST_OFDM_RATE;
-               /* 6M and 9M shared same MCS index */
-               rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0;
-               if (iwl4965_rs_extract_rate(lq_sta->last_rate_n_flags) >=
-                        IWL_RATE_MIMO2_6M_PLCP)
-                       rate_idx = rate_idx + MCS_INDEX_PER_STREAM;
-               info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
-               if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK)
-                       info->control.rates[0].flags |=
-                                       IEEE80211_TX_RC_SHORT_GI;
-               if (lq_sta->last_rate_n_flags & RATE_MCS_DUP_MSK)
-                       info->control.rates[0].flags |=
-                                       IEEE80211_TX_RC_DUP_DATA;
-               if (lq_sta->last_rate_n_flags & RATE_MCS_HT40_MSK)
-                       info->control.rates[0].flags |=
-                                       IEEE80211_TX_RC_40_MHZ_WIDTH;
-               if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK)
-                       info->control.rates[0].flags |=
-                                       IEEE80211_TX_RC_GREEN_FIELD;
-       } else {
-               /* Check for invalid rates */
-               if ((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT_LEGACY) ||
-                               ((sband->band == IEEE80211_BAND_5GHZ) &&
-                                (rate_idx < IWL_FIRST_OFDM_RATE)))
-                       rate_idx = rate_lowest_index(sband, sta);
-               /* On valid 5 GHz rate, adjust index */
-               else if (sband->band == IEEE80211_BAND_5GHZ)
-                       rate_idx -= IWL_FIRST_OFDM_RATE;
-               info->control.rates[0].flags = 0;
-       }
-       info->control.rates[0].idx = rate_idx;
-
-}
-
-static void *iwl4965_rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
-                         gfp_t gfp)
-{
-       struct iwl_lq_sta *lq_sta;
-       struct iwl_station_priv *sta_priv =
-                               (struct iwl_station_priv *) sta->drv_priv;
-       struct iwl_priv *priv;
-
-       priv = (struct iwl_priv *)priv_rate;
-       IWL_DEBUG_RATE(priv, "create station rate scale window\n");
-
-       lq_sta = &sta_priv->lq_sta;
-
-       return lq_sta;
-}
-
-/*
- * Called after adding a new station to initialize rate scaling
- */
-void
-iwl4965_rs_rate_init(struct iwl_priv *priv,
-                       struct ieee80211_sta *sta,
-                       u8 sta_id)
-{
-       int i, j;
-       struct ieee80211_hw *hw = priv->hw;
-       struct ieee80211_conf *conf = &priv->hw->conf;
-       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-       struct iwl_station_priv *sta_priv;
-       struct iwl_lq_sta *lq_sta;
-       struct ieee80211_supported_band *sband;
-
-       sta_priv = (struct iwl_station_priv *) sta->drv_priv;
-       lq_sta = &sta_priv->lq_sta;
-       sband = hw->wiphy->bands[conf->channel->band];
-
-
-       lq_sta->lq.sta_id = sta_id;
-
-       for (j = 0; j < LQ_SIZE; j++)
-               for (i = 0; i < IWL_RATE_COUNT; i++)
-                       iwl4965_rs_rate_scale_clear_window(
-                                       &lq_sta->lq_info[j].win[i]);
-
-       lq_sta->flush_timer = 0;
-       lq_sta->supp_rates = sta->supp_rates[sband->band];
-       for (j = 0; j < LQ_SIZE; j++)
-               for (i = 0; i < IWL_RATE_COUNT; i++)
-                       iwl4965_rs_rate_scale_clear_window(
-                                       &lq_sta->lq_info[j].win[i]);
-
-       IWL_DEBUG_RATE(priv, "LQ:"
-                       "*** rate scale station global init for station %d ***\n",
-                      sta_id);
-       /* TODO: what is a good starting rate for STA? About middle? Maybe not
-        * the lowest or the highest rate.. Could consider using RSSI from
-        * previous packets? Need to have IEEE 802.1X auth succeed immediately
-        * after assoc.. */
-
-       lq_sta->is_dup = 0;
-       lq_sta->max_rate_idx = -1;
-       lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
-       lq_sta->is_green = iwl4965_rs_use_green(sta);
-       lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
-       lq_sta->band = priv->band;
-       /*
-        * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
-        * supp_rates[] does not; shift to convert format, force 9 MBits off.
-        */
-       lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1;
-       lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1;
-       lq_sta->active_siso_rate &= ~((u16)0x2);
-       lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
-
-       /* Same here */
-       lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1;
-       lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1;
-       lq_sta->active_mimo2_rate &= ~((u16)0x2);
-       lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
-
-       /* These values will be overridden later */
-       lq_sta->lq.general_params.single_stream_ant_msk =
-               iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
-       lq_sta->lq.general_params.dual_stream_ant_msk =
-               priv->hw_params.valid_tx_ant &
-               ~iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
-       if (!lq_sta->lq.general_params.dual_stream_ant_msk) {
-               lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
-       } else if (iwl4965_num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
-               lq_sta->lq.general_params.dual_stream_ant_msk =
-                       priv->hw_params.valid_tx_ant;
-       }
-
-       /* as default allow aggregation for all tids */
-       lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
-       lq_sta->drv = priv;
-
-       /* Set last_txrate_idx to lowest rate */
-       lq_sta->last_txrate_idx = rate_lowest_index(sband, sta);
-       if (sband->band == IEEE80211_BAND_5GHZ)
-               lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
-       lq_sta->is_agg = 0;
-
-#ifdef CONFIG_MAC80211_DEBUGFS
-       lq_sta->dbg_fixed_rate = 0;
-#endif
-
-       iwl4965_rs_initialize_lq(priv, conf, sta, lq_sta);
-}
-
-static void iwl4965_rs_fill_link_cmd(struct iwl_priv *priv,
-                            struct iwl_lq_sta *lq_sta, u32 new_rate)
-{
-       struct iwl_scale_tbl_info tbl_type;
-       int index = 0;
-       int rate_idx;
-       int repeat_rate = 0;
-       u8 ant_toggle_cnt = 0;
-       u8 use_ht_possible = 1;
-       u8 valid_tx_ant = 0;
-       struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq;
-
-       /* Override starting rate (index 0) if needed for debug purposes */
-       iwl4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
-
-       /* Interpret new_rate (rate_n_flags) */
-       iwl4965_rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
-                                 &tbl_type, &rate_idx);
-
-       /* How many times should we repeat the initial rate? */
-       if (is_legacy(tbl_type.lq_type)) {
-               ant_toggle_cnt = 1;
-               repeat_rate = IWL_NUMBER_TRY;
-       } else {
-               repeat_rate = IWL_HT_NUMBER_TRY;
-       }
-
-       lq_cmd->general_params.mimo_delimiter =
-                       is_mimo(tbl_type.lq_type) ? 1 : 0;
-
-       /* Fill 1st table entry (index 0) */
-       lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate);
-
-       if (iwl4965_num_of_ant(tbl_type.ant_type) == 1) {
-               lq_cmd->general_params.single_stream_ant_msk =
-                                               tbl_type.ant_type;
-       } else if (iwl4965_num_of_ant(tbl_type.ant_type) == 2) {
-               lq_cmd->general_params.dual_stream_ant_msk =
-                                               tbl_type.ant_type;
-       } /* otherwise we don't modify the existing value */
-
-       index++;
-       repeat_rate--;
-       if (priv)
-               valid_tx_ant = priv->hw_params.valid_tx_ant;
-
-       /* Fill rest of rate table */
-       while (index < LINK_QUAL_MAX_RETRY_NUM) {
-               /* Repeat initial/next rate.
-                * For legacy IWL_NUMBER_TRY == 1, this loop will not execute.
-                * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
-               while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
-                       if (is_legacy(tbl_type.lq_type)) {
-                               if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
-                                       ant_toggle_cnt++;
-                               else if (priv &&
-                                        iwl4965_rs_toggle_antenna(valid_tx_ant,
-                                                       &new_rate, &tbl_type))
-                                       ant_toggle_cnt = 1;
-                       }
-
-                       /* Override next rate if needed for debug purposes */
-                       iwl4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
-
-                       /* Fill next table entry */
-                       lq_cmd->rs_table[index].rate_n_flags =
-                                       cpu_to_le32(new_rate);
-                       repeat_rate--;
-                       index++;
-               }
-
-               iwl4965_rs_get_tbl_info_from_mcs(new_rate,
-                                               lq_sta->band, &tbl_type,
-                                               &rate_idx);
-
-               /* Indicate to uCode which entries might be MIMO.
-                * If initial rate was MIMO, this will finally end up
-                * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */
-               if (is_mimo(tbl_type.lq_type))
-                       lq_cmd->general_params.mimo_delimiter = index;
-
-               /* Get next rate */
-               new_rate = iwl4965_rs_get_lower_rate(lq_sta,
-                                       &tbl_type, rate_idx,
-                                            use_ht_possible);
-
-               /* How many times should we repeat the next rate? */
-               if (is_legacy(tbl_type.lq_type)) {
-                       if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
-                               ant_toggle_cnt++;
-                       else if (priv &&
-                                iwl4965_rs_toggle_antenna(valid_tx_ant,
-                                                  &new_rate, &tbl_type))
-                               ant_toggle_cnt = 1;
-
-                       repeat_rate = IWL_NUMBER_TRY;
-               } else {
-                       repeat_rate = IWL_HT_NUMBER_TRY;
-               }
-
-               /* Don't allow HT rates after next pass.
-                * iwl4965_rs_get_lower_rate() will change type to LQ_A or LQ_G. */
-               use_ht_possible = 0;
-
-               /* Override next rate if needed for debug purposes */
-               iwl4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
-
-               /* Fill next table entry */
-               lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate);
-
-               index++;
-               repeat_rate--;
-       }
-
-       lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
-       lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
-
-       lq_cmd->agg_params.agg_time_limit =
-               cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
-}
-
-static void
-*iwl4965_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
-{
-       return hw->priv;
-}
-/* rate scale requires free function to be implemented */
-static void iwl4965_rs_free(void *priv_rate)
-{
-       return;
-}
-
-static void iwl4965_rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
-                       void *priv_sta)
-{
-       struct iwl_priv *priv __maybe_unused = priv_r;
-
-       IWL_DEBUG_RATE(priv, "enter\n");
-       IWL_DEBUG_RATE(priv, "leave\n");
-}
-
-
-#ifdef CONFIG_MAC80211_DEBUGFS
-static int iwl4965_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-static void iwl4965_rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
-                            u32 *rate_n_flags, int index)
-{
-       struct iwl_priv *priv;
-       u8 valid_tx_ant;
-       u8 ant_sel_tx;
-
-       priv = lq_sta->drv;
-       valid_tx_ant = priv->hw_params.valid_tx_ant;
-       if (lq_sta->dbg_fixed_rate) {
-               ant_sel_tx =
-                 ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK)
-                 >> RATE_MCS_ANT_POS);
-               if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) {
-                       *rate_n_flags = lq_sta->dbg_fixed_rate;
-                       IWL_DEBUG_RATE(priv, "Fixed rate ON\n");
-               } else {
-                       lq_sta->dbg_fixed_rate = 0;
-                       IWL_ERR(priv,
-                           "Invalid antenna selection 0x%X, Valid is 0x%X\n",
-                           ant_sel_tx, valid_tx_ant);
-                       IWL_DEBUG_RATE(priv, "Fixed rate OFF\n");
-               }
-       } else {
-               IWL_DEBUG_RATE(priv, "Fixed rate OFF\n");
-       }
-}
-
-static ssize_t iwl4965_rs_sta_dbgfs_scale_table_write(struct file *file,
-                       const char __user *user_buf, size_t count, loff_t *ppos)
-{
-       struct iwl_lq_sta *lq_sta = file->private_data;
-       struct iwl_priv *priv;
-       char buf[64];
-       size_t buf_size;
-       u32 parsed_rate;
-       struct iwl_station_priv *sta_priv =
-               container_of(lq_sta, struct iwl_station_priv, lq_sta);
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
-
-       priv = lq_sta->drv;
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-
-       if (sscanf(buf, "%x", &parsed_rate) == 1)
-               lq_sta->dbg_fixed_rate = parsed_rate;
-       else
-               lq_sta->dbg_fixed_rate = 0;
-
-       lq_sta->active_legacy_rate = 0x0FFF;    /* 1 - 54 MBits, includes CCK */
-       lq_sta->active_siso_rate   = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
-       lq_sta->active_mimo2_rate  = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
-
-       IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
-               lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
-
-       if (lq_sta->dbg_fixed_rate) {
-               iwl4965_rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
-               iwl_legacy_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
-                               false);
-       }
-
-       return count;
-}
-
-static ssize_t iwl4965_rs_sta_dbgfs_scale_table_read(struct file *file,
-                       char __user *user_buf, size_t count, loff_t *ppos)
-{
-       char *buff;
-       int desc = 0;
-       int i = 0;
-       int index = 0;
-       ssize_t ret;
-
-       struct iwl_lq_sta *lq_sta = file->private_data;
-       struct iwl_priv *priv;
-       struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-
-       priv = lq_sta->drv;
-       buff = kmalloc(1024, GFP_KERNEL);
-       if (!buff)
-               return -ENOMEM;
-
-       desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id);
-       desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n",
-                       lq_sta->total_failed, lq_sta->total_success,
-                       lq_sta->active_legacy_rate);
-       desc += sprintf(buff+desc, "fixed rate 0x%X\n",
-                       lq_sta->dbg_fixed_rate);
-       desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
-           (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",
-           (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "",
-           (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : "");
-       desc += sprintf(buff+desc, "lq type %s\n",
-          (is_legacy(tbl->lq_type)) ? "legacy" : "HT");
-       if (is_Ht(tbl->lq_type)) {
-               desc += sprintf(buff+desc, " %s",
-                  (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2");
-                  desc += sprintf(buff+desc, " %s",
-                  (tbl->is_ht40) ? "40MHz" : "20MHz");
-                  desc += sprintf(buff+desc, " %s %s %s\n",
-                       (tbl->is_SGI) ? "SGI" : "",
-                  (lq_sta->is_green) ? "GF enabled" : "",
-                  (lq_sta->is_agg) ? "AGG on" : "");
-       }
-       desc += sprintf(buff+desc, "last tx rate=0x%X\n",
-               lq_sta->last_rate_n_flags);
-       desc += sprintf(buff+desc, "general:"
-               "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n",
-               lq_sta->lq.general_params.flags,
-               lq_sta->lq.general_params.mimo_delimiter,
-               lq_sta->lq.general_params.single_stream_ant_msk,
-               lq_sta->lq.general_params.dual_stream_ant_msk);
-
-       desc += sprintf(buff+desc, "agg:"
-                       "time_limit=%d dist_start_th=%d frame_cnt_limit=%d\n",
-                       le16_to_cpu(lq_sta->lq.agg_params.agg_time_limit),
-                       lq_sta->lq.agg_params.agg_dis_start_th,
-                       lq_sta->lq.agg_params.agg_frame_cnt_limit);
-
-       desc += sprintf(buff+desc,
-                       "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n",
-                       lq_sta->lq.general_params.start_rate_index[0],
-                       lq_sta->lq.general_params.start_rate_index[1],
-                       lq_sta->lq.general_params.start_rate_index[2],
-                       lq_sta->lq.general_params.start_rate_index[3]);
-
-       for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
-               index = iwl4965_hwrate_to_plcp_idx(
-                       le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
-               if (is_legacy(tbl->lq_type)) {
-                       desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n",
-                       i,
-                       le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags),
-                       iwl_rate_mcs[index].mbps);
-               } else {
-                       desc += sprintf(buff+desc,
-                       " rate[%d] 0x%X %smbps (%s)\n",
-                       i,
-                       le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags),
-                       iwl_rate_mcs[index].mbps, iwl_rate_mcs[index].mcs);
-               }
-       }
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
-       kfree(buff);
-       return ret;
-}
-
-static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
-       .write = iwl4965_rs_sta_dbgfs_scale_table_write,
-       .read = iwl4965_rs_sta_dbgfs_scale_table_read,
-       .open = iwl4965_open_file_generic,
-       .llseek = default_llseek,
-};
-static ssize_t iwl4965_rs_sta_dbgfs_stats_table_read(struct file *file,
-                       char __user *user_buf, size_t count, loff_t *ppos)
-{
-       char *buff;
-       int desc = 0;
-       int i, j;
-       ssize_t ret;
-
-       struct iwl_lq_sta *lq_sta = file->private_data;
-
-       buff = kmalloc(1024, GFP_KERNEL);
-       if (!buff)
-               return -ENOMEM;
-
-       for (i = 0; i < LQ_SIZE; i++) {
-               desc += sprintf(buff+desc,
-                               "%s type=%d SGI=%d HT40=%d DUP=%d GF=%d\n"
-                               "rate=0x%X\n",
-                               lq_sta->active_tbl == i ? "*" : "x",
-                               lq_sta->lq_info[i].lq_type,
-                               lq_sta->lq_info[i].is_SGI,
-                               lq_sta->lq_info[i].is_ht40,
-                               lq_sta->lq_info[i].is_dup,
-                               lq_sta->is_green,
-                               lq_sta->lq_info[i].current_rate);
-               for (j = 0; j < IWL_RATE_COUNT; j++) {
-                       desc += sprintf(buff+desc,
-                               "counter=%d success=%d %%=%d\n",
-                               lq_sta->lq_info[i].win[j].counter,
-                               lq_sta->lq_info[i].win[j].success_counter,
-                               lq_sta->lq_info[i].win[j].success_ratio);
-               }
-       }
-       ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
-       kfree(buff);
-       return ret;
-}
-
-static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
-       .read = iwl4965_rs_sta_dbgfs_stats_table_read,
-       .open = iwl4965_open_file_generic,
-       .llseek = default_llseek,
-};
-
-static ssize_t iwl4965_rs_sta_dbgfs_rate_scale_data_read(struct file *file,
-                       char __user *user_buf, size_t count, loff_t *ppos)
-{
-       char buff[120];
-       int desc = 0;
-       ssize_t ret;
-
-       struct iwl_lq_sta *lq_sta = file->private_data;
-       struct iwl_priv *priv;
-       struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
-
-       priv = lq_sta->drv;
-
-       if (is_Ht(tbl->lq_type))
-               desc += sprintf(buff+desc,
-                               "Bit Rate= %d Mb/s\n",
-                               tbl->expected_tpt[lq_sta->last_txrate_idx]);
-       else
-               desc += sprintf(buff+desc,
-                               "Bit Rate= %d Mb/s\n",
-                               iwlegacy_rates[lq_sta->last_txrate_idx].ieee >> 1);
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
-       return ret;
-}
-
-static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
-       .read = iwl4965_rs_sta_dbgfs_rate_scale_data_read,
-       .open = iwl4965_open_file_generic,
-       .llseek = default_llseek,
-};
-
-static void iwl4965_rs_add_debugfs(void *priv, void *priv_sta,
-                                       struct dentry *dir)
-{
-       struct iwl_lq_sta *lq_sta = priv_sta;
-       lq_sta->rs_sta_dbgfs_scale_table_file =
-               debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir,
-                               lq_sta, &rs_sta_dbgfs_scale_table_ops);
-       lq_sta->rs_sta_dbgfs_stats_table_file =
-               debugfs_create_file("rate_stats_table", S_IRUSR, dir,
-                       lq_sta, &rs_sta_dbgfs_stats_table_ops);
-       lq_sta->rs_sta_dbgfs_rate_scale_data_file =
-               debugfs_create_file("rate_scale_data", S_IRUSR, dir,
-                       lq_sta, &rs_sta_dbgfs_rate_scale_data_ops);
-       lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
-               debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
-               &lq_sta->tx_agg_tid_en);
-
-}
-
-static void iwl4965_rs_remove_debugfs(void *priv, void *priv_sta)
-{
-       struct iwl_lq_sta *lq_sta = priv_sta;
-       debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
-       debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
-       debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file);
-       debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
-}
-#endif
-
-/*
- * Initialization of rate scaling information is done by driver after
- * the station is added. Since mac80211 calls this function before a
- * station is added we ignore it.
- */
-static void
-iwl4965_rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband,
-                        struct ieee80211_sta *sta, void *priv_sta)
-{
-}
-static struct rate_control_ops rs_4965_ops = {
-       .module = NULL,
-       .name = IWL4965_RS_NAME,
-       .tx_status = iwl4965_rs_tx_status,
-       .get_rate = iwl4965_rs_get_rate,
-       .rate_init = iwl4965_rs_rate_init_stub,
-       .alloc = iwl4965_rs_alloc,
-       .free = iwl4965_rs_free,
-       .alloc_sta = iwl4965_rs_alloc_sta,
-       .free_sta = iwl4965_rs_free_sta,
-#ifdef CONFIG_MAC80211_DEBUGFS
-       .add_sta_debugfs = iwl4965_rs_add_debugfs,
-       .remove_sta_debugfs = iwl4965_rs_remove_debugfs,
-#endif
-};
-
-int iwl4965_rate_control_register(void)
-{
-       return ieee80211_rate_control_register(&rs_4965_ops);
-}
-
-void iwl4965_rate_control_unregister(void)
-{
-       ieee80211_rate_control_unregister(&rs_4965_ops);
-}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
deleted file mode 100644 (file)
index 2b144bb..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-4965-calib.h"
-#include "iwl-sta.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-4965-hw.h"
-#include "iwl-4965.h"
-
-void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
-
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_missed_beacon_notif *missed_beacon;
-
-       missed_beacon = &pkt->u.missed_beacon;
-       if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
-           priv->missed_beacon_threshold) {
-               IWL_DEBUG_CALIB(priv,
-                   "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
-                   le32_to_cpu(missed_beacon->consecutive_missed_beacons),
-                   le32_to_cpu(missed_beacon->total_missed_becons),
-                   le32_to_cpu(missed_beacon->num_recvd_beacons),
-                   le32_to_cpu(missed_beacon->num_expected_beacons));
-               if (!test_bit(STATUS_SCANNING, &priv->status))
-                       iwl4965_init_sensitivity(priv);
-       }
-}
-
-/* Calculate noise level, based on measurements during network silence just
- *   before arriving beacon.  This measurement can be done only if we know
- *   exactly when to expect beacons, therefore only when we're associated. */
-static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
-{
-       struct statistics_rx_non_phy *rx_info;
-       int num_active_rx = 0;
-       int total_silence = 0;
-       int bcn_silence_a, bcn_silence_b, bcn_silence_c;
-       int last_rx_noise;
-
-       rx_info = &(priv->_4965.statistics.rx.general);
-       bcn_silence_a =
-               le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
-       bcn_silence_b =
-               le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
-       bcn_silence_c =
-               le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
-
-       if (bcn_silence_a) {
-               total_silence += bcn_silence_a;
-               num_active_rx++;
-       }
-       if (bcn_silence_b) {
-               total_silence += bcn_silence_b;
-               num_active_rx++;
-       }
-       if (bcn_silence_c) {
-               total_silence += bcn_silence_c;
-               num_active_rx++;
-       }
-
-       /* Average among active antennas */
-       if (num_active_rx)
-               last_rx_noise = (total_silence / num_active_rx) - 107;
-       else
-               last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-
-       IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
-                       bcn_silence_a, bcn_silence_b, bcn_silence_c,
-                       last_rx_noise);
-}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-/*
- *  based on the assumption of all statistics counter are in DWORD
- *  FIXME: This function is for debugging, do not deal with
- *  the case of counters roll-over.
- */
-static void iwl4965_accumulative_statistics(struct iwl_priv *priv,
-                                       __le32 *stats)
-{
-       int i, size;
-       __le32 *prev_stats;
-       u32 *accum_stats;
-       u32 *delta, *max_delta;
-       struct statistics_general_common *general, *accum_general;
-       struct statistics_tx *tx, *accum_tx;
-
-       prev_stats = (__le32 *)&priv->_4965.statistics;
-       accum_stats = (u32 *)&priv->_4965.accum_statistics;
-       size = sizeof(struct iwl_notif_statistics);
-       general = &priv->_4965.statistics.general.common;
-       accum_general = &priv->_4965.accum_statistics.general.common;
-       tx = &priv->_4965.statistics.tx;
-       accum_tx = &priv->_4965.accum_statistics.tx;
-       delta = (u32 *)&priv->_4965.delta_statistics;
-       max_delta = (u32 *)&priv->_4965.max_delta;
-
-       for (i = sizeof(__le32); i < size;
-            i += sizeof(__le32), stats++, prev_stats++, delta++,
-            max_delta++, accum_stats++) {
-               if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
-                       *delta = (le32_to_cpu(*stats) -
-                               le32_to_cpu(*prev_stats));
-                       *accum_stats += *delta;
-                       if (*delta > *max_delta)
-                               *max_delta = *delta;
-               }
-       }
-
-       /* reset accumulative statistics for "no-counter" type statistics */
-       accum_general->temperature = general->temperature;
-       accum_general->ttl_timestamp = general->ttl_timestamp;
-}
-#endif
-
-#define REG_RECALIB_PERIOD (60)
-
-void iwl4965_rx_statistics(struct iwl_priv *priv,
-                             struct iwl_rx_mem_buffer *rxb)
-{
-       int change;
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-       IWL_DEBUG_RX(priv,
-                    "Statistics notification received (%d vs %d).\n",
-                    (int)sizeof(struct iwl_notif_statistics),
-                    le32_to_cpu(pkt->len_n_flags) &
-                    FH_RSCSR_FRAME_SIZE_MSK);
-
-       change = ((priv->_4965.statistics.general.common.temperature !=
-                  pkt->u.stats.general.common.temperature) ||
-                  ((priv->_4965.statistics.flag &
-                  STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
-                  (pkt->u.stats.flag &
-                  STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-       iwl4965_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
-#endif
-
-       /* TODO: reading some of statistics is unneeded */
-       memcpy(&priv->_4965.statistics, &pkt->u.stats,
-               sizeof(priv->_4965.statistics));
-
-       set_bit(STATUS_STATISTICS, &priv->status);
-
-       /* Reschedule the statistics timer to occur in
-        * REG_RECALIB_PERIOD seconds to ensure we get a
-        * thermal update even if the uCode doesn't give
-        * us one */
-       mod_timer(&priv->statistics_periodic, jiffies +
-                 msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
-
-       if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
-           (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
-               iwl4965_rx_calc_noise(priv);
-               queue_work(priv->workqueue, &priv->run_time_calib_work);
-       }
-       if (priv->cfg->ops->lib->temp_ops.temperature && change)
-               priv->cfg->ops->lib->temp_ops.temperature(priv);
-}
-
-void iwl4965_reply_statistics(struct iwl_priv *priv,
-                             struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-       if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-               memset(&priv->_4965.accum_statistics, 0,
-                       sizeof(struct iwl_notif_statistics));
-               memset(&priv->_4965.delta_statistics, 0,
-                       sizeof(struct iwl_notif_statistics));
-               memset(&priv->_4965.max_delta, 0,
-                       sizeof(struct iwl_notif_statistics));
-#endif
-               IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
-       }
-       iwl4965_rx_statistics(priv, rxb);
-}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-sta.c b/drivers/net/wireless/iwlegacy/iwl-4965-sta.c
deleted file mode 100644 (file)
index a262c23..0000000
+++ /dev/null
@@ -1,721 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <net/mac80211.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-sta.h"
-#include "iwl-4965.h"
-
-static struct iwl_link_quality_cmd *
-iwl4965_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id)
-{
-       int i, r;
-       struct iwl_link_quality_cmd *link_cmd;
-       u32 rate_flags = 0;
-       __le32 rate_n_flags;
-
-       link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
-       if (!link_cmd) {
-               IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
-               return NULL;
-       }
-       /* Set up the rate scaling to start at selected rate, fall back
-        * all the way down to 1M in IEEE order, and then spin on 1M */
-       if (priv->band == IEEE80211_BAND_5GHZ)
-               r = IWL_RATE_6M_INDEX;
-       else
-               r = IWL_RATE_1M_INDEX;
-
-       if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
-               rate_flags |= RATE_MCS_CCK_MSK;
-
-       rate_flags |= iwl4965_first_antenna(priv->hw_params.valid_tx_ant) <<
-                               RATE_MCS_ANT_POS;
-       rate_n_flags = iwl4965_hw_set_rate_n_flags(iwlegacy_rates[r].plcp,
-                                                  rate_flags);
-       for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
-               link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
-
-       link_cmd->general_params.single_stream_ant_msk =
-                               iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
-
-       link_cmd->general_params.dual_stream_ant_msk =
-               priv->hw_params.valid_tx_ant &
-               ~iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
-       if (!link_cmd->general_params.dual_stream_ant_msk) {
-               link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
-       } else if (iwl4965_num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
-               link_cmd->general_params.dual_stream_ant_msk =
-                       priv->hw_params.valid_tx_ant;
-       }
-
-       link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
-       link_cmd->agg_params.agg_time_limit =
-               cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
-
-       link_cmd->sta_id = sta_id;
-
-       return link_cmd;
-}
-
-/*
- * iwl4965_add_bssid_station - Add the special IBSS BSSID station
- *
- * Function sleeps.
- */
-int
-iwl4965_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
-                            const u8 *addr, u8 *sta_id_r)
-{
-       int ret;
-       u8 sta_id;
-       struct iwl_link_quality_cmd *link_cmd;
-       unsigned long flags;
-
-       if (sta_id_r)
-               *sta_id_r = IWL_INVALID_STATION;
-
-       ret = iwl_legacy_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
-       if (ret) {
-               IWL_ERR(priv, "Unable to add station %pM\n", addr);
-               return ret;
-       }
-
-       if (sta_id_r)
-               *sta_id_r = sta_id;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].used |= IWL_STA_LOCAL;
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       /* Set up default rate scaling table in device's station table */
-       link_cmd = iwl4965_sta_alloc_lq(priv, sta_id);
-       if (!link_cmd) {
-               IWL_ERR(priv,
-                       "Unable to initialize rate scaling for station %pM.\n",
-                       addr);
-               return -ENOMEM;
-       }
-
-       ret = iwl_legacy_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true);
-       if (ret)
-               IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].lq = link_cmd;
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return 0;
-}
-
-static int iwl4965_static_wepkey_cmd(struct iwl_priv *priv,
-                                     struct iwl_rxon_context *ctx,
-                                     bool send_if_empty)
-{
-       int i, not_empty = 0;
-       u8 buff[sizeof(struct iwl_wep_cmd) +
-               sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
-       struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
-       size_t cmd_size  = sizeof(struct iwl_wep_cmd);
-       struct iwl_host_cmd cmd = {
-               .id = ctx->wep_key_cmd,
-               .data = wep_cmd,
-               .flags = CMD_SYNC,
-       };
-
-       might_sleep();
-
-       memset(wep_cmd, 0, cmd_size +
-                       (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
-
-       for (i = 0; i < WEP_KEYS_MAX ; i++) {
-               wep_cmd->key[i].key_index = i;
-               if (ctx->wep_keys[i].key_size) {
-                       wep_cmd->key[i].key_offset = i;
-                       not_empty = 1;
-               } else {
-                       wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
-               }
-
-               wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
-               memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
-                               ctx->wep_keys[i].key_size);
-       }
-
-       wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
-       wep_cmd->num_keys = WEP_KEYS_MAX;
-
-       cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
-
-       cmd.len = cmd_size;
-
-       if (not_empty || send_if_empty)
-               return iwl_legacy_send_cmd(priv, &cmd);
-       else
-               return 0;
-}
-
-int iwl4965_restore_default_wep_keys(struct iwl_priv *priv,
-                                struct iwl_rxon_context *ctx)
-{
-       lockdep_assert_held(&priv->mutex);
-
-       return iwl4965_static_wepkey_cmd(priv, ctx, false);
-}
-
-int iwl4965_remove_default_wep_key(struct iwl_priv *priv,
-                              struct iwl_rxon_context *ctx,
-                              struct ieee80211_key_conf *keyconf)
-{
-       int ret;
-
-       lockdep_assert_held(&priv->mutex);
-
-       IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
-                     keyconf->keyidx);
-
-       memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
-       if (iwl_legacy_is_rfkill(priv)) {
-               IWL_DEBUG_WEP(priv,
-               "Not sending REPLY_WEPKEY command due to RFKILL.\n");
-               /* but keys in device are clear anyway so return success */
-               return 0;
-       }
-       ret = iwl4965_static_wepkey_cmd(priv, ctx, 1);
-       IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
-                     keyconf->keyidx, ret);
-
-       return ret;
-}
-
-int iwl4965_set_default_wep_key(struct iwl_priv *priv,
-                           struct iwl_rxon_context *ctx,
-                           struct ieee80211_key_conf *keyconf)
-{
-       int ret;
-
-       lockdep_assert_held(&priv->mutex);
-
-       if (keyconf->keylen != WEP_KEY_LEN_128 &&
-           keyconf->keylen != WEP_KEY_LEN_64) {
-               IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen);
-               return -EINVAL;
-       }
-
-       keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-       keyconf->hw_key_idx = HW_KEY_DEFAULT;
-       priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
-
-       ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
-       memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
-                                                       keyconf->keylen);
-
-       ret = iwl4965_static_wepkey_cmd(priv, ctx, false);
-       IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
-               keyconf->keylen, keyconf->keyidx, ret);
-
-       return ret;
-}
-
-static int iwl4965_set_wep_dynamic_key_info(struct iwl_priv *priv,
-                                       struct iwl_rxon_context *ctx,
-                                       struct ieee80211_key_conf *keyconf,
-                                       u8 sta_id)
-{
-       unsigned long flags;
-       __le16 key_flags = 0;
-       struct iwl_legacy_addsta_cmd sta_cmd;
-
-       lockdep_assert_held(&priv->mutex);
-
-       keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-
-       key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
-       key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-       key_flags &= ~STA_KEY_FLG_INVALID;
-
-       if (keyconf->keylen == WEP_KEY_LEN_128)
-               key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
-
-       if (sta_id == ctx->bcast_sta_id)
-               key_flags |= STA_KEY_MULTICAST_MSK;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-
-       priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
-       priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-       priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
-
-       memcpy(priv->stations[sta_id].keyinfo.key,
-                               keyconf->key, keyconf->keylen);
-
-       memcpy(&priv->stations[sta_id].sta.key.key[3],
-                               keyconf->key, keyconf->keylen);
-
-       if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-                       == STA_KEY_FLG_NO_ENC)
-               priv->stations[sta_id].sta.key.key_offset =
-                                iwl_legacy_get_free_ucode_key_index(priv);
-       /* else, we are overriding an existing key => no need to allocated room
-        * in uCode. */
-
-       WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-               "no space for a new key");
-
-       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;
-
-       memcpy(&sta_cmd, &priv->stations[sta_id].sta,
-                       sizeof(struct iwl_legacy_addsta_cmd));
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
-                                        struct iwl_rxon_context *ctx,
-                                        struct ieee80211_key_conf *keyconf,
-                                        u8 sta_id)
-{
-       unsigned long flags;
-       __le16 key_flags = 0;
-       struct iwl_legacy_addsta_cmd sta_cmd;
-
-       lockdep_assert_held(&priv->mutex);
-
-       key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
-       key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-       key_flags &= ~STA_KEY_FLG_INVALID;
-
-       if (sta_id == ctx->bcast_sta_id)
-               key_flags |= STA_KEY_MULTICAST_MSK;
-
-       keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
-       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);
-
-       if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-                       == STA_KEY_FLG_NO_ENC)
-               priv->stations[sta_id].sta.key.key_offset =
-                                iwl_legacy_get_free_ucode_key_index(priv);
-       /* else, we are overriding an existing key => no need to allocated room
-        * in uCode. */
-
-       WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-               "no space for a new key");
-
-       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;
-
-       memcpy(&sta_cmd, &priv->stations[sta_id].sta,
-                        sizeof(struct iwl_legacy_addsta_cmd));
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv,
-                                        struct iwl_rxon_context *ctx,
-                                        struct ieee80211_key_conf *keyconf,
-                                        u8 sta_id)
-{
-       unsigned long flags;
-       int ret = 0;
-       __le16 key_flags = 0;
-
-       key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
-       key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-       key_flags &= ~STA_KEY_FLG_INVALID;
-
-       if (sta_id == ctx->bcast_sta_id)
-               key_flags |= STA_KEY_MULTICAST_MSK;
-
-       keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-       keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-
-       priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
-       priv->stations[sta_id].keyinfo.keylen = 16;
-
-       if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-                       == STA_KEY_FLG_NO_ENC)
-               priv->stations[sta_id].sta.key.key_offset =
-                                iwl_legacy_get_free_ucode_key_index(priv);
-       /* else, we are overriding an existing key => no need to allocated room
-        * in uCode. */
-
-       WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-               "no space for a new key");
-
-       priv->stations[sta_id].sta.key.key_flags = key_flags;
-
-
-       /* This copy is acutally not needed: we get the key with each TX */
-       memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
-
-       memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
-
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return ret;
-}
-
-void iwl4965_update_tkip_key(struct iwl_priv *priv,
-                        struct iwl_rxon_context *ctx,
-                        struct ieee80211_key_conf *keyconf,
-                        struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
-{
-       u8 sta_id;
-       unsigned long flags;
-       int i;
-
-       if (iwl_legacy_scan_cancel(priv)) {
-               /* cancel scan failed, just live w/ bad key and rely
-                  briefly on SW decryption */
-               return;
-       }
-
-       sta_id = iwl_legacy_sta_id_or_broadcast(priv, ctx, sta);
-       if (sta_id == IWL_INVALID_STATION)
-               return;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-
-       priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
-
-       for (i = 0; i < 5; i++)
-               priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
-                       cpu_to_le16(phase1key[i]);
-
-       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
-       iwl_legacy_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-}
-
-int iwl4965_remove_dynamic_key(struct iwl_priv *priv,
-                          struct iwl_rxon_context *ctx,
-                          struct ieee80211_key_conf *keyconf,
-                          u8 sta_id)
-{
-       unsigned long flags;
-       u16 key_flags;
-       u8 keyidx;
-       struct iwl_legacy_addsta_cmd sta_cmd;
-
-       lockdep_assert_held(&priv->mutex);
-
-       ctx->key_mapping_keys--;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
-       keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
-
-       IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
-                     keyconf->keyidx, sta_id);
-
-       if (keyconf->keyidx != keyidx) {
-               /* We need to remove a key with index different that the one
-                * in the uCode. This means that the key we need to remove has
-                * been replaced by another one with different index.
-                * Don't do anything and return ok
-                */
-               spin_unlock_irqrestore(&priv->sta_lock, flags);
-               return 0;
-       }
-
-       if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
-               IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
-                           keyconf->keyidx, key_flags);
-               spin_unlock_irqrestore(&priv->sta_lock, flags);
-               return 0;
-       }
-
-       if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
-               &priv->ucode_key_table))
-               IWL_ERR(priv, "index %d not used in uCode key table.\n",
-                       priv->stations[sta_id].sta.key.key_offset);
-       memset(&priv->stations[sta_id].keyinfo, 0,
-                                       sizeof(struct iwl_hw_key));
-       memset(&priv->stations[sta_id].sta.key, 0,
-                                       sizeof(struct iwl4965_keyinfo));
-       priv->stations[sta_id].sta.key.key_flags =
-                       STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
-       priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
-       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
-       if (iwl_legacy_is_rfkill(priv)) {
-               IWL_DEBUG_WEP(priv,
-                "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
-               spin_unlock_irqrestore(&priv->sta_lock, flags);
-               return 0;
-       }
-       memcpy(&sta_cmd, &priv->stations[sta_id].sta,
-                       sizeof(struct iwl_legacy_addsta_cmd));
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-int iwl4965_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
-                       struct ieee80211_key_conf *keyconf, u8 sta_id)
-{
-       int ret;
-
-       lockdep_assert_held(&priv->mutex);
-
-       ctx->key_mapping_keys++;
-       keyconf->hw_key_idx = HW_KEY_DYNAMIC;
-
-       switch (keyconf->cipher) {
-       case WLAN_CIPHER_SUITE_CCMP:
-               ret = iwl4965_set_ccmp_dynamic_key_info(priv, ctx,
-                                                       keyconf, sta_id);
-               break;
-       case WLAN_CIPHER_SUITE_TKIP:
-               ret = iwl4965_set_tkip_dynamic_key_info(priv, ctx,
-                                                       keyconf, sta_id);
-               break;
-       case WLAN_CIPHER_SUITE_WEP40:
-       case WLAN_CIPHER_SUITE_WEP104:
-               ret = iwl4965_set_wep_dynamic_key_info(priv, ctx,
-                                                       keyconf, sta_id);
-               break;
-       default:
-               IWL_ERR(priv,
-                       "Unknown alg: %s cipher = %x\n", __func__,
-                       keyconf->cipher);
-               ret = -EINVAL;
-       }
-
-       IWL_DEBUG_WEP(priv,
-               "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
-                     keyconf->cipher, keyconf->keylen, keyconf->keyidx,
-                     sta_id, ret);
-
-       return ret;
-}
-
-/**
- * iwl4965_alloc_bcast_station - add broadcast station into driver's station table.
- *
- * This adds the broadcast station into the driver's station table
- * and marks it driver active, so that it will be restored to the
- * device at the next best time.
- */
-int iwl4965_alloc_bcast_station(struct iwl_priv *priv,
-                              struct iwl_rxon_context *ctx)
-{
-       struct iwl_link_quality_cmd *link_cmd;
-       unsigned long flags;
-       u8 sta_id;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       sta_id = iwl_legacy_prep_station(priv, ctx, iwlegacy_bcast_addr,
-                                                               false, NULL);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Unable to prepare broadcast station\n");
-               spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-               return -EINVAL;
-       }
-
-       priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
-       priv->stations[sta_id].used |= IWL_STA_BCAST;
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       link_cmd = iwl4965_sta_alloc_lq(priv, sta_id);
-       if (!link_cmd) {
-               IWL_ERR(priv,
-                       "Unable to initialize rate scaling for bcast station.\n");
-               return -ENOMEM;
-       }
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].lq = link_cmd;
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return 0;
-}
-
-/**
- * iwl4965_update_bcast_station - update broadcast station's LQ command
- *
- * Only used by iwl4965. Placed here to have all bcast station management
- * code together.
- */
-static int iwl4965_update_bcast_station(struct iwl_priv *priv,
-                                   struct iwl_rxon_context *ctx)
-{
-       unsigned long flags;
-       struct iwl_link_quality_cmd *link_cmd;
-       u8 sta_id = ctx->bcast_sta_id;
-
-       link_cmd = iwl4965_sta_alloc_lq(priv, sta_id);
-       if (!link_cmd) {
-               IWL_ERR(priv,
-               "Unable to initialize rate scaling for bcast station.\n");
-               return -ENOMEM;
-       }
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       if (priv->stations[sta_id].lq)
-               kfree(priv->stations[sta_id].lq);
-       else
-               IWL_DEBUG_INFO(priv,
-               "Bcast station rate scaling has not been initialized yet.\n");
-       priv->stations[sta_id].lq = link_cmd;
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return 0;
-}
-
-int iwl4965_update_bcast_stations(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx;
-       int ret = 0;
-
-       for_each_context(priv, ctx) {
-               ret = iwl4965_update_bcast_station(priv, ctx);
-               if (ret)
-                       break;
-       }
-
-       return ret;
-}
-
-/**
- * iwl4965_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
- */
-int iwl4965_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
-{
-       unsigned long flags;
-       struct iwl_legacy_addsta_cmd sta_cmd;
-
-       lockdep_assert_held(&priv->mutex);
-
-       /* Remove "disable" flag, to enable Tx for this TID */
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
-       priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
-       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-       memcpy(&sta_cmd, &priv->stations[sta_id].sta,
-                                       sizeof(struct iwl_legacy_addsta_cmd));
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-int iwl4965_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
-                        int tid, u16 ssn)
-{
-       unsigned long flags;
-       int sta_id;
-       struct iwl_legacy_addsta_cmd sta_cmd;
-
-       lockdep_assert_held(&priv->mutex);
-
-       sta_id = iwl_legacy_sta_id(sta);
-       if (sta_id == IWL_INVALID_STATION)
-               return -ENXIO;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].sta.station_flags_msk = 0;
-       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
-       priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
-       priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
-       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-       memcpy(&sta_cmd, &priv->stations[sta_id].sta,
-                                       sizeof(struct iwl_legacy_addsta_cmd));
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-int iwl4965_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
-                       int tid)
-{
-       unsigned long flags;
-       int sta_id;
-       struct iwl_legacy_addsta_cmd sta_cmd;
-
-       lockdep_assert_held(&priv->mutex);
-
-       sta_id = iwl_legacy_sta_id(sta);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
-               return -ENXIO;
-       }
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].sta.station_flags_msk = 0;
-       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
-       priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
-       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-       memcpy(&sta_cmd, &priv->stations[sta_id].sta,
-                               sizeof(struct iwl_legacy_addsta_cmd));
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-void
-iwl4965_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
-       priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
-       priv->stations[sta_id].sta.sta.modify_mask =
-                                       STA_MODIFY_SLEEP_TX_COUNT_MSK;
-       priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
-       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-       iwl_legacy_send_add_sta(priv,
-                               &priv->stations[sta_id].sta, CMD_ASYNC);
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
deleted file mode 100644 (file)
index 7f12e36..0000000
+++ /dev/null
@@ -1,1378 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-sta.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-4965-hw.h"
-#include "iwl-4965.h"
-
-/*
- * mac80211 queues, ACs, hardware queues, FIFOs.
- *
- * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
- *
- * Mac80211 uses the following numbers, which we get as from it
- * by way of skb_get_queue_mapping(skb):
- *
- *     VO      0
- *     VI      1
- *     BE      2
- *     BK      3
- *
- *
- * Regular (not A-MPDU) frames are put into hardware queues corresponding
- * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
- * own queue per aggregation session (RA/TID combination), such queues are
- * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
- * order to map frames to the right queue, we also need an AC->hw queue
- * mapping. This is implemented here.
- *
- * Due to the way hw queues are set up (by the hw specific modules like
- * iwl-4965.c), the AC->hw queue mapping is the identity
- * mapping.
- */
-
-static const u8 tid_to_ac[] = {
-       IEEE80211_AC_BE,
-       IEEE80211_AC_BK,
-       IEEE80211_AC_BK,
-       IEEE80211_AC_BE,
-       IEEE80211_AC_VI,
-       IEEE80211_AC_VI,
-       IEEE80211_AC_VO,
-       IEEE80211_AC_VO
-};
-
-static inline int iwl4965_get_ac_from_tid(u16 tid)
-{
-       if (likely(tid < ARRAY_SIZE(tid_to_ac)))
-               return tid_to_ac[tid];
-
-       /* no support for TIDs 8-15 yet */
-       return -EINVAL;
-}
-
-static inline int
-iwl4965_get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
-{
-       if (likely(tid < ARRAY_SIZE(tid_to_ac)))
-               return ctx->ac_to_fifo[tid_to_ac[tid]];
-
-       /* no support for TIDs 8-15 yet */
-       return -EINVAL;
-}
-
-/*
- * handle build REPLY_TX command notification.
- */
-static void iwl4965_tx_cmd_build_basic(struct iwl_priv *priv,
-                                       struct sk_buff *skb,
-                                       struct iwl_tx_cmd *tx_cmd,
-                                       struct ieee80211_tx_info *info,
-                                       struct ieee80211_hdr *hdr,
-                                       u8 std_id)
-{
-       __le16 fc = hdr->frame_control;
-       __le32 tx_flags = tx_cmd->tx_flags;
-
-       tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
-               tx_flags |= TX_CMD_FLG_ACK_MSK;
-               if (ieee80211_is_mgmt(fc))
-                       tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-               if (ieee80211_is_probe_resp(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;
-       }
-
-       if (ieee80211_is_back_req(fc))
-               tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
-
-       tx_cmd->sta_id = std_id;
-       if (ieee80211_has_morefrags(fc))
-               tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
-
-       if (ieee80211_is_data_qos(fc)) {
-               u8 *qc = ieee80211_get_qos_ctl(hdr);
-               tx_cmd->tid_tspec = qc[0] & 0xf;
-               tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
-       } else {
-               tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-       }
-
-       iwl_legacy_tx_cmd_protection(priv, info, fc, &tx_flags);
-
-       tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
-       if (ieee80211_is_mgmt(fc)) {
-               if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
-                       tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
-               else
-                       tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
-       } else {
-               tx_cmd->timeout.pm_frame_timeout = 0;
-       }
-
-       tx_cmd->driver_txop = 0;
-       tx_cmd->tx_flags = tx_flags;
-       tx_cmd->next_frame_len = 0;
-}
-
-#define RTS_DFAULT_RETRY_LIMIT         60
-
-static void iwl4965_tx_cmd_build_rate(struct iwl_priv *priv,
-                             struct iwl_tx_cmd *tx_cmd,
-                             struct ieee80211_tx_info *info,
-                             __le16 fc)
-{
-       u32 rate_flags;
-       int rate_idx;
-       u8 rts_retry_limit;
-       u8 data_retry_limit;
-       u8 rate_plcp;
-
-       /* Set retry limit on DATA packets and Probe Responses*/
-       if (ieee80211_is_probe_resp(fc))
-               data_retry_limit = 3;
-       else
-               data_retry_limit = IWL4965_DEFAULT_TX_RETRY;
-       tx_cmd->data_retry_limit = data_retry_limit;
-
-       /* Set retry limit on RTS packets */
-       rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
-       if (data_retry_limit < rts_retry_limit)
-               rts_retry_limit = data_retry_limit;
-       tx_cmd->rts_retry_limit = rts_retry_limit;
-
-       /* DATA packets will use the uCode station table for rate/antenna
-        * selection */
-       if (ieee80211_is_data(fc)) {
-               tx_cmd->initial_rate_index = 0;
-               tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
-               return;
-       }
-
-       /**
-        * If the current TX rate stored in mac80211 has the MCS bit set, it's
-        * not really a TX rate.  Thus, we use the lowest supported rate for
-        * this band.  Also use the lowest supported rate if the stored rate
-        * index is invalid.
-        */
-       rate_idx = info->control.rates[0].idx;
-       if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS ||
-                       (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY))
-               rate_idx = rate_lowest_index(&priv->bands[info->band],
-                               info->control.sta);
-       /* For 5 GHZ band, remap mac80211 rate indices into driver indices */
-       if (info->band == IEEE80211_BAND_5GHZ)
-               rate_idx += IWL_FIRST_OFDM_RATE;
-       /* Get PLCP rate for tx_cmd->rate_n_flags */
-       rate_plcp = iwlegacy_rates[rate_idx].plcp;
-       /* Zero out flags for this packet */
-       rate_flags = 0;
-
-       /* Set CCK flag as needed */
-       if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
-               rate_flags |= RATE_MCS_CCK_MSK;
-
-       /* Set up antennas */
-       priv->mgmt_tx_ant = iwl4965_toggle_tx_ant(priv, priv->mgmt_tx_ant,
-                                     priv->hw_params.valid_tx_ant);
-
-       rate_flags |= iwl4965_ant_idx_to_flags(priv->mgmt_tx_ant);
-
-       /* Set the rate in the TX cmd */
-       tx_cmd->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
-}
-
-static void iwl4965_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
-                                     struct ieee80211_tx_info *info,
-                                     struct iwl_tx_cmd *tx_cmd,
-                                     struct sk_buff *skb_frag,
-                                     int sta_id)
-{
-       struct ieee80211_key_conf *keyconf = info->control.hw_key;
-
-       switch (keyconf->cipher) {
-       case WLAN_CIPHER_SUITE_CCMP:
-               tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
-               memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
-               if (info->flags & IEEE80211_TX_CTL_AMPDU)
-                       tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
-               IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
-               break;
-
-       case WLAN_CIPHER_SUITE_TKIP:
-               tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
-               ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
-               IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
-               break;
-
-       case WLAN_CIPHER_SUITE_WEP104:
-               tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
-               /* fall through */
-       case WLAN_CIPHER_SUITE_WEP40:
-               tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP |
-                       (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
-
-               memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
-
-               IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
-                            "with key %d\n", keyconf->keyidx);
-               break;
-
-       default:
-               IWL_ERR(priv, "Unknown encode cipher %x\n", keyconf->cipher);
-               break;
-       }
-}
-
-/*
- * start REPLY_TX command process
- */
-int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
-{
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_sta *sta = info->control.sta;
-       struct iwl_station_priv *sta_priv = NULL;
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-       struct iwl_device_cmd *out_cmd;
-       struct iwl_cmd_meta *out_meta;
-       struct iwl_tx_cmd *tx_cmd;
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       int txq_id;
-       dma_addr_t phys_addr;
-       dma_addr_t txcmd_phys;
-       dma_addr_t scratch_phys;
-       u16 len, firstlen, secondlen;
-       u16 seq_number = 0;
-       __le16 fc;
-       u8 hdr_len;
-       u8 sta_id;
-       u8 wait_write_ptr = 0;
-       u8 tid = 0;
-       u8 *qc = NULL;
-       unsigned long flags;
-       bool is_agg = false;
-
-       if (info->control.vif)
-               ctx = iwl_legacy_rxon_ctx_from_vif(info->control.vif);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       if (iwl_legacy_is_rfkill(priv)) {
-               IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
-               goto drop_unlock;
-       }
-
-       fc = hdr->frame_control;
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (ieee80211_is_auth(fc))
-               IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
-       else if (ieee80211_is_assoc_req(fc))
-               IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
-       else if (ieee80211_is_reassoc_req(fc))
-               IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
-#endif
-
-       hdr_len = ieee80211_hdrlen(fc);
-
-       /* For management frames use broadcast id to do not break aggregation */
-       if (!ieee80211_is_data(fc))
-               sta_id = ctx->bcast_sta_id;
-       else {
-               /* Find index into station table for destination station */
-               sta_id = iwl_legacy_sta_id_or_broadcast(priv, ctx, info->control.sta);
-
-               if (sta_id == IWL_INVALID_STATION) {
-                       IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-                                      hdr->addr1);
-                       goto drop_unlock;
-               }
-       }
-
-       IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
-
-       if (sta)
-               sta_priv = (void *)sta->drv_priv;
-
-       if (sta_priv && sta_priv->asleep &&
-           (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) {
-               /*
-                * This sends an asynchronous command to the device,
-                * but we can rely on it being processed before the
-                * next frame is processed -- and the next frame to
-                * this station is the one that will consume this
-                * counter.
-                * For now set the counter to just 1 since we do not
-                * support uAPSD yet.
-                */
-               iwl4965_sta_modify_sleep_tx_count(priv, sta_id, 1);
-       }
-
-       /*
-        * Send this frame after DTIM -- there's a special queue
-        * reserved for this for contexts that support AP mode.
-        */
-       if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
-               txq_id = ctx->mcast_queue;
-               /*
-                * The microcode will clear the more data
-                * bit in the last frame it transmits.
-                */
-               hdr->frame_control |=
-                       cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-       } else
-               txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
-
-       /* irqs already disabled/saved above when locking priv->lock */
-       spin_lock(&priv->sta_lock);
-
-       if (ieee80211_is_data_qos(fc)) {
-               qc = ieee80211_get_qos_ctl(hdr);
-               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-               if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) {
-                       spin_unlock(&priv->sta_lock);
-                       goto drop_unlock;
-               }
-               seq_number = priv->stations[sta_id].tid[tid].seq_number;
-               seq_number &= IEEE80211_SCTL_SEQ;
-               hdr->seq_ctrl = hdr->seq_ctrl &
-                               cpu_to_le16(IEEE80211_SCTL_FRAG);
-               hdr->seq_ctrl |= cpu_to_le16(seq_number);
-               seq_number += 0x10;
-               /* aggregation is on for this <sta,tid> */
-               if (info->flags & IEEE80211_TX_CTL_AMPDU &&
-                   priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
-                       txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
-                       is_agg = true;
-               }
-       }
-
-       txq = &priv->txq[txq_id];
-       q = &txq->q;
-
-       if (unlikely(iwl_legacy_queue_space(q) < q->high_mark)) {
-               spin_unlock(&priv->sta_lock);
-               goto drop_unlock;
-       }
-
-       if (ieee80211_is_data_qos(fc)) {
-               priv->stations[sta_id].tid[tid].tfds_in_queue++;
-               if (!ieee80211_has_morefrags(fc))
-                       priv->stations[sta_id].tid[tid].seq_number = seq_number;
-       }
-
-       spin_unlock(&priv->sta_lock);
-
-       /* Set up driver data for this TFD */
-       memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
-       txq->txb[q->write_ptr].skb = skb;
-       txq->txb[q->write_ptr].ctx = ctx;
-
-       /* Set up first empty entry in queue's array of Tx/cmd buffers */
-       out_cmd = txq->cmd[q->write_ptr];
-       out_meta = &txq->meta[q->write_ptr];
-       tx_cmd = &out_cmd->cmd.tx;
-       memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
-       memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
-
-       /*
-        * Set up the Tx-command (not MAC!) header.
-        * Store the chosen Tx queue and TFD index within the sequence field;
-        * after Tx, uCode's Tx response will return this value so driver can
-        * locate the frame within the tx queue and do post-tx processing.
-        */
-       out_cmd->hdr.cmd = REPLY_TX;
-       out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
-                               INDEX_TO_SEQ(q->write_ptr)));
-
-       /* Copy MAC header from skb into command buffer */
-       memcpy(tx_cmd->hdr, hdr, hdr_len);
-
-
-       /* Total # bytes to be transmitted */
-       len = (u16)skb->len;
-       tx_cmd->len = cpu_to_le16(len);
-
-       if (info->control.hw_key)
-               iwl4965_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
-
-       /* TODO need this for burst mode later on */
-       iwl4965_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id);
-       iwl_legacy_dbg_log_tx_data_frame(priv, len, hdr);
-
-       iwl4965_tx_cmd_build_rate(priv, tx_cmd, info, fc);
-
-       iwl_legacy_update_stats(priv, true, fc, len);
-       /*
-        * Use the first empty entry in this queue's command buffer array
-        * to contain the Tx command and MAC header concatenated together
-        * (payload data will be in another buffer).
-        * Size of this varies, due to varying MAC header length.
-        * If end is not dword aligned, we'll have 2 extra bytes at the end
-        * of the MAC header (device reads on dword boundaries).
-        * We'll tell device about this padding later.
-        */
-       len = sizeof(struct iwl_tx_cmd) +
-               sizeof(struct iwl_cmd_header) + hdr_len;
-       firstlen = (len + 3) & ~3;
-
-       /* Tell NIC about any 2-byte padding after MAC header */
-       if (firstlen != len)
-               tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
-
-       /* Physical address of this Tx command's header (not MAC header!),
-        * within command buffer array. */
-       txcmd_phys = pci_map_single(priv->pci_dev,
-                                   &out_cmd->hdr, firstlen,
-                                   PCI_DMA_BIDIRECTIONAL);
-       dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-       dma_unmap_len_set(out_meta, len, firstlen);
-       /* Add buffer containing Tx command and MAC(!) header to TFD's
-        * first entry */
-       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                  txcmd_phys, firstlen, 1, 0);
-
-       if (!ieee80211_has_morefrags(hdr->frame_control)) {
-               txq->need_update = 1;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
-
-       /* Set up TFD's 2nd entry to point directly to remainder of skb,
-        * if any (802.11 null frames have no payload). */
-       secondlen = skb->len - hdr_len;
-       if (secondlen > 0) {
-               phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
-                                          secondlen, PCI_DMA_TODEVICE);
-               priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                          phys_addr, secondlen,
-                                                          0, 0);
-       }
-
-       scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
-                               offsetof(struct iwl_tx_cmd, scratch);
-
-       /* take back ownership of DMA buffer to enable update */
-       pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
-                                   firstlen, PCI_DMA_BIDIRECTIONAL);
-       tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
-       tx_cmd->dram_msb_ptr = iwl_legacy_get_dma_hi_addr(scratch_phys);
-
-       IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
-                    le16_to_cpu(out_cmd->hdr.sequence));
-       IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
-       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
-       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
-
-       /* Set up entry for this TFD in Tx byte-count array */
-       if (info->flags & IEEE80211_TX_CTL_AMPDU)
-               priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
-                                                    le16_to_cpu(tx_cmd->len));
-
-       pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
-                                      firstlen, PCI_DMA_BIDIRECTIONAL);
-
-       trace_iwlwifi_legacy_dev_tx(priv,
-                            &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
-                            sizeof(struct iwl_tfd),
-                            &out_cmd->hdr, firstlen,
-                            skb->data + hdr_len, secondlen);
-
-       /* Tell device the write index *just past* this latest filled TFD */
-       q->write_ptr = iwl_legacy_queue_inc_wrap(q->write_ptr, q->n_bd);
-       iwl_legacy_txq_update_write_ptr(priv, txq);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /*
-        * At this point the frame is "transmitted" successfully
-        * and we will get a TX status notification eventually,
-        * regardless of the value of ret. "ret" only indicates
-        * whether or not we should update the write pointer.
-        */
-
-       /*
-        * Avoid atomic ops if it isn't an associated client.
-        * Also, if this is a packet for aggregation, don't
-        * increase the counter because the ucode will stop
-        * aggregation queues when their respective station
-        * goes to sleep.
-        */
-       if (sta_priv && sta_priv->client && !is_agg)
-               atomic_inc(&sta_priv->pending_frames);
-
-       if ((iwl_legacy_queue_space(q) < q->high_mark) &&
-                       priv->mac80211_registered) {
-               if (wait_write_ptr) {
-                       spin_lock_irqsave(&priv->lock, flags);
-                       txq->need_update = 1;
-                       iwl_legacy_txq_update_write_ptr(priv, txq);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-               } else {
-                       iwl_legacy_stop_queue(priv, txq);
-               }
-       }
-
-       return 0;
-
-drop_unlock:
-       spin_unlock_irqrestore(&priv->lock, flags);
-       return -1;
-}
-
-static inline int iwl4965_alloc_dma_ptr(struct iwl_priv *priv,
-                                   struct iwl_dma_ptr *ptr, size_t size)
-{
-       ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
-                                      GFP_KERNEL);
-       if (!ptr->addr)
-               return -ENOMEM;
-       ptr->size = size;
-       return 0;
-}
-
-static inline void iwl4965_free_dma_ptr(struct iwl_priv *priv,
-                                   struct iwl_dma_ptr *ptr)
-{
-       if (unlikely(!ptr->addr))
-               return;
-
-       dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
-       memset(ptr, 0, sizeof(*ptr));
-}
-
-/**
- * iwl4965_hw_txq_ctx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv)
-{
-       int txq_id;
-
-       /* Tx queues */
-       if (priv->txq) {
-               for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-                       if (txq_id == priv->cmd_queue)
-                               iwl_legacy_cmd_queue_free(priv);
-                       else
-                               iwl_legacy_tx_queue_free(priv, txq_id);
-       }
-       iwl4965_free_dma_ptr(priv, &priv->kw);
-
-       iwl4965_free_dma_ptr(priv, &priv->scd_bc_tbls);
-
-       /* free tx queue structure */
-       iwl_legacy_txq_mem(priv);
-}
-
-/**
- * iwl4965_txq_ctx_alloc - allocate TX queue context
- * Allocate all Tx DMA structures and initialize them
- *
- * @param priv
- * @return error code
- */
-int iwl4965_txq_ctx_alloc(struct iwl_priv *priv)
-{
-       int ret;
-       int txq_id, slots_num;
-       unsigned long flags;
-
-       /* Free all tx/cmd queues and keep-warm buffer */
-       iwl4965_hw_txq_ctx_free(priv);
-
-       ret = iwl4965_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
-                               priv->hw_params.scd_bc_tbls_size);
-       if (ret) {
-               IWL_ERR(priv, "Scheduler BC Table allocation failed\n");
-               goto error_bc_tbls;
-       }
-       /* Alloc keep-warm buffer */
-       ret = iwl4965_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
-       if (ret) {
-               IWL_ERR(priv, "Keep Warm allocation failed\n");
-               goto error_kw;
-       }
-
-       /* allocate tx queue structure */
-       ret = iwl_legacy_alloc_txq_mem(priv);
-       if (ret)
-               goto error;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       /* Turn off all Tx DMA fifos */
-       iwl4965_txq_set_sched(priv, 0);
-
-       /* Tell NIC where to find the "keep warm" buffer */
-       iwl_legacy_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* Alloc and init all Tx queues, including the command queue (#4/#9) */
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-               slots_num = (txq_id == priv->cmd_queue) ?
-                                       TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-               ret = iwl_legacy_tx_queue_init(priv,
-                                       &priv->txq[txq_id], slots_num,
-                                      txq_id);
-               if (ret) {
-                       IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
-                       goto error;
-               }
-       }
-
-       return ret;
-
- error:
-       iwl4965_hw_txq_ctx_free(priv);
-       iwl4965_free_dma_ptr(priv, &priv->kw);
- error_kw:
-       iwl4965_free_dma_ptr(priv, &priv->scd_bc_tbls);
- error_bc_tbls:
-       return ret;
-}
-
-void iwl4965_txq_ctx_reset(struct iwl_priv *priv)
-{
-       int txq_id, slots_num;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       /* Turn off all Tx DMA fifos */
-       iwl4965_txq_set_sched(priv, 0);
-
-       /* Tell NIC where to find the "keep warm" buffer */
-       iwl_legacy_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* Alloc and init all Tx queues, including the command queue (#4) */
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-               slots_num = txq_id == priv->cmd_queue ?
-                           TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-               iwl_legacy_tx_queue_reset(priv, &priv->txq[txq_id],
-                                               slots_num, txq_id);
-       }
-}
-
-/**
- * iwl4965_txq_ctx_stop - Stop all Tx DMA channels
- */
-void iwl4965_txq_ctx_stop(struct iwl_priv *priv)
-{
-       int ch, txq_id;
-       unsigned long flags;
-
-       /* Turn off all Tx DMA fifos */
-       spin_lock_irqsave(&priv->lock, flags);
-
-       iwl4965_txq_set_sched(priv, 0);
-
-       /* Stop each Tx DMA channel, and wait for it to be idle */
-       for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
-               iwl_legacy_write_direct32(priv,
-                               FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
-               if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
-                                   FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
-                                   1000))
-                       IWL_ERR(priv, "Failing on timeout while stopping"
-                           " DMA channel %d [0x%08x]", ch,
-                           iwl_legacy_read_direct32(priv,
-                                       FH_TSSR_TX_STATUS_REG));
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (!priv->txq)
-               return;
-
-       /* Unmap DMA from host system and free skb's */
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-               if (txq_id == priv->cmd_queue)
-                       iwl_legacy_cmd_queue_unmap(priv);
-               else
-                       iwl_legacy_tx_queue_unmap(priv, txq_id);
-}
-
-/*
- * Find first available (lowest unused) Tx Queue, mark it "active".
- * Called only when finding queue for aggregation.
- * Should never return anything < 7, because they should already
- * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
- */
-static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv)
-{
-       int txq_id;
-
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-               if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk))
-                       return txq_id;
-       return -1;
-}
-
-/**
- * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
- */
-static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv,
-                                           u16 txq_id)
-{
-       /* Simply stop the queue, but don't change any configuration;
-        * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
-       iwl_legacy_write_prph(priv,
-               IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
-               (0 << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE)|
-               (1 << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
-}
-
-/**
- * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
- */
-static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
-                                       u16 txq_id)
-{
-       u32 tbl_dw_addr;
-       u32 tbl_dw;
-       u16 scd_q2ratid;
-
-       scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
-
-       tbl_dw_addr = priv->scd_base_addr +
-                       IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
-
-       tbl_dw = iwl_legacy_read_targ_mem(priv, tbl_dw_addr);
-
-       if (txq_id & 0x1)
-               tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
-       else
-               tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
-
-       iwl_legacy_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
-
-       return 0;
-}
-
-/**
- * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
- *
- * NOTE:  txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE,
- *        i.e. it must be one of the higher queues used for aggregation
- */
-static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
-                                 int tx_fifo, int sta_id, int tid, u16 ssn_idx)
-{
-       unsigned long flags;
-       u16 ra_tid;
-       int ret;
-
-       if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
-           (IWL49_FIRST_AMPDU_QUEUE +
-               priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
-               IWL_WARN(priv,
-                       "queue number out of range: %d, must be %d to %d\n",
-                       txq_id, IWL49_FIRST_AMPDU_QUEUE,
-                       IWL49_FIRST_AMPDU_QUEUE +
-                       priv->cfg->base_params->num_of_ampdu_queues - 1);
-               return -EINVAL;
-       }
-
-       ra_tid = BUILD_RAxTID(sta_id, tid);
-
-       /* Modify device's station table to Tx this TID */
-       ret = iwl4965_sta_tx_modify_enable_tid(priv, sta_id, tid);
-       if (ret)
-               return ret;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       /* Stop this Tx queue before configuring it */
-       iwl4965_tx_queue_stop_scheduler(priv, txq_id);
-
-       /* Map receiver-address / traffic-ID to this queue */
-       iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
-
-       /* Set this queue as a chain-building queue */
-       iwl_legacy_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
-
-       /* Place first TFD at index corresponding to start sequence number.
-        * Assumes that ssn_idx is valid (!= 0xFFF) */
-       priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-       priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-       iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
-
-       /* Set up Tx window size and frame limit for this queue */
-       iwl_legacy_write_targ_mem(priv,
-               priv->scd_base_addr + IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id),
-               (SCD_WIN_SIZE << IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
-               IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
-
-       iwl_legacy_write_targ_mem(priv, priv->scd_base_addr +
-               IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
-               (SCD_FRAME_LIMIT << IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS)
-               & IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
-
-       iwl_legacy_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
-
-       /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
-       iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       return 0;
-}
-
-
-int iwl4965_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
-                       struct ieee80211_sta *sta, u16 tid, u16 *ssn)
-{
-       int sta_id;
-       int tx_fifo;
-       int txq_id;
-       int ret;
-       unsigned long flags;
-       struct iwl_tid_data *tid_data;
-
-       tx_fifo = iwl4965_get_fifo_from_tid(iwl_legacy_rxon_ctx_from_vif(vif), tid);
-       if (unlikely(tx_fifo < 0))
-               return tx_fifo;
-
-       IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
-                       __func__, sta->addr, tid);
-
-       sta_id = iwl_legacy_sta_id(sta);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Start AGG on invalid station\n");
-               return -ENXIO;
-       }
-       if (unlikely(tid >= MAX_TID_COUNT))
-               return -EINVAL;
-
-       if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
-               IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
-               return -ENXIO;
-       }
-
-       txq_id = iwl4965_txq_ctx_activate_free(priv);
-       if (txq_id == -1) {
-               IWL_ERR(priv, "No free aggregation queue available\n");
-               return -ENXIO;
-       }
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       tid_data = &priv->stations[sta_id].tid[tid];
-       *ssn = SEQ_TO_SN(tid_data->seq_number);
-       tid_data->agg.txq_id = txq_id;
-       iwl_legacy_set_swq_id(&priv->txq[txq_id],
-                               iwl4965_get_ac_from_tid(tid), txq_id);
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       ret = iwl4965_txq_agg_enable(priv, txq_id, tx_fifo,
-                                                 sta_id, tid, *ssn);
-       if (ret)
-               return ret;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       tid_data = &priv->stations[sta_id].tid[tid];
-       if (tid_data->tfds_in_queue == 0) {
-               IWL_DEBUG_HT(priv, "HW queue is empty\n");
-               tid_data->agg.state = IWL_AGG_ON;
-               ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-       } else {
-               IWL_DEBUG_HT(priv,
-                       "HW queue is NOT empty: %d packets in HW queue\n",
-                            tid_data->tfds_in_queue);
-               tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
-       }
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-       return ret;
-}
-
-/**
- * txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE
- * priv->lock must be held by the caller
- */
-static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
-                                  u16 ssn_idx, u8 tx_fifo)
-{
-       if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
-           (IWL49_FIRST_AMPDU_QUEUE +
-               priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
-               IWL_WARN(priv,
-                       "queue number out of range: %d, must be %d to %d\n",
-                       txq_id, IWL49_FIRST_AMPDU_QUEUE,
-                       IWL49_FIRST_AMPDU_QUEUE +
-                       priv->cfg->base_params->num_of_ampdu_queues - 1);
-               return -EINVAL;
-       }
-
-       iwl4965_tx_queue_stop_scheduler(priv, txq_id);
-
-       iwl_legacy_clear_bits_prph(priv,
-                       IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
-
-       priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-       priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-       /* supposes that ssn_idx is valid (!= 0xFFF) */
-       iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
-
-       iwl_legacy_clear_bits_prph(priv,
-                        IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
-       iwl_txq_ctx_deactivate(priv, txq_id);
-       iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
-
-       return 0;
-}
-
-int iwl4965_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
-                      struct ieee80211_sta *sta, u16 tid)
-{
-       int tx_fifo_id, txq_id, sta_id, ssn;
-       struct iwl_tid_data *tid_data;
-       int write_ptr, read_ptr;
-       unsigned long flags;
-
-       tx_fifo_id = iwl4965_get_fifo_from_tid(iwl_legacy_rxon_ctx_from_vif(vif), tid);
-       if (unlikely(tx_fifo_id < 0))
-               return tx_fifo_id;
-
-       sta_id = iwl_legacy_sta_id(sta);
-
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
-               return -ENXIO;
-       }
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-
-       tid_data = &priv->stations[sta_id].tid[tid];
-       ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
-       txq_id = tid_data->agg.txq_id;
-
-       switch (priv->stations[sta_id].tid[tid].agg.state) {
-       case IWL_EMPTYING_HW_QUEUE_ADDBA:
-               /*
-                * This can happen if the peer stops aggregation
-                * again before we've had a chance to drain the
-                * queue we selected previously, i.e. before the
-                * session was really started completely.
-                */
-               IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
-               goto turn_off;
-       case IWL_AGG_ON:
-               break;
-       default:
-               IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
-       }
-
-       write_ptr = priv->txq[txq_id].q.write_ptr;
-       read_ptr = priv->txq[txq_id].q.read_ptr;
-
-       /* The queue is not empty */
-       if (write_ptr != read_ptr) {
-               IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n");
-               priv->stations[sta_id].tid[tid].agg.state =
-                               IWL_EMPTYING_HW_QUEUE_DELBA;
-               spin_unlock_irqrestore(&priv->sta_lock, flags);
-               return 0;
-       }
-
-       IWL_DEBUG_HT(priv, "HW queue is empty\n");
- turn_off:
-       priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
-
-       /* do not restore/save irqs */
-       spin_unlock(&priv->sta_lock);
-       spin_lock(&priv->lock);
-
-       /*
-        * the only reason this call can fail is queue number out of range,
-        * which can happen if uCode is reloaded and all the station
-        * information are lost. if it is outside the range, there is no need
-        * to deactivate the uCode queue, just return "success" to allow
-        *  mac80211 to clean up it own data.
-        */
-       iwl4965_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-
-       return 0;
-}
-
-int iwl4965_txq_check_empty(struct iwl_priv *priv,
-                          int sta_id, u8 tid, int txq_id)
-{
-       struct iwl_queue *q = &priv->txq[txq_id].q;
-       u8 *addr = priv->stations[sta_id].sta.sta.addr;
-       struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
-       struct iwl_rxon_context *ctx;
-
-       ctx = &priv->contexts[priv->stations[sta_id].ctxid];
-
-       lockdep_assert_held(&priv->sta_lock);
-
-       switch (priv->stations[sta_id].tid[tid].agg.state) {
-       case IWL_EMPTYING_HW_QUEUE_DELBA:
-               /* We are reclaiming the last packet of the */
-               /* aggregated HW queue */
-               if ((txq_id  == tid_data->agg.txq_id) &&
-                   (q->read_ptr == q->write_ptr)) {
-                       u16 ssn = SEQ_TO_SN(tid_data->seq_number);
-                       int tx_fifo = iwl4965_get_fifo_from_tid(ctx, tid);
-                       IWL_DEBUG_HT(priv,
-                               "HW queue empty: continue DELBA flow\n");
-                       iwl4965_txq_agg_disable(priv, txq_id, ssn, tx_fifo);
-                       tid_data->agg.state = IWL_AGG_OFF;
-                       ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
-               }
-               break;
-       case IWL_EMPTYING_HW_QUEUE_ADDBA:
-               /* We are reclaiming the last packet of the queue */
-               if (tid_data->tfds_in_queue == 0) {
-                       IWL_DEBUG_HT(priv,
-                               "HW queue empty: continue ADDBA flow\n");
-                       tid_data->agg.state = IWL_AGG_ON;
-                       ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
-               }
-               break;
-       }
-
-       return 0;
-}
-
-static void iwl4965_non_agg_tx_status(struct iwl_priv *priv,
-                                    struct iwl_rxon_context *ctx,
-                                    const u8 *addr1)
-{
-       struct ieee80211_sta *sta;
-       struct iwl_station_priv *sta_priv;
-
-       rcu_read_lock();
-       sta = ieee80211_find_sta(ctx->vif, addr1);
-       if (sta) {
-               sta_priv = (void *)sta->drv_priv;
-               /* avoid atomic ops if this isn't a client */
-               if (sta_priv->client &&
-                   atomic_dec_return(&sta_priv->pending_frames) == 0)
-                       ieee80211_sta_block_awake(priv->hw, sta, false);
-       }
-       rcu_read_unlock();
-}
-
-static void
-iwl4965_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info,
-                            bool is_agg)
-{
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data;
-
-       if (!is_agg)
-               iwl4965_non_agg_tx_status(priv, tx_info->ctx, hdr->addr1);
-
-       ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
-}
-
-int iwl4965_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;
-       struct iwl_tx_info *tx_info;
-       int nfreed = 0;
-       struct ieee80211_hdr *hdr;
-
-       if ((index >= q->n_bd) || (iwl_legacy_queue_used(q, index) == 0)) {
-               IWL_ERR(priv, "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->write_ptr, q->read_ptr);
-               return 0;
-       }
-
-       for (index = iwl_legacy_queue_inc_wrap(index, q->n_bd);
-            q->read_ptr != index;
-            q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-
-               tx_info = &txq->txb[txq->q.read_ptr];
-
-               if (WARN_ON_ONCE(tx_info->skb == NULL))
-                       continue;
-
-               hdr = (struct ieee80211_hdr *)tx_info->skb->data;
-               if (ieee80211_is_data_qos(hdr->frame_control))
-                       nfreed++;
-
-               iwl4965_tx_status(priv, tx_info,
-                                txq_id >= IWL4965_FIRST_AMPDU_QUEUE);
-               tx_info->skb = NULL;
-
-               priv->cfg->ops->lib->txq_free_tfd(priv, txq);
-       }
-       return nfreed;
-}
-
-/**
- * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack
- *
- * Go through block-ack's bitmap of ACK'd frames, update driver's record of
- * ACK vs. not.  This gets sent to mac80211, then to rate scaling algo.
- */
-static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
-                                struct iwl_ht_agg *agg,
-                                struct iwl_compressed_ba_resp *ba_resp)
-
-{
-       int i, sh, ack;
-       u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
-       u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
-       int successes = 0;
-       struct ieee80211_tx_info *info;
-       u64 bitmap, sent_bitmap;
-
-       if (unlikely(!agg->wait_for_ba))  {
-               if (unlikely(ba_resp->bitmap))
-                       IWL_ERR(priv, "Received BA when not expected\n");
-               return -EINVAL;
-       }
-
-       /* Mark that the expected block-ack response arrived */
-       agg->wait_for_ba = 0;
-       IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx,
-                                                       ba_resp->seq_ctl);
-
-       /* Calculate shift to align block-ack bits with our Tx window bits */
-       sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4);
-       if (sh < 0) /* tbw something is wrong with indices */
-               sh += 0x100;
-
-       if (agg->frame_count > (64 - sh)) {
-               IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size");
-               return -1;
-       }
-
-       /* don't use 64-bit values for now */
-       bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
-
-       /* check for success or failure according to the
-        * transmitted bitmap and block-ack bitmap */
-       sent_bitmap = bitmap & agg->bitmap;
-
-       /* For each frame attempted in aggregation,
-        * update driver's record of tx frame's status. */
-       i = 0;
-       while (sent_bitmap) {
-               ack = sent_bitmap & 1ULL;
-               successes += ack;
-               IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
-                       ack ? "ACK" : "NACK", i,
-                       (agg->start_idx + i) & 0xff,
-                       agg->start_idx + i);
-               sent_bitmap >>= 1;
-               ++i;
-       }
-
-       IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n",
-                                  (unsigned long long)bitmap);
-
-       info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
-       memset(&info->status, 0, sizeof(info->status));
-       info->flags |= IEEE80211_TX_STAT_ACK;
-       info->flags |= IEEE80211_TX_STAT_AMPDU;
-       info->status.ampdu_ack_len = successes;
-       info->status.ampdu_len = agg->frame_count;
-       iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
-
-       return 0;
-}
-
-/**
- * translate ucode response to mac80211 tx status control values
- */
-void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
-                                 struct ieee80211_tx_info *info)
-{
-       struct ieee80211_tx_rate *r = &info->control.rates[0];
-
-       info->antenna_sel_tx =
-               ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
-       if (rate_n_flags & RATE_MCS_HT_MSK)
-               r->flags |= IEEE80211_TX_RC_MCS;
-       if (rate_n_flags & RATE_MCS_GF_MSK)
-               r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
-       if (rate_n_flags & RATE_MCS_HT40_MSK)
-               r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
-       if (rate_n_flags & RATE_MCS_DUP_MSK)
-               r->flags |= IEEE80211_TX_RC_DUP_DATA;
-       if (rate_n_flags & RATE_MCS_SGI_MSK)
-               r->flags |= IEEE80211_TX_RC_SHORT_GI;
-       r->idx = iwl4965_hwrate_to_mac80211_idx(rate_n_flags, info->band);
-}
-
-/**
- * iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
- *
- * Handles block-acknowledge notification from device, which reports success
- * of frames sent via aggregation.
- */
-void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
-                                          struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
-       struct iwl_tx_queue *txq = NULL;
-       struct iwl_ht_agg *agg;
-       int index;
-       int sta_id;
-       int tid;
-       unsigned long flags;
-
-       /* "flow" corresponds to Tx queue */
-       u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
-
-       /* "ssn" is start of block-ack Tx window, corresponds to index
-        * (in Tx queue's circular buffer) of first TFD/frame in window */
-       u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
-
-       if (scd_flow >= priv->hw_params.max_txq_num) {
-               IWL_ERR(priv,
-                       "BUG_ON scd_flow is bigger than number of queues\n");
-               return;
-       }
-
-       txq = &priv->txq[scd_flow];
-       sta_id = ba_resp->sta_id;
-       tid = ba_resp->tid;
-       agg = &priv->stations[sta_id].tid[tid].agg;
-       if (unlikely(agg->txq_id != scd_flow)) {
-               /*
-                * FIXME: this is a uCode bug which need to be addressed,
-                * log the information and return for now!
-                * since it is possible happen very often and in order
-                * not to fill the syslog, don't enable the logging by default
-                */
-               IWL_DEBUG_TX_REPLY(priv,
-                       "BA scd_flow %d does not match txq_id %d\n",
-                       scd_flow, agg->txq_id);
-               return;
-       }
-
-       /* Find index just before block-ack window */
-       index = iwl_legacy_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-
-       IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
-                          "sta_id = %d\n",
-                          agg->wait_for_ba,
-                          (u8 *) &ba_resp->sta_addr_lo32,
-                          ba_resp->sta_id);
-       IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx,"
-                       "scd_flow = "
-                          "%d, scd_ssn = %d\n",
-                          ba_resp->tid,
-                          ba_resp->seq_ctl,
-                          (unsigned long long)le64_to_cpu(ba_resp->bitmap),
-                          ba_resp->scd_flow,
-                          ba_resp->scd_ssn);
-       IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n",
-                          agg->start_idx,
-                          (unsigned long long)agg->bitmap);
-
-       /* Update driver's record of ACK vs. not for each frame in window */
-       iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp);
-
-       /* Release all TFDs before the SSN, i.e. all TFDs in front of
-        * block-ack window (we assume that they've been successfully
-        * transmitted ... if not, it's too late anyway). */
-       if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
-               /* calculate mac80211 ampdu sw queue to wake */
-               int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index);
-               iwl4965_free_tfds_in_queue(priv, sta_id, tid, freed);
-
-               if ((iwl_legacy_queue_space(&txq->q) > txq->q.low_mark) &&
-                   priv->mac80211_registered &&
-                   (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
-                       iwl_legacy_wake_queue(priv, txq);
-
-               iwl4965_txq_check_empty(priv, sta_id, tid, scd_flow);
-       }
-
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-const char *iwl4965_get_tx_fail_reason(u32 status)
-{
-#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
-#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
-
-       switch (status & TX_STATUS_MSK) {
-       case TX_STATUS_SUCCESS:
-               return "SUCCESS";
-       TX_STATUS_POSTPONE(DELAY);
-       TX_STATUS_POSTPONE(FEW_BYTES);
-       TX_STATUS_POSTPONE(QUIET_PERIOD);
-       TX_STATUS_POSTPONE(CALC_TTAK);
-       TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
-       TX_STATUS_FAIL(SHORT_LIMIT);
-       TX_STATUS_FAIL(LONG_LIMIT);
-       TX_STATUS_FAIL(FIFO_UNDERRUN);
-       TX_STATUS_FAIL(DRAIN_FLOW);
-       TX_STATUS_FAIL(RFKILL_FLUSH);
-       TX_STATUS_FAIL(LIFE_EXPIRE);
-       TX_STATUS_FAIL(DEST_PS);
-       TX_STATUS_FAIL(HOST_ABORTED);
-       TX_STATUS_FAIL(BT_RETRY);
-       TX_STATUS_FAIL(STA_INVALID);
-       TX_STATUS_FAIL(FRAG_DROPPED);
-       TX_STATUS_FAIL(TID_DISABLE);
-       TX_STATUS_FAIL(FIFO_FLUSHED);
-       TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
-       TX_STATUS_FAIL(PASSIVE_NO_RX);
-       TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
-       }
-
-       return "UNKNOWN";
-
-#undef TX_STATUS_FAIL
-#undef TX_STATUS_POSTPONE
-}
-#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-ucode.c b/drivers/net/wireless/iwlegacy/iwl-4965-ucode.c
deleted file mode 100644 (file)
index 001d148..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-4965-hw.h"
-#include "iwl-4965.h"
-#include "iwl-4965-calib.h"
-
-#define IWL_AC_UNSET -1
-
-/**
- * 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
-iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
-{
-       u32 val;
-       int ret = 0;
-       u32 errcnt = 0;
-       u32 i;
-
-       IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
-
-       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_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-                       i + IWL4965_RTC_INST_LOWER_BOUND);
-               val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               if (val != le32_to_cpu(*image)) {
-                       ret = -EIO;
-                       errcnt++;
-                       if (errcnt >= 3)
-                               break;
-               }
-       }
-
-       return ret;
-}
-
-/**
- * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host,
- *     looking at all data.
- */
-static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image,
-                                u32 len)
-{
-       u32 val;
-       u32 save_len = len;
-       int ret = 0;
-       u32 errcnt;
-
-       IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
-
-       iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-                          IWL4965_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_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               if (val != le32_to_cpu(*image)) {
-                       IWL_ERR(priv, "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));
-                       ret = -EIO;
-                       errcnt++;
-                       if (errcnt >= 20)
-                               break;
-               }
-       }
-
-       if (!errcnt)
-               IWL_DEBUG_INFO(priv,
-                   "ucode image in INSTRUCTION memory is good\n");
-
-       return ret;
-}
-
-/**
- * iwl4965_verify_ucode - determine which instruction image is in SRAM,
- *    and verify its contents
- */
-int iwl4965_verify_ucode(struct iwl_priv *priv)
-{
-       __le32 *image;
-       u32 len;
-       int ret;
-
-       /* Try bootstrap */
-       image = (__le32 *)priv->ucode_boot.v_addr;
-       len = priv->ucode_boot.len;
-       ret = iwl4965_verify_inst_sparse(priv, image, len);
-       if (!ret) {
-               IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
-               return 0;
-       }
-
-       /* Try initialize */
-       image = (__le32 *)priv->ucode_init.v_addr;
-       len = priv->ucode_init.len;
-       ret = iwl4965_verify_inst_sparse(priv, image, len);
-       if (!ret) {
-               IWL_DEBUG_INFO(priv, "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;
-       ret = iwl4965_verify_inst_sparse(priv, image, len);
-       if (!ret) {
-               IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
-               return 0;
-       }
-
-       IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
-
-       /* Since nothing seems to match, show first several data entries in
-        * instruction SRAM, so maybe visual inspection will give a clue.
-        * Selection of bootstrap image (vs. other images) is arbitrary. */
-       image = (__le32 *)priv->ucode_boot.v_addr;
-       len = priv->ucode_boot.len;
-       ret = iwl4965_verify_inst_full(priv, image, len);
-
-       return ret;
-}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
deleted file mode 100644 (file)
index 86f4fce..0000000
+++ /dev/null
@@ -1,2183 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <net/mac80211.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-4965-calib.h"
-#include "iwl-sta.h"
-#include "iwl-4965-led.h"
-#include "iwl-4965.h"
-#include "iwl-4965-debugfs.h"
-
-static int iwl4965_send_tx_power(struct iwl_priv *priv);
-static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
-
-/* Highest firmware API version supported */
-#define IWL4965_UCODE_API_MAX 2
-
-/* Lowest firmware API version supported */
-#define IWL4965_UCODE_API_MIN 2
-
-#define IWL4965_FW_PRE "iwlwifi-4965-"
-#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode"
-#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api)
-
-/* check contents of special bootstrap uCode SRAM */
-static int iwl4965_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(priv, "Begin verify bsm\n");
-
-       /* verify BSM SRAM contents */
-       val = iwl_legacy_read_prph(priv, BSM_WR_DWCOUNT_REG);
-       for (reg = BSM_SRAM_LOWER_BOUND;
-            reg < BSM_SRAM_LOWER_BOUND + len;
-            reg += sizeof(u32), image++) {
-               val = iwl_legacy_read_prph(priv, reg);
-               if (val != le32_to_cpu(*image)) {
-                       IWL_ERR(priv, "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(priv, "BSM bootstrap uCode image OK\n");
-
-       return 0;
-}
-
-/**
- * iwl4965_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 iwl4965_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 i;
-       u32 done;
-       u32 reg_offset;
-       int ret;
-
-       IWL_DEBUG_INFO(priv, "Begin load bsm\n");
-
-       priv->ucode_type = UCODE_RT;
-
-       /* make sure bootstrap program is no larger than BSM's SRAM size */
-       if (len > IWL49_MAX_BSM_SIZE)
-               return -EINVAL;
-
-       /* Tell bootstrap uCode where to find the "Initialize" uCode
-        *   in host DRAM ... host DRAM physical address bits 35:4 for 4965.
-        * NOTE:  iwl_init_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_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-       iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-       iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
-       iwl_legacy_write_prph(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_legacy_write_prph(priv, reg_offset, le32_to_cpu(*image));
-
-       ret = iwl4965_verify_bsm(priv);
-       if (ret)
-               return ret;
-
-       /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
-       iwl_legacy_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
-       iwl_legacy_write_prph(priv,
-                       BSM_WR_MEM_DST_REG, IWL49_RTC_INST_LOWER_BOUND);
-       iwl_legacy_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
-
-       /* Load bootstrap code into instruction SRAM now,
-        *   to prepare to load "initialize" uCode */
-       iwl_legacy_write_prph(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_legacy_read_prph(priv, BSM_WR_CTRL_REG);
-               if (!(done & BSM_WR_CTRL_REG_BIT_START))
-                       break;
-               udelay(10);
-       }
-       if (i < 100)
-               IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
-       else {
-               IWL_ERR(priv, "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_legacy_write_prph(priv,
-                       BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
-
-
-       return 0;
-}
-
-/**
- * iwl4965_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 iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
-{
-       dma_addr_t pinst;
-       dma_addr_t pdata;
-       int ret = 0;
-
-       /* bits 35:4 for 4965 */
-       pinst = priv->ucode_code.p_addr >> 4;
-       pdata = priv->ucode_data_backup.p_addr >> 4;
-
-       /* Tell bootstrap uCode where to find image to load */
-       iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-       iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-       iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
-                                priv->ucode_data.len);
-
-       /* Inst byte count must be last to set up, bit 31 signals uCode
-        *   that all new ptr/size info is in place */
-       iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
-                                priv->ucode_code.len | BSM_DRAM_INST_LOAD);
-       IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
-
-       return ret;
-}
-
-/**
- * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received
- *
- * 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 iwl4965_init_alive_start(struct iwl_priv *priv)
-{
-       /* 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 (iwl4965_verify_ucode(priv)) {
-               /* Runtime instruction load was bad;
-                * take it all the way back down so we can try again */
-               IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
-               goto restart;
-       }
-
-       /* Calculate temperature */
-       priv->temperature = iwl4965_hw_get_temperature(priv);
-
-       /* 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(priv, "Initialization Alive received.\n");
-       if (iwl4965_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(priv, "Couldn't set up uCode pointers.\n");
-               goto restart;
-       }
-       return;
-
-restart:
-       queue_work(priv->workqueue, &priv->restart);
-}
-
-static bool iw4965_is_ht40_channel(__le32 rxon_flags)
-{
-       int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK)
-                                   >> RXON_FLG_CHANNEL_MODE_POS;
-       return ((chan_mod == CHANNEL_MODE_PURE_40) ||
-                 (chan_mod == CHANNEL_MODE_MIXED));
-}
-
-static void iwl4965_nic_config(struct iwl_priv *priv)
-{
-       unsigned long flags;
-       u16 radio_cfg;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       radio_cfg = iwl_legacy_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
-       /* write radio config values to register */
-       if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) == EEPROM_4965_RF_CFG_TYPE_MAX)
-               iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                           EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
-                           EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
-                           EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
-       /* set CSR_HW_CONFIG_REG for uCode use */
-       iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                   CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-                   CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
-
-       priv->calib_info = (struct iwl_eeprom_calib_info *)
-               iwl_legacy_eeprom_query_addr(priv,
-                               EEPROM_4965_CALIB_TXPOWER_OFFSET);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
- * Called after every association, but this runs only once!
- *  ... once chain noise is calibrated the first time, it's good forever.  */
-static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
-{
-       struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
-
-       if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
-           iwl_legacy_is_any_associated(priv)) {
-               struct iwl_calib_diff_gain_cmd cmd;
-
-               /* clear data for chain noise calibration algorithm */
-               data->chain_noise_a = 0;
-               data->chain_noise_b = 0;
-               data->chain_noise_c = 0;
-               data->chain_signal_a = 0;
-               data->chain_signal_b = 0;
-               data->chain_signal_c = 0;
-               data->beacon_count = 0;
-
-               memset(&cmd, 0, sizeof(cmd));
-               cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
-               cmd.diff_gain_a = 0;
-               cmd.diff_gain_b = 0;
-               cmd.diff_gain_c = 0;
-               if (iwl_legacy_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-                                sizeof(cmd), &cmd))
-                       IWL_ERR(priv,
-                               "Could not send REPLY_PHY_CALIBRATION_CMD\n");
-               data->state = IWL_CHAIN_NOISE_ACCUMULATE;
-               IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
-       }
-}
-
-static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
-       .min_nrg_cck = 97,
-       .max_nrg_cck = 0, /* not used, set to 0 */
-
-       .auto_corr_min_ofdm = 85,
-       .auto_corr_min_ofdm_mrc = 170,
-       .auto_corr_min_ofdm_x1 = 105,
-       .auto_corr_min_ofdm_mrc_x1 = 220,
-
-       .auto_corr_max_ofdm = 120,
-       .auto_corr_max_ofdm_mrc = 210,
-       .auto_corr_max_ofdm_x1 = 140,
-       .auto_corr_max_ofdm_mrc_x1 = 270,
-
-       .auto_corr_min_cck = 125,
-       .auto_corr_max_cck = 200,
-       .auto_corr_min_cck_mrc = 200,
-       .auto_corr_max_cck_mrc = 400,
-
-       .nrg_th_cck = 100,
-       .nrg_th_ofdm = 100,
-
-       .barker_corr_th_min = 190,
-       .barker_corr_th_min_mrc = 390,
-       .nrg_th_cca = 62,
-};
-
-static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
-{
-       /* want Kelvin */
-       priv->hw_params.ct_kill_threshold =
-               CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY);
-}
-
-/**
- * iwl4965_hw_set_hw_params
- *
- * Called when initializing driver
- */
-static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
-{
-       if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
-           priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES)
-               priv->cfg->base_params->num_of_queues =
-                       priv->cfg->mod_params->num_of_queues;
-
-       priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-       priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
-       priv->hw_params.scd_bc_tbls_size =
-                       priv->cfg->base_params->num_of_queues *
-                       sizeof(struct iwl4965_scd_bc_tbl);
-       priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
-       priv->hw_params.max_stations = IWL4965_STATION_COUNT;
-       priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL4965_BROADCAST_ID;
-       priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
-       priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
-       priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
-       priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ);
-
-       priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
-
-       priv->hw_params.tx_chains_num = iwl4965_num_of_ant(priv->cfg->valid_tx_ant);
-       priv->hw_params.rx_chains_num = iwl4965_num_of_ant(priv->cfg->valid_rx_ant);
-       priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
-       priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
-
-       iwl4965_set_ct_threshold(priv);
-
-       priv->hw_params.sens = &iwl4965_sensitivity;
-       priv->hw_params.beacon_time_tsf_bits = IWL4965_EXT_BEACON_TIME_POS;
-
-       return 0;
-}
-
-static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res)
-{
-       s32 sign = 1;
-
-       if (num < 0) {
-               sign = -sign;
-               num = -num;
-       }
-       if (denom < 0) {
-               sign = -sign;
-               denom = -denom;
-       }
-       *res = 1;
-       *res = ((num * 2 + denom) / (denom * 2)) * sign;
-
-       return 1;
-}
-
-/**
- * iwl4965_get_voltage_compensation - Power supply voltage comp for txpower
- *
- * Determines power supply voltage compensation for txpower calculations.
- * Returns number of 1/2-dB steps to subtract from gain table index,
- * to compensate for difference between power supply voltage during
- * factory measurements, vs. current power supply voltage.
- *
- * Voltage indication is higher for lower voltage.
- * Lower voltage requires more gain (lower gain table index).
- */
-static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
-                                           s32 current_voltage)
-{
-       s32 comp = 0;
-
-       if ((TX_POWER_IWL_ILLEGAL_VOLTAGE == eeprom_voltage) ||
-           (TX_POWER_IWL_ILLEGAL_VOLTAGE == current_voltage))
-               return 0;
-
-       iwl4965_math_div_round(current_voltage - eeprom_voltage,
-                              TX_POWER_IWL_VOLTAGE_CODES_PER_03V, &comp);
-
-       if (current_voltage > eeprom_voltage)
-               comp *= 2;
-       if ((comp < -2) || (comp > 2))
-               comp = 0;
-
-       return comp;
-}
-
-static s32 iwl4965_get_tx_atten_grp(u16 channel)
-{
-       if (channel >= CALIB_IWL_TX_ATTEN_GR5_FCH &&
-           channel <= CALIB_IWL_TX_ATTEN_GR5_LCH)
-               return CALIB_CH_GROUP_5;
-
-       if (channel >= CALIB_IWL_TX_ATTEN_GR1_FCH &&
-           channel <= CALIB_IWL_TX_ATTEN_GR1_LCH)
-               return CALIB_CH_GROUP_1;
-
-       if (channel >= CALIB_IWL_TX_ATTEN_GR2_FCH &&
-           channel <= CALIB_IWL_TX_ATTEN_GR2_LCH)
-               return CALIB_CH_GROUP_2;
-
-       if (channel >= CALIB_IWL_TX_ATTEN_GR3_FCH &&
-           channel <= CALIB_IWL_TX_ATTEN_GR3_LCH)
-               return CALIB_CH_GROUP_3;
-
-       if (channel >= CALIB_IWL_TX_ATTEN_GR4_FCH &&
-           channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
-               return CALIB_CH_GROUP_4;
-
-       return -EINVAL;
-}
-
-static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
-{
-       s32 b = -1;
-
-       for (b = 0; b < EEPROM_TX_POWER_BANDS; b++) {
-               if (priv->calib_info->band_info[b].ch_from == 0)
-                       continue;
-
-               if ((channel >= priv->calib_info->band_info[b].ch_from)
-                   && (channel <= priv->calib_info->band_info[b].ch_to))
-                       break;
-       }
-
-       return b;
-}
-
-static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
-{
-       s32 val;
-
-       if (x2 == x1)
-               return y1;
-       else {
-               iwl4965_math_div_round((x2 - x) * (y1 - y2), (x2 - x1), &val);
-               return val + y2;
-       }
-}
-
-/**
- * iwl4965_interpolate_chan - Interpolate factory measurements for one channel
- *
- * Interpolates factory measurements from the two sample channels within a
- * sub-band, to apply to channel of interest.  Interpolation is proportional to
- * differences in channel frequencies, which is proportional to differences
- * in channel number.
- */
-static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
-                                   struct iwl_eeprom_calib_ch_info *chan_info)
-{
-       s32 s = -1;
-       u32 c;
-       u32 m;
-       const struct iwl_eeprom_calib_measure *m1;
-       const struct iwl_eeprom_calib_measure *m2;
-       struct iwl_eeprom_calib_measure *omeas;
-       u32 ch_i1;
-       u32 ch_i2;
-
-       s = iwl4965_get_sub_band(priv, channel);
-       if (s >= EEPROM_TX_POWER_BANDS) {
-               IWL_ERR(priv, "Tx Power can not find channel %d\n", channel);
-               return -1;
-       }
-
-       ch_i1 = priv->calib_info->band_info[s].ch1.ch_num;
-       ch_i2 = priv->calib_info->band_info[s].ch2.ch_num;
-       chan_info->ch_num = (u8) channel;
-
-       IWL_DEBUG_TXPOWER(priv, "channel %d subband %d factory cal ch %d & %d\n",
-                         channel, s, ch_i1, ch_i2);
-
-       for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) {
-               for (m = 0; m < EEPROM_TX_POWER_MEASUREMENTS; m++) {
-                       m1 = &(priv->calib_info->band_info[s].ch1.
-                              measurements[c][m]);
-                       m2 = &(priv->calib_info->band_info[s].ch2.
-                              measurements[c][m]);
-                       omeas = &(chan_info->measurements[c][m]);
-
-                       omeas->actual_pow =
-                           (u8) iwl4965_interpolate_value(channel, ch_i1,
-                                                          m1->actual_pow,
-                                                          ch_i2,
-                                                          m2->actual_pow);
-                       omeas->gain_idx =
-                           (u8) iwl4965_interpolate_value(channel, ch_i1,
-                                                          m1->gain_idx, ch_i2,
-                                                          m2->gain_idx);
-                       omeas->temperature =
-                           (u8) iwl4965_interpolate_value(channel, ch_i1,
-                                                          m1->temperature,
-                                                          ch_i2,
-                                                          m2->temperature);
-                       omeas->pa_det =
-                           (s8) iwl4965_interpolate_value(channel, ch_i1,
-                                                          m1->pa_det, ch_i2,
-                                                          m2->pa_det);
-
-                       IWL_DEBUG_TXPOWER(priv,
-                               "chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m,
-                               m1->actual_pow, m2->actual_pow, omeas->actual_pow);
-                       IWL_DEBUG_TXPOWER(priv,
-                               "chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m,
-                               m1->gain_idx, m2->gain_idx, omeas->gain_idx);
-                       IWL_DEBUG_TXPOWER(priv,
-                               "chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m,
-                               m1->pa_det, m2->pa_det, omeas->pa_det);
-                       IWL_DEBUG_TXPOWER(priv,
-                               "chain %d meas %d  T1=%d  T2=%d  T=%d\n", c, m,
-                               m1->temperature, m2->temperature,
-                               omeas->temperature);
-               }
-       }
-
-       return 0;
-}
-
-/* bit-rate-dependent table to prevent Tx distortion, in half-dB units,
- * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. */
-static s32 back_off_table[] = {
-       10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 20 MHz */
-       10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 20 MHz */
-       10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 40 MHz */
-       10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 40 MHz */
-       10                      /* CCK */
-};
-
-/* Thermal compensation values for txpower for various frequency ranges ...
- *   ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */
-static struct iwl4965_txpower_comp_entry {
-       s32 degrees_per_05db_a;
-       s32 degrees_per_05db_a_denom;
-} tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = {
-       {9, 2},                 /* group 0 5.2, ch  34-43 */
-       {4, 1},                 /* group 1 5.2, ch  44-70 */
-       {4, 1},                 /* group 2 5.2, ch  71-124 */
-       {4, 1},                 /* group 3 5.2, ch 125-200 */
-       {3, 1}                  /* group 4 2.4, ch   all */
-};
-
-static s32 get_min_power_index(s32 rate_power_index, u32 band)
-{
-       if (!band) {
-               if ((rate_power_index & 7) <= 4)
-                       return MIN_TX_GAIN_INDEX_52GHZ_EXT;
-       }
-       return MIN_TX_GAIN_INDEX;
-}
-
-struct gain_entry {
-       u8 dsp;
-       u8 radio;
-};
-
-static const struct gain_entry gain_table[2][108] = {
-       /* 5.2GHz power gain index table */
-       {
-        {123, 0x3F},           /* highest txpower */
-        {117, 0x3F},
-        {110, 0x3F},
-        {104, 0x3F},
-        {98, 0x3F},
-        {110, 0x3E},
-        {104, 0x3E},
-        {98, 0x3E},
-        {110, 0x3D},
-        {104, 0x3D},
-        {98, 0x3D},
-        {110, 0x3C},
-        {104, 0x3C},
-        {98, 0x3C},
-        {110, 0x3B},
-        {104, 0x3B},
-        {98, 0x3B},
-        {110, 0x3A},
-        {104, 0x3A},
-        {98, 0x3A},
-        {110, 0x39},
-        {104, 0x39},
-        {98, 0x39},
-        {110, 0x38},
-        {104, 0x38},
-        {98, 0x38},
-        {110, 0x37},
-        {104, 0x37},
-        {98, 0x37},
-        {110, 0x36},
-        {104, 0x36},
-        {98, 0x36},
-        {110, 0x35},
-        {104, 0x35},
-        {98, 0x35},
-        {110, 0x34},
-        {104, 0x34},
-        {98, 0x34},
-        {110, 0x33},
-        {104, 0x33},
-        {98, 0x33},
-        {110, 0x32},
-        {104, 0x32},
-        {98, 0x32},
-        {110, 0x31},
-        {104, 0x31},
-        {98, 0x31},
-        {110, 0x30},
-        {104, 0x30},
-        {98, 0x30},
-        {110, 0x25},
-        {104, 0x25},
-        {98, 0x25},
-        {110, 0x24},
-        {104, 0x24},
-        {98, 0x24},
-        {110, 0x23},
-        {104, 0x23},
-        {98, 0x23},
-        {110, 0x22},
-        {104, 0x18},
-        {98, 0x18},
-        {110, 0x17},
-        {104, 0x17},
-        {98, 0x17},
-        {110, 0x16},
-        {104, 0x16},
-        {98, 0x16},
-        {110, 0x15},
-        {104, 0x15},
-        {98, 0x15},
-        {110, 0x14},
-        {104, 0x14},
-        {98, 0x14},
-        {110, 0x13},
-        {104, 0x13},
-        {98, 0x13},
-        {110, 0x12},
-        {104, 0x08},
-        {98, 0x08},
-        {110, 0x07},
-        {104, 0x07},
-        {98, 0x07},
-        {110, 0x06},
-        {104, 0x06},
-        {98, 0x06},
-        {110, 0x05},
-        {104, 0x05},
-        {98, 0x05},
-        {110, 0x04},
-        {104, 0x04},
-        {98, 0x04},
-        {110, 0x03},
-        {104, 0x03},
-        {98, 0x03},
-        {110, 0x02},
-        {104, 0x02},
-        {98, 0x02},
-        {110, 0x01},
-        {104, 0x01},
-        {98, 0x01},
-        {110, 0x00},
-        {104, 0x00},
-        {98, 0x00},
-        {93, 0x00},
-        {88, 0x00},
-        {83, 0x00},
-        {78, 0x00},
-        },
-       /* 2.4GHz power gain index table */
-       {
-        {110, 0x3f},           /* highest txpower */
-        {104, 0x3f},
-        {98, 0x3f},
-        {110, 0x3e},
-        {104, 0x3e},
-        {98, 0x3e},
-        {110, 0x3d},
-        {104, 0x3d},
-        {98, 0x3d},
-        {110, 0x3c},
-        {104, 0x3c},
-        {98, 0x3c},
-        {110, 0x3b},
-        {104, 0x3b},
-        {98, 0x3b},
-        {110, 0x3a},
-        {104, 0x3a},
-        {98, 0x3a},
-        {110, 0x39},
-        {104, 0x39},
-        {98, 0x39},
-        {110, 0x38},
-        {104, 0x38},
-        {98, 0x38},
-        {110, 0x37},
-        {104, 0x37},
-        {98, 0x37},
-        {110, 0x36},
-        {104, 0x36},
-        {98, 0x36},
-        {110, 0x35},
-        {104, 0x35},
-        {98, 0x35},
-        {110, 0x34},
-        {104, 0x34},
-        {98, 0x34},
-        {110, 0x33},
-        {104, 0x33},
-        {98, 0x33},
-        {110, 0x32},
-        {104, 0x32},
-        {98, 0x32},
-        {110, 0x31},
-        {104, 0x31},
-        {98, 0x31},
-        {110, 0x30},
-        {104, 0x30},
-        {98, 0x30},
-        {110, 0x6},
-        {104, 0x6},
-        {98, 0x6},
-        {110, 0x5},
-        {104, 0x5},
-        {98, 0x5},
-        {110, 0x4},
-        {104, 0x4},
-        {98, 0x4},
-        {110, 0x3},
-        {104, 0x3},
-        {98, 0x3},
-        {110, 0x2},
-        {104, 0x2},
-        {98, 0x2},
-        {110, 0x1},
-        {104, 0x1},
-        {98, 0x1},
-        {110, 0x0},
-        {104, 0x0},
-        {98, 0x0},
-        {97, 0},
-        {96, 0},
-        {95, 0},
-        {94, 0},
-        {93, 0},
-        {92, 0},
-        {91, 0},
-        {90, 0},
-        {89, 0},
-        {88, 0},
-        {87, 0},
-        {86, 0},
-        {85, 0},
-        {84, 0},
-        {83, 0},
-        {82, 0},
-        {81, 0},
-        {80, 0},
-        {79, 0},
-        {78, 0},
-        {77, 0},
-        {76, 0},
-        {75, 0},
-        {74, 0},
-        {73, 0},
-        {72, 0},
-        {71, 0},
-        {70, 0},
-        {69, 0},
-        {68, 0},
-        {67, 0},
-        {66, 0},
-        {65, 0},
-        {64, 0},
-        {63, 0},
-        {62, 0},
-        {61, 0},
-        {60, 0},
-        {59, 0},
-        }
-};
-
-static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
-                                   u8 is_ht40, u8 ctrl_chan_high,
-                                   struct iwl4965_tx_power_db *tx_power_tbl)
-{
-       u8 saturation_power;
-       s32 target_power;
-       s32 user_target_power;
-       s32 power_limit;
-       s32 current_temp;
-       s32 reg_limit;
-       s32 current_regulatory;
-       s32 txatten_grp = CALIB_CH_GROUP_MAX;
-       int i;
-       int c;
-       const struct iwl_channel_info *ch_info = NULL;
-       struct iwl_eeprom_calib_ch_info ch_eeprom_info;
-       const struct iwl_eeprom_calib_measure *measurement;
-       s16 voltage;
-       s32 init_voltage;
-       s32 voltage_compensation;
-       s32 degrees_per_05db_num;
-       s32 degrees_per_05db_denom;
-       s32 factory_temp;
-       s32 temperature_comp[2];
-       s32 factory_gain_index[2];
-       s32 factory_actual_pwr[2];
-       s32 power_index;
-
-       /* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units
-        *   are used for indexing into txpower table) */
-       user_target_power = 2 * priv->tx_power_user_lmt;
-
-       /* Get current (RXON) channel, band, width */
-       IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band,
-                         is_ht40);
-
-       ch_info = iwl_legacy_get_channel_info(priv, priv->band, channel);
-
-       if (!iwl_legacy_is_channel_valid(ch_info))
-               return -EINVAL;
-
-       /* get txatten group, used to select 1) thermal txpower adjustment
-        *   and 2) mimo txpower balance between Tx chains. */
-       txatten_grp = iwl4965_get_tx_atten_grp(channel);
-       if (txatten_grp < 0) {
-               IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
-                         channel);
-               return txatten_grp;
-       }
-
-       IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
-                         channel, txatten_grp);
-
-       if (is_ht40) {
-               if (ctrl_chan_high)
-                       channel -= 2;
-               else
-                       channel += 2;
-       }
-
-       /* hardware txpower limits ...
-        * saturation (clipping distortion) txpowers are in half-dBm */
-       if (band)
-               saturation_power = priv->calib_info->saturation_power24;
-       else
-               saturation_power = priv->calib_info->saturation_power52;
-
-       if (saturation_power < IWL_TX_POWER_SATURATION_MIN ||
-           saturation_power > IWL_TX_POWER_SATURATION_MAX) {
-               if (band)
-                       saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_24;
-               else
-                       saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_52;
-       }
-
-       /* regulatory txpower limits ... reg_limit values are in half-dBm,
-        *   max_power_avg values are in dBm, convert * 2 */
-       if (is_ht40)
-               reg_limit = ch_info->ht40_max_power_avg * 2;
-       else
-               reg_limit = ch_info->max_power_avg * 2;
-
-       if ((reg_limit < IWL_TX_POWER_REGULATORY_MIN) ||
-           (reg_limit > IWL_TX_POWER_REGULATORY_MAX)) {
-               if (band)
-                       reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_24;
-               else
-                       reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_52;
-       }
-
-       /* Interpolate txpower calibration values for this channel,
-        *   based on factory calibration tests on spaced channels. */
-       iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info);
-
-       /* calculate tx gain adjustment based on power supply voltage */
-       voltage = le16_to_cpu(priv->calib_info->voltage);
-       init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage);
-       voltage_compensation =
-           iwl4965_get_voltage_compensation(voltage, init_voltage);
-
-       IWL_DEBUG_TXPOWER(priv, "curr volt %d eeprom volt %d volt comp %d\n",
-                         init_voltage,
-                         voltage, voltage_compensation);
-
-       /* get current temperature (Celsius) */
-       current_temp = max(priv->temperature, IWL_TX_POWER_TEMPERATURE_MIN);
-       current_temp = min(priv->temperature, IWL_TX_POWER_TEMPERATURE_MAX);
-       current_temp = KELVIN_TO_CELSIUS(current_temp);
-
-       /* select thermal txpower adjustment params, based on channel group
-        *   (same frequency group used for mimo txatten adjustment) */
-       degrees_per_05db_num =
-           tx_power_cmp_tble[txatten_grp].degrees_per_05db_a;
-       degrees_per_05db_denom =
-           tx_power_cmp_tble[txatten_grp].degrees_per_05db_a_denom;
-
-       /* get per-chain txpower values from factory measurements */
-       for (c = 0; c < 2; c++) {
-               measurement = &ch_eeprom_info.measurements[c][1];
-
-               /* txgain adjustment (in half-dB steps) based on difference
-                *   between factory and current temperature */
-               factory_temp = measurement->temperature;
-               iwl4965_math_div_round((current_temp - factory_temp) *
-                                      degrees_per_05db_denom,
-                                      degrees_per_05db_num,
-                                      &temperature_comp[c]);
-
-               factory_gain_index[c] = measurement->gain_idx;
-               factory_actual_pwr[c] = measurement->actual_pow;
-
-               IWL_DEBUG_TXPOWER(priv, "chain = %d\n", c);
-               IWL_DEBUG_TXPOWER(priv, "fctry tmp %d, "
-                                 "curr tmp %d, comp %d steps\n",
-                                 factory_temp, current_temp,
-                                 temperature_comp[c]);
-
-               IWL_DEBUG_TXPOWER(priv, "fctry idx %d, fctry pwr %d\n",
-                                 factory_gain_index[c],
-                                 factory_actual_pwr[c]);
-       }
-
-       /* for each of 33 bit-rates (including 1 for CCK) */
-       for (i = 0; i < POWER_TABLE_NUM_ENTRIES; i++) {
-               u8 is_mimo_rate;
-               union iwl4965_tx_power_dual_stream tx_power;
-
-               /* for mimo, reduce each chain's txpower by half
-                * (3dB, 6 steps), so total output power is regulatory
-                * compliant. */
-               if (i & 0x8) {
-                       current_regulatory = reg_limit -
-                           IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION;
-                       is_mimo_rate = 1;
-               } else {
-                       current_regulatory = reg_limit;
-                       is_mimo_rate = 0;
-               }
-
-               /* find txpower limit, either hardware or regulatory */
-               power_limit = saturation_power - back_off_table[i];
-               if (power_limit > current_regulatory)
-                       power_limit = current_regulatory;
-
-               /* reduce user's txpower request if necessary
-                * for this rate on this channel */
-               target_power = user_target_power;
-               if (target_power > power_limit)
-                       target_power = power_limit;
-
-               IWL_DEBUG_TXPOWER(priv, "rate %d sat %d reg %d usr %d tgt %d\n",
-                                 i, saturation_power - back_off_table[i],
-                                 current_regulatory, user_target_power,
-                                 target_power);
-
-               /* for each of 2 Tx chains (radio transmitters) */
-               for (c = 0; c < 2; c++) {
-                       s32 atten_value;
-
-                       if (is_mimo_rate)
-                               atten_value =
-                                   (s32)le32_to_cpu(priv->card_alive_init.
-                                   tx_atten[txatten_grp][c]);
-                       else
-                               atten_value = 0;
-
-                       /* calculate index; higher index means lower txpower */
-                       power_index = (u8) (factory_gain_index[c] -
-                                           (target_power -
-                                            factory_actual_pwr[c]) -
-                                           temperature_comp[c] -
-                                           voltage_compensation +
-                                           atten_value);
-
-/*                     IWL_DEBUG_TXPOWER(priv, "calculated txpower index %d\n",
-                                               power_index); */
-
-                       if (power_index < get_min_power_index(i, band))
-                               power_index = get_min_power_index(i, band);
-
-                       /* adjust 5 GHz index to support negative indexes */
-                       if (!band)
-                               power_index += 9;
-
-                       /* CCK, rate 32, reduce txpower for CCK */
-                       if (i == POWER_TABLE_CCK_ENTRY)
-                               power_index +=
-                                   IWL_TX_POWER_CCK_COMPENSATION_C_STEP;
-
-                       /* stay within the table! */
-                       if (power_index > 107) {
-                               IWL_WARN(priv, "txpower index %d > 107\n",
-                                           power_index);
-                               power_index = 107;
-                       }
-                       if (power_index < 0) {
-                               IWL_WARN(priv, "txpower index %d < 0\n",
-                                           power_index);
-                               power_index = 0;
-                       }
-
-                       /* fill txpower command for this rate/chain */
-                       tx_power.s.radio_tx_gain[c] =
-                               gain_table[band][power_index].radio;
-                       tx_power.s.dsp_predis_atten[c] =
-                               gain_table[band][power_index].dsp;
-
-                       IWL_DEBUG_TXPOWER(priv, "chain %d mimo %d index %d "
-                                         "gain 0x%02x dsp %d\n",
-                                         c, atten_value, power_index,
-                                       tx_power.s.radio_tx_gain[c],
-                                       tx_power.s.dsp_predis_atten[c]);
-               } /* for each chain */
-
-               tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw);
-
-       } /* for each rate */
-
-       return 0;
-}
-
-/**
- * iwl4965_send_tx_power - Configure the TXPOWER level user limit
- *
- * Uses the active RXON for channel, band, and characteristics (ht40, high)
- * The power limit is taken from priv->tx_power_user_lmt.
- */
-static int iwl4965_send_tx_power(struct iwl_priv *priv)
-{
-       struct iwl4965_txpowertable_cmd cmd = { 0 };
-       int ret;
-       u8 band = 0;
-       bool is_ht40 = false;
-       u8 ctrl_chan_high = 0;
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
-                     "TX Power requested while scanning!\n"))
-               return -EAGAIN;
-
-       band = priv->band == IEEE80211_BAND_2GHZ;
-
-       is_ht40 = iw4965_is_ht40_channel(ctx->active.flags);
-
-       if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
-               ctrl_chan_high = 1;
-
-       cmd.band = band;
-       cmd.channel = ctx->active.channel;
-
-       ret = iwl4965_fill_txpower_tbl(priv, band,
-                               le16_to_cpu(ctx->active.channel),
-                               is_ht40, ctrl_chan_high, &cmd.tx_power);
-       if (ret)
-               goto out;
-
-       ret = iwl_legacy_send_cmd_pdu(priv,
-                        REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
-
-out:
-       return ret;
-}
-
-static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
-                                  struct iwl_rxon_context *ctx)
-{
-       int ret = 0;
-       struct iwl4965_rxon_assoc_cmd rxon_assoc;
-       const struct iwl_legacy_rxon_cmd *rxon1 = &ctx->staging;
-       const struct iwl_legacy_rxon_cmd *rxon2 = &ctx->active;
-
-       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(priv, "Using current RXON_ASSOC.  Not resending.\n");
-               return 0;
-       }
-
-       rxon_assoc.flags = ctx->staging.flags;
-       rxon_assoc.filter_flags = ctx->staging.filter_flags;
-       rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
-       rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
-       rxon_assoc.reserved = 0;
-       rxon_assoc.ofdm_ht_single_stream_basic_rates =
-           ctx->staging.ofdm_ht_single_stream_basic_rates;
-       rxon_assoc.ofdm_ht_dual_stream_basic_rates =
-           ctx->staging.ofdm_ht_dual_stream_basic_rates;
-       rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
-
-       ret = iwl_legacy_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
-                                    sizeof(rxon_assoc), &rxon_assoc, NULL);
-
-       return ret;
-}
-
-static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-       /* cast away the const for active_rxon in this function */
-       struct iwl_legacy_rxon_cmd *active_rxon = (void *)&ctx->active;
-       int ret;
-       bool new_assoc =
-               !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
-
-       if (!iwl_legacy_is_alive(priv))
-               return -EBUSY;
-
-       if (!ctx->is_active)
-               return 0;
-
-       /* always get timestamp with Rx frame */
-       ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
-
-       ret = iwl_legacy_check_rxon_cmd(priv, ctx);
-       if (ret) {
-               IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
-               return -EINVAL;
-       }
-
-       /*
-        * receive commit_rxon request
-        * abort any previous channel switch if still in process
-        */
-       if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) &&
-           (priv->switch_channel != ctx->staging.channel)) {
-               IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
-                     le16_to_cpu(priv->switch_channel));
-               iwl_legacy_chswitch_done(priv, false);
-       }
-
-       /* 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_legacy_full_rxon_required(priv, ctx)) {
-               ret = iwl_legacy_send_rxon_assoc(priv, ctx);
-               if (ret) {
-                       IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
-                       return ret;
-               }
-
-               memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-               iwl_legacy_print_rx_config_cmd(priv, ctx);
-               /*
-                * We do not commit tx power settings while channel changing,
-                * do it now if tx power changed.
-                */
-               iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
-               return 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_legacy_is_associated_ctx(ctx) && new_assoc) {
-               IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
-               active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-               ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
-                                      sizeof(struct iwl_legacy_rxon_cmd),
-                                      active_rxon);
-
-               /* If the mask clearing failed then we set
-                * active_rxon back to what it was previously */
-               if (ret) {
-                       active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-                       IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
-                       return ret;
-               }
-               iwl_legacy_clear_ucode_stations(priv, ctx);
-               iwl_legacy_restore_stations(priv, ctx);
-               ret = iwl4965_restore_default_wep_keys(priv, ctx);
-               if (ret) {
-                       IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
-                       return ret;
-               }
-       }
-
-       IWL_DEBUG_INFO(priv, "Sending RXON\n"
-                      "* with%s RXON_FILTER_ASSOC_MSK\n"
-                      "* channel = %d\n"
-                      "* bssid = %pM\n",
-                      (new_assoc ? "" : "out"),
-                      le16_to_cpu(ctx->staging.channel),
-                      ctx->staging.bssid_addr);
-
-       iwl_legacy_set_rxon_hwcrypto(priv, ctx,
-                               !priv->cfg->mod_params->sw_crypto);
-
-       /* Apply the new configuration
-        * RXON unassoc clears the station table in uCode so restoration of
-        * stations is needed after it (the RXON command) completes
-        */
-       if (!new_assoc) {
-               ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
-                             sizeof(struct iwl_legacy_rxon_cmd), &ctx->staging);
-               if (ret) {
-                       IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
-                       return ret;
-               }
-               IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
-               memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-               iwl_legacy_clear_ucode_stations(priv, ctx);
-               iwl_legacy_restore_stations(priv, ctx);
-               ret = iwl4965_restore_default_wep_keys(priv, ctx);
-               if (ret) {
-                       IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
-                       return ret;
-               }
-       }
-       if (new_assoc) {
-               priv->start_calib = 0;
-               /* Apply the new configuration
-                * RXON assoc doesn't clear the station table in uCode,
-                */
-               ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
-                             sizeof(struct iwl_legacy_rxon_cmd), &ctx->staging);
-               if (ret) {
-                       IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
-                       return ret;
-               }
-               memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-       }
-       iwl_legacy_print_rx_config_cmd(priv, ctx);
-
-       iwl4965_init_sensitivity(priv);
-
-       /* 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 */
-       ret = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true);
-       if (ret) {
-               IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
-                                    struct ieee80211_channel_switch *ch_switch)
-{
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       int rc;
-       u8 band = 0;
-       bool is_ht40 = false;
-       u8 ctrl_chan_high = 0;
-       struct iwl4965_channel_switch_cmd cmd;
-       const struct iwl_channel_info *ch_info;
-       u32 switch_time_in_usec, ucode_switch_time;
-       u16 ch;
-       u32 tsf_low;
-       u8 switch_count;
-       u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
-       struct ieee80211_vif *vif = ctx->vif;
-       band = priv->band == IEEE80211_BAND_2GHZ;
-
-       is_ht40 = iw4965_is_ht40_channel(ctx->staging.flags);
-
-       if (is_ht40 &&
-           (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
-               ctrl_chan_high = 1;
-
-       cmd.band = band;
-       cmd.expect_beacon = 0;
-       ch = ch_switch->channel->hw_value;
-       cmd.channel = cpu_to_le16(ch);
-       cmd.rxon_flags = ctx->staging.flags;
-       cmd.rxon_filter_flags = ctx->staging.filter_flags;
-       switch_count = ch_switch->count;
-       tsf_low = ch_switch->timestamp & 0x0ffffffff;
-       /*
-        * calculate the ucode channel switch time
-        * adding TSF as one of the factor for when to switch
-        */
-       if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
-               if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
-                   beacon_interval)) {
-                       switch_count -= (priv->ucode_beacon_time -
-                               tsf_low) / beacon_interval;
-               } else
-                       switch_count = 0;
-       }
-       if (switch_count <= 1)
-               cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
-       else {
-               switch_time_in_usec =
-                       vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
-               ucode_switch_time = iwl_legacy_usecs_to_beacons(priv,
-                                                        switch_time_in_usec,
-                                                        beacon_interval);
-               cmd.switch_time = iwl_legacy_add_beacon_time(priv,
-                                                     priv->ucode_beacon_time,
-                                                     ucode_switch_time,
-                                                     beacon_interval);
-       }
-       IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
-                     cmd.switch_time);
-       ch_info = iwl_legacy_get_channel_info(priv, priv->band, ch);
-       if (ch_info)
-               cmd.expect_beacon = iwl_legacy_is_channel_radar(ch_info);
-       else {
-               IWL_ERR(priv, "invalid channel switch from %u to %u\n",
-                       ctx->active.channel, ch);
-               return -EFAULT;
-       }
-
-       rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40,
-                                     ctrl_chan_high, &cmd.tx_power);
-       if (rc) {
-               IWL_DEBUG_11H(priv, "error:%d  fill txpower_tbl\n", rc);
-               return rc;
-       }
-
-       return iwl_legacy_send_cmd_pdu(priv,
-                        REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
-}
-
-/**
- * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
- */
-static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
-                                           struct iwl_tx_queue *txq,
-                                           u16 byte_cnt)
-{
-       struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
-       int txq_id = txq->q.id;
-       int write_ptr = txq->q.write_ptr;
-       int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
-       __le16 bc_ent;
-
-       WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
-
-       bc_ent = cpu_to_le16(len & 0xFFF);
-       /* Set up byte count within first 256 entries */
-       scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
-
-       /* If within first 64 entries, duplicate at end */
-       if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
-               scd_bc_tbl[txq_id].
-                       tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
-}
-
-/**
- * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
- * @statistics: Provides the temperature reading from the uCode
- *
- * A return of <0 indicates bogus data in the statistics
- */
-static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
-{
-       s32 temperature;
-       s32 vt;
-       s32 R1, R2, R3;
-       u32 R4;
-
-       if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
-           (priv->_4965.statistics.flag &
-                       STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
-               IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
-               R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
-               R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
-               R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]);
-               R4 = le32_to_cpu(priv->card_alive_init.therm_r4[1]);
-       } else {
-               IWL_DEBUG_TEMP(priv, "Running temperature calibration\n");
-               R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[0]);
-               R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[0]);
-               R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[0]);
-               R4 = le32_to_cpu(priv->card_alive_init.therm_r4[0]);
-       }
-
-       /*
-        * Temperature is only 23 bits, so sign extend out to 32.
-        *
-        * NOTE If we haven't received a statistics notification yet
-        * with an updated temperature, use R4 provided to us in the
-        * "initialize" ALIVE response.
-        */
-       if (!test_bit(STATUS_TEMPERATURE, &priv->status))
-               vt = sign_extend32(R4, 23);
-       else
-               vt = sign_extend32(le32_to_cpu(priv->_4965.statistics.
-                                general.common.temperature), 23);
-
-       IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
-
-       if (R3 == R1) {
-               IWL_ERR(priv, "Calibration conflict R1 == R3\n");
-               return -1;
-       }
-
-       /* Calculate temperature in degrees Kelvin, adjust by 97%.
-        * Add offset to center the adjustment around 0 degrees Centigrade. */
-       temperature = TEMPERATURE_CALIB_A_VAL * (vt - R2);
-       temperature /= (R3 - R1);
-       temperature = (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET;
-
-       IWL_DEBUG_TEMP(priv, "Calibrated temperature: %dK, %dC\n",
-                       temperature, KELVIN_TO_CELSIUS(temperature));
-
-       return temperature;
-}
-
-/* Adjust Txpower only if temperature variance is greater than threshold. */
-#define IWL_TEMPERATURE_THRESHOLD   3
-
-/**
- * iwl4965_is_temp_calib_needed - determines if new calibration is needed
- *
- * If the temperature changed has changed sufficiently, then a recalibration
- * is needed.
- *
- * Assumes caller will replace priv->last_temperature once calibration
- * executed.
- */
-static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
-{
-       int temp_diff;
-
-       if (!test_bit(STATUS_STATISTICS, &priv->status)) {
-               IWL_DEBUG_TEMP(priv, "Temperature not updated -- no statistics.\n");
-               return 0;
-       }
-
-       temp_diff = priv->temperature - priv->last_temperature;
-
-       /* get absolute value */
-       if (temp_diff < 0) {
-               IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff);
-               temp_diff = -temp_diff;
-       } else if (temp_diff == 0)
-               IWL_DEBUG_POWER(priv, "Temperature unchanged\n");
-       else
-               IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff);
-
-       if (temp_diff < IWL_TEMPERATURE_THRESHOLD) {
-               IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n");
-               return 0;
-       }
-
-       IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n");
-
-       return 1;
-}
-
-static void iwl4965_temperature_calib(struct iwl_priv *priv)
-{
-       s32 temp;
-
-       temp = iwl4965_hw_get_temperature(priv);
-       if (IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(temp))
-               return;
-
-       if (priv->temperature != temp) {
-               if (priv->temperature)
-                       IWL_DEBUG_TEMP(priv, "Temperature changed "
-                                      "from %dC to %dC\n",
-                                      KELVIN_TO_CELSIUS(priv->temperature),
-                                      KELVIN_TO_CELSIUS(temp));
-               else
-                       IWL_DEBUG_TEMP(priv, "Temperature "
-                                      "initialized to %dC\n",
-                                      KELVIN_TO_CELSIUS(temp));
-       }
-
-       priv->temperature = temp;
-       set_bit(STATUS_TEMPERATURE, &priv->status);
-
-       if (!priv->disable_tx_power_cal &&
-            unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
-            iwl4965_is_temp_calib_needed(priv))
-               queue_work(priv->workqueue, &priv->txpower_work);
-}
-
-static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len)
-{
-       switch (cmd_id) {
-       case REPLY_RXON:
-               return (u16) sizeof(struct iwl4965_rxon_cmd);
-       default:
-               return len;
-       }
-}
-
-static u16 iwl4965_build_addsta_hcmd(const struct iwl_legacy_addsta_cmd *cmd,
-                                                               u8 *data)
-{
-       struct iwl4965_addsta_cmd *addsta = (struct iwl4965_addsta_cmd *)data;
-       addsta->mode = cmd->mode;
-       memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
-       memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo));
-       addsta->station_flags = cmd->station_flags;
-       addsta->station_flags_msk = cmd->station_flags_msk;
-       addsta->tid_disable_tx = cmd->tid_disable_tx;
-       addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
-       addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
-       addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
-       addsta->sleep_tx_count = cmd->sleep_tx_count;
-       addsta->reserved1 = cpu_to_le16(0);
-       addsta->reserved2 = cpu_to_le16(0);
-
-       return (u16)sizeof(struct iwl4965_addsta_cmd);
-}
-
-static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
-{
-       return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN;
-}
-
-/**
- * iwl4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue
- */
-static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
-                                     struct iwl_ht_agg *agg,
-                                     struct iwl4965_tx_resp *tx_resp,
-                                     int txq_id, u16 start_idx)
-{
-       u16 status;
-       struct agg_tx_status *frame_status = tx_resp->u.agg_status;
-       struct ieee80211_tx_info *info = NULL;
-       struct ieee80211_hdr *hdr = NULL;
-       u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
-       int i, sh, idx;
-       u16 seq;
-       if (agg->wait_for_ba)
-               IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
-
-       agg->frame_count = tx_resp->frame_count;
-       agg->start_idx = start_idx;
-       agg->rate_n_flags = rate_n_flags;
-       agg->bitmap = 0;
-
-       /* num frames attempted by Tx command */
-       if (agg->frame_count == 1) {
-               /* Only one frame was attempted; no block-ack will arrive */
-               status = le16_to_cpu(frame_status[0].status);
-               idx = start_idx;
-
-               IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
-                                  agg->frame_count, agg->start_idx, idx);
-
-               info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
-               info->status.rates[0].count = tx_resp->failure_frame + 1;
-               info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-               info->flags |= iwl4965_tx_status_to_mac80211(status);
-               iwl4965_hwrate_to_tx_control(priv, rate_n_flags, info);
-
-               IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
-                                   status & 0xff, tx_resp->failure_frame);
-               IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags);
-
-               agg->wait_for_ba = 0;
-       } else {
-               /* Two or more frames were attempted; expect block-ack */
-               u64 bitmap = 0;
-               int start = agg->start_idx;
-
-               /* Construct bit-map of pending frames within Tx window */
-               for (i = 0; i < agg->frame_count; i++) {
-                       u16 sc;
-                       status = le16_to_cpu(frame_status[i].status);
-                       seq  = le16_to_cpu(frame_status[i].sequence);
-                       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(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
-                                          agg->frame_count, txq_id, idx);
-
-                       hdr = iwl_legacy_tx_queue_get_hdr(priv, txq_id, idx);
-                       if (!hdr) {
-                               IWL_ERR(priv,
-                                       "BUG_ON idx doesn't point to valid skb"
-                                       " idx=%d, txq_id=%d\n", idx, txq_id);
-                               return -1;
-                       }
-
-                       sc = le16_to_cpu(hdr->seq_ctrl);
-                       if (idx != (SEQ_TO_SN(sc) & 0xff)) {
-                               IWL_ERR(priv,
-                                       "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(priv, "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 |= 1ULL << sh;
-                       IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
-                                          start, (unsigned long long)bitmap);
-               }
-
-               agg->bitmap = bitmap;
-               agg->start_idx = start;
-               IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
-                                  agg->frame_count, agg->start_idx,
-                                  (unsigned long long)agg->bitmap);
-
-               if (bitmap)
-                       agg->wait_for_ba = 1;
-       }
-       return 0;
-}
-
-static u8 iwl4965_find_station(struct iwl_priv *priv, const u8 *addr)
-{
-       int i;
-       int start = 0;
-       int ret = IWL_INVALID_STATION;
-       unsigned long flags;
-
-       if ((priv->iw_mode == NL80211_IFTYPE_ADHOC))
-               start = IWL_STA_ID;
-
-       if (is_broadcast_ether_addr(addr))
-               return priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       for (i = start; i < priv->hw_params.max_stations; i++)
-               if (priv->stations[i].used &&
-                   (!compare_ether_addr(priv->stations[i].sta.sta.addr,
-                                        addr))) {
-                       ret = i;
-                       goto out;
-               }
-
-       IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n",
-                             addr, priv->num_stations);
-
- out:
-       /*
-        * It may be possible that more commands interacting with stations
-        * arrive before we completed processing the adding of
-        * station
-        */
-       if (ret != IWL_INVALID_STATION &&
-           (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) ||
-            ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) &&
-             (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) {
-               IWL_ERR(priv, "Requested station info for sta %d before ready.\n",
-                       ret);
-               ret = IWL_INVALID_STATION;
-       }
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-       return ret;
-}
-
-static int iwl4965_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
-{
-       if (priv->iw_mode == NL80211_IFTYPE_STATION) {
-               return IWL_AP_ID;
-       } else {
-               u8 *da = ieee80211_get_DA(hdr);
-               return iwl4965_find_station(priv, da);
-       }
-}
-
-/**
- * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
- */
-static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       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_hdr *hdr;
-       struct ieee80211_tx_info *info;
-       struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-       u32  status = le32_to_cpu(tx_resp->u.status);
-       int uninitialized_var(tid);
-       int sta_id;
-       int freed;
-       u8 *qc = NULL;
-       unsigned long flags;
-
-       if ((index >= txq->q.n_bd) || (iwl_legacy_queue_used(&txq->q, index) == 0)) {
-               IWL_ERR(priv, "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.write_ptr,
-                         txq->q.read_ptr);
-               return;
-       }
-
-       txq->time_stamp = jiffies;
-       info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
-       memset(&info->status, 0, sizeof(info->status));
-
-       hdr = iwl_legacy_tx_queue_get_hdr(priv, txq_id, index);
-       if (ieee80211_is_data_qos(hdr->frame_control)) {
-               qc = ieee80211_get_qos_ctl(hdr);
-               tid = qc[0] & 0xf;
-       }
-
-       sta_id = iwl4965_get_ra_sta_id(priv, hdr);
-       if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
-               IWL_ERR(priv, "Station not known\n");
-               return;
-       }
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       if (txq->sched_retry) {
-               const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
-               struct iwl_ht_agg *agg = NULL;
-               WARN_ON(!qc);
-
-               agg = &priv->stations[sta_id].tid[tid].agg;
-
-               iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
-
-               /* check if BAR is needed */
-               if ((tx_resp->frame_count == 1) && !iwl4965_is_tx_success(status))
-                       info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
-
-               if (txq->q.read_ptr != (scd_ssn & 0xff)) {
-                       index = iwl_legacy_queue_dec_wrap(scd_ssn & 0xff,
-                                                               txq->q.n_bd);
-                       IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn "
-                                          "%d index %d\n", scd_ssn , index);
-                       freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
-                       if (qc)
-                               iwl4965_free_tfds_in_queue(priv, sta_id,
-                                                      tid, freed);
-
-                       if (priv->mac80211_registered &&
-                           (iwl_legacy_queue_space(&txq->q) > txq->q.low_mark)
-                                && (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
-                               iwl_legacy_wake_queue(priv, txq);
-               }
-       } else {
-               info->status.rates[0].count = tx_resp->failure_frame + 1;
-               info->flags |= iwl4965_tx_status_to_mac80211(status);
-               iwl4965_hwrate_to_tx_control(priv,
-                                       le32_to_cpu(tx_resp->rate_n_flags),
-                                       info);
-
-               IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) "
-                                  "rate_n_flags 0x%x retries %d\n",
-                                  txq_id,
-                                  iwl4965_get_tx_fail_reason(status), status,
-                                  le32_to_cpu(tx_resp->rate_n_flags),
-                                  tx_resp->failure_frame);
-
-               freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
-               if (qc && likely(sta_id != IWL_INVALID_STATION))
-                       iwl4965_free_tfds_in_queue(priv, sta_id, tid, freed);
-               else if (sta_id == IWL_INVALID_STATION)
-                       IWL_DEBUG_TX_REPLY(priv, "Station not known\n");
-
-               if (priv->mac80211_registered &&
-                   (iwl_legacy_queue_space(&txq->q) > txq->q.low_mark))
-                       iwl_legacy_wake_queue(priv, txq);
-       }
-       if (qc && likely(sta_id != IWL_INVALID_STATION))
-               iwl4965_txq_check_empty(priv, sta_id, tid, txq_id);
-
-       iwl4965_check_abort_status(priv, tx_resp->frame_count, status);
-
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-
-static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl4965_beacon_notif *beacon = (void *)pkt->u.raw;
-       u8 rate __maybe_unused =
-               iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
-
-       IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d "
-               "tsf:0x%.8x%.8x rate:%d\n",
-               le32_to_cpu(beacon->beacon_notify_hdr.u.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);
-
-       priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
-}
-
-/* Set up 4965-specific Rx frame reply handlers */
-static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
-{
-       /* Legacy Rx frames */
-       priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx;
-       /* Tx response */
-       priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
-       priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
-}
-
-static struct iwl_hcmd_ops iwl4965_hcmd = {
-       .rxon_assoc = iwl4965_send_rxon_assoc,
-       .commit_rxon = iwl4965_commit_rxon,
-       .set_rxon_chain = iwl4965_set_rxon_chain,
-};
-
-static void iwl4965_post_scan(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       /*
-        * Since setting the RXON may have been deferred while
-        * performing the scan, fire one off if needed
-        */
-       if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
-               iwl_legacy_commit_rxon(priv, ctx);
-}
-
-static void iwl4965_post_associate(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       struct ieee80211_vif *vif = ctx->vif;
-       struct ieee80211_conf *conf = NULL;
-       int ret = 0;
-
-       if (!vif || !priv->is_open)
-               return;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       iwl_legacy_scan_cancel_timeout(priv, 200);
-
-       conf = iwl_legacy_ieee80211_get_hw_conf(priv->hw);
-
-       ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwl_legacy_commit_rxon(priv, ctx);
-
-       ret = iwl_legacy_send_rxon_timing(priv, ctx);
-       if (ret)
-               IWL_WARN(priv, "RXON timing - "
-                           "Attempting to continue.\n");
-
-       ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-
-       iwl_legacy_set_rxon_ht(priv, &priv->current_ht_config);
-
-       if (priv->cfg->ops->hcmd->set_rxon_chain)
-               priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-       ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
-
-       IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-                       vif->bss_conf.aid, vif->bss_conf.beacon_int);
-
-       if (vif->bss_conf.use_short_preamble)
-               ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-       else
-               ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-       if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-               if (vif->bss_conf.use_short_slot)
-                       ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
-               else
-                       ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-       }
-
-       iwl_legacy_commit_rxon(priv, ctx);
-
-       IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-                       vif->bss_conf.aid, ctx->active.bssid_addr);
-
-       switch (vif->type) {
-       case NL80211_IFTYPE_STATION:
-               break;
-       case NL80211_IFTYPE_ADHOC:
-               iwl4965_send_beacon_cmd(priv);
-               break;
-       default:
-               IWL_ERR(priv, "%s Should not be called in %d mode\n",
-                         __func__, vif->type);
-               break;
-       }
-
-       /* the chain noise calibration will enabled PM upon completion
-        * If chain noise has already been run, then we need to enable
-        * power management here */
-       if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
-               iwl_legacy_power_update_mode(priv, false);
-
-       /* Enable Rx differential gain and sensitivity calibrations */
-       iwl4965_chain_noise_reset(priv);
-       priv->start_calib = 1;
-}
-
-static void iwl4965_config_ap(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       struct ieee80211_vif *vif = ctx->vif;
-       int ret = 0;
-
-       lockdep_assert_held(&priv->mutex);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       /* The following should be done only at AP bring up */
-       if (!iwl_legacy_is_associated_ctx(ctx)) {
-
-               /* RXON - unassoc (to set timing command) */
-               ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwl_legacy_commit_rxon(priv, ctx);
-
-               /* RXON Timing */
-               ret = iwl_legacy_send_rxon_timing(priv, ctx);
-               if (ret)
-                       IWL_WARN(priv, "RXON timing failed - "
-                                       "Attempting to continue.\n");
-
-               /* AP has all antennas */
-               priv->chain_noise_data.active_chains =
-                       priv->hw_params.valid_rx_ant;
-               iwl_legacy_set_rxon_ht(priv, &priv->current_ht_config);
-               if (priv->cfg->ops->hcmd->set_rxon_chain)
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-               ctx->staging.assoc_id = 0;
-
-               if (vif->bss_conf.use_short_preamble)
-                       ctx->staging.flags |=
-                               RXON_FLG_SHORT_PREAMBLE_MSK;
-               else
-                       ctx->staging.flags &=
-                               ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-               if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-                       if (vif->bss_conf.use_short_slot)
-                               ctx->staging.flags |=
-                                       RXON_FLG_SHORT_SLOT_MSK;
-                       else
-                               ctx->staging.flags &=
-                                       ~RXON_FLG_SHORT_SLOT_MSK;
-               }
-               /* need to send beacon cmd before committing assoc RXON! */
-               iwl4965_send_beacon_cmd(priv);
-               /* restore RXON assoc */
-               ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-               iwl_legacy_commit_rxon(priv, ctx);
-       }
-       iwl4965_send_beacon_cmd(priv);
-}
-
-static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
-       .get_hcmd_size = iwl4965_get_hcmd_size,
-       .build_addsta_hcmd = iwl4965_build_addsta_hcmd,
-       .request_scan = iwl4965_request_scan,
-       .post_scan = iwl4965_post_scan,
-};
-
-static struct iwl_lib_ops iwl4965_lib = {
-       .set_hw_params = iwl4965_hw_set_hw_params,
-       .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
-       .txq_attach_buf_to_tfd = iwl4965_hw_txq_attach_buf_to_tfd,
-       .txq_free_tfd = iwl4965_hw_txq_free_tfd,
-       .txq_init = iwl4965_hw_tx_queue_init,
-       .rx_handler_setup = iwl4965_rx_handler_setup,
-       .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
-       .init_alive_start = iwl4965_init_alive_start,
-       .load_ucode = iwl4965_load_bsm,
-       .dump_nic_error_log = iwl4965_dump_nic_error_log,
-       .dump_fh = iwl4965_dump_fh,
-       .set_channel_switch = iwl4965_hw_channel_switch,
-       .apm_ops = {
-               .init = iwl_legacy_apm_init,
-               .config = iwl4965_nic_config,
-       },
-       .eeprom_ops = {
-               .regulatory_bands = {
-                       EEPROM_REGULATORY_BAND_1_CHANNELS,
-                       EEPROM_REGULATORY_BAND_2_CHANNELS,
-                       EEPROM_REGULATORY_BAND_3_CHANNELS,
-                       EEPROM_REGULATORY_BAND_4_CHANNELS,
-                       EEPROM_REGULATORY_BAND_5_CHANNELS,
-                       EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
-                       EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
-               },
-               .acquire_semaphore = iwl4965_eeprom_acquire_semaphore,
-               .release_semaphore = iwl4965_eeprom_release_semaphore,
-       },
-       .send_tx_power  = iwl4965_send_tx_power,
-       .update_chain_flags = iwl4965_update_chain_flags,
-       .temp_ops = {
-               .temperature = iwl4965_temperature_calib,
-       },
-       .debugfs_ops = {
-               .rx_stats_read = iwl4965_ucode_rx_stats_read,
-               .tx_stats_read = iwl4965_ucode_tx_stats_read,
-               .general_stats_read = iwl4965_ucode_general_stats_read,
-       },
-};
-
-static const struct iwl_legacy_ops iwl4965_legacy_ops = {
-       .post_associate = iwl4965_post_associate,
-       .config_ap = iwl4965_config_ap,
-       .manage_ibss_station = iwl4965_manage_ibss_station,
-       .update_bcast_stations = iwl4965_update_bcast_stations,
-};
-
-struct ieee80211_ops iwl4965_hw_ops = {
-       .tx = iwl4965_mac_tx,
-       .start = iwl4965_mac_start,
-       .stop = iwl4965_mac_stop,
-       .add_interface = iwl_legacy_mac_add_interface,
-       .remove_interface = iwl_legacy_mac_remove_interface,
-       .change_interface = iwl_legacy_mac_change_interface,
-       .config = iwl_legacy_mac_config,
-       .configure_filter = iwl4965_configure_filter,
-       .set_key = iwl4965_mac_set_key,
-       .update_tkip_key = iwl4965_mac_update_tkip_key,
-       .conf_tx = iwl_legacy_mac_conf_tx,
-       .reset_tsf = iwl_legacy_mac_reset_tsf,
-       .bss_info_changed = iwl_legacy_mac_bss_info_changed,
-       .ampdu_action = iwl4965_mac_ampdu_action,
-       .hw_scan = iwl_legacy_mac_hw_scan,
-       .sta_add = iwl4965_mac_sta_add,
-       .sta_remove = iwl_legacy_mac_sta_remove,
-       .channel_switch = iwl4965_mac_channel_switch,
-       .tx_last_beacon = iwl_legacy_mac_tx_last_beacon,
-};
-
-static const struct iwl_ops iwl4965_ops = {
-       .lib = &iwl4965_lib,
-       .hcmd = &iwl4965_hcmd,
-       .utils = &iwl4965_hcmd_utils,
-       .led = &iwl4965_led_ops,
-       .legacy = &iwl4965_legacy_ops,
-       .ieee80211_ops = &iwl4965_hw_ops,
-};
-
-static struct iwl_base_params iwl4965_base_params = {
-       .eeprom_size = IWL4965_EEPROM_IMG_SIZE,
-       .num_of_queues = IWL49_NUM_QUEUES,
-       .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
-       .pll_cfg_val = 0,
-       .set_l0s = true,
-       .use_bsm = true,
-       .led_compensation = 61,
-       .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
-       .wd_timeout = IWL_DEF_WD_TIMEOUT,
-       .temperature_kelvin = true,
-       .ucode_tracing = true,
-       .sensitivity_calib_by_driver = true,
-       .chain_noise_calib_by_driver = true,
-};
-
-struct iwl_cfg iwl4965_cfg = {
-       .name = "Intel(R) Wireless WiFi Link 4965AGN",
-       .fw_name_pre = IWL4965_FW_PRE,
-       .ucode_api_max = IWL4965_UCODE_API_MAX,
-       .ucode_api_min = IWL4965_UCODE_API_MIN,
-       .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-       .valid_tx_ant = ANT_AB,
-       .valid_rx_ant = ANT_ABC,
-       .eeprom_ver = EEPROM_4965_EEPROM_VERSION,
-       .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
-       .ops = &iwl4965_ops,
-       .mod_params = &iwl4965_mod_params,
-       .base_params = &iwl4965_base_params,
-       .led_mode = IWL_LED_BLINK,
-       /*
-        * Force use of chains B and C for scan RX on 5 GHz band
-        * because the device has off-channel reception on chain A.
-        */
-       .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
-};
-
-/* Module firmware */
-MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.h b/drivers/net/wireless/iwlegacy/iwl-4965.h
deleted file mode 100644 (file)
index 01f8163..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-/******************************************************************************
- *
- * 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) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 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_4965_h__
-#define __iwl_4965_h__
-
-#include "iwl-dev.h"
-
-/* configuration for the _4965 devices */
-extern struct iwl_cfg iwl4965_cfg;
-
-extern struct iwl_mod_params iwl4965_mod_params;
-
-extern struct ieee80211_ops iwl4965_hw_ops;
-
-/* tx queue */
-void iwl4965_free_tfds_in_queue(struct iwl_priv *priv,
-                           int sta_id, int tid, int freed);
-
-/* RXON */
-void iwl4965_set_rxon_chain(struct iwl_priv *priv,
-                               struct iwl_rxon_context *ctx);
-
-/* uCode */
-int iwl4965_verify_ucode(struct iwl_priv *priv);
-
-/* lib */
-void iwl4965_check_abort_status(struct iwl_priv *priv,
-                           u8 frame_count, u32 status);
-
-void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwl4965_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwl4965_hw_nic_init(struct iwl_priv *priv);
-int iwl4965_dump_fh(struct iwl_priv *priv, char **buf, bool display);
-
-/* rx */
-void iwl4965_rx_queue_restock(struct iwl_priv *priv);
-void iwl4965_rx_replenish(struct iwl_priv *priv);
-void iwl4965_rx_replenish_now(struct iwl_priv *priv);
-void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwl4965_rxq_stop(struct iwl_priv *priv);
-int iwl4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
-void iwl4965_rx_reply_rx(struct iwl_priv *priv,
-                    struct iwl_rx_mem_buffer *rxb);
-void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
-                        struct iwl_rx_mem_buffer *rxb);
-void iwl4965_rx_handle(struct iwl_priv *priv);
-
-/* tx */
-void iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-                                struct iwl_tx_queue *txq,
-                                dma_addr_t addr, u16 len, u8 reset, u8 pad);
-int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
-                        struct iwl_tx_queue *txq);
-void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
-                             struct ieee80211_tx_info *info);
-int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
-int iwl4965_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
-                       struct ieee80211_sta *sta, u16 tid, u16 *ssn);
-int iwl4965_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
-                      struct ieee80211_sta *sta, u16 tid);
-int iwl4965_txq_check_empty(struct iwl_priv *priv,
-                          int sta_id, u8 tid, int txq_id);
-void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb);
-int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
-void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv);
-int iwl4965_txq_ctx_alloc(struct iwl_priv *priv);
-void iwl4965_txq_ctx_reset(struct iwl_priv *priv);
-void iwl4965_txq_ctx_stop(struct iwl_priv *priv);
-void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask);
-
-/*
- * Acquire priv->lock before calling this function !
- */
-void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index);
-/**
- * iwl4965_tx_queue_set_status - (optionally) start Tx/Cmd queue
- * @tx_fifo_id: Tx DMA/FIFO channel (range 0-7) that the queue will feed
- * @scd_retry: (1) Indicates queue will be used in aggregation mode
- *
- * NOTE:  Acquire priv->lock before calling this function !
- */
-void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
-                                       struct iwl_tx_queue *txq,
-                                       int tx_fifo_id, int scd_retry);
-
-static inline u32 iwl4965_tx_status_to_mac80211(u32 status)
-{
-       status &= TX_STATUS_MSK;
-
-       switch (status) {
-       case TX_STATUS_SUCCESS:
-       case TX_STATUS_DIRECT_DONE:
-               return IEEE80211_TX_STAT_ACK;
-       case TX_STATUS_FAIL_DEST_PS:
-               return IEEE80211_TX_STAT_TX_FILTERED;
-       default:
-               return 0;
-       }
-}
-
-static inline bool iwl4965_is_tx_success(u32 status)
-{
-       status &= TX_STATUS_MSK;
-       return (status == TX_STATUS_SUCCESS) ||
-              (status == TX_STATUS_DIRECT_DONE);
-}
-
-u8 iwl4965_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
-
-/* rx */
-void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb);
-bool iwl4965_good_plcp_health(struct iwl_priv *priv,
-                         struct iwl_rx_packet *pkt);
-void iwl4965_rx_statistics(struct iwl_priv *priv,
-                      struct iwl_rx_mem_buffer *rxb);
-void iwl4965_reply_statistics(struct iwl_priv *priv,
-                         struct iwl_rx_mem_buffer *rxb);
-
-/* scan */
-int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
-
-/* station mgmt */
-int iwl4965_manage_ibss_station(struct iwl_priv *priv,
-                              struct ieee80211_vif *vif, bool add);
-
-/* hcmd */
-int iwl4965_send_beacon_cmd(struct iwl_priv *priv);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-const char *iwl4965_get_tx_fail_reason(u32 status);
-#else
-static inline const char *
-iwl4965_get_tx_fail_reason(u32 status) { return ""; }
-#endif
-
-/* station management */
-int iwl4965_alloc_bcast_station(struct iwl_priv *priv,
-                              struct iwl_rxon_context *ctx);
-int iwl4965_add_bssid_station(struct iwl_priv *priv,
-                               struct iwl_rxon_context *ctx,
-                            const u8 *addr, u8 *sta_id_r);
-int iwl4965_remove_default_wep_key(struct iwl_priv *priv,
-                              struct iwl_rxon_context *ctx,
-                              struct ieee80211_key_conf *key);
-int iwl4965_set_default_wep_key(struct iwl_priv *priv,
-                           struct iwl_rxon_context *ctx,
-                           struct ieee80211_key_conf *key);
-int iwl4965_restore_default_wep_keys(struct iwl_priv *priv,
-                                struct iwl_rxon_context *ctx);
-int iwl4965_set_dynamic_key(struct iwl_priv *priv,
-                       struct iwl_rxon_context *ctx,
-                       struct ieee80211_key_conf *key, u8 sta_id);
-int iwl4965_remove_dynamic_key(struct iwl_priv *priv,
-                       struct iwl_rxon_context *ctx,
-                       struct ieee80211_key_conf *key, u8 sta_id);
-void iwl4965_update_tkip_key(struct iwl_priv *priv,
-                        struct iwl_rxon_context *ctx,
-                        struct ieee80211_key_conf *keyconf,
-                        struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
-int iwl4965_sta_tx_modify_enable_tid(struct iwl_priv *priv,
-                       int sta_id, int tid);
-int iwl4965_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
-                        int tid, u16 ssn);
-int iwl4965_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
-                       int tid);
-void iwl4965_sta_modify_sleep_tx_count(struct iwl_priv *priv,
-                       int sta_id, int cnt);
-int iwl4965_update_bcast_stations(struct iwl_priv *priv);
-
-/* rate */
-static inline u32 iwl4965_ant_idx_to_flags(u8 ant_idx)
-{
-       return BIT(ant_idx) << RATE_MCS_ANT_POS;
-}
-
-static inline u8 iwl4965_hw_get_rate(__le32 rate_n_flags)
-{
-       return le32_to_cpu(rate_n_flags) & 0xFF;
-}
-
-static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u32 flags)
-{
-       return cpu_to_le32(flags|(u32)rate);
-}
-
-/* eeprom */
-void iwl4965_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
-int iwl4965_eeprom_acquire_semaphore(struct iwl_priv *priv);
-void iwl4965_eeprom_release_semaphore(struct iwl_priv *priv);
-int  iwl4965_eeprom_check_version(struct iwl_priv *priv);
-
-/* mac80211 handlers (for 4965) */
-void iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
-int iwl4965_mac_start(struct ieee80211_hw *hw);
-void iwl4965_mac_stop(struct ieee80211_hw *hw);
-void iwl4965_configure_filter(struct ieee80211_hw *hw,
-                            unsigned int changed_flags,
-                            unsigned int *total_flags,
-                            u64 multicast);
-int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-                      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-                      struct ieee80211_key_conf *key);
-void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif,
-                               struct ieee80211_key_conf *keyconf,
-                               struct ieee80211_sta *sta,
-                               u32 iv32, u16 *phase1key);
-int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
-                           struct ieee80211_vif *vif,
-                           enum ieee80211_ampdu_mlme_action action,
-                           struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                           u8 buf_size);
-int iwl4965_mac_sta_add(struct ieee80211_hw *hw,
-                      struct ieee80211_vif *vif,
-                      struct ieee80211_sta *sta);
-void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
-                              struct ieee80211_channel_switch *ch_switch);
-
-#endif /* __iwl_4965_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
deleted file mode 100644 (file)
index 2bd5659..0000000
+++ /dev/null
@@ -1,2661 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/etherdevice.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <net/mac80211.h>
-
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-debug.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-power.h"
-#include "iwl-sta.h"
-#include "iwl-helpers.h"
-
-
-MODULE_DESCRIPTION("iwl-legacy: common functions for 3945 and 4965");
-MODULE_VERSION(IWLWIFI_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
-MODULE_LICENSE("GPL");
-
-/*
- * set bt_coex_active to true, uCode will do kill/defer
- * every time the priority line is asserted (BT is sending signals on the
- * priority line in the PCIx).
- * set bt_coex_active to false, uCode will ignore the BT activity and
- * perform the normal operation
- *
- * User might experience transmit issue on some platform due to WiFi/BT
- * co-exist problem. The possible behaviors are:
- *   Able to scan and finding all the available AP
- *   Not able to associate with any AP
- * On those platforms, WiFi communication can be restored by set
- * "bt_coex_active" module parameter to "false"
- *
- * default: bt_coex_active = true (BT_COEX_ENABLE)
- */
-static bool bt_coex_active = true;
-module_param(bt_coex_active, bool, S_IRUGO);
-MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
-
-u32 iwlegacy_debug_level;
-EXPORT_SYMBOL(iwlegacy_debug_level);
-
-const u8 iwlegacy_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-EXPORT_SYMBOL(iwlegacy_bcast_addr);
-
-
-/* This function both allocates and initializes hw and priv. */
-struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg)
-{
-       struct iwl_priv *priv;
-       /* mac80211 allocates memory for this device instance, including
-        *   space for this driver's private structure */
-       struct ieee80211_hw *hw;
-
-       hw = ieee80211_alloc_hw(sizeof(struct iwl_priv),
-                               cfg->ops->ieee80211_ops);
-       if (hw == NULL) {
-               pr_err("%s: Can not allocate network device\n",
-                      cfg->name);
-               goto out;
-       }
-
-       priv = hw->priv;
-       priv->hw = hw;
-
-out:
-       return hw;
-}
-EXPORT_SYMBOL(iwl_legacy_alloc_all);
-
-#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
-#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
-static void iwl_legacy_init_ht_hw_capab(const struct iwl_priv *priv,
-                             struct ieee80211_sta_ht_cap *ht_info,
-                             enum ieee80211_band band)
-{
-       u16 max_bit_rate = 0;
-       u8 rx_chains_num = priv->hw_params.rx_chains_num;
-       u8 tx_chains_num = priv->hw_params.tx_chains_num;
-
-       ht_info->cap = 0;
-       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
-
-       ht_info->ht_supported = true;
-
-       ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
-       max_bit_rate = MAX_BIT_RATE_20_MHZ;
-       if (priv->hw_params.ht40_channel & BIT(band)) {
-               ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
-               ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
-               ht_info->mcs.rx_mask[4] = 0x01;
-               max_bit_rate = MAX_BIT_RATE_40_MHZ;
-       }
-
-       if (priv->cfg->mod_params->amsdu_size_8K)
-               ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
-
-       ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
-       ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
-
-       ht_info->mcs.rx_mask[0] = 0xFF;
-       if (rx_chains_num >= 2)
-               ht_info->mcs.rx_mask[1] = 0xFF;
-       if (rx_chains_num >= 3)
-               ht_info->mcs.rx_mask[2] = 0xFF;
-
-       /* Highest supported Rx data rate */
-       max_bit_rate *= rx_chains_num;
-       WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
-       ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
-
-       /* Tx MCS capabilities */
-       ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
-       if (tx_chains_num != rx_chains_num) {
-               ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
-               ht_info->mcs.tx_params |= ((tx_chains_num - 1) <<
-                               IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
-       }
-}
-
-/**
- * iwl_legacy_init_geos - Initialize mac80211's geo/channel info based from eeprom
- */
-int iwl_legacy_init_geos(struct iwl_priv *priv)
-{
-       struct iwl_channel_info *ch;
-       struct ieee80211_supported_band *sband;
-       struct ieee80211_channel *channels;
-       struct ieee80211_channel *geo_ch;
-       struct ieee80211_rate *rates;
-       int i = 0;
-       s8 max_tx_power = 0;
-
-       if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
-           priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
-               IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
-               set_bit(STATUS_GEO_CONFIGURED, &priv->status);
-               return 0;
-       }
-
-       channels = kzalloc(sizeof(struct ieee80211_channel) *
-                          priv->channel_count, GFP_KERNEL);
-       if (!channels)
-               return -ENOMEM;
-
-       rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY),
-                       GFP_KERNEL);
-       if (!rates) {
-               kfree(channels);
-               return -ENOMEM;
-       }
-
-       /* 5.2GHz channels start after the 2.4GHz channels */
-       sband = &priv->bands[IEEE80211_BAND_5GHZ];
-       sband->channels = &channels[ARRAY_SIZE(iwlegacy_eeprom_band_1)];
-       /* just OFDM */
-       sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
-       sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
-
-       if (priv->cfg->sku & IWL_SKU_N)
-               iwl_legacy_init_ht_hw_capab(priv, &sband->ht_cap,
-                                        IEEE80211_BAND_5GHZ);
-
-       sband = &priv->bands[IEEE80211_BAND_2GHZ];
-       sband->channels = channels;
-       /* OFDM & CCK */
-       sband->bitrates = rates;
-       sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
-
-       if (priv->cfg->sku & IWL_SKU_N)
-               iwl_legacy_init_ht_hw_capab(priv, &sband->ht_cap,
-                                        IEEE80211_BAND_2GHZ);
-
-       priv->ieee_channels = channels;
-       priv->ieee_rates = rates;
-
-       for (i = 0;  i < priv->channel_count; i++) {
-               ch = &priv->channel_info[i];
-
-               if (!iwl_legacy_is_channel_valid(ch))
-                       continue;
-
-               sband = &priv->bands[ch->band];
-
-               geo_ch = &sband->channels[sband->n_channels++];
-
-               geo_ch->center_freq =
-                       ieee80211_channel_to_frequency(ch->channel, ch->band);
-               geo_ch->max_power = ch->max_power_avg;
-               geo_ch->max_antenna_gain = 0xff;
-               geo_ch->hw_value = ch->channel;
-
-               if (iwl_legacy_is_channel_valid(ch)) {
-                       if (!(ch->flags & EEPROM_CHANNEL_IBSS))
-                               geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
-
-                       if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
-                               geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
-
-                       if (ch->flags & EEPROM_CHANNEL_RADAR)
-                               geo_ch->flags |= IEEE80211_CHAN_RADAR;
-
-                       geo_ch->flags |= ch->ht40_extension_channel;
-
-                       if (ch->max_power_avg > max_tx_power)
-                               max_tx_power = ch->max_power_avg;
-               } else {
-                       geo_ch->flags |= IEEE80211_CHAN_DISABLED;
-               }
-
-               IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
-                               ch->channel, geo_ch->center_freq,
-                               iwl_legacy_is_channel_a_band(ch) ?  "5.2" : "2.4",
-                               geo_ch->flags & IEEE80211_CHAN_DISABLED ?
-                               "restricted" : "valid",
-                                geo_ch->flags);
-       }
-
-       priv->tx_power_device_lmt = max_tx_power;
-       priv->tx_power_user_lmt = max_tx_power;
-       priv->tx_power_next = max_tx_power;
-
-       if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
-            priv->cfg->sku & IWL_SKU_A) {
-               IWL_INFO(priv, "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->cfg->sku &= ~IWL_SKU_A;
-       }
-
-       IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
-                  priv->bands[IEEE80211_BAND_2GHZ].n_channels,
-                  priv->bands[IEEE80211_BAND_5GHZ].n_channels);
-
-       set_bit(STATUS_GEO_CONFIGURED, &priv->status);
-
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_init_geos);
-
-/*
- * iwl_legacy_free_geos - undo allocations in iwl_legacy_init_geos
- */
-void iwl_legacy_free_geos(struct iwl_priv *priv)
-{
-       kfree(priv->ieee_channels);
-       kfree(priv->ieee_rates);
-       clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
-}
-EXPORT_SYMBOL(iwl_legacy_free_geos);
-
-static bool iwl_legacy_is_channel_extension(struct iwl_priv *priv,
-                                    enum ieee80211_band band,
-                                    u16 channel, u8 extension_chan_offset)
-{
-       const struct iwl_channel_info *ch_info;
-
-       ch_info = iwl_legacy_get_channel_info(priv, band, channel);
-       if (!iwl_legacy_is_channel_valid(ch_info))
-               return false;
-
-       if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
-               return !(ch_info->ht40_extension_channel &
-                                       IEEE80211_CHAN_NO_HT40PLUS);
-       else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
-               return !(ch_info->ht40_extension_channel &
-                                       IEEE80211_CHAN_NO_HT40MINUS);
-
-       return false;
-}
-
-bool iwl_legacy_is_ht40_tx_allowed(struct iwl_priv *priv,
-                           struct iwl_rxon_context *ctx,
-                           struct ieee80211_sta_ht_cap *ht_cap)
-{
-       if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
-               return false;
-
-       /*
-        * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
-        * the bit will not set if it is pure 40MHz case
-        */
-       if (ht_cap && !ht_cap->ht_supported)
-               return false;
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-       if (priv->disable_ht40)
-               return false;
-#endif
-
-       return iwl_legacy_is_channel_extension(priv, priv->band,
-                       le16_to_cpu(ctx->staging.channel),
-                       ctx->ht.extension_chan_offset);
-}
-EXPORT_SYMBOL(iwl_legacy_is_ht40_tx_allowed);
-
-static u16 iwl_legacy_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
-{
-       u16 new_val;
-       u16 beacon_factor;
-
-       /*
-        * If mac80211 hasn't given us a beacon interval, program
-        * the default into the device.
-        */
-       if (!beacon_val)
-               return DEFAULT_BEACON_INTERVAL;
-
-       /*
-        * If the beacon interval we obtained from the peer
-        * is too large, we'll have to wake up more often
-        * (and in IBSS case, we'll beacon too much)
-        *
-        * For example, if max_beacon_val is 4096, and the
-        * requested beacon interval is 7000, we'll have to
-        * use 3500 to be able to wake up on the beacons.
-        *
-        * This could badly influence beacon detection stats.
-        */
-
-       beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val;
-       new_val = beacon_val / beacon_factor;
-
-       if (!new_val)
-               new_val = max_beacon_val;
-
-       return new_val;
-}
-
-int
-iwl_legacy_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-       u64 tsf;
-       s32 interval_tm, rem;
-       struct ieee80211_conf *conf = NULL;
-       u16 beacon_int;
-       struct ieee80211_vif *vif = ctx->vif;
-
-       conf = iwl_legacy_ieee80211_get_hw_conf(priv->hw);
-
-       lockdep_assert_held(&priv->mutex);
-
-       memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
-
-       ctx->timing.timestamp = cpu_to_le64(priv->timestamp);
-       ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval);
-
-       beacon_int = vif ? vif->bss_conf.beacon_int : 0;
-
-       /*
-        * TODO: For IBSS we need to get atim_window from mac80211,
-        *       for now just always use 0
-        */
-       ctx->timing.atim_window = 0;
-
-       beacon_int = iwl_legacy_adjust_beacon_interval(beacon_int,
-                       priv->hw_params.max_beacon_itrvl * TIME_UNIT);
-       ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
-
-       tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
-       interval_tm = beacon_int * TIME_UNIT;
-       rem = do_div(tsf, interval_tm);
-       ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
-
-       ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1;
-
-       IWL_DEBUG_ASSOC(priv,
-                       "beacon interval %d beacon timer %d beacon tim %d\n",
-                       le16_to_cpu(ctx->timing.beacon_interval),
-                       le32_to_cpu(ctx->timing.beacon_init_val),
-                       le16_to_cpu(ctx->timing.atim_window));
-
-       return iwl_legacy_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
-                               sizeof(ctx->timing), &ctx->timing);
-}
-EXPORT_SYMBOL(iwl_legacy_send_rxon_timing);
-
-void
-iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv,
-                               struct iwl_rxon_context *ctx,
-                               int hw_decrypt)
-{
-       struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
-
-       if (hw_decrypt)
-               rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
-       else
-               rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
-
-}
-EXPORT_SYMBOL(iwl_legacy_set_rxon_hwcrypto);
-
-/* validate RXON structure is valid */
-int
-iwl_legacy_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-       struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
-       bool error = false;
-
-       if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
-               if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) {
-                       IWL_WARN(priv, "check 2.4G: wrong narrow\n");
-                       error = true;
-               }
-               if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) {
-                       IWL_WARN(priv, "check 2.4G: wrong radar\n");
-                       error = true;
-               }
-       } else {
-               if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) {
-                       IWL_WARN(priv, "check 5.2G: not short slot!\n");
-                       error = true;
-               }
-               if (rxon->flags & RXON_FLG_CCK_MSK) {
-                       IWL_WARN(priv, "check 5.2G: CCK!\n");
-                       error = true;
-               }
-       }
-       if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) {
-               IWL_WARN(priv, "mac/bssid mcast!\n");
-               error = true;
-       }
-
-       /* make sure basic rates 6Mbps and 1Mbps are supported */
-       if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 &&
-           (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) {
-               IWL_WARN(priv, "neither 1 nor 6 are basic\n");
-               error = true;
-       }
-
-       if (le16_to_cpu(rxon->assoc_id) > 2007) {
-               IWL_WARN(priv, "aid > 2007\n");
-               error = true;
-       }
-
-       if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
-                       == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) {
-               IWL_WARN(priv, "CCK and short slot\n");
-               error = true;
-       }
-
-       if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
-                       == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) {
-               IWL_WARN(priv, "CCK and auto detect");
-               error = true;
-       }
-
-       if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
-                           RXON_FLG_TGG_PROTECT_MSK)) ==
-                           RXON_FLG_TGG_PROTECT_MSK) {
-               IWL_WARN(priv, "TGg but no auto-detect\n");
-               error = true;
-       }
-
-       if (error)
-               IWL_WARN(priv, "Tuning to channel %d\n",
-                           le16_to_cpu(rxon->channel));
-
-       if (error) {
-               IWL_ERR(priv, "Invalid RXON\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_check_rxon_cmd);
-
-/**
- * iwl_legacy_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
- * @priv: staging_rxon is compared to active_rxon
- *
- * If the RXON structure is changing enough to require a new tune,
- * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
- * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
- */
-int iwl_legacy_full_rxon_required(struct iwl_priv *priv,
-                          struct iwl_rxon_context *ctx)
-{
-       const struct iwl_legacy_rxon_cmd *staging = &ctx->staging;
-       const struct iwl_legacy_rxon_cmd *active = &ctx->active;
-
-#define CHK(cond)                                                      \
-       if ((cond)) {                                                   \
-               IWL_DEBUG_INFO(priv, "need full RXON - " #cond "\n");   \
-               return 1;                                               \
-       }
-
-#define CHK_NEQ(c1, c2)                                                \
-       if ((c1) != (c2)) {                                     \
-               IWL_DEBUG_INFO(priv, "need full RXON - "        \
-                              #c1 " != " #c2 " - %d != %d\n",  \
-                              (c1), (c2));                     \
-               return 1;                                       \
-       }
-
-       /* These items are only settable from the full RXON command */
-       CHK(!iwl_legacy_is_associated_ctx(ctx));
-       CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr));
-       CHK(compare_ether_addr(staging->node_addr, active->node_addr));
-       CHK(compare_ether_addr(staging->wlap_bssid_addr,
-                               active->wlap_bssid_addr));
-       CHK_NEQ(staging->dev_type, active->dev_type);
-       CHK_NEQ(staging->channel, active->channel);
-       CHK_NEQ(staging->air_propagation, active->air_propagation);
-       CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates,
-               active->ofdm_ht_single_stream_basic_rates);
-       CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates,
-               active->ofdm_ht_dual_stream_basic_rates);
-       CHK_NEQ(staging->assoc_id, active->assoc_id);
-
-       /* 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 */
-       CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK,
-               active->flags & RXON_FLG_BAND_24G_MSK);
-
-       /* Check if we are switching association toggle */
-       CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK,
-               active->filter_flags & RXON_FILTER_ASSOC_MSK);
-
-#undef CHK
-#undef CHK_NEQ
-
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_full_rxon_required);
-
-u8 iwl_legacy_get_lowest_plcp(struct iwl_priv *priv,
-                           struct iwl_rxon_context *ctx)
-{
-       /*
-        * Assign the lowest rate -- should really get this from
-        * the beacon skb from mac80211.
-        */
-       if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
-               return IWL_RATE_1M_PLCP;
-       else
-               return IWL_RATE_6M_PLCP;
-}
-EXPORT_SYMBOL(iwl_legacy_get_lowest_plcp);
-
-static void _iwl_legacy_set_rxon_ht(struct iwl_priv *priv,
-                            struct iwl_ht_config *ht_conf,
-                            struct iwl_rxon_context *ctx)
-{
-       struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
-
-       if (!ctx->ht.enabled) {
-               rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
-                       RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
-                       RXON_FLG_HT40_PROT_MSK |
-                       RXON_FLG_HT_PROT_MSK);
-               return;
-       }
-
-       rxon->flags |= cpu_to_le32(ctx->ht.protection <<
-                                       RXON_FLG_HT_OPERATING_MODE_POS);
-
-       /* Set up channel bandwidth:
-        * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
-       /* clear the HT channel mode before set the mode */
-       rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
-                        RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
-       if (iwl_legacy_is_ht40_tx_allowed(priv, ctx, NULL)) {
-               /* pure ht40 */
-               if (ctx->ht.protection ==
-                               IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
-                       rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
-                       /* Note: control channel is opposite of extension channel */
-                       switch (ctx->ht.extension_chan_offset) {
-                       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-                               rxon->flags &=
-                                       ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
-                               break;
-                       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-                               rxon->flags |=
-                                       RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
-                               break;
-                       }
-               } else {
-                       /* Note: control channel is opposite of extension channel */
-                       switch (ctx->ht.extension_chan_offset) {
-                       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-                               rxon->flags &=
-                                       ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
-                               rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
-                               break;
-                       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-                               rxon->flags |=
-                                       RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
-                               rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
-                               break;
-                       case IEEE80211_HT_PARAM_CHA_SEC_NONE:
-                       default:
-                               /* channel location only valid if in Mixed mode */
-                               IWL_ERR(priv,
-                                       "invalid extension channel offset\n");
-                               break;
-                       }
-               }
-       } else {
-               rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
-       }
-
-       if (priv->cfg->ops->hcmd->set_rxon_chain)
-               priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-       IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
-                       "extension channel offset 0x%x\n",
-                       le32_to_cpu(rxon->flags), ctx->ht.protection,
-                       ctx->ht.extension_chan_offset);
-}
-
-void iwl_legacy_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
-{
-       struct iwl_rxon_context *ctx;
-
-       for_each_context(priv, ctx)
-               _iwl_legacy_set_rxon_ht(priv, ht_conf, ctx);
-}
-EXPORT_SYMBOL(iwl_legacy_set_rxon_ht);
-
-/* Return valid, unused, channel for a passive scan to reset the RF */
-u8 iwl_legacy_get_single_channel_number(struct iwl_priv *priv,
-                                enum ieee80211_band band)
-{
-       const struct iwl_channel_info *ch_info;
-       int i;
-       u8 channel = 0;
-       u8 min, max;
-       struct iwl_rxon_context *ctx;
-
-       if (band == IEEE80211_BAND_5GHZ) {
-               min = 14;
-               max = priv->channel_count;
-       } else {
-               min = 0;
-               max = 14;
-       }
-
-       for (i = min; i < max; i++) {
-               bool busy = false;
-
-               for_each_context(priv, ctx) {
-                       busy = priv->channel_info[i].channel ==
-                               le16_to_cpu(ctx->staging.channel);
-                       if (busy)
-                               break;
-               }
-
-               if (busy)
-                       continue;
-
-               channel = priv->channel_info[i].channel;
-               ch_info = iwl_legacy_get_channel_info(priv, band, channel);
-               if (iwl_legacy_is_channel_valid(ch_info))
-                       break;
-       }
-
-       return channel;
-}
-EXPORT_SYMBOL(iwl_legacy_get_single_channel_number);
-
-/**
- * iwl_legacy_set_rxon_channel - Set the band and channel values in staging RXON
- * @ch: requested channel as a pointer to struct ieee80211_channel
-
- * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
- * in the staging RXON flag structure based on the ch->band
- */
-int
-iwl_legacy_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
-                        struct iwl_rxon_context *ctx)
-{
-       enum ieee80211_band band = ch->band;
-       u16 channel = ch->hw_value;
-
-       if ((le16_to_cpu(ctx->staging.channel) == channel) &&
-           (priv->band == band))
-               return 0;
-
-       ctx->staging.channel = cpu_to_le16(channel);
-       if (band == IEEE80211_BAND_5GHZ)
-               ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
-       else
-               ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
-
-       priv->band = band;
-
-       IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band);
-
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_set_rxon_channel);
-
-void iwl_legacy_set_flags_for_band(struct iwl_priv *priv,
-                           struct iwl_rxon_context *ctx,
-                           enum ieee80211_band band,
-                           struct ieee80211_vif *vif)
-{
-       if (band == IEEE80211_BAND_5GHZ) {
-               ctx->staging.flags &=
-                   ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
-                     | RXON_FLG_CCK_MSK);
-               ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
-       } else {
-               /* Copied from iwl_post_associate() */
-               if (vif && vif->bss_conf.use_short_slot)
-                       ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
-               else
-                       ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-
-               ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
-               ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
-               ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_set_flags_for_band);
-
-/*
- * initialize rxon structure with default values from eeprom
- */
-void iwl_legacy_connection_init_rx_config(struct iwl_priv *priv,
-                                  struct iwl_rxon_context *ctx)
-{
-       const struct iwl_channel_info *ch_info;
-
-       memset(&ctx->staging, 0, sizeof(ctx->staging));
-
-       if (!ctx->vif) {
-               ctx->staging.dev_type = ctx->unused_devtype;
-       } else
-       switch (ctx->vif->type) {
-
-       case NL80211_IFTYPE_STATION:
-               ctx->staging.dev_type = ctx->station_devtype;
-               ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
-               break;
-
-       case NL80211_IFTYPE_ADHOC:
-               ctx->staging.dev_type = ctx->ibss_devtype;
-               ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
-               ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
-                                                 RXON_FILTER_ACCEPT_GRP_MSK;
-               break;
-
-       default:
-               IWL_ERR(priv, "Unsupported interface type %d\n",
-                       ctx->vif->type);
-               break;
-       }
-
-#if 0
-       /* TODO:  Figure out when short_preamble would be set and cache from
-        * that */
-       if (!hw_to_local(priv->hw)->short_preamble)
-               ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-       else
-               ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-#endif
-
-       ch_info = iwl_legacy_get_channel_info(priv, priv->band,
-                                      le16_to_cpu(ctx->active.channel));
-
-       if (!ch_info)
-               ch_info = &priv->channel_info[0];
-
-       ctx->staging.channel = cpu_to_le16(ch_info->channel);
-       priv->band = ch_info->band;
-
-       iwl_legacy_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
-
-       ctx->staging.ofdm_basic_rates =
-           (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
-       ctx->staging.cck_basic_rates =
-           (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
-
-       /* clear both MIX and PURE40 mode flag */
-       ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
-                                       RXON_FLG_CHANNEL_MODE_PURE_40);
-       if (ctx->vif)
-               memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
-
-       ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
-       ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
-}
-EXPORT_SYMBOL(iwl_legacy_connection_init_rx_config);
-
-void iwl_legacy_set_rate(struct iwl_priv *priv)
-{
-       const struct ieee80211_supported_band *hw = NULL;
-       struct ieee80211_rate *rate;
-       struct iwl_rxon_context *ctx;
-       int i;
-
-       hw = iwl_get_hw_mode(priv, priv->band);
-       if (!hw) {
-               IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n");
-               return;
-       }
-
-       priv->active_rate = 0;
-
-       for (i = 0; i < hw->n_bitrates; i++) {
-               rate = &(hw->bitrates[i]);
-               if (rate->hw_value < IWL_RATE_COUNT_LEGACY)
-                       priv->active_rate |= (1 << rate->hw_value);
-       }
-
-       IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate);
-
-       for_each_context(priv, ctx) {
-               ctx->staging.cck_basic_rates =
-                   (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
-
-               ctx->staging.ofdm_basic_rates =
-                  (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_set_rate);
-
-void iwl_legacy_chswitch_done(struct iwl_priv *priv, bool is_success)
-{
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
-               ieee80211_chswitch_done(ctx->vif, is_success);
-}
-EXPORT_SYMBOL(iwl_legacy_chswitch_done);
-
-void iwl_legacy_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
-
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       struct iwl_legacy_rxon_cmd *rxon = (void *)&ctx->active;
-
-       if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
-               return;
-
-       if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
-               rxon->channel = csa->channel;
-               ctx->staging.channel = csa->channel;
-               IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
-                             le16_to_cpu(csa->channel));
-               iwl_legacy_chswitch_done(priv, true);
-       } else {
-               IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
-                       le16_to_cpu(csa->channel));
-               iwl_legacy_chswitch_done(priv, false);
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_rx_csa);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
-                            struct iwl_rxon_context *ctx)
-{
-       struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
-
-       IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
-       iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
-       IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n",
-                               le16_to_cpu(rxon->channel));
-       IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
-       IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n",
-                               le32_to_cpu(rxon->filter_flags));
-       IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type);
-       IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n",
-                       rxon->ofdm_basic_rates);
-       IWL_DEBUG_RADIO(priv, "u8 cck_basic_rates: 0x%02x\n",
-                               rxon->cck_basic_rates);
-       IWL_DEBUG_RADIO(priv, "u8[6] node_addr: %pM\n", rxon->node_addr);
-       IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
-       IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n",
-                               le16_to_cpu(rxon->assoc_id));
-}
-EXPORT_SYMBOL(iwl_legacy_print_rx_config_cmd);
-#endif
-/**
- * iwl_legacy_irq_handle_error - called for HW or SW error interrupt from card
- */
-void iwl_legacy_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);
-
-       IWL_ERR(priv, "Loaded firmware version: %s\n",
-               priv->hw->wiphy->fw_version);
-
-       priv->cfg->ops->lib->dump_nic_error_log(priv);
-       if (priv->cfg->ops->lib->dump_fh)
-               priv->cfg->ops->lib->dump_fh(priv, NULL, false);
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS)
-               iwl_legacy_print_rx_config_cmd(priv,
-                                       &priv->contexts[IWL_RXON_CTX_BSS]);
-#endif
-
-       wake_up(&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(priv, IWL_DL_FW_ERRORS,
-                         "Restarting adapter due to uCode error.\n");
-
-               if (priv->cfg->mod_params->restart_fw)
-                       queue_work(priv->workqueue, &priv->restart);
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_irq_handle_error);
-
-static int iwl_legacy_apm_stop_master(struct iwl_priv *priv)
-{
-       int ret = 0;
-
-       /* stop device's busmaster DMA activity */
-       iwl_legacy_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
-
-       ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
-                       CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
-       if (ret)
-               IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n");
-
-       IWL_DEBUG_INFO(priv, "stop master\n");
-
-       return ret;
-}
-
-void iwl_legacy_apm_stop(struct iwl_priv *priv)
-{
-       IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n");
-
-       /* Stop device's DMA activity */
-       iwl_legacy_apm_stop_master(priv);
-
-       /* Reset the entire device */
-       iwl_legacy_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
-
-       udelay(10);
-
-       /*
-        * Clear "initialization complete" bit to move adapter from
-        * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
-        */
-       iwl_legacy_clear_bit(priv, CSR_GP_CNTRL,
-                               CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-}
-EXPORT_SYMBOL(iwl_legacy_apm_stop);
-
-
-/*
- * Start up NIC's basic functionality after it has been reset
- * (e.g. after platform boot, or shutdown via iwl_legacy_apm_stop())
- * NOTE:  This does not load uCode nor start the embedded processor
- */
-int iwl_legacy_apm_init(struct iwl_priv *priv)
-{
-       int ret = 0;
-       u16 lctl;
-
-       IWL_DEBUG_INFO(priv, "Init card's basic functions\n");
-
-       /*
-        * Use "set_bit" below rather than "write", to preserve any hardware
-        * bits already set by default after reset.
-        */
-
-       /* Disable L0S exit timer (platform NMI Work/Around) */
-       iwl_legacy_set_bit(priv, CSR_GIO_CHICKEN_BITS,
-                         CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
-
-       /*
-        * Disable L0s without affecting L1;
-        *  don't wait for ICH L0s (ICH bug W/A)
-        */
-       iwl_legacy_set_bit(priv, CSR_GIO_CHICKEN_BITS,
-                         CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
-
-       /* Set FH wait threshold to maximum (HW error during stress W/A) */
-       iwl_legacy_set_bit(priv, CSR_DBG_HPET_MEM_REG,
-                                       CSR_DBG_HPET_MEM_REG_VAL);
-
-       /*
-        * Enable HAP INTA (interrupt from management bus) to
-        * wake device's PCI Express link L1a -> L0s
-        * NOTE:  This is no-op for 3945 (non-existent bit)
-        */
-       iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                                   CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
-
-       /*
-        * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
-        * Check if BIOS (or OS) enabled L1-ASPM on this device.
-        * If so (likely), disable L0S, so device moves directly L0->L1;
-        *    costs negligible amount of power savings.
-        * If not (unlikely), enable L0S, so there is at least some
-        *    power savings, even without L1.
-        */
-       if (priv->cfg->base_params->set_l0s) {
-               lctl = iwl_legacy_pcie_link_ctl(priv);
-               if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
-                                       PCI_CFG_LINK_CTRL_VAL_L1_EN) {
-                       /* L1-ASPM enabled; disable(!) L0S  */
-                       iwl_legacy_set_bit(priv, CSR_GIO_REG,
-                                       CSR_GIO_REG_VAL_L0S_ENABLED);
-                       IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
-               } else {
-                       /* L1-ASPM disabled; enable(!) L0S */
-                       iwl_legacy_clear_bit(priv, CSR_GIO_REG,
-                                       CSR_GIO_REG_VAL_L0S_ENABLED);
-                       IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
-               }
-       }
-
-       /* Configure analog phase-lock-loop before activating to D0A */
-       if (priv->cfg->base_params->pll_cfg_val)
-               iwl_legacy_set_bit(priv, CSR_ANA_PLL_CFG,
-                           priv->cfg->base_params->pll_cfg_val);
-
-       /*
-        * Set "initialization complete" bit to move adapter from
-        * D0U* --> D0A* (powered-up active) state.
-        */
-       iwl_legacy_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-
-       /*
-        * Wait for clock stabilization; once stabilized, access to
-        * device-internal resources is supported, e.g. iwl_legacy_write_prph()
-        * and accesses to uCode SRAM.
-        */
-       ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
-                       CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
-                       CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
-       if (ret < 0) {
-               IWL_DEBUG_INFO(priv, "Failed to init the card\n");
-               goto out;
-       }
-
-       /*
-        * Enable DMA and BSM (if used) clocks, wait for them to stabilize.
-        * BSM (Boostrap State Machine) is only in 3945 and 4965.
-        *
-        * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
-        * do not disable clocks.  This preserves any hardware bits already
-        * set by default in "CLK_CTRL_REG" after reset.
-        */
-       if (priv->cfg->base_params->use_bsm)
-               iwl_legacy_write_prph(priv, APMG_CLK_EN_REG,
-                       APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
-       else
-               iwl_legacy_write_prph(priv, APMG_CLK_EN_REG,
-                       APMG_CLK_VAL_DMA_CLK_RQT);
-       udelay(20);
-
-       /* Disable L1-Active */
-       iwl_legacy_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
-                         APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
-
-out:
-       return ret;
-}
-EXPORT_SYMBOL(iwl_legacy_apm_init);
-
-
-int iwl_legacy_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
-{
-       int ret;
-       s8 prev_tx_power;
-       bool defer;
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       lockdep_assert_held(&priv->mutex);
-
-       if (priv->tx_power_user_lmt == tx_power && !force)
-               return 0;
-
-       if (!priv->cfg->ops->lib->send_tx_power)
-               return -EOPNOTSUPP;
-
-       /* 0 dBm mean 1 milliwatt */
-       if (tx_power < 0) {
-               IWL_WARN(priv,
-                        "Requested user TXPOWER %d below 1 mW.\n",
-                        tx_power);
-               return -EINVAL;
-       }
-
-       if (tx_power > priv->tx_power_device_lmt) {
-               IWL_WARN(priv,
-                       "Requested user TXPOWER %d above upper limit %d.\n",
-                        tx_power, priv->tx_power_device_lmt);
-               return -EINVAL;
-       }
-
-       if (!iwl_legacy_is_ready_rf(priv))
-               return -EIO;
-
-       /* scan complete and commit_rxon use tx_power_next value,
-        * it always need to be updated for newest request */
-       priv->tx_power_next = tx_power;
-
-       /* do not set tx power when scanning or channel changing */
-       defer = test_bit(STATUS_SCANNING, &priv->status) ||
-               memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
-       if (defer && !force) {
-               IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
-               return 0;
-       }
-
-       prev_tx_power = priv->tx_power_user_lmt;
-       priv->tx_power_user_lmt = tx_power;
-
-       ret = priv->cfg->ops->lib->send_tx_power(priv);
-
-       /* if fail to set tx_power, restore the orig. tx power */
-       if (ret) {
-               priv->tx_power_user_lmt = prev_tx_power;
-               priv->tx_power_next = prev_tx_power;
-       }
-       return ret;
-}
-EXPORT_SYMBOL(iwl_legacy_set_tx_power);
-
-void iwl_legacy_send_bt_config(struct iwl_priv *priv)
-{
-       struct iwl_bt_cmd bt_cmd = {
-               .lead_time = BT_LEAD_TIME_DEF,
-               .max_kill = BT_MAX_KILL_DEF,
-               .kill_ack_mask = 0,
-               .kill_cts_mask = 0,
-       };
-
-       if (!bt_coex_active)
-               bt_cmd.flags = BT_COEX_DISABLE;
-       else
-               bt_cmd.flags = BT_COEX_ENABLE;
-
-       IWL_DEBUG_INFO(priv, "BT coex %s\n",
-               (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
-
-       if (iwl_legacy_send_cmd_pdu(priv, REPLY_BT_CONFIG,
-                            sizeof(struct iwl_bt_cmd), &bt_cmd))
-               IWL_ERR(priv, "failed to send BT Coex Config\n");
-}
-EXPORT_SYMBOL(iwl_legacy_send_bt_config);
-
-int iwl_legacy_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
-{
-       struct iwl_statistics_cmd statistics_cmd = {
-               .configuration_flags =
-                       clear ? IWL_STATS_CONF_CLEAR_STATS : 0,
-       };
-
-       if (flags & CMD_ASYNC)
-               return iwl_legacy_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD,
-                                       sizeof(struct iwl_statistics_cmd),
-                                       &statistics_cmd, NULL);
-       else
-               return iwl_legacy_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
-                                       sizeof(struct iwl_statistics_cmd),
-                                       &statistics_cmd);
-}
-EXPORT_SYMBOL(iwl_legacy_send_statistics_request);
-
-void iwl_legacy_rx_pm_sleep_notif(struct iwl_priv *priv,
-                          struct iwl_rx_mem_buffer *rxb)
-{
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
-       IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
-                    sleep->pm_sleep_mode, sleep->pm_wakeup_src);
-#endif
-}
-EXPORT_SYMBOL(iwl_legacy_rx_pm_sleep_notif);
-
-void iwl_legacy_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
-                                     struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
-       IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
-                       "notification for %s:\n", len,
-                       iwl_legacy_get_cmd_string(pkt->hdr.cmd));
-       iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
-}
-EXPORT_SYMBOL(iwl_legacy_rx_pm_debug_statistics_notif);
-
-void iwl_legacy_rx_reply_error(struct iwl_priv *priv,
-                       struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-       IWL_ERR(priv, "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),
-               iwl_legacy_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));
-}
-EXPORT_SYMBOL(iwl_legacy_rx_reply_error);
-
-void iwl_legacy_clear_isr_stats(struct iwl_priv *priv)
-{
-       memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
-}
-
-int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw,
-                          struct ieee80211_vif *vif, u16 queue,
-                          const struct ieee80211_tx_queue_params *params)
-{
-       struct iwl_priv *priv = hw->priv;
-       struct iwl_rxon_context *ctx;
-       unsigned long flags;
-       int q;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (!iwl_legacy_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-               return -EIO;
-       }
-
-       if (queue >= AC_NUM) {
-               IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
-               return 0;
-       }
-
-       q = AC_NUM - 1 - queue;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       for_each_context(priv, ctx) {
-               ctx->qos_data.def_qos_parm.ac[q].cw_min =
-                       cpu_to_le16(params->cw_min);
-               ctx->qos_data.def_qos_parm.ac[q].cw_max =
-                       cpu_to_le16(params->cw_max);
-               ctx->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
-               ctx->qos_data.def_qos_parm.ac[q].edca_txop =
-                               cpu_to_le16((params->txop * 32));
-
-               ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
-       }
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_mac_conf_tx);
-
-int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw)
-{
-       struct iwl_priv *priv = hw->priv;
-
-       return priv->ibss_manager == IWL_IBSS_MANAGER;
-}
-EXPORT_SYMBOL_GPL(iwl_legacy_mac_tx_last_beacon);
-
-static int
-iwl_legacy_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-       iwl_legacy_connection_init_rx_config(priv, ctx);
-
-       if (priv->cfg->ops->hcmd->set_rxon_chain)
-               priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-       return iwl_legacy_commit_rxon(priv, ctx);
-}
-
-static int iwl_legacy_setup_interface(struct iwl_priv *priv,
-                              struct iwl_rxon_context *ctx)
-{
-       struct ieee80211_vif *vif = ctx->vif;
-       int err;
-
-       lockdep_assert_held(&priv->mutex);
-
-       /*
-        * This variable will be correct only when there's just
-        * a single context, but all code using it is for hardware
-        * that supports only one context.
-        */
-       priv->iw_mode = vif->type;
-
-       ctx->is_active = true;
-
-       err = iwl_legacy_set_mode(priv, ctx);
-       if (err) {
-               if (!ctx->always_active)
-                       ctx->is_active = false;
-               return err;
-       }
-
-       return 0;
-}
-
-int
-iwl_legacy_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-       struct iwl_priv *priv = hw->priv;
-       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-       struct iwl_rxon_context *tmp, *ctx = NULL;
-       int err;
-
-       IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
-                          vif->type, vif->addr);
-
-       mutex_lock(&priv->mutex);
-
-       if (!iwl_legacy_is_ready_rf(priv)) {
-               IWL_WARN(priv, "Try to add interface when device not ready\n");
-               err = -EINVAL;
-               goto out;
-       }
-
-       for_each_context(priv, tmp) {
-               u32 possible_modes =
-                       tmp->interface_modes | tmp->exclusive_interface_modes;
-
-               if (tmp->vif) {
-                       /* check if this busy context is exclusive */
-                       if (tmp->exclusive_interface_modes &
-                                               BIT(tmp->vif->type)) {
-                               err = -EINVAL;
-                               goto out;
-                       }
-                       continue;
-               }
-
-               if (!(possible_modes & BIT(vif->type)))
-                       continue;
-
-               /* have maybe usable context w/o interface */
-               ctx = tmp;
-               break;
-       }
-
-       if (!ctx) {
-               err = -EOPNOTSUPP;
-               goto out;
-       }
-
-       vif_priv->ctx = ctx;
-       ctx->vif = vif;
-
-       err = iwl_legacy_setup_interface(priv, ctx);
-       if (!err)
-               goto out;
-
-       ctx->vif = NULL;
-       priv->iw_mode = NL80211_IFTYPE_STATION;
- out:
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       return err;
-}
-EXPORT_SYMBOL(iwl_legacy_mac_add_interface);
-
-static void iwl_legacy_teardown_interface(struct iwl_priv *priv,
-                                  struct ieee80211_vif *vif,
-                                  bool mode_change)
-{
-       struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
-
-       lockdep_assert_held(&priv->mutex);
-
-       if (priv->scan_vif == vif) {
-               iwl_legacy_scan_cancel_timeout(priv, 200);
-               iwl_legacy_force_scan_end(priv);
-       }
-
-       if (!mode_change) {
-               iwl_legacy_set_mode(priv, ctx);
-               if (!ctx->always_active)
-                       ctx->is_active = false;
-       }
-}
-
-void iwl_legacy_mac_remove_interface(struct ieee80211_hw *hw,
-                             struct ieee80211_vif *vif)
-{
-       struct iwl_priv *priv = hw->priv;
-       struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       mutex_lock(&priv->mutex);
-
-       WARN_ON(ctx->vif != vif);
-       ctx->vif = NULL;
-
-       iwl_legacy_teardown_interface(priv, vif, false);
-
-       memset(priv->bssid, 0, ETH_ALEN);
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-}
-EXPORT_SYMBOL(iwl_legacy_mac_remove_interface);
-
-int iwl_legacy_alloc_txq_mem(struct iwl_priv *priv)
-{
-       if (!priv->txq)
-               priv->txq = kzalloc(
-                       sizeof(struct iwl_tx_queue) *
-                               priv->cfg->base_params->num_of_queues,
-                       GFP_KERNEL);
-       if (!priv->txq) {
-               IWL_ERR(priv, "Not enough memory for txq\n");
-               return -ENOMEM;
-       }
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_alloc_txq_mem);
-
-void iwl_legacy_txq_mem(struct iwl_priv *priv)
-{
-       kfree(priv->txq);
-       priv->txq = NULL;
-}
-EXPORT_SYMBOL(iwl_legacy_txq_mem);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-
-#define IWL_TRAFFIC_DUMP_SIZE  (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
-
-void iwl_legacy_reset_traffic_log(struct iwl_priv *priv)
-{
-       priv->tx_traffic_idx = 0;
-       priv->rx_traffic_idx = 0;
-       if (priv->tx_traffic)
-               memset(priv->tx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
-       if (priv->rx_traffic)
-               memset(priv->rx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
-}
-
-int iwl_legacy_alloc_traffic_mem(struct iwl_priv *priv)
-{
-       u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
-
-       if (iwlegacy_debug_level & IWL_DL_TX) {
-               if (!priv->tx_traffic) {
-                       priv->tx_traffic =
-                               kzalloc(traffic_size, GFP_KERNEL);
-                       if (!priv->tx_traffic)
-                               return -ENOMEM;
-               }
-       }
-       if (iwlegacy_debug_level & IWL_DL_RX) {
-               if (!priv->rx_traffic) {
-                       priv->rx_traffic =
-                               kzalloc(traffic_size, GFP_KERNEL);
-                       if (!priv->rx_traffic)
-                               return -ENOMEM;
-               }
-       }
-       iwl_legacy_reset_traffic_log(priv);
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_alloc_traffic_mem);
-
-void iwl_legacy_free_traffic_mem(struct iwl_priv *priv)
-{
-       kfree(priv->tx_traffic);
-       priv->tx_traffic = NULL;
-
-       kfree(priv->rx_traffic);
-       priv->rx_traffic = NULL;
-}
-EXPORT_SYMBOL(iwl_legacy_free_traffic_mem);
-
-void iwl_legacy_dbg_log_tx_data_frame(struct iwl_priv *priv,
-                     u16 length, struct ieee80211_hdr *header)
-{
-       __le16 fc;
-       u16 len;
-
-       if (likely(!(iwlegacy_debug_level & IWL_DL_TX)))
-               return;
-
-       if (!priv->tx_traffic)
-               return;
-
-       fc = header->frame_control;
-       if (ieee80211_is_data(fc)) {
-               len = (length > IWL_TRAFFIC_ENTRY_SIZE)
-                      ? IWL_TRAFFIC_ENTRY_SIZE : length;
-               memcpy((priv->tx_traffic +
-                      (priv->tx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
-                      header, len);
-               priv->tx_traffic_idx =
-                       (priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_dbg_log_tx_data_frame);
-
-void iwl_legacy_dbg_log_rx_data_frame(struct iwl_priv *priv,
-                     u16 length, struct ieee80211_hdr *header)
-{
-       __le16 fc;
-       u16 len;
-
-       if (likely(!(iwlegacy_debug_level & IWL_DL_RX)))
-               return;
-
-       if (!priv->rx_traffic)
-               return;
-
-       fc = header->frame_control;
-       if (ieee80211_is_data(fc)) {
-               len = (length > IWL_TRAFFIC_ENTRY_SIZE)
-                      ? IWL_TRAFFIC_ENTRY_SIZE : length;
-               memcpy((priv->rx_traffic +
-                      (priv->rx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
-                      header, len);
-               priv->rx_traffic_idx =
-                       (priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_dbg_log_rx_data_frame);
-
-const char *iwl_legacy_get_mgmt_string(int cmd)
-{
-       switch (cmd) {
-               IWL_CMD(MANAGEMENT_ASSOC_REQ);
-               IWL_CMD(MANAGEMENT_ASSOC_RESP);
-               IWL_CMD(MANAGEMENT_REASSOC_REQ);
-               IWL_CMD(MANAGEMENT_REASSOC_RESP);
-               IWL_CMD(MANAGEMENT_PROBE_REQ);
-               IWL_CMD(MANAGEMENT_PROBE_RESP);
-               IWL_CMD(MANAGEMENT_BEACON);
-               IWL_CMD(MANAGEMENT_ATIM);
-               IWL_CMD(MANAGEMENT_DISASSOC);
-               IWL_CMD(MANAGEMENT_AUTH);
-               IWL_CMD(MANAGEMENT_DEAUTH);
-               IWL_CMD(MANAGEMENT_ACTION);
-       default:
-               return "UNKNOWN";
-
-       }
-}
-
-const char *iwl_legacy_get_ctrl_string(int cmd)
-{
-       switch (cmd) {
-               IWL_CMD(CONTROL_BACK_REQ);
-               IWL_CMD(CONTROL_BACK);
-               IWL_CMD(CONTROL_PSPOLL);
-               IWL_CMD(CONTROL_RTS);
-               IWL_CMD(CONTROL_CTS);
-               IWL_CMD(CONTROL_ACK);
-               IWL_CMD(CONTROL_CFEND);
-               IWL_CMD(CONTROL_CFENDACK);
-       default:
-               return "UNKNOWN";
-
-       }
-}
-
-void iwl_legacy_clear_traffic_stats(struct iwl_priv *priv)
-{
-       memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
-       memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
-}
-
-/*
- * if CONFIG_IWLWIFI_LEGACY_DEBUGFS defined,
- * iwl_legacy_update_stats function will
- * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass
- * Use debugFs to display the rx/rx_statistics
- * if CONFIG_IWLWIFI_LEGACY_DEBUGFS not being defined, then no MGMT and CTRL
- * information will be recorded, but DATA pkt still will be recorded
- * for the reason of iwl_led.c need to control the led blinking based on
- * number of tx and rx data.
- *
- */
-void
-iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
-{
-       struct traffic_stats    *stats;
-
-       if (is_tx)
-               stats = &priv->tx_stats;
-       else
-               stats = &priv->rx_stats;
-
-       if (ieee80211_is_mgmt(fc)) {
-               switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
-               case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
-                       stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
-                       stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
-                       stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
-                       stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
-                       stats->mgmt[MANAGEMENT_PROBE_REQ]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
-                       stats->mgmt[MANAGEMENT_PROBE_RESP]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_BEACON):
-                       stats->mgmt[MANAGEMENT_BEACON]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_ATIM):
-                       stats->mgmt[MANAGEMENT_ATIM]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
-                       stats->mgmt[MANAGEMENT_DISASSOC]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_AUTH):
-                       stats->mgmt[MANAGEMENT_AUTH]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-                       stats->mgmt[MANAGEMENT_DEAUTH]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_ACTION):
-                       stats->mgmt[MANAGEMENT_ACTION]++;
-                       break;
-               }
-       } else if (ieee80211_is_ctl(fc)) {
-               switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
-               case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
-                       stats->ctrl[CONTROL_BACK_REQ]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_BACK):
-                       stats->ctrl[CONTROL_BACK]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
-                       stats->ctrl[CONTROL_PSPOLL]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_RTS):
-                       stats->ctrl[CONTROL_RTS]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_CTS):
-                       stats->ctrl[CONTROL_CTS]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_ACK):
-                       stats->ctrl[CONTROL_ACK]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_CFEND):
-                       stats->ctrl[CONTROL_CFEND]++;
-                       break;
-               case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
-                       stats->ctrl[CONTROL_CFENDACK]++;
-                       break;
-               }
-       } else {
-               /* data */
-               stats->data_cnt++;
-               stats->data_bytes += len;
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_update_stats);
-#endif
-
-int iwl_legacy_force_reset(struct iwl_priv *priv, bool external)
-{
-       struct iwl_force_reset *force_reset;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return -EINVAL;
-
-       force_reset = &priv->force_reset;
-       force_reset->reset_request_count++;
-       if (!external) {
-               if (force_reset->last_force_reset_jiffies &&
-                   time_after(force_reset->last_force_reset_jiffies +
-                   force_reset->reset_duration, jiffies)) {
-                       IWL_DEBUG_INFO(priv, "force reset rejected\n");
-                       force_reset->reset_reject_count++;
-                       return -EAGAIN;
-               }
-       }
-       force_reset->reset_success_count++;
-       force_reset->last_force_reset_jiffies = jiffies;
-
-       /*
-        * if the request is from external(ex: debugfs),
-        * then always perform the request in regardless the module
-        * parameter setting
-        * if the request is from internal (uCode error or driver
-        * detect failure), then fw_restart module parameter
-        * need to be check before performing firmware reload
-        */
-
-       if (!external && !priv->cfg->mod_params->restart_fw) {
-               IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
-                              "module parameter setting\n");
-               return 0;
-       }
-
-       IWL_ERR(priv, "On demand firmware reload\n");
-
-       /* Set the FW error flag -- cleared on iwl_down */
-       set_bit(STATUS_FW_ERROR, &priv->status);
-       wake_up(&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);
-       queue_work(priv->workqueue, &priv->restart);
-
-       return 0;
-}
-
-int
-iwl_legacy_mac_change_interface(struct ieee80211_hw *hw,
-                       struct ieee80211_vif *vif,
-                       enum nl80211_iftype newtype, bool newp2p)
-{
-       struct iwl_priv *priv = hw->priv;
-       struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
-       struct iwl_rxon_context *tmp;
-       u32 interface_modes;
-       int err;
-
-       newtype = ieee80211_iftype_p2p(newtype, newp2p);
-
-       mutex_lock(&priv->mutex);
-
-       if (!ctx->vif || !iwl_legacy_is_ready_rf(priv)) {
-               /*
-                * Huh? But wait ... this can maybe happen when
-                * we're in the middle of a firmware restart!
-                */
-               err = -EBUSY;
-               goto out;
-       }
-
-       interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
-
-       if (!(interface_modes & BIT(newtype))) {
-               err = -EBUSY;
-               goto out;
-       }
-
-       if (ctx->exclusive_interface_modes & BIT(newtype)) {
-               for_each_context(priv, tmp) {
-                       if (ctx == tmp)
-                               continue;
-
-                       if (!tmp->vif)
-                               continue;
-
-                       /*
-                        * The current mode switch would be exclusive, but
-                        * another context is active ... refuse the switch.
-                        */
-                       err = -EBUSY;
-                       goto out;
-               }
-       }
-
-       /* success */
-       iwl_legacy_teardown_interface(priv, vif, true);
-       vif->type = newtype;
-       vif->p2p = newp2p;
-       err = iwl_legacy_setup_interface(priv, ctx);
-       WARN_ON(err);
-       /*
-        * We've switched internally, but submitting to the
-        * device may have failed for some reason. Mask this
-        * error, because otherwise mac80211 will not switch
-        * (and set the interface type back) and we'll be
-        * out of sync with it.
-        */
-       err = 0;
-
- out:
-       mutex_unlock(&priv->mutex);
-       return err;
-}
-EXPORT_SYMBOL(iwl_legacy_mac_change_interface);
-
-/*
- * On every watchdog tick we check (latest) time stamp. If it does not
- * change during timeout period and queue is not empty we reset firmware.
- */
-static int iwl_legacy_check_stuck_queue(struct iwl_priv *priv, int cnt)
-{
-       struct iwl_tx_queue *txq = &priv->txq[cnt];
-       struct iwl_queue *q = &txq->q;
-       unsigned long timeout;
-       int ret;
-
-       if (q->read_ptr == q->write_ptr) {
-               txq->time_stamp = jiffies;
-               return 0;
-       }
-
-       timeout = txq->time_stamp +
-                 msecs_to_jiffies(priv->cfg->base_params->wd_timeout);
-
-       if (time_after(jiffies, timeout)) {
-               IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
-                               q->id, priv->cfg->base_params->wd_timeout);
-               ret = iwl_legacy_force_reset(priv, false);
-               return (ret == -EAGAIN) ? 0 : 1;
-       }
-
-       return 0;
-}
-
-/*
- * Making watchdog tick be a quarter of timeout assure we will
- * discover the queue hung between timeout and 1.25*timeout
- */
-#define IWL_WD_TICK(timeout) ((timeout) / 4)
-
-/*
- * Watchdog timer callback, we check each tx queue for stuck, if if hung
- * we reset the firmware. If everything is fine just rearm the timer.
- */
-void iwl_legacy_bg_watchdog(unsigned long data)
-{
-       struct iwl_priv *priv = (struct iwl_priv *)data;
-       int cnt;
-       unsigned long timeout;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       timeout = priv->cfg->base_params->wd_timeout;
-       if (timeout == 0)
-               return;
-
-       /* monitor and check for stuck cmd queue */
-       if (iwl_legacy_check_stuck_queue(priv, priv->cmd_queue))
-               return;
-
-       /* monitor and check for other stuck queues */
-       if (iwl_legacy_is_any_associated(priv)) {
-               for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
-                       /* skip as we already checked the command queue */
-                       if (cnt == priv->cmd_queue)
-                               continue;
-                       if (iwl_legacy_check_stuck_queue(priv, cnt))
-                               return;
-               }
-       }
-
-       mod_timer(&priv->watchdog, jiffies +
-                 msecs_to_jiffies(IWL_WD_TICK(timeout)));
-}
-EXPORT_SYMBOL(iwl_legacy_bg_watchdog);
-
-void iwl_legacy_setup_watchdog(struct iwl_priv *priv)
-{
-       unsigned int timeout = priv->cfg->base_params->wd_timeout;
-
-       if (timeout)
-               mod_timer(&priv->watchdog,
-                         jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout)));
-       else
-               del_timer(&priv->watchdog);
-}
-EXPORT_SYMBOL(iwl_legacy_setup_watchdog);
-
-/*
- * extended beacon time format
- * time in usec will be changed into a 32-bit value in extended:internal format
- * the extended part is the beacon counts
- * the internal part is the time in usec within one beacon interval
- */
-u32
-iwl_legacy_usecs_to_beacons(struct iwl_priv *priv,
-                                       u32 usec, u32 beacon_interval)
-{
-       u32 quot;
-       u32 rem;
-       u32 interval = beacon_interval * TIME_UNIT;
-
-       if (!interval || !usec)
-               return 0;
-
-       quot = (usec / interval) &
-               (iwl_legacy_beacon_time_mask_high(priv,
-               priv->hw_params.beacon_time_tsf_bits) >>
-               priv->hw_params.beacon_time_tsf_bits);
-       rem = (usec % interval) & iwl_legacy_beacon_time_mask_low(priv,
-                                  priv->hw_params.beacon_time_tsf_bits);
-
-       return (quot << priv->hw_params.beacon_time_tsf_bits) + rem;
-}
-EXPORT_SYMBOL(iwl_legacy_usecs_to_beacons);
-
-/* base is usually what we get from ucode with each received frame,
- * the same as HW timer counter counting down
- */
-__le32 iwl_legacy_add_beacon_time(struct iwl_priv *priv, u32 base,
-                          u32 addon, u32 beacon_interval)
-{
-       u32 base_low = base & iwl_legacy_beacon_time_mask_low(priv,
-                                       priv->hw_params.beacon_time_tsf_bits);
-       u32 addon_low = addon & iwl_legacy_beacon_time_mask_low(priv,
-                                       priv->hw_params.beacon_time_tsf_bits);
-       u32 interval = beacon_interval * TIME_UNIT;
-       u32 res = (base & iwl_legacy_beacon_time_mask_high(priv,
-                               priv->hw_params.beacon_time_tsf_bits)) +
-                               (addon & iwl_legacy_beacon_time_mask_high(priv,
-                               priv->hw_params.beacon_time_tsf_bits));
-
-       if (base_low > addon_low)
-               res += base_low - addon_low;
-       else if (base_low < addon_low) {
-               res += interval + base_low - addon_low;
-               res += (1 << priv->hw_params.beacon_time_tsf_bits);
-       } else
-               res += (1 << priv->hw_params.beacon_time_tsf_bits);
-
-       return cpu_to_le32(res);
-}
-EXPORT_SYMBOL(iwl_legacy_add_beacon_time);
-
-#ifdef CONFIG_PM
-
-int iwl_legacy_pci_suspend(struct device *device)
-{
-       struct pci_dev *pdev = to_pci_dev(device);
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-
-       /*
-        * This function is called when system goes into suspend state
-        * mac80211 will call iwl_mac_stop() from the mac80211 suspend function
-        * first but since iwl_mac_stop() has no knowledge of who the caller is,
-        * it will not call apm_ops.stop() to stop the DMA operation.
-        * Calling apm_ops.stop here to make sure we stop the DMA.
-        */
-       iwl_legacy_apm_stop(priv);
-
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_pci_suspend);
-
-int iwl_legacy_pci_resume(struct device *device)
-{
-       struct pci_dev *pdev = to_pci_dev(device);
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-       bool hw_rfkill = false;
-
-       /*
-        * We disable the RETRY_TIMEOUT register (0x41) to keep
-        * PCI Tx retries from interfering with C3 CPU state.
-        */
-       pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
-
-       iwl_legacy_enable_interrupts(priv);
-
-       if (!(iwl_read32(priv, CSR_GP_CNTRL) &
-                               CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
-               hw_rfkill = true;
-
-       if (hw_rfkill)
-               set_bit(STATUS_RF_KILL_HW, &priv->status);
-       else
-               clear_bit(STATUS_RF_KILL_HW, &priv->status);
-
-       wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill);
-
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_pci_resume);
-
-const struct dev_pm_ops iwl_legacy_pm_ops = {
-       .suspend = iwl_legacy_pci_suspend,
-       .resume = iwl_legacy_pci_resume,
-       .freeze = iwl_legacy_pci_suspend,
-       .thaw = iwl_legacy_pci_resume,
-       .poweroff = iwl_legacy_pci_suspend,
-       .restore = iwl_legacy_pci_resume,
-};
-EXPORT_SYMBOL(iwl_legacy_pm_ops);
-
-#endif /* CONFIG_PM */
-
-static void
-iwl_legacy_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       if (!ctx->is_active)
-               return;
-
-       ctx->qos_data.def_qos_parm.qos_flags = 0;
-
-       if (ctx->qos_data.qos_active)
-               ctx->qos_data.def_qos_parm.qos_flags |=
-                       QOS_PARAM_FLG_UPDATE_EDCA_MSK;
-
-       if (ctx->ht.enabled)
-               ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
-
-       IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
-                     ctx->qos_data.qos_active,
-                     ctx->qos_data.def_qos_parm.qos_flags);
-
-       iwl_legacy_send_cmd_pdu_async(priv, ctx->qos_cmd,
-                              sizeof(struct iwl_qosparam_cmd),
-                              &ctx->qos_data.def_qos_parm, NULL);
-}
-
-/**
- * iwl_legacy_mac_config - mac80211 config callback
- */
-int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
-{
-       struct iwl_priv *priv = hw->priv;
-       const struct iwl_channel_info *ch_info;
-       struct ieee80211_conf *conf = &hw->conf;
-       struct ieee80211_channel *channel = conf->channel;
-       struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-       struct iwl_rxon_context *ctx;
-       unsigned long flags = 0;
-       int ret = 0;
-       u16 ch;
-       int scan_active = 0;
-       bool ht_changed[NUM_IWL_RXON_CTX] = {};
-
-       if (WARN_ON(!priv->cfg->ops->legacy))
-               return -EOPNOTSUPP;
-
-       mutex_lock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
-                                       channel->hw_value, changed);
-
-       if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
-               scan_active = 1;
-               IWL_DEBUG_MAC80211(priv, "scan active\n");
-       }
-
-       if (changed & (IEEE80211_CONF_CHANGE_SMPS |
-                      IEEE80211_CONF_CHANGE_CHANNEL)) {
-               /* mac80211 uses static for non-HT which is what we want */
-               priv->current_ht_config.smps = conf->smps_mode;
-
-               /*
-                * Recalculate chain counts.
-                *
-                * If monitor mode is enabled then mac80211 will
-                * set up the SM PS mode to OFF if an HT channel is
-                * configured.
-                */
-               if (priv->cfg->ops->hcmd->set_rxon_chain)
-                       for_each_context(priv, ctx)
-                               priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-       }
-
-       /* during scanning mac80211 will delay channel setting until
-        * scan finish with changed = 0
-        */
-       if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
-               if (scan_active)
-                       goto set_ch_out;
-
-               ch = channel->hw_value;
-               ch_info = iwl_legacy_get_channel_info(priv, channel->band, ch);
-               if (!iwl_legacy_is_channel_valid(ch_info)) {
-                       IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
-                       ret = -EINVAL;
-                       goto set_ch_out;
-               }
-
-               if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
-                   !iwl_legacy_is_channel_ibss(ch_info)) {
-                       IWL_DEBUG_MAC80211(priv, "leave - not IBSS channel\n");
-                       ret = -EINVAL;
-                       goto set_ch_out;
-               }
-
-               spin_lock_irqsave(&priv->lock, flags);
-
-               for_each_context(priv, ctx) {
-                       /* Configure HT40 channels */
-                       if (ctx->ht.enabled != conf_is_ht(conf)) {
-                               ctx->ht.enabled = conf_is_ht(conf);
-                               ht_changed[ctx->ctxid] = true;
-                       }
-                       if (ctx->ht.enabled) {
-                               if (conf_is_ht40_minus(conf)) {
-                                       ctx->ht.extension_chan_offset =
-                                       IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-                                       ctx->ht.is_40mhz = true;
-                               } else if (conf_is_ht40_plus(conf)) {
-                                       ctx->ht.extension_chan_offset =
-                                       IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-                                       ctx->ht.is_40mhz = true;
-                               } else {
-                                       ctx->ht.extension_chan_offset =
-                                       IEEE80211_HT_PARAM_CHA_SEC_NONE;
-                                       ctx->ht.is_40mhz = false;
-                               }
-                       } else
-                               ctx->ht.is_40mhz = false;
-
-                       /*
-                        * Default to no protection. Protection mode will
-                        * later be set from BSS config in iwl_ht_conf
-                        */
-                       ctx->ht.protection =
-                                       IEEE80211_HT_OP_MODE_PROTECTION_NONE;
-
-                       /* if we are switching from ht to 2.4 clear flags
-                        * from any ht related info since 2.4 does not
-                        * support ht */
-                       if ((le16_to_cpu(ctx->staging.channel) != ch))
-                               ctx->staging.flags = 0;
-
-                       iwl_legacy_set_rxon_channel(priv, channel, ctx);
-                       iwl_legacy_set_rxon_ht(priv, ht_conf);
-
-                       iwl_legacy_set_flags_for_band(priv, ctx, channel->band,
-                                              ctx->vif);
-               }
-
-               spin_unlock_irqrestore(&priv->lock, flags);
-
-               if (priv->cfg->ops->legacy->update_bcast_stations)
-                       ret =
-                       priv->cfg->ops->legacy->update_bcast_stations(priv);
-
- set_ch_out:
-               /* The list of supported rates and rate mask can be different
-                * for each band; since the band may have changed, reset
-                * the rate mask to what mac80211 lists */
-               iwl_legacy_set_rate(priv);
-       }
-
-       if (changed & (IEEE80211_CONF_CHANGE_PS |
-                       IEEE80211_CONF_CHANGE_IDLE)) {
-               ret = iwl_legacy_power_update_mode(priv, false);
-               if (ret)
-                       IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
-       }
-
-       if (changed & IEEE80211_CONF_CHANGE_POWER) {
-               IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
-                       priv->tx_power_user_lmt, conf->power_level);
-
-               iwl_legacy_set_tx_power(priv, conf->power_level, false);
-       }
-
-       if (!iwl_legacy_is_ready(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-               goto out;
-       }
-
-       if (scan_active)
-               goto out;
-
-       for_each_context(priv, ctx) {
-               if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
-                       iwl_legacy_commit_rxon(priv, ctx);
-               else
-                       IWL_DEBUG_INFO(priv,
-                               "Not re-sending same RXON configuration.\n");
-               if (ht_changed[ctx->ctxid])
-                       iwl_legacy_update_qos(priv, ctx);
-       }
-
-out:
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       mutex_unlock(&priv->mutex);
-       return ret;
-}
-EXPORT_SYMBOL(iwl_legacy_mac_config);
-
-void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw,
-                             struct ieee80211_vif *vif)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-       /* IBSS can only be the IWL_RXON_CTX_BSS context */
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       if (WARN_ON(!priv->cfg->ops->legacy))
-               return;
-
-       mutex_lock(&priv->mutex);
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       spin_lock_irqsave(&priv->lock, flags);
-       memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       /* new association get rid of ibss beacon skb */
-       if (priv->beacon_skb)
-               dev_kfree_skb(priv->beacon_skb);
-
-       priv->beacon_skb = NULL;
-
-       priv->timestamp = 0;
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       iwl_legacy_scan_cancel_timeout(priv, 100);
-       if (!iwl_legacy_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-               mutex_unlock(&priv->mutex);
-               return;
-       }
-
-       /* we are restarting association process
-        * clear RXON_FILTER_ASSOC_MSK bit
-        */
-       ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwl_legacy_commit_rxon(priv, ctx);
-
-       iwl_legacy_set_rate(priv);
-
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
-
-static void iwl_legacy_ht_conf(struct iwl_priv *priv,
-                       struct ieee80211_vif *vif)
-{
-       struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-       struct ieee80211_sta *sta;
-       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-       struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
-
-       IWL_DEBUG_ASSOC(priv, "enter:\n");
-
-       if (!ctx->ht.enabled)
-               return;
-
-       ctx->ht.protection =
-               bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
-       ctx->ht.non_gf_sta_present =
-               !!(bss_conf->ht_operation_mode &
-                               IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
-
-       ht_conf->single_chain_sufficient = false;
-
-       switch (vif->type) {
-       case NL80211_IFTYPE_STATION:
-               rcu_read_lock();
-               sta = ieee80211_find_sta(vif, bss_conf->bssid);
-               if (sta) {
-                       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-                       int maxstreams;
-
-                       maxstreams = (ht_cap->mcs.tx_params &
-                             IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
-                               >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
-                       maxstreams += 1;
-
-                       if ((ht_cap->mcs.rx_mask[1] == 0) &&
-                           (ht_cap->mcs.rx_mask[2] == 0))
-                               ht_conf->single_chain_sufficient = true;
-                       if (maxstreams <= 1)
-                               ht_conf->single_chain_sufficient = true;
-               } else {
-                       /*
-                        * If at all, this can only happen through a race
-                        * when the AP disconnects us while we're still
-                        * setting up the connection, in that case mac80211
-                        * will soon tell us about that.
-                        */
-                       ht_conf->single_chain_sufficient = true;
-               }
-               rcu_read_unlock();
-               break;
-       case NL80211_IFTYPE_ADHOC:
-               ht_conf->single_chain_sufficient = true;
-               break;
-       default:
-               break;
-       }
-
-       IWL_DEBUG_ASSOC(priv, "leave\n");
-}
-
-static inline void iwl_legacy_set_no_assoc(struct iwl_priv *priv,
-                                   struct ieee80211_vif *vif)
-{
-       struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
-
-       /*
-        * inform the ucode that there is no longer an
-        * association and that no more packets should be
-        * sent
-        */
-       ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       ctx->staging.assoc_id = 0;
-       iwl_legacy_commit_rxon(priv, ctx);
-}
-
-static void iwl_legacy_beacon_update(struct ieee80211_hw *hw,
-                                 struct ieee80211_vif *vif)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-       __le64 timestamp;
-       struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
-
-       if (!skb)
-               return;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       lockdep_assert_held(&priv->mutex);
-
-       if (!priv->beacon_ctx) {
-               IWL_ERR(priv, "update beacon but no beacon context!\n");
-               dev_kfree_skb(skb);
-               return;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       if (priv->beacon_skb)
-               dev_kfree_skb(priv->beacon_skb);
-
-       priv->beacon_skb = skb;
-
-       timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
-       priv->timestamp = le64_to_cpu(timestamp);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (!iwl_legacy_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-               return;
-       }
-
-       priv->cfg->ops->legacy->post_associate(priv);
-}
-
-void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
-                                    struct ieee80211_vif *vif,
-                                    struct ieee80211_bss_conf *bss_conf,
-                                    u32 changes)
-{
-       struct iwl_priv *priv = hw->priv;
-       struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
-       int ret;
-
-       if (WARN_ON(!priv->cfg->ops->legacy))
-               return;
-
-       IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
-
-       mutex_lock(&priv->mutex);
-
-       if (!iwl_legacy_is_alive(priv)) {
-               mutex_unlock(&priv->mutex);
-               return;
-       }
-
-       if (changes & BSS_CHANGED_QOS) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&priv->lock, flags);
-               ctx->qos_data.qos_active = bss_conf->qos;
-               iwl_legacy_update_qos(priv, ctx);
-               spin_unlock_irqrestore(&priv->lock, flags);
-       }
-
-       if (changes & BSS_CHANGED_BEACON_ENABLED) {
-               /*
-                * the add_interface code must make sure we only ever
-                * have a single interface that could be beaconing at
-                * any time.
-                */
-               if (vif->bss_conf.enable_beacon)
-                       priv->beacon_ctx = ctx;
-               else
-                       priv->beacon_ctx = NULL;
-       }
-
-       if (changes & BSS_CHANGED_BSSID) {
-               IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
-
-               /*
-                * If there is currently a HW scan going on in the
-                * background then we need to cancel it else the RXON
-                * below/in post_associate will fail.
-                */
-               if (iwl_legacy_scan_cancel_timeout(priv, 100)) {
-                       IWL_WARN(priv,
-                               "Aborted scan still in progress after 100ms\n");
-                       IWL_DEBUG_MAC80211(priv,
-                               "leaving - scan abort failed.\n");
-                       mutex_unlock(&priv->mutex);
-                       return;
-               }
-
-               /* mac80211 only sets assoc when in STATION mode */
-               if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
-                       memcpy(ctx->staging.bssid_addr,
-                              bss_conf->bssid, ETH_ALEN);
-
-                       /* currently needed in a few places */
-                       memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-               } else {
-                       ctx->staging.filter_flags &=
-                               ~RXON_FILTER_ASSOC_MSK;
-               }
-
-       }
-
-       /*
-        * This needs to be after setting the BSSID in case
-        * mac80211 decides to do both changes at once because
-        * it will invoke post_associate.
-        */
-       if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
-               iwl_legacy_beacon_update(hw, vif);
-
-       if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-               IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
-                                  bss_conf->use_short_preamble);
-               if (bss_conf->use_short_preamble)
-                       ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-               else
-                       ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-       }
-
-       if (changes & BSS_CHANGED_ERP_CTS_PROT) {
-               IWL_DEBUG_MAC80211(priv,
-                       "ERP_CTS %d\n", bss_conf->use_cts_prot);
-               if (bss_conf->use_cts_prot &&
-                       (priv->band != IEEE80211_BAND_5GHZ))
-                       ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
-               else
-                       ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
-               if (bss_conf->use_cts_prot)
-                       ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
-               else
-                       ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
-       }
-
-       if (changes & BSS_CHANGED_BASIC_RATES) {
-               /* XXX use this information
-                *
-                * To do that, remove code from iwl_legacy_set_rate() and put something
-                * like this here:
-                *
-               if (A-band)
-                       ctx->staging.ofdm_basic_rates =
-                               bss_conf->basic_rates;
-               else
-                       ctx->staging.ofdm_basic_rates =
-                               bss_conf->basic_rates >> 4;
-                       ctx->staging.cck_basic_rates =
-                               bss_conf->basic_rates & 0xF;
-                */
-       }
-
-       if (changes & BSS_CHANGED_HT) {
-               iwl_legacy_ht_conf(priv, vif);
-
-               if (priv->cfg->ops->hcmd->set_rxon_chain)
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-       }
-
-       if (changes & BSS_CHANGED_ASSOC) {
-               IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
-               if (bss_conf->assoc) {
-                       priv->timestamp = bss_conf->timestamp;
-
-                       if (!iwl_legacy_is_rfkill(priv))
-                               priv->cfg->ops->legacy->post_associate(priv);
-               } else
-                       iwl_legacy_set_no_assoc(priv, vif);
-       }
-
-       if (changes && iwl_legacy_is_associated_ctx(ctx) && bss_conf->aid) {
-               IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
-                                  changes);
-               ret = iwl_legacy_send_rxon_assoc(priv, ctx);
-               if (!ret) {
-                       /* Sync active_rxon with latest change. */
-                       memcpy((void *)&ctx->active,
-                               &ctx->staging,
-                               sizeof(struct iwl_legacy_rxon_cmd));
-               }
-       }
-
-       if (changes & BSS_CHANGED_BEACON_ENABLED) {
-               if (vif->bss_conf.enable_beacon) {
-                       memcpy(ctx->staging.bssid_addr,
-                              bss_conf->bssid, ETH_ALEN);
-                       memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-                       priv->cfg->ops->legacy->config_ap(priv);
-               } else
-                       iwl_legacy_set_no_assoc(priv, vif);
-       }
-
-       if (changes & BSS_CHANGED_IBSS) {
-               ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
-                                                       bss_conf->ibss_joined);
-               if (ret)
-                       IWL_ERR(priv, "failed to %s IBSS station %pM\n",
-                               bss_conf->ibss_joined ? "add" : "remove",
-                               bss_conf->bssid);
-       }
-
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
-
-irqreturn_t iwl_legacy_isr(int irq, void *data)
-{
-       struct iwl_priv *priv = data;
-       u32 inta, inta_mask;
-       u32 inta_fh;
-       unsigned long flags;
-       if (!priv)
-               return IRQ_NONE;
-
-       spin_lock_irqsave(&priv->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);
-
-       /* 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(priv,
-                       "Ignore interrupt, inta == 0, inta_fh == 0\n");
-               goto none;
-       }
-
-       if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-               /* Hardware disappeared. It might have already raised
-                * an interrupt */
-               IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-               goto unplugged;
-       }
-
-       IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-                     inta, inta_mask, inta_fh);
-
-       inta &= ~CSR_INT_BIT_SCD;
-
-       /* iwl_irq_tasklet() will service interrupts and re-enable them */
-       if (likely(inta || inta_fh))
-               tasklet_schedule(&priv->irq_tasklet);
-
-unplugged:
-       spin_unlock_irqrestore(&priv->lock, flags);
-       return IRQ_HANDLED;
-
-none:
-       /* re-enable interrupts here since we don't have anything to service. */
-       /* only Re-enable if disabled by irq */
-       if (test_bit(STATUS_INT_ENABLED, &priv->status))
-               iwl_legacy_enable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       return IRQ_NONE;
-}
-EXPORT_SYMBOL(iwl_legacy_isr);
-
-/*
- *  iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
- *  function.
- */
-void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
-                              struct ieee80211_tx_info *info,
-                              __le16 fc, __le32 *tx_flags)
-{
-       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-               *tx_flags |= TX_CMD_FLG_RTS_MSK;
-               *tx_flags &= ~TX_CMD_FLG_CTS_MSK;
-               *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-
-               if (!ieee80211_is_mgmt(fc))
-                       return;
-
-               switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
-               case cpu_to_le16(IEEE80211_STYPE_AUTH):
-               case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-               case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
-               case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
-                       *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-                       *tx_flags |= TX_CMD_FLG_CTS_MSK;
-                       break;
-               }
-       } else if (info->control.rates[0].flags &
-                  IEEE80211_TX_RC_USE_CTS_PROTECT) {
-               *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-               *tx_flags |= TX_CMD_FLG_CTS_MSK;
-               *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h
deleted file mode 100644 (file)
index d1271fe..0000000
+++ /dev/null
@@ -1,636 +0,0 @@
-/******************************************************************************
- *
- * 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) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 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_legacy_core_h__
-#define __iwl_legacy_core_h__
-
-/************************
- * forward declarations *
- ************************/
-struct iwl_host_cmd;
-struct iwl_cmd;
-
-
-#define IWLWIFI_VERSION "in-tree:"
-#define DRV_COPYRIGHT  "Copyright(c) 2003-2011 Intel Corporation"
-#define DRV_AUTHOR     "<ilw@linux.intel.com>"
-
-#define IWL_PCI_DEVICE(dev, subdev, cfg) \
-       .vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
-       .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
-       .driver_data = (kernel_ulong_t)&(cfg)
-
-#define TIME_UNIT              1024
-
-#define IWL_SKU_G       0x1
-#define IWL_SKU_A       0x2
-#define IWL_SKU_N       0x8
-
-#define IWL_CMD(x) case x: return #x
-
-struct iwl_hcmd_ops {
-       int (*rxon_assoc)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-       int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-       void (*set_rxon_chain)(struct iwl_priv *priv,
-                              struct iwl_rxon_context *ctx);
-};
-
-struct iwl_hcmd_utils_ops {
-       u16 (*get_hcmd_size)(u8 cmd_id, u16 len);
-       u16 (*build_addsta_hcmd)(const struct iwl_legacy_addsta_cmd *cmd,
-                                                               u8 *data);
-       int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
-       void (*post_scan)(struct iwl_priv *priv);
-};
-
-struct iwl_apm_ops {
-       int (*init)(struct iwl_priv *priv);
-       void (*config)(struct iwl_priv *priv);
-};
-
-struct iwl_debugfs_ops {
-       ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf,
-                                size_t count, loff_t *ppos);
-       ssize_t (*tx_stats_read)(struct file *file, char __user *user_buf,
-                                size_t count, loff_t *ppos);
-       ssize_t (*general_stats_read)(struct file *file, char __user *user_buf,
-                                     size_t count, loff_t *ppos);
-};
-
-struct iwl_temp_ops {
-       void (*temperature)(struct iwl_priv *priv);
-};
-
-struct iwl_lib_ops {
-       /* set hw dependent parameters */
-       int (*set_hw_params)(struct iwl_priv *priv);
-       /* Handling TX */
-       void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
-                                       struct iwl_tx_queue *txq,
-                                       u16 byte_cnt);
-       int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv,
-                                    struct iwl_tx_queue *txq,
-                                    dma_addr_t addr,
-                                    u16 len, u8 reset, u8 pad);
-       void (*txq_free_tfd)(struct iwl_priv *priv,
-                            struct iwl_tx_queue *txq);
-       int (*txq_init)(struct iwl_priv *priv,
-                       struct iwl_tx_queue *txq);
-       /* setup Rx handler */
-       void (*rx_handler_setup)(struct iwl_priv *priv);
-       /* alive notification after init uCode load */
-       void (*init_alive_start)(struct iwl_priv *priv);
-       /* check validity of rtc data address */
-       int (*is_valid_rtc_data_addr)(u32 addr);
-       /* 1st ucode load */
-       int (*load_ucode)(struct iwl_priv *priv);
-
-       void (*dump_nic_error_log)(struct iwl_priv *priv);
-       int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
-       int (*set_channel_switch)(struct iwl_priv *priv,
-                                 struct ieee80211_channel_switch *ch_switch);
-       /* power management */
-       struct iwl_apm_ops apm_ops;
-
-       /* power */
-       int (*send_tx_power) (struct iwl_priv *priv);
-       void (*update_chain_flags)(struct iwl_priv *priv);
-
-       /* eeprom operations (as defined in iwl-eeprom.h) */
-       struct iwl_eeprom_ops eeprom_ops;
-
-       /* temperature */
-       struct iwl_temp_ops temp_ops;
-
-       struct iwl_debugfs_ops debugfs_ops;
-
-};
-
-struct iwl_led_ops {
-       int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd);
-};
-
-struct iwl_legacy_ops {
-       void (*post_associate)(struct iwl_priv *priv);
-       void (*config_ap)(struct iwl_priv *priv);
-       /* station management */
-       int (*update_bcast_stations)(struct iwl_priv *priv);
-       int (*manage_ibss_station)(struct iwl_priv *priv,
-                                  struct ieee80211_vif *vif, bool add);
-};
-
-struct iwl_ops {
-       const struct iwl_lib_ops *lib;
-       const struct iwl_hcmd_ops *hcmd;
-       const struct iwl_hcmd_utils_ops *utils;
-       const struct iwl_led_ops *led;
-       const struct iwl_nic_ops *nic;
-       const struct iwl_legacy_ops *legacy;
-       const struct ieee80211_ops *ieee80211_ops;
-};
-
-struct iwl_mod_params {
-       int sw_crypto;          /* def: 0 = using hardware encryption */
-       int disable_hw_scan;    /* def: 0 = use h/w scan */
-       int num_of_queues;      /* def: HW dependent */
-       int disable_11n;        /* def: 0 = 11n capabilities enabled */
-       int amsdu_size_8K;      /* def: 1 = enable 8K amsdu size */
-       int antenna;            /* def: 0 = both antennas (use diversity) */
-       int restart_fw;         /* def: 1 = restart firmware */
-};
-
-/*
- * @led_compensation: compensate on the led on/off time per HW according
- *     to the deviation to achieve the desired led frequency.
- *     The detail algorithm is described in iwl-led.c
- * @chain_noise_num_beacons: number of beacons used to compute chain noise
- * @wd_timeout: TX queues watchdog timeout
- * @temperature_kelvin: temperature report by uCode in kelvin
- * @ucode_tracing: support ucode continuous tracing
- * @sensitivity_calib_by_driver: driver has the capability to perform
- *     sensitivity calibration operation
- * @chain_noise_calib_by_driver: driver has the capability to perform
- *     chain noise calibration operation
- */
-struct iwl_base_params {
-       int eeprom_size;
-       int num_of_queues;      /* def: HW dependent */
-       int num_of_ampdu_queues;/* def: HW dependent */
-       /* for iwl_legacy_apm_init() */
-       u32 pll_cfg_val;
-       bool set_l0s;
-       bool use_bsm;
-
-       u16 led_compensation;
-       int chain_noise_num_beacons;
-       unsigned int wd_timeout;
-       bool temperature_kelvin;
-       const bool ucode_tracing;
-       const bool sensitivity_calib_by_driver;
-       const bool chain_noise_calib_by_driver;
-};
-
-/**
- * struct iwl_cfg
- * @fw_name_pre: Firmware filename prefix. The api version and extension
- *     (.ucode) will be added to filename before loading from disk. The
- *     filename is constructed as fw_name_pre<api>.ucode.
- * @ucode_api_max: Highest version of uCode API supported by driver.
- * @ucode_api_min: Lowest version of uCode API supported by driver.
- * @scan_antennas: available antenna for scan operation
- * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
- *
- * We enable the driver to be backward compatible wrt API version. The
- * driver specifies which APIs it supports (with @ucode_api_max being the
- * highest and @ucode_api_min the lowest). Firmware will only be loaded if
- * it has a supported API version. The firmware's API version will be
- * stored in @iwl_priv, enabling the driver to make runtime changes based
- * on firmware version used.
- *
- * For example,
- * if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
- *     Driver interacts with Firmware API version >= 2.
- * } else {
- *     Driver interacts with Firmware API version 1.
- * }
- *
- * The ideal usage of this infrastructure is to treat a new ucode API
- * release as a new hardware revision. That is, through utilizing the
- * iwl_hcmd_utils_ops etc. we accommodate different command structures
- * and flows between hardware versions as well as their API
- * versions.
- *
- */
-struct iwl_cfg {
-       /* params specific to an individual device within a device family */
-       const char *name;
-       const char *fw_name_pre;
-       const unsigned int ucode_api_max;
-       const unsigned int ucode_api_min;
-       u8   valid_tx_ant;
-       u8   valid_rx_ant;
-       unsigned int sku;
-       u16  eeprom_ver;
-       u16  eeprom_calib_ver;
-       const struct iwl_ops *ops;
-       /* module based parameters which can be set from modprobe cmd */
-       const struct iwl_mod_params *mod_params;
-       /* params not likely to change within a device family */
-       struct iwl_base_params *base_params;
-       /* params likely to change within a device family */
-       u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
-       enum iwl_led_mode led_mode;
-};
-
-/***************************
- *   L i b                 *
- ***************************/
-
-struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg);
-int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw,
-                   struct ieee80211_vif *vif, u16 queue,
-                   const struct ieee80211_tx_queue_params *params);
-int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw);
-void iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv,
-                       struct iwl_rxon_context *ctx,
-                       int hw_decrypt);
-int iwl_legacy_check_rxon_cmd(struct iwl_priv *priv,
-                       struct iwl_rxon_context *ctx);
-int iwl_legacy_full_rxon_required(struct iwl_priv *priv,
-                       struct iwl_rxon_context *ctx);
-int iwl_legacy_set_rxon_channel(struct iwl_priv *priv,
-                       struct ieee80211_channel *ch,
-                       struct iwl_rxon_context *ctx);
-void iwl_legacy_set_flags_for_band(struct iwl_priv *priv,
-                           struct iwl_rxon_context *ctx,
-                           enum ieee80211_band band,
-                           struct ieee80211_vif *vif);
-u8 iwl_legacy_get_single_channel_number(struct iwl_priv *priv,
-                                 enum ieee80211_band band);
-void iwl_legacy_set_rxon_ht(struct iwl_priv *priv,
-                       struct iwl_ht_config *ht_conf);
-bool iwl_legacy_is_ht40_tx_allowed(struct iwl_priv *priv,
-                           struct iwl_rxon_context *ctx,
-                           struct ieee80211_sta_ht_cap *ht_cap);
-void iwl_legacy_connection_init_rx_config(struct iwl_priv *priv,
-                                  struct iwl_rxon_context *ctx);
-void iwl_legacy_set_rate(struct iwl_priv *priv);
-int iwl_legacy_set_decrypted_flag(struct iwl_priv *priv,
-                          struct ieee80211_hdr *hdr,
-                          u32 decrypt_res,
-                          struct ieee80211_rx_status *stats);
-void iwl_legacy_irq_handle_error(struct iwl_priv *priv);
-int iwl_legacy_mac_add_interface(struct ieee80211_hw *hw,
-                         struct ieee80211_vif *vif);
-void iwl_legacy_mac_remove_interface(struct ieee80211_hw *hw,
-                             struct ieee80211_vif *vif);
-int iwl_legacy_mac_change_interface(struct ieee80211_hw *hw,
-                            struct ieee80211_vif *vif,
-                            enum nl80211_iftype newtype, bool newp2p);
-int iwl_legacy_alloc_txq_mem(struct iwl_priv *priv);
-void iwl_legacy_txq_mem(struct iwl_priv *priv);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-int iwl_legacy_alloc_traffic_mem(struct iwl_priv *priv);
-void iwl_legacy_free_traffic_mem(struct iwl_priv *priv);
-void iwl_legacy_reset_traffic_log(struct iwl_priv *priv);
-void iwl_legacy_dbg_log_tx_data_frame(struct iwl_priv *priv,
-                               u16 length, struct ieee80211_hdr *header);
-void iwl_legacy_dbg_log_rx_data_frame(struct iwl_priv *priv,
-                               u16 length, struct ieee80211_hdr *header);
-const char *iwl_legacy_get_mgmt_string(int cmd);
-const char *iwl_legacy_get_ctrl_string(int cmd);
-void iwl_legacy_clear_traffic_stats(struct iwl_priv *priv);
-void iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc,
-                     u16 len);
-#else
-static inline int iwl_legacy_alloc_traffic_mem(struct iwl_priv *priv)
-{
-       return 0;
-}
-static inline void iwl_legacy_free_traffic_mem(struct iwl_priv *priv)
-{
-}
-static inline void iwl_legacy_reset_traffic_log(struct iwl_priv *priv)
-{
-}
-static inline void iwl_legacy_dbg_log_tx_data_frame(struct iwl_priv *priv,
-                     u16 length, struct ieee80211_hdr *header)
-{
-}
-static inline void iwl_legacy_dbg_log_rx_data_frame(struct iwl_priv *priv,
-                     u16 length, struct ieee80211_hdr *header)
-{
-}
-static inline void iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx,
-                                   __le16 fc, u16 len)
-{
-}
-#endif
-/*****************************************************
- * RX handlers.
- * **************************************************/
-void iwl_legacy_rx_pm_sleep_notif(struct iwl_priv *priv,
-                          struct iwl_rx_mem_buffer *rxb);
-void iwl_legacy_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
-                                     struct iwl_rx_mem_buffer *rxb);
-void iwl_legacy_rx_reply_error(struct iwl_priv *priv,
-                       struct iwl_rx_mem_buffer *rxb);
-
-/*****************************************************
-* RX
-******************************************************/
-void iwl_legacy_cmd_queue_unmap(struct iwl_priv *priv);
-void iwl_legacy_cmd_queue_free(struct iwl_priv *priv);
-int iwl_legacy_rx_queue_alloc(struct iwl_priv *priv);
-void iwl_legacy_rx_queue_update_write_ptr(struct iwl_priv *priv,
-                                 struct iwl_rx_queue *q);
-int iwl_legacy_rx_queue_space(const struct iwl_rx_queue *q);
-void iwl_legacy_tx_cmd_complete(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb);
-/* Handlers */
-void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,
-                                         struct iwl_rx_mem_buffer *rxb);
-void iwl_legacy_recover_from_statistics(struct iwl_priv *priv,
-                               struct iwl_rx_packet *pkt);
-void iwl_legacy_chswitch_done(struct iwl_priv *priv, bool is_success);
-void iwl_legacy_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
-
-/* TX helpers */
-
-/*****************************************************
-* TX
-******************************************************/
-void iwl_legacy_txq_update_write_ptr(struct iwl_priv *priv,
-                                       struct iwl_tx_queue *txq);
-int iwl_legacy_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
-                     int slots_num, u32 txq_id);
-void iwl_legacy_tx_queue_reset(struct iwl_priv *priv,
-                       struct iwl_tx_queue *txq,
-                       int slots_num, u32 txq_id);
-void iwl_legacy_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
-void iwl_legacy_tx_queue_free(struct iwl_priv *priv, int txq_id);
-void iwl_legacy_setup_watchdog(struct iwl_priv *priv);
-/*****************************************************
- * TX power
- ****************************************************/
-int iwl_legacy_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
-
-/*******************************************************************************
- * Rate
- ******************************************************************************/
-
-u8 iwl_legacy_get_lowest_plcp(struct iwl_priv *priv,
-                           struct iwl_rxon_context *ctx);
-
-/*******************************************************************************
- * Scanning
- ******************************************************************************/
-void iwl_legacy_init_scan_params(struct iwl_priv *priv);
-int iwl_legacy_scan_cancel(struct iwl_priv *priv);
-int iwl_legacy_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
-void iwl_legacy_force_scan_end(struct iwl_priv *priv);
-int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
-                   struct ieee80211_vif *vif,
-                   struct cfg80211_scan_request *req);
-void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv);
-int iwl_legacy_force_reset(struct iwl_priv *priv, bool external);
-u16 iwl_legacy_fill_probe_req(struct iwl_priv *priv,
-                       struct ieee80211_mgmt *frame,
-                      const u8 *ta, const u8 *ie, int ie_len, int left);
-void iwl_legacy_setup_rx_scan_handlers(struct iwl_priv *priv);
-u16 iwl_legacy_get_active_dwell_time(struct iwl_priv *priv,
-                             enum ieee80211_band band,
-                             u8 n_probes);
-u16 iwl_legacy_get_passive_dwell_time(struct iwl_priv *priv,
-                              enum ieee80211_band band,
-                              struct ieee80211_vif *vif);
-void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv);
-void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv);
-
-/* 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_ACTIVE_QUIET_TIME       cpu_to_le16(10)  /* msec */
-#define IWL_PLCP_QUIET_THRESH       cpu_to_le16(1)  /* packets */
-
-#define IWL_SCAN_CHECK_WATCHDOG                (HZ * 7)
-
-/*****************************************************
- *   S e n d i n g     H o s t     C o m m a n d s   *
- *****************************************************/
-
-const char *iwl_legacy_get_cmd_string(u8 cmd);
-int __must_check iwl_legacy_send_cmd_sync(struct iwl_priv *priv,
-                                  struct iwl_host_cmd *cmd);
-int iwl_legacy_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-int __must_check iwl_legacy_send_cmd_pdu(struct iwl_priv *priv, u8 id,
-                                 u16 len, const void *data);
-int iwl_legacy_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
-                          const void *data,
-                          void (*callback)(struct iwl_priv *priv,
-                                           struct iwl_device_cmd *cmd,
-                                           struct iwl_rx_packet *pkt));
-
-int iwl_legacy_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-
-
-/*****************************************************
- * PCI                                              *
- *****************************************************/
-
-static inline u16 iwl_legacy_pcie_link_ctl(struct iwl_priv *priv)
-{
-       int pos;
-       u16 pci_lnk_ctl;
-       pos = pci_pcie_cap(priv->pci_dev);
-       pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
-       return pci_lnk_ctl;
-}
-
-void iwl_legacy_bg_watchdog(unsigned long data);
-u32 iwl_legacy_usecs_to_beacons(struct iwl_priv *priv,
-                                       u32 usec, u32 beacon_interval);
-__le32 iwl_legacy_add_beacon_time(struct iwl_priv *priv, u32 base,
-                          u32 addon, u32 beacon_interval);
-
-#ifdef CONFIG_PM
-int iwl_legacy_pci_suspend(struct device *device);
-int iwl_legacy_pci_resume(struct device *device);
-extern const struct dev_pm_ops iwl_legacy_pm_ops;
-
-#define IWL_LEGACY_PM_OPS      (&iwl_legacy_pm_ops)
-
-#else /* !CONFIG_PM */
-
-#define IWL_LEGACY_PM_OPS      NULL
-
-#endif /* !CONFIG_PM */
-
-/*****************************************************
-*  Error Handling Debugging
-******************************************************/
-void iwl4965_dump_nic_error_log(struct iwl_priv *priv);
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
-                            struct iwl_rxon_context *ctx);
-#else
-static inline void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
-                                          struct iwl_rxon_context *ctx)
-{
-}
-#endif
-
-void iwl_legacy_clear_isr_stats(struct iwl_priv *priv);
-
-/*****************************************************
-*  GEOS
-******************************************************/
-int iwl_legacy_init_geos(struct iwl_priv *priv);
-void iwl_legacy_free_geos(struct iwl_priv *priv);
-
-/*************** DRIVER STATUS FUNCTIONS   *****/
-
-#define STATUS_HCMD_ACTIVE     0       /* host command in progress */
-/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
-#define STATUS_INT_ENABLED     2
-#define STATUS_RF_KILL_HW      3
-#define STATUS_CT_KILL         4
-#define STATUS_INIT            5
-#define STATUS_ALIVE           6
-#define STATUS_READY           7
-#define STATUS_TEMPERATURE     8
-#define STATUS_GEO_CONFIGURED  9
-#define STATUS_EXIT_PENDING    10
-#define STATUS_STATISTICS      12
-#define STATUS_SCANNING                13
-#define STATUS_SCAN_ABORTING   14
-#define STATUS_SCAN_HW         15
-#define STATUS_POWER_PMI       16
-#define STATUS_FW_ERROR                17
-#define STATUS_CHANNEL_SWITCH_PENDING 18
-
-static inline int iwl_legacy_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_legacy_is_alive(struct iwl_priv *priv)
-{
-       return test_bit(STATUS_ALIVE, &priv->status);
-}
-
-static inline int iwl_legacy_is_init(struct iwl_priv *priv)
-{
-       return test_bit(STATUS_INIT, &priv->status);
-}
-
-static inline int iwl_legacy_is_rfkill_hw(struct iwl_priv *priv)
-{
-       return test_bit(STATUS_RF_KILL_HW, &priv->status);
-}
-
-static inline int iwl_legacy_is_rfkill(struct iwl_priv *priv)
-{
-       return iwl_legacy_is_rfkill_hw(priv);
-}
-
-static inline int iwl_legacy_is_ctkill(struct iwl_priv *priv)
-{
-       return test_bit(STATUS_CT_KILL, &priv->status);
-}
-
-static inline int iwl_legacy_is_ready_rf(struct iwl_priv *priv)
-{
-
-       if (iwl_legacy_is_rfkill(priv))
-               return 0;
-
-       return iwl_legacy_is_ready(priv);
-}
-
-extern void iwl_legacy_send_bt_config(struct iwl_priv *priv);
-extern int iwl_legacy_send_statistics_request(struct iwl_priv *priv,
-                                      u8 flags, bool clear);
-void iwl_legacy_apm_stop(struct iwl_priv *priv);
-int iwl_legacy_apm_init(struct iwl_priv *priv);
-
-int iwl_legacy_send_rxon_timing(struct iwl_priv *priv,
-                               struct iwl_rxon_context *ctx);
-static inline int iwl_legacy_send_rxon_assoc(struct iwl_priv *priv,
-                                     struct iwl_rxon_context *ctx)
-{
-       return priv->cfg->ops->hcmd->rxon_assoc(priv, ctx);
-}
-static inline int iwl_legacy_commit_rxon(struct iwl_priv *priv,
-                                     struct iwl_rxon_context *ctx)
-{
-       return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
-}
-static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
-                       struct iwl_priv *priv, enum ieee80211_band band)
-{
-       return priv->hw->wiphy->bands[band];
-}
-
-/* mac80211 handlers */
-int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
-void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw,
-                             struct ieee80211_vif *vif);
-void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
-                                    struct ieee80211_vif *vif,
-                                    struct ieee80211_bss_conf *bss_conf,
-                                    u32 changes);
-void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
-                               struct ieee80211_tx_info *info,
-                               __le16 fc, __le32 *tx_flags);
-
-irqreturn_t iwl_legacy_isr(int irq, void *data);
-
-#endif /* __iwl_legacy_core_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-debug.h b/drivers/net/wireless/iwlegacy/iwl-debug.h
deleted file mode 100644 (file)
index ae13112..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_legacy_debug_h__
-#define __iwl_legacy_debug_h__
-
-struct iwl_priv;
-extern u32 iwlegacy_debug_level;
-
-#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a)
-#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a)
-#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a)
-#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a)
-
-#define iwl_print_hex_error(priv, p, len)                               \
-do {                                                                   \
-       print_hex_dump(KERN_ERR, "iwl data: ",                          \
-                      DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);           \
-} while (0)
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-#define IWL_DEBUG(__priv, level, fmt, args...)                         \
-do {                                                                   \
-       if (iwl_legacy_get_debug_level(__priv) & (level))                       \
-               dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev),         \
-                        "%c %s " fmt, in_interrupt() ? 'I' : 'U',      \
-                       __func__ , ## args);                            \
-} while (0)
-
-#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)                   \
-do {                                                                   \
-       if ((iwl_legacy_get_debug_level(__priv) & (level)) && net_ratelimit())  \
-               dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev),         \
-                       "%c %s " fmt, in_interrupt() ? 'I' : 'U',       \
-                        __func__ , ## args);                           \
-} while (0)
-
-#define iwl_print_hex_dump(priv, level, p, len)                        \
-do {                                                                   \
-       if (iwl_legacy_get_debug_level(priv) & level)                           \
-               print_hex_dump(KERN_DEBUG, "iwl data: ",                \
-                              DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);   \
-} while (0)
-
-#else
-#define IWL_DEBUG(__priv, level, fmt, args...)
-#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)
-static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
-                                     const void *p, u32 len)
-{}
-#endif                         /* CONFIG_IWLWIFI_LEGACY_DEBUG */
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name);
-void iwl_legacy_dbgfs_unregister(struct iwl_priv *priv);
-#else
-static inline int
-iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
-{
-       return 0;
-}
-static inline void iwl_legacy_dbgfs_unregister(struct iwl_priv *priv)
-{
-}
-#endif                         /* CONFIG_IWLWIFI_LEGACY_DEBUGFS */
-
-/*
- * 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
- *
- * where 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.
- *
- * The active debug levels can be accessed via files
- *
- *     /sys/module/iwl4965/parameters/debug{50}
- *     /sys/module/iwl3945/parameters/debug
- *     /sys/class/net/wlan0/device/debug_level
- *
- * when CONFIG_IWLWIFI_LEGACY_DEBUG=y.
- */
-
-/* 0x0000000F - 0x00000001 */
-#define IWL_DL_INFO            (1 << 0)
-#define IWL_DL_MAC80211                (1 << 1)
-#define IWL_DL_HCMD            (1 << 2)
-#define IWL_DL_STATE           (1 << 3)
-/* 0x000000F0 - 0x00000010 */
-#define IWL_DL_MACDUMP         (1 << 4)
-#define IWL_DL_HCMD_DUMP       (1 << 5)
-#define IWL_DL_EEPROM          (1 << 6)
-#define IWL_DL_RADIO           (1 << 7)
-/* 0x00000F00 - 0x00000100 */
-#define IWL_DL_POWER           (1 << 8)
-#define IWL_DL_TEMP            (1 << 9)
-#define IWL_DL_NOTIF           (1 << 10)
-#define IWL_DL_SCAN            (1 << 11)
-/* 0x0000F000 - 0x00001000 */
-#define IWL_DL_ASSOC           (1 << 12)
-#define IWL_DL_DROP            (1 << 13)
-#define IWL_DL_TXPOWER         (1 << 14)
-#define IWL_DL_AP              (1 << 15)
-/* 0x000F0000 - 0x00010000 */
-#define IWL_DL_FW              (1 << 16)
-#define IWL_DL_RF_KILL         (1 << 17)
-#define IWL_DL_FW_ERRORS       (1 << 18)
-#define IWL_DL_LED             (1 << 19)
-/* 0x00F00000 - 0x00100000 */
-#define IWL_DL_RATE            (1 << 20)
-#define IWL_DL_CALIB           (1 << 21)
-#define IWL_DL_WEP             (1 << 22)
-#define IWL_DL_TX              (1 << 23)
-/* 0x0F000000 - 0x01000000 */
-#define IWL_DL_RX              (1 << 24)
-#define IWL_DL_ISR             (1 << 25)
-#define IWL_DL_HT              (1 << 26)
-#define IWL_DL_IO              (1 << 27)
-/* 0xF0000000 - 0x10000000 */
-#define IWL_DL_11H             (1 << 28)
-#define IWL_DL_STATS           (1 << 29)
-#define IWL_DL_TX_REPLY                (1 << 30)
-#define IWL_DL_QOS             (1 << 31)
-
-#define IWL_DEBUG_INFO(p, f, a...)     IWL_DEBUG(p, IWL_DL_INFO, f, ## a)
-#define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a)
-#define IWL_DEBUG_MACDUMP(p, f, a...)  IWL_DEBUG(p, IWL_DL_MACDUMP, f, ## a)
-#define IWL_DEBUG_TEMP(p, f, a...)     IWL_DEBUG(p, IWL_DL_TEMP, f, ## a)
-#define IWL_DEBUG_SCAN(p, f, a...)     IWL_DEBUG(p, IWL_DL_SCAN, f, ## a)
-#define IWL_DEBUG_RX(p, f, a...)       IWL_DEBUG(p, IWL_DL_RX, f, ## a)
-#define IWL_DEBUG_TX(p, f, a...)       IWL_DEBUG(p, IWL_DL_TX, f, ## a)
-#define IWL_DEBUG_ISR(p, f, a...)      IWL_DEBUG(p, IWL_DL_ISR, f, ## a)
-#define IWL_DEBUG_LED(p, f, a...)      IWL_DEBUG(p, IWL_DL_LED, f, ## a)
-#define IWL_DEBUG_WEP(p, f, a...)      IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
-#define IWL_DEBUG_HC(p, f, a...)       IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
-#define IWL_DEBUG_HC_DUMP(p, f, a...)  IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a)
-#define IWL_DEBUG_EEPROM(p, f, a...)   IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a)
-#define IWL_DEBUG_CALIB(p, f, a...)    IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
-#define IWL_DEBUG_FW(p, f, a...)       IWL_DEBUG(p, IWL_DL_FW, f, ## a)
-#define IWL_DEBUG_RF_KILL(p, f, a...)  IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
-#define IWL_DEBUG_DROP(p, f, a...)     IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
-#define IWL_DEBUG_DROP_LIMIT(p, f, a...)       \
-               IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
-#define IWL_DEBUG_AP(p, f, a...)       IWL_DEBUG(p, IWL_DL_AP, f, ## a)
-#define IWL_DEBUG_TXPOWER(p, f, a...)  IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a)
-#define IWL_DEBUG_IO(p, f, a...)       IWL_DEBUG(p, IWL_DL_IO, f, ## a)
-#define IWL_DEBUG_RATE(p, f, a...)     IWL_DEBUG(p, IWL_DL_RATE, f, ## a)
-#define IWL_DEBUG_RATE_LIMIT(p, f, a...)       \
-               IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a)
-#define IWL_DEBUG_NOTIF(p, f, a...)    IWL_DEBUG(p, IWL_DL_NOTIF, f, ## a)
-#define IWL_DEBUG_ASSOC(p, f, a...)    \
-               IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
-#define IWL_DEBUG_ASSOC_LIMIT(p, f, a...)      \
-               IWL_DEBUG_LIMIT(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
-#define IWL_DEBUG_HT(p, f, a...)       IWL_DEBUG(p, IWL_DL_HT, f, ## a)
-#define IWL_DEBUG_STATS(p, f, a...)    IWL_DEBUG(p, IWL_DL_STATS, f, ## a)
-#define IWL_DEBUG_STATS_LIMIT(p, f, a...)      \
-               IWL_DEBUG_LIMIT(p, IWL_DL_STATS, f, ## a)
-#define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a)
-#define IWL_DEBUG_TX_REPLY_LIMIT(p, f, a...) \
-               IWL_DEBUG_LIMIT(p, IWL_DL_TX_REPLY, f, ## a)
-#define IWL_DEBUG_QOS(p, f, a...)      IWL_DEBUG(p, IWL_DL_QOS, f, ## a)
-#define IWL_DEBUG_RADIO(p, f, a...)    IWL_DEBUG(p, IWL_DL_RADIO, f, ## a)
-#define IWL_DEBUG_POWER(p, f, a...)    IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
-#define IWL_DEBUG_11H(p, f, a...)      IWL_DEBUG(p, IWL_DL_11H, f, ## a)
-
-#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
deleted file mode 100644 (file)
index 1407dca..0000000
+++ /dev/null
@@ -1,1314 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-#include <linux/ieee80211.h>
-#include <linux/export.h>
-#include <net/mac80211.h>
-
-
-#include "iwl-dev.h"
-#include "iwl-debug.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-
-/* create and remove of files */
-#define DEBUGFS_ADD_FILE(name, parent, mode) do {                      \
-       if (!debugfs_create_file(#name, mode, parent, priv,             \
-                        &iwl_legacy_dbgfs_##name##_ops))               \
-               goto err;                                               \
-} while (0)
-
-#define DEBUGFS_ADD_BOOL(name, parent, ptr) do {                       \
-       struct dentry *__tmp;                                           \
-       __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR,           \
-                                   parent, ptr);                       \
-       if (IS_ERR(__tmp) || !__tmp)                                    \
-               goto err;                                               \
-} while (0)
-
-#define DEBUGFS_ADD_X32(name, parent, ptr) do {                                \
-       struct dentry *__tmp;                                           \
-       __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR,            \
-                                  parent, ptr);                        \
-       if (IS_ERR(__tmp) || !__tmp)                                    \
-               goto err;                                               \
-} while (0)
-
-/* file operation */
-#define DEBUGFS_READ_FUNC(name)                                         \
-static ssize_t iwl_legacy_dbgfs_##name##_read(struct file *file,               \
-                                       char __user *user_buf,          \
-                                       size_t count, loff_t *ppos);
-
-#define DEBUGFS_WRITE_FUNC(name)                                        \
-static ssize_t iwl_legacy_dbgfs_##name##_write(struct file *file,              \
-                                       const char __user *user_buf,    \
-                                       size_t count, loff_t *ppos);
-
-
-static int
-iwl_legacy_dbgfs_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
-#define DEBUGFS_READ_FILE_OPS(name)                            \
-       DEBUGFS_READ_FUNC(name);                                        \
-static const struct file_operations iwl_legacy_dbgfs_##name##_ops = {  \
-       .read = iwl_legacy_dbgfs_##name##_read,                         \
-       .open = iwl_legacy_dbgfs_open_file_generic,                     \
-       .llseek = generic_file_llseek,                                  \
-};
-
-#define DEBUGFS_WRITE_FILE_OPS(name)                           \
-       DEBUGFS_WRITE_FUNC(name);                                       \
-static const struct file_operations iwl_legacy_dbgfs_##name##_ops = {  \
-       .write = iwl_legacy_dbgfs_##name##_write,                       \
-       .open = iwl_legacy_dbgfs_open_file_generic,                     \
-       .llseek = generic_file_llseek,                                  \
-};
-
-#define DEBUGFS_READ_WRITE_FILE_OPS(name)                           \
-       DEBUGFS_READ_FUNC(name);                                        \
-       DEBUGFS_WRITE_FUNC(name);                                       \
-static const struct file_operations iwl_legacy_dbgfs_##name##_ops = {  \
-       .write = iwl_legacy_dbgfs_##name##_write,                       \
-       .read = iwl_legacy_dbgfs_##name##_read,                         \
-       .open = iwl_legacy_dbgfs_open_file_generic,                     \
-       .llseek = generic_file_llseek,                                  \
-};
-
-static ssize_t iwl_legacy_dbgfs_tx_statistics_read(struct file *file,
-                                               char __user *user_buf,
-                                               size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       char *buf;
-       int pos = 0;
-
-       int cnt;
-       ssize_t ret;
-       const size_t bufsz = 100 +
-               sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-       pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
-       for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
-               pos += scnprintf(buf + pos, bufsz - pos,
-                                "\t%25s\t\t: %u\n",
-                                iwl_legacy_get_mgmt_string(cnt),
-                                priv->tx_stats.mgmt[cnt]);
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
-       for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
-               pos += scnprintf(buf + pos, bufsz - pos,
-                                "\t%25s\t\t: %u\n",
-                                iwl_legacy_get_ctrl_string(cnt),
-                                priv->tx_stats.ctrl[cnt]);
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
-       pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
-                        priv->tx_stats.data_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
-                        priv->tx_stats.data_bytes);
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t
-iwl_legacy_dbgfs_clear_traffic_statistics_write(struct file *file,
-                                       const char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       u32 clear_flag;
-       char buf[8];
-       int buf_size;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%x", &clear_flag) != 1)
-               return -EFAULT;
-       iwl_legacy_clear_traffic_stats(priv);
-
-       return count;
-}
-
-static ssize_t iwl_legacy_dbgfs_rx_statistics_read(struct file *file,
-                                               char __user *user_buf,
-                                               size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       char *buf;
-       int pos = 0;
-       int cnt;
-       ssize_t ret;
-       const size_t bufsz = 100 +
-               sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
-       for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
-               pos += scnprintf(buf + pos, bufsz - pos,
-                                "\t%25s\t\t: %u\n",
-                                iwl_legacy_get_mgmt_string(cnt),
-                                priv->rx_stats.mgmt[cnt]);
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
-       for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
-               pos += scnprintf(buf + pos, bufsz - pos,
-                                "\t%25s\t\t: %u\n",
-                                iwl_legacy_get_ctrl_string(cnt),
-                                priv->rx_stats.ctrl[cnt]);
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
-       pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
-                        priv->rx_stats.data_cnt);
-       pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
-                        priv->rx_stats.data_bytes);
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-#define BYTE1_MASK 0x000000ff;
-#define BYTE2_MASK 0x0000ffff;
-#define BYTE3_MASK 0x00ffffff;
-static ssize_t iwl_legacy_dbgfs_sram_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       u32 val;
-       char *buf;
-       ssize_t ret;
-       int i;
-       int pos = 0;
-       struct iwl_priv *priv = file->private_data;
-       size_t bufsz;
-
-       /* default is to dump the entire data segment */
-       if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
-               priv->dbgfs_sram_offset = 0x800000;
-               if (priv->ucode_type == UCODE_INIT)
-                       priv->dbgfs_sram_len = priv->ucode_init_data.len;
-               else
-                       priv->dbgfs_sram_len = priv->ucode_data.len;
-       }
-       bufsz =  30 + priv->dbgfs_sram_len * sizeof(char) * 10;
-       buf = kmalloc(bufsz, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-       pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
-                       priv->dbgfs_sram_len);
-       pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
-                       priv->dbgfs_sram_offset);
-       for (i = priv->dbgfs_sram_len; i > 0; i -= 4) {
-               val = iwl_legacy_read_targ_mem(priv, priv->dbgfs_sram_offset + \
-                                       priv->dbgfs_sram_len - i);
-               if (i < 4) {
-                       switch (i) {
-                       case 1:
-                               val &= BYTE1_MASK;
-                               break;
-                       case 2:
-                               val &= BYTE2_MASK;
-                               break;
-                       case 3:
-                               val &= BYTE3_MASK;
-                               break;
-                       }
-               }
-               if (!(i % 16))
-                       pos += scnprintf(buf + pos, bufsz - pos, "\n");
-               pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "\n");
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_sram_write(struct file *file,
-                                       const char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char buf[64];
-       int buf_size;
-       u32 offset, len;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-
-       if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
-               priv->dbgfs_sram_offset = offset;
-               priv->dbgfs_sram_len = len;
-       } else {
-               priv->dbgfs_sram_offset = 0;
-               priv->dbgfs_sram_len = 0;
-       }
-
-       return count;
-}
-
-static ssize_t
-iwl_legacy_dbgfs_stations_read(struct file *file, char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       struct iwl_station_entry *station;
-       int max_sta = priv->hw_params.max_stations;
-       char *buf;
-       int i, j, pos = 0;
-       ssize_t ret;
-       /* Add 30 for initial string */
-       const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
-
-       buf = kmalloc(bufsz, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
-                       priv->num_stations);
-
-       for (i = 0; i < max_sta; i++) {
-               station = &priv->stations[i];
-               if (!station->used)
-                       continue;
-               pos += scnprintf(buf + pos, bufsz - pos,
-                                "station %d - addr: %pM, flags: %#x\n",
-                                i, station->sta.sta.addr,
-                                station->sta.station_flags_msk);
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "TID\tseq_num\ttxq_id\tframes\ttfds\t");
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "start_idx\tbitmap\t\t\trate_n_flags\n");
-
-               for (j = 0; j < MAX_TID_COUNT; j++) {
-                       pos += scnprintf(buf + pos, bufsz - pos,
-                               "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
-                               j, station->tid[j].seq_number,
-                               station->tid[j].agg.txq_id,
-                               station->tid[j].agg.frame_count,
-                               station->tid[j].tfds_in_queue,
-                               station->tid[j].agg.start_idx,
-                               station->tid[j].agg.bitmap,
-                               station->tid[j].agg.rate_n_flags);
-
-                       if (station->tid[j].agg.wait_for_ba)
-                               pos += scnprintf(buf + pos, bufsz - pos,
-                                                " - waitforba");
-                       pos += scnprintf(buf + pos, bufsz - pos, "\n");
-               }
-
-               pos += scnprintf(buf + pos, bufsz - pos, "\n");
-       }
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_nvm_read(struct file *file,
-                                      char __user *user_buf,
-                                      size_t count,
-                                      loff_t *ppos)
-{
-       ssize_t ret;
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0, ofs = 0, buf_size = 0;
-       const u8 *ptr;
-       char *buf;
-       u16 eeprom_ver;
-       size_t eeprom_len = priv->cfg->base_params->eeprom_size;
-       buf_size = 4 * eeprom_len + 256;
-
-       if (eeprom_len % 16) {
-               IWL_ERR(priv, "NVM size is not multiple of 16.\n");
-               return -ENODATA;
-       }
-
-       ptr = priv->eeprom;
-       if (!ptr) {
-               IWL_ERR(priv, "Invalid EEPROM memory\n");
-               return -ENOMEM;
-       }
-
-       /* 4 characters for byte 0xYY */
-       buf = kzalloc(buf_size, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-       eeprom_ver = iwl_legacy_eeprom_query16(priv, EEPROM_VERSION);
-       pos += scnprintf(buf + pos, buf_size - pos, "EEPROM "
-                       "version: 0x%x\n", eeprom_ver);
-       for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
-               pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
-               hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
-                                  buf_size - pos, 0);
-               pos += strlen(buf + pos);
-               if (buf_size - pos > 0)
-                       buf[pos++] = '\n';
-       }
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t
-iwl_legacy_dbgfs_channels_read(struct file *file, char __user *user_buf,
-                                      size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       struct ieee80211_channel *channels = NULL;
-       const struct ieee80211_supported_band *supp_band = NULL;
-       int pos = 0, i, bufsz = PAGE_SIZE;
-       char *buf;
-       ssize_t ret;
-
-       if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
-               return -EAGAIN;
-
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
-       if (supp_band) {
-               channels = supp_band->channels;
-
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "Displaying %d channels in 2.4GHz band 802.11bg):\n",
-                               supp_band->n_channels);
-
-               for (i = 0; i < supp_band->n_channels; i++)
-                       pos += scnprintf(buf + pos, bufsz - pos,
-                               "%d: %ddBm: BSS%s%s, %s.\n",
-                               channels[i].hw_value,
-                               channels[i].max_power,
-                               channels[i].flags & IEEE80211_CHAN_RADAR ?
-                               " (IEEE 802.11h required)" : "",
-                               ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
-                               || (channels[i].flags &
-                               IEEE80211_CHAN_RADAR)) ? "" :
-                               ", IBSS",
-                               channels[i].flags &
-                               IEEE80211_CHAN_PASSIVE_SCAN ?
-                               "passive only" : "active/passive");
-       }
-       supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
-       if (supp_band) {
-               channels = supp_band->channels;
-
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "Displaying %d channels in 5.2GHz band (802.11a)\n",
-                               supp_band->n_channels);
-
-               for (i = 0; i < supp_band->n_channels; i++)
-                       pos += scnprintf(buf + pos, bufsz - pos,
-                               "%d: %ddBm: BSS%s%s, %s.\n",
-                               channels[i].hw_value,
-                               channels[i].max_power,
-                               channels[i].flags & IEEE80211_CHAN_RADAR ?
-                               " (IEEE 802.11h required)" : "",
-                               ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
-                               || (channels[i].flags &
-                               IEEE80211_CHAN_RADAR)) ? "" :
-                               ", IBSS",
-                               channels[i].flags &
-                               IEEE80211_CHAN_PASSIVE_SCAN ?
-                               "passive only" : "active/passive");
-       }
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_status_read(struct file *file,
-                                               char __user *user_buf,
-                                               size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       char buf[512];
-       int pos = 0;
-       const size_t bufsz = sizeof(buf);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
-               test_bit(STATUS_HCMD_ACTIVE, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
-               test_bit(STATUS_INT_ENABLED, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
-               test_bit(STATUS_RF_KILL_HW, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
-               test_bit(STATUS_CT_KILL, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
-               test_bit(STATUS_INIT, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
-               test_bit(STATUS_ALIVE, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
-               test_bit(STATUS_READY, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
-               test_bit(STATUS_TEMPERATURE, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
-               test_bit(STATUS_GEO_CONFIGURED, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
-               test_bit(STATUS_EXIT_PENDING, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
-               test_bit(STATUS_STATISTICS, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
-               test_bit(STATUS_SCANNING, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
-               test_bit(STATUS_SCAN_ABORTING, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
-               test_bit(STATUS_SCAN_HW, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
-               test_bit(STATUS_POWER_PMI, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
-               test_bit(STATUS_FW_ERROR, &priv->status));
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_interrupt_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       int cnt = 0;
-       char *buf;
-       int bufsz = 24 * 64; /* 24 items * 64 char per item */
-       ssize_t ret;
-
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "Interrupt Statistics Report:\n");
-
-       pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
-               priv->isr_stats.hw);
-       pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
-               priv->isr_stats.sw);
-       if (priv->isr_stats.sw || priv->isr_stats.hw) {
-               pos += scnprintf(buf + pos, bufsz - pos,
-                       "\tLast Restarting Code:  0x%X\n",
-                       priv->isr_stats.err_code);
-       }
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
-               priv->isr_stats.sch);
-       pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
-               priv->isr_stats.alive);
-#endif
-       pos += scnprintf(buf + pos, bufsz - pos,
-               "HW RF KILL switch toggled:\t %u\n",
-               priv->isr_stats.rfkill);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
-               priv->isr_stats.ctkill);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
-               priv->isr_stats.wakeup);
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-               "Rx command responses:\t\t %u\n",
-               priv->isr_stats.rx);
-       for (cnt = 0; cnt < REPLY_MAX; cnt++) {
-               if (priv->isr_stats.rx_handlers[cnt] > 0)
-                       pos += scnprintf(buf + pos, bufsz - pos,
-                               "\tRx handler[%36s]:\t\t %u\n",
-                               iwl_legacy_get_cmd_string(cnt),
-                               priv->isr_stats.rx_handlers[cnt]);
-       }
-
-       pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
-               priv->isr_stats.tx);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
-               priv->isr_stats.unhandled);
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_interrupt_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
-       int buf_size;
-       u32 reset_flag;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%x", &reset_flag) != 1)
-               return -EFAULT;
-       if (reset_flag == 0)
-               iwl_legacy_clear_isr_stats(priv);
-
-       return count;
-}
-
-static ssize_t
-iwl_legacy_dbgfs_qos_read(struct file *file, char __user *user_buf,
-                                      size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       struct iwl_rxon_context *ctx;
-       int pos = 0, i;
-       char buf[256 * NUM_IWL_RXON_CTX];
-       const size_t bufsz = sizeof(buf);
-
-       for_each_context(priv, ctx) {
-               pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
-                                ctx->ctxid);
-               for (i = 0; i < AC_NUM; i++) {
-                       pos += scnprintf(buf + pos, bufsz - pos,
-                               "\tcw_min\tcw_max\taifsn\ttxop\n");
-                       pos += scnprintf(buf + pos, bufsz - pos,
-                               "AC[%d]\t%u\t%u\t%u\t%u\n", i,
-                               ctx->qos_data.def_qos_parm.ac[i].cw_min,
-                               ctx->qos_data.def_qos_parm.ac[i].cw_max,
-                               ctx->qos_data.def_qos_parm.ac[i].aifsn,
-                               ctx->qos_data.def_qos_parm.ac[i].edca_txop);
-               }
-               pos += scnprintf(buf + pos, bufsz - pos, "\n");
-       }
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_disable_ht40_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
-       int buf_size;
-       int ht40;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &ht40) != 1)
-               return -EFAULT;
-       if (!iwl_legacy_is_any_associated(priv))
-               priv->disable_ht40 = ht40 ? true : false;
-       else {
-               IWL_ERR(priv, "Sta associated with AP - "
-                       "Change to 40MHz channel support is not allowed\n");
-               return -EINVAL;
-       }
-
-       return count;
-}
-
-static ssize_t iwl_legacy_dbgfs_disable_ht40_read(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char buf[100];
-       int pos = 0;
-       const size_t bufsz = sizeof(buf);
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "11n 40MHz Mode: %s\n",
-                       priv->disable_ht40 ? "Disabled" : "Enabled");
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-DEBUGFS_READ_WRITE_FILE_OPS(sram);
-DEBUGFS_READ_FILE_OPS(nvm);
-DEBUGFS_READ_FILE_OPS(stations);
-DEBUGFS_READ_FILE_OPS(channels);
-DEBUGFS_READ_FILE_OPS(status);
-DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
-DEBUGFS_READ_FILE_OPS(qos);
-DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
-
-static ssize_t iwl_legacy_dbgfs_traffic_log_read(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0, ofs = 0;
-       int cnt = 0, entry;
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-       struct iwl_rx_queue *rxq = &priv->rxq;
-       char *buf;
-       int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
-               (priv->cfg->base_params->num_of_queues * 32 * 8) + 400;
-       const u8 *ptr;
-       ssize_t ret;
-
-       if (!priv->txq) {
-               IWL_ERR(priv, "txq not ready\n");
-               return -EAGAIN;
-       }
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate buffer\n");
-               return -ENOMEM;
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
-       for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
-               txq = &priv->txq[cnt];
-               q = &txq->q;
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "q[%d]: read_ptr: %u, write_ptr: %u\n",
-                               cnt, q->read_ptr, q->write_ptr);
-       }
-       if (priv->tx_traffic && (iwlegacy_debug_level & IWL_DL_TX)) {
-               ptr = priv->tx_traffic;
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
-               for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
-                       for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
-                            entry++,  ofs += 16) {
-                               pos += scnprintf(buf + pos, bufsz - pos,
-                                               "0x%.4x ", ofs);
-                               hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
-                                                  buf + pos, bufsz - pos, 0);
-                               pos += strlen(buf + pos);
-                               if (bufsz - pos > 0)
-                                       buf[pos++] = '\n';
-                       }
-               }
-       }
-
-       pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "read: %u, write: %u\n",
-                        rxq->read, rxq->write);
-
-       if (priv->rx_traffic && (iwlegacy_debug_level & IWL_DL_RX)) {
-               ptr = priv->rx_traffic;
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
-               for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
-                       for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
-                            entry++,  ofs += 16) {
-                               pos += scnprintf(buf + pos, bufsz - pos,
-                                               "0x%.4x ", ofs);
-                               hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
-                                                  buf + pos, bufsz - pos, 0);
-                               pos += strlen(buf + pos);
-                               if (bufsz - pos > 0)
-                                       buf[pos++] = '\n';
-                       }
-               }
-       }
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_traffic_log_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
-       int buf_size;
-       int traffic_log;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &traffic_log) != 1)
-               return -EFAULT;
-       if (traffic_log == 0)
-               iwl_legacy_reset_traffic_log(priv);
-
-       return count;
-}
-
-static ssize_t iwl_legacy_dbgfs_tx_queue_read(struct file *file,
-                                               char __user *user_buf,
-                                               size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-       char *buf;
-       int pos = 0;
-       int cnt;
-       int ret;
-       const size_t bufsz = sizeof(char) * 64 *
-                               priv->cfg->base_params->num_of_queues;
-
-       if (!priv->txq) {
-               IWL_ERR(priv, "txq not ready\n");
-               return -EAGAIN;
-       }
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
-               txq = &priv->txq[cnt];
-               q = &txq->q;
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "hwq %.2d: read=%u write=%u stop=%d"
-                               " swq_id=%#.2x (ac %d/hwq %d)\n",
-                               cnt, q->read_ptr, q->write_ptr,
-                               !!test_bit(cnt, priv->queue_stopped),
-                               txq->swq_id, txq->swq_id & 3,
-                               (txq->swq_id >> 2) & 0x1f);
-               if (cnt >= 4)
-                       continue;
-               /* for the ACs, display the stop count too */
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "        stop-count: %d\n",
-                               atomic_read(&priv->queue_stop_count[cnt]));
-       }
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_rx_queue_read(struct file *file,
-                                               char __user *user_buf,
-                                               size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       struct iwl_rx_queue *rxq = &priv->rxq;
-       char buf[256];
-       int pos = 0;
-       const size_t bufsz = sizeof(buf);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
-                                               rxq->read);
-       pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
-                                               rxq->write);
-       pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
-                                               rxq->free_count);
-       if (rxq->rb_stts) {
-               pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
-                        le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
-       } else {
-               pos += scnprintf(buf + pos, bufsz - pos,
-                                       "closed_rb_num: Not Allocated\n");
-       }
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_ucode_rx_stats_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
-                       user_buf, count, ppos);
-}
-
-static ssize_t iwl_legacy_dbgfs_ucode_tx_stats_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
-                       user_buf, count, ppos);
-}
-
-static ssize_t iwl_legacy_dbgfs_ucode_general_stats_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file,
-                       user_buf, count, ppos);
-}
-
-static ssize_t iwl_legacy_dbgfs_sensitivity_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       int cnt = 0;
-       char *buf;
-       int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
-       ssize_t ret;
-       struct iwl_sensitivity_data *data;
-
-       data = &priv->sensitivity_data;
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
-                       data->auto_corr_ofdm);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "auto_corr_ofdm_mrc:\t\t %u\n",
-                       data->auto_corr_ofdm_mrc);
-       pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
-                       data->auto_corr_ofdm_x1);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "auto_corr_ofdm_mrc_x1:\t\t %u\n",
-                       data->auto_corr_ofdm_mrc_x1);
-       pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
-                       data->auto_corr_cck);
-       pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
-                       data->auto_corr_cck_mrc);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "last_bad_plcp_cnt_ofdm:\t\t %u\n",
-                       data->last_bad_plcp_cnt_ofdm);
-       pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
-                       data->last_fa_cnt_ofdm);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "last_bad_plcp_cnt_cck:\t\t %u\n",
-                       data->last_bad_plcp_cnt_cck);
-       pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
-                       data->last_fa_cnt_cck);
-       pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
-                       data->nrg_curr_state);
-       pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
-                       data->nrg_prev_state);
-       pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
-       for (cnt = 0; cnt < 10; cnt++) {
-               pos += scnprintf(buf + pos, bufsz - pos, " %u",
-                               data->nrg_value[cnt]);
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "\n");
-       pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
-       for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
-               pos += scnprintf(buf + pos, bufsz - pos, " %u",
-                               data->nrg_silence_rssi[cnt]);
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "\n");
-       pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
-                       data->nrg_silence_ref);
-       pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
-                       data->nrg_energy_idx);
-       pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
-                       data->nrg_silence_idx);
-       pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
-                       data->nrg_th_cck);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "nrg_auto_corr_silence_diff:\t %u\n",
-                       data->nrg_auto_corr_silence_diff);
-       pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
-                       data->num_in_cck_no_fa);
-       pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
-                       data->nrg_th_ofdm);
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-
-static ssize_t iwl_legacy_dbgfs_chain_noise_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       int cnt = 0;
-       char *buf;
-       int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
-       ssize_t ret;
-       struct iwl_chain_noise_data *data;
-
-       data = &priv->chain_noise_data;
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(priv, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
-                       data->active_chains);
-       pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
-                       data->chain_noise_a);
-       pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
-                       data->chain_noise_b);
-       pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
-                       data->chain_noise_c);
-       pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
-                       data->chain_signal_a);
-       pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
-                       data->chain_signal_b);
-       pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
-                       data->chain_signal_c);
-       pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
-                       data->beacon_count);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
-       for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
-               pos += scnprintf(buf + pos, bufsz - pos, " %u",
-                               data->disconn_array[cnt]);
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "\n");
-       pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
-       for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
-               pos += scnprintf(buf + pos, bufsz - pos, " %u",
-                               data->delta_gain_code[cnt]);
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "\n");
-       pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
-                       data->radio_write);
-       pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
-                       data->state);
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_power_save_status_read(struct file *file,
-                                                   char __user *user_buf,
-                                                   size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char buf[60];
-       int pos = 0;
-       const size_t bufsz = sizeof(buf);
-       u32 pwrsave_status;
-
-       pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) &
-                       CSR_GP_REG_POWER_SAVE_STATUS_MSK;
-
-       pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
-       pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
-               (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
-               (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
-               (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
-               "error");
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_clear_ucode_statistics_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
-       int buf_size;
-       int clear;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &clear) != 1)
-               return -EFAULT;
-
-       /* make request to uCode to retrieve statistics information */
-       mutex_lock(&priv->mutex);
-       iwl_legacy_send_statistics_request(priv, CMD_SYNC, true);
-       mutex_unlock(&priv->mutex);
-
-       return count;
-}
-
-static ssize_t iwl_legacy_dbgfs_rxon_flags_read(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       int len = 0;
-       char buf[20];
-
-       len = sprintf(buf, "0x%04X\n",
-               le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags));
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t iwl_legacy_dbgfs_rxon_filter_flags_read(struct file *file,
-                                               char __user *user_buf,
-                                               size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       int len = 0;
-       char buf[20];
-
-       len = sprintf(buf, "0x%04X\n",
-       le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags));
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t iwl_legacy_dbgfs_fh_reg_read(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char *buf;
-       int pos = 0;
-       ssize_t ret = -EFAULT;
-
-       if (priv->cfg->ops->lib->dump_fh) {
-               ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true);
-               if (buf) {
-                       ret = simple_read_from_buffer(user_buf,
-                                                     count, ppos, buf, pos);
-                       kfree(buf);
-               }
-       }
-
-       return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_missed_beacon_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       char buf[12];
-       const size_t bufsz = sizeof(buf);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
-                       priv->missed_beacon_threshold);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_missed_beacon_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
-       int buf_size;
-       int missed;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &missed) != 1)
-               return -EINVAL;
-
-       if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN ||
-           missed > IWL_MISSED_BEACON_THRESHOLD_MAX)
-               priv->missed_beacon_threshold =
-                       IWL_MISSED_BEACON_THRESHOLD_DEF;
-       else
-               priv->missed_beacon_threshold = missed;
-
-       return count;
-}
-
-static ssize_t iwl_legacy_dbgfs_force_reset_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       char buf[300];
-       const size_t bufsz = sizeof(buf);
-       struct iwl_force_reset *force_reset;
-
-       force_reset = &priv->force_reset;
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "\tnumber of reset request: %d\n",
-                       force_reset->reset_request_count);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "\tnumber of reset request success: %d\n",
-                       force_reset->reset_success_count);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "\tnumber of reset request reject: %d\n",
-                       force_reset->reset_reject_count);
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "\treset duration: %lu\n",
-                       force_reset->reset_duration);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_force_reset_write(struct file *file,
-                                       const char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       int ret;
-       struct iwl_priv *priv = file->private_data;
-
-       ret = iwl_legacy_force_reset(priv, true);
-
-       return ret ? ret : count;
-}
-
-static ssize_t iwl_legacy_dbgfs_wd_timeout_write(struct file *file,
-                                       const char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
-       int buf_size;
-       int timeout;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &timeout) != 1)
-               return -EINVAL;
-       if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
-               timeout = IWL_DEF_WD_TIMEOUT;
-
-       priv->cfg->base_params->wd_timeout = timeout;
-       iwl_legacy_setup_watchdog(priv);
-       return count;
-}
-
-DEBUGFS_READ_FILE_OPS(rx_statistics);
-DEBUGFS_READ_FILE_OPS(tx_statistics);
-DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
-DEBUGFS_READ_FILE_OPS(rx_queue);
-DEBUGFS_READ_FILE_OPS(tx_queue);
-DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
-DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
-DEBUGFS_READ_FILE_OPS(ucode_general_stats);
-DEBUGFS_READ_FILE_OPS(sensitivity);
-DEBUGFS_READ_FILE_OPS(chain_noise);
-DEBUGFS_READ_FILE_OPS(power_save_status);
-DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
-DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
-DEBUGFS_READ_FILE_OPS(fh_reg);
-DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
-DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
-DEBUGFS_READ_FILE_OPS(rxon_flags);
-DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
-DEBUGFS_WRITE_FILE_OPS(wd_timeout);
-
-/*
- * Create the debugfs files and directories
- *
- */
-int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
-{
-       struct dentry *phyd = priv->hw->wiphy->debugfsdir;
-       struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
-
-       dir_drv = debugfs_create_dir(name, phyd);
-       if (!dir_drv)
-               return -ENOMEM;
-
-       priv->debugfs_dir = dir_drv;
-
-       dir_data = debugfs_create_dir("data", dir_drv);
-       if (!dir_data)
-               goto err;
-       dir_rf = debugfs_create_dir("rf", dir_drv);
-       if (!dir_rf)
-               goto err;
-       dir_debug = debugfs_create_dir("debug", dir_drv);
-       if (!dir_debug)
-               goto err;
-
-       DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
-       DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
-       DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
-       DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
-       DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
-       DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
-       DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
-       DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
-       DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
-       DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
-       DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
-       DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
-       DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
-       DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
-       DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
-       DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
-       DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
-       DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
-       DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
-       DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
-       DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
-       DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
-
-       if (priv->cfg->base_params->sensitivity_calib_by_driver)
-               DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
-       if (priv->cfg->base_params->chain_noise_calib_by_driver)
-               DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
-       DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
-       DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
-       DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
-       if (priv->cfg->base_params->sensitivity_calib_by_driver)
-               DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
-                                &priv->disable_sens_cal);
-       if (priv->cfg->base_params->chain_noise_calib_by_driver)
-               DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
-                                &priv->disable_chain_noise_cal);
-       DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
-                               &priv->disable_tx_power_cal);
-       return 0;
-
-err:
-       IWL_ERR(priv, "Can't create the debugfs directory\n");
-       iwl_legacy_dbgfs_unregister(priv);
-       return -ENOMEM;
-}
-EXPORT_SYMBOL(iwl_legacy_dbgfs_register);
-
-/**
- * Remove the debugfs files and directories
- *
- */
-void iwl_legacy_dbgfs_unregister(struct iwl_priv *priv)
-{
-       if (!priv->debugfs_dir)
-               return;
-
-       debugfs_remove_recursive(priv->debugfs_dir);
-       priv->debugfs_dir = NULL;
-}
-EXPORT_SYMBOL(iwl_legacy_dbgfs_unregister);
diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h
deleted file mode 100644 (file)
index 9c786ed..0000000
+++ /dev/null
@@ -1,1364 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-dev.h) for driver implementation definitions.
- * Please use iwl-commands.h for uCode API definitions.
- * Please use iwl-4965-hw.h for hardware-related definitions.
- */
-
-#ifndef __iwl_legacy_dev_h__
-#define __iwl_legacy_dev_h__
-
-#include <linux/interrupt.h>
-#include <linux/pci.h> /* for struct pci_device_id */
-#include <linux/kernel.h>
-#include <linux/leds.h>
-#include <linux/wait.h>
-#include <net/ieee80211_radiotap.h>
-
-#include "iwl-eeprom.h"
-#include "iwl-csr.h"
-#include "iwl-prph.h"
-#include "iwl-fh.h"
-#include "iwl-debug.h"
-#include "iwl-4965-hw.h"
-#include "iwl-3945-hw.h"
-#include "iwl-led.h"
-#include "iwl-power.h"
-#include "iwl-legacy-rs.h"
-
-struct iwl_tx_queue;
-
-/* CT-KILL constants */
-#define CT_KILL_THRESHOLD_LEGACY   110 /* in Celsius */
-
-/* Default noise level to report when noise measurement is not available.
- *   This may be because we're:
- *   1)  Not associated (4965, no beacon statistics being sent to driver)
- *   2)  Scanning (noise measurement does not apply to associated channel)
- *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
- * Use default noise value of -127 ... this is below the range of measurable
- *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
- *   Also, -127 works better than 0 when averaging frames with/without
- *   noise info (e.g. averaging might be done in app); measured dBm values are
- *   always negative ... using a negative value as the default keeps all
- *   averages within an s8's (used in some apps) range of negative values. */
-#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
-
-/*
- * RTS threshold here is total size [2347] minus 4 FCS bytes
- * Per spec:
- *   a value of 0 means RTS on all data/management packets
- *   a value > max MSDU size means no RTS
- * else RTS for data/management frames where MPDU is larger
- *   than RTS value.
- */
-#define DEFAULT_RTS_THRESHOLD     2347U
-#define MIN_RTS_THRESHOLD         0U
-#define MAX_RTS_THRESHOLD         2347U
-#define MAX_MSDU_SIZE            2304U
-#define MAX_MPDU_SIZE            2346U
-#define DEFAULT_BEACON_INTERVAL   100U
-#define        DEFAULT_SHORT_RETRY_LIMIT 7U
-#define        DEFAULT_LONG_RETRY_LIMIT  4U
-
-struct iwl_rx_mem_buffer {
-       dma_addr_t page_dma;
-       struct page *page;
-       struct list_head list;
-};
-
-#define rxb_addr(r) page_address(r->page)
-
-/* defined below */
-struct iwl_device_cmd;
-
-struct iwl_cmd_meta {
-       /* only for SYNC commands, iff the reply skb is wanted */
-       struct iwl_host_cmd *source;
-       /*
-        * only for ASYNC commands
-        * (which is somewhat stupid -- look at iwl-sta.c for instance
-        * which duplicates a bunch of code because the callback isn't
-        * invoked for SYNC commands, if it were and its result passed
-        * through it would be simpler...)
-        */
-       void (*callback)(struct iwl_priv *priv,
-                        struct iwl_device_cmd *cmd,
-                        struct iwl_rx_packet *pkt);
-
-       /* The CMD_SIZE_HUGE flag bit indicates that the command
-        * structure is stored at the end of the shared queue memory. */
-       u32 flags;
-
-       DEFINE_DMA_UNMAP_ADDR(mapping);
-       DEFINE_DMA_UNMAP_LEN(len);
-};
-
-/*
- * Generic queue structure
- *
- * Contains common data for Rx and Tx queues
- */
-struct iwl_queue {
-       int n_bd;              /* number of BDs in this queue */
-       int write_ptr;       /* 1-st empty entry (index) host_w*/
-       int read_ptr;         /* last used entry (index) host_r*/
-       /* use for monitoring and recovering the stuck queue */
-       dma_addr_t dma_addr;   /* physical addr for BD's */
-       int n_window;          /* safe queue window */
-       u32 id;
-       int low_mark;          /* low watermark, resume queue if free
-                               * space more than this */
-       int high_mark;         /* high watermark, stop queue if free
-                               * space less than this */
-};
-
-/* One for each TFD */
-struct iwl_tx_info {
-       struct sk_buff *skb;
-       struct iwl_rxon_context *ctx;
-};
-
-/**
- * struct iwl_tx_queue - Tx Queue for DMA
- * @q: generic Rx/Tx queue descriptor
- * @bd: base of circular buffer of TFDs
- * @cmd: array of command/TX buffer pointers
- * @meta: array of meta data for each command/tx buffer
- * @dma_addr_cmd: physical address of cmd/tx buffer array
- * @txb: array of per-TFD driver data
- * @time_stamp: time (in jiffies) of last read_ptr change
- * @need_update: indicates need to update read/write index
- * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
- *
- * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
- * descriptors) and required locking structures.
- */
-#define TFD_TX_CMD_SLOTS 256
-#define TFD_CMD_SLOTS 32
-
-struct iwl_tx_queue {
-       struct iwl_queue q;
-       void *tfds;
-       struct iwl_device_cmd **cmd;
-       struct iwl_cmd_meta *meta;
-       struct iwl_tx_info *txb;
-       unsigned long time_stamp;
-       u8 need_update;
-       u8 sched_retry;
-       u8 active;
-       u8 swq_id;
-};
-
-#define IWL_NUM_SCAN_RATES         (2)
-
-struct iwl4965_channel_tgd_info {
-       u8 type;
-       s8 max_power;
-};
-
-struct iwl4965_channel_tgh_info {
-       s64 last_radar_time;
-};
-
-#define IWL4965_MAX_RATE (33)
-
-struct iwl3945_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];
-};
-
-/* 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 iwl3945_channel_power_info {
-       struct iwl3945_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 */
-};
-
-/* current scan Tx power values to use, one for each scan rate for each
- * channel. */
-struct iwl3945_scan_power_info {
-       struct iwl3945_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 */
-};
-
-/*
- * 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!
- */
-struct iwl_channel_info {
-       struct iwl4965_channel_tgd_info tgd;
-       struct iwl4965_channel_tgh_info tgh;
-       struct iwl_eeprom_channel eeprom;       /* EEPROM regulatory limit */
-       struct iwl_eeprom_channel ht40_eeprom;  /* EEPROM regulatory limit for
-                                                * HT40 channel */
-
-       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) limit */
-       s8 min_power;     /* always 0 */
-       s8 scan_power;    /* (dBm) regul. eeprom, direct scans, any rate */
-
-       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 */
-       enum ieee80211_band band;
-
-       /* HT40 channel info */
-       s8 ht40_max_power_avg;  /* (dBm) regul. eeprom, normal Tx, any rate */
-       u8 ht40_flags;          /* flags copied from EEPROM */
-       u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
-
-       /* 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 iwl3945_channel_power_info power_info[IWL4965_MAX_RATE];
-
-       /* Radio/DSP gain settings for each scan rate, for directed scans. */
-       struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
-};
-
-#define IWL_TX_FIFO_BK         0       /* shared */
-#define IWL_TX_FIFO_BE         1
-#define IWL_TX_FIFO_VI         2       /* shared */
-#define IWL_TX_FIFO_VO         3
-#define IWL_TX_FIFO_UNUSED     -1
-
-/* Minimum number of queues. MAX_NUM is defined in hw specific files.
- * Set the minimum to accommodate the 4 standard TX queues, 1 command
- * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */
-#define IWL_MIN_NUM_QUEUES     10
-
-#define IWL_DEFAULT_CMD_QUEUE_NUM      4
-
-#define IEEE80211_DATA_LEN              2304
-#define IEEE80211_4ADDR_LEN             30
-#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
-#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
-
-struct iwl_frame {
-       union {
-               struct ieee80211_hdr frame;
-               struct iwl_tx_beacon_cmd beacon;
-               u8 raw[IEEE80211_FRAME_LEN];
-               u8 cmd[360];
-       } u;
-       struct list_head list;
-};
-
-#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
-
-enum {
-       CMD_SYNC = 0,
-       CMD_SIZE_NORMAL = 0,
-       CMD_NO_SKB = 0,
-       CMD_SIZE_HUGE = (1 << 0),
-       CMD_ASYNC = (1 << 1),
-       CMD_WANT_SKB = (1 << 2),
-       CMD_MAPPED = (1 << 3),
-};
-
-#define DEF_CMD_PAYLOAD_SIZE 320
-
-/**
- * struct iwl_device_cmd
- *
- * For allocation of the command and tx queues, this establishes the overall
- * size of the largest command we send to uCode, except for a scan command
- * (which is relatively huge; space is allocated separately).
- */
-struct iwl_device_cmd {
-       struct iwl_cmd_header hdr;      /* uCode API */
-       union {
-               u32 flags;
-               u8 val8;
-               u16 val16;
-               u32 val32;
-               struct iwl_tx_cmd tx;
-               u8 payload[DEF_CMD_PAYLOAD_SIZE];
-       } __packed cmd;
-} __packed;
-
-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
-
-
-struct iwl_host_cmd {
-       const void *data;
-       unsigned long reply_page;
-       void (*callback)(struct iwl_priv *priv,
-                        struct iwl_device_cmd *cmd,
-                        struct iwl_rx_packet *pkt);
-       u32 flags;
-       u16 len;
-       u8 id;
-};
-
-#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
-#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
-#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
-
-/**
- * struct iwl_rx_queue - Rx queue
- * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
- * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
- * @read: Shared index to newest available Rx buffer
- * @write: Shared index to oldest written Rx packet
- * @free_count: Number of pre-allocated buffers in rx_free
- * @rx_free: list of free SKBs for use
- * @rx_used: List of Rx buffers with no SKB
- * @need_update: flag to indicate we need to update read/write index
- * @rb_stts: driver's pointer to receive buffer status
- * @rb_stts_dma: bus address of receive buffer status
- *
- * NOTE:  rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
- */
-struct iwl_rx_queue {
-       __le32 *bd;
-       dma_addr_t bd_dma;
-       struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
-       struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
-       u32 read;
-       u32 write;
-       u32 free_count;
-       u32 write_actual;
-       struct list_head rx_free;
-       struct list_head rx_used;
-       int need_update;
-       struct iwl_rb_status *rb_stts;
-       dma_addr_t rb_stts_dma;
-       spinlock_t lock;
-};
-
-#define IWL_SUPPORTED_RATES_IE_LEN         8
-
-#define MAX_TID_COUNT        9
-
-#define IWL_INVALID_RATE     0xFF
-#define IWL_INVALID_VALUE    -1
-
-/**
- * struct iwl_ht_agg -- aggregation status while waiting for block-ack
- * @txq_id: Tx queue used for Tx attempt
- * @frame_count: # frames attempted by Tx command
- * @wait_for_ba: Expect block-ack before next Tx reply
- * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window
- * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window
- * @bitmap1: High order, one bit for each frame pending ACK in Tx window
- * @rate_n_flags: Rate at which Tx was attempted
- *
- * If REPLY_TX indicates that aggregation was attempted, driver must wait
- * for block ack (REPLY_COMPRESSED_BA).  This struct stores tx reply info
- * until block ack arrives.
- */
-struct iwl_ht_agg {
-       u16 txq_id;
-       u16 frame_count;
-       u16 wait_for_ba;
-       u16 start_idx;
-       u64 bitmap;
-       u32 rate_n_flags;
-#define IWL_AGG_OFF 0
-#define IWL_AGG_ON 1
-#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
-#define IWL_EMPTYING_HW_QUEUE_DELBA 3
-       u8 state;
-};
-
-
-struct iwl_tid_data {
-       u16 seq_number; /* 4965 only */
-       u16 tfds_in_queue;
-       struct iwl_ht_agg agg;
-};
-
-struct iwl_hw_key {
-       u32 cipher;
-       int keylen;
-       u8 keyidx;
-       u8 key[32];
-};
-
-union iwl_ht_rate_supp {
-       u16 rates;
-       struct {
-               u8 siso_rate;
-               u8 mimo_rate;
-       };
-};
-
-#define CFG_HT_RX_AMPDU_FACTOR_8K   (0x0)
-#define CFG_HT_RX_AMPDU_FACTOR_16K  (0x1)
-#define CFG_HT_RX_AMPDU_FACTOR_32K  (0x2)
-#define CFG_HT_RX_AMPDU_FACTOR_64K  (0x3)
-#define CFG_HT_RX_AMPDU_FACTOR_DEF  CFG_HT_RX_AMPDU_FACTOR_64K
-#define CFG_HT_RX_AMPDU_FACTOR_MAX  CFG_HT_RX_AMPDU_FACTOR_64K
-#define CFG_HT_RX_AMPDU_FACTOR_MIN  CFG_HT_RX_AMPDU_FACTOR_8K
-
-/*
- * Maximal MPDU density for TX aggregation
- * 4 - 2us density
- * 5 - 4us density
- * 6 - 8us density
- * 7 - 16us density
- */
-#define CFG_HT_MPDU_DENSITY_2USEC   (0x4)
-#define CFG_HT_MPDU_DENSITY_4USEC   (0x5)
-#define CFG_HT_MPDU_DENSITY_8USEC   (0x6)
-#define CFG_HT_MPDU_DENSITY_16USEC  (0x7)
-#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
-#define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC
-#define CFG_HT_MPDU_DENSITY_MIN     (0x1)
-
-struct iwl_ht_config {
-       bool single_chain_sufficient;
-       enum ieee80211_smps_mode smps; /* current smps mode */
-};
-
-/* QoS structures */
-struct iwl_qos_info {
-       int qos_active;
-       struct iwl_qosparam_cmd def_qos_parm;
-};
-
-/*
- * Structure should be accessed with sta_lock held. When station addition
- * is in progress (IWL_STA_UCODE_INPROGRESS) it is possible to access only
- * the commands (iwl_legacy_addsta_cmd and iwl_link_quality_cmd) without
- * sta_lock held.
- */
-struct iwl_station_entry {
-       struct iwl_legacy_addsta_cmd sta;
-       struct iwl_tid_data tid[MAX_TID_COUNT];
-       u8 used, ctxid;
-       struct iwl_hw_key keyinfo;
-       struct iwl_link_quality_cmd *lq;
-};
-
-struct iwl_station_priv_common {
-       struct iwl_rxon_context *ctx;
-       u8 sta_id;
-};
-
-/*
- * iwl_station_priv: Driver's private station information
- *
- * When mac80211 creates a station it reserves some space (hw->sta_data_size)
- * in the structure for use by driver. This structure is places in that
- * space.
- *
- * The common struct MUST be first because it is shared between
- * 3945 and 4965!
- */
-struct iwl_station_priv {
-       struct iwl_station_priv_common common;
-       struct iwl_lq_sta lq_sta;
-       atomic_t pending_frames;
-       bool client;
-       bool asleep;
-};
-
-/**
- * struct iwl_vif_priv - driver's private per-interface information
- *
- * When mac80211 allocates a virtual interface, it can allocate
- * space for us to put data into.
- */
-struct iwl_vif_priv {
-       struct iwl_rxon_context *ctx;
-       u8 ibss_bssid_sta_id;
-};
-
-/* one for each uCode image (inst/data, boot/init/runtime) */
-struct fw_desc {
-       void *v_addr;           /* access by driver */
-       dma_addr_t p_addr;      /* access by card's busmaster DMA */
-       u32 len;                /* bytes */
-};
-
-/* uCode file layout */
-struct iwl_ucode_header {
-       __le32 ver;     /* major/minor/API/serial */
-       struct {
-               __le32 inst_size;       /* bytes of runtime code */
-               __le32 data_size;       /* bytes of runtime data */
-               __le32 init_size;       /* bytes of init code */
-               __le32 init_data_size;  /* bytes of init data */
-               __le32 boot_size;       /* bytes of bootstrap code */
-               u8 data[0];             /* in same order as sizes */
-       } v1;
-};
-
-struct iwl4965_ibss_seq {
-       u8 mac[ETH_ALEN];
-       u16 seq_num;
-       u16 frag_num;
-       unsigned long packet_time;
-       struct list_head list;
-};
-
-struct iwl_sensitivity_ranges {
-       u16 min_nrg_cck;
-       u16 max_nrg_cck;
-
-       u16 nrg_th_cck;
-       u16 nrg_th_ofdm;
-
-       u16 auto_corr_min_ofdm;
-       u16 auto_corr_min_ofdm_mrc;
-       u16 auto_corr_min_ofdm_x1;
-       u16 auto_corr_min_ofdm_mrc_x1;
-
-       u16 auto_corr_max_ofdm;
-       u16 auto_corr_max_ofdm_mrc;
-       u16 auto_corr_max_ofdm_x1;
-       u16 auto_corr_max_ofdm_mrc_x1;
-
-       u16 auto_corr_max_cck;
-       u16 auto_corr_max_cck_mrc;
-       u16 auto_corr_min_cck;
-       u16 auto_corr_min_cck_mrc;
-
-       u16 barker_corr_th_min;
-       u16 barker_corr_th_min_mrc;
-       u16 nrg_th_cca;
-};
-
-
-#define KELVIN_TO_CELSIUS(x) ((x)-273)
-#define CELSIUS_TO_KELVIN(x) ((x)+273)
-
-
-/**
- * struct iwl_hw_params
- * @max_txq_num: Max # Tx queues supported
- * @dma_chnl_num: Number of Tx DMA/FIFO channels
- * @scd_bc_tbls_size: size of scheduler byte count tables
- * @tfd_size: TFD size
- * @tx/rx_chains_num: Number of TX/RX chains
- * @valid_tx/rx_ant: usable antennas
- * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
- * @max_rxq_log: Log-base-2 of max_rxq_size
- * @rx_page_order: Rx buffer page order
- * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
- * @max_stations:
- * @ht40_channel: is 40MHz width possible in band 2.4
- * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
- * @sw_crypto: 0 for hw, 1 for sw
- * @max_xxx_size: for ucode uses
- * @ct_kill_threshold: temperature threshold
- * @beacon_time_tsf_bits: number of valid tsf bits for beacon time
- * @struct iwl_sensitivity_ranges: range of sensitivity values
- */
-struct iwl_hw_params {
-       u8 max_txq_num;
-       u8 dma_chnl_num;
-       u16 scd_bc_tbls_size;
-       u32 tfd_size;
-       u8  tx_chains_num;
-       u8  rx_chains_num;
-       u8  valid_tx_ant;
-       u8  valid_rx_ant;
-       u16 max_rxq_size;
-       u16 max_rxq_log;
-       u32 rx_page_order;
-       u32 rx_wrt_ptr_reg;
-       u8  max_stations;
-       u8  ht40_channel;
-       u8  max_beacon_itrvl;   /* in 1024 ms */
-       u32 max_inst_size;
-       u32 max_data_size;
-       u32 max_bsm_size;
-       u32 ct_kill_threshold; /* value in hw-dependent units */
-       u16 beacon_time_tsf_bits;
-       const struct iwl_sensitivity_ranges *sens;
-};
-
-
-/******************************************************************************
- *
- * Functions implemented in core module which are forward declared here
- * for use by iwl-[4-5].c
- *
- * NOTE:  The implementation of these functions are not hardware specific
- * which is why they are in the core module files.
- *
- * Naming convention --
- * iwl_         <-- Is part of iwlwifi
- * iwlXXXX_     <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
- * iwl4965_bg_      <-- Called from work queue context
- * iwl4965_mac_     <-- mac80211 callback
- *
- ****************************************************************************/
-extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
-extern const u8 iwlegacy_bcast_addr[ETH_ALEN];
-extern int iwl_legacy_queue_space(const struct iwl_queue *q);
-static inline int iwl_legacy_queue_used(const struct iwl_queue *q, int i)
-{
-       return q->write_ptr >= q->read_ptr ?
-               (i >= q->read_ptr && i < q->write_ptr) :
-               !(i < q->read_ptr && i >= q->write_ptr);
-}
-
-
-static inline u8 iwl_legacy_get_cmd_index(struct iwl_queue *q, u32 index,
-                                                               int is_huge)
-{
-       /*
-        * This is for init calibration result and scan command which
-        * required buffer > TFD_MAX_PAYLOAD_SIZE,
-        * the big buffer at end of command array
-        */
-       if (is_huge)
-               return q->n_window;     /* must be power of 2 */
-
-       /* Otherwise, use normal size buffers */
-       return index & (q->n_window - 1);
-}
-
-
-struct iwl_dma_ptr {
-       dma_addr_t dma;
-       void *addr;
-       size_t size;
-};
-
-#define IWL_OPERATION_MODE_AUTO     0
-#define IWL_OPERATION_MODE_HT_ONLY  1
-#define IWL_OPERATION_MODE_MIXED    2
-#define IWL_OPERATION_MODE_20MHZ    3
-
-#define IWL_TX_CRC_SIZE 4
-#define IWL_TX_DELIMITER_SIZE 4
-
-#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
-
-/* Sensitivity and chain noise calibration */
-#define INITIALIZATION_VALUE           0xFFFF
-#define IWL4965_CAL_NUM_BEACONS                20
-#define IWL_CAL_NUM_BEACONS            16
-#define MAXIMUM_ALLOWED_PATHLOSS       15
-
-#define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3
-
-#define MAX_FA_OFDM  50
-#define MIN_FA_OFDM  5
-#define MAX_FA_CCK   50
-#define MIN_FA_CCK   5
-
-#define AUTO_CORR_STEP_OFDM       1
-
-#define AUTO_CORR_STEP_CCK     3
-#define AUTO_CORR_MAX_TH_CCK   160
-
-#define NRG_DIFF               2
-#define NRG_STEP_CCK           2
-#define NRG_MARGIN             8
-#define MAX_NUMBER_CCK_NO_FA 100
-
-#define AUTO_CORR_CCK_MIN_VAL_DEF    (125)
-
-#define CHAIN_A             0
-#define CHAIN_B             1
-#define CHAIN_C             2
-#define CHAIN_NOISE_DELTA_GAIN_INIT_VAL 4
-#define ALL_BAND_FILTER                        0xFF00
-#define IN_BAND_FILTER                 0xFF
-#define MIN_AVERAGE_NOISE_MAX_VALUE    0xFFFFFFFF
-
-#define NRG_NUM_PREV_STAT_L     20
-#define NUM_RX_CHAINS           3
-
-enum iwl4965_false_alarm_state {
-       IWL_FA_TOO_MANY = 0,
-       IWL_FA_TOO_FEW = 1,
-       IWL_FA_GOOD_RANGE = 2,
-};
-
-enum iwl4965_chain_noise_state {
-       IWL_CHAIN_NOISE_ALIVE = 0,  /* must be 0 */
-       IWL_CHAIN_NOISE_ACCUMULATE,
-       IWL_CHAIN_NOISE_CALIBRATED,
-       IWL_CHAIN_NOISE_DONE,
-};
-
-enum iwl4965_calib_enabled_state {
-       IWL_CALIB_DISABLED = 0,  /* must be 0 */
-       IWL_CALIB_ENABLED = 1,
-};
-
-/*
- * enum iwl_calib
- * defines the order in which results of initial calibrations
- * should be sent to the runtime uCode
- */
-enum iwl_calib {
-       IWL_CALIB_MAX,
-};
-
-/* Opaque calibration results */
-struct iwl_calib_result {
-       void *buf;
-       size_t buf_len;
-};
-
-enum ucode_type {
-       UCODE_NONE = 0,
-       UCODE_INIT,
-       UCODE_RT
-};
-
-/* Sensitivity calib data */
-struct iwl_sensitivity_data {
-       u32 auto_corr_ofdm;
-       u32 auto_corr_ofdm_mrc;
-       u32 auto_corr_ofdm_x1;
-       u32 auto_corr_ofdm_mrc_x1;
-       u32 auto_corr_cck;
-       u32 auto_corr_cck_mrc;
-
-       u32 last_bad_plcp_cnt_ofdm;
-       u32 last_fa_cnt_ofdm;
-       u32 last_bad_plcp_cnt_cck;
-       u32 last_fa_cnt_cck;
-
-       u32 nrg_curr_state;
-       u32 nrg_prev_state;
-       u32 nrg_value[10];
-       u8  nrg_silence_rssi[NRG_NUM_PREV_STAT_L];
-       u32 nrg_silence_ref;
-       u32 nrg_energy_idx;
-       u32 nrg_silence_idx;
-       u32 nrg_th_cck;
-       s32 nrg_auto_corr_silence_diff;
-       u32 num_in_cck_no_fa;
-       u32 nrg_th_ofdm;
-
-       u16 barker_corr_th_min;
-       u16 barker_corr_th_min_mrc;
-       u16 nrg_th_cca;
-};
-
-/* Chain noise (differential Rx gain) calib data */
-struct iwl_chain_noise_data {
-       u32 active_chains;
-       u32 chain_noise_a;
-       u32 chain_noise_b;
-       u32 chain_noise_c;
-       u32 chain_signal_a;
-       u32 chain_signal_b;
-       u32 chain_signal_c;
-       u16 beacon_count;
-       u8 disconn_array[NUM_RX_CHAINS];
-       u8 delta_gain_code[NUM_RX_CHAINS];
-       u8 radio_write;
-       u8 state;
-};
-
-#define        EEPROM_SEM_TIMEOUT 10           /* milliseconds */
-#define EEPROM_SEM_RETRY_LIMIT 1000    /* number of attempts (not time) */
-
-#define IWL_TRAFFIC_ENTRIES    (256)
-#define IWL_TRAFFIC_ENTRY_SIZE  (64)
-
-enum {
-       MEASUREMENT_READY = (1 << 0),
-       MEASUREMENT_ACTIVE = (1 << 1),
-};
-
-/* interrupt statistics */
-struct isr_statistics {
-       u32 hw;
-       u32 sw;
-       u32 err_code;
-       u32 sch;
-       u32 alive;
-       u32 rfkill;
-       u32 ctkill;
-       u32 wakeup;
-       u32 rx;
-       u32 rx_handlers[REPLY_MAX];
-       u32 tx;
-       u32 unhandled;
-};
-
-/* management statistics */
-enum iwl_mgmt_stats {
-       MANAGEMENT_ASSOC_REQ = 0,
-       MANAGEMENT_ASSOC_RESP,
-       MANAGEMENT_REASSOC_REQ,
-       MANAGEMENT_REASSOC_RESP,
-       MANAGEMENT_PROBE_REQ,
-       MANAGEMENT_PROBE_RESP,
-       MANAGEMENT_BEACON,
-       MANAGEMENT_ATIM,
-       MANAGEMENT_DISASSOC,
-       MANAGEMENT_AUTH,
-       MANAGEMENT_DEAUTH,
-       MANAGEMENT_ACTION,
-       MANAGEMENT_MAX,
-};
-/* control statistics */
-enum iwl_ctrl_stats {
-       CONTROL_BACK_REQ =  0,
-       CONTROL_BACK,
-       CONTROL_PSPOLL,
-       CONTROL_RTS,
-       CONTROL_CTS,
-       CONTROL_ACK,
-       CONTROL_CFEND,
-       CONTROL_CFENDACK,
-       CONTROL_MAX,
-};
-
-struct traffic_stats {
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-       u32 mgmt[MANAGEMENT_MAX];
-       u32 ctrl[CONTROL_MAX];
-       u32 data_cnt;
-       u64 data_bytes;
-#endif
-};
-
-/*
- * host interrupt timeout value
- * used with setting interrupt coalescing timer
- * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
- *
- * default interrupt coalescing timer is 64 x 32 = 2048 usecs
- * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
- */
-#define IWL_HOST_INT_TIMEOUT_MAX       (0xFF)
-#define IWL_HOST_INT_TIMEOUT_DEF       (0x40)
-#define IWL_HOST_INT_TIMEOUT_MIN       (0x0)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
-#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
-
-#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
-
-/* TX queue watchdog timeouts in mSecs */
-#define IWL_DEF_WD_TIMEOUT     (2000)
-#define IWL_LONG_WD_TIMEOUT    (10000)
-#define IWL_MAX_WD_TIMEOUT     (120000)
-
-struct iwl_force_reset {
-       int reset_request_count;
-       int reset_success_count;
-       int reset_reject_count;
-       unsigned long reset_duration;
-       unsigned long last_force_reset_jiffies;
-};
-
-/* extend beacon time format bit shifting  */
-/*
- * for _3945 devices
- * bits 31:24 - extended
- * bits 23:0  - interval
- */
-#define IWL3945_EXT_BEACON_TIME_POS    24
-/*
- * for _4965 devices
- * bits 31:22 - extended
- * bits 21:0  - interval
- */
-#define IWL4965_EXT_BEACON_TIME_POS    22
-
-enum iwl_rxon_context_id {
-       IWL_RXON_CTX_BSS,
-
-       NUM_IWL_RXON_CTX
-};
-
-struct iwl_rxon_context {
-       struct ieee80211_vif *vif;
-
-       const u8 *ac_to_fifo;
-       const u8 *ac_to_queue;
-       u8 mcast_queue;
-
-       /*
-        * We could use the vif to indicate active, but we
-        * also need it to be active during disabling when
-        * we already removed the vif for type setting.
-        */
-       bool always_active, is_active;
-
-       bool ht_need_multiple_chains;
-
-       enum iwl_rxon_context_id ctxid;
-
-       u32 interface_modes, exclusive_interface_modes;
-       u8 unused_devtype, ap_devtype, ibss_devtype, station_devtype;
-
-       /*
-        * 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_legacy_rxon_cmd active;
-       struct iwl_legacy_rxon_cmd staging;
-
-       struct iwl_rxon_time_cmd timing;
-
-       struct iwl_qos_info qos_data;
-
-       u8 bcast_sta_id, ap_sta_id;
-
-       u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd;
-       u8 qos_cmd;
-       u8 wep_key_cmd;
-
-       struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
-       u8 key_mapping_keys;
-
-       __le32 station_flags;
-
-       struct {
-               bool non_gf_sta_present;
-               u8 protection;
-               bool enabled, is_40mhz;
-               u8 extension_chan_offset;
-       } ht;
-};
-
-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;
-       struct iwl_cfg *cfg;
-
-       /* temporary frame storage list */
-       struct list_head free_frames;
-       int frames_count;
-
-       enum ieee80211_band band;
-       int alloc_rxb_page;
-
-       void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
-                                      struct iwl_rx_mem_buffer *rxb);
-
-       struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
-
-       /* spectrum measurement report caching */
-       struct iwl_spectrum_notification measure_report;
-       u8 measurement_status;
-
-       /* ucode beacon time */
-       u32 ucode_beacon_time;
-       int missed_beacon_threshold;
-
-       /* track IBSS manager (last beacon) status */
-       u32 ibss_manager;
-
-       /* force reset */
-       struct iwl_force_reset force_reset;
-
-       /* 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 */
-
-       /* thermal calibration */
-       s32 temperature;        /* degrees Kelvin */
-       s32 last_temperature;
-
-       /* init calibration results */
-       struct iwl_calib_result calib_results[IWL_CALIB_MAX];
-
-       /* Scan related variables */
-       unsigned long scan_start;
-       unsigned long scan_start_tsf;
-       void *scan_cmd;
-       enum ieee80211_band scan_band;
-       struct cfg80211_scan_request *scan_request;
-       struct ieee80211_vif *scan_vif;
-       u8 scan_tx_ant[IEEE80211_NUM_BANDS];
-       u8 mgmt_tx_ant;
-
-       /* spinlock */
-       spinlock_t lock;        /* protect general shared data */
-       spinlock_t hcmd_lock;   /* protect hcmd */
-       spinlock_t reg_lock;    /* protect hw register access */
-       struct mutex mutex;
-
-       /* basic pci-network driver stuff */
-       struct pci_dev *pci_dev;
-
-       /* pci hardware address support */
-       void __iomem *hw_base;
-       u32  hw_rev;
-       u32  hw_wa_rev;
-       u8   rev_id;
-
-       /* microcode/device supports multiple contexts */
-       u8 valid_contexts;
-
-       /* command queue number */
-       u8 cmd_queue;
-
-       /* max number of station keys */
-       u8 sta_key_max_num;
-
-       /* EEPROM MAC addresses */
-       struct mac_address addresses[1];
-
-       /* uCode images, save to reload in case of failure */
-       int fw_index;                   /* firmware we're trying to load */
-       u32 ucode_ver;                  /* version of ucode, copy of
-                                          iwl_ucode.ver */
-       struct fw_desc ucode_code;      /* runtime inst */
-       struct fw_desc ucode_data;      /* runtime data original */
-       struct fw_desc ucode_data_backup;       /* runtime data save/restore */
-       struct fw_desc ucode_init;      /* initialization inst */
-       struct fw_desc ucode_init_data; /* initialization data */
-       struct fw_desc ucode_boot;      /* bootstrap inst */
-       enum ucode_type ucode_type;
-       u8 ucode_write_complete;        /* the image write is complete */
-       char firmware_name[25];
-
-       struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
-
-       __le16 switch_channel;
-
-       /* 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;
-
-       u16 active_rate;
-
-       u8 start_calib;
-       struct iwl_sensitivity_data sensitivity_data;
-       struct iwl_chain_noise_data chain_noise_data;
-       __le16 sensitivity_tbl[HD_TABLE_SIZE];
-
-       struct iwl_ht_config current_ht_config;
-
-       /* Rate scaling data */
-       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;
-       unsigned long txq_ctx_active_msk;
-       struct iwl_dma_ptr  kw; /* keep warm address */
-       struct iwl_dma_ptr  scd_bc_tbls;
-
-       u32 scd_base_addr;      /* scheduler sram base address */
-
-       unsigned long status;
-
-       /* counts mgmt, ctl, and data packets */
-       struct traffic_stats tx_stats;
-       struct traffic_stats rx_stats;
-
-       /* counts interrupts */
-       struct isr_statistics isr_stats;
-
-       struct iwl_power_mgr power_data;
-
-       /* context information */
-       u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */
-
-       /* station table variables */
-
-       /* Note: if lock and sta_lock are needed, lock must be acquired first */
-       spinlock_t sta_lock;
-       int num_stations;
-       struct iwl_station_entry stations[IWL_STATION_COUNT];
-       unsigned long ucode_key_table;
-
-       /* queue refcounts */
-#define IWL_MAX_HW_QUEUES      32
-       unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
-       /* for each AC */
-       atomic_t queue_stop_count[4];
-
-       /* Indication if ieee80211_ops->open has been called */
-       u8 is_open;
-
-       u8 mac80211_registered;
-
-       /* eeprom -- this is in the card's little endian byte order */
-       u8 *eeprom;
-       struct iwl_eeprom_calib_info *calib_info;
-
-       enum nl80211_iftype iw_mode;
-
-       /* Last Rx'd beacon timestamp */
-       u64 timestamp;
-
-       union {
-#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE)
-               struct {
-                       void *shared_virt;
-                       dma_addr_t shared_phys;
-
-                       struct delayed_work thermal_periodic;
-                       struct delayed_work rfkill_poll;
-
-                       struct iwl3945_notif_statistics statistics;
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-                       struct iwl3945_notif_statistics accum_statistics;
-                       struct iwl3945_notif_statistics delta_statistics;
-                       struct iwl3945_notif_statistics max_delta;
-#endif
-
-                       u32 sta_supp_rates;
-                       int last_rx_rssi;       /* From Rx packet statistics */
-
-                       /* Rx'd packet timing information */
-                       u32 last_beacon_time;
-                       u64 last_tsf;
-
-                       /*
-                        * each calibration channel group in the
-                        * EEPROM has a derived clip setting for
-                        * each rate.
-                        */
-                       const struct iwl3945_clip_group clip_groups[5];
-
-               } _3945;
-#endif
-#if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)
-               struct {
-                       struct iwl_rx_phy_res last_phy_res;
-                       bool last_phy_res_valid;
-
-                       struct completion firmware_loading_complete;
-
-                       /*
-                        * chain noise reset and gain commands are the
-                        * two extra calibration commands follows the standard
-                        * phy calibration commands
-                        */
-                       u8 phy_calib_chain_noise_reset_cmd;
-                       u8 phy_calib_chain_noise_gain_cmd;
-
-                       struct iwl_notif_statistics statistics;
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-                       struct iwl_notif_statistics accum_statistics;
-                       struct iwl_notif_statistics delta_statistics;
-                       struct iwl_notif_statistics max_delta;
-#endif
-
-               } _4965;
-#endif
-       };
-
-       struct iwl_hw_params hw_params;
-
-       u32 inta_mask;
-
-       struct workqueue_struct *workqueue;
-
-       struct work_struct restart;
-       struct work_struct scan_completed;
-       struct work_struct rx_replenish;
-       struct work_struct abort_scan;
-
-       struct iwl_rxon_context *beacon_ctx;
-       struct sk_buff *beacon_skb;
-
-       struct work_struct tx_flush;
-
-       struct tasklet_struct irq_tasklet;
-
-       struct delayed_work init_alive_start;
-       struct delayed_work alive_start;
-       struct delayed_work scan_check;
-
-       /* TX Power */
-       s8 tx_power_user_lmt;
-       s8 tx_power_device_lmt;
-       s8 tx_power_next;
-
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       /* debugging info */
-       u32 debug_level; /* per device debugging will override global
-                           iwlegacy_debug_level if set */
-#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
-       /* debugfs */
-       u16 tx_traffic_idx;
-       u16 rx_traffic_idx;
-       u8 *tx_traffic;
-       u8 *rx_traffic;
-       struct dentry *debugfs_dir;
-       u32 dbgfs_sram_offset, dbgfs_sram_len;
-       bool disable_ht40;
-#endif /* CONFIG_IWLWIFI_LEGACY_DEBUGFS */
-
-       struct work_struct txpower_work;
-       u32 disable_sens_cal;
-       u32 disable_chain_noise_cal;
-       u32 disable_tx_power_cal;
-       struct work_struct run_time_calib_work;
-       struct timer_list statistics_periodic;
-       struct timer_list watchdog;
-       bool hw_ready;
-
-       struct led_classdev led;
-       unsigned long blink_on, blink_off;
-       bool led_registered;
-}; /*iwl_priv */
-
-static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
-{
-       set_bit(txq_id, &priv->txq_ctx_active_msk);
-}
-
-static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
-{
-       clear_bit(txq_id, &priv->txq_ctx_active_msk);
-}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-/*
- * iwl_legacy_get_debug_level: Return active debug level for device
- *
- * Using sysfs it is possible to set per device debug level. This debug
- * level will be used if set, otherwise the global debug level which can be
- * set via module parameter is used.
- */
-static inline u32 iwl_legacy_get_debug_level(struct iwl_priv *priv)
-{
-       if (priv->debug_level)
-               return priv->debug_level;
-       else
-               return iwlegacy_debug_level;
-}
-#else
-static inline u32 iwl_legacy_get_debug_level(struct iwl_priv *priv)
-{
-       return iwlegacy_debug_level;
-}
-#endif
-
-
-static inline struct ieee80211_hdr *
-iwl_legacy_tx_queue_get_hdr(struct iwl_priv *priv,
-                                                int txq_id, int idx)
-{
-       if (priv->txq[txq_id].txb[idx].skb)
-               return (struct ieee80211_hdr *)priv->txq[txq_id].
-                               txb[idx].skb->data;
-       return NULL;
-}
-
-static inline struct iwl_rxon_context *
-iwl_legacy_rxon_ctx_from_vif(struct ieee80211_vif *vif)
-{
-       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-
-       return vif_priv->ctx;
-}
-
-#define for_each_context(priv, ctx)                            \
-       for (ctx = &priv->contexts[IWL_RXON_CTX_BSS];           \
-            ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++)    \
-               if (priv->valid_contexts & BIT(ctx->ctxid))
-
-static inline int iwl_legacy_is_associated(struct iwl_priv *priv,
-                                   enum iwl_rxon_context_id ctxid)
-{
-       return (priv->contexts[ctxid].active.filter_flags &
-                       RXON_FILTER_ASSOC_MSK) ? 1 : 0;
-}
-
-static inline int iwl_legacy_is_any_associated(struct iwl_priv *priv)
-{
-       return iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS);
-}
-
-static inline int iwl_legacy_is_associated_ctx(struct iwl_rxon_context *ctx)
-{
-       return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
-}
-
-static inline int iwl_legacy_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 inline int iwl_legacy_is_channel_radar(const struct iwl_channel_info *ch_info)
-{
-       return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
-}
-
-static inline u8 iwl_legacy_is_channel_a_band(const struct iwl_channel_info *ch_info)
-{
-       return ch_info->band == IEEE80211_BAND_5GHZ;
-}
-
-static inline int
-iwl_legacy_is_channel_passive(const struct iwl_channel_info *ch)
-{
-       return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
-}
-
-static inline int
-iwl_legacy_is_channel_ibss(const struct iwl_channel_info *ch)
-{
-       return (ch->flags & EEPROM_CHANNEL_IBSS) ? 1 : 0;
-}
-
-static inline void
-__iwl_legacy_free_pages(struct iwl_priv *priv, struct page *page)
-{
-       __free_pages(page, priv->hw_params.rx_page_order);
-       priv->alloc_rxb_page--;
-}
-
-static inline void iwl_legacy_free_pages(struct iwl_priv *priv, unsigned long page)
-{
-       free_pages(page, priv->hw_params.rx_page_order);
-       priv->alloc_rxb_page--;
-}
-#endif                         /* __iwl_legacy_dev_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.c b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
deleted file mode 100644 (file)
index acec991..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2009 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/module.h>
-
-/* sparse doesn't like tracepoint macros */
-#ifndef __CHECKER__
-#include "iwl-dev.h"
-
-#define CREATE_TRACE_POINTS
-#include "iwl-devtrace.h"
-
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite8);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ioread32);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite32);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_rx);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_tx);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_error);
-#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.h b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
deleted file mode 100644 (file)
index a443725..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2009 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#if !defined(__IWLWIFI_LEGACY_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
-#define __IWLWIFI_LEGACY_DEVICE_TRACE
-
-#include <linux/tracepoint.h>
-
-#if !defined(CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING) || defined(__CHECKER__)
-#undef TRACE_EVENT
-#define TRACE_EVENT(name, proto, ...) \
-static inline void trace_ ## name(proto) {}
-#endif
-
-
-#define PRIV_ENTRY     __field(struct iwl_priv *, priv)
-#define PRIV_ASSIGN    (__entry->priv = priv)
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM iwlwifi_legacy_io
-
-TRACE_EVENT(iwlwifi_legacy_dev_ioread32,
-       TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val),
-       TP_ARGS(priv, offs, val),
-       TP_STRUCT__entry(
-               PRIV_ENTRY
-               __field(u32, offs)
-               __field(u32, val)
-       ),
-       TP_fast_assign(
-               PRIV_ASSIGN;
-               __entry->offs = offs;
-               __entry->val = val;
-       ),
-       TP_printk("[%p] read io[%#x] = %#x", __entry->priv,
-                                       __entry->offs, __entry->val)
-);
-
-TRACE_EVENT(iwlwifi_legacy_dev_iowrite8,
-       TP_PROTO(struct iwl_priv *priv, u32 offs, u8 val),
-       TP_ARGS(priv, offs, val),
-       TP_STRUCT__entry(
-               PRIV_ENTRY
-               __field(u32, offs)
-               __field(u8, val)
-       ),
-       TP_fast_assign(
-               PRIV_ASSIGN;
-               __entry->offs = offs;
-               __entry->val = val;
-       ),
-       TP_printk("[%p] write io[%#x] = %#x)", __entry->priv,
-                                       __entry->offs, __entry->val)
-);
-
-TRACE_EVENT(iwlwifi_legacy_dev_iowrite32,
-       TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val),
-       TP_ARGS(priv, offs, val),
-       TP_STRUCT__entry(
-               PRIV_ENTRY
-               __field(u32, offs)
-               __field(u32, val)
-       ),
-       TP_fast_assign(
-               PRIV_ASSIGN;
-               __entry->offs = offs;
-               __entry->val = val;
-       ),
-       TP_printk("[%p] write io[%#x] = %#x)", __entry->priv,
-                                       __entry->offs, __entry->val)
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM iwlwifi_legacy_ucode
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM iwlwifi
-
-TRACE_EVENT(iwlwifi_legacy_dev_hcmd,
-       TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags),
-       TP_ARGS(priv, hcmd, len, flags),
-       TP_STRUCT__entry(
-               PRIV_ENTRY
-               __dynamic_array(u8, hcmd, len)
-               __field(u32, flags)
-       ),
-       TP_fast_assign(
-               PRIV_ASSIGN;
-               memcpy(__get_dynamic_array(hcmd), hcmd, len);
-               __entry->flags = flags;
-       ),
-       TP_printk("[%p] hcmd %#.2x (%ssync)",
-                 __entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0],
-                 __entry->flags & CMD_ASYNC ? "a" : "")
-);
-
-TRACE_EVENT(iwlwifi_legacy_dev_rx,
-       TP_PROTO(struct iwl_priv *priv, void *rxbuf, size_t len),
-       TP_ARGS(priv, rxbuf, len),
-       TP_STRUCT__entry(
-               PRIV_ENTRY
-               __dynamic_array(u8, rxbuf, len)
-       ),
-       TP_fast_assign(
-               PRIV_ASSIGN;
-               memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
-       ),
-       TP_printk("[%p] RX cmd %#.2x",
-                 __entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4])
-);
-
-TRACE_EVENT(iwlwifi_legacy_dev_tx,
-       TP_PROTO(struct iwl_priv *priv, void *tfd, size_t tfdlen,
-                void *buf0, size_t buf0_len,
-                void *buf1, size_t buf1_len),
-       TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
-       TP_STRUCT__entry(
-               PRIV_ENTRY
-
-               __field(size_t, framelen)
-               __dynamic_array(u8, tfd, tfdlen)
-
-               /*
-                * Do not insert between or below these items,
-                * we want to keep the frame together (except
-                * for the possible padding).
-                */
-               __dynamic_array(u8, buf0, buf0_len)
-               __dynamic_array(u8, buf1, buf1_len)
-       ),
-       TP_fast_assign(
-               PRIV_ASSIGN;
-               __entry->framelen = buf0_len + buf1_len;
-               memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
-               memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
-               memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
-       ),
-       TP_printk("[%p] TX %.2x (%zu bytes)",
-                 __entry->priv,
-                 ((u8 *)__get_dynamic_array(buf0))[0],
-                 __entry->framelen)
-);
-
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_error,
-       TP_PROTO(struct iwl_priv *priv, u32 desc, u32 time,
-                u32 data1, u32 data2, u32 line, u32 blink1,
-                u32 blink2, u32 ilink1, u32 ilink2),
-       TP_ARGS(priv, desc, time, data1, data2, line,
-               blink1, blink2, ilink1, ilink2),
-       TP_STRUCT__entry(
-               PRIV_ENTRY
-               __field(u32, desc)
-               __field(u32, time)
-               __field(u32, data1)
-               __field(u32, data2)
-               __field(u32, line)
-               __field(u32, blink1)
-               __field(u32, blink2)
-               __field(u32, ilink1)
-               __field(u32, ilink2)
-       ),
-       TP_fast_assign(
-               PRIV_ASSIGN;
-               __entry->desc = desc;
-               __entry->time = time;
-               __entry->data1 = data1;
-               __entry->data2 = data2;
-               __entry->line = line;
-               __entry->blink1 = blink1;
-               __entry->blink2 = blink2;
-               __entry->ilink1 = ilink1;
-               __entry->ilink2 = ilink2;
-       ),
-       TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, "
-                 "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X",
-                 __entry->priv, __entry->desc, __entry->time, __entry->data1,
-                 __entry->data2, __entry->line, __entry->blink1,
-                 __entry->blink2, __entry->ilink1, __entry->ilink2)
-);
-
-#endif /* __IWLWIFI_DEVICE_TRACE */
-
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_FILE iwl-devtrace
-#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-eeprom.c b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
deleted file mode 100644 (file)
index 5bf3f49..0000000
+++ /dev/null
@@ -1,553 +0,0 @@
-/******************************************************************************
- *
- * 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) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 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.
- *****************************************************************************/
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include <net/mac80211.h>
-
-#include "iwl-commands.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-debug.h"
-#include "iwl-eeprom.h"
-#include "iwl-io.h"
-
-/************************** EEPROM BANDS ****************************
- *
- * The iwlegacy_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 */
-const u8 iwlegacy_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 iwlegacy_eeprom_band_2[] = {   /* 4915-5080MHz */
-       183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
-};
-
-static const u8 iwlegacy_eeprom_band_3[] = {   /* 5170-5320MHz */
-       34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
-};
-
-static const u8 iwlegacy_eeprom_band_4[] = {   /* 5500-5700MHz */
-       100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
-};
-
-static const u8 iwlegacy_eeprom_band_5[] = {   /* 5725-5825MHz */
-       145, 149, 153, 157, 161, 165
-};
-
-static const u8 iwlegacy_eeprom_band_6[] = {       /* 2.4 ht40 channel */
-       1, 2, 3, 4, 5, 6, 7
-};
-
-static const u8 iwlegacy_eeprom_band_7[] = {       /* 5.2 ht40 channel */
-       36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
-};
-
-/******************************************************************************
- *
- * EEPROM related functions
- *
-******************************************************************************/
-
-static int iwl_legacy_eeprom_verify_signature(struct iwl_priv *priv)
-{
-       u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
-       int ret = 0;
-
-       IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp);
-       switch (gp) {
-       case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K:
-       case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K:
-               break;
-       default:
-               IWL_ERR(priv, "bad EEPROM signature,"
-                       "EEPROM_GP=0x%08x\n", gp);
-               ret = -ENOENT;
-               break;
-       }
-       return ret;
-}
-
-const u8
-*iwl_legacy_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
-{
-       BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
-       return &priv->eeprom[offset];
-}
-EXPORT_SYMBOL(iwl_legacy_eeprom_query_addr);
-
-u16 iwl_legacy_eeprom_query16(const struct iwl_priv *priv, size_t offset)
-{
-       if (!priv->eeprom)
-               return 0;
-       return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
-}
-EXPORT_SYMBOL(iwl_legacy_eeprom_query16);
-
-/**
- * iwl_legacy_eeprom_init - read EEPROM contents
- *
- * Load the EEPROM contents from adapter into priv->eeprom
- *
- * NOTE:  This routine uses the non-debug IO access functions.
- */
-int iwl_legacy_eeprom_init(struct iwl_priv *priv)
-{
-       __le16 *e;
-       u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
-       int sz;
-       int ret;
-       u16 addr;
-
-       /* allocate eeprom */
-       sz = priv->cfg->base_params->eeprom_size;
-       IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
-       priv->eeprom = kzalloc(sz, GFP_KERNEL);
-       if (!priv->eeprom) {
-               ret = -ENOMEM;
-               goto alloc_err;
-       }
-       e = (__le16 *)priv->eeprom;
-
-       priv->cfg->ops->lib->apm_ops.init(priv);
-
-       ret = iwl_legacy_eeprom_verify_signature(priv);
-       if (ret < 0) {
-               IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
-               ret = -ENOENT;
-               goto err;
-       }
-
-       /* Make sure driver (instead of uCode) is allowed to read EEPROM */
-       ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv);
-       if (ret < 0) {
-               IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n");
-               ret = -ENOENT;
-               goto err;
-       }
-
-       /* eeprom is an array of 16bit values */
-       for (addr = 0; addr < sz; addr += sizeof(u16)) {
-               u32 r;
-
-               _iwl_legacy_write32(priv, CSR_EEPROM_REG,
-                            CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
-
-               ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
-                                         CSR_EEPROM_REG_READ_VALID_MSK,
-                                         CSR_EEPROM_REG_READ_VALID_MSK,
-                                         IWL_EEPROM_ACCESS_TIMEOUT);
-               if (ret < 0) {
-                       IWL_ERR(priv, "Time out reading EEPROM[%d]\n",
-                                                       addr);
-                       goto done;
-               }
-               r = _iwl_legacy_read_direct32(priv, CSR_EEPROM_REG);
-               e[addr / 2] = cpu_to_le16(r >> 16);
-       }
-
-       IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n",
-                      "EEPROM",
-                      iwl_legacy_eeprom_query16(priv, EEPROM_VERSION));
-
-       ret = 0;
-done:
-       priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
-
-err:
-       if (ret)
-               iwl_legacy_eeprom_free(priv);
-       /* Reset chip to save power until we load uCode during "up". */
-       iwl_legacy_apm_stop(priv);
-alloc_err:
-       return ret;
-}
-EXPORT_SYMBOL(iwl_legacy_eeprom_init);
-
-void iwl_legacy_eeprom_free(struct iwl_priv *priv)
-{
-       kfree(priv->eeprom);
-       priv->eeprom = NULL;
-}
-EXPORT_SYMBOL(iwl_legacy_eeprom_free);
-
-static void iwl_legacy_init_band_reference(const struct iwl_priv *priv,
-                       int eep_band, int *eeprom_ch_count,
-                       const struct iwl_eeprom_channel **eeprom_ch_info,
-                       const u8 **eeprom_ch_index)
-{
-       u32 offset = priv->cfg->ops->lib->
-                       eeprom_ops.regulatory_bands[eep_band - 1];
-       switch (eep_band) {
-       case 1:         /* 2.4GHz band */
-               *eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_1);
-               *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_legacy_eeprom_query_addr(priv, offset);
-               *eeprom_ch_index = iwlegacy_eeprom_band_1;
-               break;
-       case 2:         /* 4.9GHz band */
-               *eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_2);
-               *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_legacy_eeprom_query_addr(priv, offset);
-               *eeprom_ch_index = iwlegacy_eeprom_band_2;
-               break;
-       case 3:         /* 5.2GHz band */
-               *eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_3);
-               *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_legacy_eeprom_query_addr(priv, offset);
-               *eeprom_ch_index = iwlegacy_eeprom_band_3;
-               break;
-       case 4:         /* 5.5GHz band */
-               *eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_4);
-               *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_legacy_eeprom_query_addr(priv, offset);
-               *eeprom_ch_index = iwlegacy_eeprom_band_4;
-               break;
-       case 5:         /* 5.7GHz band */
-               *eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_5);
-               *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_legacy_eeprom_query_addr(priv, offset);
-               *eeprom_ch_index = iwlegacy_eeprom_band_5;
-               break;
-       case 6:         /* 2.4GHz ht40 channels */
-               *eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_6);
-               *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_legacy_eeprom_query_addr(priv, offset);
-               *eeprom_ch_index = iwlegacy_eeprom_band_6;
-               break;
-       case 7:         /* 5 GHz ht40 channels */
-               *eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_7);
-               *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_legacy_eeprom_query_addr(priv, offset);
-               *eeprom_ch_index = iwlegacy_eeprom_band_7;
-               break;
-       default:
-               BUG();
-       }
-}
-
-#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
-                           ? # x " " : "")
-/**
- * iwl_legacy_mod_ht40_chan_info - Copy ht40 channel info into driver's priv.
- *
- * Does not set up a command, or touch hardware.
- */
-static int iwl_legacy_mod_ht40_chan_info(struct iwl_priv *priv,
-                             enum ieee80211_band band, u16 channel,
-                             const struct iwl_eeprom_channel *eeprom_ch,
-                             u8 clear_ht40_extension_channel)
-{
-       struct iwl_channel_info *ch_info;
-
-       ch_info = (struct iwl_channel_info *)
-                       iwl_legacy_get_channel_info(priv, band, channel);
-
-       if (!iwl_legacy_is_channel_valid(ch_info))
-               return -1;
-
-       IWL_DEBUG_EEPROM(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
-                       " Ad-Hoc %ssupported\n",
-                       ch_info->channel,
-                       iwl_legacy_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(DFS),
-                       eeprom_ch->flags,
-                       eeprom_ch->max_power_avg,
-                       ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS)
-                        && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
-                       "" : "not ");
-
-       ch_info->ht40_eeprom = *eeprom_ch;
-       ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
-       ch_info->ht40_flags = eeprom_ch->flags;
-       if (eeprom_ch->flags & EEPROM_CHANNEL_VALID)
-               ch_info->ht40_extension_channel &=
-                                       ~clear_ht40_extension_channel;
-
-       return 0;
-}
-
-#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
-                           ? # x " " : "")
-
-/**
- * iwl_legacy_init_channel_map - Set up driver's info for all possible channels
- */
-int iwl_legacy_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_EEPROM(priv, "Channel map already initialized.\n");
-               return 0;
-       }
-
-       IWL_DEBUG_EEPROM(priv, "Initializing regulatory info from EEPROM\n");
-
-       priv->channel_count =
-           ARRAY_SIZE(iwlegacy_eeprom_band_1) +
-           ARRAY_SIZE(iwlegacy_eeprom_band_2) +
-           ARRAY_SIZE(iwlegacy_eeprom_band_3) +
-           ARRAY_SIZE(iwlegacy_eeprom_band_4) +
-           ARRAY_SIZE(iwlegacy_eeprom_band_5);
-
-       IWL_DEBUG_EEPROM(priv, "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_ERR(priv, "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_legacy_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->band = (band == 1) ? IEEE80211_BAND_2GHZ :
-                           IEEE80211_BAND_5GHZ;
-
-                       /* 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;
-                       /* First write that ht40 is not enabled, and then enable
-                        * one by one */
-                       ch_info->ht40_extension_channel =
-                                       IEEE80211_CHAN_NO_HT40;
-
-                       if (!(iwl_legacy_is_channel_valid(ch_info))) {
-                               IWL_DEBUG_EEPROM(priv,
-                                              "Ch. %d Flags %x [%sGHz] - "
-                                              "No traffic\n",
-                                              ch_info->channel,
-                                              ch_info->flags,
-                                              iwl_legacy_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_EEPROM(priv, "Ch. %d [%sGHz] "
-                                      "%s%s%s%s%s%s(0x%02x %ddBm):"
-                                      " Ad-Hoc %ssupported\n",
-                                      ch_info->channel,
-                                      iwl_legacy_is_channel_a_band(ch_info) ?
-                                      "5.2" : "2.4",
-                                      CHECK_AND_PRINT_I(VALID),
-                                      CHECK_AND_PRINT_I(IBSS),
-                                      CHECK_AND_PRINT_I(ACTIVE),
-                                      CHECK_AND_PRINT_I(RADAR),
-                                      CHECK_AND_PRINT_I(WIDE),
-                                      CHECK_AND_PRINT_I(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 ");
-
-                       ch_info++;
-               }
-       }
-
-       /* Check if we do have HT40 channels */
-       if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] ==
-           EEPROM_REGULATORY_BAND_NO_HT40 &&
-           priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] ==
-           EEPROM_REGULATORY_BAND_NO_HT40)
-               return 0;
-
-       /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
-       for (band = 6; band <= 7; band++) {
-               enum ieee80211_band ieeeband;
-
-               iwl_legacy_init_band_reference(priv, band, &eeprom_ch_count,
-                                       &eeprom_ch_info, &eeprom_ch_index);
-
-               /* EEPROM band 6 is 2.4, band 7 is 5 GHz */
-               ieeeband =
-                       (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-
-               /* Loop through each band adding each of the channels */
-               for (ch = 0; ch < eeprom_ch_count; ch++) {
-                       /* Set up driver's info for lower half */
-                       iwl_legacy_mod_ht40_chan_info(priv, ieeeband,
-                                               eeprom_ch_index[ch],
-                                               &eeprom_ch_info[ch],
-                                               IEEE80211_CHAN_NO_HT40PLUS);
-
-                       /* Set up driver's info for upper half */
-                       iwl_legacy_mod_ht40_chan_info(priv, ieeeband,
-                                               eeprom_ch_index[ch] + 4,
-                                               &eeprom_ch_info[ch],
-                                               IEEE80211_CHAN_NO_HT40MINUS);
-               }
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_init_channel_map);
-
-/*
- * iwl_legacy_free_channel_map - undo allocations in iwl_legacy_init_channel_map
- */
-void iwl_legacy_free_channel_map(struct iwl_priv *priv)
-{
-       kfree(priv->channel_info);
-       priv->channel_count = 0;
-}
-EXPORT_SYMBOL(iwl_legacy_free_channel_map);
-
-/**
- * iwl_legacy_get_channel_info - Find driver's private channel info
- *
- * Based on band and channel number.
- */
-const struct
-iwl_channel_info *iwl_legacy_get_channel_info(const struct iwl_priv *priv,
-                                       enum ieee80211_band band, u16 channel)
-{
-       int i;
-
-       switch (band) {
-       case IEEE80211_BAND_5GHZ:
-               for (i = 14; i < priv->channel_count; i++) {
-                       if (priv->channel_info[i].channel == channel)
-                               return &priv->channel_info[i];
-               }
-               break;
-       case IEEE80211_BAND_2GHZ:
-               if (channel >= 1 && channel <= 14)
-                       return &priv->channel_info[channel - 1];
-               break;
-       default:
-               BUG();
-       }
-
-       return NULL;
-}
-EXPORT_SYMBOL(iwl_legacy_get_channel_info);
diff --git a/drivers/net/wireless/iwlegacy/iwl-eeprom.h b/drivers/net/wireless/iwlegacy/iwl-eeprom.h
deleted file mode 100644 (file)
index c59c810..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/******************************************************************************
- *
- * 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) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 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_legacy_eeprom_h__
-#define __iwl_legacy_eeprom_h__
-
-#include <net/mac80211.h>
-
-struct iwl_priv;
-
-/*
- * EEPROM access time values:
- *
- * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG.
- * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
- * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
- * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
- */
-#define IWL_EEPROM_ACCESS_TIMEOUT      5000 /* uSec */
-
-#define IWL_EEPROM_SEM_TIMEOUT         10   /* microseconds */
-#define IWL_EEPROM_SEM_RETRY_LIMIT     1000 /* number of attempts (not time) */
-
-
-/*
- * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags.
- *
- * IBSS and/or AP operation is allowed *only* on those channels with
- * (VALID && IBSS && ACTIVE && !RADAR).  This restriction is in place because
- * RADAR detection is not supported by the 4965 driver, but is a
- * requirement for establishing a new network for legal operation on channels
- * requiring RADAR detection or restricting ACTIVE scanning.
- *
- * NOTE:  "WIDE" flag does not indicate anything about "HT40" 40 MHz channels.
- *        It only indicates that 20 MHz channel use is supported; HT40 channel
- *        usage is indicated by a separate set of regulatory flags for each
- *        HT40 channel pair.
- *
- * NOTE:  Using a channel inappropriately will result in a uCode error!
- */
-#define IWL_NUM_TX_CALIB_GROUPS 5
-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),         /* 20 MHz channel okay */
-       /* Bit 6 Reserved (was Narrow Channel) */
-       EEPROM_CHANNEL_DFS = (1 << 7),  /* dynamic freq selection candidate */
-};
-
-/* SKU Capabilities */
-/* 3945 only */
-#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE                (1 << 0)
-#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
-
-/* *regulatory* channel data format in eeprom, one for each channel.
- * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */
-struct iwl_eeprom_channel {
-       u8 flags;               /* EEPROM_CHANNEL_* flags copied from EEPROM */
-       s8 max_power_avg;       /* max power (dBm) on this chnl, limit 31 */
-} __packed;
-
-/* 3945 Specific */
-#define EEPROM_3945_EEPROM_VERSION     (0x2f)
-
-/* 4965 has two radio transmitters (and 3 radio receivers) */
-#define EEPROM_TX_POWER_TX_CHAINS      (2)
-
-/* 4965 has room for up to 8 sets of txpower calibration data */
-#define EEPROM_TX_POWER_BANDS          (8)
-
-/* 4965 factory calibration measures txpower gain settings for
- * each of 3 target output levels */
-#define EEPROM_TX_POWER_MEASUREMENTS   (3)
-
-/* 4965 Specific */
-/* 4965 driver does not work with txpower calibration version < 5 */
-#define EEPROM_4965_TX_POWER_VERSION    (5)
-#define EEPROM_4965_EEPROM_VERSION     (0x2f)
-#define EEPROM_4965_CALIB_VERSION_OFFSET       (2*0xB6) /* 2 bytes */
-#define EEPROM_4965_CALIB_TXPOWER_OFFSET       (2*0xE8) /* 48  bytes */
-#define EEPROM_4965_BOARD_REVISION             (2*0x4F) /* 2 bytes */
-#define EEPROM_4965_BOARD_PBA                  (2*0x56+1) /* 9 bytes */
-
-/* 2.4 GHz */
-extern const u8 iwlegacy_eeprom_band_1[14];
-
-/*
- * factory calibration data for one txpower level, on one channel,
- * measured on one of the 2 tx chains (radio transmitter and associated
- * antenna).  EEPROM contains:
- *
- * 1)  Temperature (degrees Celsius) of device when measurement was made.
- *
- * 2)  Gain table index used to achieve the target measurement power.
- *     This refers to the "well-known" gain tables (see iwl-4965-hw.h).
- *
- * 3)  Actual measured output power, in half-dBm ("34" = 17 dBm).
- *
- * 4)  RF power amplifier detector level measurement (not used).
- */
-struct iwl_eeprom_calib_measure {
-       u8 temperature;         /* Device temperature (Celsius) */
-       u8 gain_idx;            /* Index into gain table */
-       u8 actual_pow;          /* Measured RF output power, half-dBm */
-       s8 pa_det;              /* Power amp detector level (not used) */
-} __packed;
-
-
-/*
- * measurement set for one channel.  EEPROM contains:
- *
- * 1)  Channel number measured
- *
- * 2)  Measurements for each of 3 power levels for each of 2 radio transmitters
- *     (a.k.a. "tx chains") (6 measurements altogether)
- */
-struct iwl_eeprom_calib_ch_info {
-       u8 ch_num;
-       struct iwl_eeprom_calib_measure
-               measurements[EEPROM_TX_POWER_TX_CHAINS]
-                       [EEPROM_TX_POWER_MEASUREMENTS];
-} __packed;
-
-/*
- * txpower subband info.
- *
- * For each frequency subband, EEPROM contains the following:
- *
- * 1)  First and last channels within range of the subband.  "0" values
- *     indicate that this sample set is not being used.
- *
- * 2)  Sample measurement sets for 2 channels close to the range endpoints.
- */
-struct iwl_eeprom_calib_subband_info {
-       u8 ch_from;     /* channel number of lowest channel in subband */
-       u8 ch_to;       /* channel number of highest channel in subband */
-       struct iwl_eeprom_calib_ch_info ch1;
-       struct iwl_eeprom_calib_ch_info ch2;
-} __packed;
-
-
-/*
- * txpower calibration info.  EEPROM contains:
- *
- * 1)  Factory-measured saturation power levels (maximum levels at which
- *     tx power amplifier can output a signal without too much distortion).
- *     There is one level for 2.4 GHz band and one for 5 GHz band.  These
- *     values apply to all channels within each of the bands.
- *
- * 2)  Factory-measured power supply voltage level.  This is assumed to be
- *     constant (i.e. same value applies to all channels/bands) while the
- *     factory measurements are being made.
- *
- * 3)  Up to 8 sets of factory-measured txpower calibration values.
- *     These are for different frequency ranges, since txpower gain
- *     characteristics of the analog radio circuitry vary with frequency.
- *
- *     Not all sets need to be filled with data;
- *     struct iwl_eeprom_calib_subband_info contains range of channels
- *     (0 if unused) for each set of data.
- */
-struct iwl_eeprom_calib_info {
-       u8 saturation_power24;  /* half-dBm (e.g. "34" = 17 dBm) */
-       u8 saturation_power52;  /* half-dBm */
-       __le16 voltage;         /* signed */
-       struct iwl_eeprom_calib_subband_info
-               band_info[EEPROM_TX_POWER_BANDS];
-} __packed;
-
-
-/* General */
-#define EEPROM_DEVICE_ID                    (2*0x08)   /* 2 bytes */
-#define EEPROM_MAC_ADDRESS                  (2*0x15)   /* 6  bytes */
-#define EEPROM_BOARD_REVISION               (2*0x35)   /* 2  bytes */
-#define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1) /* 9  bytes */
-#define EEPROM_VERSION                      (2*0x44)   /* 2  bytes */
-#define EEPROM_SKU_CAP                      (2*0x45)   /* 2  bytes */
-#define EEPROM_OEM_MODE                     (2*0x46)   /* 2  bytes */
-#define EEPROM_WOWLAN_MODE                  (2*0x47)   /* 2  bytes */
-#define EEPROM_RADIO_CONFIG                 (2*0x48)   /* 2  bytes */
-#define EEPROM_NUM_MAC_ADDRESS              (2*0x4C)   /* 2  bytes */
-
-/* The following masks are to be applied on EEPROM_RADIO_CONFIG */
-#define EEPROM_RF_CFG_TYPE_MSK(x)   (x & 0x3)         /* bits 0-1   */
-#define EEPROM_RF_CFG_STEP_MSK(x)   ((x >> 2)  & 0x3) /* bits 2-3   */
-#define EEPROM_RF_CFG_DASH_MSK(x)   ((x >> 4)  & 0x3) /* bits 4-5   */
-#define EEPROM_RF_CFG_PNUM_MSK(x)   ((x >> 6)  & 0x3) /* bits 6-7   */
-#define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8)  & 0xF) /* bits 8-11  */
-#define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
-
-#define EEPROM_3945_RF_CFG_TYPE_MAX  0x0
-#define EEPROM_4965_RF_CFG_TYPE_MAX  0x1
-
-/*
- * Per-channel regulatory data.
- *
- * Each channel that *might* be supported by iwl has a fixed location
- * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
- * txpower (MSB).
- *
- * Entries immediately below are for 20 MHz channel width.  HT40 (40 MHz)
- * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
- *
- * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
- */
-#define EEPROM_REGULATORY_SKU_ID            (2*0x60)    /* 4  bytes */
-#define EEPROM_REGULATORY_BAND_1            (2*0x62)   /* 2  bytes */
-#define EEPROM_REGULATORY_BAND_1_CHANNELS   (2*0x63)   /* 28 bytes */
-
-/*
- * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
- * 5.0 GHz channels 7, 8, 11, 12, 16
- * (4915-5080MHz) (none of these is ever supported)
- */
-#define EEPROM_REGULATORY_BAND_2            (2*0x71)   /* 2  bytes */
-#define EEPROM_REGULATORY_BAND_2_CHANNELS   (2*0x72)   /* 26 bytes */
-
-/*
- * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
- * (5170-5320MHz)
- */
-#define EEPROM_REGULATORY_BAND_3            (2*0x7F)   /* 2  bytes */
-#define EEPROM_REGULATORY_BAND_3_CHANNELS   (2*0x80)   /* 24 bytes */
-
-/*
- * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
- * (5500-5700MHz)
- */
-#define EEPROM_REGULATORY_BAND_4            (2*0x8C)   /* 2  bytes */
-#define EEPROM_REGULATORY_BAND_4_CHANNELS   (2*0x8D)   /* 22 bytes */
-
-/*
- * 5.7 GHz channels 145, 149, 153, 157, 161, 165
- * (5725-5825MHz)
- */
-#define EEPROM_REGULATORY_BAND_5            (2*0x98)   /* 2  bytes */
-#define EEPROM_REGULATORY_BAND_5_CHANNELS   (2*0x99)   /* 12 bytes */
-
-/*
- * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
- *
- * The channel listed is the center of the lower 20 MHz half of the channel.
- * The overall center frequency is actually 2 channels (10 MHz) above that,
- * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away
- * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5,
- * and the overall HT40 channel width centers on channel 3.
- *
- * NOTE:  The RXON command uses 20 MHz channel numbers to specify the
- *        control channel to which to tune.  RXON also specifies whether the
- *        control channel is the upper or lower half of a HT40 channel.
- *
- * NOTE:  4965 does not support HT40 channels on 2.4 GHz.
- */
-#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0)  /* 14 bytes */
-
-/*
- * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64),
- * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
- */
-#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8)  /* 22 bytes */
-
-#define EEPROM_REGULATORY_BAND_NO_HT40                 (0)
-
-struct iwl_eeprom_ops {
-       const u32 regulatory_bands[7];
-       int (*acquire_semaphore) (struct iwl_priv *priv);
-       void (*release_semaphore) (struct iwl_priv *priv);
-};
-
-
-int iwl_legacy_eeprom_init(struct iwl_priv *priv);
-void iwl_legacy_eeprom_free(struct iwl_priv *priv);
-const u8 *iwl_legacy_eeprom_query_addr(const struct iwl_priv *priv,
-                                       size_t offset);
-u16 iwl_legacy_eeprom_query16(const struct iwl_priv *priv, size_t offset);
-int iwl_legacy_init_channel_map(struct iwl_priv *priv);
-void iwl_legacy_free_channel_map(struct iwl_priv *priv);
-const struct iwl_channel_info *iwl_legacy_get_channel_info(
-               const struct iwl_priv *priv,
-               enum ieee80211_band band, u16 channel);
-
-#endif  /* __iwl_legacy_eeprom_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-fh.h b/drivers/net/wireless/iwlegacy/iwl-fh.h
deleted file mode 100644 (file)
index 6e60918..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-/******************************************************************************
- *
- * 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 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 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_legacy_fh_h__
-#define __iwl_legacy_fh_h__
-
-/****************************/
-/* Flow Handler Definitions */
-/****************************/
-
-/**
- * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
- * Addresses are offsets from device's PCI hardware base address.
- */
-#define FH_MEM_LOWER_BOUND                   (0x1000)
-#define FH_MEM_UPPER_BOUND                   (0x2000)
-
-/**
- * Keep-Warm (KW) buffer base address.
- *
- * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the
- * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency
- * DRAM access when 4965 is Txing or Rxing.  The dummy accesses prevent host
- * from going into a power-savings mode that would cause higher DRAM latency,
- * and possible data over/under-runs, before all Tx/Rx is complete.
- *
- * Driver loads FH_KW_MEM_ADDR_REG with the physical address (bits 35:4)
- * of the buffer, which must be 4K aligned.  Once this is set up, the 4965
- * automatically invokes keep-warm accesses when normal accesses might not
- * be sufficient to maintain fast DRAM response.
- *
- * Bit fields:
- *  31-0:  Keep-warm buffer physical base address [35:4], must be 4K aligned
- */
-#define FH_KW_MEM_ADDR_REG                  (FH_MEM_LOWER_BOUND + 0x97C)
-
-
-/**
- * TFD Circular Buffers Base (CBBC) addresses
- *
- * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident
- * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)
- * (see struct iwl_tfd_frame).  These 16 pointer registers are offset by 0x04
- * bytes from one another.  Each TFD circular buffer in DRAM must be 256-byte
- * aligned (address bits 0-7 must be 0).
- *
- * Bit fields in each pointer register:
- *  27-0: TFD CB physical base address [35:8], must be 256-byte aligned
- */
-#define FH_MEM_CBBC_LOWER_BOUND          (FH_MEM_LOWER_BOUND + 0x9D0)
-#define FH_MEM_CBBC_UPPER_BOUND          (FH_MEM_LOWER_BOUND + 0xA10)
-
-/* Find TFD CB base pointer for given queue (range 0-15). */
-#define FH_MEM_CBBC_QUEUE(x)  (FH_MEM_CBBC_LOWER_BOUND + (x) * 0x4)
-
-
-/**
- * Rx SRAM Control and Status Registers (RSCSR)
- *
- * These registers provide handshake between driver and 4965 for the Rx queue
- * (this queue handles *all* command responses, notifications, Rx data, etc.
- * sent from 4965 uCode to host driver).  Unlike Tx, there is only one Rx
- * queue, and only one Rx DMA/FIFO channel.  Also unlike Tx, which can
- * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer
- * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1
- * mapping between RBDs and RBs.
- *
- * Driver must allocate host DRAM memory for the following, and set the
- * physical address of each into 4965 registers:
- *
- * 1)  Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256
- *     entries (although any power of 2, up to 4096, is selectable by driver).
- *     Each entry (1 dword) points to a receive buffer (RB) of consistent size
- *     (typically 4K, although 8K or 16K are also selectable by driver).
- *     Driver sets up RB size and number of RBDs in the CB via Rx config
- *     register FH_MEM_RCSR_CHNL0_CONFIG_REG.
- *
- *     Bit fields within one RBD:
- *     27-0:  Receive Buffer physical address bits [35:8], 256-byte aligned
- *
- *     Driver sets physical address [35:8] of base of RBD circular buffer
- *     into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].
- *
- * 2)  Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers
- *     (RBs) have been filled, via a "write pointer", actually the index of
- *     the RB's corresponding RBD within the circular buffer.  Driver sets
- *     physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0].
- *
- *     Bit fields in lower dword of Rx status buffer (upper dword not used
- *     by driver; see struct iwl4965_shared, val0):
- *     31-12:  Not used by driver
- *     11- 0:  Index of last filled Rx buffer descriptor
- *             (4965 writes, driver reads this value)
- *
- * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must
- * enter pointers to these RBs into contiguous RBD circular buffer entries,
- * and update the 4965's "write" index register,
- * FH_RSCSR_CHNL0_RBDCB_WPTR_REG.
- *
- * This "write" index corresponds to the *next* RBD that the driver will make
- * available, i.e. one RBD past the tail of the ready-to-fill RBDs within
- * the circular buffer.  This value should initially be 0 (before preparing any
- * RBs), should be 8 after preparing the first 8 RBs (for example), and must
- * wrap back to 0 at the end of the circular buffer (but don't wrap before
- * "read" index has advanced past 1!  See below).
- * NOTE:  4965 EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8.
- *
- * As the 4965 fills RBs (referenced from contiguous RBDs within the circular
- * buffer), it updates the Rx status buffer in host DRAM, 2) described above,
- * to tell the driver the index of the latest filled RBD.  The driver must
- * read this "read" index from DRAM after receiving an Rx interrupt from 4965.
- *
- * The driver must also internally keep track of a third index, which is the
- * next RBD to process.  When receiving an Rx interrupt, driver should process
- * all filled but unprocessed RBs up to, but not including, the RB
- * corresponding to the "read" index.  For example, if "read" index becomes "1",
- * driver may process the RB pointed to by RBD 0.  Depending on volume of
- * traffic, there may be many RBs to process.
- *
- * If read index == write index, 4965 thinks there is no room to put new data.
- * Due to this, the maximum number of filled RBs is 255, instead of 256.  To
- * be safe, make sure that there is a gap of at least 2 RBDs between "write"
- * and "read" indexes; that is, make sure that there are no more than 254
- * buffers waiting to be filled.
- */
-#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)
-
-/**
- * Physical base address of 8-byte Rx Status buffer.
- * Bit fields:
- *  31-0: Rx status buffer physical base address [35:4], must 16-byte aligned.
- */
-#define FH_RSCSR_CHNL0_STTS_WPTR_REG   (FH_MEM_RSCSR_CHNL0)
-
-/**
- * Physical base address of Rx Buffer Descriptor Circular Buffer.
- * Bit fields:
- *  27-0:  RBD CD physical base address [35:8], must be 256-byte aligned.
- */
-#define FH_RSCSR_CHNL0_RBDCB_BASE_REG  (FH_MEM_RSCSR_CHNL0 + 0x004)
-
-/**
- * Rx write pointer (index, really!).
- * Bit fields:
- *  11-0:  Index of driver's most recent prepared-to-be-filled RBD, + 1.
- *         NOTE:  For 256-entry circular buffer, use only bits [7:0].
- */
-#define FH_RSCSR_CHNL0_RBDCB_WPTR_REG  (FH_MEM_RSCSR_CHNL0 + 0x008)
-#define FH_RSCSR_CHNL0_WPTR        (FH_RSCSR_CHNL0_RBDCB_WPTR_REG)
-
-
-/**
- * Rx Config/Status Registers (RCSR)
- * Rx Config Reg for channel 0 (only channel used)
- *
- * Driver must initialize FH_MEM_RCSR_CHNL0_CONFIG_REG as follows for
- * normal operation (see bit fields).
- *
- * Clearing FH_MEM_RCSR_CHNL0_CONFIG_REG to 0 turns off Rx DMA.
- * Driver should poll FH_MEM_RSSR_RX_STATUS_REG        for
- * FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (bit 24) before continuing.
- *
- * Bit fields:
- * 31-30: Rx DMA channel enable: '00' off/pause, '01' pause at end of frame,
- *        '10' operate normally
- * 29-24: reserved
- * 23-20: # RBDs in circular buffer = 2^value; use "8" for 256 RBDs (normal),
- *        min "5" for 32 RBDs, max "12" for 4096 RBDs.
- * 19-18: reserved
- * 17-16: size of each receive buffer; '00' 4K (normal), '01' 8K,
- *        '10' 12K, '11' 16K.
- * 15-14: reserved
- * 13-12: IRQ destination; '00' none, '01' host driver (normal operation)
- * 11- 4: timeout for closing Rx buffer and interrupting host (units 32 usec)
- *        typical value 0x10 (about 1/2 msec)
- *  3- 0: reserved
- */
-#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_CHNL0_CONFIG_REG   (FH_MEM_RCSR_CHNL0)
-
-#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0) /* bits 4-11 */
-#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK   (0x00001000) /* bits 12 */
-#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK (0x00008000) /* bit 15 */
-#define FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MSK   (0x00030000) /* bits 16-17 */
-#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000) /* bits 20-23 */
-#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31*/
-
-#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS       (20)
-#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS     (4)
-#define RX_RB_TIMEOUT  (0x10)
-
-#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_REG_VAL_RB_SIZE_4K    (0x00000000)
-#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K    (0x00010000)
-#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K   (0x00020000)
-#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K   (0x00030000)
-
-#define FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY              (0x00000004)
-#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL    (0x00000000)
-#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL  (0x00001000)
-
-#define FH_RSCSR_FRAME_SIZE_MSK        (0x00003FFF)    /* bits 0-13 */
-
-/**
- * Rx Shared Status Registers (RSSR)
- *
- * After stopping Rx DMA channel (writing 0 to
- * FH_MEM_RCSR_CHNL0_CONFIG_REG), driver must poll
- * FH_MEM_RSSR_RX_STATUS_REG until Rx channel is idle.
- *
- * Bit fields:
- *  24:  1 = Channel 0 is idle
- *
- * FH_MEM_RSSR_SHARED_CTRL_REG and FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV
- * contain default values that should not be altered by the driver.
- */
-#define FH_MEM_RSSR_LOWER_BOUND           (FH_MEM_LOWER_BOUND + 0xC40)
-#define FH_MEM_RSSR_UPPER_BOUND           (FH_MEM_LOWER_BOUND + 0xD00)
-
-#define FH_MEM_RSSR_SHARED_CTRL_REG       (FH_MEM_RSSR_LOWER_BOUND)
-#define FH_MEM_RSSR_RX_STATUS_REG      (FH_MEM_RSSR_LOWER_BOUND + 0x004)
-#define FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV\
-                                       (FH_MEM_RSSR_LOWER_BOUND + 0x008)
-
-#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE      (0x01000000)
-
-#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT        28
-
-/* TFDB  Area - TFDs buffer table */
-#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK      (0xFFFFFFFF)
-#define FH_TFDIB_LOWER_BOUND       (FH_MEM_LOWER_BOUND + 0x900)
-#define FH_TFDIB_UPPER_BOUND       (FH_MEM_LOWER_BOUND + 0x958)
-#define FH_TFDIB_CTRL0_REG(_chnl)  (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
-#define FH_TFDIB_CTRL1_REG(_chnl)  (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
-
-/**
- * Transmit DMA Channel Control/Status Registers (TCSR)
- *
- * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels
- * supported in hardware (don't confuse these with the 16 Tx queues in DRAM,
- * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes.
- *
- * To use a Tx DMA channel, driver must initialize its
- * FH_TCSR_CHNL_TX_CONFIG_REG(chnl) with:
- *
- * FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
- * FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL
- *
- * All other bits should be 0.
- *
- * Bit fields:
- * 31-30: Tx DMA channel enable: '00' off/pause, '01' pause at end of frame,
- *        '10' operate normally
- * 29- 4: Reserved, set to "0"
- *     3: Enable internal DMA requests (1, normal operation), disable (0)
- *  2- 0: Reserved, set to "0"
- */
-#define FH_TCSR_LOWER_BOUND  (FH_MEM_LOWER_BOUND + 0xD00)
-#define FH_TCSR_UPPER_BOUND  (FH_MEM_LOWER_BOUND + 0xE60)
-
-/* Find Control/Status reg for given Tx DMA/FIFO channel */
-#define FH49_TCSR_CHNL_NUM                            (7)
-#define FH50_TCSR_CHNL_NUM                            (8)
-
-/* TCSR: tx_config register values */
-#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl)      \
-               (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl))
-#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl)      \
-               (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x4)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl)     \
-               (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x8)
-
-#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF         (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRV         (0x00000001)
-
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE   (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE    (0x00000008)
-
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT      (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD     (0x00100000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD      (0x00200000)
-
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT       (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD      (0x00400000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD       (0x00800000)
-
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE       (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF   (0x40000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE      (0x80000000)
-
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY     (0x00000000)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT      (0x00002000)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID     (0x00000003)
-
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM         (20)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX         (12)
-
-/**
- * Tx Shared Status Registers (TSSR)
- *
- * After stopping Tx DMA channel (writing 0 to
- * FH_TCSR_CHNL_TX_CONFIG_REG(chnl)), driver must poll
- * FH_TSSR_TX_STATUS_REG until selected Tx channel is idle
- * (channel's buffers empty | no pending requests).
- *
- * Bit fields:
- * 31-24:  1 = Channel buffers empty (channel 7:0)
- * 23-16:  1 = No pending requests (channel 7:0)
- */
-#define FH_TSSR_LOWER_BOUND            (FH_MEM_LOWER_BOUND + 0xEA0)
-#define FH_TSSR_UPPER_BOUND            (FH_MEM_LOWER_BOUND + 0xEC0)
-
-#define FH_TSSR_TX_STATUS_REG          (FH_TSSR_LOWER_BOUND + 0x010)
-
-/**
- * Bit fields for TSSR(Tx Shared Status & Control) error status register:
- * 31:  Indicates an address error when accessed to internal memory
- *     uCode/driver must write "1" in order to clear this flag
- * 30:  Indicates that Host did not send the expected number of dwords to FH
- *     uCode/driver must write "1" in order to clear this flag
- * 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA
- *     command was received from the scheduler while the TRB was already full
- *     with previous command
- *     uCode/driver must write "1" in order to clear this flag
- * 7-0: Each status bit indicates a channel's TxCredit error. When an error
- *     bit is set, it indicates that the FH has received a full indication
- *     from the RTC TxFIFO and the current value of the TxCredit counter was
- *     not equal to zero. This mean that the credit mechanism was not
- *     synchronized to the TxFIFO status
- *     uCode/driver must write "1" in order to clear this flag
- */
-#define FH_TSSR_TX_ERROR_REG           (FH_TSSR_LOWER_BOUND + 0x018)
-
-#define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16)
-
-/* Tx service channels */
-#define FH_SRVC_CHNL           (9)
-#define FH_SRVC_LOWER_BOUND    (FH_MEM_LOWER_BOUND + 0x9C8)
-#define FH_SRVC_UPPER_BOUND    (FH_MEM_LOWER_BOUND + 0x9D0)
-#define FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \
-               (FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4)
-
-#define FH_TX_CHICKEN_BITS_REG (FH_MEM_LOWER_BOUND + 0xE98)
-/* Instruct FH to increment the retry count of a packet when
- * it is brought from the memory to TX-FIFO
- */
-#define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN   (0x00000002)
-
-#define RX_QUEUE_SIZE                         256
-#define RX_QUEUE_MASK                         255
-#define RX_QUEUE_SIZE_LOG                     8
-
-/*
- * RX related structures and functions
- */
-#define RX_FREE_BUFFERS 64
-#define RX_LOW_WATERMARK 8
-
-/* Size of one Rx buffer in host DRAM */
-#define IWL_RX_BUF_SIZE_3K (3 * 1000) /* 3945 only */
-#define IWL_RX_BUF_SIZE_4K (4 * 1024)
-#define IWL_RX_BUF_SIZE_8K (8 * 1024)
-
-/**
- * struct iwl_rb_status - reseve buffer status
- *     host memory mapped FH registers
- * @closed_rb_num [0:11] - Indicates the index of the RB which was closed
- * @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed
- * @finished_rb_num [0:11] - Indicates the index of the current RB
- *     in which the last frame was written to
- * @finished_fr_num [0:11] - Indicates the index of the RX Frame
- *     which was transferred
- */
-struct iwl_rb_status {
-       __le16 closed_rb_num;
-       __le16 closed_fr_num;
-       __le16 finished_rb_num;
-       __le16 finished_fr_nam;
-       __le32 __unused; /* 3945 only */
-} __packed;
-
-
-#define TFD_QUEUE_SIZE_MAX      (256)
-#define TFD_QUEUE_SIZE_BC_DUP  (64)
-#define TFD_QUEUE_BC_SIZE      (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
-#define IWL_TX_DMA_MASK        DMA_BIT_MASK(36)
-#define IWL_NUM_OF_TBS         20
-
-static inline u8 iwl_legacy_get_dma_hi_addr(dma_addr_t addr)
-{
-       return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
-}
-/**
- * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
- *
- * This structure contains dma address and length of transmission address
- *
- * @lo: low [31:0] portion of the dma address of TX buffer
- *     every even is unaligned on 16 bit boundary
- * @hi_n_len 0-3 [35:32] portion of dma
- *          4-15 length of the tx buffer
- */
-struct iwl_tfd_tb {
-       __le32 lo;
-       __le16 hi_n_len;
-} __packed;
-
-/**
- * struct iwl_tfd
- *
- * Transmit Frame Descriptor (TFD)
- *
- * @ __reserved1[3] reserved
- * @ num_tbs 0-4 number of active tbs
- *          5   reserved
- *          6-7 padding (not used)
- * @ tbs[20]   transmit frame buffer descriptors
- * @ __pad     padding
- *
- * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
- * Both driver and device share these circular buffers, each of which must be
- * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
- *
- * Driver must indicate the physical address of the base of each
- * circular buffer via the FH_MEM_CBBC_QUEUE registers.
- *
- * Each TFD contains pointer/size information for up to 20 data buffers
- * in host DRAM.  These buffers collectively contain the (one) frame described
- * by the TFD.  Each buffer must be a single contiguous block of memory within
- * itself, but buffers may be scattered in host DRAM.  Each buffer has max size
- * of (4K - 4).  The concatenates all of a TFD's buffers into a single
- * Tx frame, up to 8 KBytes in size.
- *
- * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
- */
-struct iwl_tfd {
-       u8 __reserved1[3];
-       u8 num_tbs;
-       struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
-       __le32 __pad;
-} __packed;
-
-/* Keep Warm Size */
-#define IWL_KW_SIZE 0x1000     /* 4k */
-
-#endif /* !__iwl_legacy_fh_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-hcmd.c b/drivers/net/wireless/iwlegacy/iwl-hcmd.c
deleted file mode 100644 (file)
index ce1fc9f..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <net/mac80211.h>
-
-#include "iwl-dev.h"
-#include "iwl-debug.h"
-#include "iwl-eeprom.h"
-#include "iwl-core.h"
-
-
-const char *iwl_legacy_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_WEPKEY);
-               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(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(REPLY_TX_PWR_TABLE_CMD);
-               IWL_CMD(REPLY_BT_CONFIG);
-               IWL_CMD(REPLY_STATISTICS_CMD);
-               IWL_CMD(STATISTICS_NOTIFICATION);
-               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_RX);
-               IWL_CMD(REPLY_COMPRESSED_BA);
-       default:
-               return "UNKNOWN";
-
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_get_cmd_string);
-
-#define HOST_COMPLETE_TIMEOUT (HZ / 2)
-
-static void iwl_legacy_generic_cmd_callback(struct iwl_priv *priv,
-                                    struct iwl_device_cmd *cmd,
-                                    struct iwl_rx_packet *pkt)
-{
-       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
-               iwl_legacy_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-               return;
-       }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       switch (cmd->hdr.cmd) {
-       case REPLY_TX_LINK_QUALITY_CMD:
-       case SENSITIVITY_CMD:
-               IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n",
-               iwl_legacy_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-               break;
-       default:
-               IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n",
-               iwl_legacy_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-       }
-#endif
-}
-
-static int
-iwl_legacy_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-{
-       int ret;
-
-       BUG_ON(!(cmd->flags & CMD_ASYNC));
-
-       /* An asynchronous command can not expect an SKB to be set. */
-       BUG_ON(cmd->flags & CMD_WANT_SKB);
-
-       /* Assign a generic callback if one is not provided */
-       if (!cmd->callback)
-               cmd->callback = iwl_legacy_generic_cmd_callback;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return -EBUSY;
-
-       ret = iwl_legacy_enqueue_hcmd(priv, cmd);
-       if (ret < 0) {
-               IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
-                         iwl_legacy_get_cmd_string(cmd->id), ret);
-               return ret;
-       }
-       return 0;
-}
-
-int iwl_legacy_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-{
-       int cmd_idx;
-       int ret;
-
-       lockdep_assert_held(&priv->mutex);
-
-       BUG_ON(cmd->flags & CMD_ASYNC);
-
-        /* A synchronous command can not have a callback set. */
-       BUG_ON(cmd->callback);
-
-       IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
-                       iwl_legacy_get_cmd_string(cmd->id));
-
-       set_bit(STATUS_HCMD_ACTIVE, &priv->status);
-       IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
-                       iwl_legacy_get_cmd_string(cmd->id));
-
-       cmd_idx = iwl_legacy_enqueue_hcmd(priv, cmd);
-       if (cmd_idx < 0) {
-               ret = cmd_idx;
-               IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
-                         iwl_legacy_get_cmd_string(cmd->id), ret);
-               goto out;
-       }
-
-       ret = wait_event_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_ERR(priv,
-                               "Error sending %s: time out after %dms.\n",
-                               iwl_legacy_get_cmd_string(cmd->id),
-                               jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
-
-                       clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-                       IWL_DEBUG_INFO(priv,
-                               "Clearing HCMD_ACTIVE for command %s\n",
-                                      iwl_legacy_get_cmd_string(cmd->id));
-                       ret = -ETIMEDOUT;
-                       goto cancel;
-               }
-       }
-
-       if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-               IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n",
-                              iwl_legacy_get_cmd_string(cmd->id));
-               ret = -ECANCELED;
-               goto fail;
-       }
-       if (test_bit(STATUS_FW_ERROR, &priv->status)) {
-               IWL_ERR(priv, "Command %s failed: FW Error\n",
-                              iwl_legacy_get_cmd_string(cmd->id));
-               ret = -EIO;
-               goto fail;
-       }
-       if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
-               IWL_ERR(priv, "Error: Response NULL in '%s'\n",
-                         iwl_legacy_get_cmd_string(cmd->id));
-               ret = -EIO;
-               goto cancel;
-       }
-
-       ret = 0;
-       goto out;
-
-cancel:
-       if (cmd->flags & CMD_WANT_SKB) {
-               /*
-                * 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).
-                */
-               priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
-                                                       ~CMD_WANT_SKB;
-       }
-fail:
-       if (cmd->reply_page) {
-               iwl_legacy_free_pages(priv, cmd->reply_page);
-               cmd->reply_page = 0;
-       }
-out:
-       return ret;
-}
-EXPORT_SYMBOL(iwl_legacy_send_cmd_sync);
-
-int iwl_legacy_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-{
-       if (cmd->flags & CMD_ASYNC)
-               return iwl_legacy_send_cmd_async(priv, cmd);
-
-       return iwl_legacy_send_cmd_sync(priv, cmd);
-}
-EXPORT_SYMBOL(iwl_legacy_send_cmd);
-
-int
-iwl_legacy_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_legacy_send_cmd_sync(priv, &cmd);
-}
-EXPORT_SYMBOL(iwl_legacy_send_cmd_pdu);
-
-int iwl_legacy_send_cmd_pdu_async(struct iwl_priv *priv,
-                          u8 id, u16 len, const void *data,
-                          void (*callback)(struct iwl_priv *priv,
-                                           struct iwl_device_cmd *cmd,
-                                           struct iwl_rx_packet *pkt))
-{
-       struct iwl_host_cmd cmd = {
-               .id = id,
-               .len = len,
-               .data = data,
-       };
-
-       cmd.flags |= CMD_ASYNC;
-       cmd.callback = callback;
-
-       return iwl_legacy_send_cmd_async(priv, &cmd);
-}
-EXPORT_SYMBOL(iwl_legacy_send_cmd_pdu_async);
diff --git a/drivers/net/wireless/iwlegacy/iwl-helpers.h b/drivers/net/wireless/iwlegacy/iwl-helpers.h
deleted file mode 100644 (file)
index 5cf23ea..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_legacy_helpers_h__
-#define __iwl_legacy_helpers_h__
-
-#include <linux/ctype.h>
-#include <net/mac80211.h>
-
-#include "iwl-io.h"
-
-#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
-
-
-static inline struct ieee80211_conf *iwl_legacy_ieee80211_get_hw_conf(
-       struct ieee80211_hw *hw)
-{
-       return &hw->conf;
-}
-
-/**
- * iwl_legacy_queue_inc_wrap - increment queue index, wrap back to beginning
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl_legacy_queue_inc_wrap(int index, int n_bd)
-{
-       return ++index & (n_bd - 1);
-}
-
-/**
- * iwl_legacy_queue_dec_wrap - decrement queue index, wrap back to end
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl_legacy_queue_dec_wrap(int index, int n_bd)
-{
-       return --index & (n_bd - 1);
-}
-
-/* TODO: Move fw_desc functions to iwl-pci.ko */
-static inline void iwl_legacy_free_fw_desc(struct pci_dev *pci_dev,
-                                   struct fw_desc *desc)
-{
-       if (desc->v_addr)
-               dma_free_coherent(&pci_dev->dev, desc->len,
-                                 desc->v_addr, desc->p_addr);
-       desc->v_addr = NULL;
-       desc->len = 0;
-}
-
-static inline int iwl_legacy_alloc_fw_desc(struct pci_dev *pci_dev,
-                                   struct fw_desc *desc)
-{
-       if (!desc->len) {
-               desc->v_addr = NULL;
-               return -EINVAL;
-       }
-
-       desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
-                                         &desc->p_addr, GFP_KERNEL);
-       return (desc->v_addr != NULL) ? 0 : -ENOMEM;
-}
-
-/*
- * we have 8 bits used like this:
- *
- * 7 6 5 4 3 2 1 0
- * | | | | | | | |
- * | | | | | | +-+-------- AC queue (0-3)
- * | | | | | |
- * | +-+-+-+-+------------ HW queue ID
- * |
- * +---------------------- unused
- */
-static inline void
-iwl_legacy_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
-{
-       BUG_ON(ac > 3);   /* only have 2 bits */
-       BUG_ON(hwq > 31); /* only use 5 bits */
-
-       txq->swq_id = (hwq << 2) | ac;
-}
-
-static inline void iwl_legacy_wake_queue(struct iwl_priv *priv,
-                                 struct iwl_tx_queue *txq)
-{
-       u8 queue = txq->swq_id;
-       u8 ac = queue & 3;
-       u8 hwq = (queue >> 2) & 0x1f;
-
-       if (test_and_clear_bit(hwq, priv->queue_stopped))
-               if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0)
-                       ieee80211_wake_queue(priv->hw, ac);
-}
-
-static inline void iwl_legacy_stop_queue(struct iwl_priv *priv,
-                                 struct iwl_tx_queue *txq)
-{
-       u8 queue = txq->swq_id;
-       u8 ac = queue & 3;
-       u8 hwq = (queue >> 2) & 0x1f;
-
-       if (!test_and_set_bit(hwq, priv->queue_stopped))
-               if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0)
-                       ieee80211_stop_queue(priv->hw, ac);
-}
-
-#ifdef ieee80211_stop_queue
-#undef ieee80211_stop_queue
-#endif
-
-#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
-
-#ifdef ieee80211_wake_queue
-#undef ieee80211_wake_queue
-#endif
-
-#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
-
-static inline void iwl_legacy_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(priv, "Disabled interrupts\n");
-}
-
-static inline void iwl_legacy_enable_rfkill_int(struct iwl_priv *priv)
-{
-       IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
-       iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
-}
-
-static inline void iwl_legacy_enable_interrupts(struct iwl_priv *priv)
-{
-       IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
-       set_bit(STATUS_INT_ENABLED, &priv->status);
-       iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
-}
-
-/**
- * iwl_legacy_beacon_time_mask_low - mask of lower 32 bit of beacon time
- * @priv -- pointer to iwl_priv data structure
- * @tsf_bits -- number of bits need to shift for masking)
- */
-static inline u32 iwl_legacy_beacon_time_mask_low(struct iwl_priv *priv,
-                                          u16 tsf_bits)
-{
-       return (1 << tsf_bits) - 1;
-}
-
-/**
- * iwl_legacy_beacon_time_mask_high - mask of higher 32 bit of beacon time
- * @priv -- pointer to iwl_priv data structure
- * @tsf_bits -- number of bits need to shift for masking)
- */
-static inline u32 iwl_legacy_beacon_time_mask_high(struct iwl_priv *priv,
-                                           u16 tsf_bits)
-{
-       return ((1 << (32 - tsf_bits)) - 1) << tsf_bits;
-}
-
-#endif                         /* __iwl_legacy_helpers_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-io.h b/drivers/net/wireless/iwlegacy/iwl-io.h
deleted file mode 100644 (file)
index 5cc5d34..0000000
+++ /dev/null
@@ -1,545 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_legacy_io_h__
-#define __iwl_legacy_io_h__
-
-#include <linux/io.h>
-
-#include "iwl-dev.h"
-#include "iwl-debug.h"
-#include "iwl-devtrace.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
- * and the current line number and caller function name are 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 name and __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_legacy_read_direct32 calls the non-check version of
- * _iwl_legacy_read32.)
- *
- * These declarations are *extremely* useful in quickly isolating code deltas
- * which result in misconfiguration 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.
- *
- */
-
-static inline void _iwl_legacy_write8(struct iwl_priv *priv, u32 ofs, u8 val)
-{
-       trace_iwlwifi_legacy_dev_iowrite8(priv, ofs, val);
-       iowrite8(val, priv->hw_base + ofs);
-}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static inline void
-__iwl_legacy_write8(const char *f, u32 l, struct iwl_priv *priv,
-                                u32 ofs, u8 val)
-{
-       IWL_DEBUG_IO(priv, "write8(0x%08X, 0x%02X) - %s %d\n", ofs, val, f, l);
-       _iwl_legacy_write8(priv, ofs, val);
-}
-#define iwl_write8(priv, ofs, val) \
-       __iwl_legacy_write8(__FILE__, __LINE__, priv, ofs, val)
-#else
-#define iwl_write8(priv, ofs, val) _iwl_legacy_write8(priv, ofs, val)
-#endif
-
-
-static inline void _iwl_legacy_write32(struct iwl_priv *priv, u32 ofs, u32 val)
-{
-       trace_iwlwifi_legacy_dev_iowrite32(priv, ofs, val);
-       iowrite32(val, priv->hw_base + ofs);
-}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static inline void
-__iwl_legacy_write32(const char *f, u32 l, struct iwl_priv *priv,
-                                u32 ofs, u32 val)
-{
-       IWL_DEBUG_IO(priv, "write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
-       _iwl_legacy_write32(priv, ofs, val);
-}
-#define iwl_write32(priv, ofs, val) \
-       __iwl_legacy_write32(__FILE__, __LINE__, priv, ofs, val)
-#else
-#define iwl_write32(priv, ofs, val) _iwl_legacy_write32(priv, ofs, val)
-#endif
-
-static inline u32 _iwl_legacy_read32(struct iwl_priv *priv, u32 ofs)
-{
-       u32 val = ioread32(priv->hw_base + ofs);
-       trace_iwlwifi_legacy_dev_ioread32(priv, ofs, val);
-       return val;
-}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static inline u32
-__iwl_legacy_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs)
-{
-       IWL_DEBUG_IO(priv, "read_direct32(0x%08X) - %s %d\n", ofs, f, l);
-       return _iwl_legacy_read32(priv, ofs);
-}
-#define iwl_read32(priv, ofs) __iwl_legacy_read32(__FILE__, __LINE__, priv, ofs)
-#else
-#define iwl_read32(p, o) _iwl_legacy_read32(p, o)
-#endif
-
-#define IWL_POLL_INTERVAL 10   /* microseconds */
-static inline int
-_iwl_legacy_poll_bit(struct iwl_priv *priv, u32 addr,
-                               u32 bits, u32 mask, int timeout)
-{
-       int t = 0;
-
-       do {
-               if ((_iwl_legacy_read32(priv, addr) & mask) == (bits & mask))
-                       return t;
-               udelay(IWL_POLL_INTERVAL);
-               t += IWL_POLL_INTERVAL;
-       } while (t < timeout);
-
-       return -ETIMEDOUT;
-}
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static inline int __iwl_legacy_poll_bit(const char *f, u32 l,
-                                struct iwl_priv *priv, u32 addr,
-                                u32 bits, u32 mask, int timeout)
-{
-       int ret = _iwl_legacy_poll_bit(priv, addr, bits, mask, timeout);
-       IWL_DEBUG_IO(priv, "poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
-                    addr, bits, mask,
-                    unlikely(ret  == -ETIMEDOUT) ? "timeout" : "", f, l);
-       return ret;
-}
-#define iwl_poll_bit(priv, addr, bits, mask, timeout) \
-       __iwl_legacy_poll_bit(__FILE__, __LINE__, priv, addr, \
-       bits, mask, timeout)
-#else
-#define iwl_poll_bit(p, a, b, m, t) _iwl_legacy_poll_bit(p, a, b, m, t)
-#endif
-
-static inline void _iwl_legacy_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
-{
-       _iwl_legacy_write32(priv, reg, _iwl_legacy_read32(priv, reg) | mask);
-}
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static inline void __iwl_legacy_set_bit(const char *f, u32 l,
-                                struct iwl_priv *priv, u32 reg, u32 mask)
-{
-       u32 val = _iwl_legacy_read32(priv, reg) | mask;
-       IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg,
-                                                       mask, val);
-       _iwl_legacy_write32(priv, reg, val);
-}
-static inline void iwl_legacy_set_bit(struct iwl_priv *p, u32 r, u32 m)
-{
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&p->reg_lock, reg_flags);
-       __iwl_legacy_set_bit(__FILE__, __LINE__, p, r, m);
-       spin_unlock_irqrestore(&p->reg_lock, reg_flags);
-}
-#else
-static inline void iwl_legacy_set_bit(struct iwl_priv *p, u32 r, u32 m)
-{
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&p->reg_lock, reg_flags);
-       _iwl_legacy_set_bit(p, r, m);
-       spin_unlock_irqrestore(&p->reg_lock, reg_flags);
-}
-#endif
-
-static inline void
-_iwl_legacy_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
-{
-       _iwl_legacy_write32(priv, reg, _iwl_legacy_read32(priv, reg) & ~mask);
-}
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static inline void
-__iwl_legacy_clear_bit(const char *f, u32 l,
-                                  struct iwl_priv *priv, u32 reg, u32 mask)
-{
-       u32 val = _iwl_legacy_read32(priv, reg) & ~mask;
-       IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
-       _iwl_legacy_write32(priv, reg, val);
-}
-static inline void iwl_legacy_clear_bit(struct iwl_priv *p, u32 r, u32 m)
-{
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&p->reg_lock, reg_flags);
-       __iwl_legacy_clear_bit(__FILE__, __LINE__, p, r, m);
-       spin_unlock_irqrestore(&p->reg_lock, reg_flags);
-}
-#else
-static inline void iwl_legacy_clear_bit(struct iwl_priv *p, u32 r, u32 m)
-{
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&p->reg_lock, reg_flags);
-       _iwl_legacy_clear_bit(p, r, m);
-       spin_unlock_irqrestore(&p->reg_lock, reg_flags);
-}
-#endif
-
-static inline int _iwl_legacy_grab_nic_access(struct iwl_priv *priv)
-{
-       int ret;
-       u32 val;
-
-       /* this bit wakes up the NIC */
-       _iwl_legacy_set_bit(priv, CSR_GP_CNTRL,
-                               CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
-       /*
-        * These bits say the device is running, and should keep running for
-        * at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
-        * but they do not indicate that embedded SRAM is restored yet;
-        * 3945 and 4965 have volatile SRAM, and must save/restore contents
-        * to/from host DRAM when sleeping/waking for power-saving.
-        * Each direction takes approximately 1/4 millisecond; with this
-        * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
-        * series of register accesses are expected (e.g. reading Event Log),
-        * to keep device from sleeping.
-        *
-        * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
-        * SRAM is okay/restored.  We don't check that here because this call
-        * is just for hardware register access; but GP1 MAC_SLEEP check is a
-        * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
-        *
-        */
-       ret = _iwl_legacy_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), 15000);
-       if (ret < 0) {
-               val = _iwl_legacy_read32(priv, CSR_GP_CNTRL);
-               IWL_ERR(priv,
-                       "MAC is in deep sleep!.  CSR_GP_CNTRL = 0x%08X\n", val);
-               _iwl_legacy_write32(priv, CSR_RESET,
-                               CSR_RESET_REG_FLAG_FORCE_NMI);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static inline int __iwl_legacy_grab_nic_access(const char *f, u32 l,
-                                              struct iwl_priv *priv)
-{
-       IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l);
-       return _iwl_legacy_grab_nic_access(priv);
-}
-#define iwl_grab_nic_access(priv) \
-       __iwl_legacy_grab_nic_access(__FILE__, __LINE__, priv)
-#else
-#define iwl_grab_nic_access(priv) \
-       _iwl_legacy_grab_nic_access(priv)
-#endif
-
-static inline void _iwl_legacy_release_nic_access(struct iwl_priv *priv)
-{
-       _iwl_legacy_clear_bit(priv, CSR_GP_CNTRL,
-                       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-}
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static inline void __iwl_legacy_release_nic_access(const char *f, u32 l,
-                                           struct iwl_priv *priv)
-{
-
-       IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l);
-       _iwl_legacy_release_nic_access(priv);
-}
-#define iwl_release_nic_access(priv) \
-       __iwl_legacy_release_nic_access(__FILE__, __LINE__, priv)
-#else
-#define iwl_release_nic_access(priv) \
-       _iwl_legacy_release_nic_access(priv)
-#endif
-
-static inline u32 _iwl_legacy_read_direct32(struct iwl_priv *priv, u32 reg)
-{
-       return _iwl_legacy_read32(priv, reg);
-}
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static inline u32 __iwl_legacy_read_direct32(const char *f, u32 l,
-                                       struct iwl_priv *priv, u32 reg)
-{
-       u32 value = _iwl_legacy_read_direct32(priv, reg);
-       IWL_DEBUG_IO(priv,
-                       "read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value,
-                    f, l);
-       return value;
-}
-static inline u32 iwl_legacy_read_direct32(struct iwl_priv *priv, u32 reg)
-{
-       u32 value;
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       iwl_grab_nic_access(priv);
-       value = __iwl_legacy_read_direct32(__FILE__, __LINE__, priv, reg);
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-       return value;
-}
-
-#else
-static inline u32 iwl_legacy_read_direct32(struct iwl_priv *priv, u32 reg)
-{
-       u32 value;
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       iwl_grab_nic_access(priv);
-       value = _iwl_legacy_read_direct32(priv, reg);
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-       return value;
-
-}
-#endif
-
-static inline void _iwl_legacy_write_direct32(struct iwl_priv *priv,
-                                        u32 reg, u32 value)
-{
-       _iwl_legacy_write32(priv, reg, value);
-}
-static inline void
-iwl_legacy_write_direct32(struct iwl_priv *priv, u32 reg, u32 value)
-{
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       if (!iwl_grab_nic_access(priv)) {
-               _iwl_legacy_write_direct32(priv, reg, value);
-               iwl_release_nic_access(priv);
-       }
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-static inline void iwl_legacy_write_reg_buf(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_legacy_write_direct32(priv, reg, *values);
-       }
-}
-
-static inline int _iwl_legacy_poll_direct_bit(struct iwl_priv *priv, u32 addr,
-                                      u32 mask, int timeout)
-{
-       int t = 0;
-
-       do {
-               if ((iwl_legacy_read_direct32(priv, addr) & mask) == mask)
-                       return t;
-               udelay(IWL_POLL_INTERVAL);
-               t += IWL_POLL_INTERVAL;
-       } while (t < timeout);
-
-       return -ETIMEDOUT;
-}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static inline int __iwl_legacy_poll_direct_bit(const char *f, u32 l,
-                                           struct iwl_priv *priv,
-                                           u32 addr, u32 mask, int timeout)
-{
-       int ret  = _iwl_legacy_poll_direct_bit(priv, addr, mask, timeout);
-
-       if (unlikely(ret == -ETIMEDOUT))
-               IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) - "
-                            "timedout - %s %d\n", addr, mask, f, l);
-       else
-               IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
-                            "- %s %d\n", addr, mask, ret, f, l);
-       return ret;
-}
-#define iwl_poll_direct_bit(priv, addr, mask, timeout) \
-__iwl_legacy_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
-#else
-#define iwl_poll_direct_bit _iwl_legacy_poll_direct_bit
-#endif
-
-static inline u32 _iwl_legacy_read_prph(struct iwl_priv *priv, u32 reg)
-{
-       _iwl_legacy_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
-       rmb();
-       return _iwl_legacy_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
-}
-static inline u32 iwl_legacy_read_prph(struct iwl_priv *priv, u32 reg)
-{
-       unsigned long reg_flags;
-       u32 val;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       iwl_grab_nic_access(priv);
-       val = _iwl_legacy_read_prph(priv, reg);
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-       return val;
-}
-
-static inline void _iwl_legacy_write_prph(struct iwl_priv *priv,
-                                            u32 addr, u32 val)
-{
-       _iwl_legacy_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
-                             ((addr & 0x0000FFFF) | (3 << 24)));
-       wmb();
-       _iwl_legacy_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
-}
-
-static inline void
-iwl_legacy_write_prph(struct iwl_priv *priv, u32 addr, u32 val)
-{
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       if (!iwl_grab_nic_access(priv)) {
-               _iwl_legacy_write_prph(priv, addr, val);
-               iwl_release_nic_access(priv);
-       }
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-#define _iwl_legacy_set_bits_prph(priv, reg, mask) \
-_iwl_legacy_write_prph(priv, reg, (_iwl_legacy_read_prph(priv, reg) | mask))
-
-static inline void
-iwl_legacy_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
-{
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       iwl_grab_nic_access(priv);
-       _iwl_legacy_set_bits_prph(priv, reg, mask);
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-#define _iwl_legacy_set_bits_mask_prph(priv, reg, bits, mask) \
-_iwl_legacy_write_prph(priv, reg,                              \
-                ((_iwl_legacy_read_prph(priv, reg) & mask) | bits))
-
-static inline void iwl_legacy_set_bits_mask_prph(struct iwl_priv *priv, u32 reg,
-                               u32 bits, u32 mask)
-{
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       iwl_grab_nic_access(priv);
-       _iwl_legacy_set_bits_mask_prph(priv, reg, bits, mask);
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-static inline void iwl_legacy_clear_bits_prph(struct iwl_priv
-                                                *priv, u32 reg, u32 mask)
-{
-       unsigned long reg_flags;
-       u32 val;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       iwl_grab_nic_access(priv);
-       val = _iwl_legacy_read_prph(priv, reg);
-       _iwl_legacy_write_prph(priv, reg, (val & ~mask));
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-static inline u32 iwl_legacy_read_targ_mem(struct iwl_priv *priv, u32 addr)
-{
-       unsigned long reg_flags;
-       u32 value;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       iwl_grab_nic_access(priv);
-
-       _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
-       rmb();
-       value = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-       return value;
-}
-
-static inline void
-iwl_legacy_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
-{
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       if (!iwl_grab_nic_access(priv)) {
-               _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
-               wmb();
-               _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
-               iwl_release_nic_access(priv);
-       }
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-static inline void
-iwl_legacy_write_targ_mem_buf(struct iwl_priv *priv, u32 addr,
-                                         u32 len, u32 *values)
-{
-       unsigned long reg_flags;
-
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       if (!iwl_grab_nic_access(priv)) {
-               _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
-               wmb();
-               for (; 0 < len; len -= sizeof(u32), values++)
-                       _iwl_legacy_write_direct32(priv,
-                                       HBUS_TARG_MEM_WDAT, *values);
-
-               iwl_release_nic_access(priv);
-       }
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-led.c b/drivers/net/wireless/iwlegacy/iwl-led.c
deleted file mode 100644 (file)
index dc568a4..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-
-#include <linux/kernel.h>
-#include <linux/module.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 <net/mac80211.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-
-/* default: IWL_LED_BLINK(0) using blinking index table */
-static int led_mode;
-module_param(led_mode, int, S_IRUGO);
-MODULE_PARM_DESC(led_mode, "0=system default, "
-               "1=On(RF On)/Off(RF Off), 2=blinking");
-
-/* Throughput          OFF time(ms)    ON time (ms)
- *     >300                    25              25
- *     >200 to 300             40              40
- *     >100 to 200             55              55
- *     >70 to 100              65              65
- *     >50 to 70               75              75
- *     >20 to 50               85              85
- *     >10 to 20               95              95
- *     >5 to 10                110             110
- *     >1 to 5                 130             130
- *     >0 to 1                 167             167
- *     <=0                                     SOLID ON
- */
-static const struct ieee80211_tpt_blink iwl_blink[] = {
-       { .throughput = 0, .blink_time = 334 },
-       { .throughput = 1 * 1024 - 1, .blink_time = 260 },
-       { .throughput = 5 * 1024 - 1, .blink_time = 220 },
-       { .throughput = 10 * 1024 - 1, .blink_time = 190 },
-       { .throughput = 20 * 1024 - 1, .blink_time = 170 },
-       { .throughput = 50 * 1024 - 1, .blink_time = 150 },
-       { .throughput = 70 * 1024 - 1, .blink_time = 130 },
-       { .throughput = 100 * 1024 - 1, .blink_time = 110 },
-       { .throughput = 200 * 1024 - 1, .blink_time = 80 },
-       { .throughput = 300 * 1024 - 1, .blink_time = 50 },
-};
-
-/*
- * Adjust led blink rate to compensate on a MAC Clock difference on every HW
- * Led blink rate analysis showed an average deviation of 0% on 3945,
- * 5% on 4965 HW.
- * Need to compensate on the led on/off time per HW according to the deviation
- * to achieve the desired led frequency
- * The calculation is: (100-averageDeviation)/100 * blinkTime
- * For code efficiency the calculation will be:
- *     compensation = (100 - averageDeviation) * 64 / 100
- *     NewBlinkTime = (compensation * BlinkTime) / 64
- */
-static inline u8 iwl_legacy_blink_compensation(struct iwl_priv *priv,
-                                   u8 time, u16 compensation)
-{
-       if (!compensation) {
-               IWL_ERR(priv, "undefined blink compensation: "
-                       "use pre-defined blinking time\n");
-               return time;
-       }
-
-       return (u8)((time * compensation) >> 6);
-}
-
-/* Set led pattern command */
-static int iwl_legacy_led_cmd(struct iwl_priv *priv,
-                      unsigned long on,
-                      unsigned long off)
-{
-       struct iwl_led_cmd led_cmd = {
-               .id = IWL_LED_LINK,
-               .interval = IWL_DEF_LED_INTRVL
-       };
-       int ret;
-
-       if (!test_bit(STATUS_READY, &priv->status))
-               return -EBUSY;
-
-       if (priv->blink_on == on && priv->blink_off == off)
-               return 0;
-
-       if (off == 0) {
-               /* led is SOLID_ON */
-               on = IWL_LED_SOLID;
-       }
-
-       IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
-                       priv->cfg->base_params->led_compensation);
-       led_cmd.on = iwl_legacy_blink_compensation(priv, on,
-                               priv->cfg->base_params->led_compensation);
-       led_cmd.off = iwl_legacy_blink_compensation(priv, off,
-                               priv->cfg->base_params->led_compensation);
-
-       ret = priv->cfg->ops->led->cmd(priv, &led_cmd);
-       if (!ret) {
-               priv->blink_on = on;
-               priv->blink_off = off;
-       }
-       return ret;
-}
-
-static void iwl_legacy_led_brightness_set(struct led_classdev *led_cdev,
-                                  enum led_brightness brightness)
-{
-       struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
-       unsigned long on = 0;
-
-       if (brightness > 0)
-               on = IWL_LED_SOLID;
-
-       iwl_legacy_led_cmd(priv, on, 0);
-}
-
-static int iwl_legacy_led_blink_set(struct led_classdev *led_cdev,
-                            unsigned long *delay_on,
-                            unsigned long *delay_off)
-{
-       struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
-
-       return iwl_legacy_led_cmd(priv, *delay_on, *delay_off);
-}
-
-void iwl_legacy_leds_init(struct iwl_priv *priv)
-{
-       int mode = led_mode;
-       int ret;
-
-       if (mode == IWL_LED_DEFAULT)
-               mode = priv->cfg->led_mode;
-
-       priv->led.name = kasprintf(GFP_KERNEL, "%s-led",
-                                  wiphy_name(priv->hw->wiphy));
-       priv->led.brightness_set = iwl_legacy_led_brightness_set;
-       priv->led.blink_set = iwl_legacy_led_blink_set;
-       priv->led.max_brightness = 1;
-
-       switch (mode) {
-       case IWL_LED_DEFAULT:
-               WARN_ON(1);
-               break;
-       case IWL_LED_BLINK:
-               priv->led.default_trigger =
-                       ieee80211_create_tpt_led_trigger(priv->hw,
-                                       IEEE80211_TPT_LEDTRIG_FL_CONNECTED,
-                                       iwl_blink, ARRAY_SIZE(iwl_blink));
-               break;
-       case IWL_LED_RF_STATE:
-               priv->led.default_trigger =
-                       ieee80211_get_radio_led_name(priv->hw);
-               break;
-       }
-
-       ret = led_classdev_register(&priv->pci_dev->dev, &priv->led);
-       if (ret) {
-               kfree(priv->led.name);
-               return;
-       }
-
-       priv->led_registered = true;
-}
-EXPORT_SYMBOL(iwl_legacy_leds_init);
-
-void iwl_legacy_leds_exit(struct iwl_priv *priv)
-{
-       if (!priv->led_registered)
-               return;
-
-       led_classdev_unregister(&priv->led);
-       kfree(priv->led.name);
-}
-EXPORT_SYMBOL(iwl_legacy_leds_exit);
diff --git a/drivers/net/wireless/iwlegacy/iwl-led.h b/drivers/net/wireless/iwlegacy/iwl-led.h
deleted file mode 100644 (file)
index f0791f7..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_legacy_leds_h__
-#define __iwl_legacy_leds_h__
-
-
-struct iwl_priv;
-
-#define IWL_LED_SOLID 11
-#define IWL_DEF_LED_INTRVL cpu_to_le32(1000)
-
-#define IWL_LED_ACTIVITY       (0<<1)
-#define IWL_LED_LINK           (1<<1)
-
-/*
- * LED mode
- *    IWL_LED_DEFAULT:  use device default
- *    IWL_LED_RF_STATE: turn LED on/off based on RF state
- *                     LED ON  = RF ON
- *                     LED OFF = RF OFF
- *    IWL_LED_BLINK:    adjust led blink rate based on blink table
- */
-enum iwl_led_mode {
-       IWL_LED_DEFAULT,
-       IWL_LED_RF_STATE,
-       IWL_LED_BLINK,
-};
-
-void iwl_legacy_leds_init(struct iwl_priv *priv);
-void iwl_legacy_leds_exit(struct iwl_priv *priv);
-
-#endif /* __iwl_legacy_leds_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-legacy-rs.h b/drivers/net/wireless/iwlegacy/iwl-legacy-rs.h
deleted file mode 100644 (file)
index 38647e4..0000000
+++ /dev/null
@@ -1,456 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_legacy_rs_h__
-#define __iwl_legacy_rs_h__
-
-struct iwl_rate_info {
-       u8 plcp;        /* uCode API:  IWL_RATE_6M_PLCP, etc. */
-       u8 plcp_siso;   /* uCode API:  IWL_RATE_SISO_6M_PLCP, etc. */
-       u8 plcp_mimo2;  /* uCode API:  IWL_RATE_MIMO2_6M_PLCP, etc. */
-       u8 ieee;        /* MAC header:  IWL_RATE_6M_IEEE, etc. */
-       u8 prev_ieee;    /* previous rate in IEEE speeds */
-       u8 next_ieee;    /* next rate in IEEE speeds */
-       u8 prev_rs;      /* previous rate used in rs algo */
-       u8 next_rs;      /* next rate used in rs algo */
-       u8 prev_rs_tgg;  /* previous rate used in TGG rs algo */
-       u8 next_rs_tgg;  /* next rate used in TGG rs algo */
-};
-
-struct iwl3945_rate_info {
-       u8 plcp;                /* uCode API:  IWL_RATE_6M_PLCP, etc. */
-       u8 ieee;                /* MAC header:  IWL_RATE_6M_IEEE, etc. */
-       u8 prev_ieee;           /* previous rate in IEEE speeds */
-       u8 next_ieee;           /* next rate in IEEE speeds */
-       u8 prev_rs;             /* previous rate used in rs algo */
-       u8 next_rs;             /* next rate used in rs algo */
-       u8 prev_rs_tgg;         /* previous rate used in TGG rs algo */
-       u8 next_rs_tgg;         /* next rate used in TGG rs algo */
-       u8 table_rs_index;      /* index in rate scale table cmd */
-       u8 prev_table_rs;       /* prev in rate table cmd */
-};
-
-
-/*
- * These serve as indexes into
- * struct iwl_rate_info iwlegacy_rates[IWL_RATE_COUNT];
- */
-enum {
-       IWL_RATE_1M_INDEX = 0,
-       IWL_RATE_2M_INDEX,
-       IWL_RATE_5M_INDEX,
-       IWL_RATE_11M_INDEX,
-       IWL_RATE_6M_INDEX,
-       IWL_RATE_9M_INDEX,
-       IWL_RATE_12M_INDEX,
-       IWL_RATE_18M_INDEX,
-       IWL_RATE_24M_INDEX,
-       IWL_RATE_36M_INDEX,
-       IWL_RATE_48M_INDEX,
-       IWL_RATE_54M_INDEX,
-       IWL_RATE_60M_INDEX,
-       IWL_RATE_COUNT,
-       IWL_RATE_COUNT_LEGACY = IWL_RATE_COUNT - 1,     /* Excluding 60M */
-       IWL_RATE_COUNT_3945 = IWL_RATE_COUNT - 1,
-       IWL_RATE_INVM_INDEX = IWL_RATE_COUNT,
-       IWL_RATE_INVALID = IWL_RATE_COUNT,
-};
-
-enum {
-       IWL_RATE_6M_INDEX_TABLE = 0,
-       IWL_RATE_9M_INDEX_TABLE,
-       IWL_RATE_12M_INDEX_TABLE,
-       IWL_RATE_18M_INDEX_TABLE,
-       IWL_RATE_24M_INDEX_TABLE,
-       IWL_RATE_36M_INDEX_TABLE,
-       IWL_RATE_48M_INDEX_TABLE,
-       IWL_RATE_54M_INDEX_TABLE,
-       IWL_RATE_1M_INDEX_TABLE,
-       IWL_RATE_2M_INDEX_TABLE,
-       IWL_RATE_5M_INDEX_TABLE,
-       IWL_RATE_11M_INDEX_TABLE,
-       IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX - 1,
-};
-
-enum {
-       IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
-       IWL39_LAST_OFDM_RATE = IWL_RATE_54M_INDEX,
-       IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX,
-       IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
-       IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
-};
-
-/* #define vs. enum to keep from defaulting to 'large integer' */
-#define        IWL_RATE_6M_MASK   (1 << IWL_RATE_6M_INDEX)
-#define        IWL_RATE_9M_MASK   (1 << IWL_RATE_9M_INDEX)
-#define        IWL_RATE_12M_MASK  (1 << IWL_RATE_12M_INDEX)
-#define        IWL_RATE_18M_MASK  (1 << IWL_RATE_18M_INDEX)
-#define        IWL_RATE_24M_MASK  (1 << IWL_RATE_24M_INDEX)
-#define        IWL_RATE_36M_MASK  (1 << IWL_RATE_36M_INDEX)
-#define        IWL_RATE_48M_MASK  (1 << IWL_RATE_48M_INDEX)
-#define        IWL_RATE_54M_MASK  (1 << IWL_RATE_54M_INDEX)
-#define IWL_RATE_60M_MASK  (1 << IWL_RATE_60M_INDEX)
-#define        IWL_RATE_1M_MASK   (1 << IWL_RATE_1M_INDEX)
-#define        IWL_RATE_2M_MASK   (1 << IWL_RATE_2M_INDEX)
-#define        IWL_RATE_5M_MASK   (1 << IWL_RATE_5M_INDEX)
-#define        IWL_RATE_11M_MASK  (1 << IWL_RATE_11M_INDEX)
-
-/* uCode API values for legacy bit rates, both OFDM and CCK */
-enum {
-       IWL_RATE_6M_PLCP  = 13,
-       IWL_RATE_9M_PLCP  = 15,
-       IWL_RATE_12M_PLCP = 5,
-       IWL_RATE_18M_PLCP = 7,
-       IWL_RATE_24M_PLCP = 9,
-       IWL_RATE_36M_PLCP = 11,
-       IWL_RATE_48M_PLCP = 1,
-       IWL_RATE_54M_PLCP = 3,
-       IWL_RATE_60M_PLCP = 3,/*FIXME:RS:should be removed*/
-       IWL_RATE_1M_PLCP  = 10,
-       IWL_RATE_2M_PLCP  = 20,
-       IWL_RATE_5M_PLCP  = 55,
-       IWL_RATE_11M_PLCP = 110,
-       /*FIXME:RS:add IWL_RATE_LEGACY_INVM_PLCP = 0,*/
-};
-
-/* uCode API values for OFDM high-throughput (HT) bit rates */
-enum {
-       IWL_RATE_SISO_6M_PLCP = 0,
-       IWL_RATE_SISO_12M_PLCP = 1,
-       IWL_RATE_SISO_18M_PLCP = 2,
-       IWL_RATE_SISO_24M_PLCP = 3,
-       IWL_RATE_SISO_36M_PLCP = 4,
-       IWL_RATE_SISO_48M_PLCP = 5,
-       IWL_RATE_SISO_54M_PLCP = 6,
-       IWL_RATE_SISO_60M_PLCP = 7,
-       IWL_RATE_MIMO2_6M_PLCP  = 0x8,
-       IWL_RATE_MIMO2_12M_PLCP = 0x9,
-       IWL_RATE_MIMO2_18M_PLCP = 0xa,
-       IWL_RATE_MIMO2_24M_PLCP = 0xb,
-       IWL_RATE_MIMO2_36M_PLCP = 0xc,
-       IWL_RATE_MIMO2_48M_PLCP = 0xd,
-       IWL_RATE_MIMO2_54M_PLCP = 0xe,
-       IWL_RATE_MIMO2_60M_PLCP = 0xf,
-       IWL_RATE_SISO_INVM_PLCP,
-       IWL_RATE_MIMO2_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP,
-};
-
-/* MAC header values for bit rates */
-enum {
-       IWL_RATE_6M_IEEE  = 12,
-       IWL_RATE_9M_IEEE  = 18,
-       IWL_RATE_12M_IEEE = 24,
-       IWL_RATE_18M_IEEE = 36,
-       IWL_RATE_24M_IEEE = 48,
-       IWL_RATE_36M_IEEE = 72,
-       IWL_RATE_48M_IEEE = 96,
-       IWL_RATE_54M_IEEE = 108,
-       IWL_RATE_60M_IEEE = 120,
-       IWL_RATE_1M_IEEE  = 2,
-       IWL_RATE_2M_IEEE  = 4,
-       IWL_RATE_5M_IEEE  = 11,
-       IWL_RATE_11M_IEEE = 22,
-};
-
-#define IWL_CCK_BASIC_RATES_MASK    \
-       (IWL_RATE_1M_MASK          | \
-       IWL_RATE_2M_MASK)
-
-#define IWL_CCK_RATES_MASK          \
-       (IWL_CCK_BASIC_RATES_MASK  | \
-       IWL_RATE_5M_MASK          | \
-       IWL_RATE_11M_MASK)
-
-#define IWL_OFDM_BASIC_RATES_MASK   \
-       (IWL_RATE_6M_MASK         | \
-       IWL_RATE_12M_MASK         | \
-       IWL_RATE_24M_MASK)
-
-#define IWL_OFDM_RATES_MASK         \
-       (IWL_OFDM_BASIC_RATES_MASK | \
-       IWL_RATE_9M_MASK          | \
-       IWL_RATE_18M_MASK         | \
-       IWL_RATE_36M_MASK         | \
-       IWL_RATE_48M_MASK         | \
-       IWL_RATE_54M_MASK)
-
-#define IWL_BASIC_RATES_MASK         \
-       (IWL_OFDM_BASIC_RATES_MASK | \
-        IWL_CCK_BASIC_RATES_MASK)
-
-#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
-#define IWL_RATES_MASK_3945 ((1 << IWL_RATE_COUNT_3945) - 1)
-
-#define IWL_INVALID_VALUE    -1
-
-#define IWL_MIN_RSSI_VAL                 -100
-#define IWL_MAX_RSSI_VAL                    0
-
-/* These values specify how many Tx frame attempts before
- * searching for a new modulation mode */
-#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
-
-/* Success ratio (ACKed / attempted tx frames) values (perfect is 128 * 100) */
-#define IWL_RS_GOOD_RATIO              12800   /* 100% */
-#define IWL_RATE_SCALE_SWITCH          10880   /*  85% */
-#define IWL_RATE_HIGH_TH               10880   /*  85% */
-#define IWL_RATE_INCREASE_TH           6400    /*  50% */
-#define IWL_RATE_DECREASE_TH           1920    /*  15% */
-
-/* possible actions when in legacy mode */
-#define IWL_LEGACY_SWITCH_ANTENNA1      0
-#define IWL_LEGACY_SWITCH_ANTENNA2      1
-#define IWL_LEGACY_SWITCH_SISO          2
-#define IWL_LEGACY_SWITCH_MIMO2_AB      3
-#define IWL_LEGACY_SWITCH_MIMO2_AC      4
-#define IWL_LEGACY_SWITCH_MIMO2_BC      5
-
-/* possible actions when in siso mode */
-#define IWL_SISO_SWITCH_ANTENNA1        0
-#define IWL_SISO_SWITCH_ANTENNA2        1
-#define IWL_SISO_SWITCH_MIMO2_AB        2
-#define IWL_SISO_SWITCH_MIMO2_AC        3
-#define IWL_SISO_SWITCH_MIMO2_BC        4
-#define IWL_SISO_SWITCH_GI              5
-
-/* possible actions when in mimo mode */
-#define IWL_MIMO2_SWITCH_ANTENNA1       0
-#define IWL_MIMO2_SWITCH_ANTENNA2       1
-#define IWL_MIMO2_SWITCH_SISO_A         2
-#define IWL_MIMO2_SWITCH_SISO_B         3
-#define IWL_MIMO2_SWITCH_SISO_C         4
-#define IWL_MIMO2_SWITCH_GI             5
-
-#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_GI
-
-#define IWL_ACTION_LIMIT               3       /* # possible actions */
-
-#define LQ_SIZE                2       /* 2 mode tables:  "Active" and "Search" */
-
-/* load per tid defines for A-MPDU activation */
-#define IWL_AGG_TPT_THREHOLD   0
-#define IWL_AGG_LOAD_THRESHOLD 10
-#define IWL_AGG_ALL_TID                0xff
-#define TID_QUEUE_CELL_SPACING 50      /*mS */
-#define TID_QUEUE_MAX_SIZE     20
-#define TID_ROUND_VALUE                5       /* mS */
-#define TID_MAX_LOAD_COUNT     8
-
-#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
-#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
-
-extern const struct iwl_rate_info iwlegacy_rates[IWL_RATE_COUNT];
-
-enum iwl_table_type {
-       LQ_NONE,
-       LQ_G,           /* legacy types */
-       LQ_A,
-       LQ_SISO,        /* high-throughput types */
-       LQ_MIMO2,
-       LQ_MAX,
-};
-
-#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A))
-#define is_siso(tbl) ((tbl) == LQ_SISO)
-#define is_mimo2(tbl) ((tbl) == LQ_MIMO2)
-#define is_mimo(tbl) (is_mimo2(tbl))
-#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl))
-#define is_a_band(tbl) ((tbl) == LQ_A)
-#define is_g_and(tbl) ((tbl) == LQ_G)
-
-#define        ANT_NONE        0x0
-#define        ANT_A           BIT(0)
-#define        ANT_B           BIT(1)
-#define        ANT_AB          (ANT_A | ANT_B)
-#define ANT_C          BIT(2)
-#define        ANT_AC          (ANT_A | ANT_C)
-#define ANT_BC         (ANT_B | ANT_C)
-#define ANT_ABC                (ANT_AB | ANT_C)
-
-#define IWL_MAX_MCS_DISPLAY_SIZE       12
-
-struct iwl_rate_mcs_info {
-       char    mbps[IWL_MAX_MCS_DISPLAY_SIZE];
-       char    mcs[IWL_MAX_MCS_DISPLAY_SIZE];
-};
-
-/**
- * struct iwl_rate_scale_data -- tx success history for one rate
- */
-struct iwl_rate_scale_data {
-       u64 data;               /* bitmap of successful frames */
-       s32 success_counter;    /* number of frames successful */
-       s32 success_ratio;      /* per-cent * 128  */
-       s32 counter;            /* number of frames attempted */
-       s32 average_tpt;        /* success ratio * expected throughput */
-       unsigned long stamp;
-};
-
-/**
- * struct iwl_scale_tbl_info -- tx params and success history for all rates
- *
- * There are two of these in struct iwl_lq_sta,
- * one for "active", and one for "search".
- */
-struct iwl_scale_tbl_info {
-       enum iwl_table_type lq_type;
-       u8 ant_type;
-       u8 is_SGI;      /* 1 = short guard interval */
-       u8 is_ht40;     /* 1 = 40 MHz channel width */
-       u8 is_dup;      /* 1 = duplicated data streams */
-       u8 action;      /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
-       u8 max_search;  /* maximun number of tables we can search */
-       s32 *expected_tpt;      /* throughput metrics; expected_tpt_G, etc. */
-       u32 current_rate;  /* rate_n_flags, uCode API format */
-       struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
-};
-
-struct iwl_traffic_load {
-       unsigned long time_stamp;       /* age of the oldest statistics */
-       u32 packet_count[TID_QUEUE_MAX_SIZE];   /* packet count in this time
-                                                * slice */
-       u32 total;                      /* total num of packets during the
-                                        * last TID_MAX_TIME_DIFF */
-       u8 queue_count;                 /* number of queues that has
-                                        * been used since the last cleanup */
-       u8 head;                        /* start of the circular buffer */
-};
-
-/**
- * struct iwl_lq_sta -- driver's rate scaling private structure
- *
- * Pointer to this gets passed back and forth between driver and mac80211.
- */
-struct iwl_lq_sta {
-       u8 active_tbl;          /* index of active table, range 0-1 */
-       u8 enable_counter;      /* indicates HT mode */
-       u8 stay_in_tbl;         /* 1: disallow, 0: allow search for new mode */
-       u8 search_better_tbl;   /* 1: currently trying alternate mode */
-       s32 last_tpt;
-
-       /* The following determine when to search for a new mode */
-       u32 table_count_limit;
-       u32 max_failure_limit;  /* # failed frames before new search */
-       u32 max_success_limit;  /* # successful frames before new search */
-       u32 table_count;
-       u32 total_failed;       /* total failed frames, any/all rates */
-       u32 total_success;      /* total successful frames, any/all rates */
-       u64 flush_timer;        /* time staying in mode before new search */
-
-       u8 action_counter;      /* # mode-switch actions tried */
-       u8 is_green;
-       u8 is_dup;
-       enum ieee80211_band band;
-
-       /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
-       u32 supp_rates;
-       u16 active_legacy_rate;
-       u16 active_siso_rate;
-       u16 active_mimo2_rate;
-       s8 max_rate_idx;     /* Max rate set by user */
-       u8 missed_rate_counter;
-
-       struct iwl_link_quality_cmd lq;
-       struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
-       struct iwl_traffic_load load[TID_MAX_LOAD_COUNT];
-       u8 tx_agg_tid_en;
-#ifdef CONFIG_MAC80211_DEBUGFS
-       struct dentry *rs_sta_dbgfs_scale_table_file;
-       struct dentry *rs_sta_dbgfs_stats_table_file;
-       struct dentry *rs_sta_dbgfs_rate_scale_data_file;
-       struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
-       u32 dbg_fixed_rate;
-#endif
-       struct iwl_priv *drv;
-
-       /* used to be in sta_info */
-       int last_txrate_idx;
-       /* last tx rate_n_flags */
-       u32 last_rate_n_flags;
-       /* packets destined for this STA are aggregated */
-       u8 is_agg;
-};
-
-static inline u8 iwl4965_num_of_ant(u8 mask)
-{
-       return  !!((mask) & ANT_A) +
-               !!((mask) & ANT_B) +
-               !!((mask) & ANT_C);
-}
-
-static inline u8 iwl4965_first_antenna(u8 mask)
-{
-       if (mask & ANT_A)
-               return ANT_A;
-       if (mask & ANT_B)
-               return ANT_B;
-       return ANT_C;
-}
-
-
-/**
- * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
- *
- * The specific throughput table used is based on the type of network
- * the associated with, including A, B, G, and G w/ TGG protection
- */
-extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
-
-/* Initialize station's rate scaling information after adding station */
-extern void iwl4965_rs_rate_init(struct iwl_priv *priv,
-                            struct ieee80211_sta *sta, u8 sta_id);
-extern void iwl3945_rs_rate_init(struct iwl_priv *priv,
-                                struct ieee80211_sta *sta, u8 sta_id);
-
-/**
- * iwl_rate_control_register - Register the rate control algorithm callbacks
- *
- * Since the rate control algorithm is hardware specific, there is no need
- * or reason to place it as a stand alone module.  The driver can call
- * iwl_rate_control_register in order to register the rate control callbacks
- * with the mac80211 subsystem.  This should be performed prior to calling
- * ieee80211_register_hw
- *
- */
-extern int iwl4965_rate_control_register(void);
-extern int iwl3945_rate_control_register(void);
-
-/**
- * iwl_rate_control_unregister - Unregister the rate control callbacks
- *
- * This should be called after calling ieee80211_unregister_hw, but before
- * the driver is unloaded.
- */
-extern void iwl4965_rate_control_unregister(void);
-extern void iwl3945_rate_control_unregister(void);
-
-#endif /* __iwl_legacy_rs__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-power.c b/drivers/net/wireless/iwlegacy/iwl-power.c
deleted file mode 100644 (file)
index 903ef0d..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include <net/mac80211.h>
-
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-commands.h"
-#include "iwl-debug.h"
-#include "iwl-power.h"
-
-/*
- * Setting power level allows the card to go to sleep when not busy.
- *
- * We calculate a sleep command based on the required latency, which
- * we get from mac80211. In order to handle thermal throttling, we can
- * also use pre-defined power levels.
- */
-
-/*
- * This defines the old power levels. They are still used by default
- * (level 1) and for thermal throttle (levels 3 through 5)
- */
-
-struct iwl_power_vec_entry {
-       struct iwl_powertable_cmd cmd;
-       u8 no_dtim;     /* number of skip dtim */
-};
-
-static void iwl_legacy_power_sleep_cam_cmd(struct iwl_priv *priv,
-                                   struct iwl_powertable_cmd *cmd)
-{
-       memset(cmd, 0, sizeof(*cmd));
-
-       if (priv->power_data.pci_pm)
-               cmd->flags |= IWL_POWER_PCI_PM_MSK;
-
-       IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
-}
-
-static int
-iwl_legacy_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
-{
-       IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
-       IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
-       IWL_DEBUG_POWER(priv, "Tx timeout = %u\n",
-                                       le32_to_cpu(cmd->tx_data_timeout));
-       IWL_DEBUG_POWER(priv, "Rx timeout = %u\n",
-                                       le32_to_cpu(cmd->rx_data_timeout));
-       IWL_DEBUG_POWER(priv,
-                       "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 iwl_legacy_send_cmd_pdu(priv, POWER_TABLE_CMD,
-                               sizeof(struct iwl_powertable_cmd), cmd);
-}
-
-int
-iwl_legacy_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
-                      bool force)
-{
-       int ret;
-       bool update_chains;
-
-       lockdep_assert_held(&priv->mutex);
-
-       /* Don't update the RX chain when chain noise calibration is running */
-       update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
-                       priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
-
-       if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
-               return 0;
-
-       if (!iwl_legacy_is_ready_rf(priv))
-               return -EIO;
-
-       /* scan complete use sleep_power_next, need to be updated */
-       memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
-       if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
-               IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
-               return 0;
-       }
-
-       if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
-               set_bit(STATUS_POWER_PMI, &priv->status);
-
-       ret = iwl_legacy_set_power(priv, cmd);
-       if (!ret) {
-               if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
-                       clear_bit(STATUS_POWER_PMI, &priv->status);
-
-               if (priv->cfg->ops->lib->update_chain_flags && update_chains)
-                       priv->cfg->ops->lib->update_chain_flags(priv);
-               else if (priv->cfg->ops->lib->update_chain_flags)
-                       IWL_DEBUG_POWER(priv,
-                                       "Cannot update the power, chain noise "
-                                       "calibration running: %d\n",
-                                       priv->chain_noise_data.state);
-
-               memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd));
-       } else
-               IWL_ERR(priv, "set power fail, ret = %d", ret);
-
-       return ret;
-}
-
-int iwl_legacy_power_update_mode(struct iwl_priv *priv, bool force)
-{
-       struct iwl_powertable_cmd cmd;
-
-       iwl_legacy_power_sleep_cam_cmd(priv, &cmd);
-       return iwl_legacy_power_set_mode(priv, &cmd, force);
-}
-EXPORT_SYMBOL(iwl_legacy_power_update_mode);
-
-/* initialize to default */
-void iwl_legacy_power_initialize(struct iwl_priv *priv)
-{
-       u16 lctl = iwl_legacy_pcie_link_ctl(priv);
-
-       priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
-
-       priv->power_data.debug_sleep_level_override = -1;
-
-       memset(&priv->power_data.sleep_cmd, 0,
-               sizeof(priv->power_data.sleep_cmd));
-}
-EXPORT_SYMBOL(iwl_legacy_power_initialize);
diff --git a/drivers/net/wireless/iwlegacy/iwl-power.h b/drivers/net/wireless/iwlegacy/iwl-power.h
deleted file mode 100644 (file)
index d30b36a..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-#ifndef __iwl_legacy_power_setting_h__
-#define __iwl_legacy_power_setting_h__
-
-#include "iwl-commands.h"
-
-enum iwl_power_level {
-       IWL_POWER_INDEX_1,
-       IWL_POWER_INDEX_2,
-       IWL_POWER_INDEX_3,
-       IWL_POWER_INDEX_4,
-       IWL_POWER_INDEX_5,
-       IWL_POWER_NUM
-};
-
-struct iwl_power_mgr {
-       struct iwl_powertable_cmd sleep_cmd;
-       struct iwl_powertable_cmd sleep_cmd_next;
-       int debug_sleep_level_override;
-       bool pci_pm;
-};
-
-int
-iwl_legacy_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
-                      bool force);
-int iwl_legacy_power_update_mode(struct iwl_priv *priv, bool force);
-void iwl_legacy_power_initialize(struct iwl_priv *priv);
-
-#endif  /* __iwl_legacy_power_setting_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-rx.c b/drivers/net/wireless/iwlegacy/iwl-rx.c
deleted file mode 100644 (file)
index f4d21ec..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/etherdevice.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <net/mac80211.h>
-#include <asm/unaligned.h>
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-sta.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-/************************** RX-FUNCTIONS ****************************/
-/*
- * Rx theory of operation
- *
- * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
- * each of which point to Receive Buffers to be filled by the NIC.  These get
- * used not only for Rx frames, but for any command response or notification
- * from the NIC.  The driver and NIC manage the Rx buffers by means
- * of indexes into the circular buffer.
- *
- * 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 iwl->rxq->rx_free.  When
- *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
- *   to replenish the iwl->rxq->rx_free.
- * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
- *   iwl->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 iwl->rxq.  The driver 'processed' index is updated.
- * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
- *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
- *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
- *   were enough free buffers and RX_STALLED is set it is cleared.
- *
- *
- * Driver sequence:
- *
- * iwl_legacy_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_legacy_rx_queue_space - Return number of free slots available in queue.
- */
-int iwl_legacy_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;
-}
-EXPORT_SYMBOL(iwl_legacy_rx_queue_space);
-
-/**
- * iwl_legacy_rx_queue_update_write_ptr - Update the write pointer for the RX queue
- */
-void
-iwl_legacy_rx_queue_update_write_ptr(struct iwl_priv *priv,
-                                       struct iwl_rx_queue *q)
-{
-       unsigned long flags;
-       u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
-       u32 reg;
-
-       spin_lock_irqsave(&q->lock, flags);
-
-       if (q->need_update == 0)
-               goto exit_unlock;
-
-       /* If power-saving is in use, make sure device is awake */
-       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_DEBUG_INFO(priv,
-                               "Rx queue requesting wakeup,"
-                               " GP1 = 0x%x\n", reg);
-                       iwl_legacy_set_bit(priv, CSR_GP_CNTRL,
-                               CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-                       goto exit_unlock;
-               }
-
-               q->write_actual = (q->write & ~0x7);
-               iwl_legacy_write_direct32(priv, rx_wrt_ptr_reg,
-                               q->write_actual);
-
-       /* Else device is assumed to be awake */
-       } else {
-               /* Device expects a multiple of 8 */
-               q->write_actual = (q->write & ~0x7);
-               iwl_legacy_write_direct32(priv, rx_wrt_ptr_reg,
-                       q->write_actual);
-       }
-
-       q->need_update = 0;
-
- exit_unlock:
-       spin_unlock_irqrestore(&q->lock, flags);
-}
-EXPORT_SYMBOL(iwl_legacy_rx_queue_update_write_ptr);
-
-int iwl_legacy_rx_queue_alloc(struct iwl_priv *priv)
-{
-       struct iwl_rx_queue *rxq = &priv->rxq;
-       struct device *dev = &priv->pci_dev->dev;
-       int i;
-
-       spin_lock_init(&rxq->lock);
-       INIT_LIST_HEAD(&rxq->rx_free);
-       INIT_LIST_HEAD(&rxq->rx_used);
-
-       /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
-       rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma,
-                                    GFP_KERNEL);
-       if (!rxq->bd)
-               goto err_bd;
-
-       rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
-                                         &rxq->rb_stts_dma, GFP_KERNEL);
-       if (!rxq->rb_stts)
-               goto err_rb;
-
-       /* 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->write_actual = 0;
-       rxq->free_count = 0;
-       rxq->need_update = 0;
-       return 0;
-
-err_rb:
-       dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-                         rxq->bd_dma);
-err_bd:
-       return -ENOMEM;
-}
-EXPORT_SYMBOL(iwl_legacy_rx_queue_alloc);
-
-
-void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,
-                                         struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
-
-       if (!report->state) {
-               IWL_DEBUG_11H(priv,
-                       "Spectrum Measure Notification: Start\n");
-               return;
-       }
-
-       memcpy(&priv->measure_report, report, sizeof(*report));
-       priv->measurement_status |= MEASUREMENT_READY;
-}
-EXPORT_SYMBOL(iwl_legacy_rx_spectrum_measure_notif);
-
-/*
- * returns non-zero if packet should be dropped
- */
-int iwl_legacy_set_decrypted_flag(struct iwl_priv *priv,
-                          struct ieee80211_hdr *hdr,
-                          u32 decrypt_res,
-                          struct ieee80211_rx_status *stats)
-{
-       u16 fc = le16_to_cpu(hdr->frame_control);
-
-       /*
-        * All contexts have the same setting here due to it being
-        * a module parameter, so OK to check any context.
-        */
-       if (priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags &
-                                               RXON_FILTER_DIS_DECRYPT_MSK)
-               return 0;
-
-       if (!(fc & IEEE80211_FCTL_PROTECTED))
-               return 0;
-
-       IWL_DEBUG_RX(priv, "decrypt_res:0x%x\n", decrypt_res);
-       switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
-       case RX_RES_STATUS_SEC_TYPE_TKIP:
-               /* The uCode has got a bad phase 1 Key, pushes the packet.
-                * Decryption will be done in SW. */
-               if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
-                   RX_RES_STATUS_BAD_KEY_TTAK)
-                       break;
-
-       case RX_RES_STATUS_SEC_TYPE_WEP:
-               if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
-                   RX_RES_STATUS_BAD_ICV_MIC) {
-                       /* bad ICV, the packet is destroyed since the
-                        * decryption is inplace, drop it */
-                       IWL_DEBUG_RX(priv, "Packet destroyed\n");
-                       return -1;
-               }
-       case RX_RES_STATUS_SEC_TYPE_CCMP:
-               if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
-                   RX_RES_STATUS_DECRYPT_OK) {
-                       IWL_DEBUG_RX(priv, "hw decrypt successfully!!!\n");
-                       stats->flag |= RX_FLAG_DECRYPTED;
-               }
-               break;
-
-       default:
-               break;
-       }
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_set_decrypted_flag);
diff --git a/drivers/net/wireless/iwlegacy/iwl-scan.c b/drivers/net/wireless/iwlegacy/iwl-scan.c
deleted file mode 100644 (file)
index 521b73b..0000000
+++ /dev/null
@@ -1,550 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/etherdevice.h>
-#include <linux/export.h>
-#include <net/mac80211.h>
-
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-sta.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-
-/* 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    (30)       /* all times in msec */
-#define IWL_ACTIVE_DWELL_TIME_52    (20)
-
-#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3)
-#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2)
-
-/* 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 int iwl_legacy_send_scan_abort(struct iwl_priv *priv)
-{
-       int ret;
-       struct iwl_rx_packet *pkt;
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_SCAN_ABORT_CMD,
-               .flags = CMD_WANT_SKB,
-       };
-
-       /* Exit instantly with error when device is not ready
-        * to receive scan abort command or it does not perform
-        * hardware scan currently */
-       if (!test_bit(STATUS_READY, &priv->status) ||
-           !test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
-           !test_bit(STATUS_SCAN_HW, &priv->status) ||
-           test_bit(STATUS_FW_ERROR, &priv->status) ||
-           test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return -EIO;
-
-       ret = iwl_legacy_send_cmd_sync(priv, &cmd);
-       if (ret)
-               return ret;
-
-       pkt = (struct iwl_rx_packet *)cmd.reply_page;
-       if (pkt->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_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
-               ret = -EIO;
-       }
-
-       iwl_legacy_free_pages(priv, cmd.reply_page);
-       return ret;
-}
-
-static void iwl_legacy_complete_scan(struct iwl_priv *priv, bool aborted)
-{
-       /* check if scan was requested from mac80211 */
-       if (priv->scan_request) {
-               IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
-               ieee80211_scan_completed(priv->hw, aborted);
-       }
-
-       priv->scan_vif = NULL;
-       priv->scan_request = NULL;
-}
-
-void iwl_legacy_force_scan_end(struct iwl_priv *priv)
-{
-       lockdep_assert_held(&priv->mutex);
-
-       if (!test_bit(STATUS_SCANNING, &priv->status)) {
-               IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
-               return;
-       }
-
-       IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
-       clear_bit(STATUS_SCANNING, &priv->status);
-       clear_bit(STATUS_SCAN_HW, &priv->status);
-       clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-       iwl_legacy_complete_scan(priv, true);
-}
-
-static void iwl_legacy_do_scan_abort(struct iwl_priv *priv)
-{
-       int ret;
-
-       lockdep_assert_held(&priv->mutex);
-
-       if (!test_bit(STATUS_SCANNING, &priv->status)) {
-               IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
-               return;
-       }
-
-       if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-               IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
-               return;
-       }
-
-       ret = iwl_legacy_send_scan_abort(priv);
-       if (ret) {
-               IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret);
-               iwl_legacy_force_scan_end(priv);
-       } else
-               IWL_DEBUG_SCAN(priv, "Successfully send scan abort\n");
-}
-
-/**
- * iwl_scan_cancel - Cancel any currently executing HW scan
- */
-int iwl_legacy_scan_cancel(struct iwl_priv *priv)
-{
-       IWL_DEBUG_SCAN(priv, "Queuing abort scan\n");
-       queue_work(priv->workqueue, &priv->abort_scan);
-       return 0;
-}
-EXPORT_SYMBOL(iwl_legacy_scan_cancel);
-
-/**
- * iwl_legacy_scan_cancel_timeout - Cancel any currently executing HW scan
- * @ms: amount of time to wait (in milliseconds) for scan to abort
- *
- */
-int iwl_legacy_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies(ms);
-
-       lockdep_assert_held(&priv->mutex);
-
-       IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
-
-       iwl_legacy_do_scan_abort(priv);
-
-       while (time_before_eq(jiffies, timeout)) {
-               if (!test_bit(STATUS_SCAN_HW, &priv->status))
-                       break;
-               msleep(20);
-       }
-
-       return test_bit(STATUS_SCAN_HW, &priv->status);
-}
-EXPORT_SYMBOL(iwl_legacy_scan_cancel_timeout);
-
-/* Service response to REPLY_SCAN_CMD (0x80) */
-static void iwl_legacy_rx_reply_scan(struct iwl_priv *priv,
-                             struct iwl_rx_mem_buffer *rxb)
-{
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_scanreq_notification *notif =
-           (struct iwl_scanreq_notification *)pkt->u.raw;
-
-       IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
-#endif
-}
-
-/* Service SCAN_START_NOTIFICATION (0x82) */
-static void iwl_legacy_rx_scan_start_notif(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       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(priv, "Scan start: "
-                      "%d [802.11%s] "
-                      "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
-                      notif->channel,
-                      notif->band ? "bg" : "a",
-                      le32_to_cpu(notif->tsf_high),
-                      le32_to_cpu(notif->tsf_low),
-                      notif->status, notif->beacon_timer);
-}
-
-/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
-static void iwl_legacy_rx_scan_results_notif(struct iwl_priv *priv,
-                                     struct iwl_rx_mem_buffer *rxb)
-{
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_scanresults_notification *notif =
-           (struct iwl_scanresults_notification *)pkt->u.raw;
-
-       IWL_DEBUG_SCAN(priv, "Scan ch.res: "
-                      "%d [802.11%s] "
-                      "(TSF: 0x%08X:%08X) - %d "
-                      "elapsed=%lu usec\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);
-#endif
-}
-
-/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
-static void iwl_legacy_rx_scan_complete_notif(struct iwl_priv *priv,
-                                      struct iwl_rx_mem_buffer *rxb)
-{
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
-#endif
-
-       IWL_DEBUG_SCAN(priv,
-                       "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);
-
-       IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
-                      (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
-                      jiffies_to_msecs(jiffies - priv->scan_start));
-
-       queue_work(priv->workqueue, &priv->scan_completed);
-}
-
-void iwl_legacy_setup_rx_scan_handlers(struct iwl_priv *priv)
-{
-       /* scan handlers */
-       priv->rx_handlers[REPLY_SCAN_CMD] = iwl_legacy_rx_reply_scan;
-       priv->rx_handlers[SCAN_START_NOTIFICATION] =
-                                       iwl_legacy_rx_scan_start_notif;
-       priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
-                                       iwl_legacy_rx_scan_results_notif;
-       priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
-                                       iwl_legacy_rx_scan_complete_notif;
-}
-EXPORT_SYMBOL(iwl_legacy_setup_rx_scan_handlers);
-
-inline u16 iwl_legacy_get_active_dwell_time(struct iwl_priv *priv,
-                                    enum ieee80211_band band,
-                                    u8 n_probes)
-{
-       if (band == IEEE80211_BAND_5GHZ)
-               return IWL_ACTIVE_DWELL_TIME_52 +
-                       IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1);
-       else
-               return IWL_ACTIVE_DWELL_TIME_24 +
-                       IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
-}
-EXPORT_SYMBOL(iwl_legacy_get_active_dwell_time);
-
-u16 iwl_legacy_get_passive_dwell_time(struct iwl_priv *priv,
-                              enum ieee80211_band band,
-                              struct ieee80211_vif *vif)
-{
-       struct iwl_rxon_context *ctx;
-       u16 passive = (band == IEEE80211_BAND_2GHZ) ?
-           IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
-           IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
-
-       if (iwl_legacy_is_any_associated(priv)) {
-               /*
-                * If we're associated, we clamp the maximum passive
-                * dwell time to be 98% of the smallest beacon interval
-                * (minus 2 * channel tune time)
-                */
-               for_each_context(priv, ctx) {
-                       u16 value;
-
-                       if (!iwl_legacy_is_associated_ctx(ctx))
-                               continue;
-                       value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
-                       if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
-                               value = IWL_PASSIVE_DWELL_BASE;
-                       value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
-                       passive = min(value, passive);
-               }
-       }
-
-       return passive;
-}
-EXPORT_SYMBOL(iwl_legacy_get_passive_dwell_time);
-
-void iwl_legacy_init_scan_params(struct iwl_priv *priv)
-{
-       u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
-       if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
-               priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
-       if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
-               priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
-}
-EXPORT_SYMBOL(iwl_legacy_init_scan_params);
-
-static int iwl_legacy_scan_initiate(struct iwl_priv *priv,
-                                   struct ieee80211_vif *vif)
-{
-       int ret;
-
-       lockdep_assert_held(&priv->mutex);
-
-       if (WARN_ON(!priv->cfg->ops->utils->request_scan))
-               return -EOPNOTSUPP;
-
-       cancel_delayed_work(&priv->scan_check);
-
-       if (!iwl_legacy_is_ready_rf(priv)) {
-               IWL_WARN(priv, "Request scan called when driver not ready.\n");
-               return -EIO;
-       }
-
-       if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-               IWL_DEBUG_SCAN(priv,
-                       "Multiple concurrent scan requests in parallel.\n");
-               return -EBUSY;
-       }
-
-       if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-               IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n");
-               return -EBUSY;
-       }
-
-       IWL_DEBUG_SCAN(priv, "Starting scan...\n");
-
-       set_bit(STATUS_SCANNING, &priv->status);
-       priv->scan_start = jiffies;
-
-       ret = priv->cfg->ops->utils->request_scan(priv, vif);
-       if (ret) {
-               clear_bit(STATUS_SCANNING, &priv->status);
-               return ret;
-       }
-
-       queue_delayed_work(priv->workqueue, &priv->scan_check,
-                          IWL_SCAN_CHECK_WATCHDOG);
-
-       return 0;
-}
-
-int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
-                   struct ieee80211_vif *vif,
-                   struct cfg80211_scan_request *req)
-{
-       struct iwl_priv *priv = hw->priv;
-       int ret;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (req->n_channels == 0)
-               return -EINVAL;
-
-       mutex_lock(&priv->mutex);
-
-       if (test_bit(STATUS_SCANNING, &priv->status)) {
-               IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
-               ret = -EAGAIN;
-               goto out_unlock;
-       }
-
-       /* mac80211 will only ask for one band at a time */
-       priv->scan_request = req;
-       priv->scan_vif = vif;
-       priv->scan_band = req->channels[0]->band;
-
-       ret = iwl_legacy_scan_initiate(priv, vif);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-out_unlock:
-       mutex_unlock(&priv->mutex);
-
-       return ret;
-}
-EXPORT_SYMBOL(iwl_legacy_mac_hw_scan);
-
-static void iwl_legacy_bg_scan_check(struct work_struct *data)
-{
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, scan_check.work);
-
-       IWL_DEBUG_SCAN(priv, "Scan check work\n");
-
-       /* Since we are here firmware does not finish scan and
-        * most likely is in bad shape, so we don't bother to
-        * send abort command, just force scan complete to mac80211 */
-       mutex_lock(&priv->mutex);
-       iwl_legacy_force_scan_end(priv);
-       mutex_unlock(&priv->mutex);
-}
-
-/**
- * iwl_legacy_fill_probe_req - fill in all required fields and IE for probe request
- */
-
-u16
-iwl_legacy_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
-                      const u8 *ta, const u8 *ies, int ie_len, int left)
-{
-       int len = 0;
-       u8 *pos = NULL;
-
-       /* Make sure there is enough space for the probe request,
-        * two mandatory IEs and the data */
-       left -= 24;
-       if (left < 0)
-               return 0;
-
-       frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
-       memcpy(frame->da, iwlegacy_bcast_addr, ETH_ALEN);
-       memcpy(frame->sa, ta, ETH_ALEN);
-       memcpy(frame->bssid, iwlegacy_bcast_addr, ETH_ALEN);
-       frame->seq_ctrl = 0;
-
-       len += 24;
-
-       /* ...next IE... */
-       pos = &frame->u.probe_req.variable[0];
-
-       /* fill in our indirect SSID IE */
-       left -= 2;
-       if (left < 0)
-               return 0;
-       *pos++ = WLAN_EID_SSID;
-       *pos++ = 0;
-
-       len += 2;
-
-       if (WARN_ON(left < ie_len))
-               return len;
-
-       if (ies && ie_len) {
-               memcpy(pos, ies, ie_len);
-               len += ie_len;
-       }
-
-       return (u16)len;
-}
-EXPORT_SYMBOL(iwl_legacy_fill_probe_req);
-
-static void iwl_legacy_bg_abort_scan(struct work_struct *work)
-{
-       struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
-
-       IWL_DEBUG_SCAN(priv, "Abort scan work\n");
-
-       /* We keep scan_check work queued in case when firmware will not
-        * report back scan completed notification */
-       mutex_lock(&priv->mutex);
-       iwl_legacy_scan_cancel_timeout(priv, 200);
-       mutex_unlock(&priv->mutex);
-}
-
-static void iwl_legacy_bg_scan_completed(struct work_struct *work)
-{
-       struct iwl_priv *priv =
-           container_of(work, struct iwl_priv, scan_completed);
-       bool aborted;
-
-       IWL_DEBUG_SCAN(priv, "Completed scan.\n");
-
-       cancel_delayed_work(&priv->scan_check);
-
-       mutex_lock(&priv->mutex);
-
-       aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-       if (aborted)
-               IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
-
-       if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) {
-               IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
-               goto out_settings;
-       }
-
-       iwl_legacy_complete_scan(priv, aborted);
-
-out_settings:
-       /* Can we still talk to firmware ? */
-       if (!iwl_legacy_is_ready_rf(priv))
-               goto out;
-
-       /*
-        * We do not commit power settings while scan is pending,
-        * do it now if the settings changed.
-        */
-       iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
-       iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
-
-       priv->cfg->ops->utils->post_scan(priv);
-
-out:
-       mutex_unlock(&priv->mutex);
-}
-
-void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv)
-{
-       INIT_WORK(&priv->scan_completed, iwl_legacy_bg_scan_completed);
-       INIT_WORK(&priv->abort_scan, iwl_legacy_bg_abort_scan);
-       INIT_DELAYED_WORK(&priv->scan_check, iwl_legacy_bg_scan_check);
-}
-EXPORT_SYMBOL(iwl_legacy_setup_scan_deferred_work);
-
-void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv)
-{
-       cancel_work_sync(&priv->abort_scan);
-       cancel_work_sync(&priv->scan_completed);
-
-       if (cancel_delayed_work_sync(&priv->scan_check)) {
-               mutex_lock(&priv->mutex);
-               iwl_legacy_force_scan_end(priv);
-               mutex_unlock(&priv->mutex);
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_cancel_scan_deferred_work);
index 9f70a4723103fa86a20149b0b8d76c19e46028e3..85fe48e520f9a75369078b63c7d4e1322c0be90e 100644 (file)
@@ -26,8 +26,8 @@
  *
  *****************************************************************************/
 
-#ifndef __iwl_legacy_spectrum_h__
-#define __iwl_legacy_spectrum_h__
+#ifndef __il_spectrum_h__
+#define __il_spectrum_h__
 enum {                         /* ieee80211_basic_report.map */
        IEEE80211_BASIC_MAP_BSS = (1 << 0),
        IEEE80211_BASIC_MAP_OFDM = (1 << 1),
index f10df3e2813a0c63f86429dd1344c8519222e369..75fe315f66b4d62904be032446851459b2cc9c2c 100644 (file)
 #include "iwl-core.h"
 #include "iwl-sta.h"
 
-/* priv->sta_lock must be held */
-static void iwl_legacy_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
+/* il->sta_lock must be held */
+static void il_sta_ucode_activate(struct il_priv *il, u8 sta_id)
 {
 
-       if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
-               IWL_ERR(priv,
+       if (!(il->stations[sta_id].used & IL_STA_DRIVER_ACTIVE))
+               IL_ERR(
                        "ACTIVATE a non DRIVER active station id %u addr %pM\n",
-                       sta_id, priv->stations[sta_id].sta.sta.addr);
+                       sta_id, il->stations[sta_id].sta.sta.addr);
 
-       if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) {
-               IWL_DEBUG_ASSOC(priv,
+       if (il->stations[sta_id].used & IL_STA_UCODE_ACTIVE) {
+               D_ASSOC(
                        "STA id %u addr %pM already present"
                        " in uCode (according to driver)\n",
-                       sta_id, priv->stations[sta_id].sta.sta.addr);
+                       sta_id, il->stations[sta_id].sta.sta.addr);
        } else {
-               priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
-               IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n",
-                               sta_id, priv->stations[sta_id].sta.sta.addr);
+               il->stations[sta_id].used |= IL_STA_UCODE_ACTIVE;
+               D_ASSOC("Added STA id %u addr %pM to uCode\n",
+                               sta_id, il->stations[sta_id].sta.sta.addr);
        }
 }
 
-static int iwl_legacy_process_add_sta_resp(struct iwl_priv *priv,
-                                   struct iwl_legacy_addsta_cmd *addsta,
-                                   struct iwl_rx_packet *pkt,
+static int il_process_add_sta_resp(struct il_priv *il,
+                                   struct il_addsta_cmd *addsta,
+                                   struct il_rx_pkt *pkt,
                                    bool sync)
 {
        u8 sta_id = addsta->sta.sta_id;
        unsigned long flags;
        int ret = -EIO;
 
-       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
+       if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
+               IL_ERR("Bad return from C_ADD_STA (0x%08X)\n",
                        pkt->hdr.flags);
                return ret;
        }
 
-       IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
+       D_INFO("Processing response for adding station %u\n",
                       sta_id);
 
-       spin_lock_irqsave(&priv->sta_lock, flags);
+       spin_lock_irqsave(&il->sta_lock, flags);
 
        switch (pkt->u.add_sta.status) {
        case ADD_STA_SUCCESS_MSK:
-               IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
-               iwl_legacy_sta_ucode_activate(priv, sta_id);
+               D_INFO("C_ADD_STA PASSED\n");
+               il_sta_ucode_activate(il, sta_id);
                ret = 0;
                break;
-       case ADD_STA_NO_ROOM_IN_TABLE:
-               IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
+       case ADD_STA_NO_ROOM_IN_TBL:
+               IL_ERR("Adding station %d failed, no room in table.\n",
                        sta_id);
                break;
        case ADD_STA_NO_BLOCK_ACK_RESOURCE:
-               IWL_ERR(priv,
+               IL_ERR(
                        "Adding station %d failed, no block ack resource.\n",
                        sta_id);
                break;
        case ADD_STA_MODIFY_NON_EXIST_STA:
-               IWL_ERR(priv, "Attempting to modify non-existing station %d\n",
+               IL_ERR("Attempting to modify non-existing station %d\n",
                        sta_id);
                break;
        default:
-               IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
+               D_ASSOC("Received C_ADD_STA:(0x%08X)\n",
                                pkt->u.add_sta.status);
                break;
        }
 
-       IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n",
-                      priv->stations[sta_id].sta.mode ==
+       D_INFO("%s station id %u addr %pM\n",
+                      il->stations[sta_id].sta.mode ==
                       STA_CONTROL_MODIFY_MSK ?  "Modified" : "Added",
-                      sta_id, priv->stations[sta_id].sta.sta.addr);
+                      sta_id, il->stations[sta_id].sta.sta.addr);
 
        /*
         * XXX: The MAC address in the command buffer is often changed from
@@ -116,68 +116,68 @@ static int iwl_legacy_process_add_sta_resp(struct iwl_priv *priv,
         * issue has not yet been resolved and this debugging is left to
         * observe the problem.
         */
-       IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n",
-                      priv->stations[sta_id].sta.mode ==
+       D_INFO("%s station according to cmd buffer %pM\n",
+                      il->stations[sta_id].sta.mode ==
                       STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
                       addsta->sta.addr);
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
+       spin_unlock_irqrestore(&il->sta_lock, flags);
 
        return ret;
 }
 
-static void iwl_legacy_add_sta_callback(struct iwl_priv *priv,
-                                struct iwl_device_cmd *cmd,
-                                struct iwl_rx_packet *pkt)
+static void il_add_sta_callback(struct il_priv *il,
+                                struct il_device_cmd *cmd,
+                                struct il_rx_pkt *pkt)
 {
-       struct iwl_legacy_addsta_cmd *addsta =
-               (struct iwl_legacy_addsta_cmd *)cmd->cmd.payload;
+       struct il_addsta_cmd *addsta =
+               (struct il_addsta_cmd *)cmd->cmd.payload;
 
-       iwl_legacy_process_add_sta_resp(priv, addsta, pkt, false);
+       il_process_add_sta_resp(il, addsta, pkt, false);
 
 }
 
-int iwl_legacy_send_add_sta(struct iwl_priv *priv,
-                    struct iwl_legacy_addsta_cmd *sta, u8 flags)
+int il_send_add_sta(struct il_priv *il,
+                    struct il_addsta_cmd *sta, u8 flags)
 {
-       struct iwl_rx_packet *pkt = NULL;
+       struct il_rx_pkt *pkt = NULL;
        int ret = 0;
        u8 data[sizeof(*sta)];
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_ADD_STA,
+       struct il_host_cmd cmd = {
+               .id = C_ADD_STA,
                .flags = flags,
                .data = data,
        };
        u8 sta_id __maybe_unused = sta->sta.sta_id;
 
-       IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n",
+       D_INFO("Adding sta %u (%pM) %ssynchronously\n",
                       sta_id, sta->sta.addr, flags & CMD_ASYNC ?  "a" : "");
 
        if (flags & CMD_ASYNC)
-               cmd.callback = iwl_legacy_add_sta_callback;
+               cmd.callback = il_add_sta_callback;
        else {
                cmd.flags |= CMD_WANT_SKB;
                might_sleep();
        }
 
-       cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
-       ret = iwl_legacy_send_cmd(priv, &cmd);
+       cmd.len = il->cfg->ops->utils->build_addsta_hcmd(sta, data);
+       ret = il_send_cmd(il, &cmd);
 
        if (ret || (flags & CMD_ASYNC))
                return ret;
 
        if (ret == 0) {
-               pkt = (struct iwl_rx_packet *)cmd.reply_page;
-               ret = iwl_legacy_process_add_sta_resp(priv, sta, pkt, true);
+               pkt = (struct il_rx_pkt *)cmd.reply_page;
+               ret = il_process_add_sta_resp(il, sta, pkt, true);
        }
-       iwl_legacy_free_pages(priv, cmd.reply_page);
+       il_free_pages(il, cmd.reply_page);
 
        return ret;
 }
-EXPORT_SYMBOL(iwl_legacy_send_add_sta);
+EXPORT_SYMBOL(il_send_add_sta);
 
-static void iwl_legacy_set_ht_add_station(struct iwl_priv *priv, u8 index,
+static void il_set_ht_add_station(struct il_priv *il, u8 idx,
                                   struct ieee80211_sta *sta,
-                                  struct iwl_rxon_context *ctx)
+                                  struct il_rxon_context *ctx)
 {
        struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
        __le32 sta_flags;
@@ -187,13 +187,13 @@ static void iwl_legacy_set_ht_add_station(struct iwl_priv *priv, u8 index,
                goto done;
 
        mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
-       IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
+       D_ASSOC("spatial multiplexing power save mode: %s\n",
                        (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
                        "static" :
                        (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
                        "dynamic" : "disabled");
 
-       sta_flags = priv->stations[index].sta.station_flags;
+       sta_flags = il->stations[idx].sta.station_flags;
 
        sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
 
@@ -207,7 +207,7 @@ static void iwl_legacy_set_ht_add_station(struct iwl_priv *priv, u8 index,
        case WLAN_HT_CAP_SM_PS_DISABLED:
                break;
        default:
-               IWL_WARN(priv, "Invalid MIMO PS mode %d\n", mimo_ps_mode);
+               IL_WARN("Invalid MIMO PS mode %d\n", mimo_ps_mode);
                break;
        }
 
@@ -217,27 +217,27 @@ static void iwl_legacy_set_ht_add_station(struct iwl_priv *priv, u8 index,
        sta_flags |= cpu_to_le32(
              (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
 
-       if (iwl_legacy_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
+       if (il_is_ht40_tx_allowed(il, ctx, &sta->ht_cap))
                sta_flags |= STA_FLG_HT40_EN_MSK;
        else
                sta_flags &= ~STA_FLG_HT40_EN_MSK;
 
-       priv->stations[index].sta.station_flags = sta_flags;
+       il->stations[idx].sta.station_flags = sta_flags;
  done:
        return;
 }
 
 /**
- * iwl_legacy_prep_station - Prepare station information for addition
+ * il_prep_station - Prepare station information for addition
  *
  * should be called with sta_lock held
  */
-u8 iwl_legacy_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+u8 il_prep_station(struct il_priv *il, struct il_rxon_context *ctx,
                    const u8 *addr, bool is_ap, struct ieee80211_sta *sta)
 {
-       struct iwl_station_entry *station;
+       struct il_station_entry *station;
        int i;
-       u8 sta_id = IWL_INVALID_STATION;
+       u8 sta_id = IL_INVALID_STATION;
        u16 rate;
 
        if (is_ap)
@@ -245,15 +245,15 @@ u8 iwl_legacy_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
        else if (is_broadcast_ether_addr(addr))
                sta_id = ctx->bcast_sta_id;
        else
-               for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
-                       if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+               for (i = IL_STA_ID; i < il->hw_params.max_stations; i++) {
+                       if (!compare_ether_addr(il->stations[i].sta.sta.addr,
                                                addr)) {
                                sta_id = i;
                                break;
                        }
 
-                       if (!priv->stations[i].used &&
-                           sta_id == IWL_INVALID_STATION)
+                       if (!il->stations[i].used &&
+                           sta_id == IL_INVALID_STATION)
                                sta_id = i;
                }
 
@@ -261,7 +261,7 @@ u8 iwl_legacy_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
         * These two conditions have the same outcome, but keep them
         * separate
         */
-       if (unlikely(sta_id == IWL_INVALID_STATION))
+       if (unlikely(sta_id == IL_INVALID_STATION))
                return sta_id;
 
        /*
@@ -269,30 +269,30 @@ u8 iwl_legacy_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
         * station. Keep track if one is in progress so that we do not send
         * another.
         */
-       if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
-               IWL_DEBUG_INFO(priv,
+       if (il->stations[sta_id].used & IL_STA_UCODE_INPROGRESS) {
+               D_INFO(
                                "STA %d already in process of being added.\n",
                                sta_id);
                return sta_id;
        }
 
-       if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
-           (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) &&
-           !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) {
-               IWL_DEBUG_ASSOC(priv,
+       if ((il->stations[sta_id].used & IL_STA_DRIVER_ACTIVE) &&
+           (il->stations[sta_id].used & IL_STA_UCODE_ACTIVE) &&
+           !compare_ether_addr(il->stations[sta_id].sta.sta.addr, addr)) {
+               D_ASSOC(
                                "STA %d (%pM) already added, not adding again.\n",
                                sta_id, addr);
                return sta_id;
        }
 
-       station = &priv->stations[sta_id];
-       station->used = IWL_STA_DRIVER_ACTIVE;
-       IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n",
+       station = &il->stations[sta_id];
+       station->used = IL_STA_DRIVER_ACTIVE;
+       D_ASSOC("Add STA to driver ID %d: %pM\n",
                        sta_id, addr);
-       priv->num_stations++;
+       il->num_stations++;
 
-       /* Set up the REPLY_ADD_STA command to send to device */
-       memset(&station->sta, 0, sizeof(struct iwl_legacy_addsta_cmd));
+       /* Set up the C_ADD_STA command to send to device */
+       memset(&station->sta, 0, sizeof(struct il_addsta_cmd));
        memcpy(station->sta.sta.addr, addr, ETH_ALEN);
        station->sta.mode = 0;
        station->sta.sta.sta_id = sta_id;
@@ -300,7 +300,7 @@ u8 iwl_legacy_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
        station->ctxid = ctx->ctxid;
 
        if (sta) {
-               struct iwl_station_priv_common *sta_priv;
+               struct il_station_priv_common *sta_priv;
 
                sta_priv = (void *)sta->drv_priv;
                sta_priv->ctx = ctx;
@@ -311,42 +311,42 @@ u8 iwl_legacy_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
         * STA and broadcast STA) pass in a NULL sta, and mac80211
         * doesn't allow HT IBSS.
         */
-       iwl_legacy_set_ht_add_station(priv, sta_id, sta, ctx);
+       il_set_ht_add_station(il, sta_id, sta, ctx);
 
        /* 3945 only */
-       rate = (priv->band == IEEE80211_BAND_5GHZ) ?
-               IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP;
+       rate = (il->band == IEEE80211_BAND_5GHZ) ?
+               RATE_6M_PLCP : RATE_1M_PLCP;
        /* Turn on both antennas for the station... */
        station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK);
 
        return sta_id;
 
 }
-EXPORT_SYMBOL_GPL(iwl_legacy_prep_station);
+EXPORT_SYMBOL_GPL(il_prep_station);
 
 #define STA_WAIT_TIMEOUT (HZ/2)
 
 /**
- * iwl_legacy_add_station_common -
+ * il_add_station_common -
  */
 int
-iwl_legacy_add_station_common(struct iwl_priv *priv,
-                       struct iwl_rxon_context *ctx,
+il_add_station_common(struct il_priv *il,
+                       struct il_rxon_context *ctx,
                           const u8 *addr, bool is_ap,
                           struct ieee80211_sta *sta, u8 *sta_id_r)
 {
        unsigned long flags_spin;
        int ret = 0;
        u8 sta_id;
-       struct iwl_legacy_addsta_cmd sta_cmd;
+       struct il_addsta_cmd sta_cmd;
 
        *sta_id_r = 0;
-       spin_lock_irqsave(&priv->sta_lock, flags_spin);
-       sta_id = iwl_legacy_prep_station(priv, ctx, addr, is_ap, sta);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
+       spin_lock_irqsave(&il->sta_lock, flags_spin);
+       sta_id = il_prep_station(il, ctx, addr, is_ap, sta);
+       if (sta_id == IL_INVALID_STATION) {
+               IL_ERR("Unable to prepare station %pM for addition\n",
                        addr);
-               spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
                return -EINVAL;
        }
 
@@ -355,75 +355,75 @@ iwl_legacy_add_station_common(struct iwl_priv *priv,
         * station. Keep track if one is in progress so that we do not send
         * another.
         */
-       if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
-               IWL_DEBUG_INFO(priv,
+       if (il->stations[sta_id].used & IL_STA_UCODE_INPROGRESS) {
+               D_INFO(
                        "STA %d already in process of being added.\n",
                       sta_id);
-               spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
                return -EEXIST;
        }
 
-       if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
-           (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
-               IWL_DEBUG_ASSOC(priv,
+       if ((il->stations[sta_id].used & IL_STA_DRIVER_ACTIVE) &&
+           (il->stations[sta_id].used & IL_STA_UCODE_ACTIVE)) {
+               D_ASSOC(
                        "STA %d (%pM) already added, not adding again.\n",
                        sta_id, addr);
-               spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
                return -EEXIST;
        }
 
-       priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
-       memcpy(&sta_cmd, &priv->stations[sta_id].sta,
-                               sizeof(struct iwl_legacy_addsta_cmd));
-       spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+       il->stations[sta_id].used |= IL_STA_UCODE_INPROGRESS;
+       memcpy(&sta_cmd, &il->stations[sta_id].sta,
+                               sizeof(struct il_addsta_cmd));
+       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
 
        /* Add station to device's station table */
-       ret = iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+       ret = il_send_add_sta(il, &sta_cmd, CMD_SYNC);
        if (ret) {
-               spin_lock_irqsave(&priv->sta_lock, flags_spin);
-               IWL_ERR(priv, "Adding station %pM failed.\n",
-                       priv->stations[sta_id].sta.sta.addr);
-               priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
-               priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
-               spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+               spin_lock_irqsave(&il->sta_lock, flags_spin);
+               IL_ERR("Adding station %pM failed.\n",
+                       il->stations[sta_id].sta.sta.addr);
+               il->stations[sta_id].used &= ~IL_STA_DRIVER_ACTIVE;
+               il->stations[sta_id].used &= ~IL_STA_UCODE_INPROGRESS;
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
        }
        *sta_id_r = sta_id;
        return ret;
 }
-EXPORT_SYMBOL(iwl_legacy_add_station_common);
+EXPORT_SYMBOL(il_add_station_common);
 
 /**
- * iwl_legacy_sta_ucode_deactivate - deactivate ucode status for a station
+ * il_sta_ucode_deactivate - deactivate ucode status for a station
  *
- * priv->sta_lock must be held
+ * il->sta_lock must be held
  */
-static void iwl_legacy_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
+static void il_sta_ucode_deactivate(struct il_priv *il, u8 sta_id)
 {
        /* Ucode must be active and driver must be non active */
-       if ((priv->stations[sta_id].used &
-            (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) !=
-                                               IWL_STA_UCODE_ACTIVE)
-               IWL_ERR(priv, "removed non active STA %u\n", sta_id);
+       if ((il->stations[sta_id].used &
+            (IL_STA_UCODE_ACTIVE | IL_STA_DRIVER_ACTIVE)) !=
+                                               IL_STA_UCODE_ACTIVE)
+               IL_ERR("removed non active STA %u\n", sta_id);
 
-       priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
+       il->stations[sta_id].used &= ~IL_STA_UCODE_ACTIVE;
 
-       memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry));
-       IWL_DEBUG_ASSOC(priv, "Removed STA %u\n", sta_id);
+       memset(&il->stations[sta_id], 0, sizeof(struct il_station_entry));
+       D_ASSOC("Removed STA %u\n", sta_id);
 }
 
-static int iwl_legacy_send_remove_station(struct iwl_priv *priv,
+static int il_send_remove_station(struct il_priv *il,
                                   const u8 *addr, int sta_id,
                                   bool temporary)
 {
-       struct iwl_rx_packet *pkt;
+       struct il_rx_pkt *pkt;
        int ret;
 
        unsigned long flags_spin;
-       struct iwl_rem_sta_cmd rm_sta_cmd;
+       struct il_rem_sta_cmd rm_sta_cmd;
 
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_REMOVE_STA,
-               .len = sizeof(struct iwl_rem_sta_cmd),
+       struct il_host_cmd cmd = {
+               .id = C_REM_STA,
+               .len = sizeof(struct il_rem_sta_cmd),
                .flags = CMD_SYNC,
                .data = &rm_sta_cmd,
        };
@@ -434,14 +434,14 @@ static int iwl_legacy_send_remove_station(struct iwl_priv *priv,
 
        cmd.flags |= CMD_WANT_SKB;
 
-       ret = iwl_legacy_send_cmd(priv, &cmd);
+       ret = il_send_cmd(il, &cmd);
 
        if (ret)
                return ret;
 
-       pkt = (struct iwl_rx_packet *)cmd.reply_page;
-       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
+       pkt = (struct il_rx_pkt *)cmd.reply_page;
+       if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
+               IL_ERR("Bad return from C_REM_STA (0x%08X)\n",
                          pkt->hdr.flags);
                ret = -EIO;
        }
@@ -450,34 +450,34 @@ static int iwl_legacy_send_remove_station(struct iwl_priv *priv,
                switch (pkt->u.rem_sta.status) {
                case REM_STA_SUCCESS_MSK:
                        if (!temporary) {
-                               spin_lock_irqsave(&priv->sta_lock, flags_spin);
-                               iwl_legacy_sta_ucode_deactivate(priv, sta_id);
-                               spin_unlock_irqrestore(&priv->sta_lock,
+                               spin_lock_irqsave(&il->sta_lock, flags_spin);
+                               il_sta_ucode_deactivate(il, sta_id);
+                               spin_unlock_irqrestore(&il->sta_lock,
                                                                flags_spin);
                        }
-                       IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
+                       D_ASSOC("C_REM_STA PASSED\n");
                        break;
                default:
                        ret = -EIO;
-                       IWL_ERR(priv, "REPLY_REMOVE_STA failed\n");
+                       IL_ERR("C_REM_STA failed\n");
                        break;
                }
        }
-       iwl_legacy_free_pages(priv, cmd.reply_page);
+       il_free_pages(il, cmd.reply_page);
 
        return ret;
 }
 
 /**
- * iwl_legacy_remove_station - Remove driver's knowledge of station.
+ * il_remove_station - Remove driver's knowledge of station.
  */
-int iwl_legacy_remove_station(struct iwl_priv *priv, const u8 sta_id,
+int il_remove_station(struct il_priv *il, const u8 sta_id,
                       const u8 *addr)
 {
        unsigned long flags;
 
-       if (!iwl_legacy_is_ready(priv)) {
-               IWL_DEBUG_INFO(priv,
+       if (!il_is_ready(il)) {
+               D_INFO(
                        "Unable to remove station %pM, device not ready.\n",
                        addr);
                /*
@@ -488,85 +488,85 @@ int iwl_legacy_remove_station(struct iwl_priv *priv, const u8 sta_id,
                return 0;
        }
 
-       IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d  %pM\n",
+       D_ASSOC("Removing STA from driver:%d  %pM\n",
                        sta_id, addr);
 
-       if (WARN_ON(sta_id == IWL_INVALID_STATION))
+       if (WARN_ON(sta_id == IL_INVALID_STATION))
                return -EINVAL;
 
-       spin_lock_irqsave(&priv->sta_lock, flags);
+       spin_lock_irqsave(&il->sta_lock, flags);
 
-       if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
-               IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
+       if (!(il->stations[sta_id].used & IL_STA_DRIVER_ACTIVE)) {
+               D_INFO("Removing %pM but non DRIVER active\n",
                                addr);
                goto out_err;
        }
 
-       if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
-               IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n",
+       if (!(il->stations[sta_id].used & IL_STA_UCODE_ACTIVE)) {
+               D_INFO("Removing %pM but non UCODE active\n",
                                addr);
                goto out_err;
        }
 
-       if (priv->stations[sta_id].used & IWL_STA_LOCAL) {
-               kfree(priv->stations[sta_id].lq);
-               priv->stations[sta_id].lq = NULL;
+       if (il->stations[sta_id].used & IL_STA_LOCAL) {
+               kfree(il->stations[sta_id].lq);
+               il->stations[sta_id].lq = NULL;
        }
 
-       priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+       il->stations[sta_id].used &= ~IL_STA_DRIVER_ACTIVE;
 
-       priv->num_stations--;
+       il->num_stations--;
 
-       BUG_ON(priv->num_stations < 0);
+       BUG_ON(il->num_stations < 0);
 
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
+       spin_unlock_irqrestore(&il->sta_lock, flags);
 
-       return iwl_legacy_send_remove_station(priv, addr, sta_id, false);
+       return il_send_remove_station(il, addr, sta_id, false);
 out_err:
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
+       spin_unlock_irqrestore(&il->sta_lock, flags);
        return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(iwl_legacy_remove_station);
+EXPORT_SYMBOL_GPL(il_remove_station);
 
 /**
- * iwl_legacy_clear_ucode_stations - clear ucode station table bits
+ * il_clear_ucode_stations - clear ucode station table bits
  *
  * This function clears all the bits in the driver indicating
  * which stations are active in the ucode. Call when something
  * other than explicit station management would cause this in
  * the ucode, e.g. unassociated RXON.
  */
-void iwl_legacy_clear_ucode_stations(struct iwl_priv *priv,
-                             struct iwl_rxon_context *ctx)
+void il_clear_ucode_stations(struct il_priv *il,
+                             struct il_rxon_context *ctx)
 {
        int i;
        unsigned long flags_spin;
        bool cleared = false;
 
-       IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
+       D_INFO("Clearing ucode stations in driver\n");
 
-       spin_lock_irqsave(&priv->sta_lock, flags_spin);
-       for (i = 0; i < priv->hw_params.max_stations; i++) {
-               if (ctx && ctx->ctxid != priv->stations[i].ctxid)
+       spin_lock_irqsave(&il->sta_lock, flags_spin);
+       for (i = 0; i < il->hw_params.max_stations; i++) {
+               if (ctx && ctx->ctxid != il->stations[i].ctxid)
                        continue;
 
-               if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
-                       IWL_DEBUG_INFO(priv,
+               if (il->stations[i].used & IL_STA_UCODE_ACTIVE) {
+                       D_INFO(
                                "Clearing ucode active for station %d\n", i);
-                       priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
+                       il->stations[i].used &= ~IL_STA_UCODE_ACTIVE;
                        cleared = true;
                }
        }
-       spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
 
        if (!cleared)
-               IWL_DEBUG_INFO(priv,
+               D_INFO(
                        "No active stations found to be cleared\n");
 }
-EXPORT_SYMBOL(iwl_legacy_clear_ucode_stations);
+EXPORT_SYMBOL(il_clear_ucode_stations);
 
 /**
- * iwl_legacy_restore_stations() - Restore driver known stations to device
+ * il_restore_stations() - Restore driver known stations to device
  *
  * All stations considered active by driver, but not present in ucode, is
  * restored.
@@ -574,58 +574,58 @@ EXPORT_SYMBOL(iwl_legacy_clear_ucode_stations);
  * Function sleeps.
  */
 void
-iwl_legacy_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx)
 {
-       struct iwl_legacy_addsta_cmd sta_cmd;
-       struct iwl_link_quality_cmd lq;
+       struct il_addsta_cmd sta_cmd;
+       struct il_link_quality_cmd lq;
        unsigned long flags_spin;
        int i;
        bool found = false;
        int ret;
        bool send_lq;
 
-       if (!iwl_legacy_is_ready(priv)) {
-               IWL_DEBUG_INFO(priv,
+       if (!il_is_ready(il)) {
+               D_INFO(
                        "Not ready yet, not restoring any stations.\n");
                return;
        }
 
-       IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
-       spin_lock_irqsave(&priv->sta_lock, flags_spin);
-       for (i = 0; i < priv->hw_params.max_stations; i++) {
-               if (ctx->ctxid != priv->stations[i].ctxid)
+       D_ASSOC("Restoring all known stations ... start.\n");
+       spin_lock_irqsave(&il->sta_lock, flags_spin);
+       for (i = 0; i < il->hw_params.max_stations; i++) {
+               if (ctx->ctxid != il->stations[i].ctxid)
                        continue;
-               if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) &&
-                           !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) {
-                       IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n",
-                                       priv->stations[i].sta.sta.addr);
-                       priv->stations[i].sta.mode = 0;
-                       priv->stations[i].used |= IWL_STA_UCODE_INPROGRESS;
+               if ((il->stations[i].used & IL_STA_DRIVER_ACTIVE) &&
+                   !(il->stations[i].used & IL_STA_UCODE_ACTIVE)) {
+                       D_ASSOC("Restoring sta %pM\n",
+                                       il->stations[i].sta.sta.addr);
+                       il->stations[i].sta.mode = 0;
+                       il->stations[i].used |= IL_STA_UCODE_INPROGRESS;
                        found = true;
                }
        }
 
-       for (i = 0; i < priv->hw_params.max_stations; i++) {
-               if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) {
-                       memcpy(&sta_cmd, &priv->stations[i].sta,
-                              sizeof(struct iwl_legacy_addsta_cmd));
+       for (i = 0; i < il->hw_params.max_stations; i++) {
+               if ((il->stations[i].used & IL_STA_UCODE_INPROGRESS)) {
+                       memcpy(&sta_cmd, &il->stations[i].sta,
+                              sizeof(struct il_addsta_cmd));
                        send_lq = false;
-                       if (priv->stations[i].lq) {
-                               memcpy(&lq, priv->stations[i].lq,
-                                      sizeof(struct iwl_link_quality_cmd));
+                       if (il->stations[i].lq) {
+                               memcpy(&lq, il->stations[i].lq,
+                                      sizeof(struct il_link_quality_cmd));
                                send_lq = true;
                        }
-                       spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-                       ret = iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+                       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
+                       ret = il_send_add_sta(il, &sta_cmd, CMD_SYNC);
                        if (ret) {
-                               spin_lock_irqsave(&priv->sta_lock, flags_spin);
-                               IWL_ERR(priv, "Adding station %pM failed.\n",
-                                       priv->stations[i].sta.sta.addr);
-                               priv->stations[i].used &=
-                                               ~IWL_STA_DRIVER_ACTIVE;
-                               priv->stations[i].used &=
-                                               ~IWL_STA_UCODE_INPROGRESS;
-                               spin_unlock_irqrestore(&priv->sta_lock,
+                               spin_lock_irqsave(&il->sta_lock, flags_spin);
+                               IL_ERR("Adding station %pM failed.\n",
+                                       il->stations[i].sta.sta.addr);
+                               il->stations[i].used &=
+                                               ~IL_STA_DRIVER_ACTIVE;
+                               il->stations[i].used &=
+                                               ~IL_STA_UCODE_INPROGRESS;
+                               spin_unlock_irqrestore(&il->sta_lock,
                                                                flags_spin);
                        }
                        /*
@@ -633,78 +633,78 @@ iwl_legacy_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
                         * current LQ command
                         */
                        if (send_lq)
-                               iwl_legacy_send_lq_cmd(priv, ctx, &lq,
+                               il_send_lq_cmd(il, ctx, &lq,
                                                                CMD_SYNC, true);
-                       spin_lock_irqsave(&priv->sta_lock, flags_spin);
-                       priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
+                       spin_lock_irqsave(&il->sta_lock, flags_spin);
+                       il->stations[i].used &= ~IL_STA_UCODE_INPROGRESS;
                }
        }
 
-       spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
        if (!found)
-               IWL_DEBUG_INFO(priv, "Restoring all known stations"
+               D_INFO("Restoring all known stations"
                                " .... no stations to be restored.\n");
        else
-               IWL_DEBUG_INFO(priv, "Restoring all known stations"
+               D_INFO("Restoring all known stations"
                                " .... complete.\n");
 }
-EXPORT_SYMBOL(iwl_legacy_restore_stations);
+EXPORT_SYMBOL(il_restore_stations);
 
-int iwl_legacy_get_free_ucode_key_index(struct iwl_priv *priv)
+int il_get_free_ucode_key_idx(struct il_priv *il)
 {
        int i;
 
-       for (i = 0; i < priv->sta_key_max_num; i++)
-               if (!test_and_set_bit(i, &priv->ucode_key_table))
+       for (i = 0; i < il->sta_key_max_num; i++)
+               if (!test_and_set_bit(i, &il->ucode_key_table))
                        return i;
 
        return WEP_INVALID_OFFSET;
 }
-EXPORT_SYMBOL(iwl_legacy_get_free_ucode_key_index);
+EXPORT_SYMBOL(il_get_free_ucode_key_idx);
 
-void iwl_legacy_dealloc_bcast_stations(struct iwl_priv *priv)
+void il_dealloc_bcast_stations(struct il_priv *il)
 {
        unsigned long flags;
        int i;
 
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       for (i = 0; i < priv->hw_params.max_stations; i++) {
-               if (!(priv->stations[i].used & IWL_STA_BCAST))
+       spin_lock_irqsave(&il->sta_lock, flags);
+       for (i = 0; i < il->hw_params.max_stations; i++) {
+               if (!(il->stations[i].used & IL_STA_BCAST))
                        continue;
 
-               priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
-               priv->num_stations--;
-               BUG_ON(priv->num_stations < 0);
-               kfree(priv->stations[i].lq);
-               priv->stations[i].lq = NULL;
+               il->stations[i].used &= ~IL_STA_UCODE_ACTIVE;
+               il->num_stations--;
+               BUG_ON(il->num_stations < 0);
+               kfree(il->stations[i].lq);
+               il->stations[i].lq = NULL;
        }
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
+       spin_unlock_irqrestore(&il->sta_lock, flags);
 }
-EXPORT_SYMBOL_GPL(iwl_legacy_dealloc_bcast_stations);
+EXPORT_SYMBOL_GPL(il_dealloc_bcast_stations);
 
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-static void iwl_legacy_dump_lq_cmd(struct iwl_priv *priv,
-                          struct iwl_link_quality_cmd *lq)
+#ifdef CONFIG_IWLEGACY_DEBUG
+static void il_dump_lq_cmd(struct il_priv *il,
+                          struct il_link_quality_cmd *lq)
 {
        int i;
-       IWL_DEBUG_RATE(priv, "lq station id 0x%x\n", lq->sta_id);
-       IWL_DEBUG_RATE(priv, "lq ant 0x%X 0x%X\n",
+       D_RATE("lq station id 0x%x\n", lq->sta_id);
+       D_RATE("lq ant 0x%X 0x%X\n",
                       lq->general_params.single_stream_ant_msk,
                       lq->general_params.dual_stream_ant_msk);
 
        for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
-               IWL_DEBUG_RATE(priv, "lq index %d 0x%X\n",
+               D_RATE("lq idx %d 0x%X\n",
                               i, lq->rs_table[i].rate_n_flags);
 }
 #else
-static inline void iwl_legacy_dump_lq_cmd(struct iwl_priv *priv,
-                                  struct iwl_link_quality_cmd *lq)
+static inline void il_dump_lq_cmd(struct il_priv *il,
+                                  struct il_link_quality_cmd *lq)
 {
 }
 #endif
 
 /**
- * iwl_legacy_is_lq_table_valid() - Test one aspect of LQ cmd for validity
+ * il_is_lq_table_valid() - Test one aspect of LQ cmd for validity
  *
  * It sometimes happens when a HT rate has been in use and we
  * loose connectivity with AP then mac80211 will first tell us that the
@@ -714,22 +714,22 @@ static inline void iwl_legacy_dump_lq_cmd(struct iwl_priv *priv,
  * Test for this to prevent driver from sending LQ command between the time
  * RXON flags are updated and when LQ command is updated.
  */
-static bool iwl_legacy_is_lq_table_valid(struct iwl_priv *priv,
-                             struct iwl_rxon_context *ctx,
-                             struct iwl_link_quality_cmd *lq)
+static bool il_is_lq_table_valid(struct il_priv *il,
+                             struct il_rxon_context *ctx,
+                             struct il_link_quality_cmd *lq)
 {
        int i;
 
        if (ctx->ht.enabled)
                return true;
 
-       IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n",
+       D_INFO("Channel %u is not an HT channel\n",
                       ctx->active.channel);
        for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
                if (le32_to_cpu(lq->rs_table[i].rate_n_flags) &
                                                RATE_MCS_HT_MSK) {
-                       IWL_DEBUG_INFO(priv,
-                                      "index %d of LQ expects HT channel\n",
+                       D_INFO(
+                                      "idx %d of LQ expects HT channel\n",
                                       i);
                        return false;
                }
@@ -738,7 +738,7 @@ static bool iwl_legacy_is_lq_table_valid(struct iwl_priv *priv,
 }
 
 /**
- * iwl_legacy_send_lq_cmd() - Send link quality command
+ * il_send_lq_cmd() - Send link quality command
  * @init: This command is sent as part of station initialization right
  *        after station has been added.
  *
@@ -747,35 +747,35 @@ static bool iwl_legacy_is_lq_table_valid(struct iwl_priv *priv,
  * this case to clear the state indicating that station creation is in
  * progress.
  */
-int iwl_legacy_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
-                   struct iwl_link_quality_cmd *lq, u8 flags, bool init)
+int il_send_lq_cmd(struct il_priv *il, struct il_rxon_context *ctx,
+                   struct il_link_quality_cmd *lq, u8 flags, bool init)
 {
        int ret = 0;
        unsigned long flags_spin;
 
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_TX_LINK_QUALITY_CMD,
-               .len = sizeof(struct iwl_link_quality_cmd),
+       struct il_host_cmd cmd = {
+               .id = C_TX_LINK_QUALITY_CMD,
+               .len = sizeof(struct il_link_quality_cmd),
                .flags = flags,
                .data = lq,
        };
 
-       if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
+       if (WARN_ON(lq->sta_id == IL_INVALID_STATION))
                return -EINVAL;
 
 
-       spin_lock_irqsave(&priv->sta_lock, flags_spin);
-       if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
-               spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+       spin_lock_irqsave(&il->sta_lock, flags_spin);
+       if (!(il->stations[lq->sta_id].used & IL_STA_DRIVER_ACTIVE)) {
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
                return -EINVAL;
        }
-       spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+       spin_unlock_irqrestore(&il->sta_lock, flags_spin);
 
-       iwl_legacy_dump_lq_cmd(priv, lq);
+       il_dump_lq_cmd(il, lq);
        BUG_ON(init && (cmd.flags & CMD_ASYNC));
 
-       if (iwl_legacy_is_lq_table_valid(priv, ctx, lq))
-               ret = iwl_legacy_send_cmd(priv, &cmd);
+       if (il_is_lq_table_valid(il, ctx, lq))
+               ret = il_send_cmd(il, &cmd);
        else
                ret = -EINVAL;
 
@@ -783,35 +783,35 @@ int iwl_legacy_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
                return ret;
 
        if (init) {
-               IWL_DEBUG_INFO(priv, "init LQ command complete,"
+               D_INFO("init LQ command complete,"
                                " clearing sta addition status for sta %d\n",
                               lq->sta_id);
-               spin_lock_irqsave(&priv->sta_lock, flags_spin);
-               priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
-               spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+               spin_lock_irqsave(&il->sta_lock, flags_spin);
+               il->stations[lq->sta_id].used &= ~IL_STA_UCODE_INPROGRESS;
+               spin_unlock_irqrestore(&il->sta_lock, flags_spin);
        }
        return ret;
 }
-EXPORT_SYMBOL(iwl_legacy_send_lq_cmd);
+EXPORT_SYMBOL(il_send_lq_cmd);
 
-int iwl_legacy_mac_sta_remove(struct ieee80211_hw *hw,
+int il_mac_sta_remove(struct ieee80211_hw *hw,
                       struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta)
 {
-       struct iwl_priv *priv = hw->priv;
-       struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv;
+       struct il_priv *il = hw->priv;
+       struct il_station_priv_common *sta_common = (void *)sta->drv_priv;
        int ret;
 
-       IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
+       D_INFO("received request to remove station %pM\n",
                        sta->addr);
-       mutex_lock(&priv->mutex);
-       IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
+       mutex_lock(&il->mutex);
+       D_INFO("proceeding to remove station %pM\n",
                        sta->addr);
-       ret = iwl_legacy_remove_station(priv, sta_common->sta_id, sta->addr);
+       ret = il_remove_station(il, sta_common->sta_id, sta->addr);
        if (ret)
-               IWL_ERR(priv, "Error removing station %pM\n",
+               IL_ERR("Error removing station %pM\n",
                        sta->addr);
-       mutex_unlock(&priv->mutex);
+       mutex_unlock(&il->mutex);
        return ret;
 }
-EXPORT_SYMBOL(iwl_legacy_mac_sta_remove);
+EXPORT_SYMBOL(il_mac_sta_remove);
diff --git a/drivers/net/wireless/iwlegacy/iwl-sta.h b/drivers/net/wireless/iwlegacy/iwl-sta.h
deleted file mode 100644 (file)
index 67bd75f..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-#ifndef __iwl_legacy_sta_h__
-#define __iwl_legacy_sta_h__
-
-#include "iwl-dev.h"
-
-#define HW_KEY_DYNAMIC 0
-#define HW_KEY_DEFAULT 1
-
-#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
-#define IWL_STA_UCODE_ACTIVE  BIT(1) /* ucode entry is active */
-#define IWL_STA_UCODE_INPROGRESS  BIT(2) /* ucode entry is in process of
-                                           being activated */
-#define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211;
-                               (this is for the IBSS BSSID stations) */
-#define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */
-
-
-void iwl_legacy_restore_stations(struct iwl_priv *priv,
-                               struct iwl_rxon_context *ctx);
-void iwl_legacy_clear_ucode_stations(struct iwl_priv *priv,
-                             struct iwl_rxon_context *ctx);
-void iwl_legacy_dealloc_bcast_stations(struct iwl_priv *priv);
-int iwl_legacy_get_free_ucode_key_index(struct iwl_priv *priv);
-int iwl_legacy_send_add_sta(struct iwl_priv *priv,
-                       struct iwl_legacy_addsta_cmd *sta, u8 flags);
-int iwl_legacy_add_station_common(struct iwl_priv *priv,
-                       struct iwl_rxon_context *ctx,
-                       const u8 *addr, bool is_ap,
-                       struct ieee80211_sta *sta, u8 *sta_id_r);
-int iwl_legacy_remove_station(struct iwl_priv *priv,
-                       const u8 sta_id,
-                       const u8 *addr);
-int iwl_legacy_mac_sta_remove(struct ieee80211_hw *hw,
-                       struct ieee80211_vif *vif,
-                       struct ieee80211_sta *sta);
-
-u8 iwl_legacy_prep_station(struct iwl_priv *priv,
-                       struct iwl_rxon_context *ctx,
-                       const u8 *addr, bool is_ap,
-                       struct ieee80211_sta *sta);
-
-int iwl_legacy_send_lq_cmd(struct iwl_priv *priv,
-                       struct iwl_rxon_context *ctx,
-                       struct iwl_link_quality_cmd *lq,
-                       u8 flags, bool init);
-
-/**
- * iwl_legacy_clear_driver_stations - clear knowledge of all stations from driver
- * @priv: iwl priv struct
- *
- * This is called during iwl_down() to make sure that in the case
- * we're coming there from a hardware restart mac80211 will be
- * able to reconfigure stations -- if we're getting there in the
- * normal down flow then the stations will already be cleared.
- */
-static inline void iwl_legacy_clear_driver_stations(struct iwl_priv *priv)
-{
-       unsigned long flags;
-       struct iwl_rxon_context *ctx;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       memset(priv->stations, 0, sizeof(priv->stations));
-       priv->num_stations = 0;
-
-       priv->ucode_key_table = 0;
-
-       for_each_context(priv, ctx) {
-               /*
-                * Remove all key information that is not stored as part
-                * of station information since mac80211 may not have had
-                * a chance to remove all the keys. When device is
-                * reconfigured by mac80211 after an error all keys will
-                * be reconfigured.
-                */
-               memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
-               ctx->key_mapping_keys = 0;
-       }
-
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-
-static inline int iwl_legacy_sta_id(struct ieee80211_sta *sta)
-{
-       if (WARN_ON(!sta))
-               return IWL_INVALID_STATION;
-
-       return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id;
-}
-
-/**
- * iwl_legacy_sta_id_or_broadcast - return sta_id or broadcast sta
- * @priv: iwl priv
- * @context: the current context
- * @sta: mac80211 station
- *
- * In certain circumstances mac80211 passes a station pointer
- * that may be %NULL, for example during TX or key setup. In
- * that case, we need to use the broadcast station, so this
- * inline wraps that pattern.
- */
-static inline int iwl_legacy_sta_id_or_broadcast(struct iwl_priv *priv,
-                                         struct iwl_rxon_context *context,
-                                         struct ieee80211_sta *sta)
-{
-       int sta_id;
-
-       if (!sta)
-               return context->bcast_sta_id;
-
-       sta_id = iwl_legacy_sta_id(sta);
-
-       /*
-        * mac80211 should not be passing a partially
-        * initialised station!
-        */
-       WARN_ON(sta_id == IWL_INVALID_STATION);
-
-       return sta_id;
-}
-#endif /* __iwl_legacy_sta_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-tx.c b/drivers/net/wireless/iwlegacy/iwl-tx.c
deleted file mode 100644 (file)
index c0dfb1a..0000000
+++ /dev/null
@@ -1,659 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/etherdevice.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <net/mac80211.h>
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-sta.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-
-/**
- * iwl_legacy_txq_update_write_ptr - Send new write index to hardware
- */
-void
-iwl_legacy_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-       u32 reg = 0;
-       int txq_id = txq->q.id;
-
-       if (txq->need_update == 0)
-               return;
-
-       /* 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(priv,
-                                       "Tx queue %d requesting wakeup,"
-                                       " GP1 = 0x%x\n", txq_id, reg);
-                       iwl_legacy_set_bit(priv, CSR_GP_CNTRL,
-                                       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-                       return;
-               }
-
-               iwl_legacy_write_direct32(priv, HBUS_TARG_WRPTR,
-                               txq->q.write_ptr | (txq_id << 8));
-
-               /*
-                * 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.write_ptr | (txq_id << 8));
-       txq->need_update = 0;
-}
-EXPORT_SYMBOL(iwl_legacy_txq_update_write_ptr);
-
-/**
- * iwl_legacy_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
- */
-void iwl_legacy_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
-{
-       struct iwl_tx_queue *txq = &priv->txq[txq_id];
-       struct iwl_queue *q = &txq->q;
-
-       if (q->n_bd == 0)
-               return;
-
-       while (q->write_ptr != q->read_ptr) {
-               priv->cfg->ops->lib->txq_free_tfd(priv, txq);
-               q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd);
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_tx_queue_unmap);
-
-/**
- * iwl_legacy_tx_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
-void iwl_legacy_tx_queue_free(struct iwl_priv *priv, int txq_id)
-{
-       struct iwl_tx_queue *txq = &priv->txq[txq_id];
-       struct device *dev = &priv->pci_dev->dev;
-       int i;
-
-       iwl_legacy_tx_queue_unmap(priv, txq_id);
-
-       /* De-alloc array of command/tx buffers */
-       for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
-               kfree(txq->cmd[i]);
-
-       /* De-alloc circular buffer of TFDs */
-       if (txq->q.n_bd)
-               dma_free_coherent(dev, priv->hw_params.tfd_size *
-                                 txq->q.n_bd, txq->tfds, txq->q.dma_addr);
-
-       /* De-alloc array of per-TFD driver data */
-       kfree(txq->txb);
-       txq->txb = NULL;
-
-       /* deallocate arrays */
-       kfree(txq->cmd);
-       kfree(txq->meta);
-       txq->cmd = NULL;
-       txq->meta = NULL;
-
-       /* 0-fill queue descriptor structure */
-       memset(txq, 0, sizeof(*txq));
-}
-EXPORT_SYMBOL(iwl_legacy_tx_queue_free);
-
-/**
- * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
- */
-void iwl_legacy_cmd_queue_unmap(struct iwl_priv *priv)
-{
-       struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
-       struct iwl_queue *q = &txq->q;
-       int i;
-
-       if (q->n_bd == 0)
-               return;
-
-       while (q->read_ptr != q->write_ptr) {
-               i = iwl_legacy_get_cmd_index(q, q->read_ptr, 0);
-
-               if (txq->meta[i].flags & CMD_MAPPED) {
-                       pci_unmap_single(priv->pci_dev,
-                                        dma_unmap_addr(&txq->meta[i], mapping),
-                                        dma_unmap_len(&txq->meta[i], len),
-                                        PCI_DMA_BIDIRECTIONAL);
-                       txq->meta[i].flags = 0;
-               }
-
-               q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd);
-       }
-
-       i = q->n_window;
-       if (txq->meta[i].flags & CMD_MAPPED) {
-               pci_unmap_single(priv->pci_dev,
-                                dma_unmap_addr(&txq->meta[i], mapping),
-                                dma_unmap_len(&txq->meta[i], len),
-                                PCI_DMA_BIDIRECTIONAL);
-               txq->meta[i].flags = 0;
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_cmd_queue_unmap);
-
-/**
- * iwl_legacy_cmd_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
-void iwl_legacy_cmd_queue_free(struct iwl_priv *priv)
-{
-       struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
-       struct device *dev = &priv->pci_dev->dev;
-       int i;
-
-       iwl_legacy_cmd_queue_unmap(priv);
-
-       /* De-alloc array of command/tx buffers */
-       for (i = 0; i <= TFD_CMD_SLOTS; i++)
-               kfree(txq->cmd[i]);
-
-       /* De-alloc circular buffer of TFDs */
-       if (txq->q.n_bd)
-               dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
-                                 txq->tfds, txq->q.dma_addr);
-
-       /* deallocate arrays */
-       kfree(txq->cmd);
-       kfree(txq->meta);
-       txq->cmd = NULL;
-       txq->meta = NULL;
-
-       /* 0-fill queue descriptor structure */
-       memset(txq, 0, sizeof(*txq));
-}
-EXPORT_SYMBOL(iwl_legacy_cmd_queue_free);
-
-/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
- * DMA services
- *
- * Theory of operation
- *
- * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
- * of buffer descriptors, each of which points to one or more data buffers for
- * the device to read from or fill.  Driver and device exchange status of each
- * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
- * entries in each circular buffer, to protect against confusing empty and full
- * queue states.
- *
- * The device reads or writes the data in the queues via the device's several
- * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
- *
- * 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.
- *
- * See more detailed info in iwl-4965-hw.h.
- ***************************************************/
-
-int iwl_legacy_queue_space(const struct iwl_queue *q)
-{
-       int s = q->read_ptr - q->write_ptr;
-
-       if (q->read_ptr > q->write_ptr)
-               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;
-}
-EXPORT_SYMBOL(iwl_legacy_queue_space);
-
-
-/**
- * iwl_legacy_queue_init - Initialize queue's high/low-water and read/write indexes
- */
-static int iwl_legacy_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_legacy_queue_inc_wrap
-        * and iwl_legacy_queue_dec_wrap are broken. */
-       BUG_ON(!is_power_of_2(count));
-
-       /* slots_num must be power-of-two size, otherwise
-        * iwl_legacy_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->write_ptr = q->read_ptr = 0;
-
-       return 0;
-}
-
-/**
- * iwl_legacy_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
- */
-static int iwl_legacy_tx_queue_alloc(struct iwl_priv *priv,
-                             struct iwl_tx_queue *txq, u32 id)
-{
-       struct device *dev = &priv->pci_dev->dev;
-       size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
-
-       /* Driver private data, only for Tx (not command) queues,
-        * not shared with device. */
-       if (id != priv->cmd_queue) {
-               txq->txb = kzalloc(sizeof(txq->txb[0]) *
-                                  TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
-               if (!txq->txb) {
-                       IWL_ERR(priv, "kmalloc for auxiliary BD "
-                                 "structures failed\n");
-                       goto error;
-               }
-       } else {
-               txq->txb = NULL;
-       }
-
-       /* Circular buffer of transmit frame descriptors (TFDs),
-        * shared with device */
-       txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
-                                      GFP_KERNEL);
-       if (!txq->tfds) {
-               IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
-               goto error;
-       }
-       txq->q.id = id;
-
-       return 0;
-
- error:
-       kfree(txq->txb);
-       txq->txb = NULL;
-
-       return -ENOMEM;
-}
-
-/**
- * iwl_legacy_tx_queue_init - Allocate and initialize one tx/cmd queue
- */
-int iwl_legacy_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
-                     int slots_num, u32 txq_id)
-{
-       int i, len;
-       int ret;
-       int actual_slots = slots_num;
-
-       /*
-        * Alloc buffer array for commands (Tx or other types of commands).
-        * For the command queue (#4/#9), allocate command space + one big
-        * command for scan, since scan command is very huge; the system will
-        * not have two scans at the same time, so only one is needed.
-        * For normal Tx queues (all other queues), no super-size command
-        * space is needed.
-        */
-       if (txq_id == priv->cmd_queue)
-               actual_slots++;
-
-       txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
-                           GFP_KERNEL);
-       txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots,
-                          GFP_KERNEL);
-
-       if (!txq->meta || !txq->cmd)
-               goto out_free_arrays;
-
-       len = sizeof(struct iwl_device_cmd);
-       for (i = 0; i < actual_slots; i++) {
-               /* only happens for cmd queue */
-               if (i == slots_num)
-                       len = IWL_MAX_CMD_SIZE;
-
-               txq->cmd[i] = kmalloc(len, GFP_KERNEL);
-               if (!txq->cmd[i])
-                       goto err;
-       }
-
-       /* Alloc driver data array and TFD circular buffer */
-       ret = iwl_legacy_tx_queue_alloc(priv, txq, txq_id);
-       if (ret)
-               goto err;
-
-       txq->need_update = 0;
-
-       /*
-        * For the default queues 0-3, set up the swq_id
-        * already -- all others need to get one later
-        * (if they need one at all).
-        */
-       if (txq_id < 4)
-               iwl_legacy_set_swq_id(txq, txq_id, txq_id);
-
-       /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
-        * iwl_legacy_queue_inc_wrap and iwl_legacy_queue_dec_wrap are broken. */
-       BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
-
-       /* Initialize queue's high/low-water marks, and head/tail indexes */
-       iwl_legacy_queue_init(priv, &txq->q,
-                               TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
-
-       /* Tell device where to find queue */
-       priv->cfg->ops->lib->txq_init(priv, txq);
-
-       return 0;
-err:
-       for (i = 0; i < actual_slots; i++)
-               kfree(txq->cmd[i]);
-out_free_arrays:
-       kfree(txq->meta);
-       kfree(txq->cmd);
-
-       return -ENOMEM;
-}
-EXPORT_SYMBOL(iwl_legacy_tx_queue_init);
-
-void iwl_legacy_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
-                       int slots_num, u32 txq_id)
-{
-       int actual_slots = slots_num;
-
-       if (txq_id == priv->cmd_queue)
-               actual_slots++;
-
-       memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
-
-       txq->need_update = 0;
-
-       /* Initialize queue's high/low-water marks, and head/tail indexes */
-       iwl_legacy_queue_init(priv, &txq->q,
-                               TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
-
-       /* Tell device where to find queue */
-       priv->cfg->ops->lib->txq_init(priv, txq);
-}
-EXPORT_SYMBOL(iwl_legacy_tx_queue_reset);
-
-/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
-
-/**
- * iwl_legacy_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.
- */
-int iwl_legacy_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-{
-       struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
-       struct iwl_queue *q = &txq->q;
-       struct iwl_device_cmd *out_cmd;
-       struct iwl_cmd_meta *out_meta;
-       dma_addr_t phys_addr;
-       unsigned long flags;
-       int len;
-       u32 idx;
-       u16 fix_size;
-
-       cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
-       fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
-
-       /* 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
-        * Also, check to see if command buffer should not exceed the size
-        * of device_cmd and max_cmd_size. */
-       BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
-              !(cmd->flags & CMD_SIZE_HUGE));
-       BUG_ON(fix_size > IWL_MAX_CMD_SIZE);
-
-       if (iwl_legacy_is_rfkill(priv) || iwl_legacy_is_ctkill(priv)) {
-               IWL_WARN(priv, "Not sending command - %s KILL\n",
-                        iwl_legacy_is_rfkill(priv) ? "RF" : "CT");
-               return -EIO;
-       }
-
-       spin_lock_irqsave(&priv->hcmd_lock, flags);
-
-       if (iwl_legacy_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
-               spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-
-               IWL_ERR(priv, "Restarting adapter due to command queue full\n");
-               queue_work(priv->workqueue, &priv->restart);
-               return -ENOSPC;
-       }
-
-       idx = iwl_legacy_get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
-       out_cmd = txq->cmd[idx];
-       out_meta = &txq->meta[idx];
-
-       if (WARN_ON(out_meta->flags & CMD_MAPPED)) {
-               spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-               return -ENOSPC;
-       }
-
-       memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
-       out_meta->flags = cmd->flags | CMD_MAPPED;
-       if (cmd->flags & CMD_WANT_SKB)
-               out_meta->source = cmd;
-       if (cmd->flags & CMD_ASYNC)
-               out_meta->callback = cmd->callback;
-
-       out_cmd->hdr.cmd = cmd->id;
-       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(priv->cmd_queue) |
-                       INDEX_TO_SEQ(q->write_ptr));
-       if (cmd->flags & CMD_SIZE_HUGE)
-               out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
-       len = sizeof(struct iwl_device_cmd);
-       if (idx == TFD_CMD_SLOTS)
-               len = IWL_MAX_CMD_SIZE;
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       switch (out_cmd->hdr.cmd) {
-       case REPLY_TX_LINK_QUALITY_CMD:
-       case SENSITIVITY_CMD:
-               IWL_DEBUG_HC_DUMP(priv,
-                               "Sending command %s (#%x), seq: 0x%04X, "
-                               "%d bytes at %d[%d]:%d\n",
-                               iwl_legacy_get_cmd_string(out_cmd->hdr.cmd),
-                               out_cmd->hdr.cmd,
-                               le16_to_cpu(out_cmd->hdr.sequence), fix_size,
-                               q->write_ptr, idx, priv->cmd_queue);
-               break;
-       default:
-               IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
-                               "%d bytes at %d[%d]:%d\n",
-                               iwl_legacy_get_cmd_string(out_cmd->hdr.cmd),
-                               out_cmd->hdr.cmd,
-                               le16_to_cpu(out_cmd->hdr.sequence), fix_size,
-                               q->write_ptr, idx, priv->cmd_queue);
-       }
-#endif
-       txq->need_update = 1;
-
-       if (priv->cfg->ops->lib->txq_update_byte_cnt_tbl)
-               /* Set up entry in queue's byte count circular buffer */
-               priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
-
-       phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
-                                  fix_size, PCI_DMA_BIDIRECTIONAL);
-       dma_unmap_addr_set(out_meta, mapping, phys_addr);
-       dma_unmap_len_set(out_meta, len, fix_size);
-
-       trace_iwlwifi_legacy_dev_hcmd(priv, &out_cmd->hdr,
-                                               fix_size, cmd->flags);
-
-       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                  phys_addr, fix_size, 1,
-                                                  U32_PAD(cmd->len));
-
-       /* Increment and update queue's write index */
-       q->write_ptr = iwl_legacy_queue_inc_wrap(q->write_ptr, q->n_bd);
-       iwl_legacy_txq_update_write_ptr(priv, txq);
-
-       spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-       return idx;
-}
-
-/**
- * iwl_legacy_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
- *
- * 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 the stack that feeds us.
- */
-static void iwl_legacy_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
-                                  int idx, int cmd_idx)
-{
-       struct iwl_tx_queue *txq = &priv->txq[txq_id];
-       struct iwl_queue *q = &txq->q;
-       int nfreed = 0;
-
-       if ((idx >= q->n_bd) || (iwl_legacy_queue_used(q, idx) == 0)) {
-               IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
-                         "is out of range [0-%d] %d %d.\n", txq_id,
-                         idx, q->n_bd, q->write_ptr, q->read_ptr);
-               return;
-       }
-
-       for (idx = iwl_legacy_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
-            q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-
-               if (nfreed++ > 0) {
-                       IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx,
-                                       q->write_ptr, q->read_ptr);
-                       queue_work(priv->workqueue, &priv->restart);
-               }
-
-       }
-}
-
-/**
- * iwl_legacy_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
- */
-void
-iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-       int txq_id = SEQ_TO_QUEUE(sequence);
-       int index = SEQ_TO_INDEX(sequence);
-       int cmd_index;
-       bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
-       struct iwl_device_cmd *cmd;
-       struct iwl_cmd_meta *meta;
-       struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
-       unsigned long flags;
-
-       /* 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 (WARN(txq_id != priv->cmd_queue,
-                "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
-                 txq_id, priv->cmd_queue, sequence,
-                 priv->txq[priv->cmd_queue].q.read_ptr,
-                 priv->txq[priv->cmd_queue].q.write_ptr)) {
-               iwl_print_hex_error(priv, pkt, 32);
-               return;
-       }
-
-       cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, huge);
-       cmd = txq->cmd[cmd_index];
-       meta = &txq->meta[cmd_index];
-
-       txq->time_stamp = jiffies;
-
-       pci_unmap_single(priv->pci_dev,
-                        dma_unmap_addr(meta, mapping),
-                        dma_unmap_len(meta, len),
-                        PCI_DMA_BIDIRECTIONAL);
-
-       /* Input error checking is done when commands are added to queue. */
-       if (meta->flags & CMD_WANT_SKB) {
-               meta->source->reply_page = (unsigned long)rxb_addr(rxb);
-               rxb->page = NULL;
-       } else if (meta->callback)
-               meta->callback(priv, cmd, pkt);
-
-       spin_lock_irqsave(&priv->hcmd_lock, flags);
-
-       iwl_legacy_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
-
-       if (!(meta->flags & CMD_ASYNC)) {
-               clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-               IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
-                              iwl_legacy_get_cmd_string(cmd->hdr.cmd));
-               wake_up(&priv->wait_command_queue);
-       }
-
-       /* Mark as unmapped */
-       meta->flags = 0;
-
-       spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-}
-EXPORT_SYMBOL(iwl_legacy_tx_cmd_complete);
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
deleted file mode 100644 (file)
index b282d86..0000000
+++ /dev/null
@@ -1,4016 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/firmware.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-
-#include <net/ieee80211_radiotap.h>
-#include <net/mac80211.h>
-
-#include <asm/div64.h>
-
-#define DRV_NAME       "iwl3945"
-
-#include "iwl-fh.h"
-#include "iwl-3945-fh.h"
-#include "iwl-commands.h"
-#include "iwl-sta.h"
-#include "iwl-3945.h"
-#include "iwl-core.h"
-#include "iwl-helpers.h"
-#include "iwl-dev.h"
-#include "iwl-spectrum.h"
-
-/*
- * module name, copyright, version, etc.
- */
-
-#define DRV_DESCRIPTION        \
-"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-#define VD "d"
-#else
-#define VD
-#endif
-
-/*
- * add "s" to indicate spectrum measurement included.
- * we add it here to be consistent with previous releases in which
- * this was configurable.
- */
-#define DRV_VERSION  IWLWIFI_VERSION VD "s"
-#define DRV_COPYRIGHT  "Copyright(c) 2003-2011 Intel Corporation"
-#define DRV_AUTHOR     "<ilw@linux.intel.com>"
-
-MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
-MODULE_LICENSE("GPL");
-
- /* module parameters */
-struct iwl_mod_params iwl3945_mod_params = {
-       .sw_crypto = 1,
-       .restart_fw = 1,
-       .disable_hw_scan = 1,
-       /* the rest are 0 by default */
-};
-
-/**
- * iwl3945_get_antenna_flags - Get antenna flags for RXON command
- * @priv: eeprom and antenna fields are used to determine antenna flags
- *
- * priv->eeprom39  is used to determine if antenna AUX/MAIN are reversed
- * iwl3945_mod_params.antenna specifies the antenna diversity mode:
- *
- * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
- * IWL_ANTENNA_MAIN      - Force MAIN antenna
- * IWL_ANTENNA_AUX       - Force AUX antenna
- */
-__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
-{
-       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-
-       switch (iwl3945_mod_params.antenna) {
-       case IWL_ANTENNA_DIVERSITY:
-               return 0;
-
-       case IWL_ANTENNA_MAIN:
-               if (eeprom->antenna_switch_type)
-                       return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
-               return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
-
-       case IWL_ANTENNA_AUX:
-               if (eeprom->antenna_switch_type)
-                       return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
-               return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
-       }
-
-       /* bad antenna selector value */
-       IWL_ERR(priv, "Bad antenna selector value (0x%x)\n",
-               iwl3945_mod_params.antenna);
-
-       return 0;               /* "diversity" is default if error */
-}
-
-static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
-                                  struct ieee80211_key_conf *keyconf,
-                                  u8 sta_id)
-{
-       unsigned long flags;
-       __le16 key_flags = 0;
-       int ret;
-
-       key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
-       key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-
-       if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
-               key_flags |= STA_KEY_MULTICAST_MSK;
-
-       keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-       keyconf->hw_key_idx = keyconf->keyidx;
-       key_flags &= ~STA_KEY_FLG_INVALID;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
-       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);
-
-       if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-                       == STA_KEY_FLG_NO_ENC)
-               priv->stations[sta_id].sta.key.key_offset =
-                                iwl_legacy_get_free_ucode_key_index(priv);
-       /* else, we are overriding an existing key => no need to allocated room
-       * in uCode. */
-
-       WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-               "no space for a new key");
-
-       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;
-
-       IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n");
-
-       ret = iwl_legacy_send_add_sta(priv,
-                               &priv->stations[sta_id].sta, CMD_ASYNC);
-
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return ret;
-}
-
-static int iwl3945_set_tkip_dynamic_key_info(struct iwl_priv *priv,
-                                 struct ieee80211_key_conf *keyconf,
-                                 u8 sta_id)
-{
-       return -EOPNOTSUPP;
-}
-
-static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv,
-                                 struct ieee80211_key_conf *keyconf,
-                                 u8 sta_id)
-{
-       return -EOPNOTSUPP;
-}
-
-static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
-{
-       unsigned long flags;
-       struct iwl_legacy_addsta_cmd sta_cmd;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
-       memset(&priv->stations[sta_id].sta.key, 0,
-               sizeof(struct iwl4965_keyinfo));
-       priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
-       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-       memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_legacy_addsta_cmd));
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
-       return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
-                       struct ieee80211_key_conf *keyconf, u8 sta_id)
-{
-       int ret = 0;
-
-       keyconf->hw_key_idx = HW_KEY_DYNAMIC;
-
-       switch (keyconf->cipher) {
-       case WLAN_CIPHER_SUITE_CCMP:
-               ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
-               break;
-       case WLAN_CIPHER_SUITE_TKIP:
-               ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
-               break;
-       case WLAN_CIPHER_SUITE_WEP40:
-       case WLAN_CIPHER_SUITE_WEP104:
-               ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
-               break;
-       default:
-               IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__,
-                       keyconf->cipher);
-               ret = -EINVAL;
-       }
-
-       IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
-                     keyconf->cipher, keyconf->keylen, keyconf->keyidx,
-                     sta_id, ret);
-
-       return ret;
-}
-
-static int iwl3945_remove_static_key(struct iwl_priv *priv)
-{
-       int ret = -EOPNOTSUPP;
-
-       return ret;
-}
-
-static int iwl3945_set_static_key(struct iwl_priv *priv,
-                               struct ieee80211_key_conf *key)
-{
-       if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-           key->cipher == WLAN_CIPHER_SUITE_WEP104)
-               return -EOPNOTSUPP;
-
-       IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher);
-       return -EINVAL;
-}
-
-static void iwl3945_clear_free_frames(struct iwl_priv *priv)
-{
-       struct list_head *element;
-
-       IWL_DEBUG_INFO(priv, "%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 iwl3945_frame, list));
-               priv->frames_count--;
-       }
-
-       if (priv->frames_count) {
-               IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
-                           priv->frames_count);
-               priv->frames_count = 0;
-       }
-}
-
-static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv)
-{
-       struct iwl3945_frame *frame;
-       struct list_head *element;
-       if (list_empty(&priv->free_frames)) {
-               frame = kzalloc(sizeof(*frame), GFP_KERNEL);
-               if (!frame) {
-                       IWL_ERR(priv, "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 iwl3945_frame, list);
-}
-
-static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame)
-{
-       memset(frame, 0, sizeof(*frame));
-       list_add(&frame->list, &priv->free_frames);
-}
-
-unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
-                               struct ieee80211_hdr *hdr,
-                               int left)
-{
-
-       if (!iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
-               return 0;
-
-       if (priv->beacon_skb->len > left)
-               return 0;
-
-       memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
-
-       return priv->beacon_skb->len;
-}
-
-static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
-{
-       struct iwl3945_frame *frame;
-       unsigned int frame_size;
-       int rc;
-       u8 rate;
-
-       frame = iwl3945_get_free_frame(priv);
-
-       if (!frame) {
-               IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
-                         "command.\n");
-               return -ENOMEM;
-       }
-
-       rate = iwl_legacy_get_lowest_plcp(priv,
-                               &priv->contexts[IWL_RXON_CTX_BSS]);
-
-       frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
-
-       rc = iwl_legacy_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
-                             &frame->u.cmd[0]);
-
-       iwl3945_free_frame(priv, frame);
-
-       return rc;
-}
-
-static void iwl3945_unset_hw_params(struct iwl_priv *priv)
-{
-       if (priv->_3945.shared_virt)
-               dma_free_coherent(&priv->pci_dev->dev,
-                                 sizeof(struct iwl3945_shared),
-                                 priv->_3945.shared_virt,
-                                 priv->_3945.shared_phys);
-}
-
-static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
-                                     struct ieee80211_tx_info *info,
-                                     struct iwl_device_cmd *cmd,
-                                     struct sk_buff *skb_frag,
-                                     int sta_id)
-{
-       struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-       struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
-
-       tx_cmd->sec_ctl = 0;
-
-       switch (keyinfo->cipher) {
-       case WLAN_CIPHER_SUITE_CCMP:
-               tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
-               memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
-               IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
-               break;
-
-       case WLAN_CIPHER_SUITE_TKIP:
-               break;
-
-       case WLAN_CIPHER_SUITE_WEP104:
-               tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
-               /* fall through */
-       case WLAN_CIPHER_SUITE_WEP40:
-               tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
-                   (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
-
-               memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
-
-               IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
-                            "with key %d\n", info->control.hw_key->hw_key_idx);
-               break;
-
-       default:
-               IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher);
-               break;
-       }
-}
-
-/*
- * handle build REPLY_TX command notification.
- */
-static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
-                                 struct iwl_device_cmd *cmd,
-                                 struct ieee80211_tx_info *info,
-                                 struct ieee80211_hdr *hdr, u8 std_id)
-{
-       struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-       __le32 tx_flags = tx_cmd->tx_flags;
-       __le16 fc = hdr->frame_control;
-
-       tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
-               tx_flags |= TX_CMD_FLG_ACK_MSK;
-               if (ieee80211_is_mgmt(fc))
-                       tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-               if (ieee80211_is_probe_resp(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;
-       }
-
-       tx_cmd->sta_id = std_id;
-       if (ieee80211_has_morefrags(fc))
-               tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
-
-       if (ieee80211_is_data_qos(fc)) {
-               u8 *qc = ieee80211_get_qos_ctl(hdr);
-               tx_cmd->tid_tspec = qc[0] & 0xf;
-               tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
-       } else {
-               tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-       }
-
-       iwl_legacy_tx_cmd_protection(priv, info, fc, &tx_flags);
-
-       tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
-       if (ieee80211_is_mgmt(fc)) {
-               if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
-                       tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
-               else
-                       tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
-       } else {
-               tx_cmd->timeout.pm_frame_timeout = 0;
-       }
-
-       tx_cmd->driver_txop = 0;
-       tx_cmd->tx_flags = tx_flags;
-       tx_cmd->next_frame_len = 0;
-}
-
-/*
- * start REPLY_TX command process
- */
-static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
-{
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct iwl3945_tx_cmd *tx_cmd;
-       struct iwl_tx_queue *txq = NULL;
-       struct iwl_queue *q = NULL;
-       struct iwl_device_cmd *out_cmd;
-       struct iwl_cmd_meta *out_meta;
-       dma_addr_t phys_addr;
-       dma_addr_t txcmd_phys;
-       int txq_id = skb_get_queue_mapping(skb);
-       u16 len, idx, hdr_len;
-       u8 id;
-       u8 unicast;
-       u8 sta_id;
-       u8 tid = 0;
-       __le16 fc;
-       u8 wait_write_ptr = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       if (iwl_legacy_is_rfkill(priv)) {
-               IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
-               goto drop_unlock;
-       }
-
-       if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
-               IWL_ERR(priv, "ERROR: No TX rate available.\n");
-               goto drop_unlock;
-       }
-
-       unicast = !is_multicast_ether_addr(hdr->addr1);
-       id = 0;
-
-       fc = hdr->frame_control;
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (ieee80211_is_auth(fc))
-               IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
-       else if (ieee80211_is_assoc_req(fc))
-               IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
-       else if (ieee80211_is_reassoc_req(fc))
-               IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
-#endif
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       hdr_len = ieee80211_hdrlen(fc);
-
-       /* Find index into station table for destination station */
-       sta_id = iwl_legacy_sta_id_or_broadcast(
-                       priv, &priv->contexts[IWL_RXON_CTX_BSS],
-                       info->control.sta);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-                              hdr->addr1);
-               goto drop;
-       }
-
-       IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
-
-       if (ieee80211_is_data_qos(fc)) {
-               u8 *qc = ieee80211_get_qos_ctl(hdr);
-               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-               if (unlikely(tid >= MAX_TID_COUNT))
-                       goto drop;
-       }
-
-       /* Descriptor for chosen Tx queue */
-       txq = &priv->txq[txq_id];
-       q = &txq->q;
-
-       if ((iwl_legacy_queue_space(q) < q->high_mark))
-               goto drop;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       idx = iwl_legacy_get_cmd_index(q, q->write_ptr, 0);
-
-       /* Set up driver data for this TFD */
-       memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
-       txq->txb[q->write_ptr].skb = skb;
-       txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       /* Init first empty entry in queue's array of Tx/cmd buffers */
-       out_cmd = txq->cmd[idx];
-       out_meta = &txq->meta[idx];
-       tx_cmd = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
-       memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
-       memset(tx_cmd, 0, sizeof(*tx_cmd));
-
-       /*
-        * Set up the Tx-command (not MAC!) header.
-        * Store the chosen Tx queue and TFD index within the sequence field;
-        * after Tx, uCode's Tx response will return this value so driver can
-        * locate the frame within the tx queue and do post-tx processing.
-        */
-       out_cmd->hdr.cmd = REPLY_TX;
-       out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
-                               INDEX_TO_SEQ(q->write_ptr)));
-
-       /* Copy MAC header from skb into command buffer */
-       memcpy(tx_cmd->hdr, hdr, hdr_len);
-
-
-       if (info->control.hw_key)
-               iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
-
-       /* TODO need this for burst mode later on */
-       iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
-
-       /* set is_hcca to 0; it probably will never be implemented */
-       iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
-
-       /* Total # bytes to be transmitted */
-       len = (u16)skb->len;
-       tx_cmd->len = cpu_to_le16(len);
-
-       iwl_legacy_dbg_log_tx_data_frame(priv, len, hdr);
-       iwl_legacy_update_stats(priv, true, fc, len);
-       tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
-       tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
-
-       if (!ieee80211_has_morefrags(hdr->frame_control)) {
-               txq->need_update = 1;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
-
-       IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
-                    le16_to_cpu(out_cmd->hdr.sequence));
-       IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
-       iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd));
-       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr,
-                          ieee80211_hdrlen(fc));
-
-       /*
-        * Use the first empty entry in this queue's command buffer array
-        * to contain the Tx command and MAC header concatenated together
-        * (payload data will be in another buffer).
-        * Size of this varies, due to varying MAC header length.
-        * If end is not dword aligned, we'll have 2 extra bytes at the end
-        * of the MAC header (device reads on dword boundaries).
-        * We'll tell device about this padding later.
-        */
-       len = sizeof(struct iwl3945_tx_cmd) +
-                       sizeof(struct iwl_cmd_header) + hdr_len;
-       len = (len + 3) & ~3;
-
-       /* Physical address of this Tx command's header (not MAC header!),
-        * within command buffer array. */
-       txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
-                                   len, PCI_DMA_TODEVICE);
-       /* we do not map meta data ... so we can safely access address to
-        * provide to unmap command*/
-       dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-       dma_unmap_len_set(out_meta, len, len);
-
-       /* Add buffer containing Tx command and MAC(!) header to TFD's
-        * first entry */
-       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                  txcmd_phys, len, 1, 0);
-
-
-       /* Set up TFD's 2nd entry to point directly to remainder of skb,
-        * if any (802.11 null frames 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);
-               priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                          phys_addr, len,
-                                                          0, U32_PAD(len));
-       }
-
-
-       /* Tell device the write index *just past* this latest filled TFD */
-       q->write_ptr = iwl_legacy_queue_inc_wrap(q->write_ptr, q->n_bd);
-       iwl_legacy_txq_update_write_ptr(priv, txq);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if ((iwl_legacy_queue_space(q) < q->high_mark)
-           && priv->mac80211_registered) {
-               if (wait_write_ptr) {
-                       spin_lock_irqsave(&priv->lock, flags);
-                       txq->need_update = 1;
-                       iwl_legacy_txq_update_write_ptr(priv, txq);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-               }
-
-               iwl_legacy_stop_queue(priv, txq);
-       }
-
-       return 0;
-
-drop_unlock:
-       spin_unlock_irqrestore(&priv->lock, flags);
-drop:
-       return -1;
-}
-
-static int iwl3945_get_measurement(struct iwl_priv *priv,
-                              struct ieee80211_measurement_params *params,
-                              u8 type)
-{
-       struct iwl_spectrum_cmd spectrum;
-       struct iwl_rx_packet *pkt;
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_SPECTRUM_MEASUREMENT_CMD,
-               .data = (void *)&spectrum,
-               .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);
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS))
-               add_time = iwl_legacy_usecs_to_beacons(priv,
-                       le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
-                       le16_to_cpu(ctx->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_legacy_is_associated(priv, IWL_RXON_CTX_BSS))
-               spectrum.start_time =
-                       iwl_legacy_add_beacon_time(priv,
-                               priv->_3945.last_beacon_time, add_time,
-                               le16_to_cpu(ctx->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 (ctx->active.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_legacy_send_cmd_sync(priv, &cmd);
-       if (rc)
-               return rc;
-
-       pkt = (struct iwl_rx_packet *)cmd.reply_page;
-       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
-               rc = -EIO;
-       }
-
-       spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
-       switch (spectrum_resp_status) {
-       case 0:         /* Command will be handled */
-               if (pkt->u.spectrum.id != 0xff) {
-                       IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
-                                               pkt->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;
-       }
-
-       iwl_legacy_free_pages(priv, cmd.reply_page);
-
-       return rc;
-}
-
-static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
-                              struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_alive_resp *palive;
-       struct delayed_work *pwork;
-
-       palive = &pkt->u.alive_frame;
-
-       IWL_DEBUG_INFO(priv, "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(priv, "Initialization Alive received.\n");
-               memcpy(&priv->card_alive_init, &pkt->u.alive_frame,
-                      sizeof(struct iwl_alive_resp));
-               pwork = &priv->init_alive_start;
-       } else {
-               IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
-               memcpy(&priv->card_alive, &pkt->u.alive_frame,
-                      sizeof(struct iwl_alive_resp));
-               pwork = &priv->alive_start;
-               iwl3945_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_WARN(priv, "uCode did not respond OK.\n");
-}
-
-static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
-                                struct iwl_rx_mem_buffer *rxb)
-{
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-#endif
-
-       IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
-}
-
-static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       u8 rate = beacon->beacon_notify_hdr.rate;
-
-       IWL_DEBUG_RX(priv, "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
-
-       priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
-
-}
-
-/* Handle notification from uCode that card's power state is changing
- * due to software, hardware, or critical temperature RFKILL */
-static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
-       unsigned long status = priv->status;
-
-       IWL_WARN(priv, "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);
-
-
-       iwl_legacy_scan_cancel(priv);
-
-       if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-            test_bit(STATUS_RF_KILL_HW, &priv->status)))
-               wiphy_rfkill_set_hw_state(priv->hw->wiphy,
-                               test_bit(STATUS_RF_KILL_HW, &priv->status));
-       else
-               wake_up(&priv->wait_command_queue);
-}
-
-/**
- * iwl3945_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 iwl3945_setup_rx_handlers(struct iwl_priv *priv)
-{
-       priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
-       priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
-       priv->rx_handlers[REPLY_ERROR] = iwl_legacy_rx_reply_error;
-       priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_legacy_rx_csa;
-       priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
-                       iwl_legacy_rx_spectrum_measure_notif;
-       priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_legacy_rx_pm_sleep_notif;
-       priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
-           iwl_legacy_rx_pm_debug_statistics_notif;
-       priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
-
-       /*
-        * The same handler is used for both the REPLY to a discrete
-        * statistics request from the host as well as for the periodic
-        * statistics notifications (after received beacons) from the uCode.
-        */
-       priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics;
-       priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
-
-       iwl_legacy_setup_rx_scan_handlers(priv);
-       priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
-
-       /* Set up hardware specific Rx handlers */
-       iwl3945_hw_rx_handler_setup(priv);
-}
-
-/************************** 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 iwl->rxq->rx_free.  When
- *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
- *   to replenish the iwl->rxq->rx_free.
- * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the
- *   iwl->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 iwl->rxq.  The driver 'processed' index is updated.
- * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
- *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
- *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
- *   were enough free buffers and RX_STALLED is set it is cleared.
- *
- *
- * Driver sequence:
- *
- * iwl3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
- *                            iwl3945_rx_queue_restock
- * iwl3945_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 iwl3945_rx_replenish
- *
- * -- enable interrupts --
- * ISR - iwl3945_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 iwl3945_rx_queue_restock to refill any empty
- *                            slots.
- * ...
- *
- */
-
-/**
- * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
-static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
-                                         dma_addr_t dma_addr)
-{
-       return cpu_to_le32((u32)dma_addr);
-}
-
-/**
- * iwl3945_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.
- */
-static void iwl3945_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;
-
-       spin_lock_irqsave(&rxq->lock, flags);
-       write = rxq->write & ~0x7;
-       while ((iwl_legacy_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
-               /* Get next free Rx buffer, remove from free list */
-               element = rxq->rx_free.next;
-               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-               list_del(element);
-
-               /* Point to Rx buffer via next RBD in circular buffer */
-               rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma);
-               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.
-        * Increment device's write pointer in multiples of 8. */
-       if ((rxq->write_actual != (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);
-               iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
-       }
-}
-
-/**
- * iwl3945_rx_replenish - 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 iwl3945_rx_queue_restock.
- * This is called as a scheduled work item (except for during initialization)
- */
-static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
-{
-       struct iwl_rx_queue *rxq = &priv->rxq;
-       struct list_head *element;
-       struct iwl_rx_mem_buffer *rxb;
-       struct page *page;
-       unsigned long flags;
-       gfp_t gfp_mask = priority;
-
-       while (1) {
-               spin_lock_irqsave(&rxq->lock, flags);
-
-               if (list_empty(&rxq->rx_used)) {
-                       spin_unlock_irqrestore(&rxq->lock, flags);
-                       return;
-               }
-               spin_unlock_irqrestore(&rxq->lock, flags);
-
-               if (rxq->free_count > RX_LOW_WATERMARK)
-                       gfp_mask |= __GFP_NOWARN;
-
-               if (priv->hw_params.rx_page_order > 0)
-                       gfp_mask |= __GFP_COMP;
-
-               /* Alloc a new receive buffer */
-               page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
-               if (!page) {
-                       if (net_ratelimit())
-                               IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
-                       if ((rxq->free_count <= RX_LOW_WATERMARK) &&
-                           net_ratelimit())
-                               IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
-                                        priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
-                                        rxq->free_count);
-                       /* 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;
-               }
-
-               spin_lock_irqsave(&rxq->lock, flags);
-               if (list_empty(&rxq->rx_used)) {
-                       spin_unlock_irqrestore(&rxq->lock, flags);
-                       __free_pages(page, priv->hw_params.rx_page_order);
-                       return;
-               }
-               element = rxq->rx_used.next;
-               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-               list_del(element);
-               spin_unlock_irqrestore(&rxq->lock, flags);
-
-               rxb->page = page;
-               /* Get physical address of RB/SKB */
-               rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
-                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-
-               spin_lock_irqsave(&rxq->lock, flags);
-
-               list_add_tail(&rxb->list, &rxq->rx_free);
-               rxq->free_count++;
-               priv->alloc_rxb_page++;
-
-               spin_unlock_irqrestore(&rxq->lock, flags);
-       }
-}
-
-void iwl3945_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].page != NULL) {
-                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-                       __iwl_legacy_free_pages(priv, rxq->pool[i].page);
-                       rxq->pool[i].page = 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->write_actual = 0;
-       rxq->free_count = 0;
-       spin_unlock_irqrestore(&rxq->lock, flags);
-}
-
-void iwl3945_rx_replenish(void *data)
-{
-       struct iwl_priv *priv = data;
-       unsigned long flags;
-
-       iwl3945_rx_allocate(priv, GFP_KERNEL);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl3945_rx_queue_restock(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static void iwl3945_rx_replenish_now(struct iwl_priv *priv)
-{
-       iwl3945_rx_allocate(priv, GFP_ATOMIC);
-
-       iwl3945_rx_queue_restock(priv);
-}
-
-
-/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have its 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
- */
-static void iwl3945_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].page != NULL) {
-                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-                       __iwl_legacy_free_pages(priv, rxq->pool[i].page);
-                       rxq->pool[i].page = NULL;
-               }
-       }
-
-       dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-                         rxq->bd_dma);
-       dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
-                         rxq->rb_stts, rxq->rb_stts_dma);
-       rxq->bd = NULL;
-       rxq->rb_stts  = NULL;
-}
-
-
-/* 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 iwl3945_calc_db_from_ratio(int sig_ratio)
-{
-       /* 1000:1 or higher just report as 60 dB */
-       if (sig_ratio >= 1000)
-               return 60;
-
-       /* 100:1 or higher, 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];
-}
-
-/**
- * iwl3945_rx_handle - Main entry function for receiving responses from 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 iwl3945_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;
-       u8 fill_rx = 0;
-       u32 count = 8;
-       int total_empty = 0;
-
-       /* uCode's read index (stored in shared DRAM) indicates the last Rx
-        * buffer that the driver may process (last buffer filled by ucode). */
-       r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
-       i = rxq->read;
-
-       /* calculate total frames need to be restock after handling RX */
-       total_empty = r - rxq->write_actual;
-       if (total_empty < 0)
-               total_empty += RX_QUEUE_SIZE;
-
-       if (total_empty > (RX_QUEUE_SIZE / 2))
-               fill_rx = 1;
-       /* Rx interrupt, but nothing sent from uCode */
-       if (i == r)
-               IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
-
-       while (i != r) {
-               int len;
-
-               rxb = rxq->queue[i];
-
-               /* If an RXB doesn't have a Rx 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_unmap_page(priv->pci_dev, rxb->page_dma,
-                              PAGE_SIZE << priv->hw_params.rx_page_order,
-                              PCI_DMA_FROMDEVICE);
-               pkt = rxb_addr(rxb);
-
-               len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
-               len += sizeof(u32); /* account for status word */
-               trace_iwlwifi_legacy_dev_rx(priv, pkt, len);
-
-               /* 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 iwl3945_setup_rx_handlers() */
-               if (priv->rx_handlers[pkt->hdr.cmd]) {
-                       IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
-                       iwl_legacy_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
-                       priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
-                       priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
-               } else {
-                       /* No handling needed */
-                       IWL_DEBUG_RX(priv,
-                               "r %d i %d No handler needed for %s, 0x%02x\n",
-                               r, i, iwl_legacy_get_cmd_string(pkt->hdr.cmd),
-                               pkt->hdr.cmd);
-               }
-
-               /*
-                * XXX: After here, we should always check rxb->page
-                * against NULL before touching it or its virtual
-                * memory (pkt). Because some rx_handler might have
-                * already taken or freed the pages.
-                */
-
-               if (reclaim) {
-                       /* Invoke any callbacks, transfer the buffer to caller,
-                        * and fire off the (possibly) blocking iwl_legacy_send_cmd()
-                        * as we reclaim the driver command queue */
-                       if (rxb->page)
-                               iwl_legacy_tx_cmd_complete(priv, rxb);
-                       else
-                               IWL_WARN(priv, "Claim null rxb?\n");
-               }
-
-               /* Reuse the page if possible. For notification packets and
-                * SKBs that fail to Rx correctly, add them back into the
-                * rx_free list for reuse later. */
-               spin_lock_irqsave(&rxq->lock, flags);
-               if (rxb->page != NULL) {
-                       rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
-                               0, PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-                       list_add_tail(&rxb->list, &rxq->rx_free);
-                       rxq->free_count++;
-               } else
-                       list_add_tail(&rxb->list, &rxq->rx_used);
-
-               spin_unlock_irqrestore(&rxq->lock, flags);
-
-               i = (i + 1) & RX_QUEUE_MASK;
-               /* If there are a lot of unused frames,
-                * restock the Rx queue so ucode won't assert. */
-               if (fill_rx) {
-                       count++;
-                       if (count >= 8) {
-                               rxq->read = i;
-                               iwl3945_rx_replenish_now(priv);
-                               count = 0;
-                       }
-               }
-       }
-
-       /* Backtrack one entry */
-       rxq->read = i;
-       if (fill_rx)
-               iwl3945_rx_replenish_now(priv);
-       else
-               iwl3945_rx_queue_restock(priv);
-}
-
-/* call this function to flush any scheduled tasklet */
-static inline void iwl3945_synchronize_irq(struct iwl_priv *priv)
-{
-       /* wait to make sure we flush pending tasklet*/
-       synchronize_irq(priv->pci_dev->irq);
-       tasklet_kill(&priv->irq_tasklet);
-}
-
-static const char *iwl3945_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))
-
-void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
-{
-       u32 i;
-       u32 desc, time, count, base, data1;
-       u32 blink1, blink2, ilink1, ilink2;
-
-       base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-
-       if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-               IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
-               return;
-       }
-
-
-       count = iwl_legacy_read_targ_mem(priv, base);
-
-       if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
-               IWL_ERR(priv, "Start IWL Error Log Dump:\n");
-               IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
-                       priv->status, count);
-       }
-
-       IWL_ERR(priv, "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_legacy_read_targ_mem(priv, base + i);
-               time =
-                   iwl_legacy_read_targ_mem(priv, base + i + 1 * sizeof(u32));
-               blink1 =
-                   iwl_legacy_read_targ_mem(priv, base + i + 2 * sizeof(u32));
-               blink2 =
-                   iwl_legacy_read_targ_mem(priv, base + i + 3 * sizeof(u32));
-               ilink1 =
-                   iwl_legacy_read_targ_mem(priv, base + i + 4 * sizeof(u32));
-               ilink2 =
-                   iwl_legacy_read_targ_mem(priv, base + i + 5 * sizeof(u32));
-               data1 =
-                   iwl_legacy_read_targ_mem(priv, base + i + 6 * sizeof(u32));
-
-               IWL_ERR(priv,
-                       "%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
-                       iwl3945_desc_lookup(desc), desc, time, blink1, blink2,
-                       ilink1, ilink2, data1);
-               trace_iwlwifi_legacy_dev_ucode_error(priv, desc, time, data1, 0,
-                                       0, blink1, blink2, ilink1, ilink2);
-       }
-}
-
-static void iwl3945_irq_tasklet(struct iwl_priv *priv)
-{
-       u32 inta, handled = 0;
-       u32 inta_fh;
-       unsigned long flags;
-#ifdef CONFIG_IWLWIFI_LEGACY_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_LEGACY_DEBUG
-       if (iwl_legacy_get_debug_level(priv) & IWL_DL_ISR) {
-               /* just for debug */
-               inta_mask = iwl_read32(priv, CSR_INT_MASK);
-               IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-                             inta, inta_mask, inta_fh);
-       }
-#endif
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* 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 & CSR39_FH_INT_RX_MASK)
-               inta |= CSR_INT_BIT_FH_RX;
-       if (inta_fh & CSR39_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_ERR(priv, "Hardware error detected.  Restarting.\n");
-
-               /* Tell the device to stop sending interrupts */
-               iwl_legacy_disable_interrupts(priv);
-
-               priv->isr_stats.hw++;
-               iwl_legacy_irq_handle_error(priv);
-
-               handled |= CSR_INT_BIT_HW_ERR;
-
-               return;
-       }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) {
-               /* NIC fires this, but we don't use it, redundant with WAKEUP */
-               if (inta & CSR_INT_BIT_SCD) {
-                       IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
-                                     "the frame/frames.\n");
-                       priv->isr_stats.sch++;
-               }
-
-               /* Alive notification via Rx interrupt will do the real work */
-               if (inta & CSR_INT_BIT_ALIVE) {
-                       IWL_DEBUG_ISR(priv, "Alive interrupt\n");
-                       priv->isr_stats.alive++;
-               }
-       }
-#endif
-       /* Safely ignore these bits for debug checks below */
-       inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
-
-       /* Error detected by uCode */
-       if (inta & CSR_INT_BIT_SW_ERR) {
-               IWL_ERR(priv, "Microcode SW error detected. "
-                       "Restarting 0x%X.\n", inta);
-               priv->isr_stats.sw++;
-               iwl_legacy_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(priv, "Wakeup interrupt\n");
-               iwl_legacy_rx_queue_update_write_ptr(priv, &priv->rxq);
-               iwl_legacy_txq_update_write_ptr(priv, &priv->txq[0]);
-               iwl_legacy_txq_update_write_ptr(priv, &priv->txq[1]);
-               iwl_legacy_txq_update_write_ptr(priv, &priv->txq[2]);
-               iwl_legacy_txq_update_write_ptr(priv, &priv->txq[3]);
-               iwl_legacy_txq_update_write_ptr(priv, &priv->txq[4]);
-               iwl_legacy_txq_update_write_ptr(priv, &priv->txq[5]);
-
-               priv->isr_stats.wakeup++;
-               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)) {
-               iwl3945_rx_handle(priv);
-               priv->isr_stats.rx++;
-               handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
-       }
-
-       if (inta & CSR_INT_BIT_FH_TX) {
-               IWL_DEBUG_ISR(priv, "Tx interrupt\n");
-               priv->isr_stats.tx++;
-
-               iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
-               iwl_legacy_write_direct32(priv, FH39_TCSR_CREDIT
-                                       (FH39_SRVC_CHNL), 0x0);
-               handled |= CSR_INT_BIT_FH_TX;
-       }
-
-       if (inta & ~handled) {
-               IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
-               priv->isr_stats.unhandled++;
-       }
-
-       if (inta & ~priv->inta_mask) {
-               IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
-                        inta & ~priv->inta_mask);
-               IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
-       }
-
-       /* Re-enable all interrupts */
-       /* only Re-enable if disabled by irq */
-       if (test_bit(STATUS_INT_ENABLED, &priv->status))
-               iwl_legacy_enable_interrupts(priv);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (iwl_legacy_get_debug_level(priv) & (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(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
-                       "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
-       }
-#endif
-}
-
-static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
-                                        enum ieee80211_band band,
-                                    u8 is_active, u8 n_probes,
-                                    struct iwl3945_scan_channel *scan_ch,
-                                    struct ieee80211_vif *vif)
-{
-       struct ieee80211_channel *chan;
-       const struct ieee80211_supported_band *sband;
-       const struct iwl_channel_info *ch_info;
-       u16 passive_dwell = 0;
-       u16 active_dwell = 0;
-       int added, i;
-
-       sband = iwl_get_hw_mode(priv, band);
-       if (!sband)
-               return 0;
-
-       active_dwell = iwl_legacy_get_active_dwell_time(priv, band, n_probes);
-       passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
-       if (passive_dwell <= active_dwell)
-               passive_dwell = active_dwell + 1;
-
-       for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
-               chan = priv->scan_request->channels[i];
-
-               if (chan->band != band)
-                       continue;
-
-               scan_ch->channel = chan->hw_value;
-
-               ch_info = iwl_legacy_get_channel_info(priv, band,
-                                                       scan_ch->channel);
-               if (!iwl_legacy_is_channel_valid(ch_info)) {
-                       IWL_DEBUG_SCAN(priv,
-                               "Channel %d is INVALID for this band.\n",
-                              scan_ch->channel);
-                       continue;
-               }
-
-               scan_ch->active_dwell = cpu_to_le16(active_dwell);
-               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-               /* If passive , set up for auto-switch
-                *  and use long active_dwell time.
-                */
-               if (!is_active || iwl_legacy_is_channel_passive(ch_info) ||
-                   (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
-                       scan_ch->type = 0;      /* passive */
-                       if (IWL_UCODE_API(priv->ucode_ver) == 1)
-                               scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
-               } else {
-                       scan_ch->type = 1;      /* active */
-               }
-
-               /* Set direct probe bits. These may be used both for active
-                * scan channels (probes gets sent right away),
-                * or for passive channels (probes get se sent only after
-                * hearing clear Rx packet).*/
-               if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
-                       if (n_probes)
-                               scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
-               } else {
-                       /* uCode v1 does not allow setting direct probe bits on
-                        * passive channel. */
-                       if ((scan_ch->type & 1) && n_probes)
-                               scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
-               }
-
-               /* Set txpower levels to defaults */
-               scan_ch->tpc.dsp_atten = 110;
-               /* scan_pwr_info->tpc.dsp_atten; */
-
-               /*scan_pwr_info->tpc.tx_gain; */
-               if (band == IEEE80211_BAND_5GHZ)
-                       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(priv, "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(priv, "total channels to scan %d\n", added);
-       return added;
-}
-
-static void iwl3945_init_hw_rates(struct iwl_priv *priv,
-                             struct ieee80211_rate *rates)
-{
-       int i;
-
-       for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
-               rates[i].bitrate = iwl3945_rates[i].ieee * 5;
-               rates[i].hw_value = i; /* Rate scaling will work on indexes */
-               rates[i].hw_value_short = i;
-               rates[i].flags = 0;
-               if ((i > IWL39_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
-                       /*
-                        * If CCK != 1M then set short preamble rate flag.
-                        */
-                       rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
-                               0 : IEEE80211_RATE_SHORT_PREAMBLE;
-               }
-       }
-}
-
-/******************************************************************************
- *
- * uCode download functions
- *
- ******************************************************************************/
-
-static void iwl3945_dealloc_ucode_pci(struct iwl_priv *priv)
-{
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_code);
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data);
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init);
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
-}
-
-/**
- * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host,
- *     looking at all data.
- */
-static int iwl3945_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(priv, "ucode inst image size is %u\n", len);
-
-       iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-                              IWL39_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_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               if (val != le32_to_cpu(*image)) {
-                       IWL_ERR(priv, "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;
-               }
-       }
-
-
-       if (!errcnt)
-               IWL_DEBUG_INFO(priv,
-                       "ucode image in INSTRUCTION memory is good\n");
-
-       return rc;
-}
-
-
-/**
- * iwl3945_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 iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
-{
-       u32 val;
-       int rc = 0;
-       u32 errcnt = 0;
-       u32 i;
-
-       IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
-
-       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_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-                       i + IWL39_RTC_INST_LOWER_BOUND);
-               val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               if (val != le32_to_cpu(*image)) {
-#if 0 /* Enable this if you want to see details */
-                       IWL_ERR(priv, "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;
-               }
-       }
-
-       return rc;
-}
-
-
-/**
- * iwl3945_verify_ucode - determine which instruction image is in SRAM,
- *    and verify its contents
- */
-static int iwl3945_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 = iwl3945_verify_inst_sparse(priv, image, len);
-       if (rc == 0) {
-               IWL_DEBUG_INFO(priv, "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 = iwl3945_verify_inst_sparse(priv, image, len);
-       if (rc == 0) {
-               IWL_DEBUG_INFO(priv, "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 = iwl3945_verify_inst_sparse(priv, image, len);
-       if (rc == 0) {
-               IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
-               return 0;
-       }
-
-       IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
-
-       /* Since nothing seems to match, show first several data entries in
-        * instruction SRAM, so maybe visual inspection will give a clue.
-        * Selection of bootstrap image (vs. other images) is arbitrary. */
-       image = (__le32 *)priv->ucode_boot.v_addr;
-       len = priv->ucode_boot.len;
-       rc = iwl3945_verify_inst_full(priv, image, len);
-
-       return rc;
-}
-
-static void iwl3945_nic_start(struct iwl_priv *priv)
-{
-       /* Remove all resets to allow NIC to operate */
-       iwl_write32(priv, CSR_RESET, 0);
-}
-
-#define IWL3945_UCODE_GET(item)                                                \
-static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\
-{                                                                      \
-       return le32_to_cpu(ucode->v1.item);                             \
-}
-
-static u32 iwl3945_ucode_get_header_size(u32 api_ver)
-{
-       return 24;
-}
-
-static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode)
-{
-       return (u8 *) ucode->v1.data;
-}
-
-IWL3945_UCODE_GET(inst_size);
-IWL3945_UCODE_GET(data_size);
-IWL3945_UCODE_GET(init_size);
-IWL3945_UCODE_GET(init_data_size);
-IWL3945_UCODE_GET(boot_size);
-
-/**
- * iwl3945_read_ucode - Read uCode images from disk file.
- *
- * Copy into buffers for card to fetch via bus-mastering
- */
-static int iwl3945_read_ucode(struct iwl_priv *priv)
-{
-       const struct iwl_ucode_header *ucode;
-       int ret = -EINVAL, index;
-       const struct firmware *ucode_raw;
-       /* firmware file name contains uCode/driver compatibility version */
-       const char *name_pre = priv->cfg->fw_name_pre;
-       const unsigned int api_max = priv->cfg->ucode_api_max;
-       const unsigned int api_min = priv->cfg->ucode_api_min;
-       char buf[25];
-       u8 *src;
-       size_t len;
-       u32 api_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. */
-       for (index = api_max; index >= api_min; index--) {
-               sprintf(buf, "%s%u%s", name_pre, index, ".ucode");
-               ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
-               if (ret < 0) {
-                       IWL_ERR(priv, "%s firmware file req failed: %d\n",
-                                 buf, ret);
-                       if (ret == -ENOENT)
-                               continue;
-                       else
-                               goto error;
-               } else {
-                       if (index < api_max)
-                               IWL_ERR(priv, "Loaded firmware %s, "
-                                       "which is deprecated. "
-                                       " Please use API v%u instead.\n",
-                                         buf, api_max);
-                       IWL_DEBUG_INFO(priv, "Got firmware '%s' file "
-                                      "(%zd bytes) from disk\n",
-                                      buf, ucode_raw->size);
-                       break;
-               }
-       }
-
-       if (ret < 0)
-               goto error;
-
-       /* Make sure that we got at least our header! */
-       if (ucode_raw->size <  iwl3945_ucode_get_header_size(1)) {
-               IWL_ERR(priv, "File size way too small!\n");
-               ret = -EINVAL;
-               goto err_release;
-       }
-
-       /* Data from ucode file:  header followed by uCode images */
-       ucode = (struct iwl_ucode_header *)ucode_raw->data;
-
-       priv->ucode_ver = le32_to_cpu(ucode->ver);
-       api_ver = IWL_UCODE_API(priv->ucode_ver);
-       inst_size = iwl3945_ucode_get_inst_size(ucode);
-       data_size = iwl3945_ucode_get_data_size(ucode);
-       init_size = iwl3945_ucode_get_init_size(ucode);
-       init_data_size = iwl3945_ucode_get_init_data_size(ucode);
-       boot_size = iwl3945_ucode_get_boot_size(ucode);
-       src = iwl3945_ucode_get_data(ucode);
-
-       /* api_ver should match the api version forming part of the
-        * firmware filename ... but we don't check for that and only rely
-        * on the API version read from firmware header from here on forward */
-
-       if (api_ver < api_min || api_ver > api_max) {
-               IWL_ERR(priv, "Driver unable to support your firmware API. "
-                         "Driver supports v%u, firmware is v%u.\n",
-                         api_max, api_ver);
-               priv->ucode_ver = 0;
-               ret = -EINVAL;
-               goto err_release;
-       }
-       if (api_ver != api_max)
-               IWL_ERR(priv, "Firmware has old API version. Expected %u, "
-                         "got %u. New firmware can be obtained "
-                         "from http://www.intellinuxwireless.org.\n",
-                         api_max, api_ver);
-
-       IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
-               IWL_UCODE_MAJOR(priv->ucode_ver),
-               IWL_UCODE_MINOR(priv->ucode_ver),
-               IWL_UCODE_API(priv->ucode_ver),
-               IWL_UCODE_SERIAL(priv->ucode_ver));
-
-       snprintf(priv->hw->wiphy->fw_version,
-                sizeof(priv->hw->wiphy->fw_version),
-                "%u.%u.%u.%u",
-                IWL_UCODE_MAJOR(priv->ucode_ver),
-                IWL_UCODE_MINOR(priv->ucode_ver),
-                IWL_UCODE_API(priv->ucode_ver),
-                IWL_UCODE_SERIAL(priv->ucode_ver));
-
-       IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
-                      priv->ucode_ver);
-       IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
-                      inst_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n",
-                      data_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n",
-                      init_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n",
-                      init_data_size);
-       IWL_DEBUG_INFO(priv, "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 != iwl3945_ucode_get_header_size(api_ver) +
-               inst_size + data_size + init_size +
-               init_data_size + boot_size) {
-
-               IWL_DEBUG_INFO(priv,
-                       "uCode file size %zd does not match expected size\n",
-                       ucode_raw->size);
-               ret = -EINVAL;
-               goto err_release;
-       }
-
-       /* Verify that uCode images will fit in card's SRAM */
-       if (inst_size > IWL39_MAX_INST_SIZE) {
-               IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n",
-                              inst_size);
-               ret = -EINVAL;
-               goto err_release;
-       }
-
-       if (data_size > IWL39_MAX_DATA_SIZE) {
-               IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n",
-                              data_size);
-               ret = -EINVAL;
-               goto err_release;
-       }
-       if (init_size > IWL39_MAX_INST_SIZE) {
-               IWL_DEBUG_INFO(priv,
-                               "uCode init instr len %d too large to fit in\n",
-                               init_size);
-               ret = -EINVAL;
-               goto err_release;
-       }
-       if (init_data_size > IWL39_MAX_DATA_SIZE) {
-               IWL_DEBUG_INFO(priv,
-                               "uCode init data len %d too large to fit in\n",
-                               init_data_size);
-               ret = -EINVAL;
-               goto err_release;
-       }
-       if (boot_size > IWL39_MAX_BSM_SIZE) {
-               IWL_DEBUG_INFO(priv,
-                               "uCode boot instr len %d too large to fit in\n",
-                               boot_size);
-               ret = -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;
-       iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
-
-       priv->ucode_data.len = data_size;
-       iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
-
-       priv->ucode_data_backup.len = data_size;
-       iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
-
-       if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
-           !priv->ucode_data_backup.v_addr)
-               goto err_pci_alloc;
-
-       /* Initialization instructions and data */
-       if (init_size && init_data_size) {
-               priv->ucode_init.len = init_size;
-               iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
-
-               priv->ucode_init_data.len = init_data_size;
-               iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
-
-               if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
-                       goto err_pci_alloc;
-       }
-
-       /* Bootstrap (instructions only, no data) */
-       if (boot_size) {
-               priv->ucode_boot.len = boot_size;
-               iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
-
-               if (!priv->ucode_boot.v_addr)
-                       goto err_pci_alloc;
-       }
-
-       /* Copy images into buffers for card's bus-master reads ... */
-
-       /* Runtime instructions (first block of data in file) */
-       len = inst_size;
-       IWL_DEBUG_INFO(priv,
-               "Copying (but not loading) uCode instr len %zd\n", len);
-       memcpy(priv->ucode_code.v_addr, src, len);
-       src += len;
-
-       IWL_DEBUG_INFO(priv, "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 iwl3945_up()  */
-       len = data_size;
-       IWL_DEBUG_INFO(priv,
-               "Copying (but not loading) uCode data len %zd\n", len);
-       memcpy(priv->ucode_data.v_addr, src, len);
-       memcpy(priv->ucode_data_backup.v_addr, src, len);
-       src += len;
-
-       /* Initialization instructions (3rd block) */
-       if (init_size) {
-               len = init_size;
-               IWL_DEBUG_INFO(priv,
-                       "Copying (but not loading) init instr len %zd\n", len);
-               memcpy(priv->ucode_init.v_addr, src, len);
-               src += len;
-       }
-
-       /* Initialization data (4th block) */
-       if (init_data_size) {
-               len = init_data_size;
-               IWL_DEBUG_INFO(priv,
-                       "Copying (but not loading) init data len %zd\n", len);
-               memcpy(priv->ucode_init_data.v_addr, src, len);
-               src += len;
-       }
-
-       /* Bootstrap instructions (5th block) */
-       len = boot_size;
-       IWL_DEBUG_INFO(priv,
-               "Copying (but not loading) boot instr len %zd\n", 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_ERR(priv, "failed to allocate pci memory\n");
-       ret = -ENOMEM;
-       iwl3945_dealloc_ucode_pci(priv);
-
- err_release:
-       release_firmware(ucode_raw);
-
- error:
-       return ret;
-}
-
-
-/**
- * iwl3945_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 iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
-{
-       dma_addr_t pinst;
-       dma_addr_t pdata;
-
-       /* bits 31:0 for 3945 */
-       pinst = priv->ucode_code.p_addr;
-       pdata = priv->ucode_data_backup.p_addr;
-
-       /* Tell bootstrap uCode where to find image to load */
-       iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-       iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-       iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
-                                priv->ucode_data.len);
-
-       /* Inst byte count must be last to set up, bit 31 signals uCode
-        *   that all new ptr/size info is in place */
-       iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
-                                priv->ucode_code.len | BSM_DRAM_INST_LOAD);
-
-       IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
-
-       return 0;
-}
-
-/**
- * iwl3945_init_alive_start - Called after REPLY_ALIVE notification received
- *
- * Called after REPLY_ALIVE notification received from "initialize" uCode.
- *
- * Tell "initialize" uCode to go ahead and load the runtime uCode.
- */
-static void iwl3945_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(priv, "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 (iwl3945_verify_ucode(priv)) {
-               /* Runtime instruction load was bad;
-                * take it all the way back down so we can try again */
-               IWL_DEBUG_INFO(priv, "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(priv, "Initialization Alive received.\n");
-       if (iwl3945_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(priv, "Couldn't set up uCode pointers.\n");
-               goto restart;
-       }
-       return;
-
- restart:
-       queue_work(priv->workqueue, &priv->restart);
-}
-
-/**
- * iwl3945_alive_start - called after REPLY_ALIVE notification received
- *                   from protocol/runtime uCode (initialization uCode's
- *                   Alive gets handled by iwl3945_init_alive_start()).
- */
-static void iwl3945_alive_start(struct iwl_priv *priv)
-{
-       int thermal_spin = 0;
-       u32 rfkill;
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       IWL_DEBUG_INFO(priv, "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(priv, "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 (iwl3945_verify_ucode(priv)) {
-               /* Runtime instruction load was bad;
-                * take it all the way back down so we can try again */
-               IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
-               goto restart;
-       }
-
-       rfkill = iwl_legacy_read_prph(priv, APMG_RFKILL_REG);
-       IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill);
-
-       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 (iwl3945_hw_get_temperature(priv) == 0) {
-                       thermal_spin++;
-                       udelay(10);
-               }
-
-               if (thermal_spin)
-                       IWL_DEBUG_INFO(priv, "Thermal calibration took %dus\n",
-                                      thermal_spin * 10);
-       } else
-               set_bit(STATUS_RF_KILL_HW, &priv->status);
-
-       /* After the ALIVE response, we can send commands to 3945 uCode */
-       set_bit(STATUS_ALIVE, &priv->status);
-
-       /* Enable watchdog to monitor the driver tx queues */
-       iwl_legacy_setup_watchdog(priv);
-
-       if (iwl_legacy_is_rfkill(priv))
-               return;
-
-       ieee80211_wake_queues(priv->hw);
-
-       priv->active_rate = IWL_RATES_MASK_3945;
-
-       iwl_legacy_power_update_mode(priv, true);
-
-       if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
-               struct iwl3945_rxon_cmd *active_rxon =
-                               (struct iwl3945_rxon_cmd *)(&ctx->active);
-
-               ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-               active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       } else {
-               /* Initialize our rx_config data */
-               iwl_legacy_connection_init_rx_config(priv, ctx);
-       }
-
-       /* Configure Bluetooth device coexistence support */
-       iwl_legacy_send_bt_config(priv);
-
-       set_bit(STATUS_READY, &priv->status);
-
-       /* Configure the adapter for unassociated operation */
-       iwl3945_commit_rxon(priv, ctx);
-
-       iwl3945_reg_txpower_periodic(priv);
-
-       IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
-       wake_up(&priv->wait_command_queue);
-
-       return;
-
- restart:
-       queue_work(priv->workqueue, &priv->restart);
-}
-
-static void iwl3945_cancel_deferred_work(struct iwl_priv *priv);
-
-static void __iwl3945_down(struct iwl_priv *priv)
-{
-       unsigned long flags;
-       int exit_pending;
-
-       IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
-
-       iwl_legacy_scan_cancel_timeout(priv, 200);
-
-       exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-       /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
-        * to prevent rearm timer */
-       del_timer_sync(&priv->watchdog);
-
-       /* Station information will now be cleared in device */
-       iwl_legacy_clear_ucode_stations(priv, NULL);
-       iwl_legacy_dealloc_bcast_stations(priv);
-       iwl_legacy_clear_driver_stations(priv);
-
-       /* Unblock any waiting calls */
-       wake_up_all(&priv->wait_command_queue);
-
-       /* 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 */
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_legacy_disable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       iwl3945_synchronize_irq(priv);
-
-       if (priv->mac80211_registered)
-               ieee80211_stop_queues(priv->hw);
-
-       /* If we have not previously called iwl3945_init() then
-        * clear all bits but the RF Kill bits and return */
-       if (!iwl_legacy_is_init(priv)) {
-               priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
-                                       STATUS_RF_KILL_HW |
-                              test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
-                                       STATUS_GEO_CONFIGURED |
-                               test_bit(STATUS_EXIT_PENDING, &priv->status) <<
-                                       STATUS_EXIT_PENDING;
-               goto exit;
-       }
-
-       /* ...otherwise clear out all the status bits but the RF Kill
-        * bit and continue taking the NIC down. */
-       priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
-                               STATUS_RF_KILL_HW |
-                       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
-                               STATUS_GEO_CONFIGURED |
-                       test_bit(STATUS_FW_ERROR, &priv->status) <<
-                               STATUS_FW_ERROR |
-                       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
-                               STATUS_EXIT_PENDING;
-
-       iwl3945_hw_txq_ctx_stop(priv);
-       iwl3945_hw_rxq_stop(priv);
-
-       /* Power-down device's busmaster DMA clocks */
-       iwl_legacy_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
-       udelay(5);
-
-       /* Stop the device, and put it in low power state */
-       iwl_legacy_apm_stop(priv);
-
- exit:
-       memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
-
-       if (priv->beacon_skb)
-               dev_kfree_skb(priv->beacon_skb);
-       priv->beacon_skb = NULL;
-
-       /* clear out any free frames */
-       iwl3945_clear_free_frames(priv);
-}
-
-static void iwl3945_down(struct iwl_priv *priv)
-{
-       mutex_lock(&priv->mutex);
-       __iwl3945_down(priv);
-       mutex_unlock(&priv->mutex);
-
-       iwl3945_cancel_deferred_work(priv);
-}
-
-#define MAX_HW_RESTARTS 5
-
-static int iwl3945_alloc_bcast_station(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       unsigned long flags;
-       u8 sta_id;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       sta_id = iwl_legacy_prep_station(priv, ctx,
-                                       iwlegacy_bcast_addr, false, NULL);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Unable to prepare broadcast station\n");
-               spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-               return -EINVAL;
-       }
-
-       priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
-       priv->stations[sta_id].used |= IWL_STA_BCAST;
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-       return 0;
-}
-
-static int __iwl3945_up(struct iwl_priv *priv)
-{
-       int rc, i;
-
-       rc = iwl3945_alloc_bcast_station(priv);
-       if (rc)
-               return rc;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-               IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
-               return -EIO;
-       }
-
-       if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
-               IWL_ERR(priv, "ucode not available for device bring up\n");
-               return -EIO;
-       }
-
-       /* If platform's RF_KILL switch is NOT set to KILL */
-       if (iwl_read32(priv, CSR_GP_CNTRL) &
-                               CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-               clear_bit(STATUS_RF_KILL_HW, &priv->status);
-       else {
-               set_bit(STATUS_RF_KILL_HW, &priv->status);
-               IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
-               return -ENODEV;
-       }
-
-       iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-
-       rc = iwl3945_hw_nic_init(priv);
-       if (rc) {
-               IWL_ERR(priv, "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_legacy_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);
-
-       /* We return success when we resume from suspend and rf_kill is on. */
-       if (test_bit(STATUS_RF_KILL_HW, &priv->status))
-               return 0;
-
-       for (i = 0; i < MAX_HW_RESTARTS; i++) {
-
-               /* load bootstrap state machine,
-                * load bootstrap program into processor's memory,
-                * prepare to load the "initialize" uCode */
-               rc = priv->cfg->ops->lib->load_ucode(priv);
-
-               if (rc) {
-                       IWL_ERR(priv,
-                               "Unable to set up bootstrap uCode: %d\n", rc);
-                       continue;
-               }
-
-               /* start card; "initialize" will load runtime ucode */
-               iwl3945_nic_start(priv);
-
-               IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
-
-               return 0;
-       }
-
-       set_bit(STATUS_EXIT_PENDING, &priv->status);
-       __iwl3945_down(priv);
-       clear_bit(STATUS_EXIT_PENDING, &priv->status);
-
-       /* tried to restart and config the device for as long as our
-        * patience could withstand */
-       IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
-       return -EIO;
-}
-
-
-/*****************************************************************************
- *
- * Workqueue callbacks
- *
- *****************************************************************************/
-
-static void iwl3945_bg_init_alive_start(struct work_struct *data)
-{
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, init_alive_start.work);
-
-       mutex_lock(&priv->mutex);
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               goto out;
-
-       iwl3945_init_alive_start(priv);
-out:
-       mutex_unlock(&priv->mutex);
-}
-
-static void iwl3945_bg_alive_start(struct work_struct *data)
-{
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, alive_start.work);
-
-       mutex_lock(&priv->mutex);
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               goto out;
-
-       iwl3945_alive_start(priv);
-out:
-       mutex_unlock(&priv->mutex);
-}
-
-/*
- * 3945 cannot interrupt driver when hardware rf kill switch toggles;
- * driver must poll CSR_GP_CNTRL_REG register for change.  This register
- * *is* readable even when device has been SW_RESET into low power mode
- * (e.g. during RF KILL).
- */
-static void iwl3945_rfkill_poll(struct work_struct *data)
-{
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, _3945.rfkill_poll.work);
-       bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status);
-       bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL)
-                       & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
-
-       if (new_rfkill != old_rfkill) {
-               if (new_rfkill)
-                       set_bit(STATUS_RF_KILL_HW, &priv->status);
-               else
-                       clear_bit(STATUS_RF_KILL_HW, &priv->status);
-
-               wiphy_rfkill_set_hw_state(priv->hw->wiphy, new_rfkill);
-
-               IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
-                               new_rfkill ? "disable radio" : "enable radio");
-       }
-
-       /* Keep this running, even if radio now enabled.  This will be
-        * cancelled in mac_start() if system decides to start again */
-       queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
-                          round_jiffies_relative(2 * HZ));
-
-}
-
-int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_SCAN_CMD,
-               .len = sizeof(struct iwl3945_scan_cmd),
-               .flags = CMD_SIZE_HUGE,
-       };
-       struct iwl3945_scan_cmd *scan;
-       u8 n_probes = 0;
-       enum ieee80211_band band;
-       bool is_active = false;
-       int ret;
-       u16 len;
-
-       lockdep_assert_held(&priv->mutex);
-
-       if (!priv->scan_cmd) {
-               priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) +
-                                        IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-               if (!priv->scan_cmd) {
-                       IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
-                       return -ENOMEM;
-               }
-       }
-       scan = priv->scan_cmd;
-       memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
-
-       scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
-       scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
-
-       if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
-               u16 interval;
-               u32 extra;
-               u32 suspend_time = 100;
-               u32 scan_suspend_time = 100;
-
-               IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-
-               interval = vif->bss_conf.beacon_int;
-
-               scan->suspend_time = 0;
-               scan->max_out_time = cpu_to_le32(200 * 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(priv, "suspend_time 0x%X beacon interval %d\n",
-                              scan_suspend_time, interval);
-       }
-
-       if (priv->scan_request->n_ssids) {
-               int i, p = 0;
-               IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
-               for (i = 0; i < priv->scan_request->n_ssids; i++) {
-                       /* always does wildcard anyway */
-                       if (!priv->scan_request->ssids[i].ssid_len)
-                               continue;
-                       scan->direct_scan[p].id = WLAN_EID_SSID;
-                       scan->direct_scan[p].len =
-                               priv->scan_request->ssids[i].ssid_len;
-                       memcpy(scan->direct_scan[p].ssid,
-                              priv->scan_request->ssids[i].ssid,
-                              priv->scan_request->ssids[i].ssid_len);
-                       n_probes++;
-                       p++;
-               }
-               is_active = true;
-       } else
-               IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n");
-
-       /* 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.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
-       scan->tx_cmd.sta_id = priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
-       scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
-       /* flags + rate selection */
-
-       switch (priv->scan_band) {
-       case IEEE80211_BAND_2GHZ:
-               scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
-               scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
-               band = IEEE80211_BAND_2GHZ;
-               break;
-       case IEEE80211_BAND_5GHZ:
-               scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
-               band = IEEE80211_BAND_5GHZ;
-               break;
-       default:
-               IWL_WARN(priv, "Invalid scan band\n");
-               return -EIO;
-       }
-
-       /*
-        * If active scaning is requested but a certain channel
-        * is marked passive, we can do active scanning if we
-        * detect transmissions.
-        */
-       scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
-                                       IWL_GOOD_CRC_TH_DISABLED;
-
-       len = iwl_legacy_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
-                                       vif->addr, priv->scan_request->ie,
-                                       priv->scan_request->ie_len,
-                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
-       scan->tx_cmd.len = cpu_to_le16(len);
-
-       /* select Rx antennas */
-       scan->flags |= iwl3945_get_antenna_flags(priv);
-
-       scan->channel_count = iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
-                                                           (void *)&scan->data[len], vif);
-       if (scan->channel_count == 0) {
-               IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
-               return -EIO;
-       }
-
-       cmd.len += le16_to_cpu(scan->tx_cmd.len) +
-           scan->channel_count * sizeof(struct iwl3945_scan_channel);
-       cmd.data = scan;
-       scan->len = cpu_to_le16(cmd.len);
-
-       set_bit(STATUS_SCAN_HW, &priv->status);
-       ret = iwl_legacy_send_cmd_sync(priv, &cmd);
-       if (ret)
-               clear_bit(STATUS_SCAN_HW, &priv->status);
-       return ret;
-}
-
-void iwl3945_post_scan(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       /*
-        * Since setting the RXON may have been deferred while
-        * performing the scan, fire one off if needed
-        */
-       if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
-               iwl3945_commit_rxon(priv, ctx);
-}
-
-static void iwl3945_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;
-
-       if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
-               struct iwl_rxon_context *ctx;
-               mutex_lock(&priv->mutex);
-               for_each_context(priv, ctx)
-                       ctx->vif = NULL;
-               priv->is_open = 0;
-               mutex_unlock(&priv->mutex);
-               iwl3945_down(priv);
-               ieee80211_restart_hw(priv->hw);
-       } else {
-               iwl3945_down(priv);
-
-               mutex_lock(&priv->mutex);
-               if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-                       mutex_unlock(&priv->mutex);
-                       return;
-               }
-
-               __iwl3945_up(priv);
-               mutex_unlock(&priv->mutex);
-       }
-}
-
-static void iwl3945_bg_rx_replenish(struct work_struct *data)
-{
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, rx_replenish);
-
-       mutex_lock(&priv->mutex);
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               goto out;
-
-       iwl3945_rx_replenish(priv);
-out:
-       mutex_unlock(&priv->mutex);
-}
-
-void iwl3945_post_associate(struct iwl_priv *priv)
-{
-       int rc = 0;
-       struct ieee80211_conf *conf = NULL;
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       if (!ctx->vif || !priv->is_open)
-               return;
-
-       IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-                       ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       iwl_legacy_scan_cancel_timeout(priv, 200);
-
-       conf = iwl_legacy_ieee80211_get_hw_conf(priv->hw);
-
-       ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwl3945_commit_rxon(priv, ctx);
-
-       rc = iwl_legacy_send_rxon_timing(priv, ctx);
-       if (rc)
-               IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
-                           "Attempting to continue.\n");
-
-       ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-
-       ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
-
-       IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-                       ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
-
-       if (ctx->vif->bss_conf.use_short_preamble)
-               ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-       else
-               ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-       if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-               if (ctx->vif->bss_conf.use_short_slot)
-                       ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
-               else
-                       ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-       }
-
-       iwl3945_commit_rxon(priv, ctx);
-
-       switch (ctx->vif->type) {
-       case NL80211_IFTYPE_STATION:
-               iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
-               break;
-       case NL80211_IFTYPE_ADHOC:
-               iwl3945_send_beacon_cmd(priv);
-               break;
-       default:
-               IWL_ERR(priv, "%s Should not be called in %d mode\n",
-                       __func__, ctx->vif->type);
-               break;
-       }
-}
-
-/*****************************************************************************
- *
- * mac80211 entry point functions
- *
- *****************************************************************************/
-
-#define UCODE_READY_TIMEOUT    (2 * HZ)
-
-static int iwl3945_mac_start(struct ieee80211_hw *hw)
-{
-       struct iwl_priv *priv = hw->priv;
-       int ret;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       /* we should be verifying the device is ready to be opened */
-       mutex_lock(&priv->mutex);
-
-       /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
-        * ucode filename and max sizes are card-specific. */
-
-       if (!priv->ucode_code.len) {
-               ret = iwl3945_read_ucode(priv);
-               if (ret) {
-                       IWL_ERR(priv, "Could not read microcode: %d\n", ret);
-                       mutex_unlock(&priv->mutex);
-                       goto out_release_irq;
-               }
-       }
-
-       ret = __iwl3945_up(priv);
-
-       mutex_unlock(&priv->mutex);
-
-       if (ret)
-               goto out_release_irq;
-
-       IWL_DEBUG_INFO(priv, "Start UP work.\n");
-
-       /* Wait for START_ALIVE from ucode. Otherwise callbacks from
-        * mac80211 will not be run successfully. */
-       ret = wait_event_timeout(priv->wait_command_queue,
-                       test_bit(STATUS_READY, &priv->status),
-                       UCODE_READY_TIMEOUT);
-       if (!ret) {
-               if (!test_bit(STATUS_READY, &priv->status)) {
-                       IWL_ERR(priv,
-                               "Wait for START_ALIVE timeout after %dms.\n",
-                               jiffies_to_msecs(UCODE_READY_TIMEOUT));
-                       ret = -ETIMEDOUT;
-                       goto out_release_irq;
-               }
-       }
-
-       /* ucode is running and will send rfkill notifications,
-        * no need to poll the killswitch state anymore */
-       cancel_delayed_work(&priv->_3945.rfkill_poll);
-
-       priv->is_open = 1;
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       return 0;
-
-out_release_irq:
-       priv->is_open = 0;
-       IWL_DEBUG_MAC80211(priv, "leave - failed\n");
-       return ret;
-}
-
-static void iwl3945_mac_stop(struct ieee80211_hw *hw)
-{
-       struct iwl_priv *priv = hw->priv;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (!priv->is_open) {
-               IWL_DEBUG_MAC80211(priv, "leave - skip\n");
-               return;
-       }
-
-       priv->is_open = 0;
-
-       iwl3945_down(priv);
-
-       flush_workqueue(priv->workqueue);
-
-       /* start polling the killswitch state again */
-       queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
-                          round_jiffies_relative(2 * HZ));
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-static void iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct iwl_priv *priv = hw->priv;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-                    ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
-
-       if (iwl3945_tx_skb(priv, skb))
-               dev_kfree_skb_any(skb);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-void iwl3945_config_ap(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       struct ieee80211_vif *vif = ctx->vif;
-       int rc = 0;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       /* The following should be done only at AP bring up */
-       if (!(iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS))) {
-
-               /* RXON - unassoc (to set timing command) */
-               ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv, ctx);
-
-               /* RXON Timing */
-               rc = iwl_legacy_send_rxon_timing(priv, ctx);
-               if (rc)
-                       IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
-                                       "Attempting to continue.\n");
-
-               ctx->staging.assoc_id = 0;
-
-               if (vif->bss_conf.use_short_preamble)
-                       ctx->staging.flags |=
-                               RXON_FLG_SHORT_PREAMBLE_MSK;
-               else
-                       ctx->staging.flags &=
-                               ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-               if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-                       if (vif->bss_conf.use_short_slot)
-                               ctx->staging.flags |=
-                                       RXON_FLG_SHORT_SLOT_MSK;
-                       else
-                               ctx->staging.flags &=
-                                       ~RXON_FLG_SHORT_SLOT_MSK;
-               }
-               /* restore RXON assoc */
-               ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-               iwl3945_commit_rxon(priv, ctx);
-       }
-       iwl3945_send_beacon_cmd(priv);
-}
-
-static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-                              struct ieee80211_vif *vif,
-                              struct ieee80211_sta *sta,
-                              struct ieee80211_key_conf *key)
-{
-       struct iwl_priv *priv = hw->priv;
-       int ret = 0;
-       u8 sta_id = IWL_INVALID_STATION;
-       u8 static_key;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (iwl3945_mod_params.sw_crypto) {
-               IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
-               return -EOPNOTSUPP;
-       }
-
-       /*
-        * To support IBSS RSN, don't program group keys in IBSS, the
-        * hardware will then not attempt to decrypt the frames.
-        */
-       if (vif->type == NL80211_IFTYPE_ADHOC &&
-           !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
-               return -EOPNOTSUPP;
-
-       static_key = !iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS);
-
-       if (!static_key) {
-               sta_id = iwl_legacy_sta_id_or_broadcast(
-                               priv, &priv->contexts[IWL_RXON_CTX_BSS], sta);
-               if (sta_id == IWL_INVALID_STATION)
-                       return -EINVAL;
-       }
-
-       mutex_lock(&priv->mutex);
-       iwl_legacy_scan_cancel_timeout(priv, 100);
-
-       switch (cmd) {
-       case SET_KEY:
-               if (static_key)
-                       ret = iwl3945_set_static_key(priv, key);
-               else
-                       ret = iwl3945_set_dynamic_key(priv, key, sta_id);
-               IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
-               break;
-       case DISABLE_KEY:
-               if (static_key)
-                       ret = iwl3945_remove_static_key(priv);
-               else
-                       ret = iwl3945_clear_sta_key_info(priv, sta_id);
-               IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-       mutex_unlock(&priv->mutex);
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-       return ret;
-}
-
-static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
-                              struct ieee80211_vif *vif,
-                              struct ieee80211_sta *sta)
-{
-       struct iwl_priv *priv = hw->priv;
-       struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv;
-       int ret;
-       bool is_ap = vif->type == NL80211_IFTYPE_STATION;
-       u8 sta_id;
-
-       IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
-                       sta->addr);
-       mutex_lock(&priv->mutex);
-       IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
-                       sta->addr);
-       sta_priv->common.sta_id = IWL_INVALID_STATION;
-
-
-       ret = iwl_legacy_add_station_common(priv,
-                               &priv->contexts[IWL_RXON_CTX_BSS],
-                                    sta->addr, is_ap, sta, &sta_id);
-       if (ret) {
-               IWL_ERR(priv, "Unable to add station %pM (%d)\n",
-                       sta->addr, ret);
-               /* Should we return success if return code is EEXIST ? */
-               mutex_unlock(&priv->mutex);
-               return ret;
-       }
-
-       sta_priv->common.sta_id = sta_id;
-
-       /* Initialize rate scaling */
-       IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
-                      sta->addr);
-       iwl3945_rs_rate_init(priv, sta, sta_id);
-       mutex_unlock(&priv->mutex);
-
-       return 0;
-}
-
-static void iwl3945_configure_filter(struct ieee80211_hw *hw,
-                                    unsigned int changed_flags,
-                                    unsigned int *total_flags,
-                                    u64 multicast)
-{
-       struct iwl_priv *priv = hw->priv;
-       __le32 filter_or = 0, filter_nand = 0;
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-#define CHK(test, flag)        do { \
-       if (*total_flags & (test))              \
-               filter_or |= (flag);            \
-       else                                    \
-               filter_nand |= (flag);          \
-       } while (0)
-
-       IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
-                       changed_flags, *total_flags);
-
-       CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
-       CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
-       CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
-
-#undef CHK
-
-       mutex_lock(&priv->mutex);
-
-       ctx->staging.filter_flags &= ~filter_nand;
-       ctx->staging.filter_flags |= filter_or;
-
-       /*
-        * Not committing directly because hardware can perform a scan,
-        * but even if hw is ready, committing here breaks for some reason,
-        * we'll eventually commit the filter flags change anyway.
-        */
-
-       mutex_unlock(&priv->mutex);
-
-       /*
-        * Receiving all multicast frames is always enabled by the
-        * default flags setup in iwl_legacy_connection_init_rx_config()
-        * since we currently do not support programming multicast
-        * filters into the device.
-        */
-       *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
-                       FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
-}
-
-
-/*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-
-#ifdef CONFIG_IWLWIFI_LEGACY_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/iwl/)
- * used for controlling the debug level.
- *
- * See the level definitions in iwl for details.
- *
- * The debug_level being managed using sysfs below is a per device debug
- * level that is used instead of the global debug level if it (the per
- * device debug level) is set.
- */
-static ssize_t iwl3945_show_debug_level(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       return sprintf(buf, "0x%08X\n", iwl_legacy_get_debug_level(priv));
-}
-static ssize_t iwl3945_store_debug_level(struct device *d,
-                               struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 0, &val);
-       if (ret)
-               IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
-       else {
-               priv->debug_level = val;
-               if (iwl_legacy_alloc_traffic_mem(priv))
-                       IWL_ERR(priv,
-                               "Not enough memory to generate traffic log\n");
-       }
-       return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
-                       iwl3945_show_debug_level, iwl3945_store_debug_level);
-
-#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
-
-static ssize_t iwl3945_show_temperature(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       if (!iwl_legacy_is_alive(priv))
-               return -EAGAIN;
-
-       return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv));
-}
-
-static DEVICE_ATTR(temperature, S_IRUGO, iwl3945_show_temperature, NULL);
-
-static ssize_t iwl3945_show_tx_power(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
-}
-
-static ssize_t iwl3945_store_tx_power(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       char *p = (char *)buf;
-       u32 val;
-
-       val = simple_strtoul(p, &p, 10);
-       if (p == buf)
-               IWL_INFO(priv, ": %s is not in decimal form.\n", buf);
-       else
-               iwl3945_hw_reg_set_txpower(priv, val);
-
-       return count;
-}
-
-static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, iwl3945_show_tx_power, iwl3945_store_tx_power);
-
-static ssize_t iwl3945_show_flags(struct device *d,
-                         struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       return sprintf(buf, "0x%04X\n", ctx->active.flags);
-}
-
-static ssize_t iwl3945_store_flags(struct device *d,
-                          struct device_attribute *attr,
-                          const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       u32 flags = simple_strtoul(buf, NULL, 0);
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       mutex_lock(&priv->mutex);
-       if (le32_to_cpu(ctx->staging.flags) != flags) {
-               /* Cancel any currently running scans... */
-               if (iwl_legacy_scan_cancel_timeout(priv, 100))
-                       IWL_WARN(priv, "Could not cancel scan.\n");
-               else {
-                       IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
-                                      flags);
-                       ctx->staging.flags = cpu_to_le32(flags);
-                       iwl3945_commit_rxon(priv, ctx);
-               }
-       }
-       mutex_unlock(&priv->mutex);
-
-       return count;
-}
-
-static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, iwl3945_show_flags, iwl3945_store_flags);
-
-static ssize_t iwl3945_show_filter_flags(struct device *d,
-                                struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       return sprintf(buf, "0x%04X\n",
-               le32_to_cpu(ctx->active.filter_flags));
-}
-
-static ssize_t iwl3945_store_filter_flags(struct device *d,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       u32 filter_flags = simple_strtoul(buf, NULL, 0);
-
-       mutex_lock(&priv->mutex);
-       if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) {
-               /* Cancel any currently running scans... */
-               if (iwl_legacy_scan_cancel_timeout(priv, 100))
-                       IWL_WARN(priv, "Could not cancel scan.\n");
-               else {
-                       IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
-                                      "0x%04X\n", filter_flags);
-                       ctx->staging.filter_flags =
-                               cpu_to_le32(filter_flags);
-                       iwl3945_commit_rxon(priv, ctx);
-               }
-       }
-       mutex_unlock(&priv->mutex);
-
-       return count;
-}
-
-static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, iwl3945_show_filter_flags,
-                  iwl3945_store_filter_flags);
-
-static ssize_t iwl3945_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;
-
-       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);
-
-       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);
-       }
-
-       return len;
-}
-
-static ssize_t iwl3945_store_measurement(struct device *d,
-                                struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       struct ieee80211_measurement_params params = {
-               .channel = le16_to_cpu(ctx->active.channel),
-               .start_time = cpu_to_le64(priv->_3945.last_tsf),
-               .duration = cpu_to_le16(1),
-       };
-       u8 type = IWL_MEASURE_BASIC;
-       u8 buffer[32];
-       u8 channel;
-
-       if (count) {
-               char *p = buffer;
-               strncpy(buffer, buf, min(sizeof(buffer), count));
-               channel = simple_strtoul(p, NULL, 0);
-               if (channel)
-                       params.channel = channel;
-
-               p = buffer;
-               while (*p && *p != ' ')
-                       p++;
-               if (*p)
-                       type = simple_strtoul(p + 1, NULL, 0);
-       }
-
-       IWL_DEBUG_INFO(priv, "Invoking measurement of type %d on "
-                      "channel %d (for '%s')\n", type, params.channel, buf);
-       iwl3945_get_measurement(priv, &params, type);
-
-       return count;
-}
-
-static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
-                  iwl3945_show_measurement, iwl3945_store_measurement);
-
-static ssize_t iwl3945_store_retry_rate(struct device *d,
-                               struct device_attribute *attr,
-                               const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       priv->retry_rate = simple_strtoul(buf, NULL, 0);
-       if (priv->retry_rate <= 0)
-               priv->retry_rate = 1;
-
-       return count;
-}
-
-static ssize_t iwl3945_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);
-}
-
-static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, iwl3945_show_retry_rate,
-                  iwl3945_store_retry_rate);
-
-
-static ssize_t iwl3945_show_channels(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       /* all this shit doesn't belong into sysfs anyway */
-       return 0;
-}
-
-static DEVICE_ATTR(channels, S_IRUSR, iwl3945_show_channels, NULL);
-
-static ssize_t iwl3945_show_antenna(struct device *d,
-                           struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       if (!iwl_legacy_is_alive(priv))
-               return -EAGAIN;
-
-       return sprintf(buf, "%d\n", iwl3945_mod_params.antenna);
-}
-
-static ssize_t iwl3945_store_antenna(struct device *d,
-                            struct device_attribute *attr,
-                            const char *buf, size_t count)
-{
-       struct iwl_priv *priv __maybe_unused = dev_get_drvdata(d);
-       int ant;
-
-       if (count == 0)
-               return 0;
-
-       if (sscanf(buf, "%1i", &ant) != 1) {
-               IWL_DEBUG_INFO(priv, "not in hex or decimal form.\n");
-               return count;
-       }
-
-       if ((ant >= 0) && (ant <= 2)) {
-               IWL_DEBUG_INFO(priv, "Setting antenna select to %d.\n", ant);
-               iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant;
-       } else
-               IWL_DEBUG_INFO(priv, "Bad antenna select value %d.\n", ant);
-
-
-       return count;
-}
-
-static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, iwl3945_show_antenna, iwl3945_store_antenna);
-
-static ssize_t iwl3945_show_status(struct device *d,
-                          struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       if (!iwl_legacy_is_alive(priv))
-               return -EAGAIN;
-       return sprintf(buf, "0x%08x\n", (int)priv->status);
-}
-
-static DEVICE_ATTR(status, S_IRUGO, iwl3945_show_status, NULL);
-
-static ssize_t iwl3945_dump_error_log(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       char *p = (char *)buf;
-
-       if (p[0] == '1')
-               iwl3945_dump_nic_error_log(priv);
-
-       return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, iwl3945_dump_error_log);
-
-/*****************************************************************************
- *
- * driver setup and tear down
- *
- *****************************************************************************/
-
-static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
-{
-       priv->workqueue = create_singlethread_workqueue(DRV_NAME);
-
-       init_waitqueue_head(&priv->wait_command_queue);
-
-       INIT_WORK(&priv->restart, iwl3945_bg_restart);
-       INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
-       INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
-       INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
-       INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
-
-       iwl_legacy_setup_scan_deferred_work(priv);
-
-       iwl3945_hw_setup_deferred_work(priv);
-
-       init_timer(&priv->watchdog);
-       priv->watchdog.data = (unsigned long)priv;
-       priv->watchdog.function = iwl_legacy_bg_watchdog;
-
-       tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-                    iwl3945_irq_tasklet, (unsigned long)priv);
-}
-
-static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
-{
-       iwl3945_hw_cancel_deferred_work(priv);
-
-       cancel_delayed_work_sync(&priv->init_alive_start);
-       cancel_delayed_work(&priv->alive_start);
-
-       iwl_legacy_cancel_scan_deferred_work(priv);
-}
-
-static struct attribute *iwl3945_sysfs_entries[] = {
-       &dev_attr_antenna.attr,
-       &dev_attr_channels.attr,
-       &dev_attr_dump_errors.attr,
-       &dev_attr_flags.attr,
-       &dev_attr_filter_flags.attr,
-       &dev_attr_measurement.attr,
-       &dev_attr_retry_rate.attr,
-       &dev_attr_status.attr,
-       &dev_attr_temperature.attr,
-       &dev_attr_tx_power.attr,
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       &dev_attr_debug_level.attr,
-#endif
-       NULL
-};
-
-static struct attribute_group iwl3945_attribute_group = {
-       .name = NULL,           /* put in device directory */
-       .attrs = iwl3945_sysfs_entries,
-};
-
-struct ieee80211_ops iwl3945_hw_ops = {
-       .tx = iwl3945_mac_tx,
-       .start = iwl3945_mac_start,
-       .stop = iwl3945_mac_stop,
-       .add_interface = iwl_legacy_mac_add_interface,
-       .remove_interface = iwl_legacy_mac_remove_interface,
-       .change_interface = iwl_legacy_mac_change_interface,
-       .config = iwl_legacy_mac_config,
-       .configure_filter = iwl3945_configure_filter,
-       .set_key = iwl3945_mac_set_key,
-       .conf_tx = iwl_legacy_mac_conf_tx,
-       .reset_tsf = iwl_legacy_mac_reset_tsf,
-       .bss_info_changed = iwl_legacy_mac_bss_info_changed,
-       .hw_scan = iwl_legacy_mac_hw_scan,
-       .sta_add = iwl3945_mac_sta_add,
-       .sta_remove = iwl_legacy_mac_sta_remove,
-       .tx_last_beacon = iwl_legacy_mac_tx_last_beacon,
-};
-
-static int iwl3945_init_drv(struct iwl_priv *priv)
-{
-       int ret;
-       struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-
-       priv->retry_rate = 1;
-       priv->beacon_skb = NULL;
-
-       spin_lock_init(&priv->sta_lock);
-       spin_lock_init(&priv->hcmd_lock);
-
-       INIT_LIST_HEAD(&priv->free_frames);
-
-       mutex_init(&priv->mutex);
-
-       priv->ieee_channels = NULL;
-       priv->ieee_rates = NULL;
-       priv->band = IEEE80211_BAND_2GHZ;
-
-       priv->iw_mode = NL80211_IFTYPE_STATION;
-       priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
-
-       /* initialize force reset */
-       priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
-
-       if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
-               IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
-                        eeprom->version);
-               ret = -EINVAL;
-               goto err;
-       }
-       ret = iwl_legacy_init_channel_map(priv);
-       if (ret) {
-               IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
-               goto err;
-       }
-
-       /* Set up txpower settings in driver for all channels */
-       if (iwl3945_txpower_set_from_eeprom(priv)) {
-               ret = -EIO;
-               goto err_free_channel_map;
-       }
-
-       ret = iwl_legacy_init_geos(priv);
-       if (ret) {
-               IWL_ERR(priv, "initializing geos failed: %d\n", ret);
-               goto err_free_channel_map;
-       }
-       iwl3945_init_hw_rates(priv, priv->ieee_rates);
-
-       return 0;
-
-err_free_channel_map:
-       iwl_legacy_free_channel_map(priv);
-err:
-       return ret;
-}
-
-#define IWL3945_MAX_PROBE_REQUEST      200
-
-static int iwl3945_setup_mac(struct iwl_priv *priv)
-{
-       int ret;
-       struct ieee80211_hw *hw = priv->hw;
-
-       hw->rate_control_algorithm = "iwl-3945-rs";
-       hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
-       hw->vif_data_size = sizeof(struct iwl_vif_priv);
-
-       /* Tell mac80211 our characteristics */
-       hw->flags = IEEE80211_HW_SIGNAL_DBM |
-                   IEEE80211_HW_SPECTRUM_MGMT;
-
-       hw->wiphy->interface_modes =
-               priv->contexts[IWL_RXON_CTX_BSS].interface_modes;
-
-       hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
-                           WIPHY_FLAG_DISABLE_BEACON_HINTS |
-                           WIPHY_FLAG_IBSS_RSN;
-
-       hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
-       /* we create the 802.11 header and a zero-length SSID element */
-       hw->wiphy->max_scan_ie_len = IWL3945_MAX_PROBE_REQUEST - 24 - 2;
-
-       /* Default value; 4 EDCA QOS priorities */
-       hw->queues = 4;
-
-       if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
-               priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-                       &priv->bands[IEEE80211_BAND_2GHZ];
-
-       if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
-               priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-                       &priv->bands[IEEE80211_BAND_5GHZ];
-
-       iwl_legacy_leds_init(priv);
-
-       ret = ieee80211_register_hw(priv->hw);
-       if (ret) {
-               IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
-               return ret;
-       }
-       priv->mac80211_registered = 1;
-
-       return 0;
-}
-
-static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       int err = 0, i;
-       struct iwl_priv *priv;
-       struct ieee80211_hw *hw;
-       struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
-       struct iwl3945_eeprom *eeprom;
-       unsigned long flags;
-
-       /***********************
-        * 1. Allocating HW data
-        * ********************/
-
-       /* mac80211 allocates memory for this device instance, including
-        *   space for this driver's private structure */
-       hw = iwl_legacy_alloc_all(cfg);
-       if (hw == NULL) {
-               pr_err("Can not allocate network device\n");
-               err = -ENOMEM;
-               goto out;
-       }
-       priv = hw->priv;
-       SET_IEEE80211_DEV(hw, &pdev->dev);
-
-       priv->cmd_queue = IWL39_CMD_QUEUE_NUM;
-
-       /* 3945 has only one valid context */
-       priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
-
-       for (i = 0; i < NUM_IWL_RXON_CTX; i++)
-               priv->contexts[i].ctxid = i;
-
-       priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
-       priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
-       priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
-       priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
-       priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
-       priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
-       priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
-               BIT(NL80211_IFTYPE_STATION) |
-               BIT(NL80211_IFTYPE_ADHOC);
-       priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
-       priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
-       priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
-
-       /*
-        * Disabling hardware scan means that mac80211 will perform scans
-        * "the hard way", rather than using device's scan.
-        */
-       if (iwl3945_mod_params.disable_hw_scan) {
-               IWL_DEBUG_INFO(priv, "Disabling hw_scan\n");
-               iwl3945_hw_ops.hw_scan = NULL;
-       }
-
-       IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
-       priv->cfg = cfg;
-       priv->pci_dev = pdev;
-       priv->inta_mask = CSR_INI_SET_MASK;
-
-       if (iwl_legacy_alloc_traffic_mem(priv))
-               IWL_ERR(priv, "Not enough memory to generate traffic log\n");
-
-       /***************************
-        * 2. Initializing PCI bus
-        * *************************/
-       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-                               PCIE_LINK_STATE_CLKPM);
-
-       if (pci_enable_device(pdev)) {
-               err = -ENODEV;
-               goto out_ieee80211_free_hw;
-       }
-
-       pci_set_master(pdev);
-
-       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-       if (!err)
-               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-       if (err) {
-               IWL_WARN(priv, "No suitable DMA available.\n");
-               goto out_pci_disable_device;
-       }
-
-       pci_set_drvdata(pdev, priv);
-       err = pci_request_regions(pdev, DRV_NAME);
-       if (err)
-               goto out_pci_disable_device;
-
-       /***********************
-        * 3. Read REV Register
-        * ********************/
-       priv->hw_base = pci_iomap(pdev, 0, 0);
-       if (!priv->hw_base) {
-               err = -ENODEV;
-               goto out_pci_release_regions;
-       }
-
-       IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
-                       (unsigned long long) pci_resource_len(pdev, 0));
-       IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
-
-       /* 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);
-
-       /* these spin locks will be used in apm_ops.init and EEPROM access
-        * we should init now
-        */
-       spin_lock_init(&priv->reg_lock);
-       spin_lock_init(&priv->lock);
-
-       /*
-        * stop and reset the on-board processor just in case it is in a
-        * strange state ... like being left stranded by a primary kernel
-        * and this is now the kdump kernel trying to start up
-        */
-       iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-       /***********************
-        * 4. Read EEPROM
-        * ********************/
-
-       /* Read the EEPROM */
-       err = iwl_legacy_eeprom_init(priv);
-       if (err) {
-               IWL_ERR(priv, "Unable to init EEPROM\n");
-               goto out_iounmap;
-       }
-       /* MAC Address location in EEPROM same for 3945/4965 */
-       eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-       IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address);
-       SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address);
-
-       /***********************
-        * 5. Setup HW Constants
-        * ********************/
-       /* Device-specific setup */
-       if (iwl3945_hw_set_hw_params(priv)) {
-               IWL_ERR(priv, "failed to set hw settings\n");
-               goto out_eeprom_free;
-       }
-
-       /***********************
-        * 6. Setup priv
-        * ********************/
-
-       err = iwl3945_init_drv(priv);
-       if (err) {
-               IWL_ERR(priv, "initializing driver failed\n");
-               goto out_unset_hw_params;
-       }
-
-       IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n",
-               priv->cfg->name);
-
-       /***********************
-        * 7. Setup Services
-        * ********************/
-
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_legacy_disable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       pci_enable_msi(priv->pci_dev);
-
-       err = request_irq(priv->pci_dev->irq, iwl_legacy_isr,
-                         IRQF_SHARED, DRV_NAME, priv);
-       if (err) {
-               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
-               goto out_disable_msi;
-       }
-
-       err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
-       if (err) {
-               IWL_ERR(priv, "failed to create sysfs device attributes\n");
-               goto out_release_irq;
-       }
-
-       iwl_legacy_set_rxon_channel(priv,
-                            &priv->bands[IEEE80211_BAND_2GHZ].channels[5],
-                            &priv->contexts[IWL_RXON_CTX_BSS]);
-       iwl3945_setup_deferred_work(priv);
-       iwl3945_setup_rx_handlers(priv);
-       iwl_legacy_power_initialize(priv);
-
-       /*********************************
-        * 8. Setup and Register mac80211
-        * *******************************/
-
-       iwl_legacy_enable_interrupts(priv);
-
-       err = iwl3945_setup_mac(priv);
-       if (err)
-               goto  out_remove_sysfs;
-
-       err = iwl_legacy_dbgfs_register(priv, DRV_NAME);
-       if (err)
-               IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
-
-       /* Start monitoring the killswitch */
-       queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
-                          2 * HZ);
-
-       return 0;
-
- out_remove_sysfs:
-       destroy_workqueue(priv->workqueue);
-       priv->workqueue = NULL;
-       sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
- out_release_irq:
-       free_irq(priv->pci_dev->irq, priv);
- out_disable_msi:
-       pci_disable_msi(priv->pci_dev);
-       iwl_legacy_free_geos(priv);
-       iwl_legacy_free_channel_map(priv);
- out_unset_hw_params:
-       iwl3945_unset_hw_params(priv);
- out_eeprom_free:
-       iwl_legacy_eeprom_free(priv);
- out_iounmap:
-       pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
-       pci_release_regions(pdev);
- out_pci_disable_device:
-       pci_set_drvdata(pdev, NULL);
-       pci_disable_device(pdev);
- out_ieee80211_free_hw:
-       iwl_legacy_free_traffic_mem(priv);
-       ieee80211_free_hw(priv->hw);
- out:
-       return err;
-}
-
-static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
-{
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-       unsigned long flags;
-
-       if (!priv)
-               return;
-
-       IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
-
-       iwl_legacy_dbgfs_unregister(priv);
-
-       set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-       iwl_legacy_leds_exit(priv);
-
-       if (priv->mac80211_registered) {
-               ieee80211_unregister_hw(priv->hw);
-               priv->mac80211_registered = 0;
-       } else {
-               iwl3945_down(priv);
-       }
-
-       /*
-        * Make sure device is reset to low power before unloading driver.
-        * This may be redundant with iwl_down(), but there are paths to
-        * run iwl_down() without calling apm_ops.stop(), and there are
-        * paths to avoid running iwl_down() at all before leaving driver.
-        * This (inexpensive) call *makes sure* device is reset.
-        */
-       iwl_legacy_apm_stop(priv);
-
-       /* make sure we flush any pending irq or
-        * tasklet for the driver
-        */
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_legacy_disable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       iwl3945_synchronize_irq(priv);
-
-       sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
-
-       cancel_delayed_work_sync(&priv->_3945.rfkill_poll);
-
-       iwl3945_dealloc_ucode_pci(priv);
-
-       if (priv->rxq.bd)
-               iwl3945_rx_queue_free(priv, &priv->rxq);
-       iwl3945_hw_txq_ctx_free(priv);
-
-       iwl3945_unset_hw_params(priv);
-
-       /*netif_stop_queue(dev); */
-       flush_workqueue(priv->workqueue);
-
-       /* ieee80211_unregister_hw calls iwl3945_mac_stop, which flushes
-        * priv->workqueue... so we can't take down the workqueue
-        * until now... */
-       destroy_workqueue(priv->workqueue);
-       priv->workqueue = NULL;
-       iwl_legacy_free_traffic_mem(priv);
-
-       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);
-
-       iwl_legacy_free_channel_map(priv);
-       iwl_legacy_free_geos(priv);
-       kfree(priv->scan_cmd);
-       if (priv->beacon_skb)
-               dev_kfree_skb(priv->beacon_skb);
-
-       ieee80211_free_hw(priv->hw);
-}
-
-
-/*****************************************************************************
- *
- * driver and module entry point
- *
- *****************************************************************************/
-
-static struct pci_driver iwl3945_driver = {
-       .name = DRV_NAME,
-       .id_table = iwl3945_hw_card_ids,
-       .probe = iwl3945_pci_probe,
-       .remove = __devexit_p(iwl3945_pci_remove),
-       .driver.pm = IWL_LEGACY_PM_OPS,
-};
-
-static int __init iwl3945_init(void)
-{
-
-       int ret;
-       pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
-       pr_info(DRV_COPYRIGHT "\n");
-
-       ret = iwl3945_rate_control_register();
-       if (ret) {
-               pr_err("Unable to register rate control algorithm: %d\n", ret);
-               return ret;
-       }
-
-       ret = pci_register_driver(&iwl3945_driver);
-       if (ret) {
-               pr_err("Unable to initialize PCI module\n");
-               goto error_register;
-       }
-
-       return ret;
-
-error_register:
-       iwl3945_rate_control_unregister();
-       return ret;
-}
-
-static void __exit iwl3945_exit(void)
-{
-       pci_unregister_driver(&iwl3945_driver);
-       iwl3945_rate_control_unregister();
-}
-
-MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
-
-module_param_named(antenna, iwl3945_mod_params.antenna, int, S_IRUGO);
-MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, S_IRUGO);
-MODULE_PARM_DESC(swcrypto,
-               "using software crypto (default 1 [software])");
-module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan,
-               int, S_IRUGO);
-MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 1)");
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-module_param_named(debug, iwlegacy_debug_level, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "debug output mask");
-#endif
-module_param_named(fw_restart, iwl3945_mod_params.restart_fw, int, S_IRUGO);
-MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
-
-module_exit(iwl3945_exit);
-module_init(iwl3945_init);
diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c
deleted file mode 100644 (file)
index d2fba9e..0000000
+++ /dev/null
@@ -1,3281 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 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:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/firmware.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-
-#include <net/mac80211.h>
-
-#include <asm/div64.h>
-
-#define DRV_NAME        "iwl4965"
-
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-sta.h"
-#include "iwl-4965-calib.h"
-#include "iwl-4965.h"
-#include "iwl-4965-led.h"
-
-
-/******************************************************************************
- *
- * module boiler plate
- *
- ******************************************************************************/
-
-/*
- * module name, copyright, version, etc.
- */
-#define DRV_DESCRIPTION        "Intel(R) Wireless WiFi 4965 driver for Linux"
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-#define VD "d"
-#else
-#define VD
-#endif
-
-#define DRV_VERSION     IWLWIFI_VERSION VD
-
-
-MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("iwl4965");
-
-void iwl4965_update_chain_flags(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx;
-
-       if (priv->cfg->ops->hcmd->set_rxon_chain) {
-               for_each_context(priv, ctx) {
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-                       if (ctx->active.rx_chain != ctx->staging.rx_chain)
-                               iwl_legacy_commit_rxon(priv, ctx);
-               }
-       }
-}
-
-static void iwl4965_clear_free_frames(struct iwl_priv *priv)
-{
-       struct list_head *element;
-
-       IWL_DEBUG_INFO(priv, "%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_WARN(priv, "%d frames still in use.  Did we lose one?\n",
-                           priv->frames_count);
-               priv->frames_count = 0;
-       }
-}
-
-static struct iwl_frame *iwl4965_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_ERR(priv, "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 iwl4965_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
-{
-       memset(frame, 0, sizeof(*frame));
-       list_add(&frame->list, &priv->free_frames);
-}
-
-static u32 iwl4965_fill_beacon_frame(struct iwl_priv *priv,
-                                struct ieee80211_hdr *hdr,
-                                int left)
-{
-       lockdep_assert_held(&priv->mutex);
-
-       if (!priv->beacon_skb)
-               return 0;
-
-       if (priv->beacon_skb->len > left)
-               return 0;
-
-       memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
-
-       return priv->beacon_skb->len;
-}
-
-/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
-static void iwl4965_set_beacon_tim(struct iwl_priv *priv,
-                              struct iwl_tx_beacon_cmd *tx_beacon_cmd,
-                              u8 *beacon, u32 frame_size)
-{
-       u16 tim_idx;
-       struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
-
-       /*
-        * The index is relative to frame start but we start looking at the
-        * variable-length part of the beacon.
-        */
-       tim_idx = mgmt->u.beacon.variable - beacon;
-
-       /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
-       while ((tim_idx < (frame_size - 2)) &&
-                       (beacon[tim_idx] != WLAN_EID_TIM))
-               tim_idx += beacon[tim_idx+1] + 2;
-
-       /* If TIM field was found, set variables */
-       if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
-               tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
-               tx_beacon_cmd->tim_size = beacon[tim_idx+1];
-       } else
-               IWL_WARN(priv, "Unable to find TIM Element in beacon\n");
-}
-
-static unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
-                                      struct iwl_frame *frame)
-{
-       struct iwl_tx_beacon_cmd *tx_beacon_cmd;
-       u32 frame_size;
-       u32 rate_flags;
-       u32 rate;
-       /*
-        * We have to set up the TX command, the TX Beacon command, and the
-        * beacon contents.
-        */
-
-       lockdep_assert_held(&priv->mutex);
-
-       if (!priv->beacon_ctx) {
-               IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
-               return 0;
-       }
-
-       /* Initialize memory */
-       tx_beacon_cmd = &frame->u.beacon;
-       memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
-
-       /* Set up TX beacon contents */
-       frame_size = iwl4965_fill_beacon_frame(priv, tx_beacon_cmd->frame,
-                               sizeof(frame->u) - sizeof(*tx_beacon_cmd));
-       if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
-               return 0;
-       if (!frame_size)
-               return 0;
-
-       /* Set up TX command fields */
-       tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
-       tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id;
-       tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-       tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
-               TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
-
-       /* Set up TX beacon command fields */
-       iwl4965_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
-                          frame_size);
-
-       /* Set up packet rate and flags */
-       rate = iwl_legacy_get_lowest_plcp(priv, priv->beacon_ctx);
-       priv->mgmt_tx_ant = iwl4965_toggle_tx_ant(priv, priv->mgmt_tx_ant,
-                                             priv->hw_params.valid_tx_ant);
-       rate_flags = iwl4965_ant_idx_to_flags(priv->mgmt_tx_ant);
-       if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE))
-               rate_flags |= RATE_MCS_CCK_MSK;
-       tx_beacon_cmd->tx.rate_n_flags = iwl4965_hw_set_rate_n_flags(rate,
-                       rate_flags);
-
-       return sizeof(*tx_beacon_cmd) + frame_size;
-}
-
-int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
-{
-       struct iwl_frame *frame;
-       unsigned int frame_size;
-       int rc;
-
-       frame = iwl4965_get_free_frame(priv);
-       if (!frame) {
-               IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
-                         "command.\n");
-               return -ENOMEM;
-       }
-
-       frame_size = iwl4965_hw_get_beacon_cmd(priv, frame);
-       if (!frame_size) {
-               IWL_ERR(priv, "Error configuring the beacon command\n");
-               iwl4965_free_frame(priv, frame);
-               return -EINVAL;
-       }
-
-       rc = iwl_legacy_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
-                             &frame->u.cmd[0]);
-
-       iwl4965_free_frame(priv, frame);
-
-       return rc;
-}
-
-static inline dma_addr_t iwl4965_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
-{
-       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-
-       dma_addr_t addr = get_unaligned_le32(&tb->lo);
-       if (sizeof(dma_addr_t) > sizeof(u32))
-               addr |=
-               ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
-
-       return addr;
-}
-
-static inline u16 iwl4965_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
-{
-       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-
-       return le16_to_cpu(tb->hi_n_len) >> 4;
-}
-
-static inline void iwl4965_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
-                                 dma_addr_t addr, u16 len)
-{
-       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-       u16 hi_n_len = len << 4;
-
-       put_unaligned_le32(addr, &tb->lo);
-       if (sizeof(dma_addr_t) > sizeof(u32))
-               hi_n_len |= ((addr >> 16) >> 16) & 0xF;
-
-       tb->hi_n_len = cpu_to_le16(hi_n_len);
-
-       tfd->num_tbs = idx + 1;
-}
-
-static inline u8 iwl4965_tfd_get_num_tbs(struct iwl_tfd *tfd)
-{
-       return tfd->num_tbs & 0x1f;
-}
-
-/**
- * iwl4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
- * @priv - driver private data
- * @txq - tx queue
- *
- * Does NOT advance any TFD circular buffer read/write indexes
- * Does NOT free the TFD itself (which is within circular buffer)
- */
-void iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-       struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds;
-       struct iwl_tfd *tfd;
-       struct pci_dev *dev = priv->pci_dev;
-       int index = txq->q.read_ptr;
-       int i;
-       int num_tbs;
-
-       tfd = &tfd_tmp[index];
-
-       /* Sanity check on number of chunks */
-       num_tbs = iwl4965_tfd_get_num_tbs(tfd);
-
-       if (num_tbs >= IWL_NUM_OF_TBS) {
-               IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
-               /* @todo issue fatal error, it is quite serious situation */
-               return;
-       }
-
-       /* Unmap tx_cmd */
-       if (num_tbs)
-               pci_unmap_single(dev,
-                               dma_unmap_addr(&txq->meta[index], mapping),
-                               dma_unmap_len(&txq->meta[index], len),
-                               PCI_DMA_BIDIRECTIONAL);
-
-       /* Unmap chunks, if any. */
-       for (i = 1; i < num_tbs; i++)
-               pci_unmap_single(dev, iwl4965_tfd_tb_get_addr(tfd, i),
-                               iwl4965_tfd_tb_get_len(tfd, i),
-                               PCI_DMA_TODEVICE);
-
-       /* free SKB */
-       if (txq->txb) {
-               struct sk_buff *skb;
-
-               skb = txq->txb[txq->q.read_ptr].skb;
-
-               /* can be called from irqs-disabled context */
-               if (skb) {
-                       dev_kfree_skb_any(skb);
-                       txq->txb[txq->q.read_ptr].skb = NULL;
-               }
-       }
-}
-
-int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-                                struct iwl_tx_queue *txq,
-                                dma_addr_t addr, u16 len,
-                                u8 reset, u8 pad)
-{
-       struct iwl_queue *q;
-       struct iwl_tfd *tfd, *tfd_tmp;
-       u32 num_tbs;
-
-       q = &txq->q;
-       tfd_tmp = (struct iwl_tfd *)txq->tfds;
-       tfd = &tfd_tmp[q->write_ptr];
-
-       if (reset)
-               memset(tfd, 0, sizeof(*tfd));
-
-       num_tbs = iwl4965_tfd_get_num_tbs(tfd);
-
-       /* Each TFD can point to a maximum 20 Tx buffers */
-       if (num_tbs >= IWL_NUM_OF_TBS) {
-               IWL_ERR(priv, "Error can not send more than %d chunks\n",
-                         IWL_NUM_OF_TBS);
-               return -EINVAL;
-       }
-
-       BUG_ON(addr & ~DMA_BIT_MASK(36));
-       if (unlikely(addr & ~IWL_TX_DMA_MASK))
-               IWL_ERR(priv, "Unaligned address = %llx\n",
-                         (unsigned long long)addr);
-
-       iwl4965_tfd_set_tb(tfd, num_tbs, addr, len);
-
-       return 0;
-}
-
-/*
- * Tell nic where to find circular buffer of Tx Frame Descriptors for
- * given Tx queue, and enable the DMA channel used for that queue.
- *
- * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
- * channels supported in hardware.
- */
-int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
-                        struct iwl_tx_queue *txq)
-{
-       int txq_id = txq->q.id;
-
-       /* Circular buffer (TFD queue in DRAM) physical base address */
-       iwl_legacy_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
-                            txq->q.dma_addr >> 8);
-
-       return 0;
-}
-
-/******************************************************************************
- *
- * Generic RX handler implementations
- *
- ******************************************************************************/
-static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_alive_resp *palive;
-       struct delayed_work *pwork;
-
-       palive = &pkt->u.alive_frame;
-
-       IWL_DEBUG_INFO(priv, "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(priv, "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(priv, "Runtime Alive received.\n");
-               memcpy(&priv->card_alive, &pkt->u.alive_frame,
-                      sizeof(struct iwl_alive_resp));
-               pwork = &priv->alive_start;
-       }
-
-       /* 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_WARN(priv, "uCode did not respond OK.\n");
-}
-
-/**
- * iwl4965_bg_statistics_periodic - Timer callback to queue statistics
- *
- * This callback is provided in order to send a statistics request.
- *
- * This timer function is continually reset to execute within
- * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
- * was received.  We need to ensure we receive the statistics in order
- * to update the temperature used for calibrating the TXPOWER.
- */
-static void iwl4965_bg_statistics_periodic(unsigned long data)
-{
-       struct iwl_priv *priv = (struct iwl_priv *)data;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       /* dont send host command if rf-kill is on */
-       if (!iwl_legacy_is_ready_rf(priv))
-               return;
-
-       iwl_legacy_send_statistics_request(priv, CMD_ASYNC, false);
-}
-
-static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl4965_beacon_notif *beacon =
-               (struct iwl4965_beacon_notif *)pkt->u.raw;
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
-
-       IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
-               "tsf %d %d rate %d\n",
-               le32_to_cpu(beacon->beacon_notify_hdr.u.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
-
-       priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
-}
-
-static void iwl4965_perform_ct_kill_task(struct iwl_priv *priv)
-{
-       unsigned long flags;
-
-       IWL_DEBUG_POWER(priv, "Stop all queues\n");
-
-       if (priv->mac80211_registered)
-               ieee80211_stop_queues(priv->hw);
-
-       iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-                       CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-       iwl_read32(priv, CSR_UCODE_DRV_GP1);
-
-       spin_lock_irqsave(&priv->reg_lock, flags);
-       if (!iwl_grab_nic_access(priv))
-               iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, flags);
-}
-
-/* Handle notification from uCode that card's power state is changing
- * due to software, hardware, or critical temperature RFKILL */
-static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
-       unsigned long status = priv->status;
-
-       IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
-                         (flags & HW_CARD_DISABLED) ? "Kill" : "On",
-                         (flags & SW_CARD_DISABLED) ? "Kill" : "On",
-                         (flags & CT_CARD_DISABLED) ?
-                         "Reached" : "Not reached");
-
-       if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
-                    CT_CARD_DISABLED)) {
-
-               iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-                           CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-               iwl_legacy_write_direct32(priv, HBUS_TARG_MBX_C,
-                                       HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-
-               if (!(flags & RXON_CARD_DISABLED)) {
-                       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-                                   CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-                       iwl_legacy_write_direct32(priv, HBUS_TARG_MBX_C,
-                                       HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-               }
-       }
-
-       if (flags & CT_CARD_DISABLED)
-               iwl4965_perform_ct_kill_task(priv);
-
-       if (flags & HW_CARD_DISABLED)
-               set_bit(STATUS_RF_KILL_HW, &priv->status);
-       else
-               clear_bit(STATUS_RF_KILL_HW, &priv->status);
-
-       if (!(flags & RXON_CARD_DISABLED))
-               iwl_legacy_scan_cancel(priv);
-
-       if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-            test_bit(STATUS_RF_KILL_HW, &priv->status)))
-               wiphy_rfkill_set_hw_state(priv->hw->wiphy,
-                       test_bit(STATUS_RF_KILL_HW, &priv->status));
-       else
-               wake_up(&priv->wait_command_queue);
-}
-
-/**
- * iwl4965_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 iwl4965_setup_rx_handlers(struct iwl_priv *priv)
-{
-       priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive;
-       priv->rx_handlers[REPLY_ERROR] = iwl_legacy_rx_reply_error;
-       priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_legacy_rx_csa;
-       priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
-                       iwl_legacy_rx_spectrum_measure_notif;
-       priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_legacy_rx_pm_sleep_notif;
-       priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
-           iwl_legacy_rx_pm_debug_statistics_notif;
-       priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
-
-       /*
-        * The same handler is used for both the REPLY to a discrete
-        * statistics request from the host as well as for the periodic
-        * statistics notifications (after received beacons) from the uCode.
-        */
-       priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_reply_statistics;
-       priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_rx_statistics;
-
-       iwl_legacy_setup_rx_scan_handlers(priv);
-
-       /* status change handler */
-       priv->rx_handlers[CARD_STATE_NOTIFICATION] =
-                                       iwl4965_rx_card_state_notif;
-
-       priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
-           iwl4965_rx_missed_beacon_notif;
-       /* Rx handlers */
-       priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
-       priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx;
-       /* block ack */
-       priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
-       /* Set up hardware specific Rx handlers */
-       priv->cfg->ops->lib->rx_handler_setup(priv);
-}
-
-/**
- * iwl4965_rx_handle - Main entry function for receiving responses from uCode
- *
- * Uses the priv->rx_handlers callback function array to invoke
- * the appropriate handlers, including command responses,
- * frame-received notifications, and other notifications.
- */
-void iwl4965_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;
-       u8 fill_rx = 0;
-       u32 count = 8;
-       int total_empty;
-
-       /* uCode's read index (stored in shared DRAM) indicates the last Rx
-        * buffer that the driver may process (last buffer filled by ucode). */
-       r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
-       i = rxq->read;
-
-       /* Rx interrupt, but nothing sent from uCode */
-       if (i == r)
-               IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
-
-       /* calculate total frames need to be restock after handling RX */
-       total_empty = r - rxq->write_actual;
-       if (total_empty < 0)
-               total_empty += RX_QUEUE_SIZE;
-
-       if (total_empty > (RX_QUEUE_SIZE / 2))
-               fill_rx = 1;
-
-       while (i != r) {
-               int len;
-
-               rxb = rxq->queue[i];
-
-               /* If an RXB doesn't have a Rx 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_unmap_page(priv->pci_dev, rxb->page_dma,
-                              PAGE_SIZE << priv->hw_params.rx_page_order,
-                              PCI_DMA_FROMDEVICE);
-               pkt = rxb_addr(rxb);
-
-               len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
-               len += sizeof(u32); /* account for status word */
-               trace_iwlwifi_legacy_dev_rx(priv, pkt, len);
-
-               /* 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_RX) &&
-                       (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
-                       (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
-                       (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 iwl4965_setup_rx_handlers() */
-               if (priv->rx_handlers[pkt->hdr.cmd]) {
-                       IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
-                               i, iwl_legacy_get_cmd_string(pkt->hdr.cmd),
-                               pkt->hdr.cmd);
-                       priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
-                       priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
-               } else {
-                       /* No handling needed */
-                       IWL_DEBUG_RX(priv,
-                               "r %d i %d No handler needed for %s, 0x%02x\n",
-                               r, i, iwl_legacy_get_cmd_string(pkt->hdr.cmd),
-                               pkt->hdr.cmd);
-               }
-
-               /*
-                * XXX: After here, we should always check rxb->page
-                * against NULL before touching it or its virtual
-                * memory (pkt). Because some rx_handler might have
-                * already taken or freed the pages.
-                */
-
-               if (reclaim) {
-                       /* Invoke any callbacks, transfer the buffer to caller,
-                        * and fire off the (possibly) blocking iwl_legacy_send_cmd()
-                        * as we reclaim the driver command queue */
-                       if (rxb->page)
-                               iwl_legacy_tx_cmd_complete(priv, rxb);
-                       else
-                               IWL_WARN(priv, "Claim null rxb?\n");
-               }
-
-               /* Reuse the page if possible. For notification packets and
-                * SKBs that fail to Rx correctly, add them back into the
-                * rx_free list for reuse later. */
-               spin_lock_irqsave(&rxq->lock, flags);
-               if (rxb->page != NULL) {
-                       rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
-                               0, PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-                       list_add_tail(&rxb->list, &rxq->rx_free);
-                       rxq->free_count++;
-               } else
-                       list_add_tail(&rxb->list, &rxq->rx_used);
-
-               spin_unlock_irqrestore(&rxq->lock, flags);
-
-               i = (i + 1) & RX_QUEUE_MASK;
-               /* If there are a lot of unused frames,
-                * restock the Rx queue so ucode wont assert. */
-               if (fill_rx) {
-                       count++;
-                       if (count >= 8) {
-                               rxq->read = i;
-                               iwl4965_rx_replenish_now(priv);
-                               count = 0;
-                       }
-               }
-       }
-
-       /* Backtrack one entry */
-       rxq->read = i;
-       if (fill_rx)
-               iwl4965_rx_replenish_now(priv);
-       else
-               iwl4965_rx_queue_restock(priv);
-}
-
-/* call this function to flush any scheduled tasklet */
-static inline void iwl4965_synchronize_irq(struct iwl_priv *priv)
-{
-       /* wait to make sure we flush pending tasklet*/
-       synchronize_irq(priv->pci_dev->irq);
-       tasklet_kill(&priv->irq_tasklet);
-}
-
-static void iwl4965_irq_tasklet(struct iwl_priv *priv)
-{
-       u32 inta, handled = 0;
-       u32 inta_fh;
-       unsigned long flags;
-       u32 i;
-#ifdef CONFIG_IWLWIFI_LEGACY_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_LEGACY_DEBUG
-       if (iwl_legacy_get_debug_level(priv) & IWL_DL_ISR) {
-               /* just for debug */
-               inta_mask = iwl_read32(priv, CSR_INT_MASK);
-               IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-                             inta, inta_mask, inta_fh);
-       }
-#endif
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* 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 & CSR49_FH_INT_RX_MASK)
-               inta |= CSR_INT_BIT_FH_RX;
-       if (inta_fh & CSR49_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_ERR(priv, "Hardware error detected.  Restarting.\n");
-
-               /* Tell the device to stop sending interrupts */
-               iwl_legacy_disable_interrupts(priv);
-
-               priv->isr_stats.hw++;
-               iwl_legacy_irq_handle_error(priv);
-
-               handled |= CSR_INT_BIT_HW_ERR;
-
-               return;
-       }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) {
-               /* NIC fires this, but we don't use it, redundant with WAKEUP */
-               if (inta & CSR_INT_BIT_SCD) {
-                       IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
-                                     "the frame/frames.\n");
-                       priv->isr_stats.sch++;
-               }
-
-               /* Alive notification via Rx interrupt will do the real work */
-               if (inta & CSR_INT_BIT_ALIVE) {
-                       IWL_DEBUG_ISR(priv, "Alive interrupt\n");
-                       priv->isr_stats.alive++;
-               }
-       }
-#endif
-       /* Safely ignore these bits for debug checks below */
-       inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
-
-       /* HW RF KILL switch toggled */
-       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_WARN(priv, "RF_KILL bit toggled to %s.\n",
-                               hw_rf_kill ? "disable radio" : "enable radio");
-
-               priv->isr_stats.rfkill++;
-
-               /* driver only loads ucode once setting the interface up.
-                * the driver allows loading the ucode even if the radio
-                * is killed. Hence update the killswitch state here. The
-                * rfkill handler will care about restarting if needed.
-                */
-               if (!test_bit(STATUS_ALIVE, &priv->status)) {
-                       if (hw_rf_kill)
-                               set_bit(STATUS_RF_KILL_HW, &priv->status);
-                       else
-                               clear_bit(STATUS_RF_KILL_HW, &priv->status);
-                       wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
-               }
-
-               handled |= CSR_INT_BIT_RF_KILL;
-       }
-
-       /* Chip got too hot and stopped itself */
-       if (inta & CSR_INT_BIT_CT_KILL) {
-               IWL_ERR(priv, "Microcode CT kill error detected.\n");
-               priv->isr_stats.ctkill++;
-               handled |= CSR_INT_BIT_CT_KILL;
-       }
-
-       /* Error detected by uCode */
-       if (inta & CSR_INT_BIT_SW_ERR) {
-               IWL_ERR(priv, "Microcode SW error detected. "
-                       " Restarting 0x%X.\n", inta);
-               priv->isr_stats.sw++;
-               iwl_legacy_irq_handle_error(priv);
-               handled |= CSR_INT_BIT_SW_ERR;
-       }
-
-       /*
-        * uCode wakes up after power-down sleep.
-        * Tell device about any new tx or host commands enqueued,
-        * and about any Rx buffers made available while asleep.
-        */
-       if (inta & CSR_INT_BIT_WAKEUP) {
-               IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
-               iwl_legacy_rx_queue_update_write_ptr(priv, &priv->rxq);
-               for (i = 0; i < priv->hw_params.max_txq_num; i++)
-                       iwl_legacy_txq_update_write_ptr(priv, &priv->txq[i]);
-               priv->isr_stats.wakeup++;
-               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)) {
-               iwl4965_rx_handle(priv);
-               priv->isr_stats.rx++;
-               handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
-       }
-
-       /* This "Tx" DMA channel is used only for loading uCode */
-       if (inta & CSR_INT_BIT_FH_TX) {
-               IWL_DEBUG_ISR(priv, "uCode load interrupt\n");
-               priv->isr_stats.tx++;
-               handled |= CSR_INT_BIT_FH_TX;
-               /* Wake up uCode load routine, now that load is complete */
-               priv->ucode_write_complete = 1;
-               wake_up(&priv->wait_command_queue);
-       }
-
-       if (inta & ~handled) {
-               IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
-               priv->isr_stats.unhandled++;
-       }
-
-       if (inta & ~(priv->inta_mask)) {
-               IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
-                        inta & ~priv->inta_mask);
-               IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
-       }
-
-       /* Re-enable all interrupts */
-       /* only Re-enable if disabled by irq */
-       if (test_bit(STATUS_INT_ENABLED, &priv->status))
-               iwl_legacy_enable_interrupts(priv);
-       /* Re-enable RF_KILL if it occurred */
-       else if (handled & CSR_INT_BIT_RF_KILL)
-               iwl_legacy_enable_rfkill_int(priv);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (iwl_legacy_get_debug_level(priv) & (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(priv,
-                       "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
-                       "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
-       }
-#endif
-}
-
-/*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-
-/*
- * The following adds a new attribute to the sysfs representation
- * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
- * used for controlling the debug level.
- *
- * See the level definitions in iwl for details.
- *
- * The debug_level being managed using sysfs below is a per device debug
- * level that is used instead of the global debug level if it (the per
- * device debug level) is set.
- */
-static ssize_t iwl4965_show_debug_level(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       return sprintf(buf, "0x%08X\n", iwl_legacy_get_debug_level(priv));
-}
-static ssize_t iwl4965_store_debug_level(struct device *d,
-                               struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 0, &val);
-       if (ret)
-               IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
-       else {
-               priv->debug_level = val;
-               if (iwl_legacy_alloc_traffic_mem(priv))
-                       IWL_ERR(priv,
-                               "Not enough memory to generate traffic log\n");
-       }
-       return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
-                       iwl4965_show_debug_level, iwl4965_store_debug_level);
-
-
-#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
-
-
-static ssize_t iwl4965_show_temperature(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       if (!iwl_legacy_is_alive(priv))
-               return -EAGAIN;
-
-       return sprintf(buf, "%d\n", priv->temperature);
-}
-
-static DEVICE_ATTR(temperature, S_IRUGO, iwl4965_show_temperature, NULL);
-
-static ssize_t iwl4965_show_tx_power(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       if (!iwl_legacy_is_ready_rf(priv))
-               return sprintf(buf, "off\n");
-       else
-               return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
-}
-
-static ssize_t iwl4965_store_tx_power(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 10, &val);
-       if (ret)
-               IWL_INFO(priv, "%s is not in decimal form.\n", buf);
-       else {
-               ret = iwl_legacy_set_tx_power(priv, val, false);
-               if (ret)
-                       IWL_ERR(priv, "failed setting tx power (0x%d).\n",
-                               ret);
-               else
-                       ret = count;
-       }
-       return ret;
-}
-
-static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO,
-                       iwl4965_show_tx_power, iwl4965_store_tx_power);
-
-static struct attribute *iwl_sysfs_entries[] = {
-       &dev_attr_temperature.attr,
-       &dev_attr_tx_power.attr,
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       &dev_attr_debug_level.attr,
-#endif
-       NULL
-};
-
-static struct attribute_group iwl_attribute_group = {
-       .name = NULL,           /* put in device directory */
-       .attrs = iwl_sysfs_entries,
-};
-
-/******************************************************************************
- *
- * uCode download functions
- *
- ******************************************************************************/
-
-static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
-{
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_code);
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data);
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init);
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
-       iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
-}
-
-static void iwl4965_nic_start(struct iwl_priv *priv)
-{
-       /* Remove all resets to allow NIC to operate */
-       iwl_write32(priv, CSR_RESET, 0);
-}
-
-static void iwl4965_ucode_callback(const struct firmware *ucode_raw,
-                                       void *context);
-static int iwl4965_mac_setup_register(struct iwl_priv *priv,
-                                               u32 max_probe_length);
-
-static int __must_check iwl4965_request_firmware(struct iwl_priv *priv, bool first)
-{
-       const char *name_pre = priv->cfg->fw_name_pre;
-       char tag[8];
-
-       if (first) {
-               priv->fw_index = priv->cfg->ucode_api_max;
-               sprintf(tag, "%d", priv->fw_index);
-       } else {
-               priv->fw_index--;
-               sprintf(tag, "%d", priv->fw_index);
-       }
-
-       if (priv->fw_index < priv->cfg->ucode_api_min) {
-               IWL_ERR(priv, "no suitable firmware found!\n");
-               return -ENOENT;
-       }
-
-       sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
-
-       IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n",
-                      priv->firmware_name);
-
-       return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
-                                      &priv->pci_dev->dev, GFP_KERNEL, priv,
-                                      iwl4965_ucode_callback);
-}
-
-struct iwl4965_firmware_pieces {
-       const void *inst, *data, *init, *init_data, *boot;
-       size_t inst_size, data_size, init_size, init_data_size, boot_size;
-};
-
-static int iwl4965_load_firmware(struct iwl_priv *priv,
-                                      const struct firmware *ucode_raw,
-                                      struct iwl4965_firmware_pieces *pieces)
-{
-       struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
-       u32 api_ver, hdr_size;
-       const u8 *src;
-
-       priv->ucode_ver = le32_to_cpu(ucode->ver);
-       api_ver = IWL_UCODE_API(priv->ucode_ver);
-
-       switch (api_ver) {
-       default:
-       case 0:
-       case 1:
-       case 2:
-               hdr_size = 24;
-               if (ucode_raw->size < hdr_size) {
-                       IWL_ERR(priv, "File size too small!\n");
-                       return -EINVAL;
-               }
-               pieces->inst_size = le32_to_cpu(ucode->v1.inst_size);
-               pieces->data_size = le32_to_cpu(ucode->v1.data_size);
-               pieces->init_size = le32_to_cpu(ucode->v1.init_size);
-               pieces->init_data_size =
-                               le32_to_cpu(ucode->v1.init_data_size);
-               pieces->boot_size = le32_to_cpu(ucode->v1.boot_size);
-               src = ucode->v1.data;
-               break;
-       }
-
-       /* Verify size of file vs. image size info in file's header */
-       if (ucode_raw->size != hdr_size + pieces->inst_size +
-                               pieces->data_size + pieces->init_size +
-                               pieces->init_data_size + pieces->boot_size) {
-
-               IWL_ERR(priv,
-                       "uCode file size %d does not match expected size\n",
-                       (int)ucode_raw->size);
-               return -EINVAL;
-       }
-
-       pieces->inst = src;
-       src += pieces->inst_size;
-       pieces->data = src;
-       src += pieces->data_size;
-       pieces->init = src;
-       src += pieces->init_size;
-       pieces->init_data = src;
-       src += pieces->init_data_size;
-       pieces->boot = src;
-       src += pieces->boot_size;
-
-       return 0;
-}
-
-/**
- * iwl4965_ucode_callback - callback when firmware was loaded
- *
- * If loaded successfully, copies the firmware into buffers
- * for the card to fetch (via DMA).
- */
-static void
-iwl4965_ucode_callback(const struct firmware *ucode_raw, void *context)
-{
-       struct iwl_priv *priv = context;
-       struct iwl_ucode_header *ucode;
-       int err;
-       struct iwl4965_firmware_pieces pieces;
-       const unsigned int api_max = priv->cfg->ucode_api_max;
-       const unsigned int api_min = priv->cfg->ucode_api_min;
-       u32 api_ver;
-
-       u32 max_probe_length = 200;
-       u32 standard_phy_calibration_size =
-                       IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
-
-       memset(&pieces, 0, sizeof(pieces));
-
-       if (!ucode_raw) {
-               if (priv->fw_index <= priv->cfg->ucode_api_max)
-                       IWL_ERR(priv,
-                               "request for firmware file '%s' failed.\n",
-                               priv->firmware_name);
-               goto try_again;
-       }
-
-       IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n",
-                      priv->firmware_name, ucode_raw->size);
-
-       /* Make sure that we got at least the API version number */
-       if (ucode_raw->size < 4) {
-               IWL_ERR(priv, "File size way too small!\n");
-               goto try_again;
-       }
-
-       /* Data from ucode file:  header followed by uCode images */
-       ucode = (struct iwl_ucode_header *)ucode_raw->data;
-
-       err = iwl4965_load_firmware(priv, ucode_raw, &pieces);
-
-       if (err)
-               goto try_again;
-
-       api_ver = IWL_UCODE_API(priv->ucode_ver);
-
-       /*
-        * api_ver should match the api version forming part of the
-        * firmware filename ... but we don't check for that and only rely
-        * on the API version read from firmware header from here on forward
-        */
-       if (api_ver < api_min || api_ver > api_max) {
-               IWL_ERR(priv,
-                       "Driver unable to support your firmware API. "
-                       "Driver supports v%u, firmware is v%u.\n",
-                       api_max, api_ver);
-               goto try_again;
-       }
-
-       if (api_ver != api_max)
-               IWL_ERR(priv,
-                       "Firmware has old API version. Expected v%u, "
-                       "got v%u. New firmware can be obtained "
-                       "from http://www.intellinuxwireless.org.\n",
-                       api_max, api_ver);
-
-       IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
-                IWL_UCODE_MAJOR(priv->ucode_ver),
-                IWL_UCODE_MINOR(priv->ucode_ver),
-                IWL_UCODE_API(priv->ucode_ver),
-                IWL_UCODE_SERIAL(priv->ucode_ver));
-
-       snprintf(priv->hw->wiphy->fw_version,
-                sizeof(priv->hw->wiphy->fw_version),
-                "%u.%u.%u.%u",
-                IWL_UCODE_MAJOR(priv->ucode_ver),
-                IWL_UCODE_MINOR(priv->ucode_ver),
-                IWL_UCODE_API(priv->ucode_ver),
-                IWL_UCODE_SERIAL(priv->ucode_ver));
-
-       /*
-        * For any of the failures below (before allocating pci memory)
-        * we will try to load a version with a smaller API -- maybe the
-        * user just got a corrupted version of the latest API.
-        */
-
-       IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
-                      priv->ucode_ver);
-       IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n",
-                      pieces.inst_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n",
-                      pieces.data_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n",
-                      pieces.init_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n",
-                      pieces.init_data_size);
-       IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n",
-                      pieces.boot_size);
-
-       /* Verify that uCode images will fit in card's SRAM */
-       if (pieces.inst_size > priv->hw_params.max_inst_size) {
-               IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n",
-                       pieces.inst_size);
-               goto try_again;
-       }
-
-       if (pieces.data_size > priv->hw_params.max_data_size) {
-               IWL_ERR(priv, "uCode data len %Zd too large to fit in\n",
-                       pieces.data_size);
-               goto try_again;
-       }
-
-       if (pieces.init_size > priv->hw_params.max_inst_size) {
-               IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n",
-                       pieces.init_size);
-               goto try_again;
-       }
-
-       if (pieces.init_data_size > priv->hw_params.max_data_size) {
-               IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n",
-                       pieces.init_data_size);
-               goto try_again;
-       }
-
-       if (pieces.boot_size > priv->hw_params.max_bsm_size) {
-               IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n",
-                       pieces.boot_size);
-               goto try_again;
-       }
-
-       /* 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 = pieces.inst_size;
-       iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
-
-       priv->ucode_data.len = pieces.data_size;
-       iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
-
-       priv->ucode_data_backup.len = pieces.data_size;
-       iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
-
-       if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
-           !priv->ucode_data_backup.v_addr)
-               goto err_pci_alloc;
-
-       /* Initialization instructions and data */
-       if (pieces.init_size && pieces.init_data_size) {
-               priv->ucode_init.len = pieces.init_size;
-               iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
-
-               priv->ucode_init_data.len = pieces.init_data_size;
-               iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
-
-               if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
-                       goto err_pci_alloc;
-       }
-
-       /* Bootstrap (instructions only, no data) */
-       if (pieces.boot_size) {
-               priv->ucode_boot.len = pieces.boot_size;
-               iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
-
-               if (!priv->ucode_boot.v_addr)
-                       goto err_pci_alloc;
-       }
-
-       /* Now that we can no longer fail, copy information */
-
-       priv->sta_key_max_num = STA_KEY_MAX_NUM;
-
-       /* Copy images into buffers for card's bus-master reads ... */
-
-       /* Runtime instructions (first block of data in file) */
-       IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n",
-                       pieces.inst_size);
-       memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size);
-
-       IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
-               priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
-
-       /*
-        * Runtime data
-        * NOTE:  Copy into backup buffer will be done in iwl_up()
-        */
-       IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n",
-                       pieces.data_size);
-       memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size);
-       memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size);
-
-       /* Initialization instructions */
-       if (pieces.init_size) {
-               IWL_DEBUG_INFO(priv,
-                               "Copying (but not loading) init instr len %Zd\n",
-                               pieces.init_size);
-               memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size);
-       }
-
-       /* Initialization data */
-       if (pieces.init_data_size) {
-               IWL_DEBUG_INFO(priv,
-                               "Copying (but not loading) init data len %Zd\n",
-                              pieces.init_data_size);
-               memcpy(priv->ucode_init_data.v_addr, pieces.init_data,
-                      pieces.init_data_size);
-       }
-
-       /* Bootstrap instructions */
-       IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n",
-                       pieces.boot_size);
-       memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
-
-       /*
-        * figure out the offset of chain noise reset and gain commands
-        * base on the size of standard phy calibration commands table size
-        */
-       priv->_4965.phy_calib_chain_noise_reset_cmd =
-               standard_phy_calibration_size;
-       priv->_4965.phy_calib_chain_noise_gain_cmd =
-               standard_phy_calibration_size + 1;
-
-       /**************************************************
-        * This is still part of probe() in a sense...
-        *
-        * 9. Setup and register with mac80211 and debugfs
-        **************************************************/
-       err = iwl4965_mac_setup_register(priv, max_probe_length);
-       if (err)
-               goto out_unbind;
-
-       err = iwl_legacy_dbgfs_register(priv, DRV_NAME);
-       if (err)
-               IWL_ERR(priv,
-               "failed to create debugfs files. Ignoring error: %d\n", err);
-
-       err = sysfs_create_group(&priv->pci_dev->dev.kobj,
-                                       &iwl_attribute_group);
-       if (err) {
-               IWL_ERR(priv, "failed to create sysfs device attributes\n");
-               goto out_unbind;
-       }
-
-       /* We have our copies now, allow OS release its copies */
-       release_firmware(ucode_raw);
-       complete(&priv->_4965.firmware_loading_complete);
-       return;
-
- try_again:
-       /* try next, if any */
-       if (iwl4965_request_firmware(priv, false))
-               goto out_unbind;
-       release_firmware(ucode_raw);
-       return;
-
- err_pci_alloc:
-       IWL_ERR(priv, "failed to allocate pci memory\n");
-       iwl4965_dealloc_ucode_pci(priv);
- out_unbind:
-       complete(&priv->_4965.firmware_loading_complete);
-       device_release_driver(&priv->pci_dev->dev);
-       release_firmware(ucode_raw);
-}
-
-static const char * const desc_lookup_text[] = {
-       "OK",
-       "FAIL",
-       "BAD_PARAM",
-       "BAD_CHECKSUM",
-       "NMI_INTERRUPT_WDG",
-       "SYSASSERT",
-       "FATAL_ERROR",
-       "BAD_COMMAND",
-       "HW_ERROR_TUNE_LOCK",
-       "HW_ERROR_TEMPERATURE",
-       "ILLEGAL_CHAN_FREQ",
-       "VCC_NOT_STABLE",
-       "FH_ERROR",
-       "NMI_INTERRUPT_HOST",
-       "NMI_INTERRUPT_ACTION_PT",
-       "NMI_INTERRUPT_UNKNOWN",
-       "UCODE_VERSION_MISMATCH",
-       "HW_ERROR_ABS_LOCK",
-       "HW_ERROR_CAL_LOCK_FAIL",
-       "NMI_INTERRUPT_INST_ACTION_PT",
-       "NMI_INTERRUPT_DATA_ACTION_PT",
-       "NMI_TRM_HW_ER",
-       "NMI_INTERRUPT_TRM",
-       "NMI_INTERRUPT_BREAK_POINT",
-       "DEBUG_0",
-       "DEBUG_1",
-       "DEBUG_2",
-       "DEBUG_3",
-};
-
-static struct { char *name; u8 num; } advanced_lookup[] = {
-       { "NMI_INTERRUPT_WDG", 0x34 },
-       { "SYSASSERT", 0x35 },
-       { "UCODE_VERSION_MISMATCH", 0x37 },
-       { "BAD_COMMAND", 0x38 },
-       { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
-       { "FATAL_ERROR", 0x3D },
-       { "NMI_TRM_HW_ERR", 0x46 },
-       { "NMI_INTERRUPT_TRM", 0x4C },
-       { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
-       { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
-       { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
-       { "NMI_INTERRUPT_HOST", 0x66 },
-       { "NMI_INTERRUPT_ACTION_PT", 0x7C },
-       { "NMI_INTERRUPT_UNKNOWN", 0x84 },
-       { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
-       { "ADVANCED_SYSASSERT", 0 },
-};
-
-static const char *iwl4965_desc_lookup(u32 num)
-{
-       int i;
-       int max = ARRAY_SIZE(desc_lookup_text);
-
-       if (num < max)
-               return desc_lookup_text[num];
-
-       max = ARRAY_SIZE(advanced_lookup) - 1;
-       for (i = 0; i < max; i++) {
-               if (advanced_lookup[i].num == num)
-                       break;
-       }
-       return advanced_lookup[i].name;
-}
-
-#define ERROR_START_OFFSET  (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
-
-void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
-{
-       u32 data2, line;
-       u32 desc, time, count, base, data1;
-       u32 blink1, blink2, ilink1, ilink2;
-       u32 pc, hcmd;
-
-       if (priv->ucode_type == UCODE_INIT) {
-               base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
-       } else {
-               base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-       }
-
-       if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
-               IWL_ERR(priv,
-                       "Not valid error log pointer 0x%08X for %s uCode\n",
-                       base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
-               return;
-       }
-
-       count = iwl_legacy_read_targ_mem(priv, base);
-
-       if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
-               IWL_ERR(priv, "Start IWL Error Log Dump:\n");
-               IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
-                       priv->status, count);
-       }
-
-       desc = iwl_legacy_read_targ_mem(priv, base + 1 * sizeof(u32));
-       priv->isr_stats.err_code = desc;
-       pc = iwl_legacy_read_targ_mem(priv, base + 2 * sizeof(u32));
-       blink1 = iwl_legacy_read_targ_mem(priv, base + 3 * sizeof(u32));
-       blink2 = iwl_legacy_read_targ_mem(priv, base + 4 * sizeof(u32));
-       ilink1 = iwl_legacy_read_targ_mem(priv, base + 5 * sizeof(u32));
-       ilink2 = iwl_legacy_read_targ_mem(priv, base + 6 * sizeof(u32));
-       data1 = iwl_legacy_read_targ_mem(priv, base + 7 * sizeof(u32));
-       data2 = iwl_legacy_read_targ_mem(priv, base + 8 * sizeof(u32));
-       line = iwl_legacy_read_targ_mem(priv, base + 9 * sizeof(u32));
-       time = iwl_legacy_read_targ_mem(priv, base + 11 * sizeof(u32));
-       hcmd = iwl_legacy_read_targ_mem(priv, base + 22 * sizeof(u32));
-
-       trace_iwlwifi_legacy_dev_ucode_error(priv, desc,
-                                       time, data1, data2, line,
-                                     blink1, blink2, ilink1, ilink2);
-
-       IWL_ERR(priv, "Desc                                  Time       "
-               "data1      data2      line\n");
-       IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
-               iwl4965_desc_lookup(desc), desc, time, data1, data2, line);
-       IWL_ERR(priv, "pc      blink1  blink2  ilink1  ilink2  hcmd\n");
-       IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n",
-               pc, blink1, blink2, ilink1, ilink2, hcmd);
-}
-
-static void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
-{
-       struct iwl_ct_kill_config cmd;
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-                   CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       cmd.critical_temperature_R =
-               cpu_to_le32(priv->hw_params.ct_kill_threshold);
-
-       ret = iwl_legacy_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-                              sizeof(cmd), &cmd);
-       if (ret)
-               IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
-       else
-               IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
-                               "succeeded, "
-                               "critical temperature is %d\n",
-                               priv->hw_params.ct_kill_threshold);
-}
-
-static const s8 default_queue_to_tx_fifo[] = {
-       IWL_TX_FIFO_VO,
-       IWL_TX_FIFO_VI,
-       IWL_TX_FIFO_BE,
-       IWL_TX_FIFO_BK,
-       IWL49_CMD_FIFO_NUM,
-       IWL_TX_FIFO_UNUSED,
-       IWL_TX_FIFO_UNUSED,
-};
-
-static int iwl4965_alive_notify(struct iwl_priv *priv)
-{
-       u32 a;
-       unsigned long flags;
-       int i, chan;
-       u32 reg_val;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       /* Clear 4965's internal Tx Scheduler data base */
-       priv->scd_base_addr = iwl_legacy_read_prph(priv,
-                                       IWL49_SCD_SRAM_BASE_ADDR);
-       a = priv->scd_base_addr + IWL49_SCD_CONTEXT_DATA_OFFSET;
-       for (; a < priv->scd_base_addr + IWL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4)
-               iwl_legacy_write_targ_mem(priv, a, 0);
-       for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
-               iwl_legacy_write_targ_mem(priv, a, 0);
-       for (; a < priv->scd_base_addr +
-              IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
-               iwl_legacy_write_targ_mem(priv, a, 0);
-
-       /* Tel 4965 where to find Tx byte count tables */
-       iwl_legacy_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
-                       priv->scd_bc_tbls.dma >> 10);
-
-       /* Enable DMA channel */
-       for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++)
-               iwl_legacy_write_direct32(priv,
-                               FH_TCSR_CHNL_TX_CONFIG_REG(chan),
-                               FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
-                               FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
-
-       /* Update FH chicken bits */
-       reg_val = iwl_legacy_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
-       iwl_legacy_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
-                          reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
-
-       /* Disable chain mode for all queues */
-       iwl_legacy_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
-
-       /* Initialize each Tx queue (including the command queue) */
-       for (i = 0; i < priv->hw_params.max_txq_num; i++) {
-
-               /* TFD circular buffer read/write indexes */
-               iwl_legacy_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0);
-               iwl_legacy_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
-
-               /* Max Tx Window size for Scheduler-ACK mode */
-               iwl_legacy_write_targ_mem(priv, priv->scd_base_addr +
-                               IWL49_SCD_CONTEXT_QUEUE_OFFSET(i),
-                               (SCD_WIN_SIZE <<
-                               IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
-                               IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
-
-               /* Frame limit */
-               iwl_legacy_write_targ_mem(priv, priv->scd_base_addr +
-                               IWL49_SCD_CONTEXT_QUEUE_OFFSET(i) +
-                               sizeof(u32),
-                               (SCD_FRAME_LIMIT <<
-                               IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
-                               IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
-
-       }
-       iwl_legacy_write_prph(priv, IWL49_SCD_INTERRUPT_MASK,
-                                (1 << priv->hw_params.max_txq_num) - 1);
-
-       /* Activate all Tx DMA/FIFO channels */
-       iwl4965_txq_set_sched(priv, IWL_MASK(0, 6));
-
-       iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0);
-
-       /* make sure all queue are not stopped */
-       memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
-       for (i = 0; i < 4; i++)
-               atomic_set(&priv->queue_stop_count[i], 0);
-
-       /* reset to 0 to enable all the queue first */
-       priv->txq_ctx_active_msk = 0;
-       /* Map each Tx/cmd queue to its corresponding fifo */
-       BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
-
-       for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
-               int ac = default_queue_to_tx_fifo[i];
-
-               iwl_txq_ctx_activate(priv, i);
-
-               if (ac == IWL_TX_FIFO_UNUSED)
-                       continue;
-
-               iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
-       }
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       return 0;
-}
-
-/**
- * iwl4965_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 iwl4965_alive_start(struct iwl_priv *priv)
-{
-       int ret = 0;
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-       IWL_DEBUG_INFO(priv, "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(priv, "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 (iwl4965_verify_ucode(priv)) {
-               /* Runtime instruction load was bad;
-                * take it all the way back down so we can try again */
-               IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
-               goto restart;
-       }
-
-       ret = iwl4965_alive_notify(priv);
-       if (ret) {
-               IWL_WARN(priv,
-                       "Could not complete ALIVE transition [ntf]: %d\n", ret);
-               goto restart;
-       }
-
-
-       /* After the ALIVE response, we can send host commands to the uCode */
-       set_bit(STATUS_ALIVE, &priv->status);
-
-       /* Enable watchdog to monitor the driver tx queues */
-       iwl_legacy_setup_watchdog(priv);
-
-       if (iwl_legacy_is_rfkill(priv))
-               return;
-
-       ieee80211_wake_queues(priv->hw);
-
-       priv->active_rate = IWL_RATES_MASK;
-
-       if (iwl_legacy_is_associated_ctx(ctx)) {
-               struct iwl_legacy_rxon_cmd *active_rxon =
-                               (struct iwl_legacy_rxon_cmd *)&ctx->active;
-               /* apply any changes in staging */
-               ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-               active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       } else {
-               struct iwl_rxon_context *tmp;
-               /* Initialize our rx_config data */
-               for_each_context(priv, tmp)
-                       iwl_legacy_connection_init_rx_config(priv, tmp);
-
-               if (priv->cfg->ops->hcmd->set_rxon_chain)
-                       priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-       }
-
-       /* Configure bluetooth coexistence if enabled */
-       iwl_legacy_send_bt_config(priv);
-
-       iwl4965_reset_run_time_calib(priv);
-
-       set_bit(STATUS_READY, &priv->status);
-
-       /* Configure the adapter for unassociated operation */
-       iwl_legacy_commit_rxon(priv, ctx);
-
-       /* At this point, the NIC is initialized and operational */
-       iwl4965_rf_kill_ct_config(priv);
-
-       IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
-       wake_up(&priv->wait_command_queue);
-
-       iwl_legacy_power_update_mode(priv, true);
-       IWL_DEBUG_INFO(priv, "Updated power mode\n");
-
-       return;
-
- restart:
-       queue_work(priv->workqueue, &priv->restart);
-}
-
-static void iwl4965_cancel_deferred_work(struct iwl_priv *priv);
-
-static void __iwl4965_down(struct iwl_priv *priv)
-{
-       unsigned long flags;
-       int exit_pending;
-
-       IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
-
-       iwl_legacy_scan_cancel_timeout(priv, 200);
-
-       exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-       /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
-        * to prevent rearm timer */
-       del_timer_sync(&priv->watchdog);
-
-       iwl_legacy_clear_ucode_stations(priv, NULL);
-       iwl_legacy_dealloc_bcast_stations(priv);
-       iwl_legacy_clear_driver_stations(priv);
-
-       /* Unblock any waiting calls */
-       wake_up_all(&priv->wait_command_queue);
-
-       /* 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 */
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_legacy_disable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       iwl4965_synchronize_irq(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 bit and return */
-       if (!iwl_legacy_is_init(priv)) {
-               priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
-                                       STATUS_RF_KILL_HW |
-                              test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
-                                       STATUS_GEO_CONFIGURED |
-                              test_bit(STATUS_EXIT_PENDING, &priv->status) <<
-                                       STATUS_EXIT_PENDING;
-               goto exit;
-       }
-
-       /* ...otherwise clear out all the status bits but the RF Kill
-        * bit and continue taking the NIC down. */
-       priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
-                               STATUS_RF_KILL_HW |
-                       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
-                               STATUS_GEO_CONFIGURED |
-                       test_bit(STATUS_FW_ERROR, &priv->status) <<
-                               STATUS_FW_ERROR |
-                      test_bit(STATUS_EXIT_PENDING, &priv->status) <<
-                               STATUS_EXIT_PENDING;
-
-       iwl4965_txq_ctx_stop(priv);
-       iwl4965_rxq_stop(priv);
-
-       /* Power-down device's busmaster DMA clocks */
-       iwl_legacy_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
-       udelay(5);
-
-       /* Make sure (redundant) we've released our request to stay awake */
-       iwl_legacy_clear_bit(priv, CSR_GP_CNTRL,
-                               CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
-       /* Stop the device, and put it in low power state */
-       iwl_legacy_apm_stop(priv);
-
- exit:
-       memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
-
-       dev_kfree_skb(priv->beacon_skb);
-       priv->beacon_skb = NULL;
-
-       /* clear out any free frames */
-       iwl4965_clear_free_frames(priv);
-}
-
-static void iwl4965_down(struct iwl_priv *priv)
-{
-       mutex_lock(&priv->mutex);
-       __iwl4965_down(priv);
-       mutex_unlock(&priv->mutex);
-
-       iwl4965_cancel_deferred_work(priv);
-}
-
-#define HW_READY_TIMEOUT (50)
-
-static int iwl4965_set_hw_ready(struct iwl_priv *priv)
-{
-       int ret = 0;
-
-       iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-               CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
-
-       /* See if we got it */
-       ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
-                               CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
-                               CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
-                               HW_READY_TIMEOUT);
-       if (ret != -ETIMEDOUT)
-               priv->hw_ready = true;
-       else
-               priv->hw_ready = false;
-
-       IWL_DEBUG_INFO(priv, "hardware %s\n",
-                     (priv->hw_ready == 1) ? "ready" : "not ready");
-       return ret;
-}
-
-static int iwl4965_prepare_card_hw(struct iwl_priv *priv)
-{
-       int ret = 0;
-
-       IWL_DEBUG_INFO(priv, "iwl4965_prepare_card_hw enter\n");
-
-       ret = iwl4965_set_hw_ready(priv);
-       if (priv->hw_ready)
-               return ret;
-
-       /* If HW is not ready, prepare the conditions to check again */
-       iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                       CSR_HW_IF_CONFIG_REG_PREPARE);
-
-       ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
-                       ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
-                       CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
-
-       /* HW should be ready by now, check again. */
-       if (ret != -ETIMEDOUT)
-               iwl4965_set_hw_ready(priv);
-
-       return ret;
-}
-
-#define MAX_HW_RESTARTS 5
-
-static int __iwl4965_up(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx;
-       int i;
-       int ret;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-               IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
-               return -EIO;
-       }
-
-       if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
-               IWL_ERR(priv, "ucode not available for device bringup\n");
-               return -EIO;
-       }
-
-       for_each_context(priv, ctx) {
-               ret = iwl4965_alloc_bcast_station(priv, ctx);
-               if (ret) {
-                       iwl_legacy_dealloc_bcast_stations(priv);
-                       return ret;
-               }
-       }
-
-       iwl4965_prepare_card_hw(priv);
-
-       if (!priv->hw_ready) {
-               IWL_WARN(priv, "Exit HW not ready\n");
-               return -EIO;
-       }
-
-       /* If platform's RF_KILL switch is NOT set to KILL */
-       if (iwl_read32(priv,
-               CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-               clear_bit(STATUS_RF_KILL_HW, &priv->status);
-       else
-               set_bit(STATUS_RF_KILL_HW, &priv->status);
-
-       if (iwl_legacy_is_rfkill(priv)) {
-               wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
-
-               iwl_legacy_enable_interrupts(priv);
-               IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
-               return 0;
-       }
-
-       iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-
-       /* must be initialised before iwl_hw_nic_init */
-       priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
-
-       ret = iwl4965_hw_nic_init(priv);
-       if (ret) {
-               IWL_ERR(priv, "Unable to init nic\n");
-               return ret;
-       }
-
-       /* 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_legacy_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++) {
-
-               /* load bootstrap state machine,
-                * load bootstrap program into processor's memory,
-                * prepare to load the "initialize" uCode */
-               ret = priv->cfg->ops->lib->load_ucode(priv);
-
-               if (ret) {
-                       IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n",
-                               ret);
-                       continue;
-               }
-
-               /* start card; "initialize" will load runtime ucode */
-               iwl4965_nic_start(priv);
-
-               IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
-
-               return 0;
-       }
-
-       set_bit(STATUS_EXIT_PENDING, &priv->status);
-       __iwl4965_down(priv);
-       clear_bit(STATUS_EXIT_PENDING, &priv->status);
-
-       /* tried to restart and config the device for as long as our
-        * patience could withstand */
-       IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
-       return -EIO;
-}
-
-
-/*****************************************************************************
- *
- * Workqueue callbacks
- *
- *****************************************************************************/
-
-static void iwl4965_bg_init_alive_start(struct work_struct *data)
-{
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, init_alive_start.work);
-
-       mutex_lock(&priv->mutex);
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               goto out;
-
-       priv->cfg->ops->lib->init_alive_start(priv);
-out:
-       mutex_unlock(&priv->mutex);
-}
-
-static void iwl4965_bg_alive_start(struct work_struct *data)
-{
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, alive_start.work);
-
-       mutex_lock(&priv->mutex);
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               goto out;
-
-       iwl4965_alive_start(priv);
-out:
-       mutex_unlock(&priv->mutex);
-}
-
-static void iwl4965_bg_run_time_calib_work(struct work_struct *work)
-{
-       struct iwl_priv *priv = container_of(work, struct iwl_priv,
-                       run_time_calib_work);
-
-       mutex_lock(&priv->mutex);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
-           test_bit(STATUS_SCANNING, &priv->status)) {
-               mutex_unlock(&priv->mutex);
-               return;
-       }
-
-       if (priv->start_calib) {
-               iwl4965_chain_noise_calibration(priv,
-                               (void *)&priv->_4965.statistics);
-               iwl4965_sensitivity_calibration(priv,
-                               (void *)&priv->_4965.statistics);
-       }
-
-       mutex_unlock(&priv->mutex);
-}
-
-static void iwl4965_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;
-
-       if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
-               struct iwl_rxon_context *ctx;
-
-               mutex_lock(&priv->mutex);
-               for_each_context(priv, ctx)
-                       ctx->vif = NULL;
-               priv->is_open = 0;
-
-               __iwl4965_down(priv);
-
-               mutex_unlock(&priv->mutex);
-               iwl4965_cancel_deferred_work(priv);
-               ieee80211_restart_hw(priv->hw);
-       } else {
-               iwl4965_down(priv);
-
-               mutex_lock(&priv->mutex);
-               if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-                       mutex_unlock(&priv->mutex);
-                       return;
-               }
-
-               __iwl4965_up(priv);
-               mutex_unlock(&priv->mutex);
-       }
-}
-
-static void iwl4965_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);
-       iwl4965_rx_replenish(priv);
-       mutex_unlock(&priv->mutex);
-}
-
-/*****************************************************************************
- *
- * mac80211 entry point functions
- *
- *****************************************************************************/
-
-#define UCODE_READY_TIMEOUT    (4 * HZ)
-
-/*
- * Not a mac80211 entry point function, but it fits in with all the
- * other mac80211 functions grouped here.
- */
-static int iwl4965_mac_setup_register(struct iwl_priv *priv,
-                                 u32 max_probe_length)
-{
-       int ret;
-       struct ieee80211_hw *hw = priv->hw;
-       struct iwl_rxon_context *ctx;
-
-       hw->rate_control_algorithm = "iwl-4965-rs";
-
-       /* Tell mac80211 our characteristics */
-       hw->flags = IEEE80211_HW_SIGNAL_DBM |
-                   IEEE80211_HW_AMPDU_AGGREGATION |
-                   IEEE80211_HW_NEED_DTIM_PERIOD |
-                   IEEE80211_HW_SPECTRUM_MGMT |
-                   IEEE80211_HW_REPORTS_TX_ACK_STATUS;
-
-       if (priv->cfg->sku & IWL_SKU_N)
-               hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
-                            IEEE80211_HW_SUPPORTS_STATIC_SMPS;
-
-       hw->sta_data_size = sizeof(struct iwl_station_priv);
-       hw->vif_data_size = sizeof(struct iwl_vif_priv);
-
-       for_each_context(priv, ctx) {
-               hw->wiphy->interface_modes |= ctx->interface_modes;
-               hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
-       }
-
-       hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
-                           WIPHY_FLAG_DISABLE_BEACON_HINTS;
-
-       /*
-        * For now, disable PS by default because it affects
-        * RX performance significantly.
-        */
-       hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-
-       hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
-       /* we create the 802.11 header and a zero-length SSID element */
-       hw->wiphy->max_scan_ie_len = max_probe_length - 24 - 2;
-
-       /* Default value; 4 EDCA QOS priorities */
-       hw->queues = 4;
-
-       hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
-
-       if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
-               priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-                       &priv->bands[IEEE80211_BAND_2GHZ];
-       if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
-               priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-                       &priv->bands[IEEE80211_BAND_5GHZ];
-
-       iwl_legacy_leds_init(priv);
-
-       ret = ieee80211_register_hw(priv->hw);
-       if (ret) {
-               IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
-               return ret;
-       }
-       priv->mac80211_registered = 1;
-
-       return 0;
-}
-
-
-int iwl4965_mac_start(struct ieee80211_hw *hw)
-{
-       struct iwl_priv *priv = hw->priv;
-       int ret;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       /* we should be verifying the device is ready to be opened */
-       mutex_lock(&priv->mutex);
-       ret = __iwl4965_up(priv);
-       mutex_unlock(&priv->mutex);
-
-       if (ret)
-               return ret;
-
-       if (iwl_legacy_is_rfkill(priv))
-               goto out;
-
-       IWL_DEBUG_INFO(priv, "Start UP work done.\n");
-
-       /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
-        * mac80211 will not be run successfully. */
-       ret = wait_event_timeout(priv->wait_command_queue,
-                       test_bit(STATUS_READY, &priv->status),
-                       UCODE_READY_TIMEOUT);
-       if (!ret) {
-               if (!test_bit(STATUS_READY, &priv->status)) {
-                       IWL_ERR(priv, "START_ALIVE timeout after %dms.\n",
-                               jiffies_to_msecs(UCODE_READY_TIMEOUT));
-                       return -ETIMEDOUT;
-               }
-       }
-
-       iwl4965_led_enable(priv);
-
-out:
-       priv->is_open = 1;
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       return 0;
-}
-
-void iwl4965_mac_stop(struct ieee80211_hw *hw)
-{
-       struct iwl_priv *priv = hw->priv;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (!priv->is_open)
-               return;
-
-       priv->is_open = 0;
-
-       iwl4965_down(priv);
-
-       flush_workqueue(priv->workqueue);
-
-       /* User space software may expect getting rfkill changes
-        * even if interface is down */
-       iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-       iwl_legacy_enable_rfkill_int(priv);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-void iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct iwl_priv *priv = hw->priv;
-
-       IWL_DEBUG_MACDUMP(priv, "enter\n");
-
-       IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-                    ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
-
-       if (iwl4965_tx_skb(priv, skb))
-               dev_kfree_skb_any(skb);
-
-       IWL_DEBUG_MACDUMP(priv, "leave\n");
-}
-
-void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif,
-                               struct ieee80211_key_conf *keyconf,
-                               struct ieee80211_sta *sta,
-                               u32 iv32, u16 *phase1key)
-{
-       struct iwl_priv *priv = hw->priv;
-       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       iwl4965_update_tkip_key(priv, vif_priv->ctx, keyconf, sta,
-                           iv32, phase1key);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-                      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-                      struct ieee80211_key_conf *key)
-{
-       struct iwl_priv *priv = hw->priv;
-       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-       struct iwl_rxon_context *ctx = vif_priv->ctx;
-       int ret;
-       u8 sta_id;
-       bool is_default_wep_key = false;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (priv->cfg->mod_params->sw_crypto) {
-               IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
-               return -EOPNOTSUPP;
-       }
-
-       sta_id = iwl_legacy_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
-       if (sta_id == IWL_INVALID_STATION)
-               return -EINVAL;
-
-       mutex_lock(&priv->mutex);
-       iwl_legacy_scan_cancel_timeout(priv, 100);
-
-       /*
-        * If we are getting WEP group key and we didn't receive any key mapping
-        * so far, we are in legacy wep mode (group key only), otherwise we are
-        * in 1X mode.
-        * In legacy wep mode, we use another host command to the uCode.
-        */
-       if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-            key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
-           !sta) {
-               if (cmd == SET_KEY)
-                       is_default_wep_key = !ctx->key_mapping_keys;
-               else
-                       is_default_wep_key =
-                                       (key->hw_key_idx == HW_KEY_DEFAULT);
-       }
-
-       switch (cmd) {
-       case SET_KEY:
-               if (is_default_wep_key)
-                       ret = iwl4965_set_default_wep_key(priv,
-                                                       vif_priv->ctx, key);
-               else
-                       ret = iwl4965_set_dynamic_key(priv, vif_priv->ctx,
-                                                 key, sta_id);
-
-               IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
-               break;
-       case DISABLE_KEY:
-               if (is_default_wep_key)
-                       ret = iwl4965_remove_default_wep_key(priv, ctx, key);
-               else
-                       ret = iwl4965_remove_dynamic_key(priv, ctx,
-                                                       key, sta_id);
-
-               IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-       mutex_unlock(&priv->mutex);
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-       return ret;
-}
-
-int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
-                           struct ieee80211_vif *vif,
-                           enum ieee80211_ampdu_mlme_action action,
-                           struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                           u8 buf_size)
-{
-       struct iwl_priv *priv = hw->priv;
-       int ret = -EINVAL;
-
-       IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
-                    sta->addr, tid);
-
-       if (!(priv->cfg->sku & IWL_SKU_N))
-               return -EACCES;
-
-       mutex_lock(&priv->mutex);
-
-       switch (action) {
-       case IEEE80211_AMPDU_RX_START:
-               IWL_DEBUG_HT(priv, "start Rx\n");
-               ret = iwl4965_sta_rx_agg_start(priv, sta, tid, *ssn);
-               break;
-       case IEEE80211_AMPDU_RX_STOP:
-               IWL_DEBUG_HT(priv, "stop Rx\n");
-               ret = iwl4965_sta_rx_agg_stop(priv, sta, tid);
-               if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-                       ret = 0;
-               break;
-       case IEEE80211_AMPDU_TX_START:
-               IWL_DEBUG_HT(priv, "start Tx\n");
-               ret = iwl4965_tx_agg_start(priv, vif, sta, tid, ssn);
-               break;
-       case IEEE80211_AMPDU_TX_STOP:
-               IWL_DEBUG_HT(priv, "stop Tx\n");
-               ret = iwl4965_tx_agg_stop(priv, vif, sta, tid);
-               if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-                       ret = 0;
-               break;
-       case IEEE80211_AMPDU_TX_OPERATIONAL:
-               ret = 0;
-               break;
-       }
-       mutex_unlock(&priv->mutex);
-
-       return ret;
-}
-
-int iwl4965_mac_sta_add(struct ieee80211_hw *hw,
-                      struct ieee80211_vif *vif,
-                      struct ieee80211_sta *sta)
-{
-       struct iwl_priv *priv = hw->priv;
-       struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-       bool is_ap = vif->type == NL80211_IFTYPE_STATION;
-       int ret;
-       u8 sta_id;
-
-       IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
-                       sta->addr);
-       mutex_lock(&priv->mutex);
-       IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
-                       sta->addr);
-       sta_priv->common.sta_id = IWL_INVALID_STATION;
-
-       atomic_set(&sta_priv->pending_frames, 0);
-
-       ret = iwl_legacy_add_station_common(priv, vif_priv->ctx, sta->addr,
-                                    is_ap, sta, &sta_id);
-       if (ret) {
-               IWL_ERR(priv, "Unable to add station %pM (%d)\n",
-                       sta->addr, ret);
-               /* Should we return success if return code is EEXIST ? */
-               mutex_unlock(&priv->mutex);
-               return ret;
-       }
-
-       sta_priv->common.sta_id = sta_id;
-
-       /* Initialize rate scaling */
-       IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
-                      sta->addr);
-       iwl4965_rs_rate_init(priv, sta, sta_id);
-       mutex_unlock(&priv->mutex);
-
-       return 0;
-}
-
-void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
-                              struct ieee80211_channel_switch *ch_switch)
-{
-       struct iwl_priv *priv = hw->priv;
-       const struct iwl_channel_info *ch_info;
-       struct ieee80211_conf *conf = &hw->conf;
-       struct ieee80211_channel *channel = ch_switch->channel;
-       struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       u16 ch;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       mutex_lock(&priv->mutex);
-
-       if (iwl_legacy_is_rfkill(priv))
-               goto out;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
-           test_bit(STATUS_SCANNING, &priv->status) ||
-           test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
-               goto out;
-
-       if (!iwl_legacy_is_associated_ctx(ctx))
-               goto out;
-
-       if (!priv->cfg->ops->lib->set_channel_switch)
-               goto out;
-
-       ch = channel->hw_value;
-       if (le16_to_cpu(ctx->active.channel) == ch)
-               goto out;
-
-       ch_info = iwl_legacy_get_channel_info(priv, channel->band, ch);
-       if (!iwl_legacy_is_channel_valid(ch_info)) {
-               IWL_DEBUG_MAC80211(priv, "invalid channel\n");
-               goto out;
-       }
-
-       spin_lock_irq(&priv->lock);
-
-       priv->current_ht_config.smps = conf->smps_mode;
-
-       /* Configure HT40 channels */
-       ctx->ht.enabled = conf_is_ht(conf);
-       if (ctx->ht.enabled) {
-               if (conf_is_ht40_minus(conf)) {
-                       ctx->ht.extension_chan_offset =
-                               IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-                       ctx->ht.is_40mhz = true;
-               } else if (conf_is_ht40_plus(conf)) {
-                       ctx->ht.extension_chan_offset =
-                               IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-                       ctx->ht.is_40mhz = true;
-               } else {
-                       ctx->ht.extension_chan_offset =
-                               IEEE80211_HT_PARAM_CHA_SEC_NONE;
-                       ctx->ht.is_40mhz = false;
-               }
-       } else
-               ctx->ht.is_40mhz = false;
-
-       if ((le16_to_cpu(ctx->staging.channel) != ch))
-               ctx->staging.flags = 0;
-
-       iwl_legacy_set_rxon_channel(priv, channel, ctx);
-       iwl_legacy_set_rxon_ht(priv, ht_conf);
-       iwl_legacy_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
-
-       spin_unlock_irq(&priv->lock);
-
-       iwl_legacy_set_rate(priv);
-       /*
-        * at this point, staging_rxon has the
-        * configuration for channel switch
-        */
-       set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
-       priv->switch_channel = cpu_to_le16(ch);
-       if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
-               clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
-               priv->switch_channel = 0;
-               ieee80211_chswitch_done(ctx->vif, false);
-       }
-
-out:
-       mutex_unlock(&priv->mutex);
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-void iwl4965_configure_filter(struct ieee80211_hw *hw,
-                            unsigned int changed_flags,
-                            unsigned int *total_flags,
-                            u64 multicast)
-{
-       struct iwl_priv *priv = hw->priv;
-       __le32 filter_or = 0, filter_nand = 0;
-       struct iwl_rxon_context *ctx;
-
-#define CHK(test, flag)        do { \
-       if (*total_flags & (test))              \
-               filter_or |= (flag);            \
-       else                                    \
-               filter_nand |= (flag);          \
-       } while (0)
-
-       IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
-                       changed_flags, *total_flags);
-
-       CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
-       /* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */
-       CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
-       CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
-
-#undef CHK
-
-       mutex_lock(&priv->mutex);
-
-       for_each_context(priv, ctx) {
-               ctx->staging.filter_flags &= ~filter_nand;
-               ctx->staging.filter_flags |= filter_or;
-
-               /*
-                * Not committing directly because hardware can perform a scan,
-                * but we'll eventually commit the filter flags change anyway.
-                */
-       }
-
-       mutex_unlock(&priv->mutex);
-
-       /*
-        * Receiving all multicast frames is always enabled by the
-        * default flags setup in iwl_legacy_connection_init_rx_config()
-        * since we currently do not support programming multicast
-        * filters into the device.
-        */
-       *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
-                       FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
-}
-
-/*****************************************************************************
- *
- * driver setup and teardown
- *
- *****************************************************************************/
-
-static void iwl4965_bg_txpower_work(struct work_struct *work)
-{
-       struct iwl_priv *priv = container_of(work, struct iwl_priv,
-                       txpower_work);
-
-       mutex_lock(&priv->mutex);
-
-       /* If a scan happened to start before we got here
-        * then just return; the statistics notification will
-        * kick off another scheduled work to compensate for
-        * any temperature delta we missed here. */
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
-           test_bit(STATUS_SCANNING, &priv->status))
-               goto out;
-
-       /* Regardless of if we are associated, we must reconfigure the
-        * TX power since frames can be sent on non-radar channels while
-        * not associated */
-       priv->cfg->ops->lib->send_tx_power(priv);
-
-       /* Update last_temperature to keep is_calib_needed from running
-        * when it isn't needed... */
-       priv->last_temperature = priv->temperature;
-out:
-       mutex_unlock(&priv->mutex);
-}
-
-static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
-{
-       priv->workqueue = create_singlethread_workqueue(DRV_NAME);
-
-       init_waitqueue_head(&priv->wait_command_queue);
-
-       INIT_WORK(&priv->restart, iwl4965_bg_restart);
-       INIT_WORK(&priv->rx_replenish, iwl4965_bg_rx_replenish);
-       INIT_WORK(&priv->run_time_calib_work, iwl4965_bg_run_time_calib_work);
-       INIT_DELAYED_WORK(&priv->init_alive_start, iwl4965_bg_init_alive_start);
-       INIT_DELAYED_WORK(&priv->alive_start, iwl4965_bg_alive_start);
-
-       iwl_legacy_setup_scan_deferred_work(priv);
-
-       INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work);
-
-       init_timer(&priv->statistics_periodic);
-       priv->statistics_periodic.data = (unsigned long)priv;
-       priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
-
-       init_timer(&priv->watchdog);
-       priv->watchdog.data = (unsigned long)priv;
-       priv->watchdog.function = iwl_legacy_bg_watchdog;
-
-       tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-               iwl4965_irq_tasklet, (unsigned long)priv);
-}
-
-static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
-{
-       cancel_work_sync(&priv->txpower_work);
-       cancel_delayed_work_sync(&priv->init_alive_start);
-       cancel_delayed_work(&priv->alive_start);
-       cancel_work_sync(&priv->run_time_calib_work);
-
-       iwl_legacy_cancel_scan_deferred_work(priv);
-
-       del_timer_sync(&priv->statistics_periodic);
-}
-
-static void iwl4965_init_hw_rates(struct iwl_priv *priv,
-                             struct ieee80211_rate *rates)
-{
-       int i;
-
-       for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
-               rates[i].bitrate = iwlegacy_rates[i].ieee * 5;
-               rates[i].hw_value = i; /* Rate scaling will work on indexes */
-               rates[i].hw_value_short = i;
-               rates[i].flags = 0;
-               if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) {
-                       /*
-                        * If CCK != 1M then set short preamble rate flag.
-                        */
-                       rates[i].flags |=
-                               (iwlegacy_rates[i].plcp == IWL_RATE_1M_PLCP) ?
-                                       0 : IEEE80211_RATE_SHORT_PREAMBLE;
-               }
-       }
-}
-/*
- * Acquire priv->lock before calling this function !
- */
-void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index)
-{
-       iwl_legacy_write_direct32(priv, HBUS_TARG_WRPTR,
-                            (index & 0xff) | (txq_id << 8));
-       iwl_legacy_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index);
-}
-
-void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
-                                       struct iwl_tx_queue *txq,
-                                       int tx_fifo_id, int scd_retry)
-{
-       int txq_id = txq->q.id;
-
-       /* Find out whether to activate Tx queue */
-       int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
-
-       /* Set up and activate */
-       iwl_legacy_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
-                        (active << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
-                        (tx_fifo_id << IWL49_SCD_QUEUE_STTS_REG_POS_TXF) |
-                        (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_WSL) |
-                        (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) |
-                        IWL49_SCD_QUEUE_STTS_REG_MSK);
-
-       txq->sched_retry = scd_retry;
-
-       IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n",
-                      active ? "Activate" : "Deactivate",
-                      scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
-}
-
-
-static int iwl4965_init_drv(struct iwl_priv *priv)
-{
-       int ret;
-
-       spin_lock_init(&priv->sta_lock);
-       spin_lock_init(&priv->hcmd_lock);
-
-       INIT_LIST_HEAD(&priv->free_frames);
-
-       mutex_init(&priv->mutex);
-
-       priv->ieee_channels = NULL;
-       priv->ieee_rates = NULL;
-       priv->band = IEEE80211_BAND_2GHZ;
-
-       priv->iw_mode = NL80211_IFTYPE_STATION;
-       priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
-       priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
-
-       /* initialize force reset */
-       priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
-
-       /* Choose which receivers/antennas to use */
-       if (priv->cfg->ops->hcmd->set_rxon_chain)
-               priv->cfg->ops->hcmd->set_rxon_chain(priv,
-                                       &priv->contexts[IWL_RXON_CTX_BSS]);
-
-       iwl_legacy_init_scan_params(priv);
-
-       ret = iwl_legacy_init_channel_map(priv);
-       if (ret) {
-               IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
-               goto err;
-       }
-
-       ret = iwl_legacy_init_geos(priv);
-       if (ret) {
-               IWL_ERR(priv, "initializing geos failed: %d\n", ret);
-               goto err_free_channel_map;
-       }
-       iwl4965_init_hw_rates(priv, priv->ieee_rates);
-
-       return 0;
-
-err_free_channel_map:
-       iwl_legacy_free_channel_map(priv);
-err:
-       return ret;
-}
-
-static void iwl4965_uninit_drv(struct iwl_priv *priv)
-{
-       iwl4965_calib_free_results(priv);
-       iwl_legacy_free_geos(priv);
-       iwl_legacy_free_channel_map(priv);
-       kfree(priv->scan_cmd);
-}
-
-static void iwl4965_hw_detect(struct iwl_priv *priv)
-{
-       priv->hw_rev = _iwl_legacy_read32(priv, CSR_HW_REV);
-       priv->hw_wa_rev = _iwl_legacy_read32(priv, CSR_HW_REV_WA_REG);
-       priv->rev_id = priv->pci_dev->revision;
-       IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
-}
-
-static int iwl4965_set_hw_params(struct iwl_priv *priv)
-{
-       priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
-       priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
-       if (priv->cfg->mod_params->amsdu_size_8K)
-               priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
-       else
-               priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
-
-       priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
-
-       if (priv->cfg->mod_params->disable_11n)
-               priv->cfg->sku &= ~IWL_SKU_N;
-
-       /* Device-specific setup */
-       return priv->cfg->ops->lib->set_hw_params(priv);
-}
-
-static const u8 iwl4965_bss_ac_to_fifo[] = {
-       IWL_TX_FIFO_VO,
-       IWL_TX_FIFO_VI,
-       IWL_TX_FIFO_BE,
-       IWL_TX_FIFO_BK,
-};
-
-static const u8 iwl4965_bss_ac_to_queue[] = {
-       0, 1, 2, 3,
-};
-
-static int
-iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       int err = 0, i;
-       struct iwl_priv *priv;
-       struct ieee80211_hw *hw;
-       struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
-       unsigned long flags;
-       u16 pci_cmd;
-
-       /************************
-        * 1. Allocating HW data
-        ************************/
-
-       hw = iwl_legacy_alloc_all(cfg);
-       if (!hw) {
-               err = -ENOMEM;
-               goto out;
-       }
-       priv = hw->priv;
-       /* At this point both hw and priv are allocated. */
-
-       /*
-        * The default context is always valid,
-        * more may be discovered when firmware
-        * is loaded.
-        */
-       priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
-
-       for (i = 0; i < NUM_IWL_RXON_CTX; i++)
-               priv->contexts[i].ctxid = i;
-
-       priv->contexts[IWL_RXON_CTX_BSS].always_active = true;
-       priv->contexts[IWL_RXON_CTX_BSS].is_active = true;
-       priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
-       priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
-       priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
-       priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
-       priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
-       priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
-       priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwl4965_bss_ac_to_fifo;
-       priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwl4965_bss_ac_to_queue;
-       priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
-               BIT(NL80211_IFTYPE_ADHOC);
-       priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
-               BIT(NL80211_IFTYPE_STATION);
-       priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
-       priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
-       priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
-       priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
-
-       BUILD_BUG_ON(NUM_IWL_RXON_CTX != 1);
-
-       SET_IEEE80211_DEV(hw, &pdev->dev);
-
-       IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
-       priv->cfg = cfg;
-       priv->pci_dev = pdev;
-       priv->inta_mask = CSR_INI_SET_MASK;
-
-       if (iwl_legacy_alloc_traffic_mem(priv))
-               IWL_ERR(priv, "Not enough memory to generate traffic log\n");
-
-       /**************************
-        * 2. Initializing PCI bus
-        **************************/
-       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-                               PCIE_LINK_STATE_CLKPM);
-
-       if (pci_enable_device(pdev)) {
-               err = -ENODEV;
-               goto out_ieee80211_free_hw;
-       }
-
-       pci_set_master(pdev);
-
-       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
-       if (!err)
-               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
-       if (err) {
-               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-               if (!err)
-                       err = pci_set_consistent_dma_mask(pdev,
-                                                       DMA_BIT_MASK(32));
-               /* both attempts failed: */
-               if (err) {
-                       IWL_WARN(priv, "No suitable DMA available.\n");
-                       goto out_pci_disable_device;
-               }
-       }
-
-       err = pci_request_regions(pdev, DRV_NAME);
-       if (err)
-               goto out_pci_disable_device;
-
-       pci_set_drvdata(pdev, priv);
-
-
-       /***********************
-        * 3. Read REV register
-        ***********************/
-       priv->hw_base = pci_iomap(pdev, 0, 0);
-       if (!priv->hw_base) {
-               err = -ENODEV;
-               goto out_pci_release_regions;
-       }
-
-       IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
-               (unsigned long long) pci_resource_len(pdev, 0));
-       IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
-
-       /* these spin locks will be used in apm_ops.init and EEPROM access
-        * we should init now
-        */
-       spin_lock_init(&priv->reg_lock);
-       spin_lock_init(&priv->lock);
-
-       /*
-        * stop and reset the on-board processor just in case it is in a
-        * strange state ... like being left stranded by a primary kernel
-        * and this is now the kdump kernel trying to start up
-        */
-       iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-       iwl4965_hw_detect(priv);
-       IWL_INFO(priv, "Detected %s, REV=0x%X\n",
-               priv->cfg->name, priv->hw_rev);
-
-       /* We disable the RETRY_TIMEOUT register (0x41) to keep
-        * PCI Tx retries from interfering with C3 CPU state */
-       pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
-
-       iwl4965_prepare_card_hw(priv);
-       if (!priv->hw_ready) {
-               IWL_WARN(priv, "Failed, HW not ready\n");
-               goto out_iounmap;
-       }
-
-       /*****************
-        * 4. Read EEPROM
-        *****************/
-       /* Read the EEPROM */
-       err = iwl_legacy_eeprom_init(priv);
-       if (err) {
-               IWL_ERR(priv, "Unable to init EEPROM\n");
-               goto out_iounmap;
-       }
-       err = iwl4965_eeprom_check_version(priv);
-       if (err)
-               goto out_free_eeprom;
-
-       if (err)
-               goto out_free_eeprom;
-
-       /* extract MAC Address */
-       iwl4965_eeprom_get_mac(priv, priv->addresses[0].addr);
-       IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
-       priv->hw->wiphy->addresses = priv->addresses;
-       priv->hw->wiphy->n_addresses = 1;
-
-       /************************
-        * 5. Setup HW constants
-        ************************/
-       if (iwl4965_set_hw_params(priv)) {
-               IWL_ERR(priv, "failed to set hw parameters\n");
-               goto out_free_eeprom;
-       }
-
-       /*******************
-        * 6. Setup priv
-        *******************/
-
-       err = iwl4965_init_drv(priv);
-       if (err)
-               goto out_free_eeprom;
-       /* At this point both hw and priv are initialized. */
-
-       /********************
-        * 7. Setup services
-        ********************/
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_legacy_disable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       pci_enable_msi(priv->pci_dev);
-
-       err = request_irq(priv->pci_dev->irq, iwl_legacy_isr,
-                         IRQF_SHARED, DRV_NAME, priv);
-       if (err) {
-               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
-               goto out_disable_msi;
-       }
-
-       iwl4965_setup_deferred_work(priv);
-       iwl4965_setup_rx_handlers(priv);
-
-       /*********************************************
-        * 8. Enable interrupts and read RFKILL state
-        *********************************************/
-
-       /* enable rfkill interrupt: hw bug w/a */
-       pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
-       if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
-               pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
-               pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
-       }
-
-       iwl_legacy_enable_rfkill_int(priv);
-
-       /* If platform's RF_KILL switch is NOT set to KILL */
-       if (iwl_read32(priv, CSR_GP_CNTRL) &
-               CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-               clear_bit(STATUS_RF_KILL_HW, &priv->status);
-       else
-               set_bit(STATUS_RF_KILL_HW, &priv->status);
-
-       wiphy_rfkill_set_hw_state(priv->hw->wiphy,
-               test_bit(STATUS_RF_KILL_HW, &priv->status));
-
-       iwl_legacy_power_initialize(priv);
-
-       init_completion(&priv->_4965.firmware_loading_complete);
-
-       err = iwl4965_request_firmware(priv, true);
-       if (err)
-               goto out_destroy_workqueue;
-
-       return 0;
-
- out_destroy_workqueue:
-       destroy_workqueue(priv->workqueue);
-       priv->workqueue = NULL;
-       free_irq(priv->pci_dev->irq, priv);
- out_disable_msi:
-       pci_disable_msi(priv->pci_dev);
-       iwl4965_uninit_drv(priv);
- out_free_eeprom:
-       iwl_legacy_eeprom_free(priv);
- out_iounmap:
-       pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
-       pci_set_drvdata(pdev, NULL);
-       pci_release_regions(pdev);
- out_pci_disable_device:
-       pci_disable_device(pdev);
- out_ieee80211_free_hw:
-       iwl_legacy_free_traffic_mem(priv);
-       ieee80211_free_hw(priv->hw);
- out:
-       return err;
-}
-
-static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
-{
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-       unsigned long flags;
-
-       if (!priv)
-               return;
-
-       wait_for_completion(&priv->_4965.firmware_loading_complete);
-
-       IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
-
-       iwl_legacy_dbgfs_unregister(priv);
-       sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
-
-       /* ieee80211_unregister_hw call wil cause iwl_mac_stop to
-        * to be called and iwl4965_down since we are removing the device
-        * we need to set STATUS_EXIT_PENDING bit.
-        */
-       set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-       iwl_legacy_leds_exit(priv);
-
-       if (priv->mac80211_registered) {
-               ieee80211_unregister_hw(priv->hw);
-               priv->mac80211_registered = 0;
-       } else {
-               iwl4965_down(priv);
-       }
-
-       /*
-        * Make sure device is reset to low power before unloading driver.
-        * This may be redundant with iwl4965_down(), but there are paths to
-        * run iwl4965_down() without calling apm_ops.stop(), and there are
-        * paths to avoid running iwl4965_down() at all before leaving driver.
-        * This (inexpensive) call *makes sure* device is reset.
-        */
-       iwl_legacy_apm_stop(priv);
-
-       /* make sure we flush any pending irq or
-        * tasklet for the driver
-        */
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_legacy_disable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       iwl4965_synchronize_irq(priv);
-
-       iwl4965_dealloc_ucode_pci(priv);
-
-       if (priv->rxq.bd)
-               iwl4965_rx_queue_free(priv, &priv->rxq);
-       iwl4965_hw_txq_ctx_free(priv);
-
-       iwl_legacy_eeprom_free(priv);
-
-
-       /*netif_stop_queue(dev); */
-       flush_workqueue(priv->workqueue);
-
-       /* 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;
-       iwl_legacy_free_traffic_mem(priv);
-
-       free_irq(priv->pci_dev->irq, priv);
-       pci_disable_msi(priv->pci_dev);
-       pci_iounmap(pdev, priv->hw_base);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
-
-       iwl4965_uninit_drv(priv);
-
-       dev_kfree_skb(priv->beacon_skb);
-
-       ieee80211_free_hw(priv->hw);
-}
-
-/*
- * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- * must be called under priv->lock and mac access
- */
-void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
-{
-       iwl_legacy_write_prph(priv, IWL49_SCD_TXFACT, mask);
-}
-
-/*****************************************************************************
- *
- * driver and module entry point
- *
- *****************************************************************************/
-
-/* Hardware specific file defines the PCI IDs table for that hardware module */
-static DEFINE_PCI_DEVICE_TABLE(iwl4965_hw_card_ids) = {
-#if defined(CONFIG_IWL4965_MODULE) || defined(CONFIG_IWL4965)
-       {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_cfg)},
-       {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_cfg)},
-#endif /* CONFIG_IWL4965 */
-
-       {0}
-};
-MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids);
-
-static struct pci_driver iwl4965_driver = {
-       .name = DRV_NAME,
-       .id_table = iwl4965_hw_card_ids,
-       .probe = iwl4965_pci_probe,
-       .remove = __devexit_p(iwl4965_pci_remove),
-       .driver.pm = IWL_LEGACY_PM_OPS,
-};
-
-static int __init iwl4965_init(void)
-{
-
-       int ret;
-       pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
-       pr_info(DRV_COPYRIGHT "\n");
-
-       ret = iwl4965_rate_control_register();
-       if (ret) {
-               pr_err("Unable to register rate control algorithm: %d\n", ret);
-               return ret;
-       }
-
-       ret = pci_register_driver(&iwl4965_driver);
-       if (ret) {
-               pr_err("Unable to initialize PCI module\n");
-               goto error_register;
-       }
-
-       return ret;
-
-error_register:
-       iwl4965_rate_control_unregister();
-       return ret;
-}
-
-static void __exit iwl4965_exit(void)
-{
-       pci_unregister_driver(&iwl4965_driver);
-       iwl4965_rate_control_unregister();
-}
-
-module_exit(iwl4965_exit);
-module_init(iwl4965_init);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-module_param_named(debug, iwlegacy_debug_level, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "debug output mask");
-#endif
-
-module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO);
-MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
-module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO);
-MODULE_PARM_DESC(queues_num, "number of hw queues.");
-module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO);
-MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
-module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K,
-                  int, S_IRUGO);
-MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
-module_param_named(fw_restart, iwl4965_mod_params.restart_fw, int, S_IRUGO);
-MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
similarity index 83%
rename from drivers/net/wireless/iwlegacy/iwl-prph.h
rename to drivers/net/wireless/iwlegacy/prph.h
index 30a493003ab09a74f8a198f11556ab38d1289888..ffec4b4a248ab498bff1bee28d2868a10c53e65d 100644 (file)
@@ -60,8 +60,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
-#ifndef        __iwl_legacy_prph_h__
-#define __iwl_legacy_prph_h__
+#ifndef        __il_prph_h__
+#define __il_prph_h__
 
 /*
  * Registers in this file are internal, not PCI bus memory mapped.
@@ -91,9 +91,9 @@
 #define APMG_PS_CTRL_VAL_RESET_REQ             (0x04000000)
 #define APMG_PS_CTRL_MSK_PWR_SRC               (0x03000000)
 #define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN         (0x00000000)
-#define APMG_PS_CTRL_VAL_PWR_SRC_MAX           (0x01000000) /* 3945 only */
+#define APMG_PS_CTRL_VAL_PWR_SRC_MAX           (0x01000000)    /* 3945 only */
 #define APMG_PS_CTRL_VAL_PWR_SRC_VAUX          (0x02000000)
-#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK        (0x000001E0) /* bit 8:5 */
+#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK        (0x000001E0)    /* bit 8:5 */
 #define APMG_SVR_DIGITAL_VOLTAGE_1_32          (0x00000060)
 
 #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS         (0x00000800)
  *
  * 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.
+ *     (struct il_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
+ *     notifies host via "alive" notification (struct il_alive_resp) that it
  *     is ready to be used.
  *
  * When initializing the NIC, the host driver does the following procedure:
  *        procedure.
  *
  * This save/restore method is mostly for autonomous power management during
- * normal operation (result of POWER_TABLE_CMD).  Platform suspend/resume and
+ * normal operation (result of C_POWER_TBL).  Platform suspend/resume and
  * RFKILL should use complete restarts (with total re-initialization) of uCode,
  * allowing total shutdown (including BSM memory).
  *
  */
 
 /* 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 */
+#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 */
+#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.
  * 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 */
-
+#define BSM_SRAM_SIZE                  (1024)  /* bytes */
 
 /* 3945 Tx scheduler registers */
 #define ALM_SCD_BASE                        (PRPH_BASE + 0x2E00)
  * but one DMA channel may take input from several queues.
  *
  * Tx DMA FIFOs have dedicated purposes.  For 4965, they are used as follows
- * (cf. default_queue_to_tx_fifo in iwl-4965.c):
+ * (cf. default_queue_to_tx_fifo in 4965.c):
  *
  * 0 -- EDCA BK (background) frames, lowest priority
  * 1 -- EDCA BE (best effort) frames, normal priority
  * The driver sets up each queue to work in one of two modes:
  *
  * 1)  Scheduler-Ack, in which the scheduler automatically supports a
- *     block-ack (BA) window of up to 64 TFDs.  In this mode, each queue
+ *     block-ack (BA) win of up to 64 TFDs.  In this mode, each queue
  *     contains TFDs for a unique combination of Recipient Address (RA)
  *     and Traffic Identifier (TID), that is, traffic of a given
  *     Quality-Of-Service (QOS) priority, destined for a single station.
  *
  *     In scheduler-ack mode, the scheduler keeps track of the Tx status of
- *     each frame within the BA window, including whether it's been transmitted,
+ *     each frame within the BA win, including whether it's been transmitted,
  *     and whether it's been acknowledged by the receiving station.  The device
  *     automatically processes block-acks received from the receiving STA,
  *     and reschedules un-acked frames to be retransmitted (successful
  *     Tx completion may end up being out-of-order).
  *
  *     The driver must maintain the queue's Byte Count table in host DRAM
- *     (struct iwl4965_sched_queue_byte_cnt_tbl) for this mode.
+ *     (struct il4965_sched_queue_byte_cnt_tbl) for this mode.
  *     This mode does not support fragmentation.
  *
  * 2)  FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.
  */
 
 /**
- * Max Tx window size is the max number of contiguous TFDs that the scheduler
+ * Max Tx win size is the max number of contiguous TFDs that the scheduler
  * can keep track of at one time when creating block-ack chains of frames.
  * Note that "64" matches the number of ack bits in a block-ack packet.
  * Driver should use SCD_WIN_SIZE and SCD_FRAME_LIMIT values to initialize
- * IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) values.
+ * IL49_SCD_CONTEXT_QUEUE_OFFSET(x) values.
  */
 #define SCD_WIN_SIZE                           64
 #define SCD_FRAME_LIMIT                                64
 
 /* SCD registers are internal, must be accessed via HBUS_TARG_PRPH regs */
-#define IWL49_SCD_START_OFFSET         0xa02c00
+#define IL49_SCD_START_OFFSET          0xa02c00
 
 /*
  * 4965 tells driver SRAM address for internal scheduler structs via this reg.
  * Value is valid only after "Alive" response from uCode.
  */
-#define IWL49_SCD_SRAM_BASE_ADDR           (IWL49_SCD_START_OFFSET + 0x0)
+#define IL49_SCD_SRAM_BASE_ADDR           (IL49_SCD_START_OFFSET + 0x0)
 
 /*
  * Driver may need to update queue-empty bits after changing queue's
- * write and read pointers (indexes) during (re-)initialization (i.e. when
+ * write and read pointers (idxes) during (re-)initialization (i.e. when
  * scheduler is not tracking what's happening).
  * Bit fields:
  * 31-16:  Write mask -- 1: update empty bit, 0: don't change empty bit
  * 15-00:  Empty state, one for each queue -- 1: empty, 0: non-empty
  * NOTE:  This register is not used by Linux driver.
  */
-#define IWL49_SCD_EMPTY_BITS               (IWL49_SCD_START_OFFSET + 0x4)
+#define IL49_SCD_EMPTY_BITS               (IL49_SCD_START_OFFSET + 0x4)
 
 /*
  * Physical base address of array of byte count (BC) circular buffers (CBs).
  * This register points to BC CB for queue 0, must be on 1024-byte boundary.
  * Others are spaced by 1024 bytes.
  * Each BC CB is 2 bytes * (256 + 64) = 740 bytes, followed by 384 bytes pad.
- * (Index into a queue's BC CB) = (index into queue's TFD CB) = (SSN & 0xff).
+ * (Index into a queue's BC CB) = (idx into queue's TFD CB) = (SSN & 0xff).
  * Bit fields:
  * 25-00:  Byte Count CB physical address [35:10], must be 1024-byte aligned.
  */
-#define IWL49_SCD_DRAM_BASE_ADDR           (IWL49_SCD_START_OFFSET + 0x10)
+#define IL49_SCD_DRAM_BASE_ADDR           (IL49_SCD_START_OFFSET + 0x10)
 
 /*
  * Enables any/all Tx DMA/FIFO channels.
  * Bit fields:
  *  7- 0:  Enable (1), disable (0), one bit for each channel 0-7
  */
-#define IWL49_SCD_TXFACT                   (IWL49_SCD_START_OFFSET + 0x1c)
+#define IL49_SCD_TXFACT                   (IL49_SCD_START_OFFSET + 0x1c)
 /*
- * Queue (x) Write Pointers (indexes, really!), one for each Tx queue.
+ * Queue (x) Write Pointers (idxes, really!), one for each Tx queue.
  * Initialized and updated by driver as new TFDs are added to queue.
- * NOTE:  If using Block Ack, index must correspond to frame's
- *        Start Sequence Number; index = (SSN & 0xff)
+ * NOTE:  If using Block Ack, idx must correspond to frame's
+ *        Start Sequence Number; idx = (SSN & 0xff)
  * NOTE:  Alternative to HBUS_TARG_WRPTR, which is what Linux driver uses?
  */
-#define IWL49_SCD_QUEUE_WRPTR(x)  (IWL49_SCD_START_OFFSET + 0x24 + (x) * 4)
+#define IL49_SCD_QUEUE_WRPTR(x)  (IL49_SCD_START_OFFSET + 0x24 + (x) * 4)
 
 /*
- * Queue (x) Read Pointers (indexes, really!), one for each Tx queue.
- * For FIFO mode, index indicates next frame to transmit.
- * For Scheduler-ACK mode, index indicates first frame in Tx window.
+ * Queue (x) Read Pointers (idxes, really!), one for each Tx queue.
+ * For FIFO mode, idx indicates next frame to transmit.
+ * For Scheduler-ACK mode, idx indicates first frame in Tx win.
  * Initialized by driver, updated by scheduler.
  */
-#define IWL49_SCD_QUEUE_RDPTR(x)  (IWL49_SCD_START_OFFSET + 0x64 + (x) * 4)
+#define IL49_SCD_QUEUE_RDPTR(x)  (IL49_SCD_START_OFFSET + 0x64 + (x) * 4)
 
 /*
  * Select which queues work in chain mode (1) vs. not (0).
  * NOTE:  If driver sets up queue for chain mode, it should be also set up
  *        Scheduler-ACK mode as well, via SCD_QUEUE_STATUS_BITS(x).
  */
-#define IWL49_SCD_QUEUECHAIN_SEL  (IWL49_SCD_START_OFFSET + 0xd0)
+#define IL49_SCD_QUEUECHAIN_SEL  (IL49_SCD_START_OFFSET + 0xd0)
 
 /*
  * Select which queues interrupt driver when scheduler increments
- * a queue's read pointer (index).
+ * a queue's read pointer (idx).
  * Bit fields:
  * 31-16:  Reserved
  * 15-00:  Interrupt enable, one bit for each queue -- 1: enabled, 0: disabled
  * NOTE:  This functionality is apparently a no-op; driver relies on interrupts
  *        from Rx queue to read Tx command responses and update Tx queues.
  */
-#define IWL49_SCD_INTERRUPT_MASK  (IWL49_SCD_START_OFFSET + 0xe4)
+#define IL49_SCD_INTERRUPT_MASK  (IL49_SCD_START_OFFSET + 0xe4)
 
 /*
  * Queue search status registers.  One for each queue.
  *        Driver should init to "1" for aggregation mode, or "0" otherwise.
  *   7-6: Driver should init to "0"
  *     5: Window Size Left; indicates whether scheduler can request
- *        another TFD, based on window size, etc.  Driver should init
+ *        another TFD, based on win size, etc.  Driver should init
  *        this bit to "1" for aggregation mode, or "0" for non-agg.
  *   4-1: Tx FIFO to use (range 0-7).
  *     0: Queue is active (1), not active (0).
  * NOTE:  If enabling Scheduler-ACK mode, chain mode should also be enabled
  *        via SCD_QUEUECHAIN_SEL.
  */
-#define IWL49_SCD_QUEUE_STATUS_BITS(x)\
-       (IWL49_SCD_START_OFFSET + 0x104 + (x) * 4)
+#define IL49_SCD_QUEUE_STATUS_BITS(x)\
+       (IL49_SCD_START_OFFSET + 0x104 + (x) * 4)
 
 /* Bit field positions */
-#define IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE    (0)
-#define IWL49_SCD_QUEUE_STTS_REG_POS_TXF       (1)
-#define IWL49_SCD_QUEUE_STTS_REG_POS_WSL       (5)
-#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK   (8)
+#define IL49_SCD_QUEUE_STTS_REG_POS_ACTIVE     (0)
+#define IL49_SCD_QUEUE_STTS_REG_POS_TXF        (1)
+#define IL49_SCD_QUEUE_STTS_REG_POS_WSL        (5)
+#define IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK    (8)
 
 /* Write masks */
-#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN        (10)
-#define IWL49_SCD_QUEUE_STTS_REG_MSK           (0x0007FC00)
+#define IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (10)
+#define IL49_SCD_QUEUE_STTS_REG_MSK            (0x0007FC00)
 
 /**
  * 4965 internal SRAM structures for scheduler, shared with driver ...
  * each queue's entry as follows:
  *
  * LS Dword bit fields:
- *  0-06:  Max Tx window size for Scheduler-ACK.  Driver should init to 64.
+ *  0-06:  Max Tx win size for Scheduler-ACK.  Driver should init to 64.
  *
  * MS Dword bit fields:
  * 16-22:  Frame limit.  Driver should init to 10 (0xa).
  * Init must be done after driver receives "Alive" response from 4965 uCode,
  * and when setting up queue for aggregation.
  */
-#define IWL49_SCD_CONTEXT_DATA_OFFSET                  0x380
-#define IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) \
-                       (IWL49_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
+#define IL49_SCD_CONTEXT_DATA_OFFSET                   0x380
+#define IL49_SCD_CONTEXT_QUEUE_OFFSET(x) \
+                       (IL49_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
 
-#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS          (0)
-#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK          (0x0000007F)
-#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS       (16)
-#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK       (0x007F0000)
+#define IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS           (0)
+#define IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK           (0x0000007F)
+#define IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS        (16)
+#define IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK        (0x007F0000)
 
 /*
  * Tx Status Bitmap
  * "Alive" notification from uCode.  Area is used only by device itself;
  * no other support (besides clearing) is required from driver.
  */
-#define IWL49_SCD_TX_STTS_BITMAP_OFFSET                0x400
+#define IL49_SCD_TX_STTS_BITMAP_OFFSET         0x400
 
 /*
  * RAxTID to queue translation mapping.
  * When queue is in Scheduler-ACK mode, frames placed in a that queue must be
  * for only one combination of receiver address (RA) and traffic ID (TID), i.e.
  * one QOS priority level destined for one station (for this wireless link,
- * not final destination).  The SCD_TRANSLATE_TABLE area provides 16 16-bit
+ * not final destination).  The SCD_TRANSLATE_TBL area provides 16 16-bit
  * mappings, one for each of the 16 queues.  If queue is not in Scheduler-ACK
  * mode, the device ignores the mapping value.
  *
  * must read a dword-aligned value from device SRAM, replace the 16-bit map
  * value of interest, and write the dword value back into device SRAM.
  */
-#define IWL49_SCD_TRANSLATE_TBL_OFFSET         0x500
+#define IL49_SCD_TRANSLATE_TBL_OFFSET          0x500
 
 /* Find translation table dword to read/write for given queue */
-#define IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
-       ((IWL49_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc)
+#define IL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
+       ((IL49_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc)
 
-#define IWL_SCD_TXFIFO_POS_TID                 (0)
-#define IWL_SCD_TXFIFO_POS_RA                  (4)
-#define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK     (0x01FF)
+#define IL_SCD_TXFIFO_POS_TID                  (0)
+#define IL_SCD_TXFIFO_POS_RA                   (4)
+#define IL_SCD_QUEUE_RA_TID_MAP_RATID_MSK      (0x01FF)
 
 /*********************** END TX SCHEDULER *************************************/
 
-#endif                         /* __iwl_legacy_prph_h__ */
+#endif /* __il_prph_h__ */
index e6a02e09ee18e1115ef83986e3bfaa998ec6d383..a1a95d5f3923e7f93811b466f48a4411f81d2046 100644 (file)
@@ -790,6 +790,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
                iwl_rx_reply_tx_agg(priv, tx_resp);
 
        if (tx_resp->frame_count == 1) {
+               IWL_DEBUG_TX_REPLY(priv, "Q %d, ssn %d", txq_id, ssn);
                __skb_queue_head_init(&skbs);
                /*we can free until ssn % q.n_bd not inclusive */
                iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
@@ -920,11 +921,9 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                           ba_resp->sta_id);
        IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, "
                           "scd_flow = %d, scd_ssn = %d\n",
-                          ba_resp->tid,
-                          ba_resp->seq_ctl,
+                          ba_resp->tid, ba_resp->seq_ctl,
                           (unsigned long long)le64_to_cpu(ba_resp->bitmap),
-                          ba_resp->scd_flow,
-                          ba_resp->scd_ssn);
+                          scd_flow, ba_resp_scd_ssn);
 
        /* Mark that the expected block-ack response arrived */
        agg->wait_for_ba = false;
index 40ef97bac1aa232139d8d4274ee46fd9e7f64398..44a7bdd7ccfd410acce5b9e704a35d18fad587ba 100644 (file)
@@ -47,20 +47,21 @@ do {                                                                        \
 } while (0)
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-#define IWL_DEBUG(m, level, fmt, args...)                              \
+#define IWL_DEBUG(m, level, fmt, ...)                                  \
 do {                                                                   \
        if (iwl_get_debug_level((m)->shrd) & (level))                   \
-               dev_printk(KERN_ERR, bus(m)->dev,                       \
-                        "%c %s " fmt, in_interrupt() ? 'I' : 'U',      \
-                       __func__ , ## args);                            \
+               dev_err(bus(m)->dev, "%c %s " fmt,                      \
+                       in_interrupt() ? 'I' : 'U', __func__,           \
+                       ##__VA_ARGS__);                                 \
 } while (0)
 
-#define IWL_DEBUG_LIMIT(m, level, fmt, args...)                                \
+#define IWL_DEBUG_LIMIT(m, level, fmt, ...)                            \
 do {                                                                   \
-       if (iwl_get_debug_level((m)->shrd) & (level) && net_ratelimit())\
-               dev_printk(KERN_ERR, bus(m)->dev,                       \
-                       "%c %s " fmt, in_interrupt() ? 'I' : 'U',       \
-                        __func__ , ## args);                           \
+       if (iwl_get_debug_level((m)->shrd) & (level) &&                 \
+           net_ratelimit())                                            \
+               dev_err(bus(m)->dev, "%c %s " fmt,                      \
+                       in_interrupt() ? 'I' : 'U', __func__,           \
+                       ##__VA_ARGS__);                                 \
 } while (0)
 
 #define iwl_print_hex_dump(m, level, p, len)                           \
@@ -70,14 +71,18 @@ do {                                                                \
                               DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);   \
 } while (0)
 
-#define IWL_DEBUG_QUIET_RFKILL(p, fmt, args...)                        \
+#define IWL_DEBUG_QUIET_RFKILL(p, fmt, ...)                            \
 do {                                                                   \
-       if (!iwl_is_rfkill(p->shrd))                            \
-               dev_printk(KERN_ERR, bus(p)->dev, "%c %s " fmt, \
-               (in_interrupt() ? 'I' : 'U'), __func__ , ##args);       \
-       else if (iwl_get_debug_level(p->shrd) & IWL_DL_RADIO)   \
-               dev_printk(KERN_ERR, bus(p)->dev, "(RFKILL) %c %s " fmt, \
-               (in_interrupt() ? 'I' : 'U'), __func__ , ##args);       \
+       if (!iwl_is_rfkill(p->shrd))                                    \
+               dev_err(bus(p)->dev, "%s%c %s " fmt,                    \
+                       "",                                             \
+                       in_interrupt() ? 'I' : 'U', __func__,           \
+                       ##__VA_ARGS__);                                 \
+       else if (iwl_get_debug_level(p->shrd) & IWL_DL_RADIO)           \
+               dev_err(bus(p)->dev, "%s%c %s " fmt,                    \
+                       "(RFKILL) ",                                    \
+                       in_interrupt() ? 'I' : 'U', __func__,           \
+                       ##__VA_ARGS__);                                 \
 } while (0)
 
 #else
index 3ffa8e62b8565e442394083fad92a2c9c6fa6ad7..3464cad7e38ccf9998e68b575e051eac74b47ca8 100644 (file)
@@ -143,7 +143,7 @@ u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg)
 
        spin_lock_irqsave(&bus->reg_lock, flags);
        iwl_grab_nic_access(bus);
-       value = iwl_read32(bus(bus), reg);
+       value = iwl_read32(bus, reg);
        iwl_release_nic_access(bus);
        spin_unlock_irqrestore(&bus->reg_lock, flags);
 
index afaaa2a51b966e0bb93477f03fabfbb5590f0d40..5a384b309b097df902aaf1700f56ebb449fa8d06 100644 (file)
@@ -354,6 +354,11 @@ static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
        txq->swq_id = (hwq << 2) | ac;
 }
 
+static inline u8 iwl_get_queue_ac(struct iwl_tx_queue *txq)
+{
+       return txq->swq_id & 0x3;
+}
+
 static inline void iwl_wake_queue(struct iwl_trans *trans,
                                  struct iwl_tx_queue *txq, const char *msg)
 {
index 6dba1515023c89efcc95330da663c34c336ea3fd..79331fb10aa5664395624b5adcab7caedcdd0c16 100644 (file)
@@ -559,7 +559,6 @@ int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
        tid_data->agg.txq_id = txq_id;
        iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id);
 
-       tid_data = &trans->shrd->tid_data[sta_id][tid];
        if (tid_data->tfds_in_queue == 0) {
                IWL_DEBUG_TX_QUEUES(trans, "HW queue is empty\n");
                tid_data->agg.state = IWL_AGG_ON;
@@ -1121,9 +1120,6 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
                return 0;
        }
 
-       IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id,
-                          q->read_ptr, index);
-
        if (WARN_ON(!skb_queue_empty(skbs)))
                return 0;
 
index 93c4f56ac408b5beb783836b2d9ac0fc5e897784..5954fdfd60dd12ea64126b5d2201ee8c050cc045 100644 (file)
@@ -1351,9 +1351,9 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
        }
 
        if (txq->q.read_ptr != tfd_num) {
-               IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim "
-                               "scd_ssn=%d idx=%d txq=%d swq=%d\n",
-                               ssn , tfd_num, txq_id, txq->swq_id);
+               IWL_DEBUG_TX_REPLY(trans, "[Q %d | AC %d] %d -> %d (%d)\n",
+                               txq_id, iwl_get_queue_ac(txq), txq->q.read_ptr,
+                               tfd_num, ssn);
                freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
                if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond)
                        iwl_wake_queue(trans, txq, "Packets reclaimed");
@@ -1516,8 +1516,12 @@ static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt)
        if (time_after(jiffies, timeout)) {
                IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id,
                        hw_params(trans).wd_timeout);
-               IWL_ERR(trans, "Current read_ptr %d write_ptr %d\n",
+               IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n",
                        q->read_ptr, q->write_ptr);
+               IWL_ERR(trans, "Current HW read_ptr %d write_ptr %d\n",
+                       iwl_read_prph(bus(trans), SCD_QUEUE_RDPTR(cnt))
+                               & (TFD_QUEUE_SIZE_MAX - 1),
+                       iwl_read_prph(bus(trans), SCD_QUEUE_WRPTR(cnt)));
                return 1;
        }
 
index 885ddc1c4fed70d8b6a2a47042cba18016069c00..f955b2d66ed6e7609836e919678fc8c79d479b4b 100644 (file)
@@ -13,13 +13,14 @@ static void lbs_ethtool_get_drvinfo(struct net_device *dev,
 {
        struct lbs_private *priv = dev->ml_priv;
 
-       snprintf(info->fw_version, 32, "%u.%u.%u.p%u",
+       snprintf(info->fw_version, sizeof(info->fw_version),
+               "%u.%u.%u.p%u",
                priv->fwrelease >> 24 & 0xff,
                priv->fwrelease >> 16 & 0xff,
                priv->fwrelease >>  8 & 0xff,
                priv->fwrelease       & 0xff);
-       strcpy(info->driver, "libertas");
-       strcpy(info->version, lbs_driver_version);
+       strlcpy(info->driver, "libertas", sizeof(info->driver));
+       strlcpy(info->version, lbs_driver_version, sizeof(info->version));
 }
 
 /*
index 8f2797aa0c6083be6f22f557b4b479d7014b1b69..2a078cea830a01b04237a646c5d9b73f84febd4e 100644 (file)
@@ -10,12 +10,12 @@ config MWIFIEX
          mwifiex.
 
 config MWIFIEX_SDIO
-       tristate "Marvell WiFi-Ex Driver for SD8787"
+       tristate "Marvell WiFi-Ex Driver for SD8787/SD8797"
        depends on MWIFIEX && MMC
        select FW_LOADER
        ---help---
          This adds support for wireless adapters based on Marvell
-         8787 chipset with SDIO interface.
+         8787/8797 chipsets with SDIO interface.
 
          If you choose to build it as a module, it will be called
          mwifiex_sdio.
index f2e6de03805cd61bbe246d8ccf8a5a6235d78e0b..1782a77f15dcb82b9a2d1febef1f0fecd03f2895 100644 (file)
@@ -75,18 +75,32 @@ static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
  * This function maps an index in supported rates table into
  * the corresponding data rate.
  */
-u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info)
+u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index,
+                                                       u8 ht_info)
 {
-       u16 mcs_rate[4][8] = {
-               {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e}
-       ,                       /* LG 40M */
-       {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c}
-       ,                       /* SG 40M */
-       {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82}
-       ,                       /* LG 20M */
-       {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90}
-       };                      /* SG 20M */
-
+       /*
+        * For every mcs_rate line, the first 8 bytes are for stream 1x1,
+        * and all 16 bytes are for stream 2x2.
+        */
+       u16  mcs_rate[4][16] = {
+               /* LGI 40M */
+               { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e,
+                 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c },
+
+               /* SGI 40M */
+               { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c,
+                 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 },
+
+               /* LGI 20M */
+               { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82,
+                 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 },
+
+               /* SGI 20M */
+               { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,
+                 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }
+       };
+       u32 mcs_num_supp =
+               (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8;
        u32 rate;
 
        if (ht_info & BIT(0)) {
@@ -95,7 +109,7 @@ u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info)
                                rate = 0x0D;    /* MCS 32 SGI rate */
                        else
                                rate = 0x0C;    /* MCS 32 LGI rate */
-               } else if (index < 8) {
+               } else if (index < mcs_num_supp) {
                        if (ht_info & BIT(1)) {
                                if (ht_info & BIT(2))
                                        /* SGI, 40M */
index 35cb29cbd96e5d083b438fa62c22e85493dec45d..62b863907698028f07a5abb51d33bde8c3a96681 100644 (file)
@@ -165,6 +165,7 @@ enum MWIFIEX_802_11_WEP_STATUS {
 
 #define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
 #define SETHT_MCS32(x) (x[4] |= 1)
+#define HT_STREAM_2X2  0x22
 
 #define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4))
 
index 30f138b6fa4c6cf4545ca1c2500baf8a42c43248..3861a617c0e13e3b5b61a768924e20bfb2784715 100644 (file)
@@ -775,7 +775,8 @@ struct mwifiex_chan_freq_power *
 struct mwifiex_chan_freq_power *mwifiex_get_cfp_by_band_and_freq_from_cfg80211(
                                                struct mwifiex_private *priv,
                                                u8 band, u32 freq);
-u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info);
+u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index,
+                                                       u8 ht_info);
 u32 mwifiex_find_freq_from_band_chan(u8, u8);
 int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask,
                                u8 **buffer);
index ffaf3f3a57df047beea84986504a071b4b05e3ca..702452b505c33c3e29f00dc45b576879524a3eed 100644 (file)
@@ -256,10 +256,13 @@ static int mwifiex_sdio_resume(struct device *dev)
 
 /* Device ID for SD8787 */
 #define SDIO_DEVICE_ID_MARVELL_8787   (0x9119)
+/* Device ID for SD8797 */
+#define SDIO_DEVICE_ID_MARVELL_8797   (0x9129)
 
 /* WLAN IDs */
 static const struct sdio_device_id mwifiex_ids[] = {
        {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787)},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797)},
        {},
 };
 
@@ -1573,7 +1576,16 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
        sdio_set_drvdata(func, card);
 
        adapter->dev = &func->dev;
-       strcpy(adapter->fw_name, SD8787_DEFAULT_FW_NAME);
+
+       switch (func->device) {
+       case SDIO_DEVICE_ID_MARVELL_8797:
+               strcpy(adapter->fw_name, SD8797_DEFAULT_FW_NAME);
+               break;
+       case SDIO_DEVICE_ID_MARVELL_8787:
+       default:
+               strcpy(adapter->fw_name, SD8787_DEFAULT_FW_NAME);
+               break;
+       }
 
        return 0;
 
@@ -1774,4 +1786,5 @@ MODULE_AUTHOR("Marvell International Ltd.");
 MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);
 MODULE_VERSION(SDIO_VERSION);
 MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
+MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME);
index 3f711801e58a9cb4916ffe259e5a5c71691cdfbd..a3fb322205b0a69c295049cecb94c6522ea4b768 100644 (file)
@@ -29,6 +29,7 @@
 #include "main.h"
 
 #define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
+#define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin"
 
 #define BLOCK_MODE     1
 #define BYTE_MODE      0
index 7a16b0c417afc58a0d7a23cf5aadd6151d2b7fd6..e812db8b695cabdfa294c19d9ab08e92b4cb88b7 100644 (file)
@@ -508,7 +508,7 @@ static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv,
        priv->tx_htinfo = resp->params.tx_rate.ht_info;
        if (!priv->is_data_rate_auto)
                priv->data_rate =
-                       mwifiex_index_to_data_rate(priv->tx_rate,
+                       mwifiex_index_to_data_rate(priv, priv->tx_rate,
                                                   priv->tx_htinfo);
 
        return 0;
index ea4a29b7e331c4bccf646deb92f414c4825a5796..4b6f5539657d6cd250c07939cda005c02e66fba0 100644 (file)
@@ -832,8 +832,8 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
 
        if (!ret) {
                if (rate->is_rate_auto)
-                       rate->rate = mwifiex_index_to_data_rate(priv->tx_rate,
-                                                       priv->tx_htinfo);
+                       rate->rate = mwifiex_index_to_data_rate(priv,
+                                       priv->tx_rate, priv->tx_htinfo);
                else
                        rate->rate = priv->data_rate;
        } else {
index 78d0d6988553d40354b9fbf2396e1657eaefd9c6..2d5cf5ba319b13324ee5b435a3db4559a974d100 100644 (file)
@@ -581,11 +581,7 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
        struct p54s_priv *priv = dev->priv;
        unsigned long flags;
 
-       if (mutex_lock_interruptible(&priv->mutex)) {
-               /* FIXME: how to handle this error? */
-               return;
-       }
-
+       mutex_lock(&priv->mutex);
        WARN_ON(priv->fw_state != FW_STATE_READY);
 
        p54spi_power_off(priv);
index 6ed9c323e3cb866c1b69dc7294b71f82f7cc8878..42b97bc3847717fa017d923fd840c6c12261bd8a 100644 (file)
@@ -242,7 +242,7 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
 
        skb_unlink(skb, &priv->tx_queue);
        p54_tx_qos_accounting_free(priv, skb);
-       dev_kfree_skb_any(skb);
+       ieee80211_free_txskb(dev, skb);
 }
 EXPORT_SYMBOL_GPL(p54_free_skb);
 
@@ -788,7 +788,7 @@ void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
                            &hdr_flags, &aid, &burst_allowed);
 
        if (p54_tx_qos_accounting_alloc(priv, skb, queue)) {
-               dev_kfree_skb_any(skb);
+               ieee80211_free_txskb(dev, skb);
                return;
        }
 
index 5d0f61508a2edd51fbf6a5b58b9c0f456a0f7df3..8a3cf4fe376f99e96a639a5c3b0ca1105fb71e8c 100644 (file)
@@ -793,8 +793,8 @@ islpci_set_multicast_list(struct net_device *dev)
 static void islpci_ethtool_get_drvinfo(struct net_device *dev,
                                        struct ethtool_drvinfo *info)
 {
-       strcpy(info->driver, DRV_NAME);
-       strcpy(info->version, DRV_VERSION);
+       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
 }
 
 static const struct ethtool_ops islpci_ethtool_ops = {
index 620e3c0e88e039152b39ddbe3f2173be46b6aa1e..3802c31fefcd105d62b46925508ec2f34ca54733 100644 (file)
@@ -244,6 +244,10 @@ enum ndis_80211_power_mode {
        NDIS_80211_POWER_MODE_FAST_PSP,
 };
 
+enum ndis_80211_pmkid_cand_list_flag_bits {
+       NDIS_80211_PMKID_CAND_PREAUTH = cpu_to_le32(1 << 0)
+};
+
 struct ndis_80211_auth_request {
        __le32 length;
        u8 bssid[6];
@@ -387,19 +391,17 @@ struct ndis_80211_capability {
 struct ndis_80211_bssid_info {
        u8 bssid[6];
        u8 pmkid[16];
-};
+} __packed;
 
 struct ndis_80211_pmkid {
        __le32 length;
        __le32 bssid_info_count;
        struct ndis_80211_bssid_info bssid_info[0];
-};
+} __packed;
 
 /*
  *  private data
  */
-#define NET_TYPE_11FB  0
-
 #define CAP_MODE_80211A                1
 #define CAP_MODE_80211B                2
 #define CAP_MODE_80211G                4
@@ -1347,6 +1349,32 @@ static int set_channel(struct usbnet *usbdev, int channel)
        return ret;
 }
 
+static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev,
+                                                    u16 *beacon_interval)
+{
+       struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+       struct ieee80211_channel *channel;
+       struct ndis_80211_conf config;
+       int len, ret;
+
+       /* Get channel and beacon interval */
+       len = sizeof(config);
+       ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
+       netdev_dbg(usbdev->net, "%s(): OID_802_11_CONFIGURATION -> %d\n",
+                               __func__, ret);
+       if (ret < 0)
+               return NULL;
+
+       channel = ieee80211_get_channel(priv->wdev.wiphy,
+                               KHZ_TO_MHZ(le32_to_cpu(config.ds_config)));
+       if (!channel)
+               return NULL;
+
+       if (beacon_interval)
+               *beacon_interval = le16_to_cpu(config.beacon_period);
+       return channel;
+}
+
 /* index must be 0 - N, as per NDIS  */
 static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len,
                                                                int index)
@@ -2650,13 +2678,12 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
 {
        struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
        struct ieee80211_channel *channel;
-       struct ndis_80211_conf config;
        struct ndis_80211_ssid ssid;
        struct cfg80211_bss *bss;
        s32 signal;
        u64 timestamp;
        u16 capability;
-       u16 beacon_interval;
+       u16 beacon_interval = 0;
        __le32 rssi;
        u8 ie_buf[34];
        int len, ret, ie_len;
@@ -2681,22 +2708,10 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid,
        }
 
        /* Get channel and beacon interval */
-       len = sizeof(config);
-       ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
-       netdev_dbg(usbdev->net, "%s(): OID_802_11_CONFIGURATION -> %d\n",
-                               __func__, ret);
-       if (ret >= 0) {
-               beacon_interval = le16_to_cpu(config.beacon_period);
-               channel = ieee80211_get_channel(priv->wdev.wiphy,
-                               KHZ_TO_MHZ(le32_to_cpu(config.ds_config)));
-               if (!channel) {
-                       netdev_warn(usbdev->net, "%s(): could not get channel."
-                                                "\n", __func__);
-                       return;
-               }
-       } else {
-               netdev_warn(usbdev->net, "%s(): could not get configuration.\n",
-                                        __func__);
+       channel = get_current_channel(usbdev, &beacon_interval);
+       if (!channel) {
+               netdev_warn(usbdev->net, "%s(): could not get channel.\n",
+                                       __func__);
                return;
        }
 
@@ -2841,8 +2856,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
                                                req_ie_len, resp_ie,
                                                resp_ie_len, 0, GFP_KERNEL);
                else
-                       cfg80211_roamed(usbdev->net, NULL, bssid,
-                                       req_ie, req_ie_len,
+                       cfg80211_roamed(usbdev->net,
+                                       get_current_channel(usbdev, NULL),
+                                       bssid, req_ie, req_ie_len,
                                        resp_ie, resp_ie_len, GFP_KERNEL);
        } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
                cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
@@ -3008,25 +3024,13 @@ static void rndis_wlan_pmkid_cand_list_indication(struct usbnet *usbdev,
        for (i = 0; i < le32_to_cpu(cand_list->num_candidates); i++) {
                struct ndis_80211_pmkid_candidate *cand =
                                                &cand_list->candidate_list[i];
+               bool preauth = !!(cand->flags & NDIS_80211_PMKID_CAND_PREAUTH);
 
-               netdev_dbg(usbdev->net, "cand[%i]: flags: 0x%08x, bssid: %pM\n",
-                          i, le32_to_cpu(cand->flags), cand->bssid);
-
-#if 0
-               struct iw_pmkid_cand pcand;
-               union iwreq_data wrqu;
+               netdev_dbg(usbdev->net, "cand[%i]: flags: 0x%08x, preauth: %d, bssid: %pM\n",
+                          i, le32_to_cpu(cand->flags), preauth, cand->bssid);
 
-               memset(&pcand, 0, sizeof(pcand));
-               if (le32_to_cpu(cand->flags) & 0x01)
-                       pcand.flags |= IW_PMKID_CAND_PREAUTH;
-               pcand.index = i;
-               memcpy(pcand.bssid.sa_data, cand->bssid, ETH_ALEN);
-
-               memset(&wrqu, 0, sizeof(wrqu));
-               wrqu.data.length = sizeof(pcand);
-               wireless_send_event(usbdev->net, IWEVPMKIDCAND, &wrqu,
-                                                               (u8 *)&pcand);
-#endif
+               cfg80211_pmksa_candidate_notify(usbdev->net, i, cand->bssid,
+                                               preauth, GFP_ATOMIC);
        }
 }
 
index b4ce93436d2e705a3661e616c3b7111fa5f64641..a13ecfce482554f4fb62bbf3bd2caeaabd639a21 100644 (file)
@@ -345,9 +345,9 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
        if (is_valid_ether_addr(rtlefuse->dev_addr)) {
                SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr);
        } else {
-               u8 rtlmac[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 };
-               get_random_bytes((rtlmac + (ETH_ALEN - 1)), 1);
-               SET_IEEE80211_PERM_ADDR(hw, rtlmac);
+               u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 };
+               get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1);
+               SET_IEEE80211_PERM_ADDR(hw, rtlmac1);
        }
 
 }
index 4ae905983d0d5299670787b9001b07f4754d5dd4..f66b5757f6b9b5bfef1a5111b517fa65131eed78 100644 (file)
@@ -76,7 +76,7 @@ enum ap_peer {
        SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val)
 
 #define SET_80211_PS_POLL_AID(_hdr, _val)              \
-       (*(u16 *)((u8 *)(_hdr) + 2) = le16_to_cpu(_val))
+       (*(u16 *)((u8 *)(_hdr) + 2) = _val)
 #define SET_80211_PS_POLL_BSSID(_hdr, _val)            \
        memcpy(((u8 *)(_hdr)) + 4, (u8 *)(_val), ETH_ALEN)
 #define SET_80211_PS_POLL_TA(_hdr, _val)               \
index eb61061821e40cc2f3f1d25ac678bbd4b813e1b2..b6683a247b51846cc67cc602a1e65c6c0272be0e 100644 (file)
@@ -890,9 +890,6 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
        if (rtlpriv->rtlhal.earlymode_enable)
                tasklet_schedule(&rtlpriv->works.irq_tasklet);
 
-       spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
-       return IRQ_HANDLED;
-
 done:
        spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
        return IRQ_HANDLED;
index 950c65a15b8a7fa0521471f5124cd89ee111268b..fa393dfe136cbcf07ccac43a1fb8ca472cea33f0 100644 (file)
@@ -73,6 +73,34 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
        }
 }
 
+static void rtl_block_fw_writeN(struct ieee80211_hw *hw, const u8 *buffer,
+                               u32 size)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u32 blockSize = REALTEK_USB_VENQT_MAX_BUF_SIZE - 20;
+       u8 *bufferPtr = (u8 *) buffer;
+       u32 i, offset, blockCount, remainSize;
+
+       blockCount = size / blockSize;
+       remainSize = size % blockSize;
+
+       for (i = 0; i < blockCount; i++) {
+               offset = i * blockSize;
+               rtlpriv->io.writeN_sync(rtlpriv,
+                                       (FW_8192C_START_ADDRESS + offset),
+                                       (void *)(bufferPtr + offset),
+                                       blockSize);
+       }
+
+       if (remainSize) {
+               offset = blockCount * blockSize;
+               rtlpriv->io.writeN_sync(rtlpriv,
+                                       (FW_8192C_START_ADDRESS + offset),
+                                       (void *)(bufferPtr + offset),
+                                       remainSize);
+       }
+}
+
 static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
                                   const u8 *buffer, u32 size)
 {
@@ -81,23 +109,30 @@ static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
        u8 *bufferPtr = (u8 *) buffer;
        u32 *pu4BytePtr = (u32 *) buffer;
        u32 i, offset, blockCount, remainSize;
+       u32 data;
 
+       if (rtlpriv->io.writeN_sync) {
+               rtl_block_fw_writeN(hw, buffer, size);
+               return;
+       }
        blockCount = size / blockSize;
        remainSize = size % blockSize;
+       if (remainSize) {
+               /* the last word is < 4 bytes - pad it with zeros */
+               for (i = 0; i < 4 - remainSize; i++)
+                       *(bufferPtr + size + i) = 0;
+               blockCount++;
+       }
 
        for (i = 0; i < blockCount; i++) {
                offset = i * blockSize;
+               /* for big-endian platforms, the firmware data need to be byte
+                * swapped as it was read as a byte string and will be written
+                * as 32-bit dwords and byte swapped when written
+                */
+               data = le32_to_cpu(*(__le32 *)(pu4BytePtr + i));
                rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
-                               *(pu4BytePtr + i));
-       }
-
-       if (remainSize) {
-               offset = blockCount * blockSize;
-               bufferPtr += offset;
-               for (i = 0; i < remainSize; i++) {
-                       rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
-                                                offset + i), *(bufferPtr + i));
-               }
+                               data);
        }
 }
 
@@ -238,8 +273,9 @@ int rtl92c_download_fw(struct ieee80211_hw *hw)
        if (IS_FW_HEADER_EXIST(pfwheader)) {
                RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
                         ("Firmware Version(%d), Signature(%#x),Size(%d)\n",
-                         pfwheader->version, pfwheader->signature,
-                         (uint)sizeof(struct rtl92c_firmware_header)));
+                        le16_to_cpu(pfwheader->version),
+                        le16_to_cpu(pfwheader->signature),
+                        (uint)sizeof(struct rtl92c_firmware_header)));
 
                pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
                fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
index 3d5823c12621ef0e2da79d1c3d68616f7671a431..cec5a3a1cc5338ab0f136c933b3073cbbd02dc53 100644 (file)
 
 #define FW_8192C_SIZE                          0x3000
 #define FW_8192C_START_ADDRESS                 0x1000
-#define FW_8192C_END_ADDRESS                   0x3FFF
+#define FW_8192C_END_ADDRESS                   0x1FFF
 #define FW_8192C_PAGE_SIZE                     4096
 #define FW_8192C_POLLING_DELAY                 5
 #define FW_8192C_POLLING_TIMEOUT_COUNT         100
 
 #define IS_FW_HEADER_EXIST(_pfwhdr)    \
-       ((_pfwhdr->signature&0xFFF0) == 0x92C0 ||\
-       (_pfwhdr->signature&0xFFF0) == 0x88C0)
+       ((le16_to_cpu(_pfwhdr->signature)&0xFFF0) == 0x92C0 ||\
+       (le16_to_cpu(_pfwhdr->signature)&0xFFF0) == 0x88C0)
 
 struct rtl92c_firmware_header {
-       u16 signature;
+       __le16 signature;
        u8 category;
        u8 function;
-       u16 version;
+       __le16 version;
        u8 subversion;
        u8 rsvd1;
        u8 month;
        u8 date;
        u8 hour;
        u8 minute;
-       u16 ramcodeSize;
-       u16 rsvd2;
-       u32 svnindex;
-       u32 rsvd3;
-       u32 rsvd4;
-       u32 rsvd5;
+       __le16 ramcodeSize;
+       __le16 rsvd2;
+       __le32 svnindex;
+       __le32 rsvd3;
+       __le32 rsvd4;
+       __le32 rsvd5;
 };
 
 enum rtl8192c_h2c_cmd {
@@ -94,5 +94,6 @@ void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
 void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len);
 
 #endif
index 814c05df51e8b3d299c754320d53ee0c75271a12..4ed973a3aa177fd822531eeb3a4d04014a0ee504 100644 (file)
@@ -498,7 +498,7 @@ static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw)
        }
        RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, ("MAP\n"),
                      hwinfo, HWSET_MAX_SIZE);
-       eeprom_id = *((u16 *)&hwinfo[0]);
+       eeprom_id = le16_to_cpu(*((__le16 *)&hwinfo[0]));
        if (eeprom_id != RTL8190_EEPROM_ID) {
                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
                         ("EEPROM ID(%#x) is invalid!!\n", eeprom_id));
@@ -516,13 +516,14 @@ static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw)
        pr_info("MAC address: %pM\n", rtlefuse->dev_addr);
        _rtl92cu_read_txpower_info_from_hwpg(hw,
                                           rtlefuse->autoload_failflag, hwinfo);
-       rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
-       rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID];
+       rtlefuse->eeprom_vid = le16_to_cpu(*(__le16 *)&hwinfo[EEPROM_VID]);
+       rtlefuse->eeprom_did = le16_to_cpu(*(__le16 *)&hwinfo[EEPROM_DID]);
        RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
                 (" VID = 0x%02x PID = 0x%02x\n",
                 rtlefuse->eeprom_vid, rtlefuse->eeprom_did));
        rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN];
-       rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
+       rtlefuse->eeprom_version =
+                        le16_to_cpu(*(__le16 *)&hwinfo[EEPROM_VERSION]);
        rtlefuse->txpwr_fromeprom = true;
        rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
index 060a06f4a885ef2d2bba48cee48d3c1e8f24a8df..9e0c8fcdf90fb60c1fb9370e3fe0c36d563f3da7 100644 (file)
@@ -84,6 +84,7 @@ void rtl92c_read_chip_version(struct ieee80211_hw *hw)
                }
        }
        rtlhal->version  = (enum version_8192c)chip_version;
+       pr_info("rtl8192cu: Chip version 0x%x\n", chip_version);
        switch (rtlhal->version) {
        case VERSION_NORMAL_TSMC_CHIP_92C_1T2R:
                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
index bc33b147f44f70f502d3dfe83994f0f3ed4e57c7..b3cc7b9499927d3db75af87c0d1d2ebcd66e8b3b 100644 (file)
@@ -491,7 +491,7 @@ static void _rtl_tx_desc_checksum(u8 *txdesc)
        SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, 0);
        for (index = 0; index < 16; index++)
                checksum = checksum ^ (*(ptr + index));
-       SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum);
+       SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, cpu_to_le16(checksum));
 }
 
 void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
index 54cb8a60514d582e6bf5ae07fdf3d2b212aa2c2c..e956fa71d040756952868e423d497b8a329aff2b 100644 (file)
 #include "usb.h"
 #include "base.h"
 #include "ps.h"
+#include "rtl8192c/fw_common.h"
 
 #define        REALTEK_USB_VENQT_READ                  0xC0
 #define        REALTEK_USB_VENQT_WRITE                 0x40
 #define REALTEK_USB_VENQT_CMD_REQ              0x05
 #define        REALTEK_USB_VENQT_CMD_IDX               0x00
 
-#define REALTEK_USB_VENQT_MAX_BUF_SIZE         254
+#define MAX_USBCTRL_VENDORREQ_TIMES            10
 
 static void usbctrl_async_callback(struct urb *urb)
 {
@@ -82,6 +83,7 @@ static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
        dr->wValue = cpu_to_le16(value);
        dr->wIndex = cpu_to_le16(index);
        dr->wLength = cpu_to_le16(len);
+       /* data are already in little-endian order */
        memcpy(buf, pdata, len);
        usb_fill_control_urb(urb, udev, pipe,
                             (unsigned char *)dr, buf, len,
@@ -100,16 +102,28 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
        unsigned int pipe;
        int status;
        u8 reqtype;
+       int vendorreq_times = 0;
+       static int count;
 
        pipe = usb_rcvctrlpipe(udev, 0); /* read_in */
        reqtype =  REALTEK_USB_VENQT_READ;
 
-       status = usb_control_msg(udev, pipe, request, reqtype, value, index,
-                                pdata, len, 0); /* max. timeout */
+       do {
+               status = usb_control_msg(udev, pipe, request, reqtype, value,
+                                        index, pdata, len, 0); /*max. timeout*/
+               if (status < 0) {
+                       /* firmware download is checksumed, don't retry */
+                       if ((value >= FW_8192C_START_ADDRESS &&
+                           value <= FW_8192C_END_ADDRESS))
+                               break;
+               } else {
+                       break;
+               }
+       } while (++vendorreq_times < MAX_USBCTRL_VENDORREQ_TIMES);
 
-       if (status < 0)
+       if (status < 0 && count++ < 4)
                pr_err("reg 0x%x, usbctrl_vendorreq TimeOut! status:0x%x value=0x%x\n",
-                      value, status, *(u32 *)pdata);
+                      value, status, le32_to_cpu(*(u32 *)pdata));
        return status;
 }
 
@@ -129,7 +143,7 @@ static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len)
 
        wvalue = (u16)addr;
        _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
-       ret = *data;
+       ret = le32_to_cpu(*data);
        kfree(data);
        return ret;
 }
@@ -161,12 +175,12 @@ static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
        u8 request;
        u16 wvalue;
        u16 index;
-       u32 data;
+       __le32 data;
 
        request = REALTEK_USB_VENQT_CMD_REQ;
        index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
        wvalue = (u16)(addr&0x0000ffff);
-       data = val;
+       data = cpu_to_le32(val);
        _usbctrl_vendorreq_async_write(udev, request, wvalue, index, &data,
                                       len);
 }
@@ -192,6 +206,30 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val)
        _usb_write_async(to_usb_device(dev), addr, val, 4);
 }
 
+static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data,
+                            u16 len)
+{
+       struct device *dev = rtlpriv->io.dev;
+       struct usb_device *udev = to_usb_device(dev);
+       u8 request = REALTEK_USB_VENQT_CMD_REQ;
+       u8 reqtype =  REALTEK_USB_VENQT_WRITE;
+       u16 wvalue;
+       u16 index = REALTEK_USB_VENQT_CMD_IDX;
+       int pipe = usb_sndctrlpipe(udev, 0); /* write_out */
+       u8 *buffer;
+       dma_addr_t dma_addr;
+
+       wvalue = (u16)(addr&0x0000ffff);
+       buffer = usb_alloc_coherent(udev, (size_t)len, GFP_ATOMIC, &dma_addr);
+       if (!buffer)
+               return;
+       memcpy(buffer, data, len);
+       usb_control_msg(udev, pipe, request, reqtype, wvalue,
+                       index, buffer, len, 50);
+
+       usb_free_coherent(udev, (size_t)len, buffer, dma_addr);
+}
+
 static void _rtl_usb_io_handler_init(struct device *dev,
                                     struct ieee80211_hw *hw)
 {
@@ -205,6 +243,7 @@ static void _rtl_usb_io_handler_init(struct device *dev,
        rtlpriv->io.read8_sync          = _usb_read8_sync;
        rtlpriv->io.read16_sync         = _usb_read16_sync;
        rtlpriv->io.read32_sync         = _usb_read32_sync;
+       rtlpriv->io.writeN_sync         = _usb_writeN_sync;
 }
 
 static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
index 713c7ddba8eb6e8c9a55a7e1b913f3e3916b6891..f3c132b55d42b5ada63c3a25761c8958fc935952 100644 (file)
@@ -63,6 +63,7 @@
 #define AC_MAX                                 4
 #define QOS_QUEUE_NUM                          4
 #define RTL_MAC80211_NUM_QUEUE                 5
+#define REALTEK_USB_VENQT_MAX_BUF_SIZE         254
 
 #define QBSS_LOAD_SIZE                         5
 #define MAX_WMMELE_LENGTH                      64
@@ -943,8 +944,10 @@ struct rtl_io {
        unsigned long pci_base_addr;    /*device I/O address */
 
        void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val);
-       void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, __le16 val);
-       void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, __le32 val);
+       void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val);
+       void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val);
+       void (*writeN_sync) (struct rtl_priv *rtlpriv, u32 addr, void *buf,
+                            u16 len);
 
        u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr);
        u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr);
index f9261c253735b362f22769f38aa4519f984118c3..97bfebfcce903b5165b64bd839b60379e23ecc78 100644 (file)
@@ -1169,6 +1169,21 @@ enum nl80211_commands {
  * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire
  *     probe-response frame. The DA field in the 802.11 header is zero-ed out,
  *     to be filled by the FW.
+ * @NL80211_ATTR_DISABLE_HT:  Force HT capable interfaces to disable
+ *      this feature.  Currently, only supported in mac80211 drivers.
+ * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the
+ *      ATTR_HT_CAPABILITY to which attention should be paid.
+ *      Currently, only mac80211 NICs support this feature.
+ *      The values that may be configured are:
+ *       MCS rates, MAX-AMSDU, HT-20-40 and HT_CAP_SGI_40
+ *       AMPDU density and AMPDU factor.
+ *      All values are treated as suggestions and may be ignored
+ *      by the driver as required.  The actual values may be seen in
+ *      the station debugfs ht_caps file.
+ *
+ * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country
+ *    abides to when initiating radiation on DFS channels. A country maps
+ *    to one DFS region.
  *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -1408,6 +1423,11 @@ enum nl80211_attrs {
 
        NL80211_ATTR_PROBE_RESP,
 
+       NL80211_ATTR_DFS_REGION,
+
+       NL80211_ATTR_DISABLE_HT,
+       NL80211_ATTR_HT_CAPABILITY_MASK,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -1916,6 +1936,21 @@ enum nl80211_reg_rule_flags {
        NL80211_RRF_NO_IBSS             = 1<<8,
 };
 
+/**
+ * enum nl80211_dfs_regions - regulatory DFS regions
+ *
+ * @NL80211_DFS_UNSET: Country has no DFS master region specified
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from FCC
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from ETSI
+ * @NL80211_DFS_JP_: Country follows DFS master rules from JP/MKK/Telec
+ */
+enum nl80211_dfs_regions {
+       NL80211_DFS_UNSET       = 0,
+       NL80211_DFS_FCC         = 1,
+       NL80211_DFS_ETSI        = 2,
+       NL80211_DFS_JP          = 3,
+};
+
 /**
  * enum nl80211_survey_info - survey information
  *
index 8d7ba0961d3e694115f60b7c17dbaadc396b93b0..d5e18913f293af6eb2329e1ee4a88bc0cd9383c8 100644 (file)
@@ -1043,6 +1043,15 @@ struct cfg80211_auth_request {
        bool local_state_change;
 };
 
+/**
+ * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association.
+ *
+ * @ASSOC_REQ_DISABLE_HT:  Disable HT (802.11n)
+ */
+enum cfg80211_assoc_req_flags {
+       ASSOC_REQ_DISABLE_HT            = BIT(0),
+};
+
 /**
  * struct cfg80211_assoc_request - (Re)Association request data
  *
@@ -1054,6 +1063,10 @@ struct cfg80211_auth_request {
  * @use_mfp: Use management frame protection (IEEE 802.11w) in this association
  * @crypto: crypto settings
  * @prev_bssid: previous BSSID, if not %NULL use reassociate frame
+ * @flags:  See &enum cfg80211_assoc_req_flags
+ * @ht_capa:  HT Capabilities over-rides.  Values set in ht_capa_mask
+ *   will be used in ht_capa.  Un-supported values will be ignored.
+ * @ht_capa_mask:  The bits of ht_capa which are to be used.
  */
 struct cfg80211_assoc_request {
        struct cfg80211_bss *bss;
@@ -1061,6 +1074,9 @@ struct cfg80211_assoc_request {
        size_t ie_len;
        struct cfg80211_crypto_settings crypto;
        bool use_mfp;
+       u32 flags;
+       struct ieee80211_ht_cap ht_capa;
+       struct ieee80211_ht_cap ht_capa_mask;
 };
 
 /**
@@ -1159,6 +1175,10 @@ struct cfg80211_ibss_params {
  * @key_len: length of WEP key for shared key authentication
  * @key_idx: index of WEP key for shared key authentication
  * @key: WEP key for shared key authentication
+ * @flags:  See &enum cfg80211_assoc_req_flags
+ * @ht_capa:  HT Capabilities over-rides.  Values set in ht_capa_mask
+ *   will be used in ht_capa.  Un-supported values will be ignored.
+ * @ht_capa_mask:  The bits of ht_capa which are to be used.
  */
 struct cfg80211_connect_params {
        struct ieee80211_channel *channel;
@@ -1172,6 +1192,9 @@ struct cfg80211_connect_params {
        struct cfg80211_crypto_settings crypto;
        const u8 *key;
        u8 key_len, key_idx;
+       u32 flags;
+       struct ieee80211_ht_cap ht_capa;
+       struct ieee80211_ht_cap ht_capa_mask;
 };
 
 /**
@@ -1700,6 +1723,8 @@ struct cfg80211_ops {
  *     cfg80211_report_obss_beacon().
  * @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD: When operating as an AP, the device
  *     responds to probe-requests in hardware.
+ * @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX.
+ * @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call.
  */
 enum wiphy_flags {
        WIPHY_FLAG_CUSTOM_REGULATORY            = BIT(0),
@@ -1721,6 +1746,8 @@ enum wiphy_flags {
        WIPHY_FLAG_HAVE_AP_SME                  = BIT(17),
        WIPHY_FLAG_REPORTS_OBSS                 = BIT(18),
        WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD        = BIT(19),
+       WIPHY_FLAG_OFFCHAN_TX                   = BIT(20),
+       WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL        = BIT(21),
 };
 
 /**
@@ -1934,6 +1961,8 @@ struct wiphy_wowlan_support {
  * @wowlan: WoWLAN support information
  *
  * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
+ * @ht_capa_mod_mask:  Specify what ht_cap values can be over-ridden.
+ *     If null, then none can be over-ridden.
  */
 struct wiphy {
        /* assign these fields before you register the wiphy */
@@ -2023,6 +2052,8 @@ struct wiphy {
        /* dir in debugfs: ieee80211/<wiphyname> */
        struct dentry *debugfsdir;
 
+       const struct ieee80211_ht_cap *ht_capa_mod_mask;
+
 #ifdef CONFIG_NET_NS
        /* the network namespace this phy lives in currently */
        struct net *_net;
@@ -2387,69 +2418,6 @@ extern int ieee80211_radiotap_iterator_next(
 extern const unsigned char rfc1042_header[6];
 extern const unsigned char bridge_tunnel_header[6];
 
-/* Parsed Information Elements */
-struct ieee802_11_elems {
-       u8 *ie_start;
-       size_t total_len;
-
-       /* pointers to IEs */
-       u8 *ssid;
-       u8 *supp_rates;
-       u8 *fh_params;
-       u8 *ds_params;
-       u8 *cf_params;
-       struct ieee80211_tim_ie *tim;
-       u8 *ibss_params;
-       u8 *challenge;
-       u8 *wpa;
-       u8 *rsn;
-       u8 *erp_info;
-       u8 *ext_supp_rates;
-       u8 *wmm_info;
-       u8 *wmm_param;
-       struct ieee80211_ht_cap *ht_cap_elem;
-       struct ieee80211_ht_info *ht_info_elem;
-       struct ieee80211_meshconf_ie *mesh_config;
-       u8 *mesh_id;
-       u8 *peering;
-       u8 *preq;
-       u8 *prep;
-       u8 *perr;
-       struct ieee80211_rann_ie *rann;
-       u8 *ch_switch_elem;
-       u8 *country_elem;
-       u8 *pwr_constr_elem;
-       u8 *quiet_elem; /* first quite element */
-       u8 *timeout_int;
-
-       /* length of them, respectively */
-       u8 ssid_len;
-       u8 supp_rates_len;
-       u8 fh_params_len;
-       u8 ds_params_len;
-       u8 cf_params_len;
-       u8 tim_len;
-       u8 ibss_params_len;
-       u8 challenge_len;
-       u8 wpa_len;
-       u8 rsn_len;
-       u8 erp_info_len;
-       u8 ext_supp_rates_len;
-       u8 wmm_info_len;
-       u8 wmm_param_len;
-       u8 mesh_id_len;
-       u8 peering_len;
-       u8 preq_len;
-       u8 prep_len;
-       u8 perr_len;
-       u8 ch_switch_elem_len;
-       u8 country_elem_len;
-       u8 pwr_constr_elem_len;
-       u8 quiet_elem_len;
-       u8 num_of_quiet_elem;   /* can be more the one */
-       u8 timeout_int_len;
-};
-
 /**
  * ieee80211_get_hdrlen_from_skb - get header length from data
  *
index 0756049ae76d69c2a8cb9e2342deb868cefeaf94..5b5c8a7e26d7756923fa285784acbf257f4e8938 100644 (file)
@@ -1760,11 +1760,21 @@ enum ieee80211_frame_release_type {
  *     skb contains the buffer starting from the IEEE 802.11 header.
  *     The low-level driver should send the frame out based on
  *     configuration in the TX control data. This handler should,
- *     preferably, never fail and stop queues appropriately, more
- *     importantly, however, it must never fail for A-MPDU-queues.
- *     This function should return NETDEV_TX_OK except in very
- *     limited cases.
- *     Must be implemented and atomic.
+ *     preferably, never fail and stop queues appropriately.
+ *     This must be implemented if @tx_frags is not.
+ *     Must be atomic.
+ *
+ * @tx_frags: Called to transmit multiple fragments of a single MSDU.
+ *     This handler must consume all fragments, sending out some of
+ *     them only is useless and it can't ask for some of them to be
+ *     queued again. If the frame is not fragmented the queue has a
+ *     single SKB only. To avoid issues with the networking stack
+ *     when TX status is reported the frames should be removed from
+ *     the skb queue.
+ *     If this is used, the tx_info @vif and @sta pointers will be
+ *     invalid -- you must not use them in that case.
+ *     This must be implemented if @tx isn't.
+ *     Must be atomic.
  *
  * @start: Called before the first netdevice attached to the hardware
  *     is enabled. This should turn on the hardware and must turn on
@@ -2101,6 +2111,8 @@ enum ieee80211_frame_release_type {
  */
 struct ieee80211_ops {
        void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
+       void (*tx_frags)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                        struct ieee80211_sta *sta, struct sk_buff_head *skbs);
        int (*start)(struct ieee80211_hw *hw);
        void (*stop)(struct ieee80211_hw *hw);
 #ifdef CONFIG_PM
index cdbe671393432e92015920e9827c9614ace17666..b61eb6c9df14f81d6275fd7039f82b42fcce3930 100644 (file)
 #define NCI_MAX_NUM_CONN                                       10
 
 /* NCI Status Codes */
-#define        NCI_STATUS_OK                                           0x00
-#define        NCI_STATUS_REJECTED                                     0x01
-#define        NCI_STATUS_RF_FRAME_CORRUPTED                           0x02
-#define        NCI_STATUS_FAILED                                       0x03
-#define        NCI_STATUS_NOT_INITIALIZED                              0x04
-#define        NCI_STATUS_SYNTAX_ERROR                                 0x05
-#define        NCI_STATUS_SEMANTIC_ERROR                               0x06
-#define        NCI_STATUS_UNKNOWN_GID                                  0x07
-#define        NCI_STATUS_UNKNOWN_OID                                  0x08
-#define        NCI_STATUS_INVALID_PARAM                                0x09
-#define        NCI_STATUS_MESSAGE_SIZE_EXCEEDED                        0x0a
+#define NCI_STATUS_OK                                          0x00
+#define NCI_STATUS_REJECTED                                    0x01
+#define NCI_STATUS_RF_FRAME_CORRUPTED                          0x02
+#define NCI_STATUS_FAILED                                      0x03
+#define NCI_STATUS_NOT_INITIALIZED                             0x04
+#define NCI_STATUS_SYNTAX_ERROR                                        0x05
+#define NCI_STATUS_SEMANTIC_ERROR                              0x06
+#define NCI_STATUS_UNKNOWN_GID                                 0x07
+#define NCI_STATUS_UNKNOWN_OID                                 0x08
+#define NCI_STATUS_INVALID_PARAM                               0x09
+#define NCI_STATUS_MESSAGE_SIZE_EXCEEDED                       0x0a
 /* Discovery Specific Status Codes */
-#define        NCI_STATUS_DISCOVERY_ALREADY_STARTED                    0xa0
-#define        NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED           0xa1
-#define        NCI_STATUS_DISCOVERY_TEAR_DOWN                          0xa2
+#define NCI_STATUS_DISCOVERY_ALREADY_STARTED                   0xa0
+#define NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED          0xa1
+#define NCI_STATUS_DISCOVERY_TEAR_DOWN                         0xa2
 /* RF Interface Specific Status Codes */
-#define        NCI_STATUS_RF_TRANSMISSION_ERROR                        0xb0
-#define        NCI_STATUS_RF_PROTOCOL_ERROR                            0xb1
-#define        NCI_STATUS_RF_TIMEOUT_ERROR                             0xb2
+#define NCI_STATUS_RF_TRANSMISSION_ERROR                       0xb0
+#define NCI_STATUS_RF_PROTOCOL_ERROR                           0xb1
+#define NCI_STATUS_RF_TIMEOUT_ERROR                            0xb2
 /* NFCEE Interface Specific Status Codes */
-#define        NCI_STATUS_MAX_ACTIVE_NFCEE_INTERFACES_REACHED          0xc0
-#define        NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED            0xc1
-#define        NCI_STATUS_NFCEE_TRANSMISSION_ERROR                     0xc2
-#define        NCI_STATUS_NFCEE_PROTOCOL_ERROR                         0xc3
+#define NCI_STATUS_MAX_ACTIVE_NFCEE_INTERFACES_REACHED         0xc0
+#define NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED           0xc1
+#define NCI_STATUS_NFCEE_TRANSMISSION_ERROR                    0xc2
+#define NCI_STATUS_NFCEE_PROTOCOL_ERROR                                0xc3
 #define NCI_STATUS_NFCEE_TIMEOUT_ERROR                         0xc4
 
 /* NCI RF Technology and Mode */
@@ -97,9 +97,9 @@
 
 /* NCI RF Interfaces */
 #define NCI_RF_INTERFACE_NFCEE_DIRECT                          0x00
-#define        NCI_RF_INTERFACE_FRAME                                  0x01
-#define        NCI_RF_INTERFACE_ISO_DEP                                0x02
-#define        NCI_RF_INTERFACE_NFC_DEP                                0x03
+#define NCI_RF_INTERFACE_FRAME                                 0x01
+#define NCI_RF_INTERFACE_ISO_DEP                               0x02
+#define NCI_RF_INTERFACE_NFC_DEP                               0x03
 
 /* NCI Reset types */
 #define NCI_RESET_TYPE_KEEP_CONFIG                             0x00
 
 /* NCI Discovery Types */
 #define NCI_DISCOVERY_TYPE_POLL_A_PASSIVE                      0x00
-#define        NCI_DISCOVERY_TYPE_POLL_B_PASSIVE                       0x01
-#define        NCI_DISCOVERY_TYPE_POLL_F_PASSIVE                       0x02
-#define        NCI_DISCOVERY_TYPE_POLL_A_ACTIVE                        0x03
-#define        NCI_DISCOVERY_TYPE_POLL_F_ACTIVE                        0x05
-#define        NCI_DISCOVERY_TYPE_WAKEUP_A_ACTIVE                      0x09
-#define        NCI_DISCOVERY_TYPE_LISTEN_A_PASSIVE                     0x80
-#define        NCI_DISCOVERY_TYPE_LISTEN_B_PASSIVE                     0x81
-#define        NCI_DISCOVERY_TYPE_LISTEN_F_PASSIVE                     0x82
-#define        NCI_DISCOVERY_TYPE_LISTEN_A_ACTIVE                      0x83
-#define        NCI_DISCOVERY_TYPE_LISTEN_F_ACTIVE                      0x85
+#define NCI_DISCOVERY_TYPE_POLL_B_PASSIVE                      0x01
+#define NCI_DISCOVERY_TYPE_POLL_F_PASSIVE                      0x02
+#define NCI_DISCOVERY_TYPE_POLL_A_ACTIVE                       0x03
+#define NCI_DISCOVERY_TYPE_POLL_F_ACTIVE                       0x05
+#define NCI_DISCOVERY_TYPE_WAKEUP_A_ACTIVE                     0x09
+#define NCI_DISCOVERY_TYPE_LISTEN_A_PASSIVE                    0x80
+#define NCI_DISCOVERY_TYPE_LISTEN_B_PASSIVE                    0x81
+#define NCI_DISCOVERY_TYPE_LISTEN_F_PASSIVE                    0x82
+#define NCI_DISCOVERY_TYPE_LISTEN_A_ACTIVE                     0x83
+#define NCI_DISCOVERY_TYPE_LISTEN_F_ACTIVE                     0x85
 
 /* NCI Deactivation Type */
-#define        NCI_DEACTIVATE_TYPE_IDLE_MODE                           0x00
-#define        NCI_DEACTIVATE_TYPE_SLEEP_MODE                          0x01
-#define        NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE                       0x02
-#define        NCI_DEACTIVATE_TYPE_DISCOVERY                           0x03
+#define NCI_DEACTIVATE_TYPE_IDLE_MODE                          0x00
+#define NCI_DEACTIVATE_TYPE_SLEEP_MODE                         0x01
+#define NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE                      0x02
+#define NCI_DEACTIVATE_TYPE_DISCOVERY                          0x03
 
 /* Message Type (MT) */
 #define NCI_MT_DATA_PKT                                                0x00
 #define nci_conn_id(hdr)               (__u8)(((hdr)[0])&0x0f)
 
 /* GID values */
-#define        NCI_GID_CORE                                            0x0
-#define        NCI_GID_RF_MGMT                                         0x1
-#define        NCI_GID_NFCEE_MGMT                                      0x2
-#define        NCI_GID_PROPRIETARY                                     0xf
+#define NCI_GID_CORE                                           0x0
+#define NCI_GID_RF_MGMT                                                0x1
+#define NCI_GID_NFCEE_MGMT                                     0x2
+#define NCI_GID_PROPRIETARY                                    0xf
 
 /* ---- NCI Packet structures ---- */
 #define NCI_CTRL_HDR_SIZE                                      3
index eb7d3c2d427480d8c9bb77723386681cdc6c1b35..a5f79933e211216668a9b4cf573e73ec2e26d912 100644 (file)
@@ -48,6 +48,10 @@ enum environment_cap {
  *     99 - built by driver but a specific alpha2 cannot be determined
  *     98 - result of an intersection between two regulatory domains
  *     97 - regulatory domain has not yet been configured
+ * @dfs_region: If CRDA responded with a regulatory domain that requires
+ *     DFS master operation on a known DFS region (NL80211_DFS_*),
+ *     dfs_region represents that region. Drivers can use this and the
+ *     @alpha2 to adjust their device's DFS parameters as required.
  * @intersect: indicates whether the wireless core should intersect
  *     the requested regulatory domain with the presently set regulatory
  *     domain.
@@ -67,6 +71,7 @@ struct regulatory_request {
        int wiphy_idx;
        enum nl80211_reg_initiator initiator;
        char alpha2[2];
+       u8 dfs_region;
        bool intersect;
        bool processed;
        enum environment_cap country_ie_env;
@@ -93,6 +98,7 @@ struct ieee80211_reg_rule {
 struct ieee80211_regdomain {
        u32 n_reg_rules;
        char alpha2[2];
+       u8 dfs_region;
        struct ieee80211_reg_rule reg_rules[];
 };
 
index 1063a7e57d62a9d2cf68e965e71152c9f1eb3033..2577c45069e5d779373646dc0c760164914ad0d5 100644 (file)
@@ -832,7 +832,7 @@ static void sta_apply_parameters(struct ieee80211_local *local,
        }
 
        if (params->ht_capa)
-               ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+               ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
                                                  params->ht_capa,
                                                  &sta->sta.ht_cap);
 
index 3110cbdc501b83d3650c978d26c51c2ef7c47568..2406b3e7393fb042d8ec82b417c7e985a0801fa2 100644 (file)
@@ -63,10 +63,10 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
        test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
 
        int res = scnprintf(buf, sizeof(buf),
-                           "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+                           "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                            TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
                            TEST(PS_DRIVER), TEST(AUTHORIZED),
-                           TEST(SHORT_PREAMBLE), TEST(ASSOC_AP),
+                           TEST(SHORT_PREAMBLE),
                            TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
                            TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
                            TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
index b12ed52732c814b976bfc0084e680782faf5442d..49cc5e0e8a6af67a5c733c6cff07155f9e5b69fd 100644 (file)
@@ -15,6 +15,14 @@ static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
        local->ops->tx(&local->hw, skb);
 }
 
+static inline void drv_tx_frags(struct ieee80211_local *local,
+                               struct ieee80211_vif *vif,
+                               struct ieee80211_sta *sta,
+                               struct sk_buff_head *skbs)
+{
+       local->ops->tx_frags(&local->hw, vif, sta, skbs);
+}
+
 static inline int drv_start(struct ieee80211_local *local)
 {
        int ret;
index d06975098aad49b4ff9334d8b775b0227d7671ef..810cfbea6ad1c77028fcbf54a428753b85a202a8 100644 (file)
 #include "ieee80211_i.h"
 #include "rate.h"
 
-void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
+bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata)
+{
+       const __le16 flg = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40);
+       if ((sdata->u.mgd.ht_capa_mask.cap_info & flg) &&
+           !(sdata->u.mgd.ht_capa.cap_info & flg))
+               return true;
+       return false;
+}
+
+void __check_htcap_disable(struct ieee80211_sub_if_data *sdata,
+                          struct ieee80211_sta_ht_cap *ht_cap,
+                          u16 flag)
+{
+       __le16 le_flag = cpu_to_le16(flag);
+       if (sdata->u.mgd.ht_capa_mask.cap_info & le_flag) {
+               if (!(sdata->u.mgd.ht_capa.cap_info & le_flag))
+                       ht_cap->cap &= ~flag;
+       }
+}
+
+void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
+                                    struct ieee80211_sta_ht_cap *ht_cap)
+{
+       u8 *scaps = (u8 *)(&sdata->u.mgd.ht_capa.mcs.rx_mask);
+       u8 *smask = (u8 *)(&sdata->u.mgd.ht_capa_mask.mcs.rx_mask);
+       int i;
+
+       if (sdata->vif.type != NL80211_IFTYPE_STATION) {
+               WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
+               return;
+       }
+
+       /* NOTE:  If you add more over-rides here, update register_hw
+        * ht_capa_mod_msk logic in main.c as well.
+        * And, if this method can ever change ht_cap.ht_supported, fix
+        * the check in ieee80211_add_ht_ie.
+        */
+
+       /* check for HT over-rides, MCS rates first. */
+       for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
+               u8 m = smask[i];
+               ht_cap->mcs.rx_mask[i] &= ~m; /* turn off all masked bits */
+               /* Add back rates that are supported */
+               ht_cap->mcs.rx_mask[i] |= (m & scaps[i]);
+       }
+
+       /* Force removal of HT-40 capabilities? */
+       __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SUP_WIDTH_20_40);
+       __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_40);
+
+       /* Allow user to disable the max-AMSDU bit. */
+       __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_MAX_AMSDU);
+
+       /* Allow user to decrease AMPDU factor */
+       if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
+           IEEE80211_HT_AMPDU_PARM_FACTOR) {
+               u8 n = sdata->u.mgd.ht_capa.ampdu_params_info
+                       & IEEE80211_HT_AMPDU_PARM_FACTOR;
+               if (n < ht_cap->ampdu_factor)
+                       ht_cap->ampdu_factor = n;
+       }
+
+       /* Allow the user to increase AMPDU density. */
+       if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
+           IEEE80211_HT_AMPDU_PARM_DENSITY) {
+               u8 n = (sdata->u.mgd.ht_capa.ampdu_params_info &
+                       IEEE80211_HT_AMPDU_PARM_DENSITY)
+                       >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
+               if (n > ht_cap->ampdu_density)
+                       ht_cap->ampdu_density = n;
+       }
+}
+
+
+void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
+                                      struct ieee80211_supported_band *sband,
                                       struct ieee80211_ht_cap *ht_cap_ie,
                                       struct ieee80211_sta_ht_cap *ht_cap)
 {
@@ -103,6 +178,12 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
        /* handle MCS rate 32 too */
        if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
                ht_cap->mcs.rx_mask[32/8] |= 1;
+
+       /*
+        * If user has specified capability over-rides, take care
+        * of that here.
+        */
+       ieee80211_apply_htcap_overrides(sdata, ht_cap);
 }
 
 void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx)
index 068cc92d16aa8dea3f33ce2b7793f87aa7407798..762243e469dfde36d78035b48554cb9361d23e43 100644 (file)
@@ -142,6 +142,7 @@ typedef unsigned __bitwise__ ieee80211_tx_result;
 
 struct ieee80211_tx_data {
        struct sk_buff *skb;
+       struct sk_buff_head skbs;
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
        struct sta_info *sta;
@@ -448,6 +449,9 @@ struct ieee80211_if_managed {
         */
        int rssi_min_thold, rssi_max_thold;
        int last_ave_beacon_signal;
+
+       struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */
+       struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */
 };
 
 struct ieee80211_if_ibss {
@@ -1039,6 +1043,69 @@ struct ieee80211_ra_tid {
        u16 tid;
 };
 
+/* Parsed Information Elements */
+struct ieee802_11_elems {
+       u8 *ie_start;
+       size_t total_len;
+
+       /* pointers to IEs */
+       u8 *ssid;
+       u8 *supp_rates;
+       u8 *fh_params;
+       u8 *ds_params;
+       u8 *cf_params;
+       struct ieee80211_tim_ie *tim;
+       u8 *ibss_params;
+       u8 *challenge;
+       u8 *wpa;
+       u8 *rsn;
+       u8 *erp_info;
+       u8 *ext_supp_rates;
+       u8 *wmm_info;
+       u8 *wmm_param;
+       struct ieee80211_ht_cap *ht_cap_elem;
+       struct ieee80211_ht_info *ht_info_elem;
+       struct ieee80211_meshconf_ie *mesh_config;
+       u8 *mesh_id;
+       u8 *peering;
+       u8 *preq;
+       u8 *prep;
+       u8 *perr;
+       struct ieee80211_rann_ie *rann;
+       u8 *ch_switch_elem;
+       u8 *country_elem;
+       u8 *pwr_constr_elem;
+       u8 *quiet_elem; /* first quite element */
+       u8 *timeout_int;
+
+       /* length of them, respectively */
+       u8 ssid_len;
+       u8 supp_rates_len;
+       u8 fh_params_len;
+       u8 ds_params_len;
+       u8 cf_params_len;
+       u8 tim_len;
+       u8 ibss_params_len;
+       u8 challenge_len;
+       u8 wpa_len;
+       u8 rsn_len;
+       u8 erp_info_len;
+       u8 ext_supp_rates_len;
+       u8 wmm_info_len;
+       u8 wmm_param_len;
+       u8 mesh_id_len;
+       u8 peering_len;
+       u8 preq_len;
+       u8 prep_len;
+       u8 perr_len;
+       u8 ch_switch_elem_len;
+       u8 country_elem_len;
+       u8 pwr_constr_elem_len;
+       u8 quiet_elem_len;
+       u8 num_of_quiet_elem;   /* can be more the one */
+       u8 timeout_int_len;
+};
+
 static inline struct ieee80211_local *hw_to_local(
        struct ieee80211_hw *hw)
 {
@@ -1188,7 +1255,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                                       struct net_device *dev);
 
 /* HT */
-void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
+bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata);
+void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
+                                    struct ieee80211_sta_ht_cap *ht_cap);
+void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
+                                      struct ieee80211_supported_band *sband,
                                       struct ieee80211_ht_cap *ht_cap_ie,
                                       struct ieee80211_sta_ht_cap *ht_cap);
 void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
@@ -1343,7 +1414,7 @@ void ieee80211_recalc_smps(struct ieee80211_local *local);
 size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
                          const u8 *ids, int n_ids, size_t offset);
 size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
-u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
                              u16 cap);
 u8 *ieee80211_ie_build_ht_info(u8 *pos,
                                struct ieee80211_sta_ht_cap *ht_cap,
index 12a6d4bb5d3736b348996bac224b43d5651873a1..b34ca0cbdf6cef9c06f013f010abe3087c700e00 100644 (file)
@@ -474,7 +474,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL);
                synchronize_rcu();
                kfree(old_beacon);
-               kfree(old_probe_resp);
+               kfree_skb(old_probe_resp);
 
                /* down all dependent devices, that is VLANs */
                list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
index e323d4e6647bd702ab0a5f0a63e5d1dbfc4fed7d..dddedfad5404e8700ebb675206753c9c6f438bd9 100644 (file)
@@ -558,6 +558,19 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
        },
 };
 
+static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
+       .ampdu_params_info = IEEE80211_HT_AMPDU_PARM_FACTOR |
+                            IEEE80211_HT_AMPDU_PARM_DENSITY,
+
+       .cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+                               IEEE80211_HT_CAP_MAX_AMSDU |
+                               IEEE80211_HT_CAP_SGI_40),
+       .mcs = {
+               .rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff,
+                            0xff, 0xff, 0xff, 0xff, 0xff, },
+       },
+};
+
 struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
                                        const struct ieee80211_ops *ops)
 {
@@ -594,7 +607,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        wiphy->flags |= WIPHY_FLAG_NETNS_OK |
                        WIPHY_FLAG_4ADDR_AP |
                        WIPHY_FLAG_4ADDR_STATION |
-                       WIPHY_FLAG_REPORTS_OBSS;
+                       WIPHY_FLAG_REPORTS_OBSS |
+                       WIPHY_FLAG_OFFCHAN_TX |
+                       WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
 
        wiphy->features = NL80211_FEATURE_SK_TX_STATUS;
 
@@ -609,7 +624,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 
        local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
 
-       BUG_ON(!ops->tx);
+       BUG_ON(!ops->tx && !ops->tx_frags);
        BUG_ON(!ops->start);
        BUG_ON(!ops->stop);
        BUG_ON(!ops->config);
@@ -629,6 +644,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        local->user_power_level = -1;
        local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
        local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+       wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
 
        INIT_LIST_HEAD(&local->interfaces);
 
index b3a125f60347d47a9b474bdde83291611a3e505a..ee82d2f7f11409e2dc91559ddac5027a01b16b1b 100644 (file)
@@ -366,7 +366,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb,
                return -ENOMEM;
 
        pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap));
-       ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
+       ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, sband->ht_cap.cap);
 
        return 0;
 }
index a7afb2d32def7bfe308566b0147328827eb80067..ce3db2735d7c3a3685af102fd03a22d331a98ede 100644 (file)
@@ -867,10 +867,11 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
                return;
        }
 
-       spin_lock_bh(&mpath->state_lock);
+       spin_lock(&mpath->state_lock);
        if (mpath->flags & MESH_PATH_REQ_QUEUED) {
-               spin_unlock_bh(&mpath->state_lock);
+               spin_unlock(&mpath->state_lock);
                spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
+               kfree(preq_node);
                return;
        }
 
@@ -878,7 +879,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
        preq_node->flags = flags;
 
        mpath->flags |= MESH_PATH_REQ_QUEUED;
-       spin_unlock_bh(&mpath->state_lock);
+       spin_unlock(&mpath->state_lock);
 
        list_add_tail(&preq_node->list, &ifmsh->preq_queue.list);
        ++ifmsh->preq_queue_len;
index 4fc23d1b9c3af921036643d6ed7f242e817685ce..7bd2a76aef0ec7b56cb0117ff6b5a06feecfcb54 100644 (file)
@@ -69,8 +69,6 @@ static inline struct mesh_table *resize_dereference_mpp_paths(void)
                lockdep_is_held(&pathtbl_resize_lock));
 }
 
-static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath);
-
 /*
  * CAREFUL -- "tbl" must not be an expression,
  * in particular not an rcu_dereference(), since
@@ -420,21 +418,18 @@ static void mesh_gate_node_reclaim(struct rcu_head *rp)
 }
 
 /**
- * mesh_gate_add - mark mpath as path to a mesh gate and add to known_gates
- * @mesh_tbl: table which contains known_gates list
- * @mpath: mpath to known mesh gate
- *
- * Returns: 0 on success
- *
+ * mesh_path_add_gate - add the given mpath to a mesh gate to our path table
+ * @mpath: gate path to add to table
  */
-static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath)
+int mesh_path_add_gate(struct mesh_path *mpath)
 {
+       struct mesh_table *tbl;
        struct mpath_node *gate, *new_gate;
        struct hlist_node *n;
        int err;
 
        rcu_read_lock();
-       tbl = rcu_dereference(tbl);
+       tbl = rcu_dereference(mesh_paths);
 
        hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list)
                if (gate->mpath == mpath) {
@@ -478,8 +473,6 @@ static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath)
        struct mpath_node *gate;
        struct hlist_node *p, *q;
 
-       tbl = rcu_dereference(tbl);
-
        hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list)
                if (gate->mpath == mpath) {
                        spin_lock_bh(&tbl->gates_lock);
@@ -497,16 +490,6 @@ static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath)
        return 0;
 }
 
-/**
- *
- * mesh_path_add_gate - add the given mpath to a mesh gate to our path table
- * @mpath: gate path to add to table
- */
-int mesh_path_add_gate(struct mesh_path *mpath)
-{
-       return mesh_gate_add(mesh_paths, mpath);
-}
-
 /**
  * mesh_gate_num - number of gates known to this interface
  * @sdata: subif data
index 0140e88a8220ce2f4c25c4758b6c555c2436b180..7314372b12ba2eb2096a749737ae05434be2e8bb 100644 (file)
@@ -101,7 +101,8 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
        set_sta_flag(sta, WLAN_STA_WME);
        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
        if (elems->ht_cap_elem)
-               ieee80211_ht_cap_ie_to_sta_ht_cap(sband, elems->ht_cap_elem,
+               ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
+                                                 elems->ht_cap_elem,
                                                  &sta->sta.ht_cap);
        rate_control_rate_init(sta);
 
index f9ec15b3fe096dcb2a96682193dc01f7801dcb20..09019d135942af5042175b0955a6147af464e84d 100644 (file)
@@ -209,6 +209,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
                channel_type = NL80211_CHAN_HT20;
 
                if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
+                   !ieee80111_cfg_override_disables_ht40(sdata) &&
                    (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
                    (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
                        switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
@@ -1120,6 +1121,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
        /* on the next assoc, re-program HT parameters */
        sdata->ht_opmode_valid = false;
+       memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
+       memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
 
        local->power_constr_level = 0;
 
@@ -1359,9 +1362,6 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
        ieee80211_set_disassoc(sdata, true, true);
        mutex_unlock(&ifmgd->mtx);
 
-       mutex_lock(&local->mtx);
-       ieee80211_recalc_idle(local);
-       mutex_unlock(&local->mtx);
        /*
         * must be outside lock due to cfg80211,
         * but that's not a problem.
@@ -1370,6 +1370,10 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
                                       IEEE80211_STYPE_DEAUTH,
                                       WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
                                       NULL, true);
+
+       mutex_lock(&local->mtx);
+       ieee80211_recalc_idle(local);
+       mutex_unlock(&local->mtx);
 }
 
 void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@ -1575,7 +1579,6 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
 
        set_sta_flag(sta, WLAN_STA_AUTH);
        set_sta_flag(sta, WLAN_STA_ASSOC);
-       set_sta_flag(sta, WLAN_STA_ASSOC_AP);
        if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
                set_sta_flag(sta, WLAN_STA_AUTHORIZED);
 
@@ -1613,7 +1616,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
                sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
 
        if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
-               ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+               ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
                                elems.ht_cap_elem, &sta->sta.ht_cap);
 
        ap_ht_cap_flags = sta->sta.ht_cap.cap;
@@ -1982,7 +1985,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 
                sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 
-               ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+               ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
                                elems.ht_cap_elem, &sta->sta.ht_cap);
 
                ap_ht_cap_flags = sta->sta.ht_cap.cap;
@@ -2136,9 +2139,6 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
 
        ieee80211_set_disassoc(sdata, true, true);
        mutex_unlock(&ifmgd->mtx);
-       mutex_lock(&local->mtx);
-       ieee80211_recalc_idle(local);
-       mutex_unlock(&local->mtx);
        /*
         * must be outside lock due to cfg80211,
         * but that's not a problem.
@@ -2146,6 +2146,11 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
        ieee80211_send_deauth_disassoc(sdata, bssid,
                        IEEE80211_STYPE_DEAUTH, reason,
                        NULL, true);
+
+       mutex_lock(&local->mtx);
+       ieee80211_recalc_idle(local);
+       mutex_unlock(&local->mtx);
+
        mutex_lock(&ifmgd->mtx);
 }
 
@@ -2640,6 +2645,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
                        ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
 
 
+       if (req->flags & ASSOC_REQ_DISABLE_HT)
+               ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+
+       memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
+       memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask,
+              sizeof(ifmgd->ht_capa_mask));
+
        if (req->ie && req->ie_len) {
                memcpy(wk->ie, req->ie, req->ie_len);
                wk->ie_len = req->ie_len;
index 3d414411a96e212ee7fc25247373b86d1d382072..ebd8cccac8f277184b14d0b990c80e6ef4b04d93 100644 (file)
@@ -212,8 +212,6 @@ static void ieee80211_hw_roc_start(struct work_struct *work)
                return;
        }
 
-       ieee80211_recalc_idle(local);
-
        if (local->hw_roc_skb) {
                sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev);
                ieee80211_tx_skb(sdata, local->hw_roc_skb);
@@ -227,6 +225,8 @@ static void ieee80211_hw_roc_start(struct work_struct *work)
                                          GFP_KERNEL);
        }
 
+       ieee80211_recalc_idle(local);
+
        mutex_unlock(&local->mtx);
 }
 
index cdb28535716b14d907d6423578c10db604d9c43f..ff5f7b84e825a37f925917a2a6488ddc5da38f3a 100644 (file)
 /* Transmit duration for the raw data part of an average sized packet */
 #define MCS_DURATION(streams, sgi, bps) MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps)))
 
+/*
+ * Define group sort order: HT40 -> SGI -> #streams
+ */
+#define GROUP_IDX(_streams, _sgi, _ht40)       \
+       MINSTREL_MAX_STREAMS * 2 * _ht40 +      \
+       MINSTREL_MAX_STREAMS * _sgi +           \
+       _streams - 1
+
 /* MCS rate information for an MCS group */
-#define MCS_GROUP(_streams, _sgi, _ht40) {                             \
+#define MCS_GROUP(_streams, _sgi, _ht40)                               \
+       [GROUP_IDX(_streams, _sgi, _ht40)] = {                          \
        .streams = _streams,                                            \
        .flags =                                                        \
                (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) |                 \
@@ -58,6 +67,9 @@
  * To enable sufficiently targeted rate sampling, MCS rates are divided into
  * groups, based on the number of streams and flags (HT40, SGI) that they
  * use.
+ *
+ * Sortorder has to be fixed for GROUP_IDX macro to be applicable:
+ * HT40 -> SGI -> #streams
  */
 const struct mcs_group minstrel_mcs_groups[] = {
        MCS_GROUP(1, 0, 0),
@@ -102,21 +114,9 @@ minstrel_ewma(int old, int new, int weight)
 static int
 minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
 {
-       int streams = (rate->idx / MCS_GROUP_RATES) + 1;
-       u32 flags = IEEE80211_TX_RC_SHORT_GI | IEEE80211_TX_RC_40_MHZ_WIDTH;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) {
-               if (minstrel_mcs_groups[i].streams != streams)
-                       continue;
-               if (minstrel_mcs_groups[i].flags != (rate->flags & flags))
-                       continue;
-
-               return i;
-       }
-
-       WARN_ON(1);
-       return 0;
+       return GROUP_IDX((rate->idx / MCS_GROUP_RATES) + 1,
+                        !!(rate->flags & IEEE80211_TX_RC_SHORT_GI),
+                        !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
 }
 
 static inline struct minstrel_rate_stats *
@@ -130,7 +130,7 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
  * Recalculate success probabilities and counters for a rate using EWMA
  */
 static void
-minstrel_calc_rate_ewma(struct minstrel_priv *mp, struct minstrel_rate_stats *mr)
+minstrel_calc_rate_ewma(struct minstrel_rate_stats *mr)
 {
        if (unlikely(mr->attempts > 0)) {
                mr->sample_skipped = 0;
@@ -156,8 +156,7 @@ minstrel_calc_rate_ewma(struct minstrel_priv *mp, struct minstrel_rate_stats *mr
  * the expected number of retransmissions and their expected length
  */
 static void
-minstrel_ht_calc_tp(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-                    int group, int rate)
+minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
 {
        struct minstrel_rate_stats *mr;
        unsigned int usecs;
@@ -226,8 +225,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
                        mr = &mg->rates[i];
                        mr->retry_updated = false;
                        index = MCS_GROUP_RATES * group + i;
-                       minstrel_calc_rate_ewma(mp, mr);
-                       minstrel_ht_calc_tp(mp, mi, group, i);
+                       minstrel_calc_rate_ewma(mr);
+                       minstrel_ht_calc_tp(mi, group, i);
 
                        if (!mr->cur_tp)
                                continue;
@@ -300,10 +299,10 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 static bool
 minstrel_ht_txstat_valid(struct ieee80211_tx_rate *rate)
 {
-       if (!rate->count)
+       if (rate->idx < 0)
                return false;
 
-       if (rate->idx < 0)
+       if (!rate->count)
                return false;
 
        return !!(rate->flags & IEEE80211_TX_RC_MCS);
@@ -357,7 +356,7 @@ minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
 }
 
 static void
-minstrel_aggr_check(struct minstrel_priv *mp, struct ieee80211_sta *pubsta, struct sk_buff *skb)
+minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
@@ -455,7 +454,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
        if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
                minstrel_ht_update_stats(mp, mi);
                if (!(info->flags & IEEE80211_TX_CTL_AMPDU))
-                       minstrel_aggr_check(mp, sta, skb);
+                       minstrel_aggr_check(sta, skb);
        }
 }
 
@@ -515,7 +514,6 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
 static void
 minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
                      struct ieee80211_tx_rate *rate, int index,
-                     struct ieee80211_tx_rate_control *txrc,
                      bool sample, bool rtscts)
 {
        const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
@@ -628,11 +626,11 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
        if (sample_idx >= 0) {
                sample = true;
                minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
-                       txrc, true, false);
+                       true, false);
                info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
        } else {
                minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
-                       txrc, false, false);
+                       false, false);
        }
 
        if (mp->hw->max_rates >= 3) {
@@ -643,13 +641,13 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
                 */
                if (sample_idx >= 0)
                        minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
-                               txrc, false, false);
+                               false, false);
                else
                        minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
-                               txrc, false, true);
+                               false, true);
 
                minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
-                                    txrc, false, !sample);
+                                    false, !sample);
 
                ar[3].count = 0;
                ar[3].idx = -1;
@@ -660,7 +658,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
                 * max_tp_rate -> max_prob_rate by default.
                 */
                minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
-                                    txrc, false, !sample);
+                                    false, !sample);
 
                ar[2].count = 0;
                ar[2].idx = -1;
index c5923ab8a070c167e125bc64e99ce3cee6c15cd2..6280e8bca49d084b89fae9dd545c83a45f6d52d8 100644 (file)
@@ -30,7 +30,6 @@
  *     when virtual port control is not in use.
  * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
  *     frames.
- * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
  * @WLAN_STA_WME: Station is a QoS-STA.
  * @WLAN_STA_WDS: Station is one of our WDS peers.
  * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
@@ -60,7 +59,6 @@ enum ieee80211_sta_info_flags {
        WLAN_STA_PS_STA,
        WLAN_STA_AUTHORIZED,
        WLAN_STA_SHORT_PREAMBLE,
-       WLAN_STA_ASSOC_AP,
        WLAN_STA_WME,
        WLAN_STA_WDS,
        WLAN_STA_CLEAR_PS_FILT,
index f044963feb9a13159b3137afe2c83caaa2d466a5..8d31933abe6ad1696853532a8b0fd03c987468a7 100644 (file)
@@ -36,7 +36,8 @@
 
 /* misc utils */
 
-static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
+static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
+                                struct sk_buff *skb, int group_addr,
                                 int next_frag_len)
 {
        int rate, mrate, erp, dur, i;
@@ -44,7 +45,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
        struct ieee80211_local *local = tx->local;
        struct ieee80211_supported_band *sband;
        struct ieee80211_hdr *hdr;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
        /* assume HW handles this */
        if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
@@ -76,7 +77,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
         *   at the highest possible rate belonging to the PHY rates in the
         *   BSSBasicRateSet
         */
-       hdr = (struct ieee80211_hdr *)tx->skb->data;
+       hdr = (struct ieee80211_hdr *)skb->data;
        if (ieee80211_is_ctl(hdr->frame_control)) {
                /* TODO: These control frames are not currently sent by
                 * mac80211, but should they be implemented, this function
@@ -572,8 +573,6 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
                switch (tx->key->conf.cipher) {
                case WLAN_CIPHER_SUITE_WEP40:
                case WLAN_CIPHER_SUITE_WEP104:
-                       if (ieee80211_is_auth(hdr->frame_control))
-                               break;
                case WLAN_CIPHER_SUITE_TKIP:
                        if (!ieee80211_is_data_present(hdr->frame_control))
                                tx->key = NULL;
@@ -844,11 +843,13 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
        return TX_CONTINUE;
 }
 
-static int ieee80211_fragment(struct ieee80211_local *local,
+static int ieee80211_fragment(struct ieee80211_tx_data *tx,
                              struct sk_buff *skb, int hdrlen,
                              int frag_threshold)
 {
-       struct sk_buff *tail = skb, *tmp;
+       struct ieee80211_local *local = tx->local;
+       struct ieee80211_tx_info *info;
+       struct sk_buff *tmp;
        int per_fragm = frag_threshold - hdrlen - FCS_LEN;
        int pos = hdrlen + per_fragm;
        int rem = skb->len - hdrlen - per_fragm;
@@ -856,6 +857,8 @@ static int ieee80211_fragment(struct ieee80211_local *local,
        if (WARN_ON(rem < 0))
                return -EINVAL;
 
+       /* first fragment was already added to queue by caller */
+
        while (rem) {
                int fraglen = per_fragm;
 
@@ -868,12 +871,21 @@ static int ieee80211_fragment(struct ieee80211_local *local,
                                    IEEE80211_ENCRYPT_TAILROOM);
                if (!tmp)
                        return -ENOMEM;
-               tail->next = tmp;
-               tail = tmp;
+
+               __skb_queue_tail(&tx->skbs, tmp);
+
                skb_reserve(tmp, local->tx_headroom +
                                 IEEE80211_ENCRYPT_HEADROOM);
                /* copy control information */
                memcpy(tmp->cb, skb->cb, sizeof(tmp->cb));
+
+               info = IEEE80211_SKB_CB(tmp);
+               info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
+                                IEEE80211_TX_CTL_FIRST_FRAGMENT);
+
+               if (rem)
+                       info->flags |= IEEE80211_TX_CTL_MORE_FRAMES;
+
                skb_copy_queue_mapping(tmp, skb);
                tmp->priority = skb->priority;
                tmp->dev = skb->dev;
@@ -885,6 +897,7 @@ static int ieee80211_fragment(struct ieee80211_local *local,
                pos += fraglen;
        }
 
+       /* adjust first fragment's length */
        skb->len = hdrlen + per_fragm;
        return 0;
 }
@@ -899,6 +912,10 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
        int hdrlen;
        int fragnum;
 
+       /* no matter what happens, tx->skb moves to tx->skbs */
+       __skb_queue_tail(&tx->skbs, skb);
+       tx->skb = NULL;
+
        if (info->flags & IEEE80211_TX_CTL_DONTFRAG)
                return TX_CONTINUE;
 
@@ -927,21 +944,21 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
         * of the fragments then we will simply pretend to accept the skb
         * but store it away as pending.
         */
-       if (ieee80211_fragment(tx->local, skb, hdrlen, frag_threshold))
+       if (ieee80211_fragment(tx, skb, hdrlen, frag_threshold))
                return TX_DROP;
 
        /* update duration/seq/flags of fragments */
        fragnum = 0;
-       do {
+
+       skb_queue_walk(&tx->skbs, skb) {
                int next_len;
                const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
 
                hdr = (void *)skb->data;
                info = IEEE80211_SKB_CB(skb);
 
-               if (skb->next) {
+               if (!skb_queue_is_last(&tx->skbs, skb)) {
                        hdr->frame_control |= morefrags;
-                       next_len = skb->next->len;
                        /*
                         * No multi-rate retries for fragmented frames, that
                         * would completely throw off the NAV at other STAs.
@@ -956,10 +973,9 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
                        hdr->frame_control &= ~morefrags;
                        next_len = 0;
                }
-               hdr->duration_id = ieee80211_duration(tx, 0, next_len);
                hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG);
                fragnum++;
-       } while ((skb = skb->next));
+       }
 
        return TX_CONTINUE;
 }
@@ -967,16 +983,16 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
 {
-       struct sk_buff *skb = tx->skb;
+       struct sk_buff *skb;
 
        if (!tx->sta)
                return TX_CONTINUE;
 
        tx->sta->tx_packets++;
-       do {
+       skb_queue_walk(&tx->skbs, skb) {
                tx->sta->tx_fragments++;
                tx->sta->tx_bytes += skb->len;
-       } while ((skb = skb->next));
+       }
 
        return TX_CONTINUE;
 }
@@ -1015,21 +1031,25 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
 {
-       struct sk_buff *skb = tx->skb;
+       struct sk_buff *skb;
        struct ieee80211_hdr *hdr;
        int next_len;
        bool group_addr;
 
-       do {
+       skb_queue_walk(&tx->skbs, skb) {
                hdr = (void *) skb->data;
                if (unlikely(ieee80211_is_pspoll(hdr->frame_control)))
                        break; /* must not overwrite AID */
-               next_len = skb->next ? skb->next->len : 0;
+               if (!skb_queue_is_last(&tx->skbs, skb)) {
+                       struct sk_buff *next = skb_queue_next(&tx->skbs, skb);
+                       next_len = next->len;
+               } else
+                       next_len = 0;
                group_addr = is_multicast_ether_addr(hdr->addr1);
 
                hdr->duration_id =
-                       ieee80211_duration(tx, group_addr, next_len);
-       } while ((skb = skb->next));
+                       ieee80211_duration(tx, skb, group_addr, next_len);
+       }
 
        return TX_CONTINUE;
 }
@@ -1108,6 +1128,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
        tx->local = local;
        tx->sdata = sdata;
        tx->channel = local->hw.conf.channel;
+       __skb_queue_head_init(&tx->skbs);
 
        /*
         * If this flag is set to true anywhere, and we get here,
@@ -1180,22 +1201,18 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
        return TX_CONTINUE;
 }
 
-/*
- * Returns false if the frame couldn't be transmitted but was queued instead.
- */
-static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp,
-                          struct sta_info *sta, bool txpending)
+static bool ieee80211_tx_frags(struct ieee80211_local *local,
+                              struct ieee80211_vif *vif,
+                              struct ieee80211_sta *sta,
+                              struct sk_buff_head *skbs,
+                              bool txpending)
 {
-       struct sk_buff *skb = *skbp, *next;
+       struct sk_buff *skb, *tmp;
        struct ieee80211_tx_info *info;
-       struct ieee80211_sub_if_data *sdata;
        unsigned long flags;
-       int len;
-       bool fragm = false;
 
-       while (skb) {
+       skb_queue_walk_safe(skbs, skb, tmp) {
                int q = skb_get_queue_mapping(skb);
-               __le16 fc;
 
                spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
                if (local->queue_stop_reasons[q] ||
@@ -1205,24 +1222,10 @@ static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp,
                         * transmission from the tx-pending tasklet when the
                         * queue is woken again.
                         */
-
-                       do {
-                               next = skb->next;
-                               skb->next = NULL;
-                               /*
-                                * NB: If txpending is true, next must already
-                                * be NULL since we must've gone through this
-                                * loop before already; therefore we can just
-                                * queue the frame to the head without worrying
-                                * about reordering of fragments.
-                                */
-                               if (unlikely(txpending))
-                                       __skb_queue_head(&local->pending[q],
-                                                        skb);
-                               else
-                                       __skb_queue_tail(&local->pending[q],
-                                                        skb);
-                       } while ((skb = next));
+                       if (txpending)
+                               skb_queue_splice(skbs, &local->pending[q]);
+                       else
+                               skb_queue_splice_tail(skbs, &local->pending[q]);
 
                        spin_unlock_irqrestore(&local->queue_stop_reason_lock,
                                               flags);
@@ -1231,47 +1234,72 @@ static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp,
                spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
                info = IEEE80211_SKB_CB(skb);
+               info->control.vif = vif;
+               info->control.sta = sta;
 
-               if (fragm)
-                       info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
-                                        IEEE80211_TX_CTL_FIRST_FRAGMENT);
-
-               next = skb->next;
-               len = skb->len;
+               __skb_unlink(skb, skbs);
+               drv_tx(local, skb);
+       }
 
-               if (next)
-                       info->flags |= IEEE80211_TX_CTL_MORE_FRAMES;
+       return true;
+}
 
-               sdata = vif_to_sdata(info->control.vif);
+/*
+ * Returns false if the frame couldn't be transmitted but was queued instead.
+ */
+static bool __ieee80211_tx(struct ieee80211_local *local,
+                          struct sk_buff_head *skbs, int led_len,
+                          struct sta_info *sta, bool txpending)
+{
+       struct ieee80211_tx_info *info;
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_vif *vif;
+       struct ieee80211_sta *pubsta;
+       struct sk_buff *skb;
+       bool result = true;
+       __le16 fc;
 
-               switch (sdata->vif.type) {
-               case NL80211_IFTYPE_MONITOR:
-                       info->control.vif = NULL;
-                       break;
-               case NL80211_IFTYPE_AP_VLAN:
-                       info->control.vif = &container_of(sdata->bss,
-                               struct ieee80211_sub_if_data, u.ap)->vif;
-                       break;
-               default:
-                       /* keep */
-                       break;
-               }
+       if (WARN_ON(skb_queue_empty(skbs)))
+               return true;
 
-               if (sta && sta->uploaded)
-                       info->control.sta = &sta->sta;
-               else
-                       info->control.sta = NULL;
+       skb = skb_peek(skbs);
+       fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
+       info = IEEE80211_SKB_CB(skb);
+       sdata = vif_to_sdata(info->control.vif);
+       if (sta && !sta->uploaded)
+               sta = NULL;
 
-               fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
-               drv_tx(local, skb);
+       if (sta)
+               pubsta = &sta->sta;
+       else
+               pubsta = NULL;
 
-               ieee80211_tpt_led_trig_tx(local, fc, len);
-               *skbp = skb = next;
-               ieee80211_led_tx(local, 1);
-               fragm = true;
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_MONITOR:
+               sdata = NULL;
+               vif = NULL;
+               break;
+       case NL80211_IFTYPE_AP_VLAN:
+               sdata = container_of(sdata->bss,
+                                    struct ieee80211_sub_if_data, u.ap);
+               /* fall through */
+       default:
+               vif = &sdata->vif;
+               break;
        }
 
-       return true;
+       if (local->ops->tx_frags)
+               drv_tx_frags(local, vif, pubsta, skbs);
+       else
+               result = ieee80211_tx_frags(local, vif, pubsta, skbs,
+                                           txpending);
+
+       ieee80211_tpt_led_trig_tx(local, fc, led_len);
+       ieee80211_led_tx(local, 1);
+
+       WARN_ON(!skb_queue_empty(skbs));
+
+       return result;
 }
 
 /*
@@ -1280,8 +1308,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp,
  */
 static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
 {
-       struct sk_buff *skb = tx->skb;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
        ieee80211_tx_result res = TX_DROP;
 
 #define CALL_TXH(txh) \
@@ -1315,13 +1342,10 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
  txh_done:
        if (unlikely(res == TX_DROP)) {
                I802_DEBUG_INC(tx->local->tx_handlers_drop);
-               while (skb) {
-                       struct sk_buff *next;
-
-                       next = skb->next;
-                       dev_kfree_skb(skb);
-                       skb = next;
-               }
+               if (tx->skb)
+                       dev_kfree_skb(tx->skb);
+               else
+                       __skb_queue_purge(&tx->skbs);
                return -1;
        } else if (unlikely(res == TX_QUEUED)) {
                I802_DEBUG_INC(tx->local->tx_handlers_queued);
@@ -1342,6 +1366,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
        ieee80211_tx_result res_prepare;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        bool result = true;
+       int led_len;
 
        if (unlikely(skb->len < 10)) {
                dev_kfree_skb(skb);
@@ -1351,6 +1376,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
        rcu_read_lock();
 
        /* initialises tx */
+       led_len = skb->len;
        res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
 
        if (unlikely(res_prepare == TX_DROP)) {
@@ -1364,7 +1390,8 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
        info->band = tx.channel->band;
 
        if (!invoke_tx_handlers(&tx))
-               result = __ieee80211_tx(local, &tx.skb, tx.sta, txpending);
+               result = __ieee80211_tx(local, &tx.skbs, led_len,
+                                       tx.sta, txpending);
  out:
        rcu_read_unlock();
        return result;
@@ -2112,10 +2139,15 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
        if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
                result = ieee80211_tx(sdata, skb, true);
        } else {
+               struct sk_buff_head skbs;
+
+               __skb_queue_head_init(&skbs);
+               __skb_queue_tail(&skbs, skb);
+
                hdr = (struct ieee80211_hdr *)skb->data;
                sta = sta_info_get(sdata, hdr->addr1);
 
-               result = __ieee80211_tx(local, &skb, sta, true);
+               result = __ieee80211_tx(local, &skbs, skb->len, sta, true);
        }
 
        return result;
index 3a00814699f028344b627c782e98c1a15daad344..3b9b492e9403d53e16578f4e16b4d89f2604f6d8 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 #include <linux/bitmap.h>
+#include <linux/crc32.h>
 #include <net/net_namespace.h>
 #include <net/cfg80211.h>
 #include <net/rtnetlink.h>
@@ -96,13 +97,13 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
 
 void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
 {
-       struct sk_buff *skb = tx->skb;
+       struct sk_buff *skb;
        struct ieee80211_hdr *hdr;
 
-       do {
+       skb_queue_walk(&tx->skbs, skb) {
                hdr = (struct ieee80211_hdr *) skb->data;
                hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-       } while ((skb = skb->next));
+       }
 }
 
 int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
@@ -564,6 +565,172 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_queue_delayed_work);
 
+u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
+                              struct ieee802_11_elems *elems,
+                              u64 filter, u32 crc)
+{
+       size_t left = len;
+       u8 *pos = start;
+       bool calc_crc = filter != 0;
+
+       memset(elems, 0, sizeof(*elems));
+       elems->ie_start = start;
+       elems->total_len = len;
+
+       while (left >= 2) {
+               u8 id, elen;
+
+               id = *pos++;
+               elen = *pos++;
+               left -= 2;
+
+               if (elen > left)
+                       break;
+
+               if (calc_crc && id < 64 && (filter & (1ULL << id)))
+                       crc = crc32_be(crc, pos - 2, elen + 2);
+
+               switch (id) {
+               case WLAN_EID_SSID:
+                       elems->ssid = pos;
+                       elems->ssid_len = elen;
+                       break;
+               case WLAN_EID_SUPP_RATES:
+                       elems->supp_rates = pos;
+                       elems->supp_rates_len = elen;
+                       break;
+               case WLAN_EID_FH_PARAMS:
+                       elems->fh_params = pos;
+                       elems->fh_params_len = elen;
+                       break;
+               case WLAN_EID_DS_PARAMS:
+                       elems->ds_params = pos;
+                       elems->ds_params_len = elen;
+                       break;
+               case WLAN_EID_CF_PARAMS:
+                       elems->cf_params = pos;
+                       elems->cf_params_len = elen;
+                       break;
+               case WLAN_EID_TIM:
+                       if (elen >= sizeof(struct ieee80211_tim_ie)) {
+                               elems->tim = (void *)pos;
+                               elems->tim_len = elen;
+                       }
+                       break;
+               case WLAN_EID_IBSS_PARAMS:
+                       elems->ibss_params = pos;
+                       elems->ibss_params_len = elen;
+                       break;
+               case WLAN_EID_CHALLENGE:
+                       elems->challenge = pos;
+                       elems->challenge_len = elen;
+                       break;
+               case WLAN_EID_VENDOR_SPECIFIC:
+                       if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
+                           pos[2] == 0xf2) {
+                               /* Microsoft OUI (00:50:F2) */
+
+                               if (calc_crc)
+                                       crc = crc32_be(crc, pos - 2, elen + 2);
+
+                               if (pos[3] == 1) {
+                                       /* OUI Type 1 - WPA IE */
+                                       elems->wpa = pos;
+                                       elems->wpa_len = elen;
+                               } else if (elen >= 5 && pos[3] == 2) {
+                                       /* OUI Type 2 - WMM IE */
+                                       if (pos[4] == 0) {
+                                               elems->wmm_info = pos;
+                                               elems->wmm_info_len = elen;
+                                       } else if (pos[4] == 1) {
+                                               elems->wmm_param = pos;
+                                               elems->wmm_param_len = elen;
+                                       }
+                               }
+                       }
+                       break;
+               case WLAN_EID_RSN:
+                       elems->rsn = pos;
+                       elems->rsn_len = elen;
+                       break;
+               case WLAN_EID_ERP_INFO:
+                       elems->erp_info = pos;
+                       elems->erp_info_len = elen;
+                       break;
+               case WLAN_EID_EXT_SUPP_RATES:
+                       elems->ext_supp_rates = pos;
+                       elems->ext_supp_rates_len = elen;
+                       break;
+               case WLAN_EID_HT_CAPABILITY:
+                       if (elen >= sizeof(struct ieee80211_ht_cap))
+                               elems->ht_cap_elem = (void *)pos;
+                       break;
+               case WLAN_EID_HT_INFORMATION:
+                       if (elen >= sizeof(struct ieee80211_ht_info))
+                               elems->ht_info_elem = (void *)pos;
+                       break;
+               case WLAN_EID_MESH_ID:
+                       elems->mesh_id = pos;
+                       elems->mesh_id_len = elen;
+                       break;
+               case WLAN_EID_MESH_CONFIG:
+                       if (elen >= sizeof(struct ieee80211_meshconf_ie))
+                               elems->mesh_config = (void *)pos;
+                       break;
+               case WLAN_EID_PEER_MGMT:
+                       elems->peering = pos;
+                       elems->peering_len = elen;
+                       break;
+               case WLAN_EID_PREQ:
+                       elems->preq = pos;
+                       elems->preq_len = elen;
+                       break;
+               case WLAN_EID_PREP:
+                       elems->prep = pos;
+                       elems->prep_len = elen;
+                       break;
+               case WLAN_EID_PERR:
+                       elems->perr = pos;
+                       elems->perr_len = elen;
+                       break;
+               case WLAN_EID_RANN:
+                       if (elen >= sizeof(struct ieee80211_rann_ie))
+                               elems->rann = (void *)pos;
+                       break;
+               case WLAN_EID_CHANNEL_SWITCH:
+                       elems->ch_switch_elem = pos;
+                       elems->ch_switch_elem_len = elen;
+                       break;
+               case WLAN_EID_QUIET:
+                       if (!elems->quiet_elem) {
+                               elems->quiet_elem = pos;
+                               elems->quiet_elem_len = elen;
+                       }
+                       elems->num_of_quiet_elem++;
+                       break;
+               case WLAN_EID_COUNTRY:
+                       elems->country_elem = pos;
+                       elems->country_elem_len = elen;
+                       break;
+               case WLAN_EID_PWR_CONSTRAINT:
+                       elems->pwr_constr_elem = pos;
+                       elems->pwr_constr_elem_len = elen;
+                       break;
+               case WLAN_EID_TIMEOUT_INTERVAL:
+                       elems->timeout_int = pos;
+                       elems->timeout_int_len = elen;
+                       break;
+               default:
+                       break;
+               }
+
+               left -= elen;
+               pos += elen;
+       }
+
+       return crc;
+}
+
 void ieee802_11_parse_elems(u8 *start, size_t len,
                            struct ieee802_11_elems *elems)
 {
@@ -813,7 +980,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
        }
 
        if (sband->ht_cap.ht_supported)
-               pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
+               pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
+                                               sband->ht_cap.cap);
 
        /*
         * If adding more here, adjust code in main.c
@@ -1356,7 +1524,7 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
 }
 EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
 
-u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
                              u16 cap)
 {
        __le16 tmp;
@@ -1371,13 +1539,13 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
        pos += sizeof(u16);
 
        /* AMPDU parameters */
-       *pos++ = sband->ht_cap.ampdu_factor |
-                (sband->ht_cap.ampdu_density <<
+       *pos++ = ht_cap->ampdu_factor |
+                (ht_cap->ampdu_density <<
                        IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
 
        /* MCS set */
-       memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
-       pos += sizeof(sband->ht_cap.mcs);
+       memcpy(pos, &ht_cap->mcs, sizeof(ht_cap->mcs));
+       pos += sizeof(ht_cap->mcs);
 
        /* extended capabilities */
        pos += sizeof(__le16);
index a1c6bfd55f0ff99428f6f5bbc83b576e2a90ce8a..68ad351479dff3186ceae2139271a161154fc5dc 100644 (file)
@@ -330,13 +330,12 @@ ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx)
 
        ieee80211_tx_set_protected(tx);
 
-       skb = tx->skb;
-       do {
+       skb_queue_walk(&tx->skbs, skb) {
                if (wep_encrypt_skb(tx, skb) < 0) {
                        I802_DEBUG_INC(tx->local->tx_handlers_drop_wep);
                        return TX_DROP;
                }
-       } while ((skb = skb->next));
+       }
 
        return TX_CONTINUE;
 }
index 3dd5a89e99a79f2cc37687928bee12ade66089d8..6884a2d986dc99d5f1e803f08e20376559ece9dc 100644 (file)
@@ -94,7 +94,8 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
 
 /* frame sending functions */
 
-static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
+static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
+                               struct sk_buff *skb, const u8 *ht_info_ie,
                                struct ieee80211_supported_band *sband,
                                struct ieee80211_channel *channel,
                                enum ieee80211_smps_mode smps)
@@ -102,7 +103,10 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
        struct ieee80211_ht_info *ht_info;
        u8 *pos;
        u32 flags = channel->flags;
-       u16 cap = sband->ht_cap.cap;
+       u16 cap;
+       struct ieee80211_sta_ht_cap ht_cap;
+
+       BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap));
 
        if (!sband->ht_cap.ht_supported)
                return;
@@ -113,9 +117,13 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
        if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info))
                return;
 
+       memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
+       ieee80211_apply_htcap_overrides(sdata, &ht_cap);
+
        ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2);
 
        /* determine capability flags */
+       cap = ht_cap.cap;
 
        switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
        case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
@@ -154,7 +162,7 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
 
        /* reserve and fill IE */
        pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
-       ieee80211_ie_build_ht_cap(pos, sband, cap);
+       ieee80211_ie_build_ht_cap(pos, &ht_cap, cap);
 }
 
 static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
@@ -329,7 +337,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
 
        if (wk->assoc.use_11n && wk->assoc.wmm_used &&
            local->hw.queues >= 4)
-               ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie,
+               ieee80211_add_ht_ie(sdata, skb, wk->assoc.ht_information_ie,
                                    sband, wk->chan, wk->assoc.smps);
 
        /* if present, add any custom non-vendor IEs that go after HT */
index 106e15a4649f1f24ba5335227c44b5a79817e2fb..93aab0715e8ab6f63f4b4f35dde067c0caa023cd 100644 (file)
@@ -223,14 +223,14 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 ieee80211_tx_result
 ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
 {
-       struct sk_buff *skb = tx->skb;
+       struct sk_buff *skb;
 
        ieee80211_tx_set_protected(tx);
 
-       do {
+       skb_queue_walk(&tx->skbs, skb) {
                if (tkip_encrypt_skb(tx, skb) < 0)
                        return TX_DROP;
-       } while ((skb = skb->next));
+       }
 
        return TX_CONTINUE;
 }
@@ -449,14 +449,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 ieee80211_tx_result
 ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
 {
-       struct sk_buff *skb = tx->skb;
+       struct sk_buff *skb;
 
        ieee80211_tx_set_protected(tx);
 
-       do {
+       skb_queue_walk(&tx->skbs, skb) {
                if (ccmp_encrypt_skb(tx, skb) < 0)
                        return TX_DROP;
-       } while ((skb = skb->next));
+       }
 
        return TX_CONTINUE;
 }
@@ -554,15 +554,22 @@ static inline void bip_ipn_swap(u8 *d, const u8 *s)
 ieee80211_tx_result
 ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
 {
-       struct sk_buff *skb = tx->skb;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *info;
        struct ieee80211_key *key = tx->key;
        struct ieee80211_mmie *mmie;
        u8 aad[20];
        u64 pn64;
 
+       if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
+               return TX_DROP;
+
+       skb = skb_peek(&tx->skbs);
+
+       info = IEEE80211_SKB_CB(skb);
+
        if (info->control.hw_key)
-               return 0;
+               return TX_CONTINUE;
 
        if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
                return TX_DROP;
index 1c7d4df5418cdef9929939a782c0fcf0893a0bd3..fb08c28fc90ad9b1051912c8cd878cbaaa6d6187 100644 (file)
@@ -341,13 +341,17 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
                          const u8 *bssid, const u8 *prev_bssid,
                          const u8 *ssid, int ssid_len,
                          const u8 *ie, int ie_len, bool use_mfp,
-                         struct cfg80211_crypto_settings *crypt);
+                         struct cfg80211_crypto_settings *crypt,
+                         u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+                         struct ieee80211_ht_cap *ht_capa_mask);
 int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
                        struct net_device *dev, struct ieee80211_channel *chan,
                        const u8 *bssid, const u8 *prev_bssid,
                        const u8 *ssid, int ssid_len,
                        const u8 *ie, int ie_len, bool use_mfp,
-                       struct cfg80211_crypto_settings *crypt);
+                       struct cfg80211_crypto_settings *crypt,
+                       u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+                       struct ieee80211_ht_cap *ht_capa_mask);
 int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
                           struct net_device *dev, const u8 *bssid,
                           const u8 *ie, int ie_len, u16 reason,
@@ -379,6 +383,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
                          bool channel_type_valid, unsigned int wait,
                          const u8 *buf, size_t len, bool no_cck,
                          bool dont_wait_for_ack, u64 *cookie);
+void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
+                              const struct ieee80211_ht_cap *ht_capa_mask);
 
 /* SME */
 int __cfg80211_connect(struct cfg80211_registered_device *rdev,
index 6c1bafd508c8dabddee9422448084f92c04a2be8..438dfc105b4a0b316fa801e2bef001d89b0d39dc 100644 (file)
@@ -501,13 +501,32 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
        return err;
 }
 
+/*  Do a logical ht_capa &= ht_capa_mask.  */
+void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
+                              const struct ieee80211_ht_cap *ht_capa_mask)
+{
+       int i;
+       u8 *p1, *p2;
+       if (!ht_capa_mask) {
+               memset(ht_capa, 0, sizeof(*ht_capa));
+               return;
+       }
+
+       p1 = (u8*)(ht_capa);
+       p2 = (u8*)(ht_capa_mask);
+       for (i = 0; i<sizeof(*ht_capa); i++)
+               p1[i] &= p2[i];
+}
+
 int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
                          struct net_device *dev,
                          struct ieee80211_channel *chan,
                          const u8 *bssid, const u8 *prev_bssid,
                          const u8 *ssid, int ssid_len,
                          const u8 *ie, int ie_len, bool use_mfp,
-                         struct cfg80211_crypto_settings *crypt)
+                         struct cfg80211_crypto_settings *crypt,
+                         u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+                         struct ieee80211_ht_cap *ht_capa_mask)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_assoc_request req;
@@ -537,6 +556,15 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
        memcpy(&req.crypto, crypt, sizeof(req.crypto));
        req.use_mfp = use_mfp;
        req.prev_bssid = prev_bssid;
+       req.flags = assoc_flags;
+       if (ht_capa)
+               memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa));
+       if (ht_capa_mask)
+               memcpy(&req.ht_capa_mask, ht_capa_mask,
+                      sizeof(req.ht_capa_mask));
+       cfg80211_oper_and_ht_capa(&req.ht_capa_mask,
+                                 rdev->wiphy.ht_capa_mod_mask);
+
        req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
                                   WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
        if (!req.bss) {
@@ -574,14 +602,17 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
                        const u8 *bssid, const u8 *prev_bssid,
                        const u8 *ssid, int ssid_len,
                        const u8 *ie, int ie_len, bool use_mfp,
-                       struct cfg80211_crypto_settings *crypt)
+                       struct cfg80211_crypto_settings *crypt,
+                       u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+                       struct ieee80211_ht_cap *ht_capa_mask)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        int err;
 
        wdev_lock(wdev);
        err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
-                                   ssid, ssid_len, ie, ie_len, use_mfp, crypt);
+                                   ssid, ssid_len, ie, ie_len, use_mfp, crypt,
+                                   assoc_flags, ht_capa, ht_capa_mask);
        wdev_unlock(wdev);
 
        return err;
index 6bc7c4b32fa5786196dd39e5755d2dd3282e25a0..a1cabde7cb5f506263a2e173d04de29a9f48447a 100644 (file)
@@ -199,6 +199,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
        [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
        [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
                                      .len = IEEE80211_MAX_DATA_LEN },
+       [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
+       [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
+       [NL80211_ATTR_HT_CAPABILITY_MASK] = {
+               .len = NL80211_HT_CAPABILITY_LEN
+       },
 };
 
 /* policy for the key attributes */
@@ -881,7 +886,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
        CMD(set_pmksa, SET_PMKSA);
        CMD(del_pmksa, DEL_PMKSA);
        CMD(flush_pmksa, FLUSH_PMKSA);
-       CMD(remain_on_channel, REMAIN_ON_CHANNEL);
+       if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
+               CMD(remain_on_channel, REMAIN_ON_CHANNEL);
        CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
        CMD(mgmt_tx, FRAME);
        CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
@@ -903,6 +909,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
                NLA_PUT_U32(msg, i, NL80211_CMD_REGISTER_BEACONS);
        }
 
+#ifdef CONFIG_NL80211_TESTMODE
+       CMD(testmode_cmd, TESTMODE);
+#endif
+
 #undef CMD
 
        if (dev->ops->connect || dev->ops->auth) {
@@ -917,11 +927,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 
        nla_nest_end(msg, nl_cmds);
 
-       if (dev->ops->remain_on_channel)
+       if (dev->ops->remain_on_channel &&
+           dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
                NLA_PUT_U32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
                            dev->wiphy.max_remain_on_channel_duration);
 
-       if (dev->ops->mgmt_tx_cancel_wait)
+       if (dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)
                NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
 
        if (mgmt_stypes) {
@@ -1025,6 +1036,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 
        NLA_PUT_U32(msg, NL80211_ATTR_FEATURE_FLAGS, dev->wiphy.features);
 
+       if (dev->wiphy.ht_capa_mod_mask)
+               NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
+                       sizeof(*dev->wiphy.ht_capa_mod_mask),
+                       dev->wiphy.ht_capa_mod_mask);
+
        return genlmsg_end(msg, hdr);
 
  nla_put_failure:
@@ -2478,26 +2494,34 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
 /*
  * Get vlan interface making sure it is running and on the right wiphy.
  */
-static int get_vlan(struct genl_info *info,
-                   struct cfg80211_registered_device *rdev,
-                   struct net_device **vlan)
+static struct net_device *get_vlan(struct genl_info *info,
+                                  struct cfg80211_registered_device *rdev)
 {
        struct nlattr *vlanattr = info->attrs[NL80211_ATTR_STA_VLAN];
-       *vlan = NULL;
-
-       if (vlanattr) {
-               *vlan = dev_get_by_index(genl_info_net(info),
-                                        nla_get_u32(vlanattr));
-               if (!*vlan)
-                       return -ENODEV;
-               if (!(*vlan)->ieee80211_ptr)
-                       return -EINVAL;
-               if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
-                       return -EINVAL;
-               if (!netif_running(*vlan))
-                       return -ENETDOWN;
+       struct net_device *v;
+       int ret;
+
+       if (!vlanattr)
+               return NULL;
+
+       v = dev_get_by_index(genl_info_net(info), nla_get_u32(vlanattr));
+       if (!v)
+               return ERR_PTR(-ENODEV);
+
+       if (!v->ieee80211_ptr || v->ieee80211_ptr->wiphy != &rdev->wiphy) {
+               ret = -EINVAL;
+               goto error;
        }
-       return 0;
+
+       if (!netif_running(v)) {
+               ret = -ENETDOWN;
+               goto error;
+       }
+
+       return v;
+ error:
+       dev_put(v);
+       return ERR_PTR(ret);
 }
 
 static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
@@ -2547,9 +2571,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
                params.plink_state =
                    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
 
-       err = get_vlan(info, rdev, &params.vlan);
-       if (err)
-               goto out;
+       params.vlan = get_vlan(info, rdev);
+       if (IS_ERR(params.vlan))
+               return PTR_ERR(params.vlan);
 
        /* validate settings */
        err = 0;
@@ -2717,9 +2741,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
              (rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)))
                return -EINVAL;
 
-       err = get_vlan(info, rdev, &params.vlan);
-       if (err)
-               goto out;
+       params.vlan = get_vlan(info, rdev);
+       if (IS_ERR(params.vlan))
+               return PTR_ERR(params.vlan);
 
        /* validate settings */
        err = 0;
@@ -3382,6 +3406,9 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
 
        NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2,
                cfg80211_regdomain->alpha2);
+       if (cfg80211_regdomain->dfs_region)
+               NLA_PUT_U8(msg, NL80211_ATTR_DFS_REGION,
+                          cfg80211_regdomain->dfs_region);
 
        nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
        if (!nl_reg_rules)
@@ -3440,6 +3467,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
        char *alpha2 = NULL;
        int rem_reg_rules = 0, r = 0;
        u32 num_rules = 0, rule_idx = 0, size_of_regd;
+       u8 dfs_region = 0;
        struct ieee80211_regdomain *rd = NULL;
 
        if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
@@ -3450,6 +3478,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
 
        alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
 
+       if (info->attrs[NL80211_ATTR_DFS_REGION])
+               dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
+
        nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
                        rem_reg_rules) {
                num_rules++;
@@ -3477,6 +3508,13 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
        rd->alpha2[0] = alpha2[0];
        rd->alpha2[1] = alpha2[1];
 
+       /*
+        * Disable DFS master mode if the DFS region was
+        * not supported or known on this kernel.
+        */
+       if (reg_supported_dfs_region(dfs_region))
+               rd->dfs_region = dfs_region;
+
        nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
                        rem_reg_rules) {
                nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
@@ -4384,6 +4422,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
        const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
        int err, ssid_len, ie_len = 0;
        bool use_mfp = false;
+       u32 flags = 0;
+       struct ieee80211_ht_cap *ht_capa = NULL;
+       struct ieee80211_ht_cap *ht_capa_mask = NULL;
 
        if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
                return -EINVAL;
@@ -4427,11 +4468,25 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_PREV_BSSID])
                prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
 
+       if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
+               flags |= ASSOC_REQ_DISABLE_HT;
+
+       if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+               ht_capa_mask =
+                       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]);
+
+       if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
+               if (!ht_capa_mask)
+                       return -EINVAL;
+               ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
+       }
+
        err = nl80211_crypto_settings(rdev, info, &crypto, 1);
        if (!err)
                err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
                                          ssid, ssid_len, ie, ie_len, use_mfp,
-                                         &crypto);
+                                         &crypto, flags, ht_capa,
+                                         ht_capa_mask);
 
        return err;
 }
@@ -4921,6 +4976,22 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
                        return PTR_ERR(connkeys);
        }
 
+       if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
+               connect.flags |= ASSOC_REQ_DISABLE_HT;
+
+       if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+               memcpy(&connect.ht_capa_mask,
+                      nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
+                      sizeof(connect.ht_capa_mask));
+
+       if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
+               if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+                       return -EINVAL;
+               memcpy(&connect.ht_capa,
+                      nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
+                      sizeof(connect.ht_capa));
+       }
+
        err = cfg80211_connect(rdev, dev, &connect, connkeys);
        if (err)
                kfree(connkeys);
@@ -5108,7 +5179,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
            duration > rdev->wiphy.max_remain_on_channel_duration)
                return -EINVAL;
 
-       if (!rdev->ops->remain_on_channel)
+       if (!rdev->ops->remain_on_channel ||
+           !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
                return -EOPNOTSUPP;
 
        if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
@@ -5321,7 +5393,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
                return -EOPNOTSUPP;
 
        if (info->attrs[NL80211_ATTR_DURATION]) {
-               if (!rdev->ops->mgmt_tx_cancel_wait)
+               if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
                        return -EINVAL;
                wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
        }
@@ -5339,6 +5411,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
 
        offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
 
+       if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
+               return -EINVAL;
+
        no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
 
        freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
index 77e926738014638d68ab0088aa5eff2489916c35..76b35df3962306dc194b86ae4f57a944dbb7c469 100644 (file)
@@ -1123,6 +1123,8 @@ static void wiphy_update_regulatory(struct wiphy *wiphy,
        if (ignore_reg_update(wiphy, initiator))
                return;
 
+       last_request->dfs_region = cfg80211_regdomain->dfs_region;
+
        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                if (wiphy->bands[band])
                        handle_band(wiphy, band, initiator);
@@ -1948,6 +1950,42 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
        }
 }
 
+bool reg_supported_dfs_region(u8 dfs_region)
+{
+       switch (dfs_region) {
+       case NL80211_DFS_UNSET:
+       case NL80211_DFS_FCC:
+       case NL80211_DFS_ETSI:
+       case NL80211_DFS_JP:
+               return true;
+       default:
+               REG_DBG_PRINT("Ignoring uknown DFS master region: %d\n",
+                             dfs_region);
+               return false;
+       }
+}
+
+static void print_dfs_region(u8 dfs_region)
+{
+       if (!dfs_region)
+               return;
+
+       switch (dfs_region) {
+       case NL80211_DFS_FCC:
+               pr_info(" DFS Master region FCC");
+               break;
+       case NL80211_DFS_ETSI:
+               pr_info(" DFS Master region ETSI");
+               break;
+       case NL80211_DFS_JP:
+               pr_info(" DFS Master region JP");
+               break;
+       default:
+               pr_info(" DFS Master region Uknown");
+               break;
+       }
+}
+
 static void print_regdomain(const struct ieee80211_regdomain *rd)
 {
 
@@ -1975,6 +2013,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
                        pr_info("Regulatory domain changed to country: %c%c\n",
                                rd->alpha2[0], rd->alpha2[1]);
        }
+       print_dfs_region(rd->dfs_region);
        print_rd_rules(rd);
 }
 
index 4a56799d868d5fa7efc48ab8e21cbb67d3a8a473..786e414afd914805c7a90f16ee738106903ab9c9 100644 (file)
@@ -5,6 +5,7 @@ extern const struct ieee80211_regdomain *cfg80211_regdomain;
 
 bool is_world_regdom(const char *alpha2);
 bool reg_is_valid_request(const char *alpha2);
+bool reg_supported_dfs_region(u8 dfs_region);
 
 int regulatory_hint_user(const char *alpha2);
 
index 0acfdc9beacf8a397b8122c236cd6156d6c78b7e..f0c900ce2fb9ee2dd0606fa651c15b078eb497e0 100644 (file)
@@ -190,7 +190,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
                                            prev_bssid,
                                            params->ssid, params->ssid_len,
                                            params->ie, params->ie_len,
-                                           false, &params->crypto);
+                                           false, &params->crypto,
+                                           params->flags, &params->ht_capa,
+                                           &params->ht_capa_mask);
                if (err)
                        __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
                                               NULL, 0,
@@ -774,6 +776,9 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
                wdev->connect_keys = NULL;
        }
 
+       cfg80211_oper_and_ht_capa(&connect->ht_capa_mask,
+                                 rdev->wiphy.ht_capa_mod_mask);
+
        if (connkeys && connkeys->def >= 0) {
                int idx;
                u32 cipher;
index 4dde429441d2a45f748b0d0c8c67022e17fe5c36..9c601d59b77a802664c763c8cbaa02936348fc64 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/bitops.h>
 #include <linux/etherdevice.h>
 #include <linux/slab.h>
-#include <linux/crc32.h>
 #include <net/cfg80211.h>
 #include <net/ip.h>
 #include "core.h"
@@ -240,17 +239,6 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
        return 0;
 }
 
-/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
-/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
-const unsigned char rfc1042_header[] __aligned(2) =
-       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-EXPORT_SYMBOL(rfc1042_header);
-
-/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
-const unsigned char bridge_tunnel_header[] __aligned(2) =
-       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
-EXPORT_SYMBOL(bridge_tunnel_header);
-
 unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc)
 {
        unsigned int hdrlen = 24;
@@ -1051,169 +1039,13 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
        return 0;
 }
 
-u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
-                              struct ieee802_11_elems *elems,
-                              u64 filter, u32 crc)
-{
-       size_t left = len;
-       u8 *pos = start;
-       bool calc_crc = filter != 0;
-
-       memset(elems, 0, sizeof(*elems));
-       elems->ie_start = start;
-       elems->total_len = len;
-
-       while (left >= 2) {
-               u8 id, elen;
-
-               id = *pos++;
-               elen = *pos++;
-               left -= 2;
-
-               if (elen > left)
-                       break;
-
-               if (calc_crc && id < 64 && (filter & (1ULL << id)))
-                       crc = crc32_be(crc, pos - 2, elen + 2);
-
-               switch (id) {
-               case WLAN_EID_SSID:
-                       elems->ssid = pos;
-                       elems->ssid_len = elen;
-                       break;
-               case WLAN_EID_SUPP_RATES:
-                       elems->supp_rates = pos;
-                       elems->supp_rates_len = elen;
-                       break;
-               case WLAN_EID_FH_PARAMS:
-                       elems->fh_params = pos;
-                       elems->fh_params_len = elen;
-                       break;
-               case WLAN_EID_DS_PARAMS:
-                       elems->ds_params = pos;
-                       elems->ds_params_len = elen;
-                       break;
-               case WLAN_EID_CF_PARAMS:
-                       elems->cf_params = pos;
-                       elems->cf_params_len = elen;
-                       break;
-               case WLAN_EID_TIM:
-                       if (elen >= sizeof(struct ieee80211_tim_ie)) {
-                               elems->tim = (void *)pos;
-                               elems->tim_len = elen;
-                       }
-                       break;
-               case WLAN_EID_IBSS_PARAMS:
-                       elems->ibss_params = pos;
-                       elems->ibss_params_len = elen;
-                       break;
-               case WLAN_EID_CHALLENGE:
-                       elems->challenge = pos;
-                       elems->challenge_len = elen;
-                       break;
-               case WLAN_EID_VENDOR_SPECIFIC:
-                       if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
-                           pos[2] == 0xf2) {
-                               /* Microsoft OUI (00:50:F2) */
-
-                               if (calc_crc)
-                                       crc = crc32_be(crc, pos - 2, elen + 2);
-
-                               if (pos[3] == 1) {
-                                       /* OUI Type 1 - WPA IE */
-                                       elems->wpa = pos;
-                                       elems->wpa_len = elen;
-                               } else if (elen >= 5 && pos[3] == 2) {
-                                       /* OUI Type 2 - WMM IE */
-                                       if (pos[4] == 0) {
-                                               elems->wmm_info = pos;
-                                               elems->wmm_info_len = elen;
-                                       } else if (pos[4] == 1) {
-                                               elems->wmm_param = pos;
-                                               elems->wmm_param_len = elen;
-                                       }
-                               }
-                       }
-                       break;
-               case WLAN_EID_RSN:
-                       elems->rsn = pos;
-                       elems->rsn_len = elen;
-                       break;
-               case WLAN_EID_ERP_INFO:
-                       elems->erp_info = pos;
-                       elems->erp_info_len = elen;
-                       break;
-               case WLAN_EID_EXT_SUPP_RATES:
-                       elems->ext_supp_rates = pos;
-                       elems->ext_supp_rates_len = elen;
-                       break;
-               case WLAN_EID_HT_CAPABILITY:
-                       if (elen >= sizeof(struct ieee80211_ht_cap))
-                               elems->ht_cap_elem = (void *)pos;
-                       break;
-               case WLAN_EID_HT_INFORMATION:
-                       if (elen >= sizeof(struct ieee80211_ht_info))
-                               elems->ht_info_elem = (void *)pos;
-                       break;
-               case WLAN_EID_MESH_ID:
-                       elems->mesh_id = pos;
-                       elems->mesh_id_len = elen;
-                       break;
-               case WLAN_EID_MESH_CONFIG:
-                       if (elen >= sizeof(struct ieee80211_meshconf_ie))
-                               elems->mesh_config = (void *)pos;
-                       break;
-               case WLAN_EID_PEER_MGMT:
-                       elems->peering = pos;
-                       elems->peering_len = elen;
-                       break;
-               case WLAN_EID_PREQ:
-                       elems->preq = pos;
-                       elems->preq_len = elen;
-                       break;
-               case WLAN_EID_PREP:
-                       elems->prep = pos;
-                       elems->prep_len = elen;
-                       break;
-               case WLAN_EID_PERR:
-                       elems->perr = pos;
-                       elems->perr_len = elen;
-                       break;
-               case WLAN_EID_RANN:
-                       if (elen >= sizeof(struct ieee80211_rann_ie))
-                               elems->rann = (void *)pos;
-                       break;
-               case WLAN_EID_CHANNEL_SWITCH:
-                       elems->ch_switch_elem = pos;
-                       elems->ch_switch_elem_len = elen;
-                       break;
-               case WLAN_EID_QUIET:
-                       if (!elems->quiet_elem) {
-                               elems->quiet_elem = pos;
-                               elems->quiet_elem_len = elen;
-                       }
-                       elems->num_of_quiet_elem++;
-                       break;
-               case WLAN_EID_COUNTRY:
-                       elems->country_elem = pos;
-                       elems->country_elem_len = elen;
-                       break;
-               case WLAN_EID_PWR_CONSTRAINT:
-                       elems->pwr_constr_elem = pos;
-                       elems->pwr_constr_elem_len = elen;
-                       break;
-               case WLAN_EID_TIMEOUT_INTERVAL:
-                       elems->timeout_int = pos;
-                       elems->timeout_int_len = elen;
-                       break;
-               default:
-                       break;
-               }
-
-               left -= elen;
-               pos += elen;
-       }
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+const unsigned char rfc1042_header[] __aligned(2) =
+       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+EXPORT_SYMBOL(rfc1042_header);
 
-       return crc;
-}
-EXPORT_SYMBOL(ieee802_11_parse_elems_crc);
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+const unsigned char bridge_tunnel_header[] __aligned(2) =
+       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+EXPORT_SYMBOL(bridge_tunnel_header);