Merge branch 'master' into for-davem
authorJohn W. Linville <linville@tuxdriver.com>
Fri, 23 Apr 2010 18:43:45 +0000 (14:43 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 23 Apr 2010 18:43:45 +0000 (14:43 -0400)
Conflicts:
drivers/net/wireless/ath/ath9k/phy.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-debugfs.c

33 files changed:
1  2 
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/rc.c
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/iwmc3200wifi/rx.c
drivers/net/wireless/iwmc3200wifi/tx.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/orinoco/hw.c
drivers/net/wireless/orinoco/scan.c
drivers/net/wireless/orinoco/wext.c
drivers/net/wireless/p54/p54pci.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00pci.c
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt2x00usb.c
drivers/net/wireless/wl12xx/wl1251_main.c
include/net/mac80211.h
net/mac80211/agg-rx.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/driver-ops.h
net/mac80211/key.c
net/mac80211/mlme.c
net/wireless/sme.c

@@@ -50,7 -50,6 +50,7 @@@
  #include <linux/pci.h>
  #include <linux/ethtool.h>
  #include <linux/uaccess.h>
 +#include <linux/slab.h>
  
  #include <net/ieee80211_radiotap.h>
  
@@@ -231,7 -230,7 +231,7 @@@ static void ath5k_remove_interface(stru
                struct ieee80211_vif *vif);
  static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
  static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
 -                                 int mc_count, struct dev_addr_list *mc_list);
 +                                 struct netdev_hw_addr_list *mc_list);
  static void ath5k_configure_filter(struct ieee80211_hw *hw,
                unsigned int changed_flags,
                unsigned int *new_flags,
@@@ -242,6 -241,8 +242,8 @@@ static int ath5k_set_key(struct ieee802
                struct ieee80211_key_conf *key);
  static int ath5k_get_stats(struct ieee80211_hw *hw,
                struct ieee80211_low_level_stats *stats);
+ static int ath5k_get_survey(struct ieee80211_hw *hw,
+               int idx, struct survey_info *survey);
  static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
  static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
  static void ath5k_reset_tsf(struct ieee80211_hw *hw);
@@@ -267,6 -268,7 +269,7 @@@ static const struct ieee80211_ops ath5k
        .configure_filter = ath5k_configure_filter,
        .set_key        = ath5k_set_key,
        .get_stats      = ath5k_get_stats,
+       .get_survey     = ath5k_get_survey,
        .conf_tx        = NULL,
        .get_tsf        = ath5k_get_tsf,
        .set_tsf        = ath5k_set_tsf,
@@@ -3073,20 -3075,22 +3076,20 @@@ unlock
  }
  
  static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
 -                                 int mc_count, struct dev_addr_list *mclist)
 +                                 struct netdev_hw_addr_list *mc_list)
  {
        u32 mfilt[2], val;
 -      int i;
        u8 pos;
 +      struct netdev_hw_addr *ha;
  
        mfilt[0] = 0;
        mfilt[1] = 1;
  
 -      for (i = 0; i < mc_count; i++) {
 -              if (!mclist)
 -                      break;
 +      netdev_hw_addr_list_for_each(ha, mc_list) {
                /* calculate XOR of eight 6-bit values */
 -              val = get_unaligned_le32(mclist->dmi_addr + 0);
 +              val = get_unaligned_le32(ha->addr + 0);
                pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
 -              val = get_unaligned_le32(mclist->dmi_addr + 3);
 +              val = get_unaligned_le32(ha->addr + 3);
                pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
                pos &= 0x3f;
                mfilt[pos / 32] |= (1 << (pos % 32));
                * but not sure, needs testing, if we do use this we'd
                * neet to inform below to not reset the mcast */
                /* ath5k_hw_set_mcast_filterindex(ah,
 -               *      mclist->dmi_addr[5]); */
 -              mclist = mclist->next;
 +               *      ha->addr[5]); */
        }
  
        return ((u64)(mfilt[1]) << 32) | mfilt[0];
@@@ -3292,6 -3297,22 +3295,22 @@@ ath5k_get_stats(struct ieee80211_hw *hw
        return 0;
  }
  
+ static int ath5k_get_survey(struct ieee80211_hw *hw, int idx,
+               struct survey_info *survey)
+ {
+       struct ath5k_softc *sc = hw->priv;
+       struct ieee80211_conf *conf = &hw->conf;
+        if (idx != 0)
+               return -ENOENT;
+       survey->channel = conf->channel;
+       survey->filled = SURVEY_INFO_NOISE_DBM;
+       survey->noise = sc->ah->ah_noise_floor;
+       return 0;
+ }
  static u64
  ath5k_get_tsf(struct ieee80211_hw *hw)
  {
@@@ -14,7 -14,6 +14,7 @@@
   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   */
  
 +#include <linux/slab.h>
  #include <asm/unaligned.h>
  
  #include "ath9k.h"
@@@ -180,8 -179,15 +180,15 @@@ void ath_debug_stat_interrupt(struct at
  {
        if (status)
                sc->debug.stats.istats.total++;
-       if (status & ATH9K_INT_RX)
-               sc->debug.stats.istats.rxok++;
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               if (status & ATH9K_INT_RXLP)
+                       sc->debug.stats.istats.rxlp++;
+               if (status & ATH9K_INT_RXHP)
+                       sc->debug.stats.istats.rxhp++;
+       } else {
+               if (status & ATH9K_INT_RX)
+                       sc->debug.stats.istats.rxok++;
+       }
        if (status & ATH9K_INT_RXEOL)
                sc->debug.stats.istats.rxeol++;
        if (status & ATH9K_INT_RXORN)
@@@ -223,8 -229,15 +230,15 @@@ static ssize_t read_file_interrupt(stru
        char buf[512];
        unsigned int len = 0;
  
-       len += snprintf(buf + len, sizeof(buf) - len,
-               "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               len += snprintf(buf + len, sizeof(buf) - len,
+                       "%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp);
+               len += snprintf(buf + len, sizeof(buf) - len,
+                       "%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp);
+       } else {
+               len += snprintf(buf + len, sizeof(buf) - len,
+                       "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
+       }
        len += snprintf(buf + len, sizeof(buf) - len,
                "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
        len += snprintf(buf + len, sizeof(buf) - len,
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * Copyright (c) 2008-2009 Atheros Communications Inc.
+  * Copyright (c) 2008-2010 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
   */
  
  #include <linux/io.h>
 +#include <linux/slab.h>
  #include <asm/unaligned.h>
  
  #include "hw.h"
+ #include "hw-ops.h"
  #include "rc.h"
- #include "initvals.h"
+ #include "ar9003_mac.h"
  
  #define ATH9K_CLOCK_RATE_CCK          22
  #define ATH9K_CLOCK_RATE_5GHZ_OFDM    40
  #define ATH9K_CLOCK_RATE_2GHZ_OFDM    44
  
  static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
- static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan);
  
  MODULE_AUTHOR("Atheros Communications");
  MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
@@@ -46,6 -45,39 +46,39 @@@ static void __exit ath9k_exit(void
  }
  module_exit(ath9k_exit);
  
+ /* Private hardware callbacks */
+ static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
+ {
+       ath9k_hw_private_ops(ah)->init_cal_settings(ah);
+ }
+ static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
+ {
+       ath9k_hw_private_ops(ah)->init_mode_regs(ah);
+ }
+ static bool ath9k_hw_macversion_supported(struct ath_hw *ah)
+ {
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+       return priv_ops->macversion_supported(ah->hw_version.macVersion);
+ }
+ static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah,
+                                       struct ath9k_channel *chan)
+ {
+       return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan);
+ }
+ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
+ {
+       if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs)
+               return;
+       ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah);
+ }
  /********************/
  /* Helper Functions */
  /********************/
@@@ -233,21 -265,6 +266,6 @@@ static void ath9k_hw_read_revisions(str
        }
  }
  
- static int ath9k_hw_get_radiorev(struct ath_hw *ah)
- {
-       u32 val;
-       int i;
-       REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
-       for (i = 0; i < 8; i++)
-               REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
-       val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
-       val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
-       return ath9k_hw_reverse_bits(val, 8);
- }
  /************************************/
  /* HW Attach, Detach, Init Routines */
  /************************************/
@@@ -257,6 -274,8 +275,8 @@@ static void ath9k_hw_disablepcie(struc
        if (AR_SREV_9100(ah))
                return;
  
+       ENABLE_REGWRITE_BUFFER(ah);
        REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
        REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
        REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
        REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
  
        REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
  }
  
+ /* This should work for all families including legacy */
  static bool ath9k_hw_chip_test(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
-       u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) };
+       u32 regAddr[2] = { AR_STA_ID0 };
        u32 regHold[2];
        u32 patternData[4] = { 0x55555555,
                               0xaaaaaaaa,
                               0x66666666,
                               0x99999999 };
-       int i, j;
+       int i, j, loop_max;
  
-       for (i = 0; i < 2; i++) {
+       if (!AR_SREV_9300_20_OR_LATER(ah)) {
+               loop_max = 2;
+               regAddr[1] = AR_PHY_BASE + (8 << 2);
+       } else
+               loop_max = 1;
+       for (i = 0; i < loop_max; i++) {
                u32 addr = regAddr[i];
                u32 wrData, rdData;
  
@@@ -336,7 -365,13 +366,13 @@@ static void ath9k_hw_init_config(struc
        ah->config.ofdm_trig_high = 500;
        ah->config.cck_trig_high = 200;
        ah->config.cck_trig_low = 100;
-       ah->config.enable_ani = 1;
+       /*
+        * For now ANI is disabled for AR9003, it is still
+        * being tested.
+        */
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               ah->config.enable_ani = 1;
  
        for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
                ah->config.spurchans[i][0] = AR_NO_SPUR;
        if (num_possible_cpus() > 1)
                ah->config.serialize_regmode = SER_REG_MODE_AUTO;
  }
- EXPORT_SYMBOL(ath9k_hw_init);
  
  static void ath9k_hw_init_defaults(struct ath_hw *ah)
  {
        ah->hw_version.subvendorid = 0;
  
        ah->ah_flags = 0;
-       if (ah->hw_version.devid == AR5416_AR9100_DEVID)
-               ah->hw_version.macVersion = AR_SREV_VERSION_9100;
        if (!AR_SREV_9100(ah))
                ah->ah_flags = AH_USE_EEPROM;
  
        ah->power_mode = ATH9K_PM_UNDEFINED;
  }
  
- static int ath9k_hw_rf_claim(struct ath_hw *ah)
- {
-       u32 val;
-       REG_WRITE(ah, AR_PHY(0), 0x00000007);
-       val = ath9k_hw_get_radiorev(ah);
-       switch (val & AR_RADIO_SREV_MAJOR) {
-       case 0:
-               val = AR_RAD5133_SREV_MAJOR;
-               break;
-       case AR_RAD5133_SREV_MAJOR:
-       case AR_RAD5122_SREV_MAJOR:
-       case AR_RAD2133_SREV_MAJOR:
-       case AR_RAD2122_SREV_MAJOR:
-               break;
-       default:
-               ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-                         "Radio Chip Rev 0x%02X not supported\n",
-                         val & AR_RADIO_SREV_MAJOR);
-               return -EOPNOTSUPP;
-       }
-       ah->hw_version.analog5GhzRev = val;
-       return 0;
- }
  static int ath9k_hw_init_macaddr(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
        u32 sum;
        int i;
        u16 eeval;
+       u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
  
        sum = 0;
        for (i = 0; i < 3; i++) {
-               eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i));
+               eeval = ah->eep_ops->get_eeprom(ah, EEP_MAC[i]);
                sum += eeval;
                common->macaddr[2 * i] = eeval >> 8;
                common->macaddr[2 * i + 1] = eeval & 0xff;
        return 0;
  }
  
- static void ath9k_hw_init_rxgain_ini(struct ath_hw *ah)
- {
-       u32 rxgain_type;
-       if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) {
-               rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
-               if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                       ar9280Modes_backoff_13db_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
-               else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                       ar9280Modes_backoff_23db_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
-               else
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                       ar9280Modes_original_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
-       } else {
-               INIT_INI_ARRAY(&ah->iniModesRxGain,
-                       ar9280Modes_original_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
-       }
- }
- static void ath9k_hw_init_txgain_ini(struct ath_hw *ah)
- {
-       u32 txgain_type;
-       if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) {
-               txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
-               if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9280Modes_high_power_tx_gain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
-               else
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9280Modes_original_tx_gain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
-       } else {
-               INIT_INI_ARRAY(&ah->iniModesTxGain,
-               ar9280Modes_original_tx_gain_9280_2,
-               ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
-       }
- }
  static int ath9k_hw_post_init(struct ath_hw *ah)
  {
        int ecode;
                        return -ENODEV;
        }
  
-       ecode = ath9k_hw_rf_claim(ah);
-       if (ecode != 0)
-               return ecode;
+       if (!AR_SREV_9300_20_OR_LATER(ah)) {
+               ecode = ar9002_hw_rf_claim(ah);
+               if (ecode != 0)
+                       return ecode;
+       }
  
        ecode = ath9k_hw_eeprom_init(ah);
        if (ecode != 0)
                  ah->eep_ops->get_eeprom_ver(ah),
                  ah->eep_ops->get_eeprom_rev(ah));
  
-         if (!AR_SREV_9280_10_OR_LATER(ah)) {
-               ecode = ath9k_hw_rf_alloc_ext_banks(ah);
-               if (ecode) {
-                       ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-                                 "Failed allocating banks for "
-                                 "external radio\n");
-                       return ecode;
-               }
+       ecode = ath9k_hw_rf_alloc_ext_banks(ah);
+       if (ecode) {
+               ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
+                         "Failed allocating banks for "
+                         "external radio\n");
+               return ecode;
        }
  
        if (!AR_SREV_9100(ah)) {
        return 0;
  }
  
- static bool ath9k_hw_devid_supported(u16 devid)
+ static void ath9k_hw_attach_ops(struct ath_hw *ah)
  {
-       switch (devid) {
-       case AR5416_DEVID_PCI:
-       case AR5416_DEVID_PCIE:
-       case AR5416_AR9100_DEVID:
-       case AR9160_DEVID_PCI:
-       case AR9280_DEVID_PCI:
-       case AR9280_DEVID_PCIE:
-       case AR9285_DEVID_PCIE:
-       case AR5416_DEVID_AR9287_PCI:
-       case AR5416_DEVID_AR9287_PCIE:
-       case AR2427_DEVID_PCIE:
-               return true;
-       default:
-               break;
-       }
-       return false;
- }
- static bool ath9k_hw_macversion_supported(u32 macversion)
- {
-       switch (macversion) {
-       case AR_SREV_VERSION_5416_PCI:
-       case AR_SREV_VERSION_5416_PCIE:
-       case AR_SREV_VERSION_9160:
-       case AR_SREV_VERSION_9100:
-       case AR_SREV_VERSION_9280:
-       case AR_SREV_VERSION_9285:
-       case AR_SREV_VERSION_9287:
-       case AR_SREV_VERSION_9271:
-               return true;
-       default:
-               break;
-       }
-       return false;
- }
- static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
- {
-       if (AR_SREV_9160_10_OR_LATER(ah)) {
-               if (AR_SREV_9280_10_OR_LATER(ah)) {
-                       ah->iq_caldata.calData = &iq_cal_single_sample;
-                       ah->adcgain_caldata.calData =
-                               &adc_gain_cal_single_sample;
-                       ah->adcdc_caldata.calData =
-                               &adc_dc_cal_single_sample;
-                       ah->adcdc_calinitdata.calData =
-                               &adc_init_dc_cal;
-               } else {
-                       ah->iq_caldata.calData = &iq_cal_multi_sample;
-                       ah->adcgain_caldata.calData =
-                               &adc_gain_cal_multi_sample;
-                       ah->adcdc_caldata.calData =
-                               &adc_dc_cal_multi_sample;
-                       ah->adcdc_calinitdata.calData =
-                               &adc_init_dc_cal;
-               }
-               ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
-       }
- }
- static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
- {
-       if (AR_SREV_9271(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
-                              ARRAY_SIZE(ar9271Modes_9271), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
-                              ARRAY_SIZE(ar9271Common_9271), 2);
-               INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
-                              ar9271Common_normal_cck_fir_coeff_9271,
-                              ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2);
-               INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271,
-                              ar9271Common_japan_2484_cck_fir_coeff_9271,
-                              ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2);
-               INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
-                              ar9271Modes_9271_1_0_only,
-                              ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6);
-               INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
-                              ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6);
-               INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
-                              ar9271Modes_high_power_tx_gain_9271,
-                              ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6);
-               INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
-                              ar9271Modes_normal_power_tx_gain_9271,
-                              ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6);
-               return;
-       }
-       if (AR_SREV_9287_11_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
-                               ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
-                               ARRAY_SIZE(ar9287Common_9287_1_1), 2);
-               if (ah->config.pcie_clock_req)
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9287PciePhy_clkreq_off_L1_9287_1_1,
-                       ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2);
-               else
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9287PciePhy_clkreq_always_on_L1_9287_1_1,
-                       ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1),
-                                       2);
-       } else if (AR_SREV_9287_10_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0,
-                               ARRAY_SIZE(ar9287Modes_9287_1_0), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0,
-                               ARRAY_SIZE(ar9287Common_9287_1_0), 2);
-               if (ah->config.pcie_clock_req)
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9287PciePhy_clkreq_off_L1_9287_1_0,
-                       ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2);
-               else
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9287PciePhy_clkreq_always_on_L1_9287_1_0,
-                       ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0),
-                                 2);
-       } else if (AR_SREV_9285_12_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
-                              ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
-                              ARRAY_SIZE(ar9285Common_9285_1_2), 2);
-               if (ah->config.pcie_clock_req) {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9285PciePhy_clkreq_off_L1_9285_1_2,
-                       ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
-               } else {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
-                       ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
-                                 2);
-               }
-       } else if (AR_SREV_9285_10_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285,
-                              ARRAY_SIZE(ar9285Modes_9285), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285,
-                              ARRAY_SIZE(ar9285Common_9285), 2);
-               if (ah->config.pcie_clock_req) {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9285PciePhy_clkreq_off_L1_9285,
-                       ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2);
-               } else {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9285PciePhy_clkreq_always_on_L1_9285,
-                       ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2);
-               }
-       } else if (AR_SREV_9280_20_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
-                              ARRAY_SIZE(ar9280Modes_9280_2), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
-                              ARRAY_SIZE(ar9280Common_9280_2), 2);
-               if (ah->config.pcie_clock_req) {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                              ar9280PciePhy_clkreq_off_L1_9280,
-                              ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2);
-               } else {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                              ar9280PciePhy_clkreq_always_on_L1_9280,
-                              ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
-               }
-               INIT_INI_ARRAY(&ah->iniModesAdditional,
-                              ar9280Modes_fast_clock_9280_2,
-                              ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
-       } else if (AR_SREV_9280_10_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280,
-                              ARRAY_SIZE(ar9280Modes_9280), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280,
-                              ARRAY_SIZE(ar9280Common_9280), 2);
-       } else if (AR_SREV_9160_10_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
-                              ARRAY_SIZE(ar5416Modes_9160), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
-                              ARRAY_SIZE(ar5416Common_9160), 2);
-               INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
-                              ARRAY_SIZE(ar5416Bank0_9160), 2);
-               INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160,
-                              ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
-               INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160,
-                              ARRAY_SIZE(ar5416Bank1_9160), 2);
-               INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160,
-                              ARRAY_SIZE(ar5416Bank2_9160), 2);
-               INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160,
-                              ARRAY_SIZE(ar5416Bank3_9160), 3);
-               INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160,
-                              ARRAY_SIZE(ar5416Bank6_9160), 3);
-               INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160,
-                              ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
-               INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160,
-                              ARRAY_SIZE(ar5416Bank7_9160), 2);
-               if (AR_SREV_9160_11(ah)) {
-                       INIT_INI_ARRAY(&ah->iniAddac,
-                                      ar5416Addac_91601_1,
-                                      ARRAY_SIZE(ar5416Addac_91601_1), 2);
-               } else {
-                       INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
-                                      ARRAY_SIZE(ar5416Addac_9160), 2);
-               }
-       } else if (AR_SREV_9100_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
-                              ARRAY_SIZE(ar5416Modes_9100), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
-                              ARRAY_SIZE(ar5416Common_9100), 2);
-               INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
-                              ARRAY_SIZE(ar5416Bank0_9100), 2);
-               INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100,
-                              ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
-               INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100,
-                              ARRAY_SIZE(ar5416Bank1_9100), 2);
-               INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100,
-                              ARRAY_SIZE(ar5416Bank2_9100), 2);
-               INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100,
-                              ARRAY_SIZE(ar5416Bank3_9100), 3);
-               INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
-                              ARRAY_SIZE(ar5416Bank6_9100), 3);
-               INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
-                              ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
-               INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100,
-                              ARRAY_SIZE(ar5416Bank7_9100), 2);
-               INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
-                              ARRAY_SIZE(ar5416Addac_9100), 2);
-       } else {
-               INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
-                              ARRAY_SIZE(ar5416Modes), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
-                              ARRAY_SIZE(ar5416Common), 2);
-               INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
-                              ARRAY_SIZE(ar5416Bank0), 2);
-               INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
-                              ARRAY_SIZE(ar5416BB_RfGain), 3);
-               INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
-                              ARRAY_SIZE(ar5416Bank1), 2);
-               INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
-                              ARRAY_SIZE(ar5416Bank2), 2);
-               INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
-                              ARRAY_SIZE(ar5416Bank3), 3);
-               INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
-                              ARRAY_SIZE(ar5416Bank6), 3);
-               INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
-                              ARRAY_SIZE(ar5416Bank6TPC), 3);
-               INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
-                              ARRAY_SIZE(ar5416Bank7), 2);
-               INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
-                              ARRAY_SIZE(ar5416Addac), 2);
-       }
- }
- static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
- {
-       if (AR_SREV_9287_11_OR_LATER(ah))
-               INIT_INI_ARRAY(&ah->iniModesRxGain,
-               ar9287Modes_rx_gain_9287_1_1,
-               ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
-       else if (AR_SREV_9287_10(ah))
-               INIT_INI_ARRAY(&ah->iniModesRxGain,
-               ar9287Modes_rx_gain_9287_1_0,
-               ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6);
-       else if (AR_SREV_9280_20(ah))
-               ath9k_hw_init_rxgain_ini(ah);
-       if (AR_SREV_9287_11_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModesTxGain,
-               ar9287Modes_tx_gain_9287_1_1,
-               ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
-       } else if (AR_SREV_9287_10(ah)) {
-               INIT_INI_ARRAY(&ah->iniModesTxGain,
-               ar9287Modes_tx_gain_9287_1_0,
-               ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6);
-       } else if (AR_SREV_9280_20(ah)) {
-               ath9k_hw_init_txgain_ini(ah);
-       } else if (AR_SREV_9285_12_OR_LATER(ah)) {
-               u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
-               /* txgain table */
-               if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
-                       if (AR_SREV_9285E_20(ah)) {
-                               INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9285Modes_XE2_0_high_power,
-                               ARRAY_SIZE(
-                                 ar9285Modes_XE2_0_high_power), 6);
-                       } else {
-                               INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9285Modes_high_power_tx_gain_9285_1_2,
-                               ARRAY_SIZE(
-                                 ar9285Modes_high_power_tx_gain_9285_1_2), 6);
-                       }
-               } else {
-                       if (AR_SREV_9285E_20(ah)) {
-                               INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9285Modes_XE2_0_normal_power,
-                               ARRAY_SIZE(
-                                 ar9285Modes_XE2_0_normal_power), 6);
-                       } else {
-                               INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9285Modes_original_tx_gain_9285_1_2,
-                               ARRAY_SIZE(
-                                 ar9285Modes_original_tx_gain_9285_1_2), 6);
-                       }
-               }
-       }
- }
- static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah)
- {
-       struct base_eep_header *pBase = &(ah->eeprom.def.baseEepHeader);
-       struct ath_common *common = ath9k_hw_common(ah);
-       ah->need_an_top2_fixup = (ah->hw_version.devid == AR9280_DEVID_PCI) &&
-                                (ah->eep_map != EEP_MAP_4KBITS) &&
-                                ((pBase->version & 0xff) > 0x0a) &&
-                                (pBase->pwdclkind == 0);
-       if (ah->need_an_top2_fixup)
-               ath_print(common, ATH_DBG_EEPROM,
-                         "needs fixup for AR_AN_TOP2 register\n");
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ar9003_hw_attach_ops(ah);
+       else
+               ar9002_hw_attach_ops(ah);
  }
  
- int ath9k_hw_init(struct ath_hw *ah)
+ /* Called for all hardware families */
+ static int __ath9k_hw_init(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
        int r = 0;
  
-       if (common->bus_ops->ath_bus_type != ATH_USB) {
-               if (!ath9k_hw_devid_supported(ah->hw_version.devid)) {
-                       ath_print(common, ATH_DBG_FATAL,
-                                 "Unsupported device ID: 0x%0x\n",
-                                 ah->hw_version.devid);
-                       return -EOPNOTSUPP;
-               }
-       }
-       ath9k_hw_init_defaults(ah);
-       ath9k_hw_init_config(ah);
+       if (ah->hw_version.devid == AR5416_AR9100_DEVID)
+               ah->hw_version.macVersion = AR_SREV_VERSION_9100;
  
        if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
                ath_print(common, ATH_DBG_FATAL,
                return -EIO;
        }
  
+       ath9k_hw_init_defaults(ah);
+       ath9k_hw_init_config(ah);
+       ath9k_hw_attach_ops(ah);
        if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
                ath_print(common, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
                return -EIO;
        else
                ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
  
-       if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) {
+       if (!ath9k_hw_macversion_supported(ah)) {
                ath_print(common, ATH_DBG_FATAL,
                          "Mac Chip Rev 0x%02x.%x is not supported by "
                          "this driver\n", ah->hw_version.macVersion,
                return -EOPNOTSUPP;
        }
  
-       if (AR_SREV_9100(ah)) {
-               ah->iq_caldata.calData = &iq_cal_multi_sample;
-               ah->supp_cals = IQ_MISMATCH_CAL;
-               ah->is_pciexpress = false;
-       }
-       if (AR_SREV_9271(ah))
+       if (AR_SREV_9271(ah) || AR_SREV_9100(ah))
                ah->is_pciexpress = false;
  
        ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
        ath9k_hw_init_cal_settings(ah);
  
        ah->ani_function = ATH9K_ANI_ALL;
-       if (AR_SREV_9280_10_OR_LATER(ah)) {
+       if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
-               ah->ath9k_hw_rf_set_freq = &ath9k_hw_ar9280_set_channel;
-               ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_9280_spur_mitigate;
-       } else {
-               ah->ath9k_hw_rf_set_freq = &ath9k_hw_set_channel;
-               ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_spur_mitigate;
-       }
  
        ath9k_hw_init_mode_regs(ah);
  
        else
                ath9k_hw_disablepcie(ah);
  
-       /* Support for Japan ch.14 (2484) spread */
-       if (AR_SREV_9287_11_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniCckfirNormal,
-                      ar9287Common_normal_cck_fir_coeff_92871_1,
-                      ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_92871_1), 2);
-               INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
-                      ar9287Common_japan_2484_cck_fir_coeff_92871_1,
-                      ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_92871_1), 2);
-       }
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               ar9002_hw_cck_chan14_spread(ah);
  
        r = ath9k_hw_post_init(ah);
        if (r)
        if (r)
                return r;
  
-       ath9k_hw_init_eeprom_fix(ah);
        r = ath9k_hw_init_macaddr(ah);
        if (r) {
                ath_print(common, ATH_DBG_FATAL,
        else
                ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
  
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ar9003_hw_set_nf_limits(ah);
        ath9k_init_nfcal_hist_buffer(ah);
  
        common->state = ATH_HW_INITIALIZED;
        return 0;
  }
  
- static void ath9k_hw_init_bb(struct ath_hw *ah,
-                            struct ath9k_channel *chan)
+ int ath9k_hw_init(struct ath_hw *ah)
  {
-       u32 synthDelay;
+       int ret;
+       struct ath_common *common = ath9k_hw_common(ah);
  
-       synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
-       if (IS_CHAN_B(chan))
-               synthDelay = (4 * synthDelay) / 22;
-       else
-               synthDelay /= 10;
+       /* These are all the AR5008/AR9001/AR9002 hardware family of chipsets */
+       switch (ah->hw_version.devid) {
+       case AR5416_DEVID_PCI:
+       case AR5416_DEVID_PCIE:
+       case AR5416_AR9100_DEVID:
+       case AR9160_DEVID_PCI:
+       case AR9280_DEVID_PCI:
+       case AR9280_DEVID_PCIE:
+       case AR9285_DEVID_PCIE:
+       case AR9287_DEVID_PCI:
+       case AR9287_DEVID_PCIE:
+       case AR2427_DEVID_PCIE:
+       case AR9300_DEVID_PCIE:
+               break;
+       default:
+               if (common->bus_ops->ath_bus_type == ATH_USB)
+                       break;
+               ath_print(common, ATH_DBG_FATAL,
+                         "Hardware device ID 0x%04x not supported\n",
+                         ah->hw_version.devid);
+               return -EOPNOTSUPP;
+       }
  
-       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+       ret = __ath9k_hw_init(ah);
+       if (ret) {
+               ath_print(common, ATH_DBG_FATAL,
+                         "Unable to initialize hardware; "
+                         "initialization status: %d\n", ret);
+               return ret;
+       }
  
-       udelay(synthDelay + BASE_ACTIVATE_DELAY);
+       return 0;
  }
+ EXPORT_SYMBOL(ath9k_hw_init);
  
  static void ath9k_hw_init_qos(struct ath_hw *ah)
  {
+       ENABLE_REGWRITE_BUFFER(ah);
        REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
        REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
  
        REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
        REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
        REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
  }
  
  static void ath9k_hw_init_pll(struct ath_hw *ah,
                              struct ath9k_channel *chan)
  {
-       u32 pll;
-       if (AR_SREV_9100(ah)) {
-               if (chan && IS_CHAN_5GHZ(chan))
-                       pll = 0x1450;
-               else
-                       pll = 0x1458;
-       } else {
-               if (AR_SREV_9280_10_OR_LATER(ah)) {
-                       pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-                       if (chan && IS_CHAN_HALF_RATE(chan))
-                               pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
-                       else if (chan && IS_CHAN_QUARTER_RATE(chan))
-                               pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-                       if (chan && IS_CHAN_5GHZ(chan)) {
-                               pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
-                               if (AR_SREV_9280_20(ah)) {
-                                       if (((chan->channel % 20) == 0)
-                                           || ((chan->channel % 10) == 0))
-                                               pll = 0x2850;
-                                       else
-                                               pll = 0x142c;
-                               }
-                       } else {
-                               pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
-                       }
+       u32 pll = ath9k_hw_compute_pll_control(ah, chan);
  
-               } else if (AR_SREV_9160_10_OR_LATER(ah)) {
-                       pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-                       if (chan && IS_CHAN_HALF_RATE(chan))
-                               pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
-                       else if (chan && IS_CHAN_QUARTER_RATE(chan))
-                               pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-                       if (chan && IS_CHAN_5GHZ(chan))
-                               pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
-                       else
-                               pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
-               } else {
-                       pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
-                       if (chan && IS_CHAN_HALF_RATE(chan))
-                               pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
-                       else if (chan && IS_CHAN_QUARTER_RATE(chan))
-                               pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
-                       if (chan && IS_CHAN_5GHZ(chan))
-                               pll |= SM(0xa, AR_RTC_PLL_DIV);
-                       else
-                               pll |= SM(0xb, AR_RTC_PLL_DIV);
-               }
-       }
        REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
  
        /* Switch the core clock for ar9271 to 117Mhz */
        REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
  }
  
- static void ath9k_hw_init_chain_masks(struct ath_hw *ah)
- {
-       int rx_chainmask, tx_chainmask;
-       rx_chainmask = ah->rxchainmask;
-       tx_chainmask = ah->txchainmask;
-       switch (rx_chainmask) {
-       case 0x5:
-               REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-                           AR_PHY_SWAP_ALT_CHAIN);
-       case 0x3:
-               if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) {
-                       REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
-                       REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
-                       break;
-               }
-       case 0x1:
-       case 0x2:
-       case 0x7:
-               REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
-               REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
-               break;
-       default:
-               break;
-       }
-       REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
-       if (tx_chainmask == 0x5) {
-               REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-                           AR_PHY_SWAP_ALT_CHAIN);
-       }
-       if (AR_SREV_9100(ah))
-               REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
-                         REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
- }
  static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
                                          enum nl80211_iftype opmode)
  {
                AR_IMR_RXORN |
                AR_IMR_BCNMISC;
  
-       if (ah->config.rx_intr_mitigation)
-               imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
-       else
-               imr_reg |= AR_IMR_RXOK;
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               imr_reg |= AR_IMR_RXOK_HP;
+               if (ah->config.rx_intr_mitigation)
+                       imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+               else
+                       imr_reg |= AR_IMR_RXOK_LP;
+       } else {
+               if (ah->config.rx_intr_mitigation)
+                       imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+               else
+                       imr_reg |= AR_IMR_RXOK;
+       }
  
-       imr_reg |= AR_IMR_TXOK;
+       if (ah->config.tx_intr_mitigation)
+               imr_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR;
+       else
+               imr_reg |= AR_IMR_TXOK;
  
        if (opmode == NL80211_IFTYPE_AP)
                imr_reg |= AR_IMR_MIB;
  
+       ENABLE_REGWRITE_BUFFER(ah);
        REG_WRITE(ah, AR_IMR, imr_reg);
        ah->imrs2_reg |= AR_IMR_S2_GTT;
        REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
                REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
                REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
        }
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0);
+               REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK, 0);
+               REG_WRITE(ah, AR_INTR_PRIO_SYNC_ENABLE, 0);
+               REG_WRITE(ah, AR_INTR_PRIO_SYNC_MASK, 0);
+       }
  }
  
  static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
@@@ -1243,8 -824,7 +825,7 @@@ void ath9k_hw_deinit(struct ath_hw *ah
        ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
  
  free_hw:
-       if (!AR_SREV_9280_10_OR_LATER(ah))
-               ath9k_hw_rf_free_ext_banks(ah);
+       ath9k_hw_rf_free_ext_banks(ah);
  }
  EXPORT_SYMBOL(ath9k_hw_deinit);
  
  /* INI */
  /*******/
  
- static void ath9k_hw_override_ini(struct ath_hw *ah,
-                                 struct ath9k_channel *chan)
- {
-       u32 val;
-       /*
-        * Set the RX_ABORT and RX_DIS and clear if off only after
-        * RXE is set for MAC. This prevents frames with corrupted
-        * descriptor status.
-        */
-       REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
-       if (AR_SREV_9280_10_OR_LATER(ah)) {
-               val = REG_READ(ah, AR_PCU_MISC_MODE2);
-               if (!AR_SREV_9271(ah))
-                       val &= ~AR_PCU_MISC_MODE2_HWWAR1;
-               if (AR_SREV_9287_10_OR_LATER(ah))
-                       val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
-               REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
-       }
-       if (!AR_SREV_5416_20_OR_LATER(ah) ||
-           AR_SREV_9280_10_OR_LATER(ah))
-               return;
-       /*
-        * Disable BB clock gating
-        * Necessary to avoid issues on AR5416 2.0
-        */
-       REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
-       /*
-        * Disable RIFS search on some chips to avoid baseband
-        * hang issues.
-        */
-       if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {
-               val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
-               val &= ~AR_PHY_RIFS_INIT_DELAY;
-               REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
-       }
- }
- static void ath9k_olc_init(struct ath_hw *ah)
- {
-       u32 i;
-       if (OLC_FOR_AR9287_10_LATER) {
-               REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9,
-                               AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
-               ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0,
-                               AR9287_AN_TXPC0_TXPCMODE,
-                               AR9287_AN_TXPC0_TXPCMODE_S,
-                               AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE);
-               udelay(100);
-       } else {
-               for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
-                       ah->originalGain[i] =
-                               MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
-                                               AR_PHY_TX_GAIN);
-               ah->PDADCdelta = 0;
-       }
- }
- static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg,
-                             struct ath9k_channel *chan)
+ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan)
  {
        u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band);
  
        return ctl;
  }
  
- static int ath9k_hw_process_ini(struct ath_hw *ah,
-                               struct ath9k_channel *chan)
- {
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
-       int i, regWrites = 0;
-       struct ieee80211_channel *channel = chan->chan;
-       u32 modesIndex, freqIndex;
-       switch (chan->chanmode) {
-       case CHANNEL_A:
-       case CHANNEL_A_HT20:
-               modesIndex = 1;
-               freqIndex = 1;
-               break;
-       case CHANNEL_A_HT40PLUS:
-       case CHANNEL_A_HT40MINUS:
-               modesIndex = 2;
-               freqIndex = 1;
-               break;
-       case CHANNEL_G:
-       case CHANNEL_G_HT20:
-       case CHANNEL_B:
-               modesIndex = 4;
-               freqIndex = 2;
-               break;
-       case CHANNEL_G_HT40PLUS:
-       case CHANNEL_G_HT40MINUS:
-               modesIndex = 3;
-               freqIndex = 2;
-               break;
-       default:
-               return -EINVAL;
-       }
-       /* Set correct baseband to analog shift setting to access analog chips */
-       REG_WRITE(ah, AR_PHY(0), 0x00000007);
-       /* Write ADDAC shifts */
-       REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
-       ah->eep_ops->set_addac(ah, chan);
-       if (AR_SREV_5416_22_OR_LATER(ah)) {
-               REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
-       } else {
-               struct ar5416IniArray temp;
-               u32 addacSize =
-                       sizeof(u32) * ah->iniAddac.ia_rows *
-                       ah->iniAddac.ia_columns;
-               /* For AR5416 2.0/2.1 */
-               memcpy(ah->addac5416_21,
-                      ah->iniAddac.ia_array, addacSize);
-               /* override CLKDRV value at [row, column] = [31, 1] */
-               (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0;
-               temp.ia_array = ah->addac5416_21;
-               temp.ia_columns = ah->iniAddac.ia_columns;
-               temp.ia_rows = ah->iniAddac.ia_rows;
-               REG_WRITE_ARRAY(&temp, 1, regWrites);
-       }
-       REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
-       for (i = 0; i < ah->iniModes.ia_rows; i++) {
-               u32 reg = INI_RA(&ah->iniModes, i, 0);
-               u32 val = INI_RA(&ah->iniModes, i, modesIndex);
-               if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup)
-                       val &= ~AR_AN_TOP2_PWDCLKIND;
-               REG_WRITE(ah, reg, val);
-               if (reg >= 0x7800 && reg < 0x78a0
-                   && ah->config.analog_shiftreg) {
-                       udelay(100);
-               }
-               DO_DELAY(regWrites);
-       }
-       if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah))
-               REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
-       if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) ||
-           AR_SREV_9287_10_OR_LATER(ah))
-               REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
-       if (AR_SREV_9271_10(ah))
-               REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only,
-                               modesIndex, regWrites);
-       /* Write common array parameters */
-       for (i = 0; i < ah->iniCommon.ia_rows; i++) {
-               u32 reg = INI_RA(&ah->iniCommon, i, 0);
-               u32 val = INI_RA(&ah->iniCommon, i, 1);
-               REG_WRITE(ah, reg, val);
-               if (reg >= 0x7800 && reg < 0x78a0
-                   && ah->config.analog_shiftreg) {
-                       udelay(100);
-               }
-               DO_DELAY(regWrites);
-       }
-       if (AR_SREV_9271(ah)) {
-               if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1)
-                       REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
-                                       modesIndex, regWrites);
-               else
-                       REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
-                                       modesIndex, regWrites);
-       }
-       ath9k_hw_write_regs(ah, freqIndex, regWrites);
-       if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
-               REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
-                               regWrites);
-       }
-       ath9k_hw_override_ini(ah, chan);
-       ath9k_hw_set_regs(ah, chan);
-       ath9k_hw_init_chain_masks(ah);
-       if (OLC_FOR_AR9280_20_LATER)
-               ath9k_olc_init(ah);
-       /* Set TX power */
-       ah->eep_ops->set_txpower(ah, chan,
-                                ath9k_regd_get_ctl(regulatory, chan),
-                                channel->max_antenna_gain * 2,
-                                channel->max_power * 2,
-                                min((u32) MAX_RATE_POWER,
-                                (u32) regulatory->power_limit));
-       /* Write analog registers */
-       if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
-               ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-                         "ar5416SetRfRegs failed\n");
-               return -EIO;
-       }
-       return 0;
- }
- /****************************************/
- /* Reset and Channel Switching Routines */
- /****************************************/
- static void ath9k_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
- {
-       u32 rfMode = 0;
-       if (chan == NULL)
-               return;
-       rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
-               ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
-       if (!AR_SREV_9280_10_OR_LATER(ah))
-               rfMode |= (IS_CHAN_5GHZ(chan)) ?
-                       AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
-       if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
-               rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
-       REG_WRITE(ah, AR_PHY_MODE, rfMode);
- }
- static void ath9k_hw_mark_phy_inactive(struct ath_hw *ah)
- {
-       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
- }
+ /****************************************/
+ /* Reset and Channel Switching Routines */
+ /****************************************/
  
  static inline void ath9k_hw_set_dma(struct ath_hw *ah)
  {
+       struct ath_common *common = ath9k_hw_common(ah);
        u32 regval;
  
+       ENABLE_REGWRITE_BUFFER(ah);
        /*
         * set AHB_MODE not to do cacheline prefetches
        */
-       regval = REG_READ(ah, AR_AHB_MODE);
-       REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
+       if (!AR_SREV_9300_20_OR_LATER(ah)) {
+               regval = REG_READ(ah, AR_AHB_MODE);
+               REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
+       }
  
        /*
         * let mac dma reads be in 128 byte chunks
        regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
        REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
  
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
        /*
         * Restore TX Trigger Level to its pre-reset value.
         * The initial value depends on whether aggregation is enabled, and is
         * adjusted whenever underruns are detected.
         */
-       REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
+       ENABLE_REGWRITE_BUFFER(ah);
  
        /*
         * let mac dma writes be in 128 byte chunks
         */
        REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
  
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_HP, 0x1);
+               REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_LP, 0x1);
+               ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
+                       ah->caps.rx_status_len);
+       }
        /*
         * reduce the number of usable entries in PCU TXBUF to avoid
         * wrap around issues.
                REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
                          AR_PCU_TXBUF_CTRL_USABLE_SIZE);
        }
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ath9k_hw_reset_txstatus_ring(ah);
  }
  
  static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
        }
  }
  
- static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah,
-                                                u32 coef_scaled,
-                                                u32 *coef_mantissa,
-                                                u32 *coef_exponent)
+ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
+                                  u32 *coef_mantissa, u32 *coef_exponent)
  {
        u32 coef_exp, coef_man;
  
        *coef_exponent = coef_exp - 16;
  }
  
- static void ath9k_hw_set_delta_slope(struct ath_hw *ah,
-                                    struct ath9k_channel *chan)
- {
-       u32 coef_scaled, ds_coef_exp, ds_coef_man;
-       u32 clockMhzScaled = 0x64000000;
-       struct chan_centers centers;
-       if (IS_CHAN_HALF_RATE(chan))
-               clockMhzScaled = clockMhzScaled >> 1;
-       else if (IS_CHAN_QUARTER_RATE(chan))
-               clockMhzScaled = clockMhzScaled >> 2;
-       ath9k_hw_get_channel_centers(ah, chan, &centers);
-       coef_scaled = clockMhzScaled / centers.synth_center;
-       ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
-                                     &ds_coef_exp);
-       REG_RMW_FIELD(ah, AR_PHY_TIMING3,
-                     AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
-       REG_RMW_FIELD(ah, AR_PHY_TIMING3,
-                     AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
-       coef_scaled = (9 * coef_scaled) / 10;
-       ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
-                                     &ds_coef_exp);
-       REG_RMW_FIELD(ah, AR_PHY_HALFGI,
-                     AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
-       REG_RMW_FIELD(ah, AR_PHY_HALFGI,
-                     AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
- }
  static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
  {
        u32 rst_flags;
                (void)REG_READ(ah, AR_RTC_DERIVED_CLK);
        }
  
+       ENABLE_REGWRITE_BUFFER(ah);
        REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
                  AR_RTC_FORCE_WAKE_ON_INT);
  
                if (tmpReg &
                    (AR_INTR_SYNC_LOCAL_TIMEOUT |
                     AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+                       u32 val;
                        REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
-                       REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
-               } else {
+                       val = AR_RC_HOSTIF;
+                       if (!AR_SREV_9300_20_OR_LATER(ah))
+                               val |= AR_RC_AHB;
+                       REG_WRITE(ah, AR_RC, val);
+               } else if (!AR_SREV_9300_20_OR_LATER(ah))
                        REG_WRITE(ah, AR_RC, AR_RC_AHB);
-               }
  
                rst_flags = AR_RTC_RC_MAC_WARM;
                if (type == ATH9K_RESET_COLD)
        }
  
        REG_WRITE(ah, AR_RTC_RC, rst_flags);
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
        udelay(50);
  
        REG_WRITE(ah, AR_RTC_RC, 0);
  
  static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
  {
+       ENABLE_REGWRITE_BUFFER(ah);
        REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
                  AR_RTC_FORCE_WAKE_ON_INT);
  
-       if (!AR_SREV_9100(ah))
+       if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                REG_WRITE(ah, AR_RC, AR_RC_AHB);
  
        REG_WRITE(ah, AR_RTC_RESET, 0);
-       udelay(2);
  
-       if (!AR_SREV_9100(ah))
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               udelay(2);
+       if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                REG_WRITE(ah, AR_RC, 0);
  
        REG_WRITE(ah, AR_RTC_RESET, 1);
@@@ -1740,34 -1087,6 +1088,6 @@@ static bool ath9k_hw_set_reset_reg(stru
        }
  }
  
- static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan)
- {
-       u32 phymode;
-       u32 enableDacFifo = 0;
-       if (AR_SREV_9285_10_OR_LATER(ah))
-               enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
-                                        AR_PHY_FC_ENABLE_DAC_FIFO);
-       phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
-               | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;
-       if (IS_CHAN_HT40(chan)) {
-               phymode |= AR_PHY_FC_DYN2040_EN;
-               if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
-                   (chan->chanmode == CHANNEL_G_HT40PLUS))
-                       phymode |= AR_PHY_FC_DYN2040_PRI_CH;
-       }
-       REG_WRITE(ah, AR_PHY_TURBO, phymode);
-       ath9k_hw_set11nmac2040(ah);
-       REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
-       REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
- }
  static bool ath9k_hw_chip_reset(struct ath_hw *ah,
                                struct ath9k_channel *chan)
  {
@@@ -1793,7 -1112,7 +1113,7 @@@ static bool ath9k_hw_channel_change(str
        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ath_common *common = ath9k_hw_common(ah);
        struct ieee80211_channel *channel = chan->chan;
-       u32 synthDelay, qnum;
+       u32 qnum;
        int r;
  
        for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
                }
        }
  
-       REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
-       if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
-                          AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) {
+       if (!ath9k_hw_rfbus_req(ah)) {
                ath_print(common, ATH_DBG_FATAL,
                          "Could not kill baseband RX\n");
                return false;
        }
  
-       ath9k_hw_set_regs(ah, chan);
+       ath9k_hw_set_channel_regs(ah, chan);
  
-       r = ah->ath9k_hw_rf_set_freq(ah, chan);
+       r = ath9k_hw_rf_set_freq(ah, chan);
        if (r) {
                ath_print(common, ATH_DBG_FATAL,
                          "Failed to set channel\n");
                             min((u32) MAX_RATE_POWER,
                             (u32) regulatory->power_limit));
  
-       synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
-       if (IS_CHAN_B(chan))
-               synthDelay = (4 * synthDelay) / 22;
-       else
-               synthDelay /= 10;
-       udelay(synthDelay + BASE_ACTIVATE_DELAY);
-       REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+       ath9k_hw_rfbus_done(ah);
  
        if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
                ath9k_hw_set_delta_slope(ah, chan);
  
-       ah->ath9k_hw_spur_mitigate_freq(ah, chan);
+       ath9k_hw_spur_mitigate_freq(ah, chan);
  
        if (!chan->oneTimeCalsDone)
                chan->oneTimeCalsDone = true;
        return true;
  }
  
static void ath9k_enable_rfkill(struct ath_hw *ah)
bool ath9k_hw_check_alive(struct ath_hw *ah)
  {
-       REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
-                   AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
+       int count = 50;
+       u32 reg;
+       if (AR_SREV_9285_10_OR_LATER(ah))
+               return true;
+       do {
+               reg = REG_READ(ah, AR_OBS_BUS_1);
  
-       REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
-                   AR_GPIO_INPUT_MUX2_RFSILENT);
+               if ((reg & 0x7E7FFFEF) == 0x00702400)
+                       continue;
+               switch (reg & 0x7E000B00) {
+               case 0x1E000000:
+               case 0x52000B00:
+               case 0x18000B00:
+                       continue;
+               default:
+                       return true;
+               }
+       } while (count-- > 0);
  
-       ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
-       REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
+       return false;
  }
+ EXPORT_SYMBOL(ath9k_hw_check_alive);
  
  int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                    bool bChannelChange)
        u32 saveDefAntenna;
        u32 macStaId1;
        u64 tsf = 0;
-       int i, rx_chainmask, r;
+       int i, r;
  
        ah->txchainmask = common->tx_chainmask;
        ah->rxchainmask = common->rx_chainmask;
  
+       if (!ah->chip_fullsleep) {
+               ath9k_hw_abortpcurecv(ah);
+               if (!ath9k_hw_stopdmarecv(ah))
+                       ath_print(common, ATH_DBG_XMIT,
+                               "Failed to stop receive dma\n");
+       }
        if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
                return -EIO;
  
        if (AR_SREV_9280_10_OR_LATER(ah))
                REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
  
-       if (AR_SREV_9287_12_OR_LATER(ah)) {
-               /* Enable ASYNC FIFO */
-               REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
-                               AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
-               REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
-               REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
-                               AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
-               REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
-                               AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
-       }
        r = ath9k_hw_process_ini(ah, chan);
        if (r)
                return r;
        if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
                ath9k_hw_set_delta_slope(ah, chan);
  
-       ah->ath9k_hw_spur_mitigate_freq(ah, chan);
+       ath9k_hw_spur_mitigate_freq(ah, chan);
        ah->eep_ops->set_board_values(ah, chan);
  
+       ath9k_hw_set_operating_mode(ah, ah->opmode);
+       ENABLE_REGWRITE_BUFFER(ah);
        REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
        REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
                  | macStaId1
                  | (ah->config.
                     ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
                  | ah->sta_id1_defaults);
-       ath9k_hw_set_operating_mode(ah, ah->opmode);
        ath_hw_setbssidmask(common);
        REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
        ath9k_hw_write_associd(ah);
        REG_WRITE(ah, AR_ISR, ~0);
        REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
  
-       r = ah->ath9k_hw_rf_set_freq(ah, chan);
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+       r = ath9k_hw_rf_set_freq(ah, chan);
        if (r)
                return r;
  
+       ENABLE_REGWRITE_BUFFER(ah);
        for (i = 0; i < AR_NUM_DCU; i++)
                REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
  
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
        ah->intr_txqs = 0;
        for (i = 0; i < ah->caps.total_queues; i++)
                ath9k_hw_resettxqueue(ah, i);
  
        ath9k_hw_init_global_settings(ah);
  
-       if (AR_SREV_9287_12_OR_LATER(ah)) {
-               REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
-                         AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
-               REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
-                         AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
-               REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
-                         AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
-               REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
-               REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
-               REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
-                           AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
-               REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
-                             AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
-       }
-       if (AR_SREV_9287_12_OR_LATER(ah)) {
-               REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
-                               AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
+       if (!AR_SREV_9300_20_OR_LATER(ah)) {
+               ar9002_hw_enable_async_fifo(ah);
+               ar9002_hw_enable_wep_aggregation(ah);
        }
  
        REG_WRITE(ah, AR_STA_ID1,
                REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
        }
  
+       if (ah->config.tx_intr_mitigation) {
+               REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300);
+               REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750);
+       }
        ath9k_hw_init_bb(ah, chan);
  
        if (!ath9k_hw_init_cal(ah, chan))
                return -EIO;
  
-       rx_chainmask = ah->rxchainmask;
-       if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
-               REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
-               REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
-       }
+       ENABLE_REGWRITE_BUFFER(ah);
  
+       ath9k_hw_restore_chainmask(ah);
        REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
  
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
        /*
         * For big endian systems turn on swapping for descriptors
         */
        if (ah->btcoex_hw.enabled)
                ath9k_hw_btcoex_enable(ah);
  
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               ath9k_hw_loadnf(ah, curchan);
+               ath9k_hw_start_nfcal(ah);
+       }
        return 0;
  }
  EXPORT_SYMBOL(ath9k_hw_reset);
@@@ -2379,21 -1701,35 +1702,35 @@@ EXPORT_SYMBOL(ath9k_hw_keyisvalid)
  /* Power Management (Chipset) */
  /******************************/
  
+ /*
+  * Notify Power Mgt is disabled in self-generated frames.
+  * If requested, force chip to sleep.
+  */
  static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
  {
        REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
        if (setChip) {
+               /*
+                * Clear the RTC force wake bit to allow the
+                * mac to go to sleep.
+                */
                REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
                            AR_RTC_FORCE_WAKE_EN);
-               if (!AR_SREV_9100(ah))
+               if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                        REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
  
+               /* Shutdown chip. Active low */
                if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah))
                        REG_CLR_BIT(ah, (AR_RTC_RESET),
                                    AR_RTC_RESET_EN);
        }
  }
  
+ /*
+  * Notify Power Management is enabled in self-generating
+  * frames. If request, set power mode of chip to
+  * auto/normal.  Duration in units of 128us (1/8 TU).
+  */
  static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
  {
        REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
                struct ath9k_hw_capabilities *pCap = &ah->caps;
  
                if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+                       /* Set WakeOnInterrupt bit; clear ForceWake bit */
                        REG_WRITE(ah, AR_RTC_FORCE_WAKE,
                                  AR_RTC_FORCE_WAKE_ON_INT);
                } else {
+                       /*
+                        * Clear the RTC force wake bit to allow the
+                        * mac to go to sleep.
+                        */
                        REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
                                    AR_RTC_FORCE_WAKE_EN);
                }
@@@ -2422,7 -1763,8 +1764,8 @@@ static bool ath9k_hw_set_power_awake(st
                                           ATH9K_RESET_POWER_ON) != true) {
                                return false;
                        }
-                       ath9k_hw_init_pll(ah, NULL);
+                       if (!AR_SREV_9300_20_OR_LATER(ah))
+                               ath9k_hw_init_pll(ah, NULL);
                }
                if (AR_SREV_9100(ah))
                        REG_SET_BIT(ah, AR_RTC_RESET,
@@@ -2492,420 -1834,6 +1835,6 @@@ bool ath9k_hw_setpower(struct ath_hw *a
  }
  EXPORT_SYMBOL(ath9k_hw_setpower);
  
- /*
-  * Helper for ASPM support.
-  *
-  * Disable PLL when in L0s as well as receiver clock when in L1.
-  * This power saving option must be enabled through the SerDes.
-  *
-  * Programming the SerDes must go through the same 288 bit serial shift
-  * register as the other analog registers.  Hence the 9 writes.
-  */
- void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off)
- {
-       u8 i;
-       u32 val;
-       if (ah->is_pciexpress != true)
-               return;
-       /* Do not touch SerDes registers */
-       if (ah->config.pcie_powersave_enable == 2)
-               return;
-       /* Nothing to do on restore for 11N */
-       if (!restore) {
-               if (AR_SREV_9280_20_OR_LATER(ah)) {
-                       /*
-                        * AR9280 2.0 or later chips use SerDes values from the
-                        * initvals.h initialized depending on chipset during
-                        * ath9k_hw_init()
-                        */
-                       for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
-                               REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
-                                         INI_RA(&ah->iniPcieSerdes, i, 1));
-                       }
-               } else if (AR_SREV_9280(ah) &&
-                          (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
-                       /* RX shut off when elecidle is asserted */
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
-                       /* Shut off CLKREQ active in L1 */
-                       if (ah->config.pcie_clock_req)
-                               REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
-                       else
-                               REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
-                       /* Load the new settings */
-                       REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-               } else {
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
-                       /* RX shut off when elecidle is asserted */
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
-                       /*
-                        * Ignore ah->ah_config.pcie_clock_req setting for
-                        * pre-AR9280 11n
-                        */
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
-                       /* Load the new settings */
-                       REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-               }
-               udelay(1000);
-               /* set bit 19 to allow forcing of pcie core into L1 state */
-               REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
-               /* Several PCIe massages to ensure proper behaviour */
-               if (ah->config.pcie_waen) {
-                       val = ah->config.pcie_waen;
-                       if (!power_off)
-                               val &= (~AR_WA_D3_L1_DISABLE);
-               } else {
-                       if (AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
-                           AR_SREV_9287(ah)) {
-                               val = AR9285_WA_DEFAULT;
-                               if (!power_off)
-                                       val &= (~AR_WA_D3_L1_DISABLE);
-                       } else if (AR_SREV_9280(ah)) {
-                               /*
-                                * On AR9280 chips bit 22 of 0x4004 needs to be
-                                * set otherwise card may disappear.
-                                */
-                               val = AR9280_WA_DEFAULT;
-                               if (!power_off)
-                                       val &= (~AR_WA_D3_L1_DISABLE);
-                       } else
-                               val = AR_WA_DEFAULT;
-               }
-               REG_WRITE(ah, AR_WA, val);
-       }
-       if (power_off) {
-               /*
-                * Set PCIe workaround bits
-                * bit 14 in WA register (disable L1) should only
-                * be set when device enters D3 and be cleared
-                * when device comes back to D0.
-                */
-               if (ah->config.pcie_waen) {
-                       if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
-                               REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
-               } else {
-                       if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
-                             AR_SREV_9287(ah)) &&
-                            (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
-                           (AR_SREV_9280(ah) &&
-                            (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
-                               REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
-                       }
-               }
-       }
- }
- EXPORT_SYMBOL(ath9k_hw_configpcipowersave);
- /**********************/
- /* Interrupt Handling */
- /**********************/
- bool ath9k_hw_intrpend(struct ath_hw *ah)
- {
-       u32 host_isr;
-       if (AR_SREV_9100(ah))
-               return true;
-       host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
-       if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
-               return true;
-       host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
-       if ((host_isr & AR_INTR_SYNC_DEFAULT)
-           && (host_isr != AR_INTR_SPURIOUS))
-               return true;
-       return false;
- }
- EXPORT_SYMBOL(ath9k_hw_intrpend);
- bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
- {
-       u32 isr = 0;
-       u32 mask2 = 0;
-       struct ath9k_hw_capabilities *pCap = &ah->caps;
-       u32 sync_cause = 0;
-       bool fatal_int = false;
-       struct ath_common *common = ath9k_hw_common(ah);
-       if (!AR_SREV_9100(ah)) {
-               if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
-                       if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
-                           == AR_RTC_STATUS_ON) {
-                               isr = REG_READ(ah, AR_ISR);
-                       }
-               }
-               sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
-                       AR_INTR_SYNC_DEFAULT;
-               *masked = 0;
-               if (!isr && !sync_cause)
-                       return false;
-       } else {
-               *masked = 0;
-               isr = REG_READ(ah, AR_ISR);
-       }
-       if (isr) {
-               if (isr & AR_ISR_BCNMISC) {
-                       u32 isr2;
-                       isr2 = REG_READ(ah, AR_ISR_S2);
-                       if (isr2 & AR_ISR_S2_TIM)
-                               mask2 |= ATH9K_INT_TIM;
-                       if (isr2 & AR_ISR_S2_DTIM)
-                               mask2 |= ATH9K_INT_DTIM;
-                       if (isr2 & AR_ISR_S2_DTIMSYNC)
-                               mask2 |= ATH9K_INT_DTIMSYNC;
-                       if (isr2 & (AR_ISR_S2_CABEND))
-                               mask2 |= ATH9K_INT_CABEND;
-                       if (isr2 & AR_ISR_S2_GTT)
-                               mask2 |= ATH9K_INT_GTT;
-                       if (isr2 & AR_ISR_S2_CST)
-                               mask2 |= ATH9K_INT_CST;
-                       if (isr2 & AR_ISR_S2_TSFOOR)
-                               mask2 |= ATH9K_INT_TSFOOR;
-               }
-               isr = REG_READ(ah, AR_ISR_RAC);
-               if (isr == 0xffffffff) {
-                       *masked = 0;
-                       return false;
-               }
-               *masked = isr & ATH9K_INT_COMMON;
-               if (ah->config.rx_intr_mitigation) {
-                       if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
-                               *masked |= ATH9K_INT_RX;
-               }
-               if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
-                       *masked |= ATH9K_INT_RX;
-               if (isr &
-                   (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
-                    AR_ISR_TXEOL)) {
-                       u32 s0_s, s1_s;
-                       *masked |= ATH9K_INT_TX;
-                       s0_s = REG_READ(ah, AR_ISR_S0_S);
-                       ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
-                       ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
-                       s1_s = REG_READ(ah, AR_ISR_S1_S);
-                       ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
-                       ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
-               }
-               if (isr & AR_ISR_RXORN) {
-                       ath_print(common, ATH_DBG_INTERRUPT,
-                                 "receive FIFO overrun interrupt\n");
-               }
-               if (!AR_SREV_9100(ah)) {
-                       if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
-                               u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
-                               if (isr5 & AR_ISR_S5_TIM_TIMER)
-                                       *masked |= ATH9K_INT_TIM_TIMER;
-                       }
-               }
-               *masked |= mask2;
-       }
-       if (AR_SREV_9100(ah))
-               return true;
-       if (isr & AR_ISR_GENTMR) {
-               u32 s5_s;
-               s5_s = REG_READ(ah, AR_ISR_S5_S);
-               if (isr & AR_ISR_GENTMR) {
-                       ah->intr_gen_timer_trigger =
-                               MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
-                       ah->intr_gen_timer_thresh =
-                               MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
-                       if (ah->intr_gen_timer_trigger)
-                               *masked |= ATH9K_INT_GENTIMER;
-               }
-       }
-       if (sync_cause) {
-               fatal_int =
-                       (sync_cause &
-                        (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
-                       ? true : false;
-               if (fatal_int) {
-                       if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
-                               ath_print(common, ATH_DBG_ANY,
-                                         "received PCI FATAL interrupt\n");
-                       }
-                       if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
-                               ath_print(common, ATH_DBG_ANY,
-                                         "received PCI PERR interrupt\n");
-                       }
-                       *masked |= ATH9K_INT_FATAL;
-               }
-               if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
-                       ath_print(common, ATH_DBG_INTERRUPT,
-                                 "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
-                       REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
-                       REG_WRITE(ah, AR_RC, 0);
-                       *masked |= ATH9K_INT_FATAL;
-               }
-               if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
-                       ath_print(common, ATH_DBG_INTERRUPT,
-                                 "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
-               }
-               REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
-               (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
-       }
-       return true;
- }
- EXPORT_SYMBOL(ath9k_hw_getisr);
- enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
- {
-       enum ath9k_int omask = ah->imask;
-       u32 mask, mask2;
-       struct ath9k_hw_capabilities *pCap = &ah->caps;
-       struct ath_common *common = ath9k_hw_common(ah);
-       ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
-       if (omask & ATH9K_INT_GLOBAL) {
-               ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
-               REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
-               (void) REG_READ(ah, AR_IER);
-               if (!AR_SREV_9100(ah)) {
-                       REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
-                       (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
-                       REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
-                       (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
-               }
-       }
-       mask = ints & ATH9K_INT_COMMON;
-       mask2 = 0;
-       if (ints & ATH9K_INT_TX) {
-               if (ah->txok_interrupt_mask)
-                       mask |= AR_IMR_TXOK;
-               if (ah->txdesc_interrupt_mask)
-                       mask |= AR_IMR_TXDESC;
-               if (ah->txerr_interrupt_mask)
-                       mask |= AR_IMR_TXERR;
-               if (ah->txeol_interrupt_mask)
-                       mask |= AR_IMR_TXEOL;
-       }
-       if (ints & ATH9K_INT_RX) {
-               mask |= AR_IMR_RXERR;
-               if (ah->config.rx_intr_mitigation)
-                       mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
-               else
-                       mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
-               if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
-                       mask |= AR_IMR_GENTMR;
-       }
-       if (ints & (ATH9K_INT_BMISC)) {
-               mask |= AR_IMR_BCNMISC;
-               if (ints & ATH9K_INT_TIM)
-                       mask2 |= AR_IMR_S2_TIM;
-               if (ints & ATH9K_INT_DTIM)
-                       mask2 |= AR_IMR_S2_DTIM;
-               if (ints & ATH9K_INT_DTIMSYNC)
-                       mask2 |= AR_IMR_S2_DTIMSYNC;
-               if (ints & ATH9K_INT_CABEND)
-                       mask2 |= AR_IMR_S2_CABEND;
-               if (ints & ATH9K_INT_TSFOOR)
-                       mask2 |= AR_IMR_S2_TSFOOR;
-       }
-       if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
-               mask |= AR_IMR_BCNMISC;
-               if (ints & ATH9K_INT_GTT)
-                       mask2 |= AR_IMR_S2_GTT;
-               if (ints & ATH9K_INT_CST)
-                       mask2 |= AR_IMR_S2_CST;
-       }
-       ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
-       REG_WRITE(ah, AR_IMR, mask);
-       ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
-                          AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
-                          AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
-       ah->imrs2_reg |= mask2;
-       REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
-       if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
-               if (ints & ATH9K_INT_TIM_TIMER)
-                       REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
-               else
-                       REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
-       }
-       if (ints & ATH9K_INT_GLOBAL) {
-               ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
-               REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
-               if (!AR_SREV_9100(ah)) {
-                       REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
-                                 AR_INTR_MAC_IRQ);
-                       REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
-                       REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
-                                 AR_INTR_SYNC_DEFAULT);
-                       REG_WRITE(ah, AR_INTR_SYNC_MASK,
-                                 AR_INTR_SYNC_DEFAULT);
-               }
-               ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
-                         REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
-       }
-       return omask;
- }
- EXPORT_SYMBOL(ath9k_hw_set_interrupts);
  /*******************/
  /* Beacon Handling */
  /*******************/
@@@ -2916,6 -1844,8 +1845,8 @@@ void ath9k_hw_beaconinit(struct ath_hw 
  
        ah->beacon_interval = beacon_period;
  
+       ENABLE_REGWRITE_BUFFER(ah);
        switch (ah->opmode) {
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_MONITOR:
        REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period));
        REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
  
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
        beacon_period &= ~ATH9K_BEACON_ENA;
        if (beacon_period & ATH9K_BEACON_RESET_TSF) {
                ath9k_hw_reset_tsf(ah);
@@@ -2975,6 -1908,8 +1909,8 @@@ void ath9k_hw_set_sta_beacon_timers(str
        struct ath9k_hw_capabilities *pCap = &ah->caps;
        struct ath_common *common = ath9k_hw_common(ah);
  
+       ENABLE_REGWRITE_BUFFER(ah);
        REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
  
        REG_WRITE(ah, AR_BEACON_PERIOD,
        REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
                  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
  
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
        REG_RMW_FIELD(ah, AR_RSSI_THR,
                      AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
  
        ath_print(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval);
        ath_print(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod);
  
+       ENABLE_REGWRITE_BUFFER(ah);
        REG_WRITE(ah, AR_NEXT_DTIM,
                  TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
        REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
        REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
        REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
  
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
        REG_SET_BIT(ah, AR_TIMER_MODE,
                    AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
                    AR_DTIM_TIMER_EN);
@@@ -3241,6 -2184,20 +2185,20 @@@ int ath9k_hw_fill_cap_info(struct ath_h
                btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE;
        }
  
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC;
+               pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
+               pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH;
+               pCap->rx_status_len = sizeof(struct ar9003_rxs);
+               pCap->tx_desc_len = sizeof(struct ar9003_txc);
+               pCap->txs_len = sizeof(struct ar9003_txs);
+       } else {
+               pCap->tx_desc_len = sizeof(struct ath_desc);
+       }
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
        return 0;
  }
  
@@@ -3273,10 -2230,6 +2231,6 @@@ bool ath9k_hw_getcapability(struct ath_
        case ATH9K_CAP_TKIP_SPLIT:
                return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ?
                        false : true;
-       case ATH9K_CAP_DIVERSITY:
-               return (REG_READ(ah, AR_PHY_CCK_DETECT) &
-                       AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
-                       true : false;
        case ATH9K_CAP_MCAST_KEYSRCH:
                switch (capability) {
                case 0:
@@@ -3319,8 -2272,6 +2273,6 @@@ EXPORT_SYMBOL(ath9k_hw_getcapability)
  bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
                            u32 capability, u32 setting, int *status)
  {
-       u32 v;
        switch (type) {
        case ATH9K_CAP_TKIP_MIC:
                if (setting)
                        ah->sta_id1_defaults &=
                                ~AR_STA_ID1_CRPT_MIC_ENABLE;
                return true;
-       case ATH9K_CAP_DIVERSITY:
-               v = REG_READ(ah, AR_PHY_CCK_DETECT);
-               if (setting)
-                       v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-               else
-                       v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-               REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
-               return true;
        case ATH9K_CAP_MCAST_KEYSRCH:
                if (setting)
                        ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH;
@@@ -3405,7 -2348,9 +2349,9 @@@ u32 ath9k_hw_gpio_get(struct ath_hw *ah
        if (gpio >= ah->caps.num_gpio_pins)
                return 0xffffffff;
  
-       if (AR_SREV_9271(ah))
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               return MS_REG_READ(AR9300, gpio) != 0;
+       else if (AR_SREV_9271(ah))
                return MS_REG_READ(AR9271, gpio) != 0;
        else if (AR_SREV_9287_10_OR_LATER(ah))
                return MS_REG_READ(AR9287, gpio) != 0;
@@@ -3478,6 -2423,8 +2424,8 @@@ void ath9k_hw_setrxfilter(struct ath_h
  {
        u32 phybits;
  
+       ENABLE_REGWRITE_BUFFER(ah);
        REG_WRITE(ah, AR_RX_FILTER, bits);
  
        phybits = 0;
        else
                REG_WRITE(ah, AR_RXCFG,
                          REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
  }
  EXPORT_SYMBOL(ath9k_hw_setrxfilter);
  
@@@ -3565,14 -2515,25 +2516,25 @@@ void ath9k_hw_write_associd(struct ath_
  }
  EXPORT_SYMBOL(ath9k_hw_write_associd);
  
+ #define ATH9K_MAX_TSF_READ 10
  u64 ath9k_hw_gettsf64(struct ath_hw *ah)
  {
-       u64 tsf;
+       u32 tsf_lower, tsf_upper1, tsf_upper2;
+       int i;
+       tsf_upper1 = REG_READ(ah, AR_TSF_U32);
+       for (i = 0; i < ATH9K_MAX_TSF_READ; i++) {
+               tsf_lower = REG_READ(ah, AR_TSF_L32);
+               tsf_upper2 = REG_READ(ah, AR_TSF_U32);
+               if (tsf_upper2 == tsf_upper1)
+                       break;
+               tsf_upper1 = tsf_upper2;
+       }
  
-       tsf = REG_READ(ah, AR_TSF_U32);
-       tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
+       WARN_ON( i == ATH9K_MAX_TSF_READ );
  
-       return tsf;
+       return (((u64)tsf_upper1 << 32) | tsf_lower);
  }
  EXPORT_SYMBOL(ath9k_hw_gettsf64);
  
@@@ -3847,6 -2808,7 +2809,7 @@@ static struct 
        { AR_SREV_VERSION_9285,         "9285" },
        { AR_SREV_VERSION_9287,         "9287" },
        { AR_SREV_VERSION_9271,         "9271" },
+       { AR_SREV_VERSION_9300,         "9300" },
  };
  
  /* For devices with external radios */
@@@ -14,8 -14,6 +14,8 @@@
   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   */
  
 +#include <linux/slab.h>
 +
  #include "ath9k.h"
  
  static char *dev_info = "ath9k";
@@@ -175,6 -173,18 +175,18 @@@ static const struct ath_ops ath9k_commo
        .write = ath9k_iowrite32,
  };
  
+ static int count_streams(unsigned int chainmask, int max)
+ {
+       int streams = 0;
+       do {
+               if (++streams == max)
+                       break;
+       } while ((chainmask = chainmask & (chainmask - 1)));
+       return streams;
+ }
  /**************************/
  /*     Initialization     */
  /**************************/
  static void setup_ht_cap(struct ath_softc *sc,
                         struct ieee80211_sta_ht_cap *ht_info)
  {
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
        u8 tx_streams, rx_streams;
+       int i, max_streams;
  
        ht_info->ht_supported = true;
        ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
                       IEEE80211_HT_CAP_SGI_40 |
                       IEEE80211_HT_CAP_DSSSCCK40;
  
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC)
+               ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
        ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
        ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
  
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               max_streams = 3;
+       else
+               max_streams = 2;
+       if (AR_SREV_9280_10_OR_LATER(ah)) {
+               if (max_streams >= 2)
+                       ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
+               ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+       }
        /* set up supported mcs set */
        memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
-       tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ?
-                    1 : 2;
-       rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ?
-                    1 : 2;
+       tx_streams = count_streams(common->tx_chainmask, max_streams);
+       rx_streams = count_streams(common->rx_chainmask, max_streams);
+       ath_print(common, ATH_DBG_CONFIG,
+                 "TX streams %d, RX streams: %d\n",
+                 tx_streams, rx_streams);
  
        if (tx_streams != rx_streams) {
-               ath_print(common, ATH_DBG_CONFIG,
-                         "TX streams %d, RX streams: %d\n",
-                         tx_streams, rx_streams);
                ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
                ht_info->mcs.tx_params |= ((tx_streams - 1) <<
                                IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
        }
  
-       ht_info->mcs.rx_mask[0] = 0xff;
-       if (rx_streams >= 2)
-               ht_info->mcs.rx_mask[1] = 0xff;
+       for (i = 0; i < rx_streams; i++)
+               ht_info->mcs.rx_mask[i] = 0xff;
  
        ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
  }
@@@ -235,31 -259,37 +261,37 @@@ static int ath9k_reg_notifier(struct wi
  */
  int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
                      struct list_head *head, const char *name,
-                     int nbuf, int ndesc)
+                     int nbuf, int ndesc, bool is_tx)
  {
  #define       DS2PHYS(_dd, _ds)                                               \
        ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
  #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
  #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath_desc *ds;
+       u8 *ds;
        struct ath_buf *bf;
-       int i, bsize, error;
+       int i, bsize, error, desc_len;
  
        ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
                  name, nbuf, ndesc);
  
        INIT_LIST_HEAD(head);
+       if (is_tx)
+               desc_len = sc->sc_ah->caps.tx_desc_len;
+       else
+               desc_len = sizeof(struct ath_desc);
        /* ath_desc must be a multiple of DWORDs */
-       if ((sizeof(struct ath_desc) % 4) != 0) {
+       if ((desc_len % 4) != 0) {
                ath_print(common, ATH_DBG_FATAL,
                          "ath_desc not DWORD aligned\n");
-               BUG_ON((sizeof(struct ath_desc) % 4) != 0);
+               BUG_ON((desc_len % 4) != 0);
                error = -ENOMEM;
                goto fail;
        }
  
-       dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
+       dd->dd_desc_len = desc_len * nbuf * ndesc;
  
        /*
         * Need additional DMA memory because we can't use
                u32 dma_len;
  
                while (ndesc_skipped) {
-                       dma_len = ndesc_skipped * sizeof(struct ath_desc);
+                       dma_len = ndesc_skipped * desc_len;
                        dd->dd_desc_len += dma_len;
  
                        ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
                error = -ENOMEM;
                goto fail;
        }
-       ds = dd->dd_desc;
+       ds = (u8 *) dd->dd_desc;
        ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
                  name, ds, (u32) dd->dd_desc_len,
                  ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
        }
        dd->dd_bufptr = bf;
  
-       for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
+       for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
                bf->bf_desc = ds;
                bf->bf_daddr = DS2PHYS(dd, ds);
  
                                       ((caddr_t) dd->dd_desc +
                                        dd->dd_desc_len));
  
-                               ds += ndesc;
+                               ds += (desc_len * ndesc);
                                bf->bf_desc = ds;
                                bf->bf_daddr = DS2PHYS(dd, ds);
                        }
@@@ -514,7 -544,7 +546,7 @@@ static void ath9k_init_misc(struct ath_
        common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
        common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
  
-       ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
+       ath9k_hw_set_diversity(sc->sc_ah, true);
        sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
  
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
@@@ -568,13 -598,10 +600,10 @@@ static int ath9k_init_softc(u16 devid, 
        ath_read_cachesize(common, &csz);
        common->cachelsz = csz << 2; /* convert to bytes */
  
+       /* Initializes the hardware for all supported chipsets */
        ret = ath9k_hw_init(ah);
-       if (ret) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unable to initialize hardware; "
-                         "initialization status: %d\n", ret);
+       if (ret)
                goto err_hw;
-       }
  
        ret = ath9k_init_debug(ah);
        if (ret) {
@@@ -15,8 -15,6 +15,8 @@@
   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   */
  
 +#include <linux/slab.h>
 +
  #include "ath9k.h"
  
  static const struct ath_rate_table ar5416_11na_ratetable = {
@@@ -691,6 -689,19 +691,19 @@@ static void ath_get_rate(void *priv, st
        rate_table = sc->cur_rate_table;
        rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
  
+       /*
+        * If we're in HT mode and both us and our peer supports LDPC.
+        * We don't need to check our own device's capabilities as our own
+        * ht capabilities would have already been intersected with our peer's.
+        */
+       if (conf_is_ht(&sc->hw->conf) &&
+           (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
+               tx_info->flags |= IEEE80211_TX_CTL_LDPC;
+       if (conf_is_ht(&sc->hw->conf) &&
+           (sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))
+               tx_info->flags |= (1 << IEEE80211_TX_CTL_STBC_SHIFT);
        if (is_probe) {
                /* set one try for probe rates. For the
                 * probes don't enable rts */
@@@ -27,7 -27,6 +27,7 @@@
  #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>
@@@ -2688,6 -2687,7 +2688,7 @@@ IWL3945_UCODE_GET(boot_size)
  static struct iwl_hcmd_ops iwl3945_hcmd = {
        .rxon_assoc = iwl3945_send_rxon_assoc,
        .commit_rxon = iwl3945_commit_rxon,
+       .send_bt_config = iwl_send_bt_config,
  };
  
  static struct iwl_ucode_ops iwl3945_ucode = {
@@@ -2741,6 -2741,7 +2742,7 @@@ static struct iwl_hcmd_utils_ops iwl394
        .get_hcmd_size = iwl3945_get_hcmd_size,
        .build_addsta_hcmd = iwl3945_build_addsta_hcmd,
        .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
+       .request_scan = iwl3945_request_scan,
  };
  
  static const struct iwl_ops iwl3945_ops = {
@@@ -26,7 -26,6 +26,7 @@@
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/skbuff.h>
 +#include <linux/slab.h>
  #include <linux/wireless.h>
  #include <net/mac80211.h>
  
@@@ -295,11 -294,11 +295,11 @@@ static u32 rs_tl_get_load(struct iwl_lq
        return tl->total;
  }
  
- static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
+ static int 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;
+       int ret = -EAGAIN;
  
        if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
                IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
                         */
                        IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
                                tid);
-                       ret = ieee80211_stop_tx_ba_session(sta, tid,
+                       ieee80211_stop_tx_ba_session(sta, tid,
                                                WLAN_BACK_INITIATOR);
                }
-       }
+       } else
+               IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid);
+       return ret;
  }
  
  static void 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))
-               rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
-       else if (tid == IWL_AGG_ALL_TID)
-               for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
-                       rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
-       if (priv->cfg->use_rts_for_ht) {
-               /*
-                * switch to RTS/CTS if it is the prefer protection method
-                * for HT traffic
-                */
-               IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n");
-               priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
-               iwlcore_commit_rxon(priv);
+       if ((tid < TID_MAX_LOAD_COUNT) &&
+           !rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) {
+               if (priv->cfg->use_rts_for_ht) {
+                       /*
+                        * switch to RTS/CTS if it is the prefer protection
+                        * method for HT traffic
+                        */
+                       IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n");
+                       priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
+                       iwlcore_commit_rxon(priv);
+               }
        }
  }
  
@@@ -2558,8 -2557,17 +2558,17 @@@ void iwl_rs_rate_init(struct iwl_priv *
                     lq_sta->active_mimo3_rate);
  
        /* These values will be overridden later */
-       lq_sta->lq.general_params.single_stream_ant_msk = ANT_A;
-       lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
+       lq_sta->lq.general_params.single_stream_ant_msk =
+               first_antenna(priv->hw_params.valid_tx_ant);
+       lq_sta->lq.general_params.dual_stream_ant_msk =
+               priv->hw_params.valid_tx_ant &
+               ~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 (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;
@@@ -31,7 -31,6 +31,7 @@@
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/pci.h>
 +#include <linux/slab.h>
  #include <linux/dma-mapping.h>
  #include <linux/delay.h>
  #include <linux/sched.h>
@@@ -2174,7 -2173,7 +2174,7 @@@ static void iwl_alive_start(struct iwl_
        }
  
        /* Configure Bluetooth device coexistence support */
-       iwl_send_bt_config(priv);
+       priv->cfg->ops->hcmd->send_bt_config(priv);
  
        iwl_reset_run_time_calib(priv);
  
@@@ -3178,44 -3177,6 +3178,6 @@@ static ssize_t store_tx_power(struct de
  
  static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
  
- static ssize_t show_statistics(struct device *d,
-                              struct device_attribute *attr, char *buf)
- {
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       u32 size = sizeof(struct iwl_notif_statistics);
-       u32 len = 0, ofs = 0;
-       u8 *data = (u8 *)&priv->statistics;
-       int rc = 0;
-       if (!iwl_is_alive(priv))
-               return -EAGAIN;
-       mutex_lock(&priv->mutex);
-       rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
-       mutex_unlock(&priv->mutex);
-       if (rc) {
-               len = sprintf(buf,
-                             "Error sending statistics request: 0x%08X\n", rc);
-               return len;
-       }
-       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 DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
  static ssize_t show_rts_ht_protection(struct device *d,
                             struct device_attribute *attr, char *buf)
  {
@@@ -3401,11 -3362,10 +3363,10 @@@ static void iwl_uninit_drv(struct iwl_p
        iwl_calib_free_results(priv);
        iwlcore_free_geos(priv);
        iwl_free_channel_map(priv);
-       kfree(priv->scan);
+       kfree(priv->scan_cmd);
  }
  
  static struct attribute *iwl_sysfs_entries[] = {
-       &dev_attr_statistics.attr,
        &dev_attr_temperature.attr,
        &dev_attr_tx_power.attr,
        &dev_attr_rts_ht_protection.attr,
@@@ -3836,7 -3796,12 +3797,12 @@@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_c
        {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
        {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
        {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000i_g2_2agn_cfg)},
+ /* 6x00 Series Gen2 */
+       {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2_2agn_cfg)},
  
  /* 6x50 WiFi/WiMax Series */
        {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
@@@ -30,7 -30,6 +30,7 @@@
  #include <linux/module.h>
  #include <linux/etherdevice.h>
  #include <linux/sched.h>
 +#include <linux/slab.h>
  #include <net/mac80211.h>
  
  #include "iwl-eeprom.h"
@@@ -829,19 -828,6 +829,6 @@@ static u8 iwl_count_chain_bitmap(u32 ch
  }
  
  /**
-  * iwl_is_monitor_mode - Determine if interface in monitor mode
-  *
-  * priv->iw_mode is set in add_interface, but add_interface is
-  * never called for monitor mode. The only way mac80211 informs us about
-  * monitor mode is through configuring filters (call to configure_filter).
-  */
- bool iwl_is_monitor_mode(struct iwl_priv *priv)
- {
-       return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK);
- }
- EXPORT_SYMBOL(iwl_is_monitor_mode);
- /**
   * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
   *
   * Selects how many and which Rx receivers/antennas/chains to use.
@@@ -884,19 -870,6 +871,6 @@@ void iwl_set_rxon_chain(struct iwl_pri
        rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
        rx_chain |= idle_rx_cnt  << RXON_RX_CHAIN_CNT_POS;
  
-       /* copied from 'iwl_bg_request_scan()' */
-       /* Force use of chains B and C (0x6) for Rx
-        * Avoid A (0x1) for the device has off-channel reception on A-band.
-        * MIMO is not used here, but value is required */
-       if (iwl_is_monitor_mode(priv) &&
-           !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) &&
-           priv->cfg->off_channel_workaround) {
-               rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS;
-               rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS;
-               rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
-               rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
-       }
        priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
  
        if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
@@@ -1480,7 -1453,7 +1454,7 @@@ irqreturn_t iwl_isr_legacy(int irq, voi
  }
  EXPORT_SYMBOL(iwl_isr_legacy);
  
int iwl_send_bt_config(struct iwl_priv *priv)
void iwl_send_bt_config(struct iwl_priv *priv)
  {
        struct iwl_bt_cmd bt_cmd = {
                .lead_time = BT_LEAD_TIME_DEF,
        IWL_DEBUG_INFO(priv, "BT coex %s\n",
                (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
  
-       return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
-                               sizeof(struct iwl_bt_cmd), &bt_cmd);
+       if (iwl_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_send_bt_config);
  
@@@ -1868,7 -1842,6 +1843,6 @@@ static inline void iwl_set_no_assoc(str
        iwlcore_commit_rxon(priv);
  }
  
- #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
  void iwl_bss_info_changed(struct ieee80211_hw *hw,
                          struct ieee80211_vif *vif,
                          struct ieee80211_bss_conf *bss_conf,
  
                        iwl_led_associate(priv);
  
-                       /*
-                        * We have just associated, don't start scan too early
-                        * leave time for EAPOL exchange to complete.
-                        *
-                        * XXX: do this in mac80211
-                        */
-                       priv->next_scan_jiffies = jiffies +
-                                       IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
                        if (!iwl_is_rfkill(priv))
                                priv->cfg->ops->lib->post_associate(priv);
                } else
@@@ -2383,11 -2348,11 +2349,11 @@@ EXPORT_SYMBOL(iwl_free_txq_mem)
  
  int iwl_send_wimax_coex(struct iwl_priv *priv)
  {
-       struct iwl_wimax_coex_cmd uninitialized_var(coex_cmd);
+       struct iwl_wimax_coex_cmd coex_cmd;
  
        if (priv->cfg->support_wimax_coexist) {
                /* UnMask wake up src at associated sleep */
-               coex_cmd.flags |= COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
+               coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
  
                /* UnMask wake up src at unassociated sleep */
                coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK;
   *  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/kernel.h>
 +#include <linux/module.h>
 +#include <linux/debugfs.h>
 +
  #include <linux/ieee80211.h>
  #include <net/mac80211.h>
  
@@@ -106,6 -100,26 +106,26 @@@ static const struct file_operations iwl
        .open = iwl_dbgfs_open_file_generic,                            \
  };
  
+ int iwl_dbgfs_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->statistics.flag));
+       if (le32_to_cpu(priv->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->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->statistics.flag) &
+                       UCODE_STATISTICS_NARROW_BAND_MSK)
+                       ? "enabled" : "disabled");
+       return p;
+ }
+ EXPORT_SYMBOL(iwl_dbgfs_statistics_flag);
  
  static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
                                                char __user *user_buf,
@@@ -1034,474 -1048,15 +1054,15 @@@ static ssize_t iwl_dbgfs_rx_queue_read(
        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  }
  
- static int iwl_dbgfs_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->statistics.flag));
-       if (le32_to_cpu(priv->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->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->statistics.flag) &
-               UCODE_STATISTICS_NARROW_BAND_MSK)
-                ? "enabled" : "disabled");
-       return p;
- }
- static const char ucode_stats_header[] =
-       "%-32s     current  acumulative       delta         max\n";
- static const char ucode_stats_short_format[] =
-       "  %-30s %10u\n";
- static const char ucode_stats_format[] =
-       "  %-30s %10u  %10u  %10u  %10u\n";
  static ssize_t iwl_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;
-       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_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->statistics.rx.ofdm;
-       cck = &priv->statistics.rx.cck;
-       general = &priv->statistics.rx.general;
-       ht = &priv->statistics.rx.ofdm_ht;
-       accum_ofdm = &priv->accum_statistics.rx.ofdm;
-       accum_cck = &priv->accum_statistics.rx.cck;
-       accum_general = &priv->accum_statistics.rx.general;
-       accum_ht = &priv->accum_statistics.rx.ofdm_ht;
-       delta_ofdm = &priv->delta_statistics.rx.ofdm;
-       delta_cck = &priv->delta_statistics.rx.cck;
-       delta_general = &priv->delta_statistics.rx.general;
-       delta_ht = &priv->delta_statistics.rx.ofdm_ht;
-       max_ofdm = &priv->max_delta.rx.ofdm;
-       max_cck = &priv->max_delta.rx.cck;
-       max_general = &priv->max_delta.rx.general;
-       max_ht = &priv->max_delta.rx.ofdm_ht;
-       pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
-                        "Statistics_Rx - OFDM:");
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                       "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_header,
-                        "Statistics_Rx - CCK:");
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                       "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_header,
-                       "Statistics_Rx - GENERAL:");
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                       "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, ucode_stats_format,
-                       "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                       "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, "Statistics_Rx - OFDM_HT:\n");
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
-                       "Statistics_Rx - OFDM_HT:");
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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;
+       if (priv->cfg->ops->lib->debugfs_ops.rx_stats_read)
+               return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
+                                               user_buf, count, ppos);
+       return 0;
  }
  
  static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
                                        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_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->statistics.tx;
-       accum_tx = &priv->accum_statistics.tx;
-       delta_tx = &priv->delta_statistics.tx;
-       max_tx = &priv->max_delta.tx;
-       pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
-       pos += scnprintf(buf + pos, bufsz - pos,  ucode_stats_header,
-                       "Statistics_Tx:");
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                       "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                       "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, ucode_stats_format,
-                       "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                       "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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;
+       if (priv->cfg->ops->lib->debugfs_ops.tx_stats_read)
+               return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
+                                               user_buf, count, ppos);
+       return 0;
  }
  
  static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
                                        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 *general, *accum_general;
-       struct statistics_general *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_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->statistics.general;
-       dbg = &priv->statistics.general.dbg;
-       div = &priv->statistics.general.div;
-       accum_general = &priv->accum_statistics.general;
-       delta_general = &priv->delta_statistics.general;
-       max_general = &priv->max_delta.general;
-       accum_dbg = &priv->accum_statistics.general.dbg;
-       delta_dbg = &priv->delta_statistics.general.dbg;
-       max_dbg = &priv->max_delta.general.dbg;
-       accum_div = &priv->accum_statistics.general.div;
-       delta_div = &priv->delta_statistics.general.div;
-       max_div = &priv->max_delta.general.div;
-       pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
-                       "Statistics_General:");
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format,
-                        "temperature:",
-                        le32_to_cpu(general->temperature));
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format,
-                        "temperature_m:",
-                        le32_to_cpu(general->temperature_m));
-       pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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, ucode_stats_format,
-                        "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;
+       if (priv->cfg->ops->lib->debugfs_ops.general_stats_read)
+               return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file,
+                                               user_buf, count, ppos);
+       return 0;
  }
  
  static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
@@@ -2341,10 -1636,11 +1642,11 @@@ int iwl_dbgfs_register(struct iwl_priv 
        DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
        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->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
-               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);
                DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
                DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
                DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
@@@ -25,7 -25,6 +25,7 @@@
   *  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 <net/mac80211.h>
@@@ -69,9 -68,8 +69,8 @@@ int iwl_scan_cancel(struct iwl_priv *pr
        }
  
        if (test_bit(STATUS_SCANNING, &priv->status)) {
-               if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+               if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
                        IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n");
-                       set_bit(STATUS_SCAN_ABORTING, &priv->status);
                        queue_work(priv->workqueue, &priv->abort_scan);
  
                } else
@@@ -201,9 -199,6 +200,6 @@@ static void iwl_rx_scan_results_notif(s
                       le32_to_cpu(notif->statistics[0]),
                       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
  #endif
-       if (!priv->is_internal_short_scan)
-               priv->next_scan_jiffies = 0;
  }
  
  /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
@@@ -223,49 -218,24 +219,24 @@@ static void iwl_rx_scan_complete_notif(
        /* The HW is no longer scanning */
        clear_bit(STATUS_SCAN_HW, &priv->status);
  
-       IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n",
-                      (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
-                                               "2.4" : "5.2",
+       IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n",
+                      (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
                       jiffies_to_msecs(elapsed_jiffies
-                                       (priv->scan_pass_start, jiffies)));
-       /* Remove this scanned band from the list of pending
-        * bands to scan, band G precedes A in order of scanning
-        * as seen in iwl_bg_request_scan */
-       if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ))
-               priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ);
-       else if (priv->scan_bands &  BIT(IEEE80211_BAND_5GHZ))
-               priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ);
+                                       (priv->scan_start, jiffies)));
  
-       /* If a request to abort was given, or the scan did not succeed
+       /*
+        * If a request to abort was given, or the scan did not succeed
         * then we reset the scan state machine and terminate,
-        * re-queuing another scan if one has been requested */
-       if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+        * re-queuing another scan if one has been requested
+        */
+       if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status))
                IWL_DEBUG_INFO(priv, "Aborted scan completed.\n");
-               clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-       } else {
-               /* If there are more bands on this scan pass reschedule */
-               if (priv->scan_bands)
-                       goto reschedule;
-       }
-       if (!priv->is_internal_short_scan)
-               priv->next_scan_jiffies = 0;
  
        IWL_DEBUG_INFO(priv, "Setting scan to off\n");
  
        clear_bit(STATUS_SCANNING, &priv->status);
  
-       IWL_DEBUG_INFO(priv, "Scan took %dms\n",
-               jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));
        queue_work(priv->workqueue, &priv->scan_completed);
-       return;
- reschedule:
-       priv->scan_pass_start = jiffies;
-       queue_work(priv->workqueue, &priv->request_scan);
  }
  
  void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
@@@ -314,150 -284,6 +285,6 @@@ u16 iwl_get_passive_dwell_time(struct i
  }
  EXPORT_SYMBOL(iwl_get_passive_dwell_time);
  
- static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
-                                    enum ieee80211_band band,
-                                    struct iwl_scan_channel *scan_ch)
- {
-       const struct ieee80211_supported_band *sband;
-       const struct iwl_channel_info *ch_info;
-       u16 passive_dwell = 0;
-       u16 active_dwell = 0;
-       int i, added = 0;
-       u16 channel = 0;
-       sband = iwl_get_hw_mode(priv, band);
-       if (!sband) {
-               IWL_ERR(priv, "invalid band\n");
-               return added;
-       }
-       active_dwell = iwl_get_active_dwell_time(priv, band, 0);
-       passive_dwell = iwl_get_passive_dwell_time(priv, band);
-       if (passive_dwell <= active_dwell)
-               passive_dwell = active_dwell + 1;
-       /* only scan single channel, good enough to reset the RF */
-       /* pick the first valid not in-use channel */
-       if (band == IEEE80211_BAND_5GHZ) {
-               for (i = 14; i < priv->channel_count; i++) {
-                       if (priv->channel_info[i].channel !=
-                           le16_to_cpu(priv->staging_rxon.channel)) {
-                               channel = priv->channel_info[i].channel;
-                               ch_info = iwl_get_channel_info(priv,
-                                       band, channel);
-                               if (is_channel_valid(ch_info))
-                                       break;
-                       }
-               }
-       } else {
-               for (i = 0; i < 14; i++) {
-                       if (priv->channel_info[i].channel !=
-                           le16_to_cpu(priv->staging_rxon.channel)) {
-                                       channel =
-                                               priv->channel_info[i].channel;
-                                       ch_info = iwl_get_channel_info(priv,
-                                               band, channel);
-                                       if (is_channel_valid(ch_info))
-                                               break;
-                       }
-               }
-       }
-       if (channel) {
-               scan_ch->channel = cpu_to_le16(channel);
-               scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
-               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;
-               if (band == IEEE80211_BAND_5GHZ)
-                       scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-               else
-                       scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-               added++;
-       } else
-               IWL_ERR(priv, "no valid channel found\n");
-       return added;
- }
- static int iwl_get_channels_for_scan(struct iwl_priv *priv,
-                                    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_get_active_dwell_time(priv, band, n_probes);
-       passive_dwell = iwl_get_passive_dwell_time(priv, band);
-       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 = ieee80211_frequency_to_channel(chan->center_freq);
-               scan_ch->channel = cpu_to_le16(channel);
-               ch_info = iwl_get_channel_info(priv, band, channel);
-               if (!is_channel_valid(ch_info)) {
-                       IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
-                                       channel);
-                       continue;
-               }
-               if (!is_active || 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;
- }
  void iwl_init_scan_params(struct iwl_priv *priv)
  {
        u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
@@@ -476,26 -302,27 +303,27 @@@ static int iwl_scan_initiate(struct iwl
        set_bit(STATUS_SCANNING, &priv->status);
        priv->is_internal_short_scan = false;
        priv->scan_start = jiffies;
-       priv->scan_pass_start = priv->scan_start;
  
-       queue_work(priv->workqueue, &priv->request_scan);
+       if (WARN_ON(!priv->cfg->ops->utils->request_scan))
+               return -EOPNOTSUPP;
+       priv->cfg->ops->utils->request_scan(priv);
  
        return 0;
  }
  
- #define IWL_DELAY_NEXT_SCAN (HZ*2)
  int iwl_mac_hw_scan(struct ieee80211_hw *hw,
                     struct cfg80211_scan_request *req)
  {
-       unsigned long flags;
        struct iwl_priv *priv = hw->priv;
-       int ret, i;
+       int ret;
  
        IWL_DEBUG_MAC80211(priv, "enter\n");
  
+       if (req->n_channels == 0)
+               return -EINVAL;
        mutex_lock(&priv->mutex);
-       spin_lock_irqsave(&priv->lock, flags);
  
        if (!iwl_is_ready_rf(priv)) {
                ret = -EIO;
                goto out_unlock;
        }
  
-       /* We don't schedule scan within next_scan_jiffies period.
-        * Avoid scanning during possible EAPOL exchange, return
-        * success immediately.
-        */
-       if (priv->next_scan_jiffies &&
-           time_after(priv->next_scan_jiffies, jiffies)) {
-               IWL_DEBUG_SCAN(priv, "scan rejected: within next scan period\n");
-               queue_work(priv->workqueue, &priv->scan_completed);
-               ret = 0;
-               goto out_unlock;
-       }
-       priv->scan_bands = 0;
-       for (i = 0; i < req->n_channels; i++)
-               priv->scan_bands |= BIT(req->channels[i]->band);
+       /* mac80211 will only ask for one band at a time */
+       priv->scan_band = req->channels[0]->band;
        priv->scan_request = req;
  
        ret = iwl_scan_initiate(priv);
        IWL_DEBUG_MAC80211(priv, "leave\n");
  
  out_unlock:
-       spin_unlock_irqrestore(&priv->lock, flags);
        mutex_unlock(&priv->mutex);
  
        return ret;
@@@ -576,22 -388,20 +389,20 @@@ static void iwl_bg_start_internal_scan(
                goto unlock;
        }
  
-       priv->scan_bands = 0;
-       if (priv->band == IEEE80211_BAND_5GHZ)
-               priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
-       else
-               priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
+       priv->scan_band = priv->band;
  
        IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");
        set_bit(STATUS_SCANNING, &priv->status);
        priv->is_internal_short_scan = true;
-       queue_work(priv->workqueue, &priv->request_scan);
+       if (WARN_ON(!priv->cfg->ops->utils->request_scan))
+               goto unlock;
+       priv->cfg->ops->utils->request_scan(priv);
   unlock:
        mutex_unlock(&priv->mutex);
  }
  
- #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
  void iwl_bg_scan_check(struct work_struct *data)
  {
        struct iwl_priv *priv =
@@@ -653,275 -463,15 +464,15 @@@ u16 iwl_fill_probe_req(struct iwl_priv 
        if (WARN_ON(left < ie_len))
                return len;
  
-       if (ies)
+       if (ies && ie_len) {
                memcpy(pos, ies, ie_len);
-       len += ie_len;
-       left -= ie_len;
+               len += ie_len;
+       }
  
        return (u16)len;
  }
  EXPORT_SYMBOL(iwl_fill_probe_req);
  
- static void iwl_bg_request_scan(struct work_struct *data)
- {
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, request_scan);
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_SCAN_CMD,
-               .len = sizeof(struct iwl_scan_cmd),
-               .flags = CMD_SIZE_HUGE,
-       };
-       struct iwl_scan_cmd *scan;
-       struct ieee80211_conf *conf = NULL;
-       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;
-       conf = ieee80211_get_hw_conf(priv->hw);
-       mutex_lock(&priv->mutex);
-       cancel_delayed_work(&priv->scan_check);
-       if (!iwl_is_ready(priv)) {
-               IWL_WARN(priv, "request scan called when driver not ready.\n");
-               goto done;
-       }
-       /* Make sure the scan wasn't canceled before this queued work
-        * was given the chance to run... */
-       if (!test_bit(STATUS_SCANNING, &priv->status))
-               goto done;
-       /* This should never be called or scheduled if there is currently
-        * a scan active in the hardware. */
-       if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-               IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. "
-                              "Ignoring second request.\n");
-               goto done;
-       }
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-               IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
-               goto done;
-       }
-       if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-               IWL_DEBUG_HC(priv, "Scan request while abort pending.  Queuing.\n");
-               goto done;
-       }
-       if (iwl_is_rfkill(priv)) {
-               IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
-               goto done;
-       }
-       if (!test_bit(STATUS_READY, &priv->status)) {
-               IWL_DEBUG_HC(priv, "Scan request while uninitialized.  Queuing.\n");
-               goto done;
-       }
-       if (!priv->scan_bands) {
-               IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n");
-               goto done;
-       }
-       if (!priv->scan) {
-               priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
-                                    IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-               if (!priv->scan) {
-                       IWL_DEBUG_SCAN(priv,
-                                      "fail to allocate memory for scan\n");
-                       goto done;
-               }
-       }
-       scan = priv->scan;
-       memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
-       scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
-       scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
-       if (iwl_is_associated(priv)) {
-               u16 interval = 0;
-               u32 extra;
-               u32 suspend_time = 100;
-               u32 scan_suspend_time = 100;
-               unsigned long flags;
-               IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-               spin_lock_irqsave(&priv->lock, flags);
-               interval = priv->beacon_int;
-               spin_unlock_irqrestore(&priv->lock, flags);
-               scan->suspend_time = 0;
-               scan->max_out_time = cpu_to_le32(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->is_internal_short_scan) {
-               IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-       } else 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 = priv->hw_params.bcast_sta_id;
-       scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-       if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
-               band = IEEE80211_BAND_2GHZ;
-               scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
-               chan_mod = le32_to_cpu(priv->active_rxon.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;
-               }
-               scan->good_CRC_th = 0;
-       } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
-               band = IEEE80211_BAND_5GHZ;
-               rate = IWL_RATE_6M_PLCP;
-               /*
-                * 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 : 0;
-               /* Force use of chains B and C (0x6) for scan Rx
-                * Avoid A (0x1) for the device has off-channel reception
-                * on A-band.
-                */
-               if (priv->cfg->off_channel_workaround)
-                       rx_ant = ANT_BC;
-       } else {
-               IWL_WARN(priv, "Invalid scan band count\n");
-               goto done;
-       }
-       priv->scan_tx_ant[band] =
-                        iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
-       rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
-       scan->tx_cmd.rate_n_flags = iwl_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 = 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);
-       if (!priv->is_internal_short_scan) {
-               cmd_len = iwl_fill_probe_req(priv,
-                                       (struct ieee80211_mgmt *)scan->data,
-                                       priv->scan_request->ie,
-                                       priv->scan_request->ie_len,
-                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
-       } else {
-               cmd_len = iwl_fill_probe_req(priv,
-                                       (struct ieee80211_mgmt *)scan->data,
-                                       NULL, 0,
-                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
-       }
-       scan->tx_cmd.len = cpu_to_le16(cmd_len);
-       if (iwl_is_monitor_mode(priv))
-               scan->filter_flags = RXON_FILTER_PROMISC_MSK;
-       scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
-                              RXON_FILTER_BCON_AWARE_MSK);
-       if (priv->is_internal_short_scan) {
-               scan->channel_count =
-                       iwl_get_single_channel_for_scan(priv, band,
-                               (void *)&scan->data[le16_to_cpu(
-                               scan->tx_cmd.len)]);
-       } else {
-               scan->channel_count =
-                       iwl_get_channels_for_scan(priv, band,
-                               is_active, n_probes,
-                               (void *)&scan->data[le16_to_cpu(
-                               scan->tx_cmd.len)]);
-       }
-       if (scan->channel_count == 0) {
-               IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
-               goto done;
-       }
-       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);
-       if (iwl_send_cmd_sync(priv, &cmd))
-               goto done;
-       queue_delayed_work(priv->workqueue, &priv->scan_check,
-                          IWL_SCAN_CHECK_WATCHDOG);
-       mutex_unlock(&priv->mutex);
-       return;
-  done:
-       /* Cannot perform scan. Make sure we clear scanning
-       * bits from status so next scan request can be performed.
-       * If we don't clear scanning status bit here all next scan
-       * will fail
-       */
-       clear_bit(STATUS_SCAN_HW, &priv->status);
-       clear_bit(STATUS_SCANNING, &priv->status);
-       /* inform mac80211 scan aborted */
-       queue_work(priv->workqueue, &priv->scan_completed);
-       mutex_unlock(&priv->mutex);
- }
  void iwl_bg_abort_scan(struct work_struct *work)
  {
        struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
@@@ -969,7 -519,6 +520,6 @@@ EXPORT_SYMBOL(iwl_bg_scan_completed)
  void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
  {
        INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
-       INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
        INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
        INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
        INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
@@@ -31,7 -31,6 +31,7 @@@
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/pci.h>
 +#include <linux/slab.h>
  #include <linux/dma-mapping.h>
  #include <linux/delay.h>
  #include <linux/sched.h>
@@@ -2527,7 -2526,7 +2527,7 @@@ static void iwl3945_alive_start(struct 
        }
  
        /* Configure Bluetooth device coexistence support */
-       iwl_send_bt_config(priv);
+       priv->cfg->ops->hcmd->send_bt_config(priv);
  
        /* Configure the adapter for unassociated operation */
        iwlcore_commit_rxon(priv);
@@@ -2791,11 -2790,8 +2791,8 @@@ static void iwl3945_rfkill_poll(struct 
  
  }
  
- #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
- static void iwl3945_bg_request_scan(struct work_struct *data)
+ void iwl3945_request_scan(struct iwl_priv *priv)
  {
-       struct iwl_priv *priv =
-           container_of(data, struct iwl_priv, request_scan);
        struct iwl_host_cmd cmd = {
                .id = REPLY_SCAN_CMD,
                .len = sizeof(struct iwl3945_scan_cmd),
  
        conf = ieee80211_get_hw_conf(priv->hw);
  
-       mutex_lock(&priv->mutex);
        cancel_delayed_work(&priv->scan_check);
  
        if (!iwl_is_ready(priv)) {
                goto done;
        }
  
-       if (!priv->scan_bands) {
-               IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n");
-               goto done;
-       }
-       if (!priv->scan) {
-               priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) +
-                                    IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-               if (!priv->scan) {
+       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");
                        goto done;
                }
        }
-       scan = priv->scan;
+       scan = priv->scan_cmd;
        memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
  
        scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
  
        /* flags + rate selection */
  
-       if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
+       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;
                scan->good_CRC_th = 0;
                band = IEEE80211_BAND_2GHZ;
-       } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
+               break;
+       case IEEE80211_BAND_5GHZ:
                scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
                /*
                 * If active scaning is requested but a certain channel
                 */
                scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
                band = IEEE80211_BAND_5GHZ;
-       } else {
-               IWL_WARN(priv, "Invalid scan band count\n");
+               break;
+       default:
+               IWL_WARN(priv, "Invalid scan band\n");
                goto done;
        }
  
        /* select Rx antennas */
        scan->flags |= iwl3945_get_antenna_flags(priv);
  
-       if (iwl_is_monitor_mode(priv))
-               scan->filter_flags = RXON_FILTER_PROMISC_MSK;
        scan->channel_count =
                iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
                        (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
        queue_delayed_work(priv->workqueue, &priv->scan_check,
                           IWL_SCAN_CHECK_WATCHDOG);
  
-       mutex_unlock(&priv->mutex);
        return;
  
   done:
  
        /* inform mac80211 scan aborted */
        queue_work(priv->workqueue, &priv->scan_completed);
-       mutex_unlock(&priv->mutex);
  }
  
  static void iwl3945_bg_restart(struct work_struct *data)
@@@ -3051,8 -3038,6 +3039,6 @@@ static void iwl3945_bg_rx_replenish(str
        mutex_unlock(&priv->mutex);
  }
  
- #define IWL_DELAY_NEXT_SCAN (HZ*2)
  void iwl3945_post_associate(struct iwl_priv *priv)
  {
        int rc = 0;
                           __func__, priv->iw_mode);
                break;
        }
-       /* we have just associated, don't start scan too early */
-       priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
  }
  
  /*****************************************************************************
@@@ -3672,44 -3654,6 +3655,6 @@@ static ssize_t show_channels(struct dev
  
  static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
  
- static ssize_t show_statistics(struct device *d,
-                              struct device_attribute *attr, char *buf)
- {
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       u32 size = sizeof(struct iwl3945_notif_statistics);
-       u32 len = 0, ofs = 0;
-       u8 *data = (u8 *)&priv->_3945.statistics;
-       int rc = 0;
-       if (!iwl_is_alive(priv))
-               return -EAGAIN;
-       mutex_lock(&priv->mutex);
-       rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
-       mutex_unlock(&priv->mutex);
-       if (rc) {
-               len = sprintf(buf,
-                             "Error sending statistics request: 0x%08X\n", rc);
-               return len;
-       }
-       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 DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
  static ssize_t show_antenna(struct device *d,
                            struct device_attribute *attr, char *buf)
  {
@@@ -3793,7 -3737,6 +3738,6 @@@ static void iwl3945_setup_deferred_work
        INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
        INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
        INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
-       INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
        INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
        INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
  
@@@ -3830,7 -3773,6 +3774,6 @@@ static struct attribute *iwl3945_sysfs_
        &dev_attr_filter_flags.attr,
        &dev_attr_measurement.attr,
        &dev_attr_retry_rate.attr,
-       &dev_attr_statistics.attr,
        &dev_attr_status.attr,
        &dev_attr_temperature.attr,
        &dev_attr_tx_power.attr,
@@@ -4253,7 -4195,7 +4196,7 @@@ static void __devexit iwl3945_pci_remov
  
        iwl_free_channel_map(priv);
        iwlcore_free_geos(priv);
-       kfree(priv->scan);
+       kfree(priv->scan_cmd);
        if (priv->ibss_beacon)
                dev_kfree_skb(priv->ibss_beacon);
  
@@@ -44,7 -44,6 +44,7 @@@
  #include <linux/ieee80211.h>
  #include <linux/if_arp.h>
  #include <linux/list.h>
 +#include <linux/slab.h>
  #include <net/iw_handler.h>
  
  #include "iwm.h"
@@@ -431,7 -430,8 +431,8 @@@ static int iwm_ntf_rx_ticket(struct iwm
                                return PTR_ERR(ticket_node);
  
                        IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n",
-                                  ticket->action ==  IWM_RX_TICKET_RELEASE ?
+                                  __le16_to_cpu(ticket->action) ==
+                                                       IWM_RX_TICKET_RELEASE ?
                                   "RELEASE" : "DROP",
                                   ticket->id);
                        spin_lock(&iwm->ticket_lock);
@@@ -1143,7 -1143,7 +1144,7 @@@ static int iwm_ntf_stop_resume_tx(struc
                return -EINVAL;
        }
  
 -      for_each_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
 +      for_each_set_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
                tid_info = &sta_info->tid_info[bit];
  
                mutex_lock(&tid_info->mutex);
@@@ -64,7 -64,6 +64,7 @@@
   * (i.e. half of the max size). [iwm_tx_worker]
   */
  
 +#include <linux/slab.h>
  #include <linux/skbuff.h>
  #include <linux/netdevice.h>
  #include <linux/ieee80211.h>
@@@ -302,8 -301,8 +302,8 @@@ void iwm_tx_credit_init_pools(struct iw
  
  #define IWM_UDMA_HDR_LEN      sizeof(struct iwm_umac_wifi_out_hdr)
  
- static int iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb,
-                              int pool_id, u8 *buf)
+ static __le16 iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb,
+                                 int pool_id, u8 *buf)
  {
        struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf;
        struct iwm_udma_wifi_cmd udma_cmd;
@@@ -28,7 -28,6 +28,7 @@@
  
  #include <linux/kernel.h>
  #include <linux/moduleparam.h>
 +#include <linux/slab.h>
  #include <linux/firmware.h>
  #include <linux/netdevice.h>
  #include <linux/delay.h>
@@@ -315,12 -314,28 +315,28 @@@ out
        return ret;
  }
  
+ static int if_sdio_wait_status(struct if_sdio_card *card, const u8 condition)
+ {
+       u8 status;
+       unsigned long timeout;
+       int ret = 0;
+       timeout = jiffies + HZ;
+       while (1) {
+               status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
+               if (ret || (status & condition))
+                       break;
+               if (time_after(jiffies, timeout))
+                       return -ETIMEDOUT;
+               mdelay(1);
+       }
+       return ret;
+ }
  static int if_sdio_card_to_host(struct if_sdio_card *card)
  {
        int ret;
-       u8 status;
        u16 size, type, chunk;
-       unsigned long timeout;
  
        lbs_deb_enter(LBS_DEB_SDIO);
  
                goto out;
        }
  
-       timeout = jiffies + HZ;
-       while (1) {
-               status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
-               if (ret)
-                       goto out;
-               if (status & IF_SDIO_IO_RDY)
-                       break;
-               if (time_after(jiffies, timeout)) {
-                       ret = -ETIMEDOUT;
-                       goto out;
-               }
-               mdelay(1);
-       }
+       ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY);
+       if (ret)
+               goto out;
  
        /*
         * The transfer must be in one transaction or the firmware
@@@ -414,8 -419,6 +420,6 @@@ static void if_sdio_host_to_card_worker
  {
        struct if_sdio_card *card;
        struct if_sdio_packet *packet;
-       unsigned long timeout;
-       u8 status;
        int ret;
        unsigned long flags;
  
  
                sdio_claim_host(card->func);
  
-               timeout = jiffies + HZ;
-               while (1) {
-                       status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
-                       if (ret)
-                               goto release;
-                       if (status & IF_SDIO_IO_RDY)
-                               break;
-                       if (time_after(jiffies, timeout)) {
-                               ret = -ETIMEDOUT;
-                               goto release;
-                       }
-                       mdelay(1);
+               ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY);
+               if (ret == 0) {
+                       ret = sdio_writesb(card->func, card->ioport,
+                                          packet->buffer, packet->nb);
                }
  
-               ret = sdio_writesb(card->func, card->ioport,
-                               packet->buffer, packet->nb);
                if (ret)
-                       goto release;
- release:
+                       lbs_pr_err("error %d sending packet to firmware\n", ret);
                sdio_release_host(card->func);
  
                kfree(packet);
  /* Firmware                                                         */
  /********************************************************************/
  
+ #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY)
  static int if_sdio_prog_helper(struct if_sdio_card *card)
  {
        int ret;
-       u8 status;
        const struct firmware *fw;
        unsigned long timeout;
        u8 *chunk_buffer;
        size = fw->size;
  
        while (size) {
-               timeout = jiffies + HZ;
-               while (1) {
-                       status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
-                       if (ret)
-                               goto release;
-                       if ((status & IF_SDIO_IO_RDY) &&
-                                       (status & IF_SDIO_DL_RDY))
-                               break;
-                       if (time_after(jiffies, timeout)) {
-                               ret = -ETIMEDOUT;
-                               goto release;
-                       }
-                       mdelay(1);
-               }
+               ret = if_sdio_wait_status(card, FW_DL_READY_STATUS);
+               if (ret)
+                       goto release;
+               /* On some platforms (like Davinci) the chip needs more time
+                * between helper blocks.
+                */
+               mdelay(2);
  
                chunk_size = min(size, (size_t)60);
  
@@@ -584,7 -572,6 +573,6 @@@ out
  static int if_sdio_prog_real(struct if_sdio_card *card)
  {
        int ret;
-       u8 status;
        const struct firmware *fw;
        unsigned long timeout;
        u8 *chunk_buffer;
        size = fw->size;
  
        while (size) {
-               timeout = jiffies + HZ;
-               while (1) {
-                       status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
-                       if (ret)
-                               goto release;
-                       if ((status & IF_SDIO_IO_RDY) &&
-                                       (status & IF_SDIO_DL_RDY))
-                               break;
-                       if (time_after(jiffies, timeout)) {
-                               ret = -ETIMEDOUT;
-                               goto release;
-                       }
-                       mdelay(1);
-               }
+               ret = if_sdio_wait_status(card, FW_DL_READY_STATUS);
+               if (ret)
+                       goto release;
  
                req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);
                if (ret)
@@@ -14,7 -14,6 +14,7 @@@
   */
  
  #include <linux/list.h>
 +#include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <net/dst.h>
  #include <net/xfrm.h>
@@@ -830,6 -829,33 +830,33 @@@ static int mac80211_hwsim_conf_tx
        return 0;
  }
  
+ static int mac80211_hwsim_get_survey(
+       struct ieee80211_hw *hw, int idx,
+       struct survey_info *survey)
+ {
+       struct ieee80211_conf *conf = &hw->conf;
+       printk(KERN_DEBUG "%s:%s (idx=%d)\n",
+              wiphy_name(hw->wiphy), __func__, idx);
+       if (idx != 0)
+               return -ENOENT;
+       /* Current channel */
+       survey->channel = conf->channel;
+       /*
+        * Magically conjured noise level --- this is only ok for simulated hardware.
+        *
+        * A real driver which cannot determine the real channel noise MUST NOT
+        * report any noise, especially not a magically conjured one :-)
+        */
+       survey->filled = SURVEY_INFO_NOISE_DBM;
+       survey->noise = -92;
+       return 0;
+ }
  #ifdef CONFIG_NL80211_TESTMODE
  /*
   * This section contains example code for using netlink
@@@ -1013,6 -1039,7 +1040,7 @@@ static struct ieee80211_ops mac80211_hw
        .sta_notify = mac80211_hwsim_sta_notify,
        .set_tim = mac80211_hwsim_set_tim,
        .conf_tx = mac80211_hwsim_conf_tx,
+       .get_survey = mac80211_hwsim_get_survey,
        CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
        .ampdu_action = mac80211_hwsim_ampdu_action,
        .sw_scan_start = mac80211_hwsim_sw_scan,
@@@ -374,6 -374,32 +374,32 @@@ int orinoco_hw_read_card_settings(struc
                err = hermes_read_wordrec(hw, USER_BAP,
                                          HERMES_RID_CNFPREAMBLE_SYMBOL,
                                          &priv->preamble);
+               if (err) {
+                       dev_err(dev, "Failed to read preamble setup\n");
+                       goto out;
+               }
+       }
+       /* Retry settings */
+       err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
+                                 &priv->short_retry_limit);
+       if (err) {
+               dev_err(dev, "Failed to read short retry limit\n");
+               goto out;
+       }
+       err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
+                                 &priv->long_retry_limit);
+       if (err) {
+               dev_err(dev, "Failed to read long retry limit\n");
+               goto out;
+       }
+       err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
+                                 &priv->retry_lifetime);
+       if (err) {
+               dev_err(dev, "Failed to read max retry lifetime\n");
+               goto out;
        }
  
  out:
@@@ -1056,14 -1082,14 +1082,14 @@@ int __orinoco_hw_set_multicast_list(str
         * group address if either we want to multicast, or if we were
         * multicasting and want to stop */
        if (!promisc && (mc_count || priv->mc_count)) {
 -              struct dev_mc_list *p;
 +              struct netdev_hw_addr *ha;
                struct hermes_multicast mclist;
                int i = 0;
  
 -              netdev_for_each_mc_addr(p, dev) {
 +              netdev_for_each_mc_addr(ha, dev) {
                        if (i == mc_count)
                                break;
 -                      memcpy(mclist.addr[i++], p->dmi_addr, ETH_ALEN);
 +                      memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);
                }
  
                err = hermes_write_ltv(hw, USER_BAP,
@@@ -3,7 -3,6 +3,7 @@@
   * See copyright notice in main.c
   */
  
 +#include <linux/gfp.h>
  #include <linux/kernel.h>
  #include <linux/string.h>
  #include <linux/ieee80211.h>
@@@ -127,7 -126,7 +127,7 @@@ void orinoco_add_extscan_result(struct 
  {
        struct wiphy *wiphy = priv_to_wiphy(priv);
        struct ieee80211_channel *channel;
-       u8 *ie;
+       const u8 *ie;
        u64 timestamp;
        s32 signal;
        u16 capability;
        int chan, freq;
  
        ie_len = len - sizeof(*bss);
-       ie = orinoco_get_ie(bss->data, ie_len, WLAN_EID_DS_PARAMS);
+       ie = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bss->data, ie_len);
        chan = ie ? ie[2] : 0;
        freq = ieee80211_dsss_chan_to_freq(chan);
        channel = ieee80211_get_channel(wiphy, freq);
@@@ -2,7 -2,6 +2,7 @@@
   *
   * See copyright notice in main.c
   */
 +#include <linux/slab.h>
  #include <linux/kernel.h>
  #include <linux/if_arp.h>
  #include <linux/wireless.h>
@@@ -538,125 -537,6 +538,6 @@@ static int orinoco_ioctl_setsens(struc
        return -EINPROGRESS;            /* Call commit handler */
  }
  
- static int orinoco_ioctl_setrts(struct net_device *dev,
-                               struct iw_request_info *info,
-                               struct iw_param *rrq,
-                               char *extra)
- {
-       struct orinoco_private *priv = ndev_priv(dev);
-       int val = rrq->value;
-       unsigned long flags;
-       if (rrq->disabled)
-               val = 2347;
-       if ((val < 0) || (val > 2347))
-               return -EINVAL;
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-       priv->rts_thresh = val;
-       orinoco_unlock(priv, &flags);
-       return -EINPROGRESS;            /* Call commit handler */
- }
- static int orinoco_ioctl_getrts(struct net_device *dev,
-                               struct iw_request_info *info,
-                               struct iw_param *rrq,
-                               char *extra)
- {
-       struct orinoco_private *priv = ndev_priv(dev);
-       rrq->value = priv->rts_thresh;
-       rrq->disabled = (rrq->value == 2347);
-       rrq->fixed = 1;
-       return 0;
- }
- static int orinoco_ioctl_setfrag(struct net_device *dev,
-                                struct iw_request_info *info,
-                                struct iw_param *frq,
-                                char *extra)
- {
-       struct orinoco_private *priv = ndev_priv(dev);
-       int err = -EINPROGRESS;         /* Call commit handler */
-       unsigned long flags;
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-       if (priv->has_mwo) {
-               if (frq->disabled)
-                       priv->mwo_robust = 0;
-               else {
-                       if (frq->fixed)
-                               printk(KERN_WARNING "%s: Fixed fragmentation "
-                                      "is not supported on this firmware. "
-                                      "Using MWO robust instead.\n",
-                                      dev->name);
-                       priv->mwo_robust = 1;
-               }
-       } else {
-               if (frq->disabled)
-                       priv->frag_thresh = 2346;
-               else {
-                       if ((frq->value < 256) || (frq->value > 2346))
-                               err = -EINVAL;
-                       else
-                               /* must be even */
-                               priv->frag_thresh = frq->value & ~0x1;
-               }
-       }
-       orinoco_unlock(priv, &flags);
-       return err;
- }
- static int orinoco_ioctl_getfrag(struct net_device *dev,
-                                struct iw_request_info *info,
-                                struct iw_param *frq,
-                                char *extra)
- {
-       struct orinoco_private *priv = ndev_priv(dev);
-       hermes_t *hw = &priv->hw;
-       int err;
-       u16 val;
-       unsigned long flags;
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-       if (priv->has_mwo) {
-               err = hermes_read_wordrec(hw, USER_BAP,
-                                         HERMES_RID_CNFMWOROBUST_AGERE,
-                                         &val);
-               if (err)
-                       val = 0;
-               frq->value = val ? 2347 : 0;
-               frq->disabled = !val;
-               frq->fixed = 0;
-       } else {
-               err = hermes_read_wordrec(hw, USER_BAP,
-                                         HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
-                                         &val);
-               if (err)
-                       val = 0;
-               frq->value = val;
-               frq->disabled = (val >= 2346);
-               frq->fixed = 1;
-       }
-       orinoco_unlock(priv, &flags);
-       return err;
- }
  static int orinoco_ioctl_setrate(struct net_device *dev,
                                 struct iw_request_info *info,
                                 struct iw_param *rrq,
@@@ -1201,60 -1081,6 +1082,6 @@@ static int orinoco_ioctl_set_mlme(struc
        return ret;
  }
  
- static int orinoco_ioctl_getretry(struct net_device *dev,
-                                 struct iw_request_info *info,
-                                 struct iw_param *rrq,
-                                 char *extra)
- {
-       struct orinoco_private *priv = ndev_priv(dev);
-       hermes_t *hw = &priv->hw;
-       int err = 0;
-       u16 short_limit, long_limit, lifetime;
-       unsigned long flags;
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-       err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
-                                 &short_limit);
-       if (err)
-               goto out;
-       err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
-                                 &long_limit);
-       if (err)
-               goto out;
-       err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
-                                 &lifetime);
-       if (err)
-               goto out;
-       rrq->disabled = 0;              /* Can't be disabled */
-       /* Note : by default, display the retry number */
-       if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
-               rrq->flags = IW_RETRY_LIFETIME;
-               rrq->value = lifetime * 1000;   /* ??? */
-       } else {
-               /* By default, display the min number */
-               if ((rrq->flags & IW_RETRY_LONG)) {
-                       rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
-                       rrq->value = long_limit;
-               } else {
-                       rrq->flags = IW_RETRY_LIMIT;
-                       rrq->value = short_limit;
-                       if (short_limit != long_limit)
-                               rrq->flags |= IW_RETRY_SHORT;
-               }
-       }
-  out:
-       orinoco_unlock(priv, &flags);
-       return err;
- }
  static int orinoco_ioctl_reset(struct net_device *dev,
                               struct iw_request_info *info,
                               void *wrqu,
@@@ -1528,11 -1354,11 +1355,11 @@@ static const iw_handler      orinoco_handler
        IW_HANDLER(SIOCGIWESSID,        (iw_handler)orinoco_ioctl_getessid),
        IW_HANDLER(SIOCSIWRATE,         (iw_handler)orinoco_ioctl_setrate),
        IW_HANDLER(SIOCGIWRATE,         (iw_handler)orinoco_ioctl_getrate),
-       IW_HANDLER(SIOCSIWRTS,          (iw_handler)orinoco_ioctl_setrts),
-       IW_HANDLER(SIOCGIWRTS,          (iw_handler)orinoco_ioctl_getrts),
-       IW_HANDLER(SIOCSIWFRAG,         (iw_handler)orinoco_ioctl_setfrag),
-       IW_HANDLER(SIOCGIWFRAG,         (iw_handler)orinoco_ioctl_getfrag),
-       IW_HANDLER(SIOCGIWRETRY,        (iw_handler)orinoco_ioctl_getretry),
+       IW_HANDLER(SIOCSIWRTS,          (iw_handler)cfg80211_wext_siwrts),
+       IW_HANDLER(SIOCGIWRTS,          (iw_handler)cfg80211_wext_giwrts),
+       IW_HANDLER(SIOCSIWFRAG,         (iw_handler)cfg80211_wext_siwfrag),
+       IW_HANDLER(SIOCGIWFRAG,         (iw_handler)cfg80211_wext_giwfrag),
+       IW_HANDLER(SIOCGIWRETRY,        (iw_handler)cfg80211_wext_giwretry),
        IW_HANDLER(SIOCSIWENCODE,       (iw_handler)orinoco_ioctl_setiwencode),
        IW_HANDLER(SIOCGIWENCODE,       (iw_handler)orinoco_ioctl_getiwencode),
        IW_HANDLER(SIOCSIWPOWER,        (iw_handler)orinoco_ioctl_setpower),
@@@ -15,7 -15,6 +15,7 @@@
  
  #include <linux/init.h>
  #include <linux/pci.h>
 +#include <linux/slab.h>
  #include <linux/firmware.h>
  #include <linux/etherdevice.h>
  #include <linux/delay.h>
@@@ -140,7 -139,7 +140,7 @@@ static void p54p_refill_rx_ring(struct 
  
        idx = le32_to_cpu(ring_control->host_idx[ring_index]);
        limit = idx;
-       limit -= le32_to_cpu(index);
+       limit -= index;
        limit = ring_limit - limit;
  
        i = idx % ring_limit;
@@@ -99,7 -99,7 +99,7 @@@ static int rt2800usb_check_firmware(str
         * There are 2 variations of the rt2870 firmware.
         * a) size: 4kb
         * b) size: 8kb
 -       * Note that (b) contains 2 seperate firmware blobs of 4k
 +       * Note that (b) contains 2 separate firmware blobs of 4k
         * within the file. The first blob is the same firmware as (a),
         * but the second blob is for the additional chipsets.
         */
  
        /*
         * 8kb firmware files must be checked as if it were
 -       * 2 seperate firmware files.
 +       * 2 separate firmware files.
         */
        while (offset < len) {
                if (!rt2800usb_check_crc(data + offset, 4096))
@@@ -806,6 -806,10 +806,10 @@@ static struct usb_device_id rt2800usb_d
        { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
+       /* Allwin */
+       { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Amit */
        { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Askey */
        /* Hawking */
        { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Linksys */
        { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* AirTies */
        { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
+       /* Allwin */
+       { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* ASUS */
        { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* AzureWave */
        { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
  #endif
  #ifdef CONFIG_RT2800USB_RT35XX
+       /* Allwin */
+       { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Askey */
        { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Cisco */
         * Unclear what kind of devices these are (they aren't supported by the
         * vendor driver).
         */
-       /* Allwin */
-       { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Amigo */
        { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Gigabyte */
        { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) },
-       /* Hawking */
-       { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* LevelOne */
        { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
@@@ -27,7 -27,6 +27,7 @@@
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/pci.h>
 +#include <linux/slab.h>
  
  #include "rt2x00.h"
  #include "rt2x00pci.h"
@@@ -63,7 -62,8 +63,8 @@@ EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_rea
  /*
   * TX data handlers.
   */
- int rt2x00pci_write_tx_data(struct queue_entry *entry)
+ int rt2x00pci_write_tx_data(struct queue_entry *entry,
+                           struct txentry_desc *txdesc)
  {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct queue_entry_priv_pci *entry_priv = entry->priv_data;
@@@ -24,7 -24,6 +24,7 @@@
        Abstract: rt2x00 queue specific routines.
   */
  
 +#include <linux/slab.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/dma-mapping.h>
@@@ -498,7 -497,7 +498,7 @@@ int rt2x00queue_write_tx_frame(struct d
        /*
         * When hardware encryption is supported, and this frame
         * is to be encrypted, we should strip the IV/EIV data from
 -       * the frame so we can provide it to the driver seperately.
 +       * the frame so we can provide it to the driver separately.
         */
        if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
            !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
         * call failed. Since we always return NETDEV_TX_OK to mac80211,
         * this frame will simply be dropped.
         */
-       if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) {
+       if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry,
+                                                              &txdesc))) {
                clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
                entry->skb = NULL;
                return -EIO;
@@@ -25,7 -25,6 +25,7 @@@
  
  #include <linux/kernel.h>
  #include <linux/module.h>
 +#include <linux/slab.h>
  #include <linux/usb.h>
  #include <linux/bug.h>
  
@@@ -216,7 -215,8 +216,8 @@@ static void rt2x00usb_interrupt_txdone(
        rt2x00lib_txdone(entry, &txdesc);
  }
  
- int rt2x00usb_write_tx_data(struct queue_entry *entry)
+ int rt2x00usb_write_tx_data(struct queue_entry *entry,
+                           struct txentry_desc *txdesc)
  {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@@ -29,7 -29,6 +29,7 @@@
  #include <linux/crc32.h>
  #include <linux/etherdevice.h>
  #include <linux/vmalloc.h>
 +#include <linux/slab.h>
  
  #include "wl1251.h"
  #include "wl12xx_80211.h"
@@@ -1196,6 -1195,66 +1196,66 @@@ static const struct ieee80211_ops wl125
        .conf_tx = wl1251_op_conf_tx,
  };
  
+ static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data)
+ {
+       unsigned long timeout;
+       wl1251_reg_write32(wl, EE_ADDR, offset);
+       wl1251_reg_write32(wl, EE_CTL, EE_CTL_READ);
+       /* EE_CTL_READ clears when data is ready */
+       timeout = jiffies + msecs_to_jiffies(100);
+       while (1) {
+               if (!(wl1251_reg_read32(wl, EE_CTL) & EE_CTL_READ))
+                       break;
+               if (time_after(jiffies, timeout))
+                       return -ETIMEDOUT;
+               msleep(1);
+       }
+       *data = wl1251_reg_read32(wl, EE_DATA);
+       return 0;
+ }
+ static int wl1251_read_eeprom(struct wl1251 *wl, off_t offset,
+                             u8 *data, size_t len)
+ {
+       size_t i;
+       int ret;
+       wl1251_reg_write32(wl, EE_START, 0);
+       for (i = 0; i < len; i++) {
+               ret = wl1251_read_eeprom_byte(wl, offset + i, &data[i]);
+               if (ret < 0)
+                       return ret;
+       }
+       return 0;
+ }
+ static int wl1251_read_eeprom_mac(struct wl1251 *wl)
+ {
+       u8 mac[ETH_ALEN];
+       int i, ret;
+       wl1251_set_partition(wl, 0, 0, REGISTERS_BASE, REGISTERS_DOWN_SIZE);
+       ret = wl1251_read_eeprom(wl, 0x1c, mac, sizeof(mac));
+       if (ret < 0) {
+               wl1251_warning("failed to read MAC address from EEPROM");
+               return ret;
+       }
+       /* MAC is stored in reverse order */
+       for (i = 0; i < ETH_ALEN; i++)
+               wl->mac_addr[i] = mac[ETH_ALEN - i - 1];
+       return 0;
+ }
  static int wl1251_register_hw(struct wl1251 *wl)
  {
        int ret;
@@@ -1242,6 -1301,9 +1302,9 @@@ int wl1251_init_ieee80211(struct wl125
  
        wl->hw->queues = 4;
  
+       if (wl->use_eeprom)
+               wl1251_read_eeprom_mac(wl);
        ret = wl1251_register_hw(wl);
        if (ret)
                goto out;
diff --combined include/net/mac80211.h
@@@ -274,6 -274,9 +274,9 @@@ struct ieee80211_bss_conf 
   * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211
   *    MLME command (internal to mac80211 to figure out whether to send TX
   *    status to user space)
+  * @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame
+  * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this
+  *    frame and selects the maximum number of streams that it can use.
   */
  enum mac80211_tx_control_flags {
        IEEE80211_TX_CTL_REQ_TX_STATUS          = BIT(0),
        IEEE80211_TX_INTFL_RETRANSMISSION       = BIT(19),
        IEEE80211_TX_INTFL_HAS_RADIOTAP         = BIT(20),
        IEEE80211_TX_INTFL_NL80211_FRAME_TX     = BIT(21),
+       IEEE80211_TX_CTL_LDPC                   = BIT(22),
+       IEEE80211_TX_CTL_STBC                   = BIT(23) | BIT(24),
+ #define IEEE80211_TX_CTL_STBC_SHIFT           23
  };
  
  /**
@@@ -395,11 -401,11 +401,11 @@@ struct ieee80211_tx_rate 
   * @status: union for status data
   * @driver_data: array of driver_data pointers
   * @ampdu_ack_len: number of acked aggregated frames.
-  *    relevant only if IEEE80211_TX_STATUS_AMPDU was set.
+  *    relevant only if IEEE80211_TX_STAT_AMPDU was set.
   * @ampdu_ack_map: block ack bit map for the aggregation.
-  *    relevant only if IEEE80211_TX_STATUS_AMPDU was set.
+  *    relevant only if IEEE80211_TX_STAT_AMPDU was set.
   * @ampdu_len: number of aggregated frames.
-  *    relevant only if IEEE80211_TX_STATUS_AMPDU was set.
+  *    relevant only if IEEE80211_TX_STAT_AMPDU was set.
   * @ack_signal: signal strength of the ACK frame
   */
  struct ieee80211_tx_info {
@@@ -610,6 -616,7 +616,7 @@@ enum ieee80211_conf_flags 
   * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
   * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
   * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed
+  * @IEEE80211_CONF_CHANGE_QOS: Quality of service was enabled or disabled
   */
  enum ieee80211_conf_changed {
        IEEE80211_CONF_CHANGE_SMPS              = BIT(1),
@@@ -791,6 -798,7 +798,7 @@@ struct ieee80211_key_conf 
        u8 iv_len;
        u8 hw_key_idx;
        u8 flags;
+       u8 *ap_addr;
        s8 keyidx;
        u8 keylen;
        u8 key[0];
@@@ -1631,7 -1639,7 +1639,7 @@@ struct ieee80211_ops 
                                 struct ieee80211_bss_conf *info,
                                 u32 changed);
        u64 (*prepare_multicast)(struct ieee80211_hw *hw,
 -                               int mc_count, struct dev_addr_list *mc_list);
 +                               struct netdev_hw_addr_list *mc_list);
        void (*configure_filter)(struct ieee80211_hw *hw,
                                 unsigned int changed_flags,
                                 unsigned int *total_flags,
                            struct ieee80211_vif *vif,
                            enum ieee80211_ampdu_mlme_action action,
                            struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+       int (*get_survey)(struct ieee80211_hw *hw, int idx,
+               struct survey_info *survey);
        void (*rfkill_poll)(struct ieee80211_hw *hw);
        void (*set_coverage_class)(struct ieee80211_hw *hw, u8 coverage_class);
  #ifdef CONFIG_NL80211_TESTMODE
diff --combined net/mac80211/agg-rx.c
   */
  
  #include <linux/ieee80211.h>
 +#include <linux/slab.h>
  #include <net/mac80211.h>
  #include "ieee80211_i.h"
  #include "driver-ops.h"
  
- void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
-                                   u16 initiator, u16 reason)
+ static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
+                                           u16 initiator, u16 reason,
+                                           bool from_timer)
  {
        struct ieee80211_local *local = sta->local;
        struct tid_ampdu_rx *tid_rx;
  
        spin_unlock_bh(&sta->lock);
  
-       del_timer_sync(&tid_rx->session_timer);
+       if (!from_timer)
+               del_timer_sync(&tid_rx->session_timer);
        kfree(tid_rx);
  }
  
+ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
+                                   u16 initiator, u16 reason)
+ {
+       ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, false);
+ }
  /*
   * After accepting the AddBA Request we activated a timer,
   * resetting it after each frame that arrives from the originator.
@@@ -92,8 -99,8 +100,8 @@@ static void sta_rx_agg_session_timer_ex
  #ifdef CONFIG_MAC80211_HT_DEBUG
        printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
  #endif
-       __ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT,
-                                      WLAN_REASON_QSTA_TIMEOUT);
+       ___ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT,
+                                       WLAN_REASON_QSTA_TIMEOUT, true);
  }
  
  static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
diff --combined net/mac80211/agg-tx.c
@@@ -14,7 -14,6 +14,7 @@@
   */
  
  #include <linux/ieee80211.h>
 +#include <linux/slab.h>
  #include <net/mac80211.h>
  #include "ieee80211_i.h"
  #include "driver-ops.h"
@@@ -184,9 -183,10 +184,9 @@@ static void sta_addba_resp_timer_expire
                       HT_AGG_STATE_REQ_STOP_BA_MSK)) !=
                                                HT_ADDBA_REQUESTED_MSK) {
                spin_unlock_bh(&sta->lock);
 -              *state = HT_AGG_STATE_IDLE;
  #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "timer expired on tid %d but we are not "
-                               "(or no longer) expecting addBA response there",
+                               "(or no longer) expecting addBA response there\n",
                        tid);
  #endif
                return;
diff --combined net/mac80211/cfg.c
@@@ -9,7 -9,6 +9,7 @@@
  #include <linux/ieee80211.h>
  #include <linux/nl80211.h>
  #include <linux/rtnetlink.h>
 +#include <linux/slab.h>
  #include <net/net_namespace.h>
  #include <linux/rcupdate.h>
  #include <net/cfg80211.h>
@@@ -411,6 -410,17 +411,17 @@@ static int ieee80211_dump_station(struc
        return ret;
  }
  
+ static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
+                                int idx, struct survey_info *survey)
+ {
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       if (!local->ops->get_survey)
+               return -EOPNOTSUPP;
+       return drv_get_survey(local, idx, survey);
+ }
  static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
                                 u8 *mac, struct station_info *sinfo)
  {
@@@ -1508,6 -1518,7 +1519,7 @@@ struct cfg80211_ops mac80211_config_op
        .change_station = ieee80211_change_station,
        .get_station = ieee80211_get_station,
        .dump_station = ieee80211_dump_station,
+       .dump_survey = ieee80211_dump_survey,
  #ifdef CONFIG_MAC80211_MESH
        .add_mpath = ieee80211_add_mpath,
        .del_mpath = ieee80211_del_mpath,
@@@ -84,14 -84,16 +84,14 @@@ static inline void drv_bss_info_changed
  }
  
  static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
 -                                      int mc_count,
 -                                      struct dev_addr_list *mc_list)
 +                                      struct netdev_hw_addr_list *mc_list)
  {
        u64 ret = 0;
  
        if (local->ops->prepare_multicast)
 -              ret = local->ops->prepare_multicast(&local->hw, mc_count,
 -                                                  mc_list);
 +              ret = local->ops->prepare_multicast(&local->hw, mc_list);
  
 -      trace_drv_prepare_multicast(local, mc_count, ret);
 +      trace_drv_prepare_multicast(local, mc_list->count, ret);
  
        return ret;
  }
@@@ -344,6 -346,15 +344,15 @@@ static inline int drv_ampdu_action(stru
        return ret;
  }
  
+ static inline int drv_get_survey(struct ieee80211_local *local, int idx,
+                               struct survey_info *survey)
+ {
+       int ret = -EOPNOTSUPP;
+       if (local->ops->conf_tx)
+               ret = local->ops->get_survey(&local->hw, idx, survey);
+       /* trace_drv_get_survey(local, idx, survey, ret); */
+       return ret;
+ }
  
  static inline void drv_rfkill_poll(struct ieee80211_local *local)
  {
diff --combined net/mac80211/key.c
@@@ -14,7 -14,6 +14,7 @@@
  #include <linux/list.h>
  #include <linux/rcupdate.h>
  #include <linux/rtnetlink.h>
 +#include <linux/slab.h>
  #include <net/mac80211.h>
  #include "ieee80211_i.h"
  #include "driver-ops.h"
@@@ -140,6 -139,7 +140,7 @@@ static void ieee80211_key_enable_hw_acc
                                     struct ieee80211_sub_if_data,
                                     u.ap);
  
+       key->conf.ap_addr = sdata->dev->dev_addr;
        ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
  
        if (!ret) {
diff --combined net/mac80211/mlme.c
@@@ -19,7 -19,6 +19,7 @@@
  #include <linux/rtnetlink.h>
  #include <linux/pm_qos_params.h>
  #include <linux/crc32.h>
 +#include <linux/slab.h>
  #include <net/mac80211.h>
  #include <asm/unaligned.h>
  
@@@ -175,8 -174,6 +175,8 @@@ static u32 ieee80211_enable_ht(struct i
        ht_changed = conf_is_ht(&local->hw.conf) != enable_ht ||
                     channel_type != local->hw.conf.channel_type;
  
 +      if (local->tmp_channel)
 +              local->tmp_channel_type = channel_type;
        local->oper_channel_type = channel_type;
  
        if (ht_changed) {
@@@ -1333,12 -1330,17 +1333,17 @@@ static void ieee80211_rx_mgmt_probe_res
                mutex_lock(&sdata->local->iflist_mtx);
                ieee80211_recalc_ps(sdata->local, -1);
                mutex_unlock(&sdata->local->iflist_mtx);
+               if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
+                       return;
                /*
                 * We've received a probe response, but are not sure whether
                 * we have or will be receiving any beacons or data, so let's
                 * schedule the timers again, just in case.
                 */
                mod_beacon_timer(sdata);
                mod_timer(&ifmgd->conn_mon_timer,
                          round_jiffies_up(jiffies +
                                           IEEE80211_CONNECTION_IDLE_TIME));
diff --combined net/wireless/sme.c
@@@ -7,7 -7,6 +7,7 @@@
  
  #include <linux/etherdevice.h>
  #include <linux/if_arp.h>
 +#include <linux/slab.h>
  #include <linux/workqueue.h>
  #include <linux/wireless.h>
  #include <net/iw_handler.h>
@@@ -518,12 -517,16 +518,16 @@@ void cfg80211_connect_result(struct net
        ev->type = EVENT_CONNECT_RESULT;
        if (bssid)
                memcpy(ev->cr.bssid, bssid, ETH_ALEN);
-       ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
-       ev->cr.req_ie_len = req_ie_len;
-       memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
-       ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
-       ev->cr.resp_ie_len = resp_ie_len;
-       memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len);
+       if (req_ie_len) {
+               ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
+               ev->cr.req_ie_len = req_ie_len;
+               memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
+       }
+       if (resp_ie_len) {
+               ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
+               ev->cr.resp_ie_len = resp_ie_len;
+               memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len);
+       }
        ev->cr.status = status;
  
        spin_lock_irqsave(&wdev->event_lock, flags);