Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Thu, 15 Apr 2010 20:21:34 +0000 (16:21 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 15 Apr 2010 20:21:34 +0000 (16:21 -0400)
Conflicts:
Documentation/feature-removal-schedule.txt
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/wl12xx/wl1271_main.c

70 files changed:
1  2 
Documentation/feature-removal-schedule.txt
drivers/net/wireless/ath/ar9170/main.c
drivers/net/wireless/ath/ar9170/usb.c
drivers/net/wireless/ath/ath5k/attach.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/virtual.c
drivers/net/wireless/ath/regd.c
drivers/net/wireless/b43/phy_n.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlwifi/iwl-3945-rs.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-calib.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-devtrace.c
drivers/net/wireless/iwlwifi/iwl-io.h
drivers/net/wireless/iwlwifi/iwl-power.c
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/libertas/debugfs.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/p54/p54pci.c
drivers/net/wireless/prism54/islpci_dev.c
drivers/net/wireless/prism54/islpci_eth.c
drivers/net/wireless/prism54/islpci_mgt.c
drivers/net/wireless/prism54/oid_mgt.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/wl12xx/wl1251_main.c
drivers/net/wireless/wl12xx/wl1251_spi.c
drivers/net/wireless/wl12xx/wl1271_acx.c
drivers/net/wireless/wl12xx/wl1271_boot.c
drivers/net/wireless/wl12xx/wl1271_cmd.c
drivers/net/wireless/wl12xx/wl1271_init.c
drivers/net/wireless/wl12xx/wl1271_main.c
drivers/net/wireless/wl12xx/wl1271_rx.c
drivers/net/wireless/wl12xx/wl1271_spi.c
include/linux/mmc/sdio.h
include/net/mac80211.h
net/mac80211/agg-rx.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/debugfs_netdev.c
net/mac80211/ieee80211_i.h
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/work.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/sme.c
net/wireless/util.c

index 267e90582d20bbe0126a9656b894aa32fd57dbd0,5f460110c5ee69b521609b8f83b39d14912bb26f..116a13c4f13f701e48f384d92e8174c41fe10e5c
@@@ -117,25 -117,19 +117,25 @@@ Who:    Mauro Carvalho Chehab <mchehab@inf
  ---------------------------
  
  What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
 -When: November 2005
 +When: 2.6.35/2.6.36
  Files:        drivers/pcmcia/: pcmcia_ioctl.c
  Why:  With the 16-bit PCMCIA subsystem now behaving (almost) like a
        normal hotpluggable bus, and with it using the default kernel
        infrastructure (hotplug, driver core, sysfs) keeping the PCMCIA
        control ioctl needed by cardmgr and cardctl from pcmcia-cs is
 -      unnecessary, and makes further cleanups and integration of the
 +      unnecessary and potentially harmful (it does not provide for
 +      proper locking), and makes further cleanups and integration of the
        PCMCIA subsystem into the Linux kernel device driver model more
        difficult. The features provided by cardmgr and cardctl are either
        handled by the kernel itself now or are available in the new
        pcmciautils package available at
        http://kernel.org/pub/linux/utils/kernel/pcmcia/
 -Who:  Dominik Brodowski <linux@brodo.de>
 +
 +      For all architectures except ARM, the associated config symbol
 +      has been removed from kernel 2.6.34; for ARM, it will be likely
 +      be removed from kernel 2.6.35. The actual code will then likely
 +      be removed from kernel 2.6.36.
 +Who:  Dominik Brodowski <linux@dominikbrodowski.net>
  
  ---------------------------
  
@@@ -449,6 -443,12 +449,6 @@@ Who:      Alok N Kataria <akataria@vmware.co
  
  ----------------------------
  
 -What: adt7473 hardware monitoring driver
 -When: February 2010
 -Why:  Obsoleted by the adt7475 driver.
 -Who:  Jean Delvare <khali@linux-fr.org>
 -
 ----------------------------
  What: Support for lcd_switch and display_get in asus-laptop driver
  When: March 2010
  Why:  These two features use non-standard interfaces. There are the
@@@ -520,7 -520,6 +520,6 @@@ Who:       Hans de Goede <hdegoede@redhat.com
  
  ----------------------------
  
  What: corgikbd, spitzkbd, tosakbd driver
  When: 2.6.35
  Files:        drivers/input/keyboard/{corgi,spitz,tosa}kbd.c
@@@ -572,39 -571,23 +571,60 @@@ Who:    Jan Kiszka <jan.kiszka@web.de
  
  ----------------------------
  
 -
 -----------------------------
 +What: KVM memory aliases support
 +When: July 2010
 +Why:  Memory aliasing support is used for speeding up guest vga access
 +      through the vga windows.
 +
 +      Modern userspace no longer uses this feature, so it's just bitrotted
 +      code and can be removed with no impact.
 +Who:  Avi Kivity <avi@redhat.com>
 +
 +----------------------------
 +
 +What: KVM kernel-allocated memory slots
 +When: July 2010
 +Why:  Since 2.6.25, kvm supports user-allocated memory slots, which are
 +      much more flexible than kernel-allocated slots.  All current userspace
 +      supports the newer interface and this code can be removed with no
 +      impact.
 +Who:  Avi Kivity <avi@redhat.com>
 +
 +----------------------------
 +
 +What: KVM paravirt mmu host support
 +When: January 2011
 +Why:  The paravirt mmu host support is slower than non-paravirt mmu, both
 +      on newer and older hardware.  It is already not exposed to the guest,
 +      and kept only for live migration purposes.
 +Who:  Avi Kivity <avi@redhat.com>
 +
 +----------------------------
 +
 +What:         "acpi=ht" boot option
 +When: 2.6.35
 +Why:  Useful in 2003, implementation is a hack.
 +      Generally invoked by accident today.
 +      Seen as doing more harm than good.
 +Who:  Len Brown <len.brown@intel.com>
++
++----------------------------
++
+ What: iwlwifi 50XX module parameters
+ When: 2.6.40
+ Why:  The "..50" modules parameters were used to configure 5000 series and
+       up devices; different set of module parameters also available for 4965
+       with same functionalities. Consolidate both set into single place
+       in drivers/net/wireless/iwlwifi/iwl-agn.c
+ Who:  Wey-Yi Guy <wey-yi.w.guy@intel.com>
+ ----------------------------
+ What: iwl4965 alias support
+ When: 2.6.40
+ Why:  Internal alias support has been present in module-init-tools for some
+       time, the MODULE_ALIAS("iwl4965") boilerplate aliases can be removed
+       with no impact.
+ Who:  Wey-Yi Guy <wey-yi.w.guy@intel.com>
index 7c4a7d84535cfb902a0b8a92b2d8b3d094c1340e,fed6695ec04e4c1046cb43304f27b2bd25c5e269..0312cee395703c38c34835aa0fa180877fbe9e62
@@@ -38,7 -38,6 +38,7 @@@
   */
  
  #include <linux/init.h>
 +#include <linux/slab.h>
  #include <linux/module.h>
  #include <linux/etherdevice.h>
  #include <net/mac80211.h>
@@@ -236,7 -235,7 +236,7 @@@ static void __ar9170_dump_txqueue(struc
               wiphy_name(ar->hw->wiphy), skb_queue_len(queue));
  
        skb_queue_walk(queue, skb) {
-               printk(KERN_DEBUG "index:%d => \n", i++);
+               printk(KERN_DEBUG "index:%d =>\n", i++);
                ar9170_print_txheader(ar, skb);
        }
        if (i != skb_queue_len(queue))
@@@ -281,7 -280,7 +281,7 @@@ static void ar9170_dump_tx_status_ampdu
        unsigned long flags;
  
        spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags);
-       printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n",
+       printk(KERN_DEBUG "%s: A-MPDU tx_status queue =>\n",
               wiphy_name(ar->hw->wiphy));
        __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu);
        spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags);
@@@ -308,7 -307,7 +308,7 @@@ static void ar9170_recycle_expired(stru
                if (time_is_before_jiffies(arinfo->timeout)) {
  #ifdef AR9170_QUEUE_DEBUG
                        printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => "
-                              "recycle \n", wiphy_name(ar->hw->wiphy),
+                              "recycle\n", wiphy_name(ar->hw->wiphy),
                               jiffies, arinfo->timeout);
                        ar9170_print_txheader(ar, skb);
  #endif /* AR9170_QUEUE_DEBUG */
@@@ -395,7 -394,7 +395,7 @@@ static void ar9170_tx_fake_ampdu_status
                ieee80211_tx_status_irqsafe(ar->hw, skb);
        }
  
 -      for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) {
 +      for_each_set_bit(i, &queue_bitmap, BITS_PER_BYTE) {
  #ifdef AR9170_QUEUE_STOP_DEBUG
                printk(KERN_DEBUG "%s: wake queue %d\n",
                       wiphy_name(ar->hw->wiphy), i);
@@@ -689,7 -688,8 +689,8 @@@ void ar9170_handle_command_response(str
  
        /* firmware debug */
        case 0xca:
-               printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4);
+               printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4,
+                               (char *)buf + 4);
                break;
        case 0xcb:
                len -= 4;
@@@ -1728,7 -1728,7 +1729,7 @@@ static void ar9170_tx(struct ar9170 *ar
                        printk(KERN_DEBUG "%s: queue %d full\n",
                               wiphy_name(ar->hw->wiphy), i);
  
-                       printk(KERN_DEBUG "%s: stuck frames: ===> \n",
+                       printk(KERN_DEBUG "%s: stuck frames: ===>\n",
                               wiphy_name(ar->hw->wiphy));
                        ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
                        ar9170_dump_txqueue(ar, &ar->tx_status[i]);
        return err;
  }
  
 -static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
 -                                     struct dev_addr_list *mclist)
 +static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw,
 +                                     struct netdev_hw_addr_list *mc_list)
  {
        u64 mchash;
 -      int i;
 +      struct netdev_hw_addr *ha;
  
        /* always get broadcast frames */
        mchash = 1ULL << (0xff >> 2);
  
 -      for (i = 0; i < mc_count; i++) {
 -              if (WARN_ON(!mclist))
 -                      break;
 -              mchash |= 1ULL << (mclist->dmi_addr[5] >> 2);
 -              mclist = mclist->next;
 -      }
 +      netdev_hw_addr_list_for_each(ha, mc_list)
 +              mchash |= 1ULL << (ha->addr[5] >> 2);
  
        return mchash;
  }
@@@ -2509,10 -2513,10 +2510,10 @@@ void *ar9170_alloc(size_t priv_size
        /*
         * this buffer is used for rx stream reconstruction.
         * Under heavy load this device (or the transport layer?)
 -       * tends to split the streams into seperate rx descriptors.
 +       * tends to split the streams into separate rx descriptors.
         */
  
-       skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL);
+       skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL);
        if (!skb)
                goto err_nomem;
  
index 99a6da464bd377caf51059c2f9869420161cf317,0259bb46247d8ae2266eb421ca50bc880b5778f9..c1c7c427501c3da038a0efd06f52349568014763
@@@ -38,7 -38,6 +38,7 @@@
   */
  
  #include <linux/module.h>
 +#include <linux/slab.h>
  #include <linux/usb.h>
  #include <linux/firmware.h>
  #include <linux/etherdevice.h>
@@@ -67,18 -66,28 +67,28 @@@ static struct usb_device_id ar9170_usb_
        { USB_DEVICE(0x0cf3, 0x1001) },
        /* TP-Link TL-WN821N v2 */
        { USB_DEVICE(0x0cf3, 0x1002) },
+       /* 3Com Dual Band 802.11n USB Adapter */
+       { USB_DEVICE(0x0cf3, 0x1010) },
+       /* H3C Dual Band 802.11n USB Adapter */
+       { USB_DEVICE(0x0cf3, 0x1011) },
        /* Cace Airpcap NX */
        { USB_DEVICE(0xcace, 0x0300) },
        /* D-Link DWA 160 A1 */
        { USB_DEVICE(0x07d1, 0x3c10) },
        /* D-Link DWA 160 A2 */
        { USB_DEVICE(0x07d1, 0x3a09) },
+       /* Netgear WNA1000 */
+       { USB_DEVICE(0x0846, 0x9040) },
        /* Netgear WNDA3100 */
        { USB_DEVICE(0x0846, 0x9010) },
        /* Netgear WN111 v2 */
        { USB_DEVICE(0x0846, 0x9001) },
        /* Zydas ZD1221 */
        { USB_DEVICE(0x0ace, 0x1221) },
+       /* Proxim ORiNOCO 802.11n USB */
+       { USB_DEVICE(0x1435, 0x0804) },
+       /* WNC Generic 11n USB Dongle */
+       { USB_DEVICE(0x1435, 0x0326) },
        /* ZyXEL NWD271N */
        { USB_DEVICE(0x0586, 0x3417) },
        /* Z-Com UB81 BG */
index f571ad1a225ec5fdfbd3575e93ee68d1211dc594,dcf7c30f813f580ae8e127455e339b958af7eca8..e0c244b02f05d17cc1ee9fb7cc12dd9e0e01541e
@@@ -21,7 -21,6 +21,7 @@@
  \*************************************/
  
  #include <linux/pci.h>
 +#include <linux/slab.h>
  #include "ath5k.h"
  #include "reg.h"
  #include "debug.h"
@@@ -124,6 -123,8 +124,8 @@@ int ath5k_hw_attach(struct ath5k_softc 
        ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
        ah->ah_software_retry = false;
        ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
+       ah->ah_noise_floor = -95;       /* until first NF calibration is run */
+       sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
  
        /*
         * Find the mac version
index 7ac3a720e52c73164e2c5e13c815f45e90377d4f,92327423325fa06c51ed48b4a5363213f730807a..93005f1d326dc9e3ce9c9694575d11afc5e363d0
@@@ -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>
  
@@@ -59,8 -58,8 +59,8 @@@
  #include "base.h"
  #include "reg.h"
  #include "debug.h"
+ #include "ani.h"
  
- static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
  static int modparam_nohwcrypt;
  module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
  MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
@@@ -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,
@@@ -365,6 -364,7 +365,7 @@@ static void        ath5k_beacon_send(struct a
  static void   ath5k_beacon_config(struct ath5k_softc *sc);
  static void   ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
  static void   ath5k_tasklet_beacon(unsigned long data);
+ static void   ath5k_tasklet_ani(unsigned long data);
  
  static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
  {
@@@ -830,6 -830,7 +831,7 @@@ ath5k_attach(struct pci_dev *pdev, stru
        tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
        tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
        tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
+       tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
  
        ret = ath5k_eeprom_read_mac(ah, mac);
        if (ret) {
@@@ -1635,7 -1636,6 +1637,6 @@@ ath5k_txq_cleanup(struct ath5k_softc *s
                                        sc->txqs[i].link);
                        }
        }
-       ieee80211_wake_queues(sc->hw); /* XXX move to callers */
  
        for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
                if (sc->txqs[i].setup)
@@@ -1805,6 -1805,25 +1806,25 @@@ ath5k_check_ibss_tsf(struct ath5k_soft
        }
  }
  
+ static void
+ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
+ {
+       struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+       struct ath5k_hw *ah = sc->ah;
+       struct ath_common *common = ath5k_hw_common(ah);
+       /* only beacons from our BSSID */
+       if (!ieee80211_is_beacon(mgmt->frame_control) ||
+           memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0)
+               return;
+       ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg,
+                                                     rssi);
+       /* in IBSS mode we should keep RSSI statistics per neighbour */
+       /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */
+ }
  /*
   * Compute padding position. skb must contains an IEEE 802.11 frame
   */
@@@ -1923,6 -1942,8 +1943,8 @@@ ath5k_tasklet_rx(unsigned long data
                                sc->stats.rxerr_fifo++;
                        if (rs.rs_status & AR5K_RXERR_PHY) {
                                sc->stats.rxerr_phy++;
+                               if (rs.rs_phyerr > 0 && rs.rs_phyerr < 32)
+                                       sc->stats.rxerr_phy_code[rs.rs_phyerr]++;
                                goto next;
                        }
                        if (rs.rs_status & AR5K_RXERR_DECRYPT) {
@@@ -2024,6 -2045,8 +2046,8 @@@ accept
  
                ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
  
+               ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi);
                /* check beacons in IBSS mode */
                if (sc->opmode == NL80211_IFTYPE_ADHOC)
                        ath5k_check_ibss_tsf(sc, skb, rxs);
@@@ -2060,6 -2083,17 +2084,17 @@@ ath5k_tx_processq(struct ath5k_softc *s
        list_for_each_entry_safe(bf, bf0, &txq->q, list) {
                ds = bf->desc;
  
+               /*
+                * It's possible that the hardware can say the buffer is
+                * completed when it hasn't yet loaded the ds_link from
+                * host memory and moved on.  If there are more TX
+                * descriptors in the queue, wait for TXDP to change
+                * before processing this one.
+                */
+               if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr &&
+                   !list_is_last(&bf->list, &txq->q))
+                       break;
                ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
                if (unlikely(ret == -EINPROGRESS))
                        break;
                info->status.rates[ts.ts_final_idx].count++;
  
                if (unlikely(ts.ts_status)) {
-                       sc->ll_stats.dot11ACKFailureCount++;
+                       sc->stats.ack_fail++;
                        if (ts.ts_status & AR5K_TXERR_FILT) {
                                info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
                                sc->stats.txerr_filt++;
@@@ -2498,9 -2532,6 +2533,6 @@@ ath5k_init(struct ath5k_softc *sc
         */
        ath5k_stop_locked(sc);
  
-       /* Set PHY calibration interval */
-       ah->ah_cal_intval = ath5k_calinterval;
        /*
         * The basic interface to setting the hardware in a good
         * state is ``reset''.  On return the hardware is known to
        sc->curband = &sc->sbands[sc->curchan->band];
        sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
                AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
-               AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI;
+               AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
        ret = ath5k_reset(sc, NULL);
        if (ret)
                goto done;
        for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
                ath5k_hw_reset_key(ah, i);
  
-       /* Set ack to be sent at low bit-rates */
-       ath5k_hw_set_ack_bitrate_high(ah, false);
+       ath5k_hw_set_ack_bitrate_high(ah, true);
        ret = 0;
  done:
        mmiowb();
@@@ -2624,12 -2655,33 +2656,33 @@@ ath5k_stop_hw(struct ath5k_softc *sc
        tasklet_kill(&sc->restq);
        tasklet_kill(&sc->calib);
        tasklet_kill(&sc->beacontq);
+       tasklet_kill(&sc->ani_tasklet);
  
        ath5k_rfkill_hw_stop(sc->ah);
  
        return ret;
  }
  
+ static void
+ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
+ {
+       if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) &&
+           !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) {
+               /* run ANI only when full calibration is not active */
+               ah->ah_cal_next_ani = jiffies +
+                       msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI);
+               tasklet_schedule(&ah->ah_sc->ani_tasklet);
+       } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) {
+               ah->ah_cal_next_full = jiffies +
+                       msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL);
+               tasklet_schedule(&ah->ah_sc->calib);
+       }
+       /* we could use SWI to generate enough interrupts to meet our
+        * calibration interval requirements, if necessary:
+        * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
+ }
  static irqreturn_t
  ath5k_intr(int irq, void *dev_id)
  {
                         */
                        tasklet_schedule(&sc->restq);
                } else if (unlikely(status & AR5K_INT_RXORN)) {
-                       tasklet_schedule(&sc->restq);
+                       /*
+                        * Receive buffers are full. Either the bus is busy or
+                        * the CPU is not fast enough to process all received
+                        * frames.
+                        * Older chipsets need a reset to come out of this
+                        * condition, but we treat it as RX for newer chips.
+                        * We don't know exactly which versions need a reset -
+                        * this guess is copied from the HAL.
+                        */
+                       sc->stats.rxorn_intr++;
+                       if (ah->ah_mac_srev < AR5K_SREV_AR5212)
+                               tasklet_schedule(&sc->restq);
+                       else
+                               tasklet_schedule(&sc->rxtq);
                } else {
                        if (status & AR5K_INT_SWBA) {
                                tasklet_hi_schedule(&sc->beacontq);
                        if (status & AR5K_INT_BMISS) {
                                /* TODO */
                        }
-                       if (status & AR5K_INT_SWI) {
-                               tasklet_schedule(&sc->calib);
-                       }
                        if (status & AR5K_INT_MIB) {
-                               /*
-                                * These stats are also used for ANI i think
-                                * so how about updating them more often ?
-                                */
-                               ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
+                               sc->stats.mib_intr++;
+                               ath5k_hw_update_mib_counters(ah);
+                               ath5k_ani_mib_intr(ah);
                        }
                        if (status & AR5K_INT_GPIO)
                                tasklet_schedule(&sc->rf_kill.toggleq);
        if (unlikely(!counter))
                ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
  
-       ath5k_hw_calibration_poll(ah);
+       ath5k_intr_calibration_poll(ah);
  
        return IRQ_HANDLED;
  }
@@@ -2721,8 -2781,7 +2782,7 @@@ ath5k_tasklet_calibrate(unsigned long d
        struct ath5k_hw *ah = sc->ah;
  
        /* Only full calibration for now */
-       if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION)
-               return;
+       ah->ah_cal_mask |= AR5K_CALIBRATION_FULL;
  
        /* Stop queues so that calibration
         * doesn't interfere with tx */
                 * to load new gain values.
                 */
                ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
-               ath5k_reset_wake(sc);
+               ath5k_reset(sc, sc->curchan);
        }
        if (ath5k_hw_phy_calibrate(ah, sc->curchan))
                ATH5K_ERR(sc, "calibration of channel %u failed\n",
                        ieee80211_frequency_to_channel(
                                sc->curchan->center_freq));
  
-       ah->ah_swi_mask = 0;
        /* Wake queues */
        ieee80211_wake_queues(sc->hw);
  
+       ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;
+ }
+ static void
+ ath5k_tasklet_ani(unsigned long data)
+ {
+       struct ath5k_softc *sc = (void *)data;
+       struct ath5k_hw *ah = sc->ah;
+       ah->ah_cal_mask |= AR5K_CALIBRATION_ANI;
+       ath5k_ani_calibration(ah);
+       ah->ah_cal_mask &= ~AR5K_CALIBRATION_ANI;
  }
  
  
@@@ -2852,6 -2922,8 +2923,8 @@@ ath5k_reset(struct ath5k_softc *sc, str
                goto err;
        }
  
+       ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode);
        /*
         * Change channels and update the h/w rate map if we're switching;
         * e.g. 11a to 11b/g.
@@@ -3000,20 -3072,22 +3073,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];
@@@ -3207,12 -3282,14 +3280,14 @@@ ath5k_get_stats(struct ieee80211_hw *hw
                struct ieee80211_low_level_stats *stats)
  {
        struct ath5k_softc *sc = hw->priv;
-       struct ath5k_hw *ah = sc->ah;
  
        /* Force update */
-       ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
+       ath5k_hw_update_mib_counters(sc->ah);
  
-       memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
+       stats->dot11ACKFailureCount = sc->stats.ack_fail;
+       stats->dot11RTSFailureCount = sc->stats.rts_fail;
+       stats->dot11RTSSuccessCount = sc->stats.rts_ok;
+       stats->dot11FCSErrorCount = sc->stats.fcs_error;
  
        return 0;
  }
index 3ee74c8397684b5c877be2631d14a95048eb95e4,60873a4f6171e8a6faaf8b6f201ffa0dc6451ae4..3ce9afba1d8868fdb7c9a5d4db24ae0a64128cfc
@@@ -21,7 -21,6 +21,7 @@@
   */
  
  #include <linux/delay.h>
 +#include <linux/slab.h>
  
  #include "ath5k.h"
  #include "reg.h"
@@@ -980,7 -979,7 +980,7 @@@ static int ath5k_hw_rf5112_channel(stru
                        return -EINVAL;
  
                data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
-       } else if ((c - (c % 5)) != 2 || c > 5435) {
+       } else if ((c % 5) != 2 || c > 5435) {
                if (!(c % 20) && c >= 5120) {
                        data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
                        data2 = ath5k_hw_bitswap(3, 2);
                } else
                        return -EINVAL;
        } else {
-               data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
+               data0 = ath5k_hw_bitswap((10 * (c - 2 - 4800)) / 25 + 1, 8);
                data2 = ath5k_hw_bitswap(0, 2);
        }
  
@@@ -1021,7 -1020,7 +1021,7 @@@ static int ath5k_hw_rf2425_channel(stru
                data0 = ath5k_hw_bitswap((c - 2272), 8);
                data2 = 0;
        /* ? 5GHz ? */
-       } else if ((c - (c % 5)) != 2 || c > 5435) {
+       } else if ((c % 5) != 2 || c > 5435) {
                if (!(c % 20) && c < 5120)
                        data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
                else if (!(c % 10))
                        return -EINVAL;
                data2 = ath5k_hw_bitswap(1, 2);
        } else {
-               data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
+               data0 = ath5k_hw_bitswap((10 * (c - 2 - 4800)) / 25 + 1, 8);
                data2 = ath5k_hw_bitswap(0, 2);
        }
  
@@@ -1103,28 -1102,6 +1103,6 @@@ int ath5k_hw_channel(struct ath5k_hw *a
    PHY calibration
  \*****************/
  
- void
- ath5k_hw_calibration_poll(struct ath5k_hw *ah)
- {
-       /* Calibration interval in jiffies */
-       unsigned long cal_intval;
-       cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000);
-       /* Initialize timestamp if needed */
-       if (!ah->ah_cal_tstamp)
-               ah->ah_cal_tstamp = jiffies;
-       /* For now we always do full calibration
-        * Mark software interrupt mask and fire software
-        * interrupt (bit gets auto-cleared) */
-       if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) {
-               ah->ah_cal_tstamp = jiffies;
-               ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION;
-               AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI);
-       }
- }
  static int sign_extend(int val, const int nbits)
  {
        int order = BIT(nbits-1);
@@@ -1411,7 -1388,10 +1389,10 @@@ static int ath5k_hw_rf511x_calibrate(st
        i_coff = (-iq_corr) / i_coffd;
        i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */
  
-       q_coff = (i_pwr / q_coffd) - 128;
+       if (ah->ah_version == AR5K_AR5211)
+               q_coff = (i_pwr / q_coffd) - 64;
+       else
+               q_coff = (i_pwr / q_coffd) - 128;
        q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */
  
        ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
@@@ -2580,7 -2560,7 +2561,7 @@@ ath5k_combine_pwr_to_pdadc_curves(struc
                max_idx = (pdadc_n < table_size) ? pdadc_n : table_size;
  
                /* Fill pdadc_out table */
-               while (pdadc_0 < max_idx)
+               while (pdadc_0 < max_idx && pdadc_i < 128)
                        pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++];
  
                /* Need to extrapolate above this pdgain? */
index 081e0085ed4ce3460c82d2ba8f44eab5a090a4e7,b22d46509b67e95e952e651a1dfc37335589668e..9a8e419398f94f66fdd2d6e2fb2977cff58c6ddd
@@@ -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"
@@@ -157,10 -156,10 +157,10 @@@ static ssize_t read_file_dma(struct fil
                "txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
                (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
  
-       len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x \n",
+       len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n",
                        REG_READ_D(ah, AR_OBS_BUS_1));
        len += snprintf(buf + len, DMA_BUF_LEN - len,
-                       "AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR));
+                       "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR));
  
        ath9k_ps_restore(sc);
  
@@@ -557,10 -556,8 +557,8 @@@ static ssize_t read_file_xmit(struct fi
  }
  
  void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
-                      struct ath_buf *bf)
+                      struct ath_buf *bf, struct ath_tx_status *ts)
  {
-       struct ath_desc *ds = bf->bf_desc;
        if (bf_isampdu(bf)) {
                if (bf_isxretried(bf))
                        TX_STAT_INC(txq->axq_qnum, a_xretries);
                TX_STAT_INC(txq->axq_qnum, completed);
        }
  
-       if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)
+       if (ts->ts_status & ATH9K_TXERR_FIFO)
                TX_STAT_INC(txq->axq_qnum, fifo_underrun);
-       if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP)
+       if (ts->ts_status & ATH9K_TXERR_XTXOP)
                TX_STAT_INC(txq->axq_qnum, xtxop);
-       if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED)
+       if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
                TX_STAT_INC(txq->axq_qnum, timer_exp);
-       if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR)
+       if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
                TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
-       if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN)
+       if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
                TX_STAT_INC(txq->axq_qnum, data_underrun);
-       if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN)
+       if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
                TX_STAT_INC(txq->axq_qnum, delim_underrun);
  }
  
@@@ -663,30 -660,29 +661,29 @@@ static ssize_t read_file_recv(struct fi
  #undef PHY_ERR
  }
  
- void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf)
+ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
  {
  #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++
  #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
  
-       struct ath_desc *ds = bf->bf_desc;
        u32 phyerr;
  
-       if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
+       if (rs->rs_status & ATH9K_RXERR_CRC)
                RX_STAT_INC(crc_err);
-       if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT)
+       if (rs->rs_status & ATH9K_RXERR_DECRYPT)
                RX_STAT_INC(decrypt_crc_err);
-       if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC)
+       if (rs->rs_status & ATH9K_RXERR_MIC)
                RX_STAT_INC(mic_err);
-       if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_PRE)
+       if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
                RX_STAT_INC(pre_delim_crc_err);
-       if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_POST)
+       if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST)
                RX_STAT_INC(post_delim_crc_err);
-       if (ds->ds_rxstat.rs_status & ATH9K_RX_DECRYPT_BUSY)
+       if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY)
                RX_STAT_INC(decrypt_busy_err);
  
-       if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) {
+       if (rs->rs_status & ATH9K_RXERR_PHY) {
                RX_STAT_INC(phy_err);
-               phyerr = ds->ds_rxstat.rs_phyerr & 0x24;
+               phyerr = rs->rs_phyerr & 0x24;
                RX_PHY_ERR_INC(phyerr);
        }
  
index 7fdaea3a162907233c7ec6325a7436726b590619,3b9f4c1f8d4e41a10dacfb45c54be5d391a8df42..af730c7d50e6fe540ba3355fb221ba6c704927fb
@@@ -15,7 -15,6 +15,7 @@@
   */
  
  #include <linux/io.h>
 +#include <linux/slab.h>
  #include <asm/unaligned.h>
  
  #include "hw.h"
@@@ -28,9 -27,6 +28,6 @@@
  
  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);
- static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
-                             struct ar5416_eeprom_def *pEepData,
-                             u32 reg, u32 value);
  
  MODULE_AUTHOR("Atheros Communications");
  MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
@@@ -548,7 -544,6 +545,6 @@@ static bool ath9k_hw_devid_supported(u1
        case AR9285_DEVID_PCIE:
        case AR5416_DEVID_AR9287_PCI:
        case AR5416_DEVID_AR9287_PCIE:
-       case AR9271_USB:
        case AR2427_DEVID_PCIE:
                return true;
        default:
@@@ -817,38 -812,46 +813,46 @@@ static void ath9k_hw_init_mode_gain_reg
  
                /* txgain table */
                if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9285Modes_high_power_tx_gain_9285_1_2,
-                       ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6);
+                       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 {
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9285Modes_original_tx_gain_9285_1_2,
-                       ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6);
+                       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)
  {
-       u32 i, j;
-       if (ah->hw_version.devid == AR9280_DEVID_PCI) {
-               /* EEPROM Fixup */
-               for (i = 0; i < ah->iniModes.ia_rows; i++) {
-                       u32 reg = INI_RA(&ah->iniModes, i, 0);
+       struct base_eep_header *pBase = &(ah->eeprom.def.baseEepHeader);
+       struct ath_common *common = ath9k_hw_common(ah);
  
-                       for (j = 1; j < ah->iniModes.ia_columns; j++) {
-                               u32 val = INI_RA(&ah->iniModes, i, j);
+       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);
  
-                               INI_RA(&ah->iniModes, i, j) =
-                                       ath9k_hw_ini_fixup(ah,
-                                                          &ah->eeprom.def,
-                                                          reg, val);
-                       }
-               }
-       }
+       if (ah->need_an_top2_fixup)
+               ath_print(common, ATH_DBG_EEPROM,
+                         "needs fixup for AR_AN_TOP2 register\n");
  }
  
  int ath9k_hw_init(struct ath_hw *ah)
        struct ath_common *common = ath9k_hw_common(ah);
        int r = 0;
  
-       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;
+       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);
@@@ -1121,23 -1126,23 +1127,23 @@@ static void ath9k_hw_init_chain_masks(s
  static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
                                          enum nl80211_iftype opmode)
  {
-       ah->mask_reg = AR_IMR_TXERR |
+       u32 imr_reg = AR_IMR_TXERR |
                AR_IMR_TXURN |
                AR_IMR_RXERR |
                AR_IMR_RXORN |
                AR_IMR_BCNMISC;
  
        if (ah->config.rx_intr_mitigation)
-               ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+               imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
        else
-               ah->mask_reg |= AR_IMR_RXOK;
+               imr_reg |= AR_IMR_RXOK;
  
-       ah->mask_reg |= AR_IMR_TXOK;
+       imr_reg |= AR_IMR_TXOK;
  
        if (opmode == NL80211_IFTYPE_AP)
-               ah->mask_reg |= AR_IMR_MIB;
+               imr_reg |= AR_IMR_MIB;
  
-       REG_WRITE(ah, AR_IMR, ah->mask_reg);
+       REG_WRITE(ah, AR_IMR, imr_reg);
        ah->imrs2_reg |= AR_IMR_S2_GTT;
        REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
  
@@@ -1290,51 -1295,6 +1296,6 @@@ static void ath9k_hw_override_ini(struc
        }
  }
  
- static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah,
-                             struct ar5416_eeprom_def *pEepData,
-                             u32 reg, u32 value)
- {
-       struct base_eep_header *pBase = &(pEepData->baseEepHeader);
-       struct ath_common *common = ath9k_hw_common(ah);
-       switch (ah->hw_version.devid) {
-       case AR9280_DEVID_PCI:
-               if (reg == 0x7894) {
-                       ath_print(common, ATH_DBG_EEPROM,
-                               "ini VAL: %x  EEPROM: %x\n", value,
-                               (pBase->version & 0xff));
-                       if ((pBase->version & 0xff) > 0x0a) {
-                               ath_print(common, ATH_DBG_EEPROM,
-                                         "PWDCLKIND: %d\n",
-                                         pBase->pwdclkind);
-                               value &= ~AR_AN_TOP2_PWDCLKIND;
-                               value |= AR_AN_TOP2_PWDCLKIND &
-                                       (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
-                       } else {
-                               ath_print(common, ATH_DBG_EEPROM,
-                                         "PWDCLKIND Earlier Rev\n");
-                       }
-                       ath_print(common, ATH_DBG_EEPROM,
-                                 "final ini VAL: %x\n", value);
-               }
-               break;
-       }
-       return value;
- }
- static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
-                             struct ar5416_eeprom_def *pEepData,
-                             u32 reg, u32 value)
- {
-       if (ah->eep_map == EEP_MAP_4KBITS)
-               return value;
-       else
-               return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value);
- }
  static void ath9k_olc_init(struct ath_hw *ah)
  {
        u32 i;
@@@ -1440,6 -1400,9 +1401,9 @@@ static int ath9k_hw_process_ini(struct 
                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
@@@ -2840,7 -2803,7 +2804,7 @@@ EXPORT_SYMBOL(ath9k_hw_getisr)
  
  enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
  {
-       u32 omask = ah->mask_reg;
+       enum ath9k_int omask = ah->imask;
        u32 mask, mask2;
        struct ath9k_hw_capabilities *pCap = &ah->caps;
        struct ath_common *common = ath9k_hw_common(ah);
                           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);
-       ah->mask_reg = ints;
  
        if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
                if (ints & ATH9K_INT_TIM_TIMER)
@@@ -3231,8 -3193,10 +3194,10 @@@ int ath9k_hw_fill_cap_info(struct ath_h
                pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
        }
  #endif
-       pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
+       if (AR_SREV_9271(ah))
+               pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
+       else
+               pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
  
        if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
                pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
index 00c0e21a4af77269fb2b013a3bf25291ce39adc3,e95aaa3f18f3e4f70ed93cdf7926963587ee426c..105ad40968f6a41af2b7de50299a97d239b58d21
@@@ -14,8 -14,6 +14,8 @@@
   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   */
  
 +#include <linux/slab.h>
 +
  #include "ath9k.h"
  
  struct ath9k_vif_iter_data {
@@@ -220,7 -218,7 +220,7 @@@ static int ath9k_send_nullfunc(struct a
  
        memset(&txctl, 0, sizeof(struct ath_tx_control));
        txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]];
-       txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE;
+       txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE;
  
        if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
                goto exit;
index 00489c40be0cb66ec6993122bc3b2c8793fa1798,d5c23328aef172b392cc4595cc85864cdbd855ff..24d59883d94408cfc1d6bac2c4591776a841dcef
@@@ -15,6 -15,7 +15,6 @@@
   */
  
  #include <linux/kernel.h>
 -#include <linux/slab.h>
  #include <net/cfg80211.h>
  #include <net/mac80211.h>
  #include "regd.h"
@@@ -50,6 -51,7 +50,7 @@@
  
  #define ATH9K_5GHZ_ALL                ATH9K_5GHZ_5150_5350, \
                                ATH9K_5GHZ_5470_5850
  /* This one skips what we call "mid band" */
  #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
                                ATH9K_5GHZ_5725_5850
@@@ -360,7 -362,7 +361,7 @@@ EXPORT_SYMBOL(ath_reg_notifier_apply)
  
  static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
  {
-        u16 rd = ath_regd_get_eepromRD(reg);
+       u16 rd = ath_regd_get_eepromRD(reg);
        int i;
  
        if (rd & COUNTRY_ERD_FLAG) {
index c4dc369ce703546babdcf59322b41c79048964a6,9e93eb4a17cf61a153a406f4cbc6f5b912c095a9..3d6b33775964add64b73f96dab9c5890cd6d4275
@@@ -23,7 -23,6 +23,7 @@@
  */
  
  #include <linux/delay.h>
 +#include <linux/slab.h>
  #include <linux/types.h>
  
  #include "b43.h"
@@@ -105,7 -104,7 +105,7 @@@ static enum b43_txpwr_result b43_nphy_o
  }
  
  static void b43_chantab_radio_upload(struct b43_wldev *dev,
-                                    const struct b43_nphy_channeltab_entry *e)
+                               const struct b43_nphy_channeltab_entry_rev2 *e)
  {
        b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
        b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
  }
  
  static void b43_chantab_phy_upload(struct b43_wldev *dev,
-                                  const struct b43_nphy_channeltab_entry *e)
+                                  const struct b43_phy_n_sfo_cfg *e)
  {
        b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
        b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
@@@ -160,16 -159,16 +160,16 @@@ static void b43_nphy_tx_power_fix(struc
  
  /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
  static void b43_radio_2055_setup(struct b43_wldev *dev,
-                               const struct b43_nphy_channeltab_entry *e)
+                               const struct b43_nphy_channeltab_entry_rev2 *e)
  {
        B43_WARN_ON(dev->phy.rev >= 3);
  
        b43_chantab_radio_upload(dev, e);
        udelay(50);
-       b43_radio_write(dev, B2055_VCO_CAL10, 5);
-       b43_radio_write(dev, B2055_VCO_CAL10, 45);
+       b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
+       b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
        b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
-       b43_radio_write(dev, B2055_VCO_CAL10, 65);
+       b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
        udelay(300);
  }
  
@@@ -254,6 -253,16 +254,16 @@@ static void b43_radio_init2055(struct b
        b43_radio_init2055_post(dev);
  }
  
+ /*
+  * Initialize a Broadcom 2056 N-radio
+  * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
+  */
+ static void b43_radio_init2056(struct b43_wldev *dev)
+ {
+       /* TODO */
+ }
  /*
   * Upload the N-PHY tables.
   * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
@@@ -2791,7 -2800,7 +2801,7 @@@ static int b43_nphy_cal_tx_iq_lo(struc
                        }
                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
                                                buffer);
-                       b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2,
+                       b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2,
                                                buffer);
                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
                                                buffer);
@@@ -3261,7 -3270,7 +3271,7 @@@ int b43_phy_initn(struct b43_wldev *dev
  
  /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
  static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
-                               const struct b43_nphy_channeltab_entry *e,
+                               const struct b43_phy_n_sfo_cfg *e,
                                struct b43_chanspec chanspec)
  {
        struct b43_phy *phy = &dev->phy;
@@@ -3327,13 -3336,21 +3337,21 @@@ static int b43_nphy_set_chanspec(struc
  {
        struct b43_phy_n *nphy = dev->phy.n;
  
-       const struct b43_nphy_channeltab_entry *tabent;
+       const struct b43_nphy_channeltab_entry_rev2 *tabent_r2;
+       const struct b43_nphy_channeltab_entry_rev3 *tabent_r3;
  
        u8 tmp;
        u8 channel = chanspec.channel;
  
        if (dev->phy.rev >= 3) {
                /* TODO */
+               tabent_r3 = NULL;
+               if (!tabent_r3)
+                       return -ESRCH;
+       } else {
+               tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel);
+               if (!tabent_r2)
+                       return -ESRCH;
        }
  
        nphy->radio_chanspec = chanspec;
        if (dev->phy.rev >= 3) {
                tmp = (chanspec.b_freq == 1) ? 4 : 0;
                b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
-               /* TODO: PHY Radio2056 Setup (chan_info_ptr[i]) */
-               /* TODO: N PHY Chanspec Setup (chan_info_ptr[i]) */
+               /* TODO: PHY Radio2056 Setup (dev, tabent_r3); */
+               b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec);
        } else {
-               tabent = b43_nphy_get_chantabent(dev, channel);
-               if (!tabent)
-                       return -ESRCH;
                tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050;
                b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
-               b43_radio_2055_setup(dev, tabent);
-               b43_nphy_chanspec_setup(dev, tabent, chanspec);
+               b43_radio_2055_setup(dev, tabent_r2);
+               b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec);
        }
  
        return 0;
@@@ -3474,6 -3487,8 +3488,8 @@@ static void b43_nphy_op_radio_write(str
  static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
                                        bool blocked)
  {
+       struct b43_phy_n *nphy = dev->phy.n;
        if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
                b43err(dev->wl, "MAC not suspended\n");
  
                }
        } else {
                if (dev->phy.rev >= 3) {
-                       /* TODO: b43_radio_init2056(dev); */
-                       /* TODO: PHY Set Channel Spec (dev, radio_chanspec) */
+                       b43_radio_init2056(dev);
+                       b43_nphy_set_chanspec(dev, nphy->radio_chanspec);
                } else {
                        b43_radio_init2055(dev);
                }
index 7266730680bc96e8582faa872d8559bfe6307830,9e2ae8f3ecb0e9bef38ba80af3067d4747528b9a..82de71a3aea761301a41c9133e9c31c0c7588688
@@@ -31,7 -31,6 +31,7 @@@
  ******************************************************************************/
  
  #include <linux/sched.h>
 +#include <linux/slab.h>
  #include "ipw2200.h"
  
  
@@@ -459,7 -458,7 +459,7 @@@ static u8 _ipw_read_reg8(struct ipw_pri
  {
        u32 word;
        _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK);
-       IPW_DEBUG_IO(" reg = 0x%8X : \n", reg);
+       IPW_DEBUG_IO(" reg = 0x%8X :\n", reg);
        word = _ipw_read32(priv, IPW_INDIRECT_DATA);
        return (word >> ((reg & 0x3) * 8)) & 0xff;
  }
@@@ -473,7 -472,7 +473,7 @@@ static u32 _ipw_read_reg32(struct ipw_p
  
        _ipw_write32(priv, IPW_INDIRECT_ADDR, reg);
        value = _ipw_read32(priv, IPW_INDIRECT_DATA);
-       IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value);
+       IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x\n", reg, value);
        return value;
  }
  
@@@ -2349,16 -2348,25 +2349,25 @@@ static void ipw_bg_adapter_restart(stru
        mutex_unlock(&priv->mutex);
  }
  
- #define IPW_SCAN_CHECK_WATCHDOG (5 * HZ)
+ static void ipw_abort_scan(struct ipw_priv *priv);
+ #define IPW_SCAN_CHECK_WATCHDOG       (5 * HZ)
  
  static void ipw_scan_check(void *data)
  {
        struct ipw_priv *priv = data;
-       if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) {
+       if (priv->status & STATUS_SCAN_ABORTING) {
                IPW_DEBUG_SCAN("Scan completion watchdog resetting "
                               "adapter after (%dms).\n",
                               jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG));
                queue_work(priv->workqueue, &priv->adapter_restart);
+       } else if (priv->status & STATUS_SCANNING) {
+               IPW_DEBUG_SCAN("Scan completion watchdog aborting scan "
+                              "after (%dms).\n",
+                              jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG));
+               ipw_abort_scan(priv);
+               queue_delayed_work(priv->workqueue, &priv->scan_check, HZ);
        }
  }
  
@@@ -2739,7 -2747,7 +2748,7 @@@ static inline void ipw_fw_dma_reset_com
  static int ipw_fw_dma_enable(struct ipw_priv *priv)
  {                             /* start dma engine but no transfers yet */
  
-       IPW_DEBUG_FW(">> : \n");
+       IPW_DEBUG_FW(">> :\n");
  
        /* Start the dma */
        ipw_fw_dma_reset_command_blocks(priv);
        /* Write CB base address */
        ipw_write_reg32(priv, IPW_DMA_I_CB_BASE, IPW_SHARED_SRAM_DMA_CONTROL);
  
-       IPW_DEBUG_FW("<< : \n");
+       IPW_DEBUG_FW("<< :\n");
        return 0;
  }
  
@@@ -2762,7 -2770,7 +2771,7 @@@ static void ipw_fw_dma_abort(struct ipw
        ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control);
        priv->sram_desc.last_cb_index = 0;
  
-       IPW_DEBUG_FW("<< \n");
+       IPW_DEBUG_FW("<<\n");
  }
  
  static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index,
@@@ -2813,29 -2821,29 +2822,29 @@@ static void ipw_fw_dma_dump_command_blo
  
        IPW_DEBUG_FW(">> :\n");
        address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB);
-       IPW_DEBUG_FW_INFO("Current CB is 0x%x \n", address);
+       IPW_DEBUG_FW_INFO("Current CB is 0x%x\n", address);
  
        /* Read the DMA Controlor register */
        register_value = ipw_read_reg32(priv, IPW_DMA_I_DMA_CONTROL);
-       IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x \n", register_value);
+       IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x\n", register_value);
  
        /* Print the CB values */
        cb_fields_address = address;
        register_value = ipw_read_reg32(priv, cb_fields_address);
-       IPW_DEBUG_FW_INFO("Current CB ControlField is 0x%x \n", register_value);
+       IPW_DEBUG_FW_INFO("Current CB Control Field is 0x%x\n", register_value);
  
        cb_fields_address += sizeof(u32);
        register_value = ipw_read_reg32(priv, cb_fields_address);
-       IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x \n", register_value);
+       IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x\n", register_value);
  
        cb_fields_address += sizeof(u32);
        register_value = ipw_read_reg32(priv, cb_fields_address);
-       IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x \n",
+       IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x\n",
                          register_value);
  
        cb_fields_address += sizeof(u32);
        register_value = ipw_read_reg32(priv, cb_fields_address);
-       IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x \n", register_value);
+       IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x\n", register_value);
  
        IPW_DEBUG_FW(">> :\n");
  }
@@@ -2851,7 -2859,7 +2860,7 @@@ static int ipw_fw_dma_command_block_ind
        current_cb_index = (current_cb_address - IPW_SHARED_SRAM_DMA_CONTROL) /
            sizeof(struct command_block);
  
-       IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X \n",
+       IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X\n",
                          current_cb_index, current_cb_address);
  
        IPW_DEBUG_FW(">> :\n");
@@@ -2910,7 -2918,7 +2919,7 @@@ static int ipw_fw_dma_add_buffer(struc
        int ret, i;
        u32 size;
  
-       IPW_DEBUG_FW(">> \n");
+       IPW_DEBUG_FW(">>\n");
        IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n",
                          nr, dest_address, len);
  
                        IPW_DEBUG_FW_INFO(": Added new cb\n");
        }
  
-       IPW_DEBUG_FW("<< \n");
+       IPW_DEBUG_FW("<<\n");
        return 0;
  }
  
@@@ -2936,7 -2944,7 +2945,7 @@@ static int ipw_fw_dma_wait(struct ipw_p
        u32 current_index = 0, previous_index;
        u32 watchdog = 0;
  
-       IPW_DEBUG_FW(">> : \n");
+       IPW_DEBUG_FW(">> :\n");
  
        current_index = ipw_fw_dma_command_block_index(priv);
        IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n",
        ipw_set_bit(priv, IPW_RESET_REG,
                    IPW_RESET_REG_MASTER_DISABLED | IPW_RESET_REG_STOP_MASTER);
  
-       IPW_DEBUG_FW("<< dmaWaitSync \n");
+       IPW_DEBUG_FW("<< dmaWaitSync\n");
        return 0;
  }
  
@@@ -3026,7 -3034,7 +3035,7 @@@ static int ipw_stop_master(struct ipw_p
  {
        int rc;
  
-       IPW_DEBUG_TRACE(">> \n");
+       IPW_DEBUG_TRACE(">>\n");
        /* stop master. typical delay - 0 */
        ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER);
  
  
  static void ipw_arc_release(struct ipw_priv *priv)
  {
-       IPW_DEBUG_TRACE(">> \n");
+       IPW_DEBUG_TRACE(">>\n");
        mdelay(5);
  
        ipw_clear_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET);
@@@ -3067,7 -3075,7 +3076,7 @@@ static int ipw_load_ucode(struct ipw_pr
  
        image = (__le16 *) data;
  
-       IPW_DEBUG_TRACE(">> \n");
+       IPW_DEBUG_TRACE(">>\n");
  
        rc = ipw_stop_master(priv);
  
@@@ -3181,7 -3189,7 +3190,7 @@@ static int ipw_load_firmware(struct ipw
        void **virts;
        dma_addr_t *phys;
  
-       IPW_DEBUG_TRACE("<< : \n");
+       IPW_DEBUG_TRACE("<< :\n");
  
        virts = kmalloc(sizeof(void *) * CB_NUMBER_OF_ELEMENTS_SMALL,
                        GFP_KERNEL);
@@@ -4482,7 -4490,7 +4491,7 @@@ static void ipw_rx_notification(struct 
                        case CMAS_ASSOCIATED:{
                                        IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
                                                  IPW_DL_ASSOC,
-                                                 "associated: '%s' %pM \n",
+                                                 "associated: '%s' %pM\n",
                                                  print_ssid(ssid, priv->essid,
                                                             priv->essid_len),
                                                  priv->bssid);
                                                          IPW_DL_ASSOC,
                                                          "deauthenticated: '%s' "
                                                          "%pM"
-                                                         ": (0x%04X) - %s \n",
+                                                         ": (0x%04X) - %s\n",
                                                          print_ssid(ssid,
                                                                     priv->
                                                                     essid,
  
                                        IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
                                                  IPW_DL_ASSOC,
-                                                 "disassociated: '%s' %pM \n",
+                                                 "disassociated: '%s' %pM\n",
                                                  print_ssid(ssid, priv->essid,
                                                             priv->essid_len),
                                                  priv->bssid);
                        switch (auth->state) {
                        case CMAS_AUTHENTICATED:
                                IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
-                                         "authenticated: '%s' %pM \n",
+                                         "authenticated: '%s' %pM\n",
                                          print_ssid(ssid, priv->essid,
                                                     priv->essid_len),
                                          priv->bssid);
@@@ -6925,7 -6933,7 +6934,7 @@@ static u8 ipw_qos_current_mode(struct i
        } else {
                mode = priv->ieee->mode;
        }
-       IPW_DEBUG_QOS("QoS network/card mode %d \n", mode);
+       IPW_DEBUG_QOS("QoS network/card mode %d\n", mode);
        return mode;
  }
  
@@@ -6965,7 -6973,7 +6974,7 @@@ static int ipw_qos_handle_probe_respons
                               &def_parameters_OFDM, size);
  
                if ((network->qos_data.active == 1) && (active_network == 1)) {
-                       IPW_DEBUG_QOS("QoS was disabled call qos_activate \n");
+                       IPW_DEBUG_QOS("QoS was disabled call qos_activate\n");
                        schedule_work(&priv->qos_activate);
                }
  
@@@ -7542,7 -7550,7 +7551,7 @@@ static int ipw_associate_network(struc
                return err;
        }
  
-       IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM \n",
+       IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM\n",
                  print_ssid(ssid, priv->essid, priv->essid_len),
                  priv->bssid);
  
@@@ -8793,7 -8801,7 +8802,7 @@@ static int ipw_wx_set_freq(struct net_d
                }
        }
  
-       IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
+       IPW_DEBUG_WX("SET Freq/Channel -> %d\n", fwrq->m);
        mutex_lock(&priv->mutex);
        ret = ipw_set_channel(priv, channel);
        mutex_unlock(&priv->mutex);
@@@ -8835,7 -8843,7 +8844,7 @@@ static int ipw_wx_get_freq(struct net_d
                wrqu->freq.m = 0;
  
        mutex_unlock(&priv->mutex);
-       IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel);
+       IPW_DEBUG_WX("GET Freq/Channel -> %d\n", priv->channel);
        return 0;
  }
  
@@@ -9230,7 -9238,7 +9239,7 @@@ static int ipw_wx_get_sens(struct net_d
        wrqu->sens.value = priv->roaming_threshold;
        mutex_unlock(&priv->mutex);
  
-       IPW_DEBUG_WX("GET roaming threshold -> %s %d \n",
+       IPW_DEBUG_WX("GET roaming threshold -> %s %d\n",
                     wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value);
  
        return 0;
@@@ -9358,7 -9366,7 +9367,7 @@@ static int ipw_wx_get_rate(struct net_d
        wrqu->bitrate.value = priv->last_rate;
        wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0;
        mutex_unlock(&priv->mutex);
-       IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
+       IPW_DEBUG_WX("GET Rate -> %d\n", wrqu->bitrate.value);
        return 0;
  }
  
@@@ -9381,7 -9389,7 +9390,7 @@@ static int ipw_wx_set_rts(struct net_de
  
        ipw_send_rts_threshold(priv, priv->rts_threshold);
        mutex_unlock(&priv->mutex);
-       IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold);
+       IPW_DEBUG_WX("SET RTS Threshold -> %d\n", priv->rts_threshold);
        return 0;
  }
  
@@@ -9395,7 -9403,7 +9404,7 @@@ static int ipw_wx_get_rts(struct net_de
        wrqu->rts.fixed = 0;    /* no auto select */
        wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
        mutex_unlock(&priv->mutex);
-       IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value);
+       IPW_DEBUG_WX("GET RTS Threshold -> %d\n", wrqu->rts.value);
        return 0;
  }
  
@@@ -9445,7 -9453,7 +9454,7 @@@ static int ipw_wx_get_txpow(struct net_
        wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0;
        mutex_unlock(&priv->mutex);
  
-       IPW_DEBUG_WX("GET TX Power -> %s %d \n",
+       IPW_DEBUG_WX("GET TX Power -> %s %d\n",
                     wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value);
  
        return 0;
@@@ -9471,7 -9479,7 +9480,7 @@@ static int ipw_wx_set_frag(struct net_d
  
        ipw_send_frag_threshold(priv, wrqu->frag.value);
        mutex_unlock(&priv->mutex);
-       IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value);
+       IPW_DEBUG_WX("SET Frag Threshold -> %d\n", wrqu->frag.value);
        return 0;
  }
  
@@@ -9485,7 -9493,7 +9494,7 @@@ static int ipw_wx_get_frag(struct net_d
        wrqu->frag.fixed = 0;   /* no auto select */
        wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS);
        mutex_unlock(&priv->mutex);
-       IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value);
+       IPW_DEBUG_WX("GET Frag Threshold -> %d\n", wrqu->frag.value);
  
        return 0;
  }
@@@ -9549,7 -9557,7 +9558,7 @@@ static int ipw_wx_get_retry(struct net_
        }
        mutex_unlock(&priv->mutex);
  
-       IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value);
+       IPW_DEBUG_WX("GET retry -> %d\n", wrqu->retry.value);
  
        return 0;
  }
index 8f85a0db5c394f5135782fa69a25d5249d1b9199,80e9bbc7884ae56d9d506aa861dcac4a93986872..32eb4709acac4f6ee407c35ead9483e56a98082f
@@@ -27,7 -27,6 +27,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>
  
@@@ -342,7 -341,7 +342,7 @@@ void iwl3945_rs_rate_init(struct iwl_pr
        struct ieee80211_supported_band *sband;
        int i;
  
-       IWL_DEBUG_INFO(priv, "enter \n");
+       IWL_DEBUG_INFO(priv, "enter\n");
        if (sta_id == priv->hw_params.bcast_sta_id)
                goto out;
  
@@@ -648,7 -647,7 +648,7 @@@ static void rs_get_rate(void *priv_r, s
        unsigned long flags;
        u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0;
        s8 max_rate_idx = -1;
-       struct iwl_priv *priv = (struct iwl_priv *)priv_r;
+       struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  
        IWL_DEBUG_RATE(priv, "enter\n");
index 7ac6cec006d05027eed24f3c160f91a8b4262695,15de649888d828fec874c61d9730a3870f02cdf7..bde3b4cbab9d6519d76d287e62cffb53616449b9
@@@ -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>
@@@ -192,12 -191,12 +192,12 @@@ static int iwl3945_hwrate_to_plcp_idx(u
  }
  
  #ifdef CONFIG_IWLWIFI_DEBUG
- #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
+ #define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x
  
  static const char *iwl3945_get_tx_fail_reason(u32 status)
  {
        switch (status & TX_STATUS_MSK) {
-       case TX_STATUS_SUCCESS:
+       case TX_3945_STATUS_SUCCESS:
                return "SUCCESS";
                TX_STATUS_ENTRY(SHORT_LIMIT);
                TX_STATUS_ENTRY(LONG_LIMIT);
@@@ -487,7 -486,7 +487,7 @@@ static void _iwl3945_dbg_report_frame(s
                 *    but you can hack it to show more, if you'd like to. */
                if (dataframe)
                        IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, "
-                                    "len=%u, rssi=%d, chnl=%d, rate=%d, \n",
+                                    "len=%u, rssi=%d, chnl=%d, rate=%d,\n",
                                     title, le16_to_cpu(fc), header->addr1[5],
                                     length, rssi, channel, rate);
                else {
@@@ -549,7 -548,6 +549,6 @@@ static void iwl3945_pass_packet_to_mac8
        struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
        u16 len = le16_to_cpu(rx_hdr->len);
        struct sk_buff *skb;
-       int ret;
        __le16 fc = hdr->frame_control;
  
        /* We received data from the HW, so stop the watchdog */
                return;
        }
  
-       skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC);
+       skb = dev_alloc_skb(128);
        if (!skb) {
-               IWL_ERR(priv, "alloc_skb failed\n");
+               IWL_ERR(priv, "dev_alloc_skb failed\n");
                return;
        }
  
                                       (struct ieee80211_hdr *)rxb_addr(rxb),
                                       le32_to_cpu(rx_end->status), stats);
  
-       skb_reserve(skb, IWL_LINK_HDR_MAX);
        skb_add_rx_frag(skb, 0, rxb->page,
                        (void *)rx_hdr->payload - (void *)pkt, len);
  
-       /* mac80211 currently doesn't support paged SKB. Convert it to
-        * linear SKB for management frame and data frame requires
-        * software decryption or software defragementation. */
-       if (ieee80211_is_mgmt(fc) ||
-           ieee80211_has_protected(fc) ||
-           ieee80211_has_morefrags(fc) ||
-           le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
-               ret = skb_linearize(skb);
-       else
-               ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
-                       0 : -ENOMEM;
-       if (ret) {
-               kfree_skb(skb);
-               goto out;
-       }
-       /*
-        * XXX: We cannot touch the page and its virtual memory (pkt) after
-        * here. It might have already been freed by the above skb change.
-        */
        iwl_update_stats(priv, false, fc, len);
        memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
  
        ieee80211_rx(priv->hw, skb);
-  out:
        priv->alloc_rxb_page--;
        rxb->page = NULL;
  }
@@@ -623,9 -597,8 +598,8 @@@ static void iwl3945_rx_reply_rx(struct 
        struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
        struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
        struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-       int snr;
-       u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg);
-       u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff);
+       u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg);
+       u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff);
        u8 network_packet;
  
        rx_status.flag = 0;
        /* Convert 3945's rssi indicator to dBm */
        rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET;
  
-       /* Set default noise value to -127 */
-       if (priv->last_rx_noise == 0)
-               priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-       /* 3945 provides noise info for OFDM frames only.
-        * sig_avg and noise_diff are measured by the 3945's digital signal
-        *   processor (DSP), and indicate linear levels of signal level and
-        *   distortion/noise within the packet preamble after
-        *   automatic gain control (AGC).  sig_avg should stay fairly
-        *   constant if the radio's AGC is working well.
-        * Since these values are linear (not dB or dBm), linear
-        *   signal-to-noise ratio (SNR) is (sig_avg / noise_diff).
-        * Convert linear SNR to dB SNR, then subtract that from rssi dBm
-        *   to obtain noise level in dBm.
-        * Calculate rx_status.signal (quality indicator in %) based on SNR. */
-       if (rx_stats_noise_diff) {
-               snr = rx_stats_sig_avg / rx_stats_noise_diff;
-               rx_status.noise = rx_status.signal -
-                                       iwl3945_calc_db_from_ratio(snr);
-       } else {
-               rx_status.noise = priv->last_rx_noise;
-       }
-       IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n",
-                       rx_status.signal, rx_status.noise,
-                       rx_stats_sig_avg, rx_stats_noise_diff);
+       IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n",
+                       rx_status.signal, rx_stats_sig_avg,
+                       rx_stats_noise_diff);
  
        header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
  
        network_packet = iwl3945_is_network_packet(priv, header);
  
-       IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n",
+       IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n",
                              network_packet ? '*' : ' ',
                              le16_to_cpu(rx_hdr->channel),
                              rx_status.signal, rx_status.signal,
-                             rx_status.noise, rx_status.rate_idx);
+                             rx_status.rate_idx);
  
        /* Set "1" to report good data frames in groups of 100 */
        iwl3945_dbg_report_frame(priv, pkt, header, 1);
                        le32_to_cpu(rx_end->beacon_timestamp);
                priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
                priv->_3945.last_rx_rssi = rx_status.signal;
-               priv->last_rx_noise = rx_status.noise;
        }
  
        iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
@@@ -1050,7 -998,7 +999,7 @@@ static void iwl3945_nic_config(struct i
        IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
  
        if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
-               IWL_DEBUG_INFO(priv, "RTP type \n");
+               IWL_DEBUG_INFO(priv, "RTP type\n");
        else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
                IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n");
                iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
@@@ -2822,6 -2770,7 +2771,7 @@@ static struct iwl_cfg iwl3945_bg_cfg = 
        .broken_powersave = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .max_event_log_size = 512,
  };
  
  static struct iwl_cfg iwl3945_abg_cfg = {
        .broken_powersave = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .max_event_log_size = 512,
  };
  
  DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
index 0de80914be7771a5580c6836ed5b47ed3a8ebc97,3c1cd417bbc520765cd5b7be2f3b4f1070401413..f7d85a2173c8cdda6433eb470e965b81ef2f760b
@@@ -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>
  
@@@ -2003,7 -2002,7 +2003,7 @@@ static void rs_rate_scale_perform(struc
        /* rates available for this association, and for modulation mode */
        rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type);
  
-       IWL_DEBUG_RATE(priv, "mask 0x%04X \n", rate_mask);
+       IWL_DEBUG_RATE(priv, "mask 0x%04X\n", rate_mask);
  
        /* mask with station rate restriction */
        if (is_legacy(tbl->lq_type)) {
@@@ -2410,7 -2409,7 +2410,7 @@@ static void rs_get_rate(void *priv_r, s
  
        struct sk_buff *skb = txrc->skb;
        struct ieee80211_supported_band *sband = txrc->sband;
-       struct iwl_priv *priv = (struct iwl_priv *)priv_r;
+       struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct iwl_lq_sta *lq_sta = priv_sta;
        int rate_idx;
@@@ -2934,8 -2933,6 +2934,6 @@@ static ssize_t rs_sta_dbgfs_rate_scale_
                desc += sprintf(buff+desc,
                                "Bit Rate= %d Mb/s\n",
                                iwl_rates[lq_sta->last_txrate_idx].ieee >> 1);
-       desc += sprintf(buff+desc, "Noise Level= %d dBm\n",
-                       priv->last_rx_noise);
  
        ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
        return ret;
index fe4cec61bdecabd33c0915609ce2f643ca2bfcf7,8a002c6f3a6171331ca07bf72c680d0059a60310..0b497d4bc659e0036e485db9e896490ff4fed9c8
@@@ -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>
@@@ -84,13 -83,6 +84,6 @@@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUT
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("iwl4965");
  
- /*************** STATION TABLE MANAGEMENT ****
-  * mac80211 should be examined to determine if sta_info is duplicating
-  * the functionality provided here
-  */
- /**************************************************************/
  /**
   * iwl_commit_rxon - commit staging_rxon to hardware
   *
@@@ -166,6 -158,11 +159,11 @@@ int iwl_commit_rxon(struct iwl_priv *pr
                }
                iwl_clear_ucode_stations(priv, false);
                iwl_restore_stations(priv);
+               ret = iwl_restore_default_wep_keys(priv);
+               if (ret) {
+                       IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+                       return ret;
+               }
        }
  
        IWL_DEBUG_INFO(priv, "Sending RXON\n"
                        IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
                        return ret;
                }
-               IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON. \n");
+               IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
                memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
                iwl_clear_ucode_stations(priv, false);
                iwl_restore_stations(priv);
+               ret = iwl_restore_default_wep_keys(priv);
+               if (ret) {
+                       IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+                       return ret;
+               }
        }
  
        priv->start_calib = 0;
@@@ -885,10 -887,10 +888,10 @@@ static void iwl_setup_rx_handlers(struc
        priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
            iwl_rx_missed_beacon_notif;
        /* Rx handlers */
-       priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy;
-       priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx;
+       priv->rx_handlers[REPLY_RX_PHY_CMD] = iwlagn_rx_reply_rx_phy;
+       priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwlagn_rx_reply_rx;
        /* block ack */
-       priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba;
+       priv->rx_handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba;
        /* Set up hardware specific Rx handlers */
        priv->cfg->ops->lib->rx_handler_setup(priv);
  }
@@@ -1016,7 -1018,7 +1019,7 @@@ void iwl_rx_handle(struct iwl_priv *pri
                        count++;
                        if (count >= 8) {
                                rxq->read = i;
-                               iwl_rx_replenish_now(priv);
+                               iwlagn_rx_replenish_now(priv);
                                count = 0;
                        }
                }
        /* Backtrack one entry */
        rxq->read = i;
        if (fill_rx)
-               iwl_rx_replenish_now(priv);
+               iwlagn_rx_replenish_now(priv);
        else
-               iwl_rx_queue_restock(priv);
+               iwlagn_rx_queue_restock(priv);
  }
  
  /* call this function to flush any scheduled tasklet */
@@@ -1426,6 -1428,60 +1429,60 @@@ static void iwl_irq_tasklet(struct iwl_
                iwl_enable_interrupts(priv);
  }
  
+ /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
+ #define ACK_CNT_RATIO (50)
+ #define BA_TIMEOUT_CNT (5)
+ #define BA_TIMEOUT_MAX (16)
+ /**
+  * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries.
+  *
+  * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding
+  * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
+  * operation state.
+  */
+ bool iwl_good_ack_health(struct iwl_priv *priv,
+                               struct iwl_rx_packet *pkt)
+ {
+       bool rc = true;
+       int actual_ack_cnt_delta, expected_ack_cnt_delta;
+       int ba_timeout_delta;
+       actual_ack_cnt_delta =
+               le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
+               le32_to_cpu(priv->statistics.tx.actual_ack_cnt);
+       expected_ack_cnt_delta =
+               le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) -
+               le32_to_cpu(priv->statistics.tx.expected_ack_cnt);
+       ba_timeout_delta =
+               le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) -
+               le32_to_cpu(priv->statistics.tx.agg.ba_timeout);
+       if ((priv->_agn.agg_tids_count > 0) &&
+           (expected_ack_cnt_delta > 0) &&
+           (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta)
+               < ACK_CNT_RATIO) &&
+           (ba_timeout_delta > BA_TIMEOUT_CNT)) {
+               IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d,"
+                               " expected_ack_cnt = %d\n",
+                               actual_ack_cnt_delta, expected_ack_cnt_delta);
+ #ifdef CONFIG_IWLWIFI_DEBUG
+               IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
+                               priv->delta_statistics.tx.rx_detected_cnt);
+               IWL_DEBUG_RADIO(priv,
+                               "ack_or_ba_timeout_collision delta = %d\n",
+                               priv->delta_statistics.tx.
+                               ack_or_ba_timeout_collision);
+ #endif
+               IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
+                               ba_timeout_delta);
+               if (!actual_ack_cnt_delta &&
+                   (ba_timeout_delta >= BA_TIMEOUT_MAX))
+                       rc = false;
+       }
+       return rc;
+ }
  
  /******************************************************************************
   *
@@@ -1787,6 -1843,7 +1844,7 @@@ void iwl_dump_nic_error_log(struct iwl_
        u32 data2, line;
        u32 desc, time, count, base, data1;
        u32 blink1, blink2, ilink1, ilink2;
+       u32 pc, hcmd;
  
        if (priv->ucode_type == UCODE_INIT)
                base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
        }
  
        desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
+       pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32));
        blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
        blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
        ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
        data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
        line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
        time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
+       hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32));
  
        trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line,
                                      blink1, blink2, ilink1, ilink2);
                "data1      data2      line\n");
        IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
                desc_lookup(desc), desc, time, data1, data2, line);
-       IWL_ERR(priv, "blink1  blink2  ilink1  ilink2\n");
-       IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
-               ilink1, ilink2);
+       IWL_ERR(priv, "pc      blink1  blink2  ilink1  ilink2  hcmd\n");
+       IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n",
+               pc, blink1, blink2, ilink1, ilink2, hcmd);
  }
  
  #define EVENT_START_OFFSET  (4 * sizeof(u32))
@@@ -1944,9 -2002,6 +2003,6 @@@ static int iwl_print_last_event_logs(st
        return pos;
  }
  
- /* For sanity check only.  Actual size is determined by uCode, typ. 512 */
- #define MAX_EVENT_LOG_SIZE (512)
  #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
  
  int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
        num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
        next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
  
-       if (capacity > MAX_EVENT_LOG_SIZE) {
+       if (capacity > priv->cfg->max_event_log_size) {
                IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
-                       capacity, MAX_EVENT_LOG_SIZE);
-               capacity = MAX_EVENT_LOG_SIZE;
+                       capacity, priv->cfg->max_event_log_size);
+               capacity = priv->cfg->max_event_log_size;
        }
  
-       if (next_entry > MAX_EVENT_LOG_SIZE) {
+       if (next_entry > priv->cfg->max_event_log_size) {
                IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
-                       next_entry, MAX_EVENT_LOG_SIZE);
-               next_entry = MAX_EVENT_LOG_SIZE;
+                       next_entry, priv->cfg->max_event_log_size);
+               next_entry = priv->cfg->max_event_log_size;
        }
  
        size = num_wraps ? capacity : next_entry;
@@@ -2204,8 -2259,8 +2260,8 @@@ static void __iwl_down(struct iwl_priv 
        /* device going down, Stop using ICT table */
        iwl_disable_ict(priv);
  
-       iwl_txq_ctx_stop(priv);
-       iwl_rxq_stop(priv);
+       iwlagn_txq_ctx_stop(priv);
+       iwlagn_rxq_stop(priv);
  
        /* Power-down device's busmaster DMA clocks */
        iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
@@@ -2265,7 -2320,7 +2321,7 @@@ static int iwl_prepare_card_hw(struct i
  {
        int ret = 0;
  
-       IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter \n");
+       IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n");
  
        ret = iwl_set_hw_ready(priv);
        if (priv->hw_ready)
@@@ -2326,7 -2381,7 +2382,7 @@@ static int __iwl_up(struct iwl_priv *pr
  
        iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
  
-       ret = iwl_hw_nic_init(priv);
+       ret = iwlagn_hw_nic_init(priv);
        if (ret) {
                IWL_ERR(priv, "Unable to init nic\n");
                return ret;
@@@ -2476,7 -2531,7 +2532,7 @@@ static void iwl_bg_rx_replenish(struct 
                return;
  
        mutex_lock(&priv->mutex);
-       iwl_rx_replenish(priv);
+       iwlagn_rx_replenish(priv);
        mutex_unlock(&priv->mutex);
  }
  
@@@ -2486,7 -2541,6 +2542,6 @@@ void iwl_post_associate(struct iwl_pri
  {
        struct ieee80211_conf *conf = NULL;
        int ret = 0;
-       unsigned long flags;
  
        if (priv->iw_mode == NL80211_IFTYPE_AP) {
                IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
                break;
        }
  
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_activate_qos(priv, 0);
-       spin_unlock_irqrestore(&priv->lock, flags);
        /* the chain noise calibration will enabled PM upon completion
         * If chain noise has already been run, then we need to enable
         * power management here */
@@@ -2737,7 -2787,7 +2788,7 @@@ static int iwl_mac_tx(struct ieee80211_
        IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
                     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
  
-       if (iwl_tx_skb(priv, skb))
+       if (iwlagn_tx_skb(priv, skb))
                dev_kfree_skb_any(skb);
  
        IWL_DEBUG_MACDUMP(priv, "leave\n");
  void iwl_config_ap(struct iwl_priv *priv)
  {
        int ret = 0;
-       unsigned long flags;
  
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
                /* restore RXON assoc */
                priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
                iwlcore_commit_rxon(priv);
-               iwl_reset_qos(priv);
-               spin_lock_irqsave(&priv->lock, flags);
-               iwl_activate_qos(priv, 1);
-               spin_unlock_irqrestore(&priv->lock, flags);
                iwl_add_bcast_station(priv);
        }
        iwl_send_beacon_cmd(priv);
@@@ -2858,12 -2903,13 +2904,13 @@@ static int iwl_mac_set_key(struct ieee8
        mutex_lock(&priv->mutex);
        iwl_scan_cancel_timeout(priv, 100);
  
-       /* If we are getting WEP group key and we didn't receive any key mapping
+       /*
+        * If we are getting WEP group key and we didn't receive any key mapping
         * so far, we are in legacy wep mode (group key only), otherwise we are
         * in 1X mode.
-        * In legacy wep mode, we use another host command to the uCode */
-       if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id &&
-               priv->iw_mode != NL80211_IFTYPE_AP) {
+        * In legacy wep mode, we use another host command to the uCode.
+        */
+       if (key->alg == ALG_WEP && !sta && vif->type != NL80211_IFTYPE_AP) {
                if (cmd == SET_KEY)
                        is_default_wep_key = !priv->key_mapping_key;
                else
@@@ -2925,7 -2971,7 +2972,7 @@@ static int iwl_mac_ampdu_action(struct 
                        return ret;
        case IEEE80211_AMPDU_TX_START:
                IWL_DEBUG_HT(priv, "start Tx\n");
-               ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn);
+               ret = iwlagn_tx_agg_start(priv, sta->addr, tid, ssn);
                if (ret == 0) {
                        priv->_agn.agg_tids_count++;
                        IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
                return ret;
        case IEEE80211_AMPDU_TX_STOP:
                IWL_DEBUG_HT(priv, "stop Tx\n");
-               ret = iwl_tx_agg_stop(priv, sta->addr, tid);
+               ret = iwlagn_tx_agg_stop(priv, sta->addr, tid);
                if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) {
                        priv->_agn.agg_tids_count--;
                        IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
@@@ -2997,19 -3043,6 +3044,6 @@@ static void iwl_mac_sta_notify(struct i
        }
  }
  
- /**
-  * iwl_restore_wepkeys - Restore WEP keys to device
-  */
- static void iwl_restore_wepkeys(struct iwl_priv *priv)
- {
-       mutex_lock(&priv->mutex);
-       if (priv->iw_mode == NL80211_IFTYPE_STATION &&
-           priv->default_wep_key &&
-           iwl_send_static_wepkey_cmd(priv, 0))
-               IWL_ERR(priv, "Could not send WEP static key\n");
-       mutex_unlock(&priv->mutex);
- }
  static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
                              struct ieee80211_vif *vif,
                              struct ieee80211_sta *sta)
                return ret;
        }
  
-       iwl_restore_wepkeys(priv);
        /* Initialize rate scaling */
-       IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM \n",
+       IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
                       sta->addr);
        iwl_rs_rate_init(priv, sta, sta_id);
  
@@@ -3337,15 -3368,10 +3369,10 @@@ static int iwl_init_drv(struct iwl_pri
  
        iwl_init_scan_params(priv);
  
-       iwl_reset_qos(priv);
-       priv->qos_data.qos_active = 0;
-       priv->qos_data.qos_cap.val = 0;
        /* Set the tx_power_user_lmt to the lowest power level
         * this value will get overwritten by channel max power avg
         * from eeprom */
-       priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN;
+       priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN;
  
        ret = iwl_init_channel_map(priv);
        if (ret) {
@@@ -3692,8 -3718,8 +3719,8 @@@ static void __devexit iwl_pci_remove(st
        iwl_dealloc_ucode_pci(priv);
  
        if (priv->rxq.bd)
-               iwl_rx_queue_free(priv, &priv->rxq);
-       iwl_hw_txq_ctx_free(priv);
+               iwlagn_rx_queue_free(priv, &priv->rxq);
+       iwlagn_hw_txq_ctx_free(priv);
  
        iwl_eeprom_free(priv);
  
@@@ -3808,6 -3834,7 +3835,7 @@@ 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)},
  
  /* 6x50 WiFi/WiMax Series */
        {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
@@@ -3890,3 -3917,33 +3918,33 @@@ module_param_named(debug, iwl_debug_lev
  MODULE_PARM_DESC(debug, "debug output mask");
  #endif
  
+ module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO);
+ MODULE_PARM_DESC(swcrypto50,
+                "using crypto in software (default 0 [hardware]) (deprecated)");
+ module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO);
+ MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
+ module_param_named(queues_num50,
+                  iwlagn_mod_params.num_of_queues, int, S_IRUGO);
+ MODULE_PARM_DESC(queues_num50,
+                "number of hw queues in 50xx series (deprecated)");
+ module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO);
+ MODULE_PARM_DESC(queues_num, "number of hw queues.");
+ module_param_named(11n_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO);
+ MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality (deprecated)");
+ module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO);
+ MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
+ module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K,
+                  int, S_IRUGO);
+ MODULE_PARM_DESC(amsdu_size_8K50,
+                "enable 8K amsdu size in 50XX series (deprecated)");
+ module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K,
+                  int, S_IRUGO);
+ MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
+ module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO);
+ MODULE_PARM_DESC(fw_restart50,
+                "restart firmware in case of error (deprecated)");
+ module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO);
+ MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
+ module_param_named(
+       disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO);
+ MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
index de3b3f403d1f2cfe68db5a4a6f0182366fdc633a,dbb50a8e0ce3adcc9c42ad49134b24ef58adff4d..0471c3f8713ec9a79629a288cd73f9519ca6c4a1
@@@ -60,7 -60,6 +60,7 @@@
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *****************************************************************************/
  
 +#include <linux/slab.h>
  #include <net/mac80211.h>
  
  #include "iwl-dev.h"
@@@ -593,7 -592,7 +593,7 @@@ void iwl_sensitivity_calibration(struc
        IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
  
        if (!rx_enable_time) {
-               IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0! \n");
+               IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n");
                return;
        }
  
index 0ee8cc296e4850f7da95741d76910e0be8485272,f09bff823ab6fff804e1b7c2536e3b6c7134b4f0..2a89747d3473af15ee89573491ba3783bebbbc73
@@@ -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"
@@@ -66,7 -65,7 +66,7 @@@ MODULE_LICENSE("GPL")
   */
  static bool bt_coex_active = true;
  module_param(bt_coex_active, bool, S_IRUGO);
- MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist\n");
+ MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
  
  static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
        {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
@@@ -141,30 -140,6 +141,6 @@@ const struct iwl_rate_info iwl_rates[IW
  };
  EXPORT_SYMBOL(iwl_rates);
  
- /**
-  * translate ucode response to mac80211 tx status control values
-  */
- void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
-                                 struct ieee80211_tx_info *info)
- {
-       struct ieee80211_tx_rate *r = &info->control.rates[0];
-       info->antenna_sel_tx =
-               ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
-       if (rate_n_flags & RATE_MCS_HT_MSK)
-               r->flags |= IEEE80211_TX_RC_MCS;
-       if (rate_n_flags & RATE_MCS_GF_MSK)
-               r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
-       if (rate_n_flags & RATE_MCS_HT40_MSK)
-               r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
-       if (rate_n_flags & RATE_MCS_DUP_MSK)
-               r->flags |= IEEE80211_TX_RC_DUP_DATA;
-       if (rate_n_flags & RATE_MCS_SGI_MSK)
-               r->flags |= IEEE80211_TX_RC_SHORT_GI;
-       r->idx = iwl_hwrate_to_mac80211_idx(rate_n_flags, info->band);
- }
- EXPORT_SYMBOL(iwl_hwrate_to_tx_control);
  int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
  {
        int idx = 0;
  }
  EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
  
- int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
- {
-       int idx = 0;
-       int band_offset = 0;
-       /* HT rate format: mac80211 wants an MCS number, which is just LSB */
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
-               idx = (rate_n_flags & 0xff);
-               return idx;
-       /* Legacy rate format, search for match in table */
-       } else {
-               if (band == IEEE80211_BAND_5GHZ)
-                       band_offset = IWL_FIRST_OFDM_RATE;
-               for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
-                       if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
-                               return idx - band_offset;
-       }
-       return -1;
- }
  u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant)
  {
        int i;
@@@ -266,74 -220,16 +221,16 @@@ void iwl_hw_detect(struct iwl_priv *pri
  }
  EXPORT_SYMBOL(iwl_hw_detect);
  
- int iwl_hw_nic_init(struct iwl_priv *priv)
- {
-       unsigned long flags;
-       struct iwl_rx_queue *rxq = &priv->rxq;
-       int ret;
-       /* nic_init */
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->cfg->ops->lib->apm_ops.init(priv);
-       /* Set interrupt coalescing calibration timer to default (512 usecs) */
-       iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
-       priv->cfg->ops->lib->apm_ops.config(priv);
-       /* Allocate the RX queue, or reset if it is already allocated */
-       if (!rxq->bd) {
-               ret = iwl_rx_queue_alloc(priv);
-               if (ret) {
-                       IWL_ERR(priv, "Unable to initialize Rx queue\n");
-                       return -ENOMEM;
-               }
-       } else
-               iwl_rx_queue_reset(priv, rxq);
-       iwl_rx_replenish(priv);
-       iwl_rx_init(priv, rxq);
-       spin_lock_irqsave(&priv->lock, flags);
-       rxq->need_update = 1;
-       iwl_rx_queue_update_write_ptr(priv, rxq);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       /* Allocate or reset and init all Tx and Command queues */
-       if (!priv->txq) {
-               ret = iwl_txq_ctx_alloc(priv);
-               if (ret)
-                       return ret;
-       } else
-               iwl_txq_ctx_reset(priv);
-       set_bit(STATUS_INIT, &priv->status);
-       return 0;
- }
- EXPORT_SYMBOL(iwl_hw_nic_init);
  /*
   * QoS  support
  */
void iwl_activate_qos(struct iwl_priv *priv, u8 force)
static void iwl_update_qos(struct iwl_priv *priv)
  {
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
  
        priv->qos_data.def_qos_parm.qos_flags = 0;
  
-       if (priv->qos_data.qos_cap.q_AP.queue_request &&
-           !priv->qos_data.qos_cap.q_AP.txop_request)
-               priv->qos_data.def_qos_parm.qos_flags |=
-                       QOS_PARAM_FLG_TXOP_TYPE_MSK;
        if (priv->qos_data.qos_active)
                priv->qos_data.def_qos_parm.qos_flags |=
                        QOS_PARAM_FLG_UPDATE_EDCA_MSK;
        if (priv->current_ht_config.is_ht)
                priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
  
-       if (force || iwl_is_associated(priv)) {
-               IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
-                               priv->qos_data.qos_active,
-                               priv->qos_data.def_qos_parm.qos_flags);
+       IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+                     priv->qos_data.qos_active,
+                     priv->qos_data.def_qos_parm.qos_flags);
  
-               iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
-                                      sizeof(struct iwl_qosparam_cmd),
-                                      &priv->qos_data.def_qos_parm, NULL);
-       }
+       iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
+                              sizeof(struct iwl_qosparam_cmd),
+                              &priv->qos_data.def_qos_parm, NULL);
  }
- EXPORT_SYMBOL(iwl_activate_qos);
- /*
-  * AC        CWmin         CW max      AIFSN      TXOP Limit    TXOP Limit
-  *                                              (802.11b)      (802.11a/g)
-  * AC_BK      15            1023        7           0               0
-  * AC_BE      15            1023        3           0               0
-  * AC_VI       7              15        2          6.016ms       3.008ms
-  * AC_VO       3               7        2          3.264ms       1.504ms
-  */
- void iwl_reset_qos(struct iwl_priv *priv)
- {
-       u16 cw_min = 15;
-       u16 cw_max = 1023;
-       u8 aifs = 2;
-       bool is_legacy = false;
-       unsigned long flags;
-       int i;
-       spin_lock_irqsave(&priv->lock, flags);
-       /* QoS always active in AP and ADHOC mode
-        * In STA mode wait for association
-        */
-       if (priv->iw_mode == NL80211_IFTYPE_ADHOC ||
-           priv->iw_mode == NL80211_IFTYPE_AP)
-               priv->qos_data.qos_active = 1;
-       else
-               priv->qos_data.qos_active = 0;
-       /* check for legacy mode */
-       if ((priv->iw_mode == NL80211_IFTYPE_ADHOC &&
-           (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) ||
-           (priv->iw_mode == NL80211_IFTYPE_STATION &&
-           (priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) {
-               cw_min = 31;
-               is_legacy = 1;
-       }
-       if (priv->qos_data.qos_active)
-               aifs = 3;
-       /* AC_BE */
-       priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
-       priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
-       priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
-       priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
-       priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
-       if (priv->qos_data.qos_active) {
-               /* AC_BK */
-               i = 1;
-               priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
-               priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
-               priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
-               priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
-               priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-               /* AC_VI */
-               i = 2;
-               priv->qos_data.def_qos_parm.ac[i].cw_min =
-                       cpu_to_le16((cw_min + 1) / 2 - 1);
-               priv->qos_data.def_qos_parm.ac[i].cw_max =
-                       cpu_to_le16(cw_min);
-               priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
-               if (is_legacy)
-                       priv->qos_data.def_qos_parm.ac[i].edca_txop =
-                               cpu_to_le16(6016);
-               else
-                       priv->qos_data.def_qos_parm.ac[i].edca_txop =
-                               cpu_to_le16(3008);
-               priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-               /* AC_VO */
-               i = 3;
-               priv->qos_data.def_qos_parm.ac[i].cw_min =
-                       cpu_to_le16((cw_min + 1) / 4 - 1);
-               priv->qos_data.def_qos_parm.ac[i].cw_max =
-                       cpu_to_le16((cw_min + 1) / 2 - 1);
-               priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
-               priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-               if (is_legacy)
-                       priv->qos_data.def_qos_parm.ac[i].edca_txop =
-                               cpu_to_le16(3264);
-               else
-                       priv->qos_data.def_qos_parm.ac[i].edca_txop =
-                               cpu_to_le16(1504);
-       } else {
-               for (i = 1; i < 4; i++) {
-                       priv->qos_data.def_qos_parm.ac[i].cw_min =
-                               cpu_to_le16(cw_min);
-                       priv->qos_data.def_qos_parm.ac[i].cw_max =
-                               cpu_to_le16(cw_max);
-                       priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
-                       priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
-                       priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-               }
-       }
-       IWL_DEBUG_QOS(priv, "set QoS to default \n");
-       spin_unlock_irqrestore(&priv->lock, flags);
- }
- EXPORT_SYMBOL(iwl_reset_qos);
  
  #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
  #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
@@@ -1092,12 -884,12 +885,12 @@@ void iwl_set_rxon_chain(struct iwl_pri
        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 for 4965
-        * Avoid A (0x1) because of its off-channel reception on A-band.
+       /* 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->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) {
+           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;
@@@ -1584,10 -1376,11 +1377,11 @@@ int iwl_set_tx_power(struct iwl_priv *p
        int ret = 0;
        s8 prev_tx_power = priv->tx_power_user_lmt;
  
-       if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) {
-               IWL_WARN(priv, "Requested user TXPOWER %d below lower limit %d.\n",
+       if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
+               IWL_WARN(priv,
+                        "Requested user TXPOWER %d below lower limit %d.\n",
                         tx_power,
-                        IWL_TX_POWER_TARGET_POWER_MIN);
+                        IWLAGN_TX_POWER_TARGET_POWER_MIN);
                return -EINVAL;
        }
  
@@@ -1631,10 -1424,11 +1425,11 @@@ irqreturn_t iwl_isr_legacy(int irq, voi
        struct iwl_priv *priv = data;
        u32 inta, inta_mask;
        u32 inta_fh;
+       unsigned long flags;
        if (!priv)
                return IRQ_NONE;
  
-       spin_lock(&priv->lock);
+       spin_lock_irqsave(&priv->lock, flags);
  
        /* Disable (but don't clear!) interrupts here to avoid
         *    back-to-back ISRs and sporadic interrupts from our NIC.
                tasklet_schedule(&priv->irq_tasklet);
  
   unplugged:
-       spin_unlock(&priv->lock);
+       spin_unlock_irqrestore(&priv->lock, flags);
        return IRQ_HANDLED;
  
   none:
        /* only Re-enable if diabled by irq */
        if (test_bit(STATUS_INT_ENABLED, &priv->status))
                iwl_enable_interrupts(priv);
-       spin_unlock(&priv->lock);
+       spin_unlock_irqrestore(&priv->lock, flags);
        return IRQ_NONE;
  }
  EXPORT_SYMBOL(iwl_isr_legacy);
@@@ -1993,12 -1787,6 +1788,6 @@@ int iwl_mac_conf_tx(struct ieee80211_h
                        cpu_to_le16((params->txop * 32));
  
        priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
-       priv->qos_data.qos_active = 1;
-       if (priv->iw_mode == NL80211_IFTYPE_AP)
-               iwl_activate_qos(priv, 1);
-       else if (priv->assoc_id && iwl_is_associated(priv))
-               iwl_activate_qos(priv, 0);
  
        spin_unlock_irqrestore(&priv->lock, flags);
  
@@@ -2013,7 -1801,7 +1802,7 @@@ static void iwl_ht_conf(struct iwl_pri
        struct iwl_ht_config *ht_conf = &priv->current_ht_config;
        struct ieee80211_sta *sta;
  
-       IWL_DEBUG_MAC80211(priv, "enter: \n");
+       IWL_DEBUG_MAC80211(priv, "enter:\n");
  
        if (!ht_conf->is_ht)
                return;
@@@ -2269,11 -2057,8 +2058,8 @@@ int iwl_mac_beacon_update(struct ieee80
        IWL_DEBUG_MAC80211(priv, "leave\n");
        spin_unlock_irqrestore(&priv->lock, flags);
  
-       iwl_reset_qos(priv);
        priv->cfg->ops->lib->post_associate(priv);
  
        return 0;
  }
  EXPORT_SYMBOL(iwl_mac_beacon_update);
@@@ -2495,6 -2280,15 +2281,15 @@@ int iwl_mac_config(struct ieee80211_hw 
                iwl_set_tx_power(priv, conf->power_level, false);
        }
  
+       if (changed & IEEE80211_CONF_CHANGE_QOS) {
+               bool qos_active = !!(conf->flags & IEEE80211_CONF_QOS);
+               spin_lock_irqsave(&priv->lock, flags);
+               priv->qos_data.qos_active = qos_active;
+               iwl_update_qos(priv);
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
        if (!iwl_is_ready(priv)) {
                IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
                goto out;
@@@ -2529,8 -2323,6 +2324,6 @@@ void iwl_mac_reset_tsf(struct ieee80211
        memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
        spin_unlock_irqrestore(&priv->lock, flags);
  
-       iwl_reset_qos(priv);
        spin_lock_irqsave(&priv->lock, flags);
        priv->assoc_id = 0;
        priv->assoc_capability = 0;
@@@ -2574,7 -2366,7 +2367,7 @@@ int iwl_alloc_txq_mem(struct iwl_priv *
                        sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues,
                        GFP_KERNEL);
        if (!priv->txq) {
-               IWL_ERR(priv, "Not enough memory for txq \n");
+               IWL_ERR(priv, "Not enough memory for txq\n");
                return -ENOMEM;
        }
        return 0;
index 2ffc2edbf4f08c0e189a09802f62080e31281aca,f469aa92316a08d29fc7350c8fa4a762d6b8d8d0..4a487639d932c3086d471104d98aab4df8b5bf1b
@@@ -28,8 -28,6 +28,8 @@@
  
  /* sparse doesn't like tracepoint macros */
  #ifndef __CHECKER__
 +#include "iwl-dev.h"
 +
  #define CREATE_TRACE_POINTS
  #include "iwl-devtrace.h"
  
@@@ -37,6 -35,7 +37,7 @@@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_io
  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32);
  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32);
  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx);
+ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_tx);
  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event);
  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error);
  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event);
index 16eb3ced9b30c1f9301f0327b31487322c2248c3,4f54a5f71cd5455040273a6f40d6fda02baf3b08..0203a3bbf872e2f05086c242993e182c618f9e31
@@@ -31,7 -31,6 +31,7 @@@
  
  #include <linux/io.h>
  
 +#include "iwl-dev.h"
  #include "iwl-debug.h"
  #include "iwl-devtrace.h"
  
@@@ -298,7 -297,7 +298,7 @@@ static inline u32 __iwl_read_direct32(c
                                        struct iwl_priv *priv, u32 reg)
  {
        u32 value = _iwl_read_direct32(priv, reg);
-       IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
+       IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value,
                     f, l);
        return value;
  }
index 548dac2f6a960363b5046f1df0e8f5cf034941ae,2655dbdc8175ffb9172e80565eed4af82556a6f5..581c683a85072929519b1a99646c0883e9541616
@@@ -29,7 -29,6 +29,7 @@@
  
  #include <linux/kernel.h>
  #include <linux/module.h>
 +#include <linux/slab.h>
  #include <linux/init.h>
  
  #include <net/mac80211.h>
@@@ -384,10 -383,10 +384,10 @@@ EXPORT_SYMBOL(iwl_ht_enabled)
  
  bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
  {
-       s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */
+       s32 temp = priv->temperature; /* degrees CELSIUS except specified */
        bool within_margin = false;
  
-       if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
+       if (priv->cfg->temperature_kelvin)
                temp = KELVIN_TO_CELSIUS(priv->temperature);
  
        if (!priv->thermal_throttle.advanced_tt)
@@@ -840,12 -839,12 +840,12 @@@ EXPORT_SYMBOL(iwl_tt_exit_ct_kill)
  static void iwl_bg_tt_work(struct work_struct *work)
  {
        struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
-       s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */
+       s32 temp = priv->temperature; /* degrees CELSIUS except specified */
  
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
  
-       if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
+       if (priv->cfg->temperature_kelvin)
                temp = KELVIN_TO_CELSIUS(priv->temperature);
  
        if (!priv->thermal_throttle.advanced_tt)
@@@ -875,7 -874,7 +875,7 @@@ void iwl_tt_initialize(struct iwl_priv 
        int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
        struct iwl_tt_trans *transaction;
  
-       IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n");
+       IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
  
        memset(tt, 0, sizeof(struct iwl_tt_mgmt));
  
index d3b2fb389e58f499c469f0a9832b13f92d8c768a,1dff14a67b2c928791dec6f6be99286aa30fce2d..267eb89359020aebe4719017d3344cf324881a29
@@@ -28,7 -28,6 +28,7 @@@
   *****************************************************************************/
  
  #include <linux/etherdevice.h>
 +#include <linux/slab.h>
  #include <net/mac80211.h>
  #include <asm/unaligned.h>
  #include "iwl-eeprom.h"
@@@ -163,197 -162,6 +163,6 @@@ void iwl_rx_queue_update_write_ptr(stru
        spin_unlock_irqrestore(&q->lock, flags);
  }
  EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr);
- /**
-  * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
-  */
- static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
-                                         dma_addr_t dma_addr)
- {
-       return cpu_to_le32((u32)(dma_addr >> 8));
- }
- /**
-  * iwl_rx_queue_restock - refill RX queue from pre-allocated pool
-  *
-  * If there are slots in the RX queue that need to be restocked,
-  * and we have free pre-allocated buffers, fill the ranks as much
-  * as we can, pulling from rx_free.
-  *
-  * This moves the 'write' index forward to catch up with 'processed', and
-  * also updates the memory address in the firmware to reference the new
-  * target buffer.
-  */
- void iwl_rx_queue_restock(struct iwl_priv *priv)
- {
-       struct iwl_rx_queue *rxq = &priv->rxq;
-       struct list_head *element;
-       struct iwl_rx_mem_buffer *rxb;
-       unsigned long flags;
-       int write;
-       spin_lock_irqsave(&rxq->lock, flags);
-       write = rxq->write & ~0x7;
-       while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
-               /* Get next free Rx buffer, remove from free list */
-               element = rxq->rx_free.next;
-               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-               list_del(element);
-               /* Point to Rx buffer via next RBD in circular buffer */
-               rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma);
-               rxq->queue[rxq->write] = rxb;
-               rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
-               rxq->free_count--;
-       }
-       spin_unlock_irqrestore(&rxq->lock, flags);
-       /* If the pre-allocated buffer pool is dropping low, schedule to
-        * refill it */
-       if (rxq->free_count <= RX_LOW_WATERMARK)
-               queue_work(priv->workqueue, &priv->rx_replenish);
-       /* If we've added more space for the firmware to place data, tell it.
-        * Increment device's write pointer in multiples of 8. */
-       if (rxq->write_actual != (rxq->write & ~0x7)) {
-               spin_lock_irqsave(&rxq->lock, flags);
-               rxq->need_update = 1;
-               spin_unlock_irqrestore(&rxq->lock, flags);
-               iwl_rx_queue_update_write_ptr(priv, rxq);
-       }
- }
- EXPORT_SYMBOL(iwl_rx_queue_restock);
- /**
-  * iwl_rx_replenish - Move all used packet from rx_used to rx_free
-  *
-  * When moving to rx_free an SKB is allocated for the slot.
-  *
-  * Also restock the Rx queue via iwl_rx_queue_restock.
-  * This is called as a scheduled work item (except for during initialization)
-  */
- void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- {
-       struct iwl_rx_queue *rxq = &priv->rxq;
-       struct list_head *element;
-       struct iwl_rx_mem_buffer *rxb;
-       struct page *page;
-       unsigned long flags;
-       gfp_t gfp_mask = priority;
-       while (1) {
-               spin_lock_irqsave(&rxq->lock, flags);
-               if (list_empty(&rxq->rx_used)) {
-                       spin_unlock_irqrestore(&rxq->lock, flags);
-                       return;
-               }
-               spin_unlock_irqrestore(&rxq->lock, flags);
-               if (rxq->free_count > RX_LOW_WATERMARK)
-                       gfp_mask |= __GFP_NOWARN;
-               if (priv->hw_params.rx_page_order > 0)
-                       gfp_mask |= __GFP_COMP;
-               /* Alloc a new receive buffer */
-               page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
-               if (!page) {
-                       if (net_ratelimit())
-                               IWL_DEBUG_INFO(priv, "alloc_pages failed, "
-                                              "order: %d\n",
-                                              priv->hw_params.rx_page_order);
-                       if ((rxq->free_count <= RX_LOW_WATERMARK) &&
-                           net_ratelimit())
-                               IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n",
-                                        priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
-                                        rxq->free_count);
-                       /* We don't reschedule replenish work here -- we will
-                        * call the restock method and if it still needs
-                        * more buffers it will schedule replenish */
-                       return;
-               }
-               spin_lock_irqsave(&rxq->lock, flags);
-               if (list_empty(&rxq->rx_used)) {
-                       spin_unlock_irqrestore(&rxq->lock, flags);
-                       __free_pages(page, priv->hw_params.rx_page_order);
-                       return;
-               }
-               element = rxq->rx_used.next;
-               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-               list_del(element);
-               spin_unlock_irqrestore(&rxq->lock, flags);
-               rxb->page = page;
-               /* Get physical address of the RB */
-               rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
-                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-               /* dma address must be no more than 36 bits */
-               BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
-               /* and also 256 byte aligned! */
-               BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
-               spin_lock_irqsave(&rxq->lock, flags);
-               list_add_tail(&rxb->list, &rxq->rx_free);
-               rxq->free_count++;
-               priv->alloc_rxb_page++;
-               spin_unlock_irqrestore(&rxq->lock, flags);
-       }
- }
- void iwl_rx_replenish(struct iwl_priv *priv)
- {
-       unsigned long flags;
-       iwl_rx_allocate(priv, GFP_KERNEL);
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_rx_queue_restock(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
- }
- EXPORT_SYMBOL(iwl_rx_replenish);
- void iwl_rx_replenish_now(struct iwl_priv *priv)
- {
-       iwl_rx_allocate(priv, GFP_ATOMIC);
-       iwl_rx_queue_restock(priv);
- }
- EXPORT_SYMBOL(iwl_rx_replenish_now);
- /* Assumes that the skb field of the buffers in 'pool' is kept accurate.
-  * If an SKB has been detached, the POOL needs to have its SKB set to NULL
-  * This free routine walks the list of POOL entries and if SKB is set to
-  * non NULL it is unmapped and freed
-  */
- void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
- {
-       int i;
-       for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
-               if (rxq->pool[i].page != NULL) {
-                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-                       __iwl_free_pages(priv, rxq->pool[i].page);
-                       rxq->pool[i].page = NULL;
-               }
-       }
-       dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-                         rxq->dma_addr);
-       dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
-                         rxq->rb_stts, rxq->rb_stts_dma);
-       rxq->bd = NULL;
-       rxq->rb_stts  = NULL;
- }
- EXPORT_SYMBOL(iwl_rx_queue_free);
  
  int iwl_rx_queue_alloc(struct iwl_priv *priv)
  {
@@@ -396,98 -204,6 +205,6 @@@ err_bd
  }
  EXPORT_SYMBOL(iwl_rx_queue_alloc);
  
- void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
- {
-       unsigned long flags;
-       int i;
-       spin_lock_irqsave(&rxq->lock, flags);
-       INIT_LIST_HEAD(&rxq->rx_free);
-       INIT_LIST_HEAD(&rxq->rx_used);
-       /* Fill the rx_used queue with _all_ of the Rx buffers */
-       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
-               /* In the reset function, these buffers may have been allocated
-                * to an SKB, so we need to unmap and free potential storage */
-               if (rxq->pool[i].page != NULL) {
-                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
-                       __iwl_free_pages(priv, rxq->pool[i].page);
-                       rxq->pool[i].page = NULL;
-               }
-               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-       }
-       /* Set us so that we have processed and used all buffers, but have
-        * not restocked the Rx queue with fresh buffers */
-       rxq->read = rxq->write = 0;
-       rxq->write_actual = 0;
-       rxq->free_count = 0;
-       spin_unlock_irqrestore(&rxq->lock, flags);
- }
- int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
- {
-       u32 rb_size;
-       const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
-       u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */
-       if (!priv->cfg->use_isr_legacy)
-               rb_timeout = RX_RB_TIMEOUT;
-       if (priv->cfg->mod_params->amsdu_size_8K)
-               rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
-       else
-               rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
-       /* Stop Rx DMA */
-       iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-       /* Reset driver's Rx queue write index */
-       iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
-       /* Tell device where to find RBD circular buffer in DRAM */
-       iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
-                          (u32)(rxq->dma_addr >> 8));
-       /* Tell device where in DRAM to update its Rx status */
-       iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
-                          rxq->rb_stts_dma >> 4);
-       /* Enable Rx DMA
-        * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
-        *      the credit mechanism in 5000 HW RX FIFO
-        * Direct rx interrupts to hosts
-        * Rx buffer size 4 or 8k
-        * RB timeout 0x10
-        * 256 RBDs
-        */
-       iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
-                          FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
-                          FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
-                          FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
-                          FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
-                          rb_size|
-                          (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
-                          (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
-       /* Set interrupt coalescing timer to default (2048 usecs) */
-       iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
-       return 0;
- }
- int iwl_rxq_stop(struct iwl_priv *priv)
- {
-       /* stop Rx DMA */
-       iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-       iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
-                           FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-       return 0;
- }
- EXPORT_SYMBOL(iwl_rxq_stop);
  void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
                                struct iwl_rx_mem_buffer *rxb)
  
@@@ -543,6 -259,7 +260,7 @@@ static void iwl_rx_calc_noise(struct iw
                le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
        int bcn_silence_c =
                le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
+       int last_rx_noise;
  
        if (bcn_silence_a) {
                total_silence += bcn_silence_a;
  
        /* Average among active antennas */
        if (num_active_rx)
-               priv->last_rx_noise = (total_silence / num_active_rx) - 107;
+               last_rx_noise = (total_silence / num_active_rx) - 107;
        else
-               priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+               last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
  
        IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
                        bcn_silence_a, bcn_silence_b, bcn_silence_c,
-                       priv->last_rx_noise);
+                       last_rx_noise);
  }
  
  #ifdef CONFIG_IWLWIFI_DEBUG
@@@ -617,63 -334,6 +335,6 @@@ static void iwl_accumulative_statistics
  
  #define REG_RECALIB_PERIOD (60)
  
- /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
- #define ACK_CNT_RATIO (50)
- #define BA_TIMEOUT_CNT (5)
- #define BA_TIMEOUT_MAX (16)
- #if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE)
- /**
-  * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries.
-  *
-  * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding
-  * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
-  * operation state.
-  */
- bool iwl_good_ack_health(struct iwl_priv *priv,
-                               struct iwl_rx_packet *pkt)
- {
-       bool rc = true;
-       int actual_ack_cnt_delta, expected_ack_cnt_delta;
-       int ba_timeout_delta;
-       actual_ack_cnt_delta =
-               le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
-               le32_to_cpu(priv->statistics.tx.actual_ack_cnt);
-       expected_ack_cnt_delta =
-               le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) -
-               le32_to_cpu(priv->statistics.tx.expected_ack_cnt);
-       ba_timeout_delta =
-               le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) -
-               le32_to_cpu(priv->statistics.tx.agg.ba_timeout);
-       if ((priv->_agn.agg_tids_count > 0) &&
-           (expected_ack_cnt_delta > 0) &&
-           (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta)
-               < ACK_CNT_RATIO) &&
-           (ba_timeout_delta > BA_TIMEOUT_CNT)) {
-               IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d,"
-                               " expected_ack_cnt = %d\n",
-                               actual_ack_cnt_delta, expected_ack_cnt_delta);
- #ifdef CONFIG_IWLWIFI_DEBUG
-               IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
-                               priv->delta_statistics.tx.rx_detected_cnt);
-               IWL_DEBUG_RADIO(priv,
-                               "ack_or_ba_timeout_collision delta = %d\n",
-                               priv->delta_statistics.tx.
-                               ack_or_ba_timeout_collision);
- #endif
-               IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
-                               ba_timeout_delta);
-               if (!actual_ack_cnt_delta &&
-                   (ba_timeout_delta >= BA_TIMEOUT_MAX))
-                       rc = false;
-       }
-       return rc;
- }
- EXPORT_SYMBOL(iwl_good_ack_health);
- #endif
  /**
   * iwl_good_plcp_health - checks for plcp error.
   *
@@@ -830,139 -490,6 +491,6 @@@ void iwl_reply_statistics(struct iwl_pr
  }
  EXPORT_SYMBOL(iwl_reply_statistics);
  
- /* Calc max signal level (dBm) among 3 possible receivers */
- static inline int iwl_calc_rssi(struct iwl_priv *priv,
-                               struct iwl_rx_phy_res *rx_resp)
- {
-       return priv->cfg->ops->utils->calc_rssi(priv, rx_resp);
- }
- #ifdef CONFIG_IWLWIFI_DEBUG
- /**
-  * iwl_dbg_report_frame - dump frame to syslog during debug sessions
-  *
-  * You may hack this function to show different aspects of received frames,
-  * including selective frame dumps.
-  * group100 parameter selects whether to show 1 out of 100 good data frames.
-  *    All beacon and probe response frames are printed.
-  */
- static void iwl_dbg_report_frame(struct iwl_priv *priv,
-                     struct iwl_rx_phy_res *phy_res, u16 length,
-                     struct ieee80211_hdr *header, int group100)
- {
-       u32 to_us;
-       u32 print_summary = 0;
-       u32 print_dump = 0;     /* set to 1 to dump all frames' contents */
-       u32 hundred = 0;
-       u32 dataframe = 0;
-       __le16 fc;
-       u16 seq_ctl;
-       u16 channel;
-       u16 phy_flags;
-       u32 rate_n_flags;
-       u32 tsf_low;
-       int rssi;
-       if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX)))
-               return;
-       /* MAC header */
-       fc = header->frame_control;
-       seq_ctl = le16_to_cpu(header->seq_ctrl);
-       /* metadata */
-       channel = le16_to_cpu(phy_res->channel);
-       phy_flags = le16_to_cpu(phy_res->phy_flags);
-       rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
-       /* signal statistics */
-       rssi = iwl_calc_rssi(priv, phy_res);
-       tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff;
-       to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
-       /* if data frame is to us and all is good,
-        *   (optionally) print summary for only 1 out of every 100 */
-       if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) ==
-           cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
-               dataframe = 1;
-               if (!group100)
-                       print_summary = 1;      /* print each frame */
-               else if (priv->framecnt_to_us < 100) {
-                       priv->framecnt_to_us++;
-                       print_summary = 0;
-               } else {
-                       priv->framecnt_to_us = 0;
-                       print_summary = 1;
-                       hundred = 1;
-               }
-       } else {
-               /* print summary for all other frames */
-               print_summary = 1;
-       }
-       if (print_summary) {
-               char *title;
-               int rate_idx;
-               u32 bitrate;
-               if (hundred)
-                       title = "100Frames";
-               else if (ieee80211_has_retry(fc))
-                       title = "Retry";
-               else if (ieee80211_is_assoc_resp(fc))
-                       title = "AscRsp";
-               else if (ieee80211_is_reassoc_resp(fc))
-                       title = "RasRsp";
-               else if (ieee80211_is_probe_resp(fc)) {
-                       title = "PrbRsp";
-                       print_dump = 1; /* dump frame contents */
-               } else if (ieee80211_is_beacon(fc)) {
-                       title = "Beacon";
-                       print_dump = 1; /* dump frame contents */
-               } else if (ieee80211_is_atim(fc))
-                       title = "ATIM";
-               else if (ieee80211_is_auth(fc))
-                       title = "Auth";
-               else if (ieee80211_is_deauth(fc))
-                       title = "DeAuth";
-               else if (ieee80211_is_disassoc(fc))
-                       title = "DisAssoc";
-               else
-                       title = "Frame";
-               rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags);
-               if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) {
-                       bitrate = 0;
-                       WARN_ON_ONCE(1);
-               } else {
-                       bitrate = iwl_rates[rate_idx].ieee / 2;
-               }
-               /* print frame summary.
-                * MAC addresses show just the last byte (for brevity),
-                *    but you can hack it to show more, if you'd like to. */
-               if (dataframe)
-                       IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, "
-                                    "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
-                                    title, le16_to_cpu(fc), header->addr1[5],
-                                    length, rssi, channel, bitrate);
-               else {
-                       /* src/dst addresses assume managed mode */
-                       IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, "
-                                    "len=%u, rssi=%d, tim=%lu usec, "
-                                    "phy=0x%02x, chnl=%d\n",
-                                    title, le16_to_cpu(fc), header->addr1[5],
-                                    header->addr3[5], length, rssi,
-                                    tsf_low - priv->scan_start_tsf,
-                                    phy_flags, channel);
-               }
-       }
-       if (print_dump)
-               iwl_print_hex_dump(priv, IWL_DL_RX, header, length);
- }
- #endif
  /*
   * returns non-zero if packet should be dropped
   */
@@@ -1010,281 -537,3 +538,3 @@@ int iwl_set_decrypted_flag(struct iwl_p
        return 0;
  }
  EXPORT_SYMBOL(iwl_set_decrypted_flag);
- static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
- {
-       u32 decrypt_out = 0;
-       if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
-                                       RX_RES_STATUS_STATION_FOUND)
-               decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
-                               RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
-       decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
-       /* packet was not encrypted */
-       if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
-                                       RX_RES_STATUS_SEC_TYPE_NONE)
-               return decrypt_out;
-       /* packet was encrypted with unknown alg */
-       if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
-                                       RX_RES_STATUS_SEC_TYPE_ERR)
-               return decrypt_out;
-       /* decryption was not done in HW */
-       if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
-                                       RX_MPDU_RES_STATUS_DEC_DONE_MSK)
-               return decrypt_out;
-       switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
-       case RX_RES_STATUS_SEC_TYPE_CCMP:
-               /* alg is CCM: check MIC only */
-               if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
-                       /* Bad MIC */
-                       decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
-               else
-                       decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-               break;
-       case RX_RES_STATUS_SEC_TYPE_TKIP:
-               if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
-                       /* Bad TTAK */
-                       decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
-                       break;
-               }
-               /* fall through if TTAK OK */
-       default:
-               if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
-                       decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
-               else
-                       decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-               break;
-       };
-       IWL_DEBUG_RX(priv, "decrypt_in:0x%x  decrypt_out = 0x%x\n",
-                                       decrypt_in, decrypt_out);
-       return decrypt_out;
- }
- static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
-                                       struct ieee80211_hdr *hdr,
-                                       u16 len,
-                                       u32 ampdu_status,
-                                       struct iwl_rx_mem_buffer *rxb,
-                                       struct ieee80211_rx_status *stats)
- {
-       struct sk_buff *skb;
-       int ret = 0;
-       __le16 fc = hdr->frame_control;
-       /* We only process data packets if the interface is open */
-       if (unlikely(!priv->is_open)) {
-               IWL_DEBUG_DROP_LIMIT(priv,
-                   "Dropping packet while interface is not open.\n");
-               return;
-       }
-       /* In case of HW accelerated crypto and bad decryption, drop */
-       if (!priv->cfg->mod_params->sw_crypto &&
-           iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
-               return;
-       skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC);
-       if (!skb) {
-               IWL_ERR(priv, "alloc_skb failed\n");
-               return;
-       }
-       skb_reserve(skb, IWL_LINK_HDR_MAX);
-       skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
-       /* mac80211 currently doesn't support paged SKB. Convert it to
-        * linear SKB for management frame and data frame requires
-        * software decryption or software defragementation. */
-       if (ieee80211_is_mgmt(fc) ||
-           ieee80211_has_protected(fc) ||
-           ieee80211_has_morefrags(fc) ||
-           le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG ||
-           (ieee80211_is_data_qos(fc) &&
-            *ieee80211_get_qos_ctl(hdr) &
-            IEEE80211_QOS_CONTROL_A_MSDU_PRESENT))
-               ret = skb_linearize(skb);
-       else
-               ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
-                        0 : -ENOMEM;
-       if (ret) {
-               kfree_skb(skb);
-               goto out;
-       }
-       /*
-        * XXX: We cannot touch the page and its virtual memory (hdr) after
-        * here. It might have already been freed by the above skb change.
-        */
-       iwl_update_stats(priv, false, fc, len);
-       memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-       ieee80211_rx(priv->hw, skb);
-  out:
-       priv->alloc_rxb_page--;
-       rxb->page = NULL;
- }
- /* Called for REPLY_RX (legacy ABG frames), or
-  * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
- void iwl_rx_reply_rx(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
- {
-       struct ieee80211_hdr *header;
-       struct ieee80211_rx_status rx_status;
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_rx_phy_res *phy_res;
-       __le32 rx_pkt_status;
-       struct iwl4965_rx_mpdu_res_start *amsdu;
-       u32 len;
-       u32 ampdu_status;
-       u32 rate_n_flags;
-       /**
-        * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
-        *      REPLY_RX: physical layer info is in this buffer
-        *      REPLY_RX_MPDU_CMD: physical layer info was sent in separate
-        *              command and cached in priv->last_phy_res
-        *
-        * Here we set up local variables depending on which command is
-        * received.
-        */
-       if (pkt->hdr.cmd == REPLY_RX) {
-               phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
-               header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
-                               + phy_res->cfg_phy_cnt);
-               len = le16_to_cpu(phy_res->byte_count);
-               rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
-                               phy_res->cfg_phy_cnt + len);
-               ampdu_status = le32_to_cpu(rx_pkt_status);
-       } else {
-               if (!priv->last_phy_res[0]) {
-                       IWL_ERR(priv, "MPDU frame without cached PHY data\n");
-                       return;
-               }
-               phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1];
-               amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
-               header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
-               len = le16_to_cpu(amsdu->byte_count);
-               rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
-               ampdu_status = iwl_translate_rx_status(priv,
-                               le32_to_cpu(rx_pkt_status));
-       }
-       if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
-               IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
-                               phy_res->cfg_phy_cnt);
-               return;
-       }
-       if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
-           !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
-               IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
-                               le32_to_cpu(rx_pkt_status));
-               return;
-       }
-       /* This will be used in several places later */
-       rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
-       /* rx_status carries information about the packet to mac80211 */
-       rx_status.mactime = le64_to_cpu(phy_res->timestamp);
-       rx_status.freq =
-               ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel));
-       rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-                               IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-       rx_status.rate_idx =
-               iwl_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
-       rx_status.flag = 0;
-       /* TSF isn't reliable. In order to allow smooth user experience,
-        * this W/A doesn't propagate it to the mac80211 */
-       /*rx_status.flag |= RX_FLAG_TSFT;*/
-       priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
-       /* Find max signal strength (dBm) among 3 antenna/receiver chains */
-       rx_status.signal = iwl_calc_rssi(priv, phy_res);
-       /* Meaningful noise values are available only from beacon statistics,
-        *   which are gathered only when associated, and indicate noise
-        *   only for the associated network channel ...
-        * Ignore these noise values while scanning (other channels) */
-       if (iwl_is_associated(priv) &&
-           !test_bit(STATUS_SCANNING, &priv->status)) {
-               rx_status.noise = priv->last_rx_noise;
-       } else {
-               rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-       }
-       /* Reset beacon noise level if not associated. */
-       if (!iwl_is_associated(priv))
-               priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
- #ifdef CONFIG_IWLWIFI_DEBUG
-       /* Set "1" to report good data frames in groups of 100 */
-       if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX))
-               iwl_dbg_report_frame(priv, phy_res, len, header, 1);
- #endif
-       iwl_dbg_log_rx_data_frame(priv, len, header);
-       IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n",
-               rx_status.signal, rx_status.noise,
-               (unsigned long long)rx_status.mactime);
-       /*
-        * "antenna number"
-        *
-        * It seems that the antenna field in the phy flags value
-        * is actually a bit field. This is undefined by radiotap,
-        * it wants an actual antenna number but I always get "7"
-        * for most legacy frames I receive indicating that the
-        * same frame was received on all three RX chains.
-        *
-        * I think this field should be removed in favor of a
-        * new 802.11n radiotap field "RX chains" that is defined
-        * as a bitmask.
-        */
-       rx_status.antenna =
-               (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK)
-               >> RX_RES_PHY_FLAGS_ANTENNA_POS;
-       /* set the preamble flag if appropriate */
-       if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-               rx_status.flag |= RX_FLAG_SHORTPRE;
-       /* Set up the HT phy flags */
-       if (rate_n_flags & RATE_MCS_HT_MSK)
-               rx_status.flag |= RX_FLAG_HT;
-       if (rate_n_flags & RATE_MCS_HT40_MSK)
-               rx_status.flag |= RX_FLAG_40MHZ;
-       if (rate_n_flags & RATE_MCS_SGI_MSK)
-               rx_status.flag |= RX_FLAG_SHORT_GI;
-       iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
-                                   rxb, &rx_status);
- }
- EXPORT_SYMBOL(iwl_rx_reply_rx);
- /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
-  * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
- void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
- {
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       priv->last_phy_res[0] = 1;
-       memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
-              sizeof(struct iwl_rx_phy_res));
- }
- EXPORT_SYMBOL(iwl_rx_reply_rx_phy);
index e8e4b5493e89d7365344d291cb53aca32e7837ab,d817c9c184a532cc0a7fb27ae88f2c4303721d1b..ae981932ce611aaed52dc6e793ad16376dafc2dc
@@@ -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>
@@@ -454,7 -453,7 +454,7 @@@ static int iwl_get_channels_for_scan(st
                added++;
        }
  
-       IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added);
+       IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
        return added;
  }
  
@@@ -814,10 -813,11 +814,11 @@@ static void iwl_bg_request_scan(struct 
                 */
                scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
  
-               /* Force use of chains B and C (0x6) for scan Rx for 4965
-                * Avoid A (0x1) because of its off-channel reception on A-band.
+               /* 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->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
+               if (priv->cfg->off_channel_workaround)
                        rx_ant = ANT_BC;
        } else {
                IWL_WARN(priv, "Invalid scan band count\n");
index b798fbabc3b6a36bc5dab1155111a31a9ff7d6bd,c3c6505a8c69fe7f80eaa502ddab5a178a2a0caf..1ece2ea09773567145a5acde6bf997749856e107
@@@ -29,7 -29,6 +29,7 @@@
  
  #include <linux/etherdevice.h>
  #include <linux/sched.h>
 +#include <linux/slab.h>
  #include <net/mac80211.h>
  #include "iwl-eeprom.h"
  #include "iwl-dev.h"
  #include "iwl-io.h"
  #include "iwl-helpers.h"
  
- /*
-  * mac80211 queues, ACs, hardware queues, FIFOs.
-  *
-  * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
-  *
-  * Mac80211 uses the following numbers, which we get as from it
-  * by way of skb_get_queue_mapping(skb):
-  *
-  *    VO      0
-  *    VI      1
-  *    BE      2
-  *    BK      3
-  *
-  *
-  * Regular (not A-MPDU) frames are put into hardware queues corresponding
-  * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
-  * own queue per aggregation session (RA/TID combination), such queues are
-  * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
-  * order to map frames to the right queue, we also need an AC->hw queue
-  * mapping. This is implemented here.
-  *
-  * Due to the way hw queues are set up (by the hw specific modules like
-  * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity
-  * mapping.
-  */
- static const u8 tid_to_ac[] = {
-       /* this matches the mac80211 numbers */
-       2, 3, 3, 2, 1, 1, 0, 0
- };
- static const u8 ac_to_fifo[] = {
-       IWL_TX_FIFO_VO,
-       IWL_TX_FIFO_VI,
-       IWL_TX_FIFO_BE,
-       IWL_TX_FIFO_BK,
- };
- static inline int get_fifo_from_ac(u8 ac)
- {
-       return ac_to_fifo[ac];
- }
- static inline int get_queue_from_ac(u16 ac)
- {
-       return ac;
- }
- static inline int get_fifo_from_tid(u16 tid)
- {
-       if (likely(tid < ARRAY_SIZE(tid_to_ac)))
-               return get_fifo_from_ac(tid_to_ac[tid]);
-       /* no support for TIDs 8-15 yet */
-       return -EINVAL;
- }
- static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
-                                   struct iwl_dma_ptr *ptr, size_t size)
- {
-       ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
-                                      GFP_KERNEL);
-       if (!ptr->addr)
-               return -ENOMEM;
-       ptr->size = size;
-       return 0;
- }
- static inline void iwl_free_dma_ptr(struct iwl_priv *priv,
-                                   struct iwl_dma_ptr *ptr)
- {
-       if (unlikely(!ptr->addr))
-               return;
-       dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
-       memset(ptr, 0, sizeof(*ptr));
- }
  /**
   * iwl_txq_update_write_ptr - Send new write index to hardware
   */
@@@ -493,598 -414,6 +415,6 @@@ void iwl_tx_queue_reset(struct iwl_pri
  }
  EXPORT_SYMBOL(iwl_tx_queue_reset);
  
- /**
-  * iwl_hw_txq_ctx_free - Free TXQ Context
-  *
-  * Destroy all TX DMA queues and structures
-  */
- void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
- {
-       int txq_id;
-       /* Tx queues */
-       if (priv->txq) {
-               for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-                       if (txq_id == IWL_CMD_QUEUE_NUM)
-                               iwl_cmd_queue_free(priv);
-                       else
-                               iwl_tx_queue_free(priv, txq_id);
-       }
-       iwl_free_dma_ptr(priv, &priv->kw);
-       iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
-       /* free tx queue structure */
-       iwl_free_txq_mem(priv);
- }
- EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
- /**
-  * iwl_txq_ctx_alloc - allocate TX queue context
-  * Allocate all Tx DMA structures and initialize them
-  *
-  * @param priv
-  * @return error code
-  */
- int iwl_txq_ctx_alloc(struct iwl_priv *priv)
- {
-       int ret;
-       int txq_id, slots_num;
-       unsigned long flags;
-       /* Free all tx/cmd queues and keep-warm buffer */
-       iwl_hw_txq_ctx_free(priv);
-       ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
-                               priv->hw_params.scd_bc_tbls_size);
-       if (ret) {
-               IWL_ERR(priv, "Scheduler BC Table allocation failed\n");
-               goto error_bc_tbls;
-       }
-       /* Alloc keep-warm buffer */
-       ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
-       if (ret) {
-               IWL_ERR(priv, "Keep Warm allocation failed\n");
-               goto error_kw;
-       }
-       /* allocate tx queue structure */
-       ret = iwl_alloc_txq_mem(priv);
-       if (ret)
-               goto error;
-       spin_lock_irqsave(&priv->lock, flags);
-       /* Turn off all Tx DMA fifos */
-       priv->cfg->ops->lib->txq_set_sched(priv, 0);
-       /* Tell NIC where to find the "keep warm" buffer */
-       iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       /* Alloc and init all Tx queues, including the command queue (#4) */
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-               slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
-                                       TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-               ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
-                                      txq_id);
-               if (ret) {
-                       IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
-                       goto error;
-               }
-       }
-       return ret;
-  error:
-       iwl_hw_txq_ctx_free(priv);
-       iwl_free_dma_ptr(priv, &priv->kw);
-  error_kw:
-       iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
-  error_bc_tbls:
-       return ret;
- }
- void iwl_txq_ctx_reset(struct iwl_priv *priv)
- {
-       int txq_id, slots_num;
-       unsigned long flags;
-       spin_lock_irqsave(&priv->lock, flags);
-       /* Turn off all Tx DMA fifos */
-       priv->cfg->ops->lib->txq_set_sched(priv, 0);
-       /* Tell NIC where to find the "keep warm" buffer */
-       iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       /* Alloc and init all Tx queues, including the command queue (#4) */
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-               slots_num = txq_id == IWL_CMD_QUEUE_NUM ?
-                           TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-               iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
-       }
- }
- /**
-  * iwl_txq_ctx_stop - Stop all Tx DMA channels
-  */
- void iwl_txq_ctx_stop(struct iwl_priv *priv)
- {
-       int ch;
-       unsigned long flags;
-       /* Turn off all Tx DMA fifos */
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->cfg->ops->lib->txq_set_sched(priv, 0);
-       /* Stop each Tx DMA channel, and wait for it to be idle */
-       for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
-               iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
-               iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
-                                   FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
-                                   1000);
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
- }
- EXPORT_SYMBOL(iwl_txq_ctx_stop);
- /*
-  * handle build REPLY_TX command notification.
-  */
- static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
-                                 struct iwl_tx_cmd *tx_cmd,
-                                 struct ieee80211_tx_info *info,
-                                 struct ieee80211_hdr *hdr,
-                                 u8 std_id)
- {
-       __le16 fc = hdr->frame_control;
-       __le32 tx_flags = tx_cmd->tx_flags;
-       tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
-               tx_flags |= TX_CMD_FLG_ACK_MSK;
-               if (ieee80211_is_mgmt(fc))
-                       tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-               if (ieee80211_is_probe_resp(fc) &&
-                   !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
-                       tx_flags |= TX_CMD_FLG_TSF_MSK;
-       } else {
-               tx_flags &= (~TX_CMD_FLG_ACK_MSK);
-               tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-       }
-       if (ieee80211_is_back_req(fc))
-               tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
-       tx_cmd->sta_id = std_id;
-       if (ieee80211_has_morefrags(fc))
-               tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
-       if (ieee80211_is_data_qos(fc)) {
-               u8 *qc = ieee80211_get_qos_ctl(hdr);
-               tx_cmd->tid_tspec = qc[0] & 0xf;
-               tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
-       } else {
-               tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-       }
-       priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags);
-       if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
-               tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-       tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
-       if (ieee80211_is_mgmt(fc)) {
-               if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
-                       tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
-               else
-                       tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
-       } else {
-               tx_cmd->timeout.pm_frame_timeout = 0;
-       }
-       tx_cmd->driver_txop = 0;
-       tx_cmd->tx_flags = tx_flags;
-       tx_cmd->next_frame_len = 0;
- }
- #define RTS_DFAULT_RETRY_LIMIT                60
- static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
-                             struct iwl_tx_cmd *tx_cmd,
-                             struct ieee80211_tx_info *info,
-                             __le16 fc)
- {
-       u32 rate_flags;
-       int rate_idx;
-       u8 rts_retry_limit;
-       u8 data_retry_limit;
-       u8 rate_plcp;
-       /* Set retry limit on DATA packets and Probe Responses*/
-       if (ieee80211_is_probe_resp(fc))
-               data_retry_limit = 3;
-       else
-               data_retry_limit = IWL_DEFAULT_TX_RETRY;
-       tx_cmd->data_retry_limit = data_retry_limit;
-       /* Set retry limit on RTS packets */
-       rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
-       if (data_retry_limit < rts_retry_limit)
-               rts_retry_limit = data_retry_limit;
-       tx_cmd->rts_retry_limit = rts_retry_limit;
-       /* DATA packets will use the uCode station table for rate/antenna
-        * selection */
-       if (ieee80211_is_data(fc)) {
-               tx_cmd->initial_rate_index = 0;
-               tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
-               return;
-       }
-       /**
-        * If the current TX rate stored in mac80211 has the MCS bit set, it's
-        * not really a TX rate.  Thus, we use the lowest supported rate for
-        * this band.  Also use the lowest supported rate if the stored rate
-        * index is invalid.
-        */
-       rate_idx = info->control.rates[0].idx;
-       if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS ||
-                       (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY))
-               rate_idx = rate_lowest_index(&priv->bands[info->band],
-                               info->control.sta);
-       /* For 5 GHZ band, remap mac80211 rate indices into driver indices */
-       if (info->band == IEEE80211_BAND_5GHZ)
-               rate_idx += IWL_FIRST_OFDM_RATE;
-       /* Get PLCP rate for tx_cmd->rate_n_flags */
-       rate_plcp = iwl_rates[rate_idx].plcp;
-       /* Zero out flags for this packet */
-       rate_flags = 0;
-       /* Set CCK flag as needed */
-       if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
-               rate_flags |= RATE_MCS_CCK_MSK;
-       /* Set up RTS and CTS flags for certain packets */
-       switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
-       case cpu_to_le16(IEEE80211_STYPE_AUTH):
-       case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-       case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
-       case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
-               if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) {
-                       tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-                       tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK;
-               }
-               break;
-       default:
-               break;
-       }
-       /* Set up antennas */
-       priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
-       rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
-       /* Set the rate in the TX cmd */
-       tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags);
- }
- static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
-                                     struct ieee80211_tx_info *info,
-                                     struct iwl_tx_cmd *tx_cmd,
-                                     struct sk_buff *skb_frag,
-                                     int sta_id)
- {
-       struct ieee80211_key_conf *keyconf = info->control.hw_key;
-       switch (keyconf->alg) {
-       case ALG_CCMP:
-               tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
-               memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
-               if (info->flags & IEEE80211_TX_CTL_AMPDU)
-                       tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
-               IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
-               break;
-       case ALG_TKIP:
-               tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
-               ieee80211_get_tkip_key(keyconf, skb_frag,
-                       IEEE80211_TKIP_P2_KEY, tx_cmd->key);
-               IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
-               break;
-       case ALG_WEP:
-               tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP |
-                       (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
-               if (keyconf->keylen == WEP_KEY_LEN_128)
-                       tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
-               memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
-               IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
-                            "with key %d\n", keyconf->keyidx);
-               break;
-       default:
-               IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg);
-               break;
-       }
- }
- /*
-  * start REPLY_TX command process
-  */
- int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
- {
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_sta *sta = info->control.sta;
-       struct iwl_station_priv *sta_priv = NULL;
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-       struct iwl_device_cmd *out_cmd;
-       struct iwl_cmd_meta *out_meta;
-       struct iwl_tx_cmd *tx_cmd;
-       int swq_id, txq_id;
-       dma_addr_t phys_addr;
-       dma_addr_t txcmd_phys;
-       dma_addr_t scratch_phys;
-       u16 len, len_org, firstlen, secondlen;
-       u16 seq_number = 0;
-       __le16 fc;
-       u8 hdr_len;
-       u8 sta_id;
-       u8 wait_write_ptr = 0;
-       u8 tid = 0;
-       u8 *qc = NULL;
-       unsigned long flags;
-       spin_lock_irqsave(&priv->lock, flags);
-       if (iwl_is_rfkill(priv)) {
-               IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
-               goto drop_unlock;
-       }
-       fc = hdr->frame_control;
- #ifdef CONFIG_IWLWIFI_DEBUG
-       if (ieee80211_is_auth(fc))
-               IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
-       else if (ieee80211_is_assoc_req(fc))
-               IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
-       else if (ieee80211_is_reassoc_req(fc))
-               IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
- #endif
-       hdr_len = ieee80211_hdrlen(fc);
-       /* Find (or create) index into station table for destination station */
-       if (info->flags & IEEE80211_TX_CTL_INJECTED)
-               sta_id = priv->hw_params.bcast_sta_id;
-       else
-               sta_id = iwl_get_sta_id(priv, hdr);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-                              hdr->addr1);
-               goto drop_unlock;
-       }
-       IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
-       if (sta)
-               sta_priv = (void *)sta->drv_priv;
-       if (sta_priv && sta_id != priv->hw_params.bcast_sta_id &&
-           sta_priv->asleep) {
-               WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE));
-               /*
-                * This sends an asynchronous command to the device,
-                * but we can rely on it being processed before the
-                * next frame is processed -- and the next frame to
-                * this station is the one that will consume this
-                * counter.
-                * For now set the counter to just 1 since we do not
-                * support uAPSD yet.
-                */
-               iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
-       }
-       txq_id = get_queue_from_ac(skb_get_queue_mapping(skb));
-       if (ieee80211_is_data_qos(fc)) {
-               qc = ieee80211_get_qos_ctl(hdr);
-               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-               if (unlikely(tid >= MAX_TID_COUNT))
-                       goto drop_unlock;
-               seq_number = priv->stations[sta_id].tid[tid].seq_number;
-               seq_number &= IEEE80211_SCTL_SEQ;
-               hdr->seq_ctrl = hdr->seq_ctrl &
-                               cpu_to_le16(IEEE80211_SCTL_FRAG);
-               hdr->seq_ctrl |= cpu_to_le16(seq_number);
-               seq_number += 0x10;
-               /* aggregation is on for this <sta,tid> */
-               if (info->flags & IEEE80211_TX_CTL_AMPDU &&
-                   priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
-                       txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
-               }
-       }
-       txq = &priv->txq[txq_id];
-       swq_id = txq->swq_id;
-       q = &txq->q;
-       if (unlikely(iwl_queue_space(q) < q->high_mark))
-               goto drop_unlock;
-       if (ieee80211_is_data_qos(fc))
-               priv->stations[sta_id].tid[tid].tfds_in_queue++;
-       /* Set up driver data for this TFD */
-       memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
-       txq->txb[q->write_ptr].skb[0] = skb;
-       /* Set up first empty entry in queue's array of Tx/cmd buffers */
-       out_cmd = txq->cmd[q->write_ptr];
-       out_meta = &txq->meta[q->write_ptr];
-       tx_cmd = &out_cmd->cmd.tx;
-       memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
-       memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
-       /*
-        * Set up the Tx-command (not MAC!) header.
-        * Store the chosen Tx queue and TFD index within the sequence field;
-        * after Tx, uCode's Tx response will return this value so driver can
-        * locate the frame within the tx queue and do post-tx processing.
-        */
-       out_cmd->hdr.cmd = REPLY_TX;
-       out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
-                               INDEX_TO_SEQ(q->write_ptr)));
-       /* Copy MAC header from skb into command buffer */
-       memcpy(tx_cmd->hdr, hdr, hdr_len);
-       /* Total # bytes to be transmitted */
-       len = (u16)skb->len;
-       tx_cmd->len = cpu_to_le16(len);
-       if (info->control.hw_key)
-               iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
-       /* TODO need this for burst mode later on */
-       iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
-       iwl_dbg_log_tx_data_frame(priv, len, hdr);
-       iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc);
-       iwl_update_stats(priv, true, fc, len);
-       /*
-        * Use the first empty entry in this queue's command buffer array
-        * to contain the Tx command and MAC header concatenated together
-        * (payload data will be in another buffer).
-        * Size of this varies, due to varying MAC header length.
-        * If end is not dword aligned, we'll have 2 extra bytes at the end
-        * of the MAC header (device reads on dword boundaries).
-        * We'll tell device about this padding later.
-        */
-       len = sizeof(struct iwl_tx_cmd) +
-               sizeof(struct iwl_cmd_header) + hdr_len;
-       len_org = len;
-       firstlen = len = (len + 3) & ~3;
-       if (len_org != len)
-               len_org = 1;
-       else
-               len_org = 0;
-       /* Tell NIC about any 2-byte padding after MAC header */
-       if (len_org)
-               tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
-       /* Physical address of this Tx command's header (not MAC header!),
-        * within command buffer array. */
-       txcmd_phys = pci_map_single(priv->pci_dev,
-                                   &out_cmd->hdr, len,
-                                   PCI_DMA_BIDIRECTIONAL);
-       pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
-       pci_unmap_len_set(out_meta, len, len);
-       /* Add buffer containing Tx command and MAC(!) header to TFD's
-        * first entry */
-       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                  txcmd_phys, len, 1, 0);
-       if (!ieee80211_has_morefrags(hdr->frame_control)) {
-               txq->need_update = 1;
-               if (qc)
-                       priv->stations[sta_id].tid[tid].seq_number = seq_number;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
-       /* Set up TFD's 2nd entry to point directly to remainder of skb,
-        * if any (802.11 null frames have no payload). */
-       secondlen = len = skb->len - hdr_len;
-       if (len) {
-               phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
-                                          len, PCI_DMA_TODEVICE);
-               priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                          phys_addr, len,
-                                                          0, 0);
-       }
-       scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
-                               offsetof(struct iwl_tx_cmd, scratch);
-       len = sizeof(struct iwl_tx_cmd) +
-               sizeof(struct iwl_cmd_header) + hdr_len;
-       /* take back ownership of DMA buffer to enable update */
-       pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
-                                   len, PCI_DMA_BIDIRECTIONAL);
-       tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
-       tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
-       IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
-                    le16_to_cpu(out_cmd->hdr.sequence));
-       IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags));
-       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
-       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
-       /* Set up entry for this TFD in Tx byte-count array */
-       if (info->flags & IEEE80211_TX_CTL_AMPDU)
-               priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
-                                                    le16_to_cpu(tx_cmd->len));
-       pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
-                                      len, PCI_DMA_BIDIRECTIONAL);
-       trace_iwlwifi_dev_tx(priv,
-                            &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
-                            sizeof(struct iwl_tfd),
-                            &out_cmd->hdr, firstlen,
-                            skb->data + hdr_len, secondlen);
-       /* Tell device the write index *just past* this latest filled TFD */
-       q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-       iwl_txq_update_write_ptr(priv, txq);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       /*
-        * At this point the frame is "transmitted" successfully
-        * and we will get a TX status notification eventually,
-        * regardless of the value of ret. "ret" only indicates
-        * whether or not we should update the write pointer.
-        */
-       /* avoid atomic ops if it isn't an associated client */
-       if (sta_priv && sta_priv->client)
-               atomic_inc(&sta_priv->pending_frames);
-       if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) {
-               if (wait_write_ptr) {
-                       spin_lock_irqsave(&priv->lock, flags);
-                       txq->need_update = 1;
-                       iwl_txq_update_write_ptr(priv, txq);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-               } else {
-                       iwl_stop_queue(priv, txq->swq_id);
-               }
-       }
-       return 0;
- drop_unlock:
-       spin_unlock_irqrestore(&priv->lock, flags);
-       return -1;
- }
- EXPORT_SYMBOL(iwl_tx_skb);
  /*************** HOST COMMAND QUEUE FUNCTIONS   *****/
  
  /**
@@@ -1218,61 -547,6 +548,6 @@@ int iwl_enqueue_hcmd(struct iwl_priv *p
        return idx;
  }
  
- static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
- {
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-       struct ieee80211_sta *sta;
-       struct iwl_station_priv *sta_priv;
-       sta = ieee80211_find_sta(priv->vif, hdr->addr1);
-       if (sta) {
-               sta_priv = (void *)sta->drv_priv;
-               /* avoid atomic ops if this isn't a client */
-               if (sta_priv->client &&
-                   atomic_dec_return(&sta_priv->pending_frames) == 0)
-                       ieee80211_sta_block_awake(priv->hw, sta, false);
-       }
-       ieee80211_tx_status_irqsafe(priv->hw, skb);
- }
- int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
- {
-       struct iwl_tx_queue *txq = &priv->txq[txq_id];
-       struct iwl_queue *q = &txq->q;
-       struct iwl_tx_info *tx_info;
-       int nfreed = 0;
-       struct ieee80211_hdr *hdr;
-       if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
-               IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
-                         "is out of range [0-%d] %d %d.\n", txq_id,
-                         index, q->n_bd, q->write_ptr, q->read_ptr);
-               return 0;
-       }
-       for (index = iwl_queue_inc_wrap(index, q->n_bd);
-            q->read_ptr != index;
-            q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-               tx_info = &txq->txb[txq->q.read_ptr];
-               iwl_tx_status(priv, tx_info->skb[0]);
-               hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data;
-               if (hdr && ieee80211_is_data_qos(hdr->frame_control))
-                       nfreed++;
-               tx_info->skb[0] = NULL;
-               if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
-                       priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq);
-               priv->cfg->ops->lib->txq_free_tfd(priv, txq);
-       }
-       return nfreed;
- }
- EXPORT_SYMBOL(iwl_tx_queue_reclaim);
  /**
   * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
   *
@@@ -1366,7 -640,7 +641,7 @@@ void iwl_tx_cmd_complete(struct iwl_pri
  
        if (!(meta->flags & CMD_ASYNC)) {
                clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-               IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n",
+               IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
                               get_cmd_string(cmd->hdr.cmd));
                wake_up_interruptible(&priv->wait_command_queue);
        }
  }
  EXPORT_SYMBOL(iwl_tx_cmd_complete);
  
- /*
-  * Find first available (lowest unused) Tx Queue, mark it "active".
-  * Called only when finding queue for aggregation.
-  * Should never return anything < 7, because they should already
-  * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
-  */
- static int iwl_txq_ctx_activate_free(struct iwl_priv *priv)
- {
-       int txq_id;
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-               if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk))
-                       return txq_id;
-       return -1;
- }
- int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
- {
-       int sta_id;
-       int tx_fifo;
-       int txq_id;
-       int ret;
-       unsigned long flags;
-       struct iwl_tid_data *tid_data;
-       tx_fifo = get_fifo_from_tid(tid);
-       if (unlikely(tx_fifo < 0))
-               return tx_fifo;
-       IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
-                       __func__, ra, tid);
-       sta_id = iwl_find_station(priv, ra);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Start AGG on invalid station\n");
-               return -ENXIO;
-       }
-       if (unlikely(tid >= MAX_TID_COUNT))
-               return -EINVAL;
-       if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
-               IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
-               return -ENXIO;
-       }
-       txq_id = iwl_txq_ctx_activate_free(priv);
-       if (txq_id == -1) {
-               IWL_ERR(priv, "No free aggregation queue available\n");
-               return -ENXIO;
-       }
-       spin_lock_irqsave(&priv->sta_lock, flags);
-       tid_data = &priv->stations[sta_id].tid[tid];
-       *ssn = SEQ_TO_SN(tid_data->seq_number);
-       tid_data->agg.txq_id = txq_id;
-       priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id);
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-       ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo,
-                                                 sta_id, tid, *ssn);
-       if (ret)
-               return ret;
-       if (tid_data->tfds_in_queue == 0) {
-               IWL_DEBUG_HT(priv, "HW queue is empty\n");
-               tid_data->agg.state = IWL_AGG_ON;
-               ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid);
-       } else {
-               IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n",
-                            tid_data->tfds_in_queue);
-               tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
-       }
-       return ret;
- }
- EXPORT_SYMBOL(iwl_tx_agg_start);
- int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
- {
-       int tx_fifo_id, txq_id, sta_id, ssn = -1;
-       struct iwl_tid_data *tid_data;
-       int write_ptr, read_ptr;
-       unsigned long flags;
-       if (!ra) {
-               IWL_ERR(priv, "ra = NULL\n");
-               return -EINVAL;
-       }
-       tx_fifo_id = get_fifo_from_tid(tid);
-       if (unlikely(tx_fifo_id < 0))
-               return tx_fifo_id;
-       sta_id = iwl_find_station(priv, ra);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
-               return -ENXIO;
-       }
-       if (priv->stations[sta_id].tid[tid].agg.state ==
-                               IWL_EMPTYING_HW_QUEUE_ADDBA) {
-               IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
-               ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
-               priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
-               return 0;
-       }
-       if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON)
-               IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
-       tid_data = &priv->stations[sta_id].tid[tid];
-       ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
-       txq_id = tid_data->agg.txq_id;
-       write_ptr = priv->txq[txq_id].q.write_ptr;
-       read_ptr = priv->txq[txq_id].q.read_ptr;
-       /* The queue is not empty */
-       if (write_ptr != read_ptr) {
-               IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n");
-               priv->stations[sta_id].tid[tid].agg.state =
-                               IWL_EMPTYING_HW_QUEUE_DELBA;
-               return 0;
-       }
-       IWL_DEBUG_HT(priv, "HW queue is empty\n");
-       priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
-       spin_lock_irqsave(&priv->lock, flags);
-       /*
-        * the only reason this call can fail is queue number out of range,
-        * which can happen if uCode is reloaded and all the station
-        * information are lost. if it is outside the range, there is no need
-        * to deactivate the uCode queue, just return "success" to allow
-        *  mac80211 to clean up it own data.
-        */
-       priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
-                                                  tx_fifo_id);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
-       return 0;
- }
- EXPORT_SYMBOL(iwl_tx_agg_stop);
- int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id)
- {
-       struct iwl_queue *q = &priv->txq[txq_id].q;
-       u8 *addr = priv->stations[sta_id].sta.sta.addr;
-       struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
-       switch (priv->stations[sta_id].tid[tid].agg.state) {
-       case IWL_EMPTYING_HW_QUEUE_DELBA:
-               /* We are reclaiming the last packet of the */
-               /* aggregated HW queue */
-               if ((txq_id  == tid_data->agg.txq_id) &&
-                   (q->read_ptr == q->write_ptr)) {
-                       u16 ssn = SEQ_TO_SN(tid_data->seq_number);
-                       int tx_fifo = get_fifo_from_tid(tid);
-                       IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
-                       priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
-                                                            ssn, tx_fifo);
-                       tid_data->agg.state = IWL_AGG_OFF;
-                       ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid);
-               }
-               break;
-       case IWL_EMPTYING_HW_QUEUE_ADDBA:
-               /* We are reclaiming the last packet of the queue */
-               if (tid_data->tfds_in_queue == 0) {
-                       IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
-                       tid_data->agg.state = IWL_AGG_ON;
-                       ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid);
-               }
-               break;
-       }
-       return 0;
- }
- EXPORT_SYMBOL(iwl_txq_check_empty);
- /**
-  * iwl_tx_status_reply_compressed_ba - Update tx status from block-ack
-  *
-  * Go through block-ack's bitmap of ACK'd frames, update driver's record of
-  * ACK vs. not.  This gets sent to mac80211, then to rate scaling algo.
-  */
- static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
-                                struct iwl_ht_agg *agg,
-                                struct iwl_compressed_ba_resp *ba_resp)
- {
-       int i, sh, ack;
-       u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
-       u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
-       u64 bitmap;
-       int successes = 0;
-       struct ieee80211_tx_info *info;
-       if (unlikely(!agg->wait_for_ba))  {
-               IWL_ERR(priv, "Received BA when not expected\n");
-               return -EINVAL;
-       }
-       /* Mark that the expected block-ack response arrived */
-       agg->wait_for_ba = 0;
-       IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
-       /* Calculate shift to align block-ack bits with our Tx window bits */
-       sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4);
-       if (sh < 0) /* tbw something is wrong with indices */
-               sh += 0x100;
-       /* don't use 64-bit values for now */
-       bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
-       if (agg->frame_count > (64 - sh)) {
-               IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size");
-               return -1;
-       }
-       /* check for success or failure according to the
-        * transmitted bitmap and block-ack bitmap */
-       bitmap &= agg->bitmap;
-       /* For each frame attempted in aggregation,
-        * update driver's record of tx frame's status. */
-       for (i = 0; i < agg->frame_count ; i++) {
-               ack = bitmap & (1ULL << i);
-               successes += !!ack;
-               IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
-                       ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff,
-                       agg->start_idx + i);
-       }
-       info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]);
-       memset(&info->status, 0, sizeof(info->status));
-       info->flags |= IEEE80211_TX_STAT_ACK;
-       info->flags |= IEEE80211_TX_STAT_AMPDU;
-       info->status.ampdu_ack_map = successes;
-       info->status.ampdu_ack_len = agg->frame_count;
-       iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
-       IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap);
-       return 0;
- }
- /**
-  * iwl_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
-  *
-  * Handles block-acknowledge notification from device, which reports success
-  * of frames sent via aggregation.
-  */
- void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
-                                          struct iwl_rx_mem_buffer *rxb)
- {
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
-       struct iwl_tx_queue *txq = NULL;
-       struct iwl_ht_agg *agg;
-       int index;
-       int sta_id;
-       int tid;
-       /* "flow" corresponds to Tx queue */
-       u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
-       /* "ssn" is start of block-ack Tx window, corresponds to index
-        * (in Tx queue's circular buffer) of first TFD/frame in window */
-       u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
-       if (scd_flow >= priv->hw_params.max_txq_num) {
-               IWL_ERR(priv,
-                       "BUG_ON scd_flow is bigger than number of queues\n");
-               return;
-       }
-       txq = &priv->txq[scd_flow];
-       sta_id = ba_resp->sta_id;
-       tid = ba_resp->tid;
-       agg = &priv->stations[sta_id].tid[tid].agg;
-       /* Find index just before block-ack window */
-       index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
-       /* TODO: Need to get this copy more safely - now good for debug */
-       IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
-                          "sta_id = %d\n",
-                          agg->wait_for_ba,
-                          (u8 *) &ba_resp->sta_addr_lo32,
-                          ba_resp->sta_id);
-       IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
-                          "%d, scd_ssn = %d\n",
-                          ba_resp->tid,
-                          ba_resp->seq_ctl,
-                          (unsigned long long)le64_to_cpu(ba_resp->bitmap),
-                          ba_resp->scd_flow,
-                          ba_resp->scd_ssn);
-       IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx \n",
-                          agg->start_idx,
-                          (unsigned long long)agg->bitmap);
-       /* Update driver's record of ACK vs. not for each frame in window */
-       iwl_tx_status_reply_compressed_ba(priv, agg, ba_resp);
-       /* Release all TFDs before the SSN, i.e. all TFDs in front of
-        * block-ack window (we assume that they've been successfully
-        * transmitted ... if not, it's too late anyway). */
-       if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
-               /* calculate mac80211 ampdu sw queue to wake */
-               int freed = iwl_tx_queue_reclaim(priv, scd_flow, index);
-               iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
-               if ((iwl_queue_space(&txq->q) > txq->q.low_mark) &&
-                   priv->mac80211_registered &&
-                   (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
-                       iwl_wake_queue(priv, txq->swq_id);
-               iwl_txq_check_empty(priv, sta_id, tid, scd_flow);
-       }
- }
- EXPORT_SYMBOL(iwl_rx_reply_compressed_ba);
  #ifdef CONFIG_IWLWIFI_DEBUG
- #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
+ #define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
+ #define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
  
  const char *iwl_get_tx_fail_reason(u32 status)
  {
        switch (status & TX_STATUS_MSK) {
        case TX_STATUS_SUCCESS:
                return "SUCCESS";
-               TX_STATUS_ENTRY(SHORT_LIMIT);
-               TX_STATUS_ENTRY(LONG_LIMIT);
-               TX_STATUS_ENTRY(FIFO_UNDERRUN);
-               TX_STATUS_ENTRY(MGMNT_ABORT);
-               TX_STATUS_ENTRY(NEXT_FRAG);
-               TX_STATUS_ENTRY(LIFE_EXPIRE);
-               TX_STATUS_ENTRY(DEST_PS);
-               TX_STATUS_ENTRY(ABORTED);
-               TX_STATUS_ENTRY(BT_RETRY);
-               TX_STATUS_ENTRY(STA_INVALID);
-               TX_STATUS_ENTRY(FRAG_DROPPED);
-               TX_STATUS_ENTRY(TID_DISABLE);
-               TX_STATUS_ENTRY(FRAME_FLUSHED);
-               TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
-               TX_STATUS_ENTRY(TX_LOCKED);
-               TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
+               TX_STATUS_POSTPONE(DELAY);
+               TX_STATUS_POSTPONE(FEW_BYTES);
+               TX_STATUS_POSTPONE(BT_PRIO);
+               TX_STATUS_POSTPONE(QUIET_PERIOD);
+               TX_STATUS_POSTPONE(CALC_TTAK);
+               TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
+               TX_STATUS_FAIL(SHORT_LIMIT);
+               TX_STATUS_FAIL(LONG_LIMIT);
+               TX_STATUS_FAIL(FIFO_UNDERRUN);
+               TX_STATUS_FAIL(DRAIN_FLOW);
+               TX_STATUS_FAIL(RFKILL_FLUSH);
+               TX_STATUS_FAIL(LIFE_EXPIRE);
+               TX_STATUS_FAIL(DEST_PS);
+               TX_STATUS_FAIL(HOST_ABORTED);
+               TX_STATUS_FAIL(BT_RETRY);
+               TX_STATUS_FAIL(STA_INVALID);
+               TX_STATUS_FAIL(FRAG_DROPPED);
+               TX_STATUS_FAIL(TID_DISABLE);
+               TX_STATUS_FAIL(FIFO_FLUSHED);
+               TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
+               TX_STATUS_FAIL(FW_DROP);
+               TX_STATUS_FAIL(STA_COLOR_MISMATCH_DROP);
        }
  
        return "UNKNOWN";
index e0c05feb296c3cfdb9bc9a4727e162149d0004b5,24e969440b319f27892d46ea4567b7680e58f2f3..9f362024a29c1e336b7064a638e0578422817223
@@@ -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>
@@@ -598,9 -597,9 +598,9 @@@ static int iwl3945_tx_skb(struct iwl_pr
                txq->need_update = 0;
        }
  
-       IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
+       IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
                     le16_to_cpu(out_cmd->hdr.sequence));
-       IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags));
+       IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
        iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd));
        iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr,
                           ieee80211_hdrlen(fc));
@@@ -1604,9 -1603,6 +1604,6 @@@ static int iwl3945_print_last_event_log
        return pos;
  }
  
- /* For sanity check only.  Actual size is determined by uCode, typ. 512 */
- #define IWL3945_MAX_EVENT_LOG_SIZE (512)
  #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
  
  int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
        num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
        next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
  
-       if (capacity > IWL3945_MAX_EVENT_LOG_SIZE) {
+       if (capacity > priv->cfg->max_event_log_size) {
                IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
-                       capacity, IWL3945_MAX_EVENT_LOG_SIZE);
-               capacity = IWL3945_MAX_EVENT_LOG_SIZE;
+                       capacity, priv->cfg->max_event_log_size);
+               capacity = priv->cfg->max_event_log_size;
        }
  
-       if (next_entry > IWL3945_MAX_EVENT_LOG_SIZE) {
+       if (next_entry > priv->cfg->max_event_log_size) {
                IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
-                       next_entry, IWL3945_MAX_EVENT_LOG_SIZE);
-               next_entry = IWL3945_MAX_EVENT_LOG_SIZE;
+                       next_entry, priv->cfg->max_event_log_size);
+               next_entry = priv->cfg->max_event_log_size;
        }
  
        size = num_wraps ? capacity : next_entry;
@@@ -1938,7 -1934,7 +1935,7 @@@ static int iwl3945_get_channels_for_sca
                added++;
        }
  
-       IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added);
+       IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
        return added;
  }
  
@@@ -3141,8 -3137,6 +3138,6 @@@ void iwl3945_post_associate(struct iwl_
                break;
        }
  
-       iwl_activate_qos(priv, 0);
        /* we have just associated, don't start scan too early */
        priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
  }
@@@ -3404,7 -3398,7 +3399,7 @@@ static int iwl3945_mac_sta_add(struct i
        }
  
        /* Initialize rate scaling */
-       IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM \n",
+       IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
                       sta->addr);
        iwl3945_rs_rate_init(priv, sta, sta_id);
  
@@@ -3890,11 -3884,6 +3885,6 @@@ static int iwl3945_init_drv(struct iwl_
        priv->iw_mode = NL80211_IFTYPE_STATION;
        priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
  
-       iwl_reset_qos(priv);
-       priv->qos_data.qos_active = 0;
-       priv->qos_data.qos_cap.val = 0;
        priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
  
        if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
index a48ccaffb288a785c78c944953943cf5296eed9b,9c3c2f82f0334067e31a3b06327c36d4908e8c12..6f5b843c1f44cc0bccbb685bd66432266b66d29b
@@@ -4,7 -4,6 +4,7 @@@
  #include <linux/delay.h>
  #include <linux/mm.h>
  #include <linux/string.h>
 +#include <linux/slab.h>
  #include <net/iw_handler.h>
  #include <net/lib80211.h>
  
@@@ -75,7 -74,7 +75,7 @@@ static ssize_t lbs_getscantable(struct 
                return -ENOMEM;
  
        pos += snprintf(buf+pos, len-pos,
-               "# | ch  | rssi |       bssid       |   cap    | Qual | SSID \n");
+               "# | ch  | rssi |       bssid       |   cap    | Qual | SSID\n");
  
        mutex_lock(&priv->lock);
        list_for_each_entry (iter_bss, &priv->network_list, list) {
index 7d1a3c6b6ce0cd0f86b05d7a8959bafcf6d97feb,33206a98a5721edbb3b3e2265d01050e5da5ba1a..cd464a2589b9411bb9e07e8cbd153b8a6a2a2f7a
  
  #include <linux/kernel.h>
  #include <linux/moduleparam.h>
 +#include <linux/slab.h>
  #include <linux/firmware.h>
  #include <linux/netdevice.h>
  #include <linux/delay.h>
  #include <linux/mmc/card.h>
  #include <linux/mmc/sdio_func.h>
  #include <linux/mmc/sdio_ids.h>
+ #include <linux/mmc/sdio.h>
+ #include <linux/mmc/host.h>
  
  #include "host.h"
  #include "decl.h"
@@@ -943,6 -944,7 +945,7 @@@ static int if_sdio_probe(struct sdio_fu
        int ret, i;
        unsigned int model;
        struct if_sdio_packet *packet;
+       struct mmc_host *host = func->card->host;
  
        lbs_deb_enter(LBS_DEB_SDIO);
  
        if (ret)
                goto disable;
  
+       /* For 1-bit transfers to the 8686 model, we need to enable the
+        * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
+        * bit to allow access to non-vendor registers. */
+       if ((card->model == IF_SDIO_MODEL_8686) &&
+           (host->caps & MMC_CAP_SDIO_IRQ) &&
+           (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
+               u8 reg;
+               func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+               reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
+               if (ret)
+                       goto release_int;
+               reg |= SDIO_BUS_ECSI;
+               sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
+               if (ret)
+                       goto release_int;
+       }
        card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
        if (ret)
                goto release_int;
index 7cd5f56662fcfe1176deeeffc2a010b7ed843a3e,ec8b082917904f761f890819b463ef5e34def0ec..dfff02f5c86dd1985593add2f3bc202d7ab63c1a
@@@ -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>
@@@ -291,7 -290,8 +291,8 @@@ struct mac80211_hwsim_data 
        struct ieee80211_channel *channel;
        unsigned long beacon_int; /* in jiffies unit */
        unsigned int rx_filter;
-       bool started, idle;
+       bool started, idle, scanning;
+       struct mutex mutex;
        struct timer_list beacon_timer;
        enum ps_mode {
                PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL
@@@ -957,9 -957,9 +958,9 @@@ static int mac80211_hwsim_hw_scan(struc
        hsd->hw = hw;
        INIT_DELAYED_WORK(&hsd->w, hw_scan_done);
  
-       printk(KERN_DEBUG "hwsim scan request\n");
+       printk(KERN_DEBUG "hwsim hw_scan request\n");
        for (i = 0; i < req->n_channels; i++)
-               printk(KERN_DEBUG "hwsim scan freq %d\n",
+               printk(KERN_DEBUG "hwsim hw_scan freq %d\n",
                        req->channels[i]->center_freq);
  
        ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ);
        return 0;
  }
  
+ static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw)
+ {
+       struct mac80211_hwsim_data *hwsim = hw->priv;
+       mutex_lock(&hwsim->mutex);
+       if (hwsim->scanning) {
+               printk(KERN_DEBUG "two hwsim sw_scans detected!\n");
+               goto out;
+       }
+       printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n");
+       hwsim->scanning = true;
+ out:
+       mutex_unlock(&hwsim->mutex);
+ }
+ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw)
+ {
+       struct mac80211_hwsim_data *hwsim = hw->priv;
+       mutex_lock(&hwsim->mutex);
+       printk(KERN_DEBUG "hwsim sw_scan_complete\n");
+       hwsim->scanning = true;
+       mutex_unlock(&hwsim->mutex);
+ }
  static struct ieee80211_ops mac80211_hwsim_ops =
  {
        .tx = mac80211_hwsim_tx,
        .conf_tx = mac80211_hwsim_conf_tx,
        CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
        .ampdu_action = mac80211_hwsim_ampdu_action,
+       .sw_scan_start = mac80211_hwsim_sw_scan,
+       .sw_scan_complete = mac80211_hwsim_sw_scan_complete,
        .flush = mac80211_hwsim_flush,
  };
  
@@@ -1179,8 -1211,11 +1212,11 @@@ static int __init init_mac80211_hwsim(v
        if (radios < 1 || radios > 100)
                return -EINVAL;
  
-       if (fake_hw_scan)
+       if (fake_hw_scan) {
                mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan;
+               mac80211_hwsim_ops.sw_scan_start = NULL;
+               mac80211_hwsim_ops.sw_scan_complete = NULL;
+       }
  
        spin_lock_init(&hwsim_radio_lock);
        INIT_LIST_HEAD(&hwsim_radios);
                }
                /* By default all radios are belonging to the first group */
                data->group = 1;
+               mutex_init(&data->mutex);
  
                /* Work to be done prior to ieee80211_register_hw() */
                switch (regtest) {
index 269fda362836befbf3c95e4ccc576998d1ab9126,aa29663bf6c9f1c28429a1d47d0349a419ce53da..86f3e9ac4c7ac2edf5643b4c19767732d5582326
@@@ -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>
@@@ -132,7 -131,7 +132,7 @@@ static int p54p_upload_firmware(struct 
  
  static void p54p_refill_rx_ring(struct ieee80211_hw *dev,
        int ring_index, struct p54p_desc *ring, u32 ring_limit,
-       struct sk_buff **rx_buf)
+       struct sk_buff **rx_buf, u32 index)
  {
        struct p54p_priv *priv = dev->priv;
        struct p54p_ring_control *ring_control = priv->ring_control;
  
        idx = le32_to_cpu(ring_control->host_idx[ring_index]);
        limit = idx;
-       limit -= le32_to_cpu(ring_control->device_idx[ring_index]);
+       limit -= le32_to_cpu(index);
        limit = ring_limit - limit;
  
        i = idx % ring_limit;
@@@ -232,7 -231,7 +232,7 @@@ static void p54p_check_rx_ring(struct i
                i %= ring_limit;
        }
  
-       p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf);
+       p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf, *index);
  }
  
  static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
@@@ -277,14 -276,6 +277,6 @@@ static void p54p_tasklet(unsigned long 
        struct p54p_priv *priv = dev->priv;
        struct p54p_ring_control *ring_control = priv->ring_control;
  
-       p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt,
-                          ARRAY_SIZE(ring_control->tx_mgmt),
-                          priv->tx_buf_mgmt);
-       p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data,
-                          ARRAY_SIZE(ring_control->tx_data),
-                          priv->tx_buf_data);
        p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
                ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
  
  
        wmb();
        P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
+       p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt,
+                          ARRAY_SIZE(ring_control->tx_mgmt),
+                          priv->tx_buf_mgmt);
+       p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data,
+                          ARRAY_SIZE(ring_control->tx_data),
+                          priv->tx_buf_data);
  }
  
  static irqreturn_t p54p_interrupt(int irq, void *dev_id)
@@@ -445,10 -444,10 +445,10 @@@ static int p54p_open(struct ieee80211_h
        priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0;
  
        p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data,
-               ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data);
+               ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data, 0);
  
        p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt,
-               ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt);
+               ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt, 0);
  
        P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
        P54P_READ(ring_control_base);
index 689d59a13d5b295b0db107807ee9ef22a2131af0,7c82e432cca7383f7c2821a26c7f6fd7c6809c5b..10d91afefa331724bd5f6d81375a24b7a2aaec1f
@@@ -19,7 -19,6 +19,7 @@@
   */
  
  #include <linux/module.h>
 +#include <linux/slab.h>
  
  #include <linux/netdevice.h>
  #include <linux/ethtool.h>
@@@ -228,14 -227,14 +228,14 @@@ islpci_interrupt(int irq, void *config
  
  #if VERBOSE > SHOW_ERROR_MESSAGES
                DEBUG(SHOW_FUNCTION_CALLS,
-                     "IRQ: Identification register 0x%p 0x%x \n", device, reg);
+                     "IRQ: Identification register 0x%p 0x%x\n", device, reg);
  #endif
  
                /* check for each bit in the register separately */
                if (reg & ISL38XX_INT_IDENT_UPDATE) {
  #if VERBOSE > SHOW_ERROR_MESSAGES
                        /* Queue has been updated */
-                       DEBUG(SHOW_TRACING, "IRQ: Update flag \n");
+                       DEBUG(SHOW_TRACING, "IRQ: Update flag\n");
  
                        DEBUG(SHOW_QUEUE_INDEXES,
                              "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n",
                                                ISL38XX_CB_RX_DATA_LQ) != 0) {
  #if VERBOSE > SHOW_ERROR_MESSAGES
                                DEBUG(SHOW_TRACING,
-                                     "Received frame in Data Low Queue \n");
+                                     "Received frame in Data Low Queue\n");
  #endif
                                islpci_eth_receive(priv);
                        }
                        /* Device has been initialized */
  #if VERBOSE > SHOW_ERROR_MESSAGES
                        DEBUG(SHOW_TRACING,
-                             "IRQ: Init flag, device initialized \n");
+                             "IRQ: Init flag, device initialized\n");
  #endif
                        wake_up(&priv->reset_done);
                }
                if (reg & ISL38XX_INT_IDENT_SLEEP) {
                        /* Device intends to move to powersave state */
  #if VERBOSE > SHOW_ERROR_MESSAGES
-                       DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n");
+                       DEBUG(SHOW_TRACING, "IRQ: Sleep flag\n");
  #endif
                        isl38xx_handle_sleep_request(priv->control_block,
                                                     &powerstate,
                if (reg & ISL38XX_INT_IDENT_WAKEUP) {
                        /* Device has been woken up to active state */
  #if VERBOSE > SHOW_ERROR_MESSAGES
-                       DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n");
+                       DEBUG(SHOW_TRACING, "IRQ: Wakeup flag\n");
  #endif
  
                        isl38xx_handle_wakeup(priv->control_block,
@@@ -635,7 -634,7 +635,7 @@@ islpci_alloc_memory(islpci_private *pri
              ioremap(pci_resource_start(priv->pdev, 0),
                      ISL38XX_PCI_MEM_SIZE))) {
                /* error in remapping the PCI device memory address range */
-               printk(KERN_ERR "PCI memory remapping failed \n");
+               printk(KERN_ERR "PCI memory remapping failed\n");
                return -1;
        }
  
@@@ -902,7 -901,7 +902,7 @@@ islpci_setup(struct pci_dev *pdev
  
        if (register_netdev(ndev)) {
                DEBUG(SHOW_ERROR_MESSAGES,
-                     "ERROR: register_netdev() failed \n");
+                     "ERROR: register_netdev() failed\n");
                goto do_islpci_free_memory;
        }
  
index ac99eaaeabcee9831afdf5928271b6cc431e7d28,af9e7fbd7640aac9b643416c00ef3df0a3e91af4..64585da8a96c953a99ca23d13cd4f19d3c6a5123
@@@ -17,7 -17,6 +17,7 @@@
   */
  
  #include <linux/module.h>
 +#include <linux/gfp.h>
  
  #include <linux/pci.h>
  #include <linux/delay.h>
@@@ -90,7 -89,7 +90,7 @@@ islpci_eth_transmit(struct sk_buff *skb
        u32 curr_frag;
  
  #if VERBOSE > SHOW_ERROR_MESSAGES
-       DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n");
+       DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit\n");
  #endif
  
        /* lock the driver code */
                        }
  
  #if VERBOSE > SHOW_ERROR_MESSAGES
-                       DEBUG(SHOW_TRACING, "memmove %p %p %i \n", skb->data,
+                       DEBUG(SHOW_TRACING, "memmove %p %p %i\n", skb->data,
                              src, skb->len);
  #endif
                } else {
@@@ -320,7 -319,7 +320,7 @@@ islpci_eth_receive(islpci_private *priv
        int discard = 0;
  
  #if VERBOSE > SHOW_ERROR_MESSAGES
-       DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive \n");
+       DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive\n");
  #endif
  
        /* the device has written an Ethernet frame in the data area
                skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2);
                if (unlikely(skb == NULL)) {
                        /* error allocating an sk_buff structure elements */
-                       DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n");
+                       DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb\n");
                        break;
                }
                skb_reserve(skb, (4 - (long) skb->data) & 0x03);
index adb289723a967e5fe474332e1c256b7aa94649ad,89b0278eb7e8794266ba39b98486ed995f411fe3..a5224f6160e4b8f913ba3150a1891c1beb0e7d15
@@@ -21,7 -21,6 +21,7 @@@
  #include <linux/module.h>
  #include <linux/pci.h>
  #include <linux/sched.h>
 +#include <linux/slab.h>
  
  #include <asm/io.h>
  #include <asm/system.h>
@@@ -114,7 -113,7 +114,7 @@@ islpci_mgmt_rx_fill(struct net_device *
        u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]);
  
  #if VERBOSE > SHOW_ERROR_MESSAGES
-       DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill \n");
+       DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill\n");
  #endif
  
        while (curr - priv->index_mgmt_rx < ISL38XX_CB_MGMT_QSIZE) {
@@@ -212,7 -211,7 +212,7 @@@ islpci_mgt_transmit(struct net_device *
        {
                pimfor_header_t *h = buf.mem;
                DEBUG(SHOW_PIMFOR_FRAMES,
-                     "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x \n",
+                     "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x\n",
                      h->operation, oid, h->device_id, h->flags, length);
  
                /* display the buffer contents for debugging */
@@@ -280,7 -279,7 +280,7 @@@ islpci_mgt_receive(struct net_device *n
        u32 curr_frag;
  
  #if VERBOSE > SHOW_ERROR_MESSAGES
-       DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n");
+       DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive\n");
  #endif
  
        /* Only once per interrupt, determine fragment range to
  
  #if VERBOSE > SHOW_ERROR_MESSAGES
                DEBUG(SHOW_PIMFOR_FRAMES,
-                     "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n",
+                     "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x\n",
                      header->operation, header->oid, header->device_id,
                      header->flags, header->length);
  
index d66933d70fb9cac31c0ce007e05de592dcabca99,07df70a100711505a92ab5129bd08a2376803c59..9b796cae4afe8436ee04556d0227d8b57d021ff7
@@@ -17,7 -17,6 +17,7 @@@
   */
  
  #include <linux/kernel.h>
 +#include <linux/slab.h>
  
  #include "prismcompat.h"
  #include "islpci_dev.h"
@@@ -820,7 -819,7 +820,7 @@@ mgt_response_to_str(enum oid_num_t n, u
                        k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr);
                        for (i = 0; i < list->nr; i++)
                                k += snprintf(str + k, PRIV_STR_SIZE - k,
-                                             "bss[%u] : \nage=%u\nchannel=%u\n"
+                                             "bss[%u] :\nage=%u\nchannel=%u\n"
                                              "capinfo=0x%X\nrates=0x%X\n"
                                              "basic_rates=0x%X\n",
                                              i, list->bsslist[i].age,
index 2940d7d3775e7544fd123e4f0b07f22e436216de,f1e916a3166861620406813896bc87d83935275f..d9c45bfcee611f7961eaa8bd8e8fb0aa21c75896
@@@ -35,6 -35,7 +35,6 @@@
  #include <linux/proc_fs.h>
  #include <linux/ptrace.h>
  #include <linux/seq_file.h>
 -#include <linux/slab.h>
  #include <linux/string.h>
  #include <linux/timer.h>
  #include <linux/init.h>
@@@ -555,7 -556,7 +555,7 @@@ static int ray_init(struct net_device *
        local->fw_ver = local->startup_res.firmware_version[0];
        local->fw_bld = local->startup_res.firmware_version[1];
        local->fw_var = local->startup_res.firmware_version[2];
-       dev_dbg(&link->dev, "ray_init firmware version %d.%d \n", local->fw_ver,
+       dev_dbg(&link->dev, "ray_init firmware version %d.%d\n", local->fw_ver,
              local->fw_bld);
  
        local->tib_length = 0x20;
@@@ -1874,17 -1875,17 +1874,17 @@@ static void ray_update_multi_list(struc
                writeb(0xff, &pccs->var);
                local->num_multi = 0xff;
        } else {
 -              struct dev_mc_list *dmi;
 +              struct netdev_hw_addr *ha;
                int i = 0;
  
                /* Copy the kernel's list of MC addresses to card */
 -              netdev_for_each_mc_addr(dmi, dev) {
 -                      memcpy_toio(p, dmi->dmi_addr, ETH_ALEN);
 +              netdev_for_each_mc_addr(ha, dev) {
 +                      memcpy_toio(p, ha->addr, ETH_ALEN);
                        dev_dbg(&link->dev,
                              "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n",
 -                            dmi->dmi_addr[0], dmi->dmi_addr[1],
 -                            dmi->dmi_addr[2], dmi->dmi_addr[3],
 -                            dmi->dmi_addr[4], dmi->dmi_addr[5]);
 +                            ha->addr[0], ha->addr[1],
 +                            ha->addr[2], ha->addr[3],
 +                            ha->addr[4], ha->addr[5]);
                        p += ETH_ALEN;
                        i++;
                }
@@@ -2233,7 -2234,7 +2233,7 @@@ static void rx_data(struct net_device *
                            (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN +
                             FCS_LEN)) {
                                pr_debug(
-                                     "ray_cs invalid packet length %d received \n",
+                                     "ray_cs invalid packet length %d received\n",
                                      rx_len);
                                return;
                        }
                            (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN +
                             FCS_LEN)) {
                                pr_debug(
-                                     "ray_cs invalid packet length %d received \n",
+                                     "ray_cs invalid packet length %d received\n",
                                      rx_len);
                                return;
                        }
@@@ -2752,11 -2753,11 +2752,11 @@@ static int ray_cs_proc_show(struct seq_
                        seq_printf(m, "Hop dwell            = %d Kus\n",
                                   pfh->dwell_time[0] +
                                   256 * pfh->dwell_time[1]);
-                       seq_printf(m, "Hop set              = %d \n",
+                       seq_printf(m, "Hop set              = %d\n",
                                   pfh->hop_set);
-                       seq_printf(m, "Hop pattern          = %d \n",
+                       seq_printf(m, "Hop pattern          = %d\n",
                                   pfh->hop_pattern);
-                       seq_printf(m, "Hop index            = %d \n",
+                       seq_printf(m, "Hop index            = %d\n",
                                   pfh->hop_index);
                        p += p[1] + 2;
                } else {
index 5f5204b8289178941f579ea81319230ced397e77,08a4789fc2d82e3f91447f048e14df48d8fcfc6f..cdbf59108ef9bd878d16ccb0b613ab9a80152745
@@@ -31,7 -31,6 +31,7 @@@
  #include <linux/module.h>
  #include <linux/pci.h>
  #include <linux/eeprom_93cx6.h>
 +#include <linux/slab.h>
  
  #include "rt2x00.h"
  #include "rt2x00pci.h"
@@@ -526,6 -525,10 +526,10 @@@ static void rt2400pci_config_ps(struct 
  
                rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
                rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+       } else {
+               rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
+               rt2x00pci_register_write(rt2x00dev, CSR20, reg);
        }
  
        rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
index 2a73f593aab0cb82ef4bdaa1e949b82cd7e7d4a2,d084d70e5fe2617423a098175878f147adfb0ce0..89e986f449da51f091e806d6b87107ae7f2bdc48
@@@ -31,7 -31,6 +31,7 @@@
  #include <linux/module.h>
  #include <linux/pci.h>
  #include <linux/eeprom_93cx6.h>
 +#include <linux/slab.h>
  
  #include "rt2x00.h"
  #include "rt2x00pci.h"
@@@ -574,6 -573,10 +574,10 @@@ static void rt2500pci_config_ps(struct 
  
                rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
                rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+       } else {
+               rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
+               rt2x00pci_register_write(rt2x00dev, CSR20, reg);
        }
  
        rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
index 8ebb705fe106f6c6403bcc953c6e04d18a9403dd,c1eec17fe186d1c2451c5fab73a66cb83e705388..7185cb05f257f2ef127284aec0da1087853938bc
@@@ -29,7 -29,6 +29,7 @@@
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
 +#include <linux/slab.h>
  #include <linux/usb.h>
  
  #include "rt2x00.h"
@@@ -369,7 -368,7 +369,7 @@@ static int rt2500usb_config_key(struct 
  
                /*
                 * The encryption key doesn't fit within the CSR cache,
 -               * this means we should allocate it seperately and use
 +               * this means we should allocate it separately and use
                 * rt2x00usb_vendor_request() to send the key to the hardware.
                 */
                reg = KEY_ENTRY(key->hw_key_idx);
                /*
                 * The driver does not support the IV/EIV generation
                 * in hardware. However it demands the data to be provided
 -               * both seperately as well as inside the frame.
 +               * both separately as well as inside the frame.
                 * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib
                 * to ensure rt2x00lib will not strip the data from the
                 * frame after the copy, now we must tell mac80211
@@@ -649,6 -648,10 +649,10 @@@ static void rt2500usb_config_ps(struct 
  
                rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 1);
                rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
+       } else {
+               rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+               rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
+               rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
        }
  
        rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
@@@ -1643,11 -1646,6 +1647,6 @@@ static int rt2500usb_probe_hw_mode(stru
        char *tx_power;
        unsigned int i;
  
-       /*
-        * Disable powersaving as default.
-        */
-       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
        /*
         * Initialize all hw fields.
         */
index c015ce9fdd09925da8e46dff2495c9d69e24d7a8,638600092f19f8414e2243c477b727b6ca66980c..2648f315a93420b2a78acbede1d673a6c963d9e4
@@@ -35,7 -35,6 +35,7 @@@
  
  #include <linux/kernel.h>
  #include <linux/module.h>
 +#include <linux/slab.h>
  
  #include "rt2x00.h"
  #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)
@@@ -360,11 -359,6 +360,6 @@@ static int rt2800_blink_set(struct led_
        rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
        rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, *delay_on);
        rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off);
-       rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
-       rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
-       rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 3);
-       rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
-       rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
        rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
  
        return 0;
@@@ -610,10 -604,6 +605,6 @@@ void rt2800_config_erp(struct rt2x00_de
  {
        u32 reg;
  
-       rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
-       rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20);
-       rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
        rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
        rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
                           !!erp->short_preamble);
  
        rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
        rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time);
-       rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
        rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
  
        rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
        rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs);
        rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs);
-       rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
        rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
-       rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
        rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
  
        rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
@@@ -718,10 -705,10 +706,10 @@@ static void rt2800_config_lna_gain(stru
        rt2x00dev->lna_gain = lna_gain;
  }
  
- static void rt2800_config_channel_rt2x(struct rt2x00_dev *rt2x00dev,
-                                      struct ieee80211_conf *conf,
-                                      struct rf_channel *rf,
-                                      struct channel_info *info)
+ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
  {
        rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
  
        rt2800_rf_write(rt2x00dev, 4, rf->rf4);
  }
  
- static void rt2800_config_channel_rt3x(struct rt2x00_dev *rt2x00dev,
-                                      struct ieee80211_conf *conf,
-                                      struct rf_channel *rf,
-                                      struct channel_info *info)
+ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
  {
        u8 rfcsr;
  
        rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
  
        rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2);
+       rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
        rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
  
        rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
@@@ -827,15 -814,13 +815,13 @@@ static void rt2800_config_channel(struc
        unsigned int tx_pin;
        u8 bbp;
  
-       if ((rt2x00_rt(rt2x00dev, RT3070) ||
-            rt2x00_rt(rt2x00dev, RT3090)) &&
-           (rt2x00_rf(rt2x00dev, RF2020) ||
-            rt2x00_rf(rt2x00dev, RF3020) ||
-            rt2x00_rf(rt2x00dev, RF3021) ||
-            rt2x00_rf(rt2x00dev, RF3022)))
-               rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info);
+       if (rt2x00_rf(rt2x00dev, RF2020) ||
+           rt2x00_rf(rt2x00dev, RF3020) ||
+           rt2x00_rf(rt2x00dev, RF3021) ||
+           rt2x00_rf(rt2x00dev, RF3022))
+               rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
        else
-               rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info);
+               rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
  
        /*
         * Change BBP settings
        rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
        rt2800_bbp_write(rt2x00dev, 3, bbp);
  
-       if (rt2x00_rt(rt2x00dev, RT2860) &&
-           (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) {
+       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
                if (conf_is_ht40(conf)) {
                        rt2800_bbp_write(rt2x00dev, 69, 0x1a);
                        rt2800_bbp_write(rt2x00dev, 70, 0x0a);
@@@ -988,10 -972,6 +973,6 @@@ static void rt2800_config_retry_limit(s
                           libconf->conf->short_frame_max_tx_count);
        rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT,
                           libconf->conf->long_frame_max_tx_count);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_AGG_RTY_MODE, 0);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
        rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
  }
  
@@@ -1015,13 -995,13 +996,13 @@@ static void rt2800_config_ps(struct rt2
  
                rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
        } else {
-               rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
                rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
                rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
                rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
                rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
                rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
+               rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
        }
  }
  
@@@ -1062,9 -1042,10 +1043,10 @@@ EXPORT_SYMBOL_GPL(rt2800_link_stats)
  static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
  {
        if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
-               if (rt2x00_is_usb(rt2x00dev) &&
-                   rt2x00_rt(rt2x00dev, RT3070) &&
-                   (rt2x00_rev(rt2x00dev) == RT3070_VERSION))
+               if (rt2x00_rt(rt2x00dev, RT3070) ||
+                   rt2x00_rt(rt2x00dev, RT3071) ||
+                   rt2x00_rt(rt2x00dev, RT3090) ||
+                   rt2x00_rt(rt2x00dev, RT3390))
                        return 0x1c + (2 * rt2x00dev->lna_gain);
                else
                        return 0x2e + rt2x00dev->lna_gain;
@@@ -1095,8 -1076,7 +1077,7 @@@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner)
  void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
                       const u32 count)
  {
-       if (rt2x00_rt(rt2x00dev, RT2860) &&
-           (rt2x00_rev(rt2x00dev) == RT2860C_VERSION))
+       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C))
                return;
  
        /*
@@@ -1114,8 -1094,17 +1095,17 @@@ EXPORT_SYMBOL_GPL(rt2800_link_tuner)
  int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
  {
        u32 reg;
+       u16 eeprom;
        unsigned int i;
  
+       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
+       rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
        if (rt2x00_is_usb(rt2x00dev)) {
                /*
                 * Wait until BBP and RF are ready.
                rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
                rt2800_register_write(rt2x00dev, PBF_SYS_CTRL,
                                      reg & ~0x00002000);
-       } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
+       } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) {
+               /*
+                * Reset DMA indexes
+                */
+               rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+               rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
+               rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
+               rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
+               rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, 1);
+               rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
+               rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
+               rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
+               rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+               rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+               rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
                rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+       }
  
        rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
        rt2x00_set_field32(&reg, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0);
        rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
  
-       if (rt2x00_is_usb(rt2x00dev) &&
-           rt2x00_rt(rt2x00dev, RT3070) &&
-           (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) {
+       rt2800_config_filter(rt2x00dev, FIF_ALLMULTI);
+       rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+       rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, 9);
+       rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
+       rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
+       if (rt2x00_rt(rt2x00dev, RT3071) ||
+           rt2x00_rt(rt2x00dev, RT3090) ||
+           rt2x00_rt(rt2x00dev, RT3390)) {
                rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
                rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+               if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+                   rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
+                   rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
+                       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+                       if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST))
+                               rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+                                                     0x0000002c);
+                       else
+                               rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+                                                     0x0000000f);
+               } else {
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+               }
+               rt2800_register_write(rt2x00dev, TX_SW_CFG2, reg);
+       } else if (rt2x00_rt(rt2x00dev, RT3070)) {
+               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+               if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000002c);
+               } else {
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+               }
        } else {
                rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
                rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
  
        rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
        rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
+       rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 32);
        rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
        rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
  
        rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
        rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
-       if ((rt2x00_rt(rt2x00dev, RT2872) &&
-            (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION)) ||
-           rt2x00_rt(rt2x00dev, RT2880) ||
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
            rt2x00_rt(rt2x00dev, RT2883) ||
-           rt2x00_rt(rt2x00dev, RT2890) ||
-           rt2x00_rt(rt2x00dev, RT3052) ||
-           (rt2x00_rt(rt2x00dev, RT3070) &&
-            (rt2x00_rev(rt2x00dev) < RT3070_VERSION)))
+           rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E))
                rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
        else
                rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
        rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 0);
        rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);
  
+       rt2800_register_read(rt2x00dev, LED_CFG, &reg);
+       rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, 70);
+       rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, 30);
+       rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
+       rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
+       rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 3);
+       rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
+       rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
+       rt2800_register_write(rt2x00dev, LED_CFG, reg);
        rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
  
+       rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT, 15);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT, 31);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_AGG_RTY_MODE, 0);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
+       rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
        rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
        rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
+       rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY, 1);
        rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 0);
        rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MREF, 0);
+       rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE, 1);
        rt2x00_set_field32(&reg, AUTO_RSP_CFG_DUAL_CTS_EN, 0);
        rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
        rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
  
        rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 8);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 3);
        rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
        rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV, 1);
        rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);
        rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
        rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0);
        rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, 1);
        rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
  
        rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 8);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 3);
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV, 1);
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0);
        rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, 1);
        rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
  
        rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
        rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
        rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
        rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, 0);
        rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
  
        rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 0);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL,
+                          !rt2x00_is_usb(rt2x00dev));
        rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV, 1);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
        rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, 0);
        rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
  
        rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
        rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
        rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
        rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, 0);
        rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
  
        rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
        rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
        rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
        rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, 0);
        rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
  
        if (rt2x00_is_usb(rt2x00dev)) {
        rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);
  
        rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca);
+       rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+       rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, 32);
+       rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, 32);
+       rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
+       rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, 314);
+       rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
+       rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
        rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
  
        /*
@@@ -1483,38 -1552,67 +1553,67 @@@ int rt2800_init_bbp(struct rt2x00_dev *
  
        rt2800_bbp_write(rt2x00dev, 65, 0x2c);
        rt2800_bbp_write(rt2x00dev, 66, 0x38);
-       rt2800_bbp_write(rt2x00dev, 69, 0x12);
+       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
+               rt2800_bbp_write(rt2x00dev, 69, 0x16);
+               rt2800_bbp_write(rt2x00dev, 73, 0x12);
+       } else {
+               rt2800_bbp_write(rt2x00dev, 69, 0x12);
+               rt2800_bbp_write(rt2x00dev, 73, 0x10);
+       }
        rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-       rt2800_bbp_write(rt2x00dev, 73, 0x10);
-       rt2800_bbp_write(rt2x00dev, 81, 0x37);
+       if (rt2x00_rt(rt2x00dev, RT3070) ||
+           rt2x00_rt(rt2x00dev, RT3071) ||
+           rt2x00_rt(rt2x00dev, RT3090) ||
+           rt2x00_rt(rt2x00dev, RT3390)) {
+               rt2800_bbp_write(rt2x00dev, 79, 0x13);
+               rt2800_bbp_write(rt2x00dev, 80, 0x05);
+               rt2800_bbp_write(rt2x00dev, 81, 0x33);
+       } else {
+               rt2800_bbp_write(rt2x00dev, 81, 0x37);
+       }
        rt2800_bbp_write(rt2x00dev, 82, 0x62);
        rt2800_bbp_write(rt2x00dev, 83, 0x6a);
-       rt2800_bbp_write(rt2x00dev, 84, 0x99);
+       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D) ||
+           rt2x00_rt_rev(rt2x00dev, RT2870, REV_RT2870D))
+               rt2800_bbp_write(rt2x00dev, 84, 0x19);
+       else
+               rt2800_bbp_write(rt2x00dev, 84, 0x99);
        rt2800_bbp_write(rt2x00dev, 86, 0x00);
        rt2800_bbp_write(rt2x00dev, 91, 0x04);
        rt2800_bbp_write(rt2x00dev, 92, 0x00);
-       rt2800_bbp_write(rt2x00dev, 103, 0x00);
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||
+           rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
+           rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
+           rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E))
+               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+       else
+               rt2800_bbp_write(rt2x00dev, 103, 0x00);
        rt2800_bbp_write(rt2x00dev, 105, 0x05);
+       rt2800_bbp_write(rt2x00dev, 106, 0x35);
  
-       if (rt2x00_rt(rt2x00dev, RT2860) &&
-           (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) {
-               rt2800_bbp_write(rt2x00dev, 69, 0x16);
-               rt2800_bbp_write(rt2x00dev, 73, 0x12);
-       }
+       if (rt2x00_rt(rt2x00dev, RT3071) ||
+           rt2x00_rt(rt2x00dev, RT3090) ||
+           rt2x00_rt(rt2x00dev, RT3390)) {
+               rt2800_bbp_read(rt2x00dev, 138, &value);
  
-       if (rt2x00_rt(rt2x00dev, RT2860) &&
-           (rt2x00_rev(rt2x00dev) > RT2860D_VERSION))
-               rt2800_bbp_write(rt2x00dev, 84, 0x19);
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+               if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1)
+                       value |= 0x20;
+               if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1)
+                       value &= ~0x02;
  
-       if (rt2x00_is_usb(rt2x00dev) &&
-           rt2x00_rt(rt2x00dev, RT3070) &&
-           (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) {
-               rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-               rt2800_bbp_write(rt2x00dev, 84, 0x99);
-               rt2800_bbp_write(rt2x00dev, 105, 0x05);
+               rt2800_bbp_write(rt2x00dev, 138, value);
        }
  
-       if (rt2x00_rt(rt2x00dev, RT3052)) {
+       if (rt2x00_rt(rt2x00dev, RT2872)) {
                rt2800_bbp_write(rt2x00dev, 31, 0x08);
                rt2800_bbp_write(rt2x00dev, 78, 0x0e);
                rt2800_bbp_write(rt2x00dev, 80, 0x08);
@@@ -1598,19 -1696,15 +1697,15 @@@ int rt2800_init_rfcsr(struct rt2x00_de
  {
        u8 rfcsr;
        u8 bbp;
+       u32 reg;
+       u16 eeprom;
  
-       if (rt2x00_is_usb(rt2x00dev) &&
-           rt2x00_rt(rt2x00dev, RT3070) &&
-           (rt2x00_rev(rt2x00dev) != RT3070_VERSION))
+       if (!rt2x00_rt(rt2x00dev, RT3070) &&
+           !rt2x00_rt(rt2x00dev, RT3071) &&
+           !rt2x00_rt(rt2x00dev, RT3090) &&
+           !rt2x00_rt(rt2x00dev, RT3390))
                return 0;
  
-       if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) {
-               if (!rt2x00_rf(rt2x00dev, RF3020) &&
-                   !rt2x00_rf(rt2x00dev, RF3021) &&
-                   !rt2x00_rf(rt2x00dev, RF3022))
-                       return 0;
-       }
        /*
         * Init RF calibration.
         */
        rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
        rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
  
-       if (rt2x00_is_usb(rt2x00dev)) {
+       if (rt2x00_rt(rt2x00dev, RT3070) ||
+           rt2x00_rt(rt2x00dev, RT3071) ||
+           rt2x00_rt(rt2x00dev, RT3090)) {
                rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
                rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
                rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
                rt2800_rfcsr_write(rt2x00dev, 7, 0x70);
                rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
-               rt2800_rfcsr_write(rt2x00dev, 10, 0x71);
+               rt2800_rfcsr_write(rt2x00dev, 10, 0x41);
                rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
                rt2800_rfcsr_write(rt2x00dev, 12, 0x7b);
                rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
                rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
                rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
                rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
-               rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
                rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
-       } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) {
-               rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
-               rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
-               rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);
-               rt2800_rfcsr_write(rt2x00dev, 3, 0x75);
+       } else if (rt2x00_rt(rt2x00dev, RT3390)) {
+               rt2800_rfcsr_write(rt2x00dev, 0, 0xa0);
+               rt2800_rfcsr_write(rt2x00dev, 1, 0xe1);
+               rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
+               rt2800_rfcsr_write(rt2x00dev, 3, 0x62);
                rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
-               rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
-               rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
-               rt2800_rfcsr_write(rt2x00dev, 7, 0x50);
-               rt2800_rfcsr_write(rt2x00dev, 8, 0x39);
-               rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
-               rt2800_rfcsr_write(rt2x00dev, 10, 0x60);
+               rt2800_rfcsr_write(rt2x00dev, 5, 0x8b);
+               rt2800_rfcsr_write(rt2x00dev, 6, 0x42);
+               rt2800_rfcsr_write(rt2x00dev, 7, 0x34);
+               rt2800_rfcsr_write(rt2x00dev, 8, 0x00);
+               rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);
+               rt2800_rfcsr_write(rt2x00dev, 10, 0x61);
                rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
-               rt2800_rfcsr_write(rt2x00dev, 12, 0x75);
-               rt2800_rfcsr_write(rt2x00dev, 13, 0x75);
+               rt2800_rfcsr_write(rt2x00dev, 12, 0x3b);
+               rt2800_rfcsr_write(rt2x00dev, 13, 0xe0);
                rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
-               rt2800_rfcsr_write(rt2x00dev, 15, 0x58);
-               rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);
-               rt2800_rfcsr_write(rt2x00dev, 17, 0x92);
-               rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);
-               rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
-               rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
-               rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
+               rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+               rt2800_rfcsr_write(rt2x00dev, 16, 0xe0);
+               rt2800_rfcsr_write(rt2x00dev, 17, 0x94);
+               rt2800_rfcsr_write(rt2x00dev, 18, 0x5c);
+               rt2800_rfcsr_write(rt2x00dev, 19, 0x4a);
+               rt2800_rfcsr_write(rt2x00dev, 20, 0xb2);
+               rt2800_rfcsr_write(rt2x00dev, 21, 0xf6);
                rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
-               rt2800_rfcsr_write(rt2x00dev, 23, 0x31);
+               rt2800_rfcsr_write(rt2x00dev, 23, 0x14);
                rt2800_rfcsr_write(rt2x00dev, 24, 0x08);
-               rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
-               rt2800_rfcsr_write(rt2x00dev, 26, 0x25);
-               rt2800_rfcsr_write(rt2x00dev, 27, 0x23);
-               rt2800_rfcsr_write(rt2x00dev, 28, 0x13);
-               rt2800_rfcsr_write(rt2x00dev, 29, 0x83);
+               rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);
+               rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+               rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+               rt2800_rfcsr_write(rt2x00dev, 28, 0x41);
+               rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
+               rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
+               rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
+       }
+       if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
+               rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+               rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+               rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+       } else if (rt2x00_rt(rt2x00dev, RT3071) ||
+                  rt2x00_rt(rt2x00dev, RT3090)) {
+               rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+               rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+               rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
+               rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+               rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+               if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+                   rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {
+                       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+                       if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST))
+                               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+                       else
+                               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
+               }
+               rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+       } else if (rt2x00_rt(rt2x00dev, RT3390)) {
+               rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+               rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
+               rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
        }
  
        /*
         * Set RX Filter calibration for 20MHz and 40MHz
         */
-       rt2x00dev->calibration[0] =
-           rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16);
-       rt2x00dev->calibration[1] =
-           rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
+       if (rt2x00_rt(rt2x00dev, RT3070)) {
+               rt2x00dev->calibration[0] =
+                       rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16);
+               rt2x00dev->calibration[1] =
+                       rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
+       } else if (rt2x00_rt(rt2x00dev, RT3071) ||
+                  rt2x00_rt(rt2x00dev, RT3090) ||
+                  rt2x00_rt(rt2x00dev, RT3390)) {
+               rt2x00dev->calibration[0] =
+                       rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13);
+               rt2x00dev->calibration[1] =
+                       rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15);
+       }
  
        /*
         * Set back to initial state
        rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
        rt2800_bbp_write(rt2x00dev, 4, bbp);
  
+       if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E))
+               rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+       rt2800_register_read(rt2x00dev, OPT_14_CSR, &reg);
+       rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
+       rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
+       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
+       if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+               if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
+                       rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
+       }
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom);
+       if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1)
+               rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
+                                 rt2x00_get_field16(eeprom,
+                                                  EEPROM_TXMIXER_GAIN_BG_VAL));
+       rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+       if (rt2x00_rt(rt2x00dev, RT3090)) {
+               rt2800_bbp_read(rt2x00dev, 138, &bbp);
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+               if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1)
+                       rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
+               if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1)
+                       rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1);
+               rt2800_bbp_write(rt2x00dev, 138, bbp);
+       }
+       if (rt2x00_rt(rt2x00dev, RT3071) ||
+           rt2x00_rt(rt2x00dev, RT3090) ||
+           rt2x00_rt(rt2x00dev, RT3390)) {
+               rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+               rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+               rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0);
+               rt2800_rfcsr_write(rt2x00dev, 15, rfcsr);
+               rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0);
+               rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
+               rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);
+               rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
+       }
+       if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071)) {
+               rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
+               if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
+                   rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E))
+                       rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
+               else
+                       rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0);
+               rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
+       }
        return 0;
  }
  EXPORT_SYMBOL_GPL(rt2800_init_rfcsr);
@@@ -1775,9 -1986,7 +1987,7 @@@ int rt2800_validate_eeprom(struct rt2x0
        } else if (rt2x00_rt(rt2x00dev, RT2860) ||
                   rt2x00_rt(rt2x00dev, RT2870) ||
                   rt2x00_rt(rt2x00dev, RT2872) ||
-                  rt2x00_rt(rt2x00dev, RT2880) ||
-                  (rt2x00_rt(rt2x00dev, RT2883) &&
-                   (rt2x00_rev(rt2x00dev) < RT2883_VERSION))) {
+                  rt2x00_rt(rt2x00dev, RT2872)) {
                /*
                 * There is a max of 2 RX streams for RT28x0 series
                 */
@@@ -1882,10 -2091,7 +2092,7 @@@ int rt2800_init_eeprom(struct rt2x00_de
        if (!rt2x00_rt(rt2x00dev, RT2860) &&
            !rt2x00_rt(rt2x00dev, RT2870) &&
            !rt2x00_rt(rt2x00dev, RT2872) &&
-           !rt2x00_rt(rt2x00dev, RT2880) &&
            !rt2x00_rt(rt2x00dev, RT2883) &&
-           !rt2x00_rt(rt2x00dev, RT2890) &&
-           !rt2x00_rt(rt2x00dev, RT3052) &&
            !rt2x00_rt(rt2x00dev, RT3070) &&
            !rt2x00_rt(rt2x00dev, RT3071) &&
            !rt2x00_rt(rt2x00dev, RT3090) &&
index d27d7d5d850cc6ea7c63b85f29da3c010c9d6c37,4c12f2ffe223ed29fcce60d741fdd2e7cfac11ea..6b809ab42c618e253a1b12c5baa6471627c06dc8
@@@ -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))
@@@ -876,6 -876,8 +876,8 @@@ static struct usb_device_id rt2800usb_d
        { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* SMC */
        { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* AirTies */
        { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
+       /* ASUS */
+       { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* AzureWave */
        { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Conceptronic */
        { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Corega */
        { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) },
+       /* Draytek */
+       { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Edimax */
        { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Encore */
        { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* EnGenius */
        { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Gigabyte */
        { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* I-O DATA */
        { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) },
+       /* Logitec */
+       { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* MSI */
        { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) },
+       /* Para */
+       { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Pegatron */
        { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Sitecom */
        { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* SMC */
        { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Zinwell */
        { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Sitecom */
        { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Zinwell */
        { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) },
  #endif
        /* Amigo */
        { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
-       /* Askey */
-       { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* ASUS */
        { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* AzureWave */
        { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Belkin */
        { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Buffalo */
        { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Encore */
        { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) },
-       /* EnGenius */
-       { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Gemtek */
        { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Gigabyte */
        /* Hawking */
        { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
-       /* I-O DATA */
-       { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* LevelOne */
        { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Motorola */
        { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
-       /* MSI */
-       { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Ovislink */
        { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
-       /* Para */
-       { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Pegatron */
        { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Qcom */
        { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) },
-       /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* SMC */
        { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
        { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) },
        /* Sweex */
index 432e75f960b72d409cb3f925fb3249312eff6071,ac69dbe5719b2953b48b2730d772c3a94a74e136..b9885981f3a8103d41c8bb04838920af9f314e78
@@@ -30,7 -30,6 +30,7 @@@
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
 +#include <linux/slab.h>
  #include <linux/pci.h>
  #include <linux/eeprom_93cx6.h>
  
@@@ -477,7 -476,7 +477,7 @@@ static int rt61pci_config_pairwise_key(
                 * The driver does not support the IV/EIV generation
                 * in hardware. However it doesn't support the IV/EIV
                 * inside the ieee80211 frame either, but requires it
 -               * to be provided seperately for the descriptor.
 +               * to be provided separately for the descriptor.
                 * rt2x00lib will cut the IV/EIV data out of all frames
                 * given to us by mac80211, but we must tell mac80211
                 * to generate the IV/EIV data.
@@@ -2118,6 -2117,14 +2118,14 @@@ static void rt61pci_txdone(struct rt2x0
        }
  }
  
+ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
+ {
+       struct ieee80211_conf conf = { .flags = 0 };
+       struct rt2x00lib_conf libconf = { .conf = &conf };
+       rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
+ }
  static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
  {
        struct rt2x00_dev *rt2x00dev = dev_instance;
                rt2x00pci_register_write(rt2x00dev,
                                         M2H_CMD_DONE_CSR, 0xffffffff);
  
+       /*
+        * 4 - MCU Autowakeup interrupt.
+        */
+       if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
+               rt61pci_wakeup(rt2x00dev);
        return IRQ_HANDLED;
  }
  
index bb58d797fb72910afdd0598450d3323732bcd8ce,7ebe14b64fe8a50fd905622119ed36492e1e252a..576ea9dd28249d7743e0b5664d8aa0ea9805c743
@@@ -30,7 -30,6 +30,7 @@@
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
 +#include <linux/slab.h>
  #include <linux/usb.h>
  
  #include "rt2x00.h"
@@@ -340,7 -339,7 +340,7 @@@ static int rt73usb_config_shared_key(st
                 * The driver does not support the IV/EIV generation
                 * in hardware. However it doesn't support the IV/EIV
                 * inside the ieee80211 frame either, but requires it
 -               * to be provided seperately for the descriptor.
 +               * to be provided separately for the descriptor.
                 * rt2x00lib will cut the IV/EIV data out of all frames
                 * given to us by mac80211, but we must tell mac80211
                 * to generate the IV/EIV data.
@@@ -440,7 -439,7 +440,7 @@@ static int rt73usb_config_pairwise_key(
                 * The driver does not support the IV/EIV generation
                 * in hardware. However it doesn't support the IV/EIV
                 * inside the ieee80211 frame either, but requires it
 -               * to be provided seperately for the descriptor.
 +               * to be provided separately for the descriptor.
                 * rt2x00lib will cut the IV/EIV data out of all frames
                 * given to us by mac80211, but we must tell mac80211
                 * to generate the IV/EIV data.
@@@ -861,15 -860,15 +861,15 @@@ static void rt73usb_config_ps(struct rt
                rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
                                            USB_MODE_SLEEP, REGISTER_TIMEOUT);
        } else {
-               rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
-                                           USB_MODE_WAKEUP, REGISTER_TIMEOUT);
                rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
                rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
                rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
                rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
                rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
                rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
+               rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
+                                           USB_MODE_WAKEUP, REGISTER_TIMEOUT);
        }
  }
  
@@@ -1662,7 -1661,7 +1662,7 @@@ static void rt73usb_fill_rxdone(struct 
  
                /*
                 * Hardware has stripped IV/EIV data from 802.11 frame during
 -               * decryption. It has provided the data seperately but rt2x00lib
 +               * decryption. It has provided the data separately but rt2x00lib
                 * should decide if it should be reinserted.
                 */
                rxdesc->flags |= RX_FLAG_IV_STRIPPED;
index 56b78e4b0198687a5842205d6cb374043de0da41,7b8b21212bf79a6648ee07a9756e5b8b2549cf9f..4d479708158da2e43804029b644e9045123032da
@@@ -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"
@@@ -202,8 -201,8 +202,8 @@@ static int wl1251_chip_wakeup(struct wl
                        goto out;
        }
  
-       /* No NVS from netlink, try to get it from the filesystem */
-       if (wl->nvs == NULL) {
+       if (wl->nvs == NULL && !wl->use_eeprom) {
+               /* No NVS from netlink, try to get it from the filesystem */
                ret = wl1251_fetch_nvs(wl);
                if (ret < 0)
                        goto out;
index 3bfb59bd4635413422c3031625c5fb89c090ab0d,df2ff8bc8ef4461336796731ed48015a78131ebb..e81474203a23a9df145f9e27178d0fc26aadc225
@@@ -23,7 -23,6 +23,7 @@@
  
  #include <linux/irq.h>
  #include <linux/module.h>
 +#include <linux/slab.h>
  #include <linux/crc7.h>
  #include <linux/spi/spi.h>
  #include <linux/spi/wl12xx.h>
@@@ -310,7 -309,7 +310,7 @@@ static int __devexit wl1251_spi_remove(
  
  static struct spi_driver wl1251_spi_driver = {
        .driver = {
-               .name           = "wl1251",
+               .name           = DRIVER_NAME,
                .bus            = &spi_bus_type,
                .owner          = THIS_MODULE,
        },
index adaa3f2485c3f657464c41c51de1972a1f459766,1a6b2ec1db5899b19c8a299b68dd591236c661d4..2ad086efe06e8490ecb5d1c7405005695d6ad4d3
@@@ -27,7 -27,6 +27,7 @@@
  #include <linux/platform_device.h>
  #include <linux/crc7.h>
  #include <linux/spi/spi.h>
 +#include <linux/slab.h>
  
  #include "wl1271.h"
  #include "wl12xx_80211.h"
@@@ -505,12 -504,17 +505,17 @@@ out
        return ret;
  }
  
- int wl1271_acx_conn_monit_params(struct wl1271 *wl)
+ #define ACX_CONN_MONIT_DISABLE_VALUE  0xffffffff
+ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable)
  {
        struct acx_conn_monit_params *acx;
+       u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE;
+       u32 timeout = ACX_CONN_MONIT_DISABLE_VALUE;
        int ret;
  
-       wl1271_debug(DEBUG_ACX, "acx connection monitor parameters");
+       wl1271_debug(DEBUG_ACX, "acx connection monitor parameters: %s",
+                    enable ? "enabled" : "disabled");
  
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
        if (!acx) {
                goto out;
        }
  
-       acx->synch_fail_thold = cpu_to_le32(wl->conf.conn.synch_fail_thold);
-       acx->bss_lose_timeout = cpu_to_le32(wl->conf.conn.bss_lose_timeout);
+       if (enable) {
+               threshold = wl->conf.conn.synch_fail_thold;
+               timeout = wl->conf.conn.bss_lose_timeout;
+       }
+       acx->synch_fail_thold = cpu_to_le32(threshold);
+       acx->bss_lose_timeout = cpu_to_le32(timeout);
  
        ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
                                   acx, sizeof(*acx));
@@@ -793,7 -802,7 +803,7 @@@ int wl1271_acx_rate_policies(struct wl1
  
        /* configure one basic rate class */
        idx = ACX_TX_BASIC_RATE;
-       acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set);
+       acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate);
        acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
        acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
        acx->rate_class[idx].aflags = c->aflags;
        kfree(acx);
        return ret;
  }
+ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable)
+ {
+       struct wl1271_acx_keep_alive_mode *acx = NULL;
+       int ret = 0;
+       wl1271_debug(DEBUG_ACX, "acx keep alive mode: %d", enable);
+       acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+       if (!acx) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       acx->enabled = enable;
+       ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx));
+       if (ret < 0) {
+               wl1271_warning("acx keep alive mode failed: %d", ret);
+               goto out;
+       }
+ out:
+       kfree(acx);
+       return ret;
+ }
+ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid)
+ {
+       struct wl1271_acx_keep_alive_config *acx = NULL;
+       int ret = 0;
+       wl1271_debug(DEBUG_ACX, "acx keep alive config");
+       acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+       if (!acx) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval);
+       acx->index = index;
+       acx->tpl_validation = tpl_valid;
+       acx->trigger = ACX_KEEP_ALIVE_NO_TX;
+       ret = wl1271_cmd_configure(wl, ACX_SET_KEEP_ALIVE_CONFIG,
+                                  acx, sizeof(*acx));
+       if (ret < 0) {
+               wl1271_warning("acx keep alive config failed: %d", ret);
+               goto out;
+       }
+ out:
+       kfree(acx);
+       return ret;
+ }
+ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
+                               s16 thold, u8 hyst)
+ {
+       struct wl1271_acx_rssi_snr_trigger *acx = NULL;
+       int ret = 0;
+       wl1271_debug(DEBUG_ACX, "acx rssi snr trigger");
+       acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+       if (!acx) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       wl->last_rssi_event = -1;
+       acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing);
+       acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON;
+       acx->type = WL1271_ACX_TRIG_TYPE_EDGE;
+       if (enable)
+               acx->enable = WL1271_ACX_TRIG_ENABLE;
+       else
+               acx->enable = WL1271_ACX_TRIG_DISABLE;
+       acx->index = WL1271_ACX_TRIG_IDX_RSSI;
+       acx->dir = WL1271_ACX_TRIG_DIR_BIDIR;
+       acx->threshold = cpu_to_le16(thold);
+       acx->hysteresis = hyst;
+       ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_TRIGGER, acx, sizeof(*acx));
+       if (ret < 0) {
+               wl1271_warning("acx rssi snr trigger setting failed: %d", ret);
+               goto out;
+       }
+ out:
+       kfree(acx);
+       return ret;
+ }
+ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl)
+ {
+       struct wl1271_acx_rssi_snr_avg_weights *acx = NULL;
+       struct conf_roam_trigger_settings *c = &wl->conf.roam_trigger;
+       int ret = 0;
+       wl1271_debug(DEBUG_ACX, "acx rssi snr avg weights");
+       acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+       if (!acx) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       acx->rssi_beacon = c->avg_weight_rssi_beacon;
+       acx->rssi_data = c->avg_weight_rssi_data;
+       acx->snr_beacon = c->avg_weight_snr_beacon;
+       acx->snr_data = c->avg_weight_snr_data;
+       ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_WEIGHTS, acx, sizeof(*acx));
+       if (ret < 0) {
+               wl1271_warning("acx rssi snr trigger weights failed: %d", ret);
+               goto out;
+       }
+ out:
+       kfree(acx);
+       return ret;
+ }
index 1937859d74eb0fe2585bf932da6d8aa27290aace,f16d15bd56430ffca5d1bdda6d20d68dc3b35788..8087dc17f29d43b113a1e41c0d51931a19ea0fcb
@@@ -1,7 -1,7 +1,7 @@@
  /*
   * This file is part of wl1271
   *
-  * Copyright (C) 2008-2009 Nokia Corporation
+  * Copyright (C) 2008-2010 Nokia Corporation
   *
   * Contact: Luciano Coelho <luciano.coelho@nokia.com>
   *
@@@ -22,7 -22,6 +22,7 @@@
   */
  
  #include <linux/gpio.h>
 +#include <linux/slab.h>
  
  #include "wl1271_acx.h"
  #include "wl1271_reg.h"
@@@ -411,7 -410,10 +411,10 @@@ static int wl1271_boot_run_firmware(str
        /* unmask required mbox events  */
        wl->event_mask = BSS_LOSE_EVENT_ID |
                SCAN_COMPLETE_EVENT_ID |
-               PS_REPORT_EVENT_ID;
+               PS_REPORT_EVENT_ID |
+               JOIN_EVENT_COMPLETE_ID |
+               DISCONNECT_EVENT_COMPLETE_ID |
+               RSSI_SNR_TRIGGER_0_EVENT_ID;
  
        ret = wl1271_event_unmask(wl);
        if (ret < 0) {
@@@ -452,11 -454,15 +455,15 @@@ int wl1271_boot(struct wl1271 *wl
  
        if (REF_CLOCK != 0) {
                u16 val;
-               /* Set clock type */
+               /* Set clock type (open drain) */
                val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
                val &= FREF_CLK_TYPE_BITS;
-               val |= CLK_REQ_PRCM;
                wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
+               /* Set clock pull mode (no pull) */
+               val = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL);
+               val |= NO_PULL;
+               wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val);
        } else {
                u16 val;
                /* Set clock polarity */
index 92254d0d6c4cfe91b1f2cda603f46beaac31af96,b19090334bc00bd68691b7a40a7c4bae6f0b2e8e..6b5ba8ec94c9397c618839635bb2936215457cb9
@@@ -1,7 -1,7 +1,7 @@@
  /*
   * This file is part of wl1271
   *
-  * Copyright (C) 2009 Nokia Corporation
+  * Copyright (C) 2009-2010 Nokia Corporation
   *
   * Contact: Luciano Coelho <luciano.coelho@nokia.com>
   *
@@@ -27,7 -27,6 +27,7 @@@
  #include <linux/spi/spi.h>
  #include <linux/etherdevice.h>
  #include <linux/ieee80211.h>
 +#include <linux/slab.h>
  
  #include "wl1271.h"
  #include "wl1271_reg.h"
@@@ -35,6 -34,9 +35,9 @@@
  #include "wl1271_acx.h"
  #include "wl12xx_80211.h"
  #include "wl1271_cmd.h"
+ #include "wl1271_event.h"
+ #define WL1271_CMD_POLL_COUNT       5
  
  /*
   * send command to firmware
@@@ -52,6 -54,7 +55,7 @@@ int wl1271_cmd_send(struct wl1271 *wl, 
        u32 intr;
        int ret = 0;
        u16 status;
+       u16 poll_count = 0;
  
        cmd = buf;
        cmd->id = cpu_to_le16(id);
                        goto out;
                }
  
-               msleep(1);
+               udelay(10);
+               poll_count++;
+               if (poll_count == WL1271_CMD_POLL_COUNT)
+                       wl1271_info("cmd polling took over %d cycles",
+                                   poll_count);
  
                intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
        }
@@@ -249,6 -256,35 +257,35 @@@ int wl1271_cmd_radio_parms(struct wl127
        return ret;
  }
  
+ /*
+  * Poll the mailbox event field until any of the bits in the mask is set or a
+  * timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
+  */
+ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
+ {
+       u32 events_vector, event;
+       unsigned long timeout;
+       timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
+       do {
+               if (time_after(jiffies, timeout))
+                       return -ETIMEDOUT;
+               msleep(1);
+               /* read from both event fields */
+               wl1271_read(wl, wl->mbox_ptr[0], &events_vector,
+                           sizeof(events_vector), false);
+               event = events_vector & mask;
+               wl1271_read(wl, wl->mbox_ptr[1], &events_vector,
+                           sizeof(events_vector), false);
+               event |= events_vector & mask;
+       } while (!event);
+       return 0;
+ }
  int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
  {
        static bool do_cal = true;
        join->rx_config_options = cpu_to_le32(wl->rx_config);
        join->rx_filter_options = cpu_to_le32(wl->rx_filter);
        join->bss_type = bss_type;
+       join->basic_rate_set = wl->basic_rate_set;
  
-       if (wl->band == IEEE80211_BAND_2GHZ)
-               join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS   |
-                                                  CONF_HW_BIT_RATE_2MBPS   |
-                                                  CONF_HW_BIT_RATE_5_5MBPS |
-                                                  CONF_HW_BIT_RATE_11MBPS);
-       else {
+       if (wl->band == IEEE80211_BAND_5GHZ)
                join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
-               join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_6MBPS  |
-                                                  CONF_HW_BIT_RATE_12MBPS |
-                                                  CONF_HW_BIT_RATE_24MBPS);
-       }
  
-       join->beacon_interval = cpu_to_le16(WL1271_DEFAULT_BEACON_INT);
+       join->beacon_interval = cpu_to_le16(wl->beacon_int);
        join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
  
        join->channel = wl->channel;
                goto out_free;
        }
  
-       /*
-        * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
-        * simplify locking we just sleep instead, for now
-        */
-       msleep(10);
+       ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID);
+       if (ret < 0)
+               wl1271_error("cmd join event completion error");
  
  out_free:
        kfree(join);
@@@ -455,7 -481,7 +482,7 @@@ int wl1271_cmd_data_path(struct wl1271 
        if (ret < 0) {
                wl1271_error("tx %s cmd for channel %d failed",
                             enable ? "start" : "stop", cmd->channel);
-               return ret;
+               goto out;
        }
  
        wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d",
@@@ -547,17 -573,21 +574,21 @@@ int wl1271_cmd_scan(struct wl1271 *wl, 
        struct wl1271_cmd_trigger_scan_to *trigger = NULL;
        struct wl1271_cmd_scan *params = NULL;
        struct ieee80211_channel *channels;
+       u32 rate;
        int i, j, n_ch, ret;
        u16 scan_options = 0;
        u8 ieee_band;
  
-       if (band == WL1271_SCAN_BAND_2_4_GHZ)
+       if (band == WL1271_SCAN_BAND_2_4_GHZ) {
                ieee_band = IEEE80211_BAND_2GHZ;
-       else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled())
+               rate = wl->conf.tx.basic_rate;
+       } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) {
                ieee_band = IEEE80211_BAND_2GHZ;
-       else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled())
+               rate = wl->conf.tx.basic_rate;
+       } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) {
                ieee_band = IEEE80211_BAND_5GHZ;
-       else
+               rate = wl->conf.tx.basic_rate_5;
+       } else
                return -EINVAL;
  
        if (wl->hw->wiphy->bands[ieee_band]->channels == NULL)
        params->params.scan_options = cpu_to_le16(scan_options);
  
        params->params.num_probe_requests = probe_requests;
-       /* Let the fw autodetect suitable tx_rate for probes */
-       params->params.tx_rate = 0;
+       params->params.tx_rate = rate;
        params->params.tid_trigger = 0;
        params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
  
  
  out:
        kfree(params);
+       kfree(trigger);
        return ret;
  }
  
  int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
-                           void *buf, size_t buf_len)
+                           void *buf, size_t buf_len, int index, u32 rates)
  {
        struct wl1271_cmd_template_set *cmd;
        int ret = 0;
  
        cmd->len = cpu_to_le16(buf_len);
        cmd->template_type = template_id;
-       cmd->enabled_rates = cpu_to_le32(wl->conf.tx.rc_conf.enabled_rates);
+       cmd->enabled_rates = cpu_to_le32(rates);
        cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit;
        cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit;
+       cmd->index = index;
  
        if (buf)
                memcpy(cmd->template_data, buf, buf_len);
@@@ -727,7 -758,8 +759,8 @@@ int wl1271_cmd_build_null_data(struct w
                ptr = skb->data;
        }
  
-       ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size);
+       ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0,
+                                     WL1271_RATE_AUTOMATIC);
  
  out:
        dev_kfree_skb(skb);
  
  }
  
+ int wl1271_cmd_build_klv_null_data(struct wl1271 *wl)
+ {
+       struct sk_buff *skb = NULL;
+       int ret = -ENOMEM;
+       skb = ieee80211_nullfunc_get(wl->hw, wl->vif);
+       if (!skb)
+               goto out;
+       ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV,
+                                     skb->data, skb->len,
+                                     CMD_TEMPL_KLV_IDX_NULL_DATA,
+                                     WL1271_RATE_AUTOMATIC);
+ out:
+       dev_kfree_skb(skb);
+       if (ret)
+               wl1271_warning("cmd build klv null data failed %d", ret);
+       return ret;
+ }
  int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid)
  {
        struct sk_buff *skb;
                goto out;
  
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data,
-                                     skb->len);
+                                     skb->len, 0, wl->basic_rate);
  
  out:
        dev_kfree_skb(skb);
@@@ -773,10 -828,12 +829,12 @@@ int wl1271_cmd_build_probe_req(struct w
  
        if (band == IEEE80211_BAND_2GHZ)
                ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
-                                             skb->data, skb->len);
+                                             skb->data, skb->len, 0,
+                                             wl->conf.tx.basic_rate);
        else
                ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
-                                             skb->data, skb->len);
+                                             skb->data, skb->len, 0,
+                                             wl->conf.tx.basic_rate_5);
  
  out:
        dev_kfree_skb(skb);
@@@ -801,7 -858,8 +859,8 @@@ int wl1271_build_qos_null_data(struct w
        template.qos_ctrl = cpu_to_le16(0);
  
        return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template,
-                                      sizeof(template));
+                                      sizeof(template), 0,
+                                      WL1271_RATE_AUTOMATIC);
  }
  
  int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
@@@ -914,6 -972,10 +973,10 @@@ int wl1271_cmd_disconnect(struct wl127
                goto out_free;
        }
  
+       ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
+       if (ret < 0)
+               wl1271_error("cmd disconnect event completion error");
  out_free:
        kfree(cmd);
  
index e3806b035d0c7c36db7c0befa809197b7cf5f7d5,b880382cf15d016672ec68e19e3e6736efa1f62c..4447af1557f5c2af3d95ff7576118e543b8e0ea1
@@@ -23,7 -23,6 +23,7 @@@
  
  #include <linux/kernel.h>
  #include <linux/module.h>
 +#include <linux/slab.h>
  
  #include "wl1271_init.h"
  #include "wl12xx_80211.h"
@@@ -52,50 -51,65 +52,65 @@@ static int wl1271_init_hwenc_config(str
  
  int wl1271_init_templates_config(struct wl1271 *wl)
  {
-       int ret;
+       int ret, i;
  
        /* send empty templates for fw memory reservation */
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
-                                     sizeof(struct wl12xx_probe_req_template));
+                                     sizeof(struct wl12xx_probe_req_template),
+                                     0, WL1271_RATE_AUTOMATIC);
        if (ret < 0)
                return ret;
  
        if (wl1271_11a_enabled()) {
+               size_t size = sizeof(struct wl12xx_probe_req_template);
                ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
-                               NULL,
-                               sizeof(struct wl12xx_probe_req_template));
+                                             NULL, size, 0,
+                                             WL1271_RATE_AUTOMATIC);
                if (ret < 0)
                        return ret;
        }
  
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
-                                     sizeof(struct wl12xx_null_data_template));
+                                     sizeof(struct wl12xx_null_data_template),
+                                     0, WL1271_RATE_AUTOMATIC);
        if (ret < 0)
                return ret;
  
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
-                                     sizeof(struct wl12xx_ps_poll_template));
+                                     sizeof(struct wl12xx_ps_poll_template),
+                                     0, WL1271_RATE_AUTOMATIC);
        if (ret < 0)
                return ret;
  
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
                                      sizeof
-                                     (struct wl12xx_qos_null_data_template));
+                                     (struct wl12xx_qos_null_data_template),
+                                     0, WL1271_RATE_AUTOMATIC);
        if (ret < 0)
                return ret;
  
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
                                      sizeof
-                                     (struct wl12xx_probe_resp_template));
+                                     (struct wl12xx_probe_resp_template),
+                                     0, WL1271_RATE_AUTOMATIC);
        if (ret < 0)
                return ret;
  
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
                                      sizeof
-                                     (struct wl12xx_beacon_template));
+                                     (struct wl12xx_beacon_template),
+                                     0, WL1271_RATE_AUTOMATIC);
        if (ret < 0)
                return ret;
  
+       for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
+               ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
+                                             WL1271_CMD_TEMPL_MAX_SIZE, i,
+                                             WL1271_RATE_AUTOMATIC);
+               if (ret < 0)
+                       return ret;
+       }
        return 0;
  }
  
@@@ -237,7 -251,7 +252,7 @@@ int wl1271_hw_init(struct wl1271 *wl
                goto out_free_memmap;
  
        /* Initialize connection monitoring thresholds */
-       ret = wl1271_acx_conn_monit_params(wl);
+       ret = wl1271_acx_conn_monit_params(wl, false);
        if (ret < 0)
                goto out_free_memmap;
  
        if (ret < 0)
                goto out_free_memmap;
  
+       /* disable all keep-alive templates */
+       for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
+               ret = wl1271_acx_keep_alive_config(wl, i,
+                                                  ACX_KEEP_ALIVE_TPL_INVALID);
+               if (ret < 0)
+                       goto out_free_memmap;
+       }
+       /* disable the keep-alive feature */
+       ret = wl1271_acx_keep_alive_mode(wl, false);
+       if (ret < 0)
+               goto out_free_memmap;
+       /* Configure rssi/snr averaging weights */
+       ret = wl1271_acx_rssi_snr_avg_weights(wl);
+       if (ret < 0)
+               goto out_free_memmap;
        return 0;
  
   out_free_memmap:
index aa970b759dd564dd8d50d71a4f584078827389df,283d5dade1ae194fb255c7d8d14a3002d12e004e..814f300c3f176108db4c7c64719cd30896efe428
@@@ -30,7 -30,6 +30,7 @@@
  #include <linux/vmalloc.h>
  #include <linux/inetdevice.h>
  #include <linux/platform_device.h>
 +#include <linux/slab.h>
  
  #include "wl1271.h"
  #include "wl12xx_80211.h"
@@@ -117,8 -116,7 +117,7 @@@ static struct conf_drv_settings default
        .tx = {
                .tx_energy_detection         = 0,
                .rc_conf                     = {
-                       .enabled_rates       = CONF_HW_BIT_RATE_1MBPS |
-                                              CONF_HW_BIT_RATE_2MBPS,
+                       .enabled_rates       = 0,
                        .short_retry_limit   = 10,
                        .long_retry_limit    = 10,
                        .aflags              = 0
                },
                .frag_threshold              = IEEE80211_MAX_FRAG_THRESHOLD,
                .tx_compl_timeout            = 700,
-               .tx_compl_threshold          = 4
+               .tx_compl_threshold          = 4,
+               .basic_rate                  = CONF_HW_BIT_RATE_1MBPS,
+               .basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
        },
        .conn = {
                .wake_up_event               = CONF_WAKE_UP_EVENT_DTIM,
-               .listen_interval             = 0,
+               .listen_interval             = 1,
                .bcn_filt_mode               = CONF_BCN_FILT_MODE_ENABLED,
                .bcn_filt_ie_count           = 1,
                .bcn_filt_ie = {
                .broadcast_timeout           = 20000,
                .rx_broadcast_in_ps          = 1,
                .ps_poll_threshold           = 20,
-               .sig_trigger_count           = 2,
-               .sig_trigger = {
-                       [0] = {
-                               .threshold   = -75,
-                               .pacing      = 500,
-                               .metric      = CONF_TRIG_METRIC_RSSI_BEACON,
-                               .type        = CONF_TRIG_EVENT_TYPE_EDGE,
-                               .direction   = CONF_TRIG_EVENT_DIR_LOW,
-                               .hysteresis  = 2,
-                               .index       = 0,
-                               .enable      = 1
-                       },
-                       [1] = {
-                               .threshold   = -75,
-                               .pacing      = 500,
-                               .metric      = CONF_TRIG_METRIC_RSSI_BEACON,
-                               .type        = CONF_TRIG_EVENT_TYPE_EDGE,
-                               .direction   = CONF_TRIG_EVENT_DIR_HIGH,
-                               .hysteresis  = 2,
-                               .index       = 1,
-                               .enable      = 1
-                       }
-               },
-               .sig_weights = {
-                       .rssi_bcn_avg_weight = 10,
-                       .rssi_pkt_avg_weight = 10,
-                       .snr_bcn_avg_weight  = 10,
-                       .snr_pkt_avg_weight  = 10
-               },
                .bet_enable                  = CONF_BET_MODE_ENABLE,
                .bet_max_consecutive         = 10,
-               .psm_entry_retries           = 3
+               .psm_entry_retries           = 3,
+               .keep_alive_interval         = 55000,
+               .max_listen_interval         = 20,
        },
        .init = {
                .radioparam = {
        .pm_config = {
                .host_clk_settling_time = 5000,
                .host_fast_wakeup_support = false
+       },
+       .roam_trigger = {
+               /* FIXME: due to firmware bug, must use value 1 for now */
+               .trigger_pacing               = 1,
+               .avg_weight_rssi_beacon       = 20,
+               .avg_weight_rssi_data         = 10,
+               .avg_weight_snr_beacon        = 20,
+               .avg_weight_snr_data          = 10
        }
  };
  
@@@ -349,7 -330,7 +331,7 @@@ static int wl1271_plt_init(struct wl127
                goto out_free_memmap;
  
        /* Initialize connection monitoring thresholds */
-       ret = wl1271_acx_conn_monit_params(wl);
+       ret = wl1271_acx_conn_monit_params(wl, false);
        if (ret < 0)
                goto out_free_memmap;
  
@@@ -959,9 -940,11 +941,11 @@@ static int wl1271_op_add_interface(stru
        switch (vif->type) {
        case NL80211_IFTYPE_STATION:
                wl->bss_type = BSS_TYPE_STA_BSS;
+               wl->set_bss_type = BSS_TYPE_STA_BSS;
                break;
        case NL80211_IFTYPE_ADHOC:
                wl->bss_type = BSS_TYPE_IBSS;
+               wl->set_bss_type = BSS_TYPE_STA_BSS;
                break;
        default:
                ret = -EOPNOTSUPP;
@@@ -1066,6 -1049,7 +1050,7 @@@ static void wl1271_op_remove_interface(
        memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1);
        wl->ssid_len = 0;
        wl->bss_type = MAX_BSS_TYPE;
+       wl->set_bss_type = MAX_BSS_TYPE;
        wl->band = IEEE80211_BAND_2GHZ;
  
        wl->rx_counter = 0;
                wl->tx_blocks_freed[i] = 0;
  
        wl1271_debugfs_reset(wl);
+       kfree(wl->fw_status);
+       wl->fw_status = NULL;
+       kfree(wl->tx_res_if);
+       wl->tx_res_if = NULL;
+       kfree(wl->target_mem_map);
+       wl->target_mem_map = NULL;
        mutex_unlock(&wl->mutex);
  }
  
@@@ -1138,10 -1130,7 +1131,7 @@@ static int wl1271_join_channel(struct w
        /* pass through frames from all BSS */
        wl1271_configure_filters(wl, FIF_OTHER_BSS);
  
-       /* the dummy join is performed always with STATION BSS type to allow
-          also ad-hoc mode to listen to the surroundings without sending any
-          beacons yet. */
-       ret = wl1271_cmd_join(wl, BSS_TYPE_STA_BSS);
+       ret = wl1271_cmd_join(wl, wl->set_bss_type);
        if (ret < 0)
                goto out;
  
        return ret;
  }
  
+ static void wl1271_set_band_rate(struct wl1271 *wl)
+ {
+       if (wl->band == IEEE80211_BAND_2GHZ)
+               wl->basic_rate_set = wl->conf.tx.basic_rate;
+       else
+               wl->basic_rate_set = wl->conf.tx.basic_rate_5;
+ }
+ static u32 wl1271_min_rate_get(struct wl1271 *wl)
+ {
+       int i;
+       u32 rate = 0;
+       if (!wl->basic_rate_set) {
+               WARN_ON(1);
+               wl->basic_rate_set = wl->conf.tx.basic_rate;
+       }
+       for (i = 0; !rate; i++) {
+               if ((wl->basic_rate_set >> i) & 0x1)
+                       rate = 1 << i;
+       }
+       return rate;
+ }
  static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
  {
        struct wl1271 *wl = hw->priv;
  
        mutex_lock(&wl->mutex);
  
-       wl->band = conf->channel->band;
+       if (unlikely(wl->state == WL1271_STATE_OFF))
+               goto out;
  
        ret = wl1271_ps_elp_wakeup(wl, false);
        if (ret < 0)
                goto out;
  
+       /* if the channel changes while joined, join again */
+       if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+               wl->band = conf->channel->band;
+               wl->channel = channel;
+               /*
+                * FIXME: the mac80211 should really provide a fixed rate
+                * to use here. for now, just use the smallest possible rate
+                * for the band as a fixed rate for association frames and
+                * other control messages.
+                */
+               if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+                       wl1271_set_band_rate(wl);
+               wl->basic_rate = wl1271_min_rate_get(wl);
+               ret = wl1271_acx_rate_policies(wl);
+               if (ret < 0)
+                       wl1271_warning("rate policy for update channel "
+                                      "failed %d", ret);
+               if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
+                       ret = wl1271_cmd_join(wl, wl->set_bss_type);
+                       if (ret < 0)
+                               wl1271_warning("cmd join to update channel "
+                                              "failed %d", ret);
+               }
+       }
        if (changed & IEEE80211_CONF_CHANGE_IDLE) {
                if (conf->flags & IEEE80211_CONF_IDLE &&
                    test_bit(WL1271_FLAG_JOINED, &wl->flags))
                        wl1271_join_channel(wl, channel);
  
                if (conf->flags & IEEE80211_CONF_IDLE) {
-                       wl->rate_set = CONF_TX_RATE_MASK_BASIC;
+                       wl->rate_set = wl1271_min_rate_get(wl);
                        wl->sta_rate_set = 0;
                        wl1271_acx_rate_policies(wl);
-               }
+                       wl1271_acx_keep_alive_config(
+                               wl, CMD_TEMPL_KLV_IDX_NULL_DATA,
+                               ACX_KEEP_ALIVE_TPL_INVALID);
+                       set_bit(WL1271_FLAG_IDLE, &wl->flags);
+               } else
+                       clear_bit(WL1271_FLAG_IDLE, &wl->flags);
        }
  
-       /* if the channel changes while joined, join again */
-       if (channel != wl->channel &&
-           test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
-               wl->channel = channel;
-               /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */
-               ret = wl1271_cmd_join(wl, wl->bss_type);
-               if (ret < 0)
-                       wl1271_warning("cmd join to update channel failed %d",
-                                      ret);
-       } else
-               wl->channel = channel;
        if (conf->flags & IEEE80211_CONF_PS &&
            !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
                set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
@@@ -1267,11 -1304,15 +1305,16 @@@ struct wl1271_filter_params 
        u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
  };
  
 -static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
 -                                     struct dev_addr_list *mc_list)
 +static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw,
 +                                     struct netdev_hw_addr_list *mc_list)
  {
        struct wl1271_filter_params *fp;
 +      struct netdev_hw_addr *ha;
+       struct wl1271 *wl = hw->priv;
+       int i;
+       if (unlikely(wl->state == WL1271_STATE_OFF))
+               return 0;
  
        fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
        if (!fp) {
        }
  
        /* update multicast filtering parameters */
 -      fp->enabled = true;
 -      if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) {
 -              mc_count = 0;
 -              fp->enabled = false;
 -      }
 -
        fp->mc_list_length = 0;
 -      for (i = 0; i < mc_count; i++) {
 -              if (mc_list->da_addrlen == ETH_ALEN) {
 +      if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) {
 +              fp->enabled = false;
 +      } else {
 +              fp->enabled = true;
 +              netdev_hw_addr_list_for_each(ha, mc_list) {
                        memcpy(fp->mc_list[fp->mc_list_length],
 -                             mc_list->da_addr, ETH_ALEN);
 +                                      ha->addr, ETH_ALEN);
                        fp->mc_list_length++;
 -              } else
 -                      wl1271_warning("Unknown mc address length.");
 -              mc_list = mc_list->next;
 +              }
        }
  
        return (u64)(unsigned long)fp;
@@@ -1314,15 -1360,16 +1357,16 @@@ static void wl1271_op_configure_filter(
  
        mutex_lock(&wl->mutex);
  
-       if (wl->state == WL1271_STATE_OFF)
+       *total &= WL1271_SUPPORTED_FILTERS;
+       changed &= WL1271_SUPPORTED_FILTERS;
+       if (unlikely(wl->state == WL1271_STATE_OFF))
                goto out;
  
        ret = wl1271_ps_elp_wakeup(wl, false);
        if (ret < 0)
                goto out;
  
-       *total &= WL1271_SUPPORTED_FILTERS;
-       changed &= WL1271_SUPPORTED_FILTERS;
  
        if (*total & FIF_ALLMULTI)
                ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0);
  static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
  {
        struct wl1271 *wl = hw->priv;
-       int ret;
+       int ret = 0;
  
        mutex_lock(&wl->mutex);
  
+       if (unlikely(wl->state == WL1271_STATE_OFF))
+               goto out;
        ret = wl1271_ps_elp_wakeup(wl, false);
        if (ret < 0)
                goto out;
@@@ -1561,6 -1611,7 +1608,7 @@@ static void wl1271_op_bss_info_changed(
        enum wl1271_cmd_ps_mode mode;
        struct wl1271 *wl = hw->priv;
        bool do_join = false;
+       bool do_keepalive = false;
        int ret;
  
        wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
        if (ret < 0)
                goto out;
  
-       if (wl->bss_type == BSS_TYPE_IBSS) {
-               /* FIXME: This implements rudimentary ad-hoc support -
-                  proper templates are on the wish list and notification
-                  on when they change. This patch will update the templates
-                  on every call to this function. */
+       if ((changed && BSS_CHANGED_BEACON_INT) &&
+           (wl->bss_type == BSS_TYPE_IBSS)) {
+               wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d",
+                       bss_conf->beacon_int);
+               wl->beacon_int = bss_conf->beacon_int;
+               do_join = true;
+       }
+       if ((changed && BSS_CHANGED_BEACON) &&
+           (wl->bss_type == BSS_TYPE_IBSS)) {
                struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
  
+               wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated");
                if (beacon) {
                        struct ieee80211_hdr *hdr;
  
                        wl1271_ssid_set(wl, beacon);
                        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
                                                      beacon->data,
-                                                     beacon->len);
+                                                     beacon->len, 0,
+                                                     wl1271_min_rate_get(wl));
  
                        if (ret < 0) {
                                dev_kfree_skb(beacon);
                        ret = wl1271_cmd_template_set(wl,
                                                      CMD_TEMPL_PROBE_RESPONSE,
                                                      beacon->data,
-                                                     beacon->len);
+                                                     beacon->len, 0,
+                                                     wl1271_min_rate_get(wl));
                        dev_kfree_skb(beacon);
                        if (ret < 0)
                                goto out_sleep;
                }
        }
  
+       if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
+           (wl->bss_type == BSS_TYPE_IBSS)) {
+               wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s",
+                            bss_conf->enable_beacon ? "enabled" : "disabled");
+               if (bss_conf->enable_beacon)
+                       wl->set_bss_type = BSS_TYPE_IBSS;
+               else
+                       wl->set_bss_type = BSS_TYPE_STA_BSS;
+               do_join = true;
+       }
+       if (changed & BSS_CHANGED_CQM) {
+               bool enable = false;
+               if (bss_conf->cqm_rssi_thold)
+                       enable = true;
+               ret = wl1271_acx_rssi_snr_trigger(wl, enable,
+                                                 bss_conf->cqm_rssi_thold,
+                                                 bss_conf->cqm_rssi_hyst);
+               if (ret < 0)
+                       goto out;
+               wl->rssi_thold = bss_conf->cqm_rssi_thold;
+       }
        if ((changed & BSS_CHANGED_BSSID) &&
            /*
             * Now we know the correct bssid, so we send a new join command
  
        if (changed & BSS_CHANGED_ASSOC) {
                if (bss_conf->assoc) {
+                       u32 rates;
                        wl->aid = bss_conf->aid;
                        set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
  
+                       /*
+                        * use basic rates from AP, and determine lowest rate
+                        * to use with control frames.
+                        */
+                       rates = bss_conf->basic_rates;
+                       wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
+                                                                        rates);
+                       wl->basic_rate = wl1271_min_rate_get(wl);
+                       ret = wl1271_acx_rate_policies(wl);
+                       if (ret < 0)
+                               goto out_sleep;
                        /*
                         * with wl1271, we don't need to update the
                         * beacon_int and dtim_period, because the firmware
                        if (ret < 0)
                                goto out_sleep;
  
-                       ret = wl1271_acx_aid(wl, wl->aid);
+                       /*
+                        * The SSID is intentionally set to NULL here - the
+                        * firmware will set the probe request with a
+                        * broadcast SSID regardless of what we set in the
+                        * template.
+                        */
+                       ret = wl1271_cmd_build_probe_req(wl, NULL, 0,
+                                                        NULL, 0, wl->band);
+                       /* Enable the keep-alive feature */
+                       ret = wl1271_acx_keep_alive_mode(wl, true);
+                       if (ret < 0)
+                               goto out_sleep;
+                       /*
+                        * This is awkward. The keep-alive configs must be done
+                        * *after* the join command, because otherwise it will
+                        * not work, but it must only be done *once* because
+                        * otherwise the firmware will start complaining.
+                        */
+                       do_keepalive = true;
+                       /* enable the connection monitoring feature */
+                       ret = wl1271_acx_conn_monit_params(wl, true);
                        if (ret < 0)
                                goto out_sleep;
  
                        /* use defaults when not associated */
                        clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
                        wl->aid = 0;
+                       /* revert back to minimum rates for the current band */
+                       wl1271_set_band_rate(wl);
+                       wl->basic_rate = wl1271_min_rate_get(wl);
+                       ret = wl1271_acx_rate_policies(wl);
+                       if (ret < 0)
+                               goto out_sleep;
+                       /* disable connection monitor features */
+                       ret = wl1271_acx_conn_monit_params(wl, false);
+                       /* Disable the keep-alive feature */
+                       ret = wl1271_acx_keep_alive_mode(wl, false);
+                       if (ret < 0)
+                               goto out_sleep;
                }
  
        }
        }
  
        if (do_join) {
-               ret = wl1271_cmd_join(wl, wl->bss_type);
+               ret = wl1271_cmd_join(wl, wl->set_bss_type);
                if (ret < 0) {
                        wl1271_warning("cmd join failed %d", ret);
                        goto out_sleep;
                set_bit(WL1271_FLAG_JOINED, &wl->flags);
        }
  
+       /*
+        * The JOIN operation shuts down the firmware keep-alive as a side
+        * effect, and the ACX_AID will start the keep-alive as a side effect.
+        * Hence, for non-IBSS, the ACX_AID must always happen *after* the
+        * JOIN operation, and the template config after the ACX_AID.
+        */
+       if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+               ret = wl1271_acx_aid(wl, wl->aid);
+               if (ret < 0)
+                       goto out_sleep;
+       }
+       if (do_keepalive) {
+               ret = wl1271_cmd_build_klv_null_data(wl);
+               if (ret < 0)
+                       goto out_sleep;
+               ret = wl1271_acx_keep_alive_config(
+                       wl, CMD_TEMPL_KLV_IDX_NULL_DATA,
+                       ACX_KEEP_ALIVE_TPL_VALID);
+               if (ret < 0)
+                       goto out_sleep;
+       }
  out_sleep:
        wl1271_ps_elp_sleep(wl);
  
@@@ -1812,6 -1972,36 +1969,36 @@@ static struct ieee80211_channel wl1271_
        { .hw_value = 13, .center_freq = 2472, .max_power = 25 },
  };
  
+ /* mapping to indexes for wl1271_rates */
+ const static u8 wl1271_rate_to_idx_2ghz[] = {
+       /* MCS rates are used only with 11n */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */
+       11,                            /* CONF_HW_RXTX_RATE_54   */
+       10,                            /* CONF_HW_RXTX_RATE_48   */
+       9,                             /* CONF_HW_RXTX_RATE_36   */
+       8,                             /* CONF_HW_RXTX_RATE_24   */
+       /* TI-specific rate */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22   */
+       7,                             /* CONF_HW_RXTX_RATE_18   */
+       6,                             /* CONF_HW_RXTX_RATE_12   */
+       3,                             /* CONF_HW_RXTX_RATE_11   */
+       5,                             /* CONF_HW_RXTX_RATE_9    */
+       4,                             /* CONF_HW_RXTX_RATE_6    */
+       2,                             /* CONF_HW_RXTX_RATE_5_5  */
+       1,                             /* CONF_HW_RXTX_RATE_2    */
+       0                              /* CONF_HW_RXTX_RATE_1    */
+ };
  /* can't be const, mac80211 writes to this */
  static struct ieee80211_supported_band wl1271_band_2ghz = {
        .channels = wl1271_channels,
@@@ -1894,6 -2084,35 +2081,35 @@@ static struct ieee80211_channel wl1271_
        { .hw_value = 165, .center_freq = 5825},
  };
  
+ /* mapping to indexes for wl1271_rates_5ghz */
+ const static u8 wl1271_rate_to_idx_5ghz[] = {
+       /* MCS rates are used only with 11n */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */
+       7,                             /* CONF_HW_RXTX_RATE_54   */
+       6,                             /* CONF_HW_RXTX_RATE_48   */
+       5,                             /* CONF_HW_RXTX_RATE_36   */
+       4,                             /* CONF_HW_RXTX_RATE_24   */
+       /* TI-specific rate */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22   */
+       3,                             /* CONF_HW_RXTX_RATE_18   */
+       2,                             /* CONF_HW_RXTX_RATE_12   */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11   */
+       1,                             /* CONF_HW_RXTX_RATE_9    */
+       0,                             /* CONF_HW_RXTX_RATE_6    */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5  */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2    */
+       CONF_HW_RXTX_RATE_UNSUPPORTED  /* CONF_HW_RXTX_RATE_1    */
+ };
  
  static struct ieee80211_supported_band wl1271_band_5ghz = {
        .channels = wl1271_channels_5ghz,
        .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz),
  };
  
+ const static u8 *wl1271_band_rate_to_idx[] = {
+       [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz,
+       [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz
+ };
  static const struct ieee80211_ops wl1271_ops = {
        .start = wl1271_op_start,
        .stop = wl1271_op_stop,
        CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
  };
  
+ u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate)
+ {
+       u8 idx;
+       BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *));
+       if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) {
+               wl1271_error("Illegal RX rate from HW: %d", rate);
+               return 0;
+       }
+       idx = wl1271_band_rate_to_idx[wl->band][rate];
+       if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) {
+               wl1271_error("Unsupported RX rate from HW: %d", rate);
+               return 0;
+       }
+       return idx;
+ }
  static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev,
                                               struct device_attribute *attr,
                                               char *buf)
@@@ -2021,13 -2266,16 +2263,16 @@@ int wl1271_init_ieee80211(struct wl127
        /* unit us */
        /* FIXME: find a proper value */
        wl->hw->channel_change_time = 10000;
+       wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval;
  
        wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
                IEEE80211_HW_NOISE_DBM |
                IEEE80211_HW_BEACON_FILTER |
                IEEE80211_HW_SUPPORTS_PS |
                IEEE80211_HW_SUPPORTS_UAPSD |
-               IEEE80211_HW_HAS_RATE_CONTROL;
+               IEEE80211_HW_HAS_RATE_CONTROL |
+               IEEE80211_HW_CONNECTION_MONITOR |
+               IEEE80211_HW_SUPPORTS_CQM_RSSI;
  
        wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_ADHOC);
                wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
  
        wl->hw->queues = 4;
+       wl->hw->max_rates = 1;
  
        SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl));
  
@@@ -2053,7 -2302,6 +2299,6 @@@ struct ieee80211_hw *wl1271_alloc_hw(vo
        struct platform_device *plat_dev = NULL;
        struct wl1271 *wl;
        int i, ret;
-       static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
  
        hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
        if (!hw) {
  
        INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
        wl->channel = WL1271_DEFAULT_CHANNEL;
+       wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
        wl->default_key = 0;
        wl->rx_counter = 0;
        wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
        wl->psm_entry_retry = 0;
        wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
        wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
+       wl->basic_rate = CONF_TX_RATE_MASK_BASIC;
        wl->rate_set = CONF_TX_RATE_MASK_BASIC;
        wl->sta_rate_set = 0;
        wl->band = IEEE80211_BAND_2GHZ;
        wl->state = WL1271_STATE_OFF;
        mutex_init(&wl->mutex);
  
-       /*
-        * FIXME: we should use a zero MAC address here, but for now we
-        * generate a random Nokia address.
-        */
-       memcpy(wl->mac_addr, nokia_oui, 3);
-       get_random_bytes(wl->mac_addr + 3, 3);
        /* Apply default driver configuration. */
        wl1271_conf_init(wl);
  
@@@ -2157,7 -2400,6 +2397,6 @@@ int wl1271_free_hw(struct wl1271 *wl
  
        wl1271_debugfs_exit(wl);
  
-       kfree(wl->target_mem_map);
        vfree(wl->fw);
        wl->fw = NULL;
        kfree(wl->nvs);
index 6f1b732ae43b0e64ae52fb59a99a604d30128d75,ca442703d1ab8e2ea5aefb3f2ae0fe184fb37004..57f4bfd959c8d46519fbe375901d3d2f3de2864f
@@@ -21,8 -21,6 +21,8 @@@
   *
   */
  
 +#include <linux/gfp.h>
 +
  #include "wl1271.h"
  #include "wl1271_acx.h"
  #include "wl1271_reg.h"
@@@ -43,66 -41,6 +43,6 @@@ static u32 wl1271_rx_get_buf_size(struc
                RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
  }
  
- /* The values of this table must match the wl1271_rates[] array */
- static u8 wl1271_rx_rate_to_idx[] = {
-       /* MCS rates are used only with 11n */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */
-       11,                         /* WL1271_RATE_54   */
-       10,                         /* WL1271_RATE_48   */
-       9,                          /* WL1271_RATE_36   */
-       8,                          /* WL1271_RATE_24   */
-       /* TI-specific rate */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22   */
-       7,                          /* WL1271_RATE_18   */
-       6,                          /* WL1271_RATE_12   */
-       3,                          /* WL1271_RATE_11   */
-       5,                          /* WL1271_RATE_9    */
-       4,                          /* WL1271_RATE_6    */
-       2,                          /* WL1271_RATE_5_5  */
-       1,                          /* WL1271_RATE_2    */
-       0                           /* WL1271_RATE_1    */
- };
- /* The values of this table must match the wl1271_rates[] array */
- static u8 wl1271_5_ghz_rx_rate_to_idx[] = {
-       /* MCS rates are used only with 11n */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */
-       7,                          /* WL1271_RATE_54   */
-       6,                          /* WL1271_RATE_48   */
-       5,                          /* WL1271_RATE_36   */
-       4,                          /* WL1271_RATE_24   */
-       /* TI-specific rate */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22   */
-       3,                          /* WL1271_RATE_18   */
-       2,                          /* WL1271_RATE_12   */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_11   */
-       1,                          /* WL1271_RATE_9    */
-       0,                          /* WL1271_RATE_6    */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_5_5  */
-       WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_2    */
-       WL1271_RX_RATE_UNSUPPORTED  /* WL1271_RATE_1    */
- };
  static void wl1271_rx_status(struct wl1271 *wl,
                             struct wl1271_rx_descriptor *desc,
                             struct ieee80211_rx_status *status,
  {
        memset(status, 0, sizeof(struct ieee80211_rx_status));
  
-       if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
-           WL1271_RX_DESC_BAND_BG) {
-               status->band = IEEE80211_BAND_2GHZ;
-               status->rate_idx = wl1271_rx_rate_to_idx[desc->rate];
-       } else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
-                WL1271_RX_DESC_BAND_A) {
-               status->band = IEEE80211_BAND_5GHZ;
-               status->rate_idx = wl1271_5_ghz_rx_rate_to_idx[desc->rate];
-       } else
-               wl1271_warning("unsupported band 0x%x",
-                              desc->flags & WL1271_RX_DESC_BAND_MASK);
-       if (unlikely(status->rate_idx == WL1271_RX_RATE_UNSUPPORTED))
-               wl1271_warning("unsupported rate");
+       status->band = wl->band;
+       status->rate_idx = wl1271_rate_to_idx(wl, desc->rate);
  
        /*
         * FIXME: Add mactime handling.  For IBSS (ad-hoc) we need to get the
         */
        status->signal = desc->rssi;
  
-       /*
-        * FIXME: In wl1251, the SNR should be divided by two.  In wl1271 we
-        * need to divide by two for now, but TI has been discussing about
-        * changing it.  This needs to be rechecked.
-        */
-       status->noise = desc->rssi - (desc->snr >> 1);
        status->freq = ieee80211_channel_to_frequency(desc->channel);
  
        if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
index 256e84ad0baff8e26d7fb96f2e8659552cbcc828,7a7db011a797f2ddb5eab89e35b8a9e9caaf0fc3..5189b812f939e4744b60b46ad637bd7332d1c11e
@@@ -26,7 -26,6 +26,7 @@@
  #include <linux/crc7.h>
  #include <linux/spi/spi.h>
  #include <linux/spi/wl12xx.h>
 +#include <linux/slab.h>
  
  #include "wl1271.h"
  #include "wl12xx_80211.h"
@@@ -105,6 -104,7 +105,7 @@@ static void wl1271_spi_reset(struct wl1
        spi_message_add_tail(&t, &m);
  
        spi_sync(wl_to_spi(wl), &m);
+       kfree(cmd);
  
        wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
  }
@@@ -159,47 -159,24 +160,24 @@@ static void wl1271_spi_init(struct wl12
        spi_message_add_tail(&t, &m);
  
        spi_sync(wl_to_spi(wl), &m);
+       kfree(cmd);
  
        wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
  }
  
  #define WL1271_BUSY_WORD_TIMEOUT 1000
  
- /* FIXME: Check busy words, removed due to SPI bug */
- #if 0
- static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len)
+ static int wl1271_spi_read_busy(struct wl1271 *wl)
  {
        struct spi_transfer t[1];
        struct spi_message m;
        u32 *busy_buf;
        int num_busy_bytes = 0;
  
-       wl1271_info("spi read BUSY!");
-       /*
-        * Look for the non-busy word in the read buffer, and if found,
-        * read in the remaining data into the buffer.
-        */
-       busy_buf = (u32 *)buf;
-       for (; (u32)busy_buf < (u32)buf + len; busy_buf++) {
-               num_busy_bytes += sizeof(u32);
-               if (*busy_buf & 0x1) {
-                       spi_message_init(&m);
-                       memset(t, 0, sizeof(t));
-                       memmove(buf, busy_buf, len - num_busy_bytes);
-                       t[0].rx_buf = buf + (len - num_busy_bytes);
-                       t[0].len = num_busy_bytes;
-                       spi_message_add_tail(&t[0], &m);
-                       spi_sync(wl_to_spi(wl), &m);
-                       return;
-               }
-       }
        /*
         * Read further busy words from SPI until a non-busy word is
         * encountered, then read the data itself into the buffer.
         */
-       wl1271_info("spi read BUSY-polling needed!");
  
        num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT;
        busy_buf = wl->buffer_busyword;
                memset(t, 0, sizeof(t));
                t[0].rx_buf = busy_buf;
                t[0].len = sizeof(u32);
+               t[0].cs_change = true;
                spi_message_add_tail(&t[0], &m);
                spi_sync(wl_to_spi(wl), &m);
  
-               if (*busy_buf & 0x1) {
-                       spi_message_init(&m);
-                       memset(t, 0, sizeof(t));
-                       t[0].rx_buf = buf;
-                       t[0].len = len;
-                       spi_message_add_tail(&t[0], &m);
-                       spi_sync(wl_to_spi(wl), &m);
-                       return;
-               }
+               if (*busy_buf & 0x1)
+                       return 0;
        }
  
        /* The SPI bus is unresponsive, the read failed. */
-       memset(buf, 0, len);
        wl1271_error("SPI read busy-word timeout!\n");
+       return -ETIMEDOUT;
  }
- #endif
  
  static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
-                        size_t len, bool fixed)
+                               size_t len, bool fixed)
  {
        struct spi_transfer t[3];
        struct spi_message m;
  
        t[0].tx_buf = cmd;
        t[0].len = 4;
+       t[0].cs_change = true;
        spi_message_add_tail(&t[0], &m);
  
        /* Busy and non busy words read */
        t[1].rx_buf = busy_buf;
        t[1].len = WL1271_BUSY_WORD_LEN;
+       t[1].cs_change = true;
        spi_message_add_tail(&t[1], &m);
  
-       t[2].rx_buf = buf;
-       t[2].len = len;
-       spi_message_add_tail(&t[2], &m);
        spi_sync(wl_to_spi(wl), &m);
  
-       /* FIXME: Check busy words, removed due to SPI bug */
-       /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1))
-          wl1271_spi_read_busy(wl, buf, len); */
+       if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
+           wl1271_spi_read_busy(wl)) {
+               memset(buf, 0, len);
+               return;
+       }
+       spi_message_init(&m);
+       memset(t, 0, sizeof(t));
+       t[0].rx_buf = buf;
+       t[0].len = len;
+       t[0].cs_change = true;
+       spi_message_add_tail(&t[0], &m);
+       spi_sync(wl_to_spi(wl), &m);
  
        wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
        wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
@@@ -443,7 -423,7 +424,7 @@@ static int __devexit wl1271_remove(stru
  
  static struct spi_driver wl1271_spi_driver = {
        .driver = {
-               .name           = "wl1271",
+               .name           = "wl1271_spi",
                .bus            = &spi_bus_type,
                .owner          = THIS_MODULE,
        },
diff --combined include/linux/mmc/sdio.h
index 0ebaef577ff59ef0666e68357f4e61fa08f2a864,118f0295a575c81af69aa179d588a450f881a193..329a8faa6e37bb32bd6e65f1b8fd758ac45baa36
  
  #define  SDIO_BUS_WIDTH_1BIT  0x00
  #define  SDIO_BUS_WIDTH_4BIT  0x02
+ #define  SDIO_BUS_ECSI                0x20    /* Enable continuous SPI interrupt */
+ #define  SDIO_BUS_SCSI                0x40    /* Support continuous SPI interrupt */
  
 +#define  SDIO_BUS_ASYNC_INT   0x20
 +
  #define  SDIO_BUS_CD_DISABLE     0x80 /* disable pull-up on DAT3 (pin 1) */
  
  #define SDIO_CCCR_CAPS                0x08
diff --combined include/net/mac80211.h
index 20823d04e03c0848b469b8d05c17f5ae12c81cf1,dcf3c5f23c965049e66e56424afaf605140ece2f..344e5bf72062b98651307e3ba92523a60cd22b90
@@@ -587,11 -587,15 +587,15 @@@ struct ieee80211_rx_status 
   *    may turn the device off as much as possible. Typically, this flag will
   *    be set when an interface is set UP but not associated or scanning, but
   *    it can also be unset in that case when monitor interfaces are active.
+  * @IEEE80211_CONF_QOS: Enable 802.11e QoS also know as WMM (Wireless
+  *      Multimedia). On some drivers (iwlwifi is one of know) we have
+  *      to enable/disable QoS explicitly.
   */
  enum ieee80211_conf_flags {
        IEEE80211_CONF_MONITOR          = (1<<0),
        IEEE80211_CONF_PS               = (1<<1),
        IEEE80211_CONF_IDLE             = (1<<2),
+       IEEE80211_CONF_QOS              = (1<<3),
  };
  
  
@@@ -616,6 -620,7 +620,7 @@@ enum ieee80211_conf_changed 
        IEEE80211_CONF_CHANGE_CHANNEL           = BIT(6),
        IEEE80211_CONF_CHANGE_RETRY_LIMITS      = BIT(7),
        IEEE80211_CONF_CHANGE_IDLE              = BIT(8),
+       IEEE80211_CONF_CHANGE_QOS               = BIT(9),
  };
  
  /**
@@@ -1626,7 -1631,7 +1631,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,
@@@ -1822,7 -1827,10 +1827,10 @@@ void ieee80211_restart_hw(struct ieee80
   * ieee80211_rx - receive frame
   *
   * Use this function to hand received frames to mac80211. The receive
-  * buffer in @skb must start with an IEEE 802.11 header.
+  * buffer in @skb must start with an IEEE 802.11 header. In case of a
+  * paged @skb is used, the driver is recommended to put the ieee80211
+  * header of the frame on the linear part of the @skb to avoid memory
+  * allocation and/or memcpy by the stack.
   *
   * This function may not be called in IRQ context. Calls to this function
   * for a single hardware must be synchronized against each other. Calls to
diff --combined net/mac80211/agg-rx.c
index f9516a27e233ba09ebf1d69a81968552d47902ee,53233ab50f656da9a9e1e33994adcc2aacb5077b..9598fdb4ad011c1fb06c6dd84acb3aa3f97efed6
@@@ -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"
@@@ -23,19 -22,20 +23,20 @@@ void __ieee80211_stop_rx_ba_session(str
                                    u16 initiator, u16 reason)
  {
        struct ieee80211_local *local = sta->local;
+       struct tid_ampdu_rx *tid_rx;
        int i;
  
-       /* check if TID is in operational state */
        spin_lock_bh(&sta->lock);
-       if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) {
+       /* check if TID is in operational state */
+       if (!sta->ampdu_mlme.tid_active_rx[tid]) {
                spin_unlock_bh(&sta->lock);
                return;
        }
  
-       sta->ampdu_mlme.tid_state_rx[tid] =
-               HT_AGG_STATE_REQ_STOP_BA_MSK |
-               (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
-       spin_unlock_bh(&sta->lock);
+       sta->ampdu_mlme.tid_active_rx[tid] = false;
+       tid_rx = sta->ampdu_mlme.tid_rx[tid];
  
  #ifdef CONFIG_MAC80211_HT_DEBUG
        printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n",
                printk(KERN_DEBUG "HW problem - can not stop rx "
                                "aggregation for tid %d\n", tid);
  
-       /* shutdown timer has not expired */
-       if (initiator != WLAN_BACK_TIMER)
-               del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
        /* check if this is a self generated aggregation halt */
-       if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
+       if (initiator == WLAN_BACK_RECIPIENT)
                ieee80211_send_delba(sta->sdata, sta->sta.addr,
                                     tid, 0, reason);
  
        /* free the reordering buffer */
-       for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
-               if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
+       for (i = 0; i < tid_rx->buf_size; i++) {
+               if (tid_rx->reorder_buf[i]) {
                        /* release the reordered frames */
-                       dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
-                       sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
-                       sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
+                       dev_kfree_skb(tid_rx->reorder_buf[i]);
+                       tid_rx->stored_mpdu_num--;
+                       tid_rx->reorder_buf[i] = NULL;
                }
        }
  
-       spin_lock_bh(&sta->lock);
        /* free resources */
-       kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
-       kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time);
+       kfree(tid_rx->reorder_buf);
+       kfree(tid_rx->reorder_time);
+       sta->ampdu_mlme.tid_rx[tid] = NULL;
  
-       if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) {
-               kfree(sta->ampdu_mlme.tid_rx[tid]);
-               sta->ampdu_mlme.tid_rx[tid] = NULL;
-       }
-       sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
        spin_unlock_bh(&sta->lock);
- }
- void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid,
-                                       u16 initiator, u16 reason)
- {
-       struct sta_info *sta;
-       rcu_read_lock();
-       sta = sta_info_get(sdata, ra);
-       if (!sta) {
-               rcu_read_unlock();
-               return;
-       }
-       __ieee80211_stop_rx_ba_session(sta, tid, initiator, reason);
  
-       rcu_read_unlock();
+       del_timer_sync(&tid_rx->session_timer);
+       kfree(tid_rx);
  }
  
  /*
   * After accepting the AddBA Request we activated a timer,
   * resetting it after each frame that arrives from the originator.
-  * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
   */
  static void sta_rx_agg_session_timer_expired(unsigned long data)
  {
  #ifdef CONFIG_MAC80211_HT_DEBUG
        printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
  #endif
-       ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
-                                        (u16)*ptid, WLAN_BACK_TIMER,
-                                        WLAN_REASON_QSTA_TIMEOUT);
+       __ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT,
+                                      WLAN_REASON_QSTA_TIMEOUT);
  }
  
  static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
@@@ -194,7 -167,7 +168,7 @@@ void ieee80211_process_addba_request(st
  
        status = WLAN_STATUS_REQUEST_DECLINED;
  
-       if (test_sta_flags(sta, WLAN_STA_SUSPEND)) {
+       if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
  #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Suspend in progress. "
                       "Denying ADDBA request\n");
        /* examine state machine */
        spin_lock_bh(&sta->lock);
  
-       if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
+       if (sta->ampdu_mlme.tid_active_rx[tid]) {
  #ifdef CONFIG_MAC80211_HT_DEBUG
                if (net_ratelimit())
                        printk(KERN_DEBUG "unexpected AddBA Req from "
        }
  
        /* change state and send addba resp */
-       sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL;
+       sta->ampdu_mlme.tid_active_rx[tid] = true;
        tid_agg_rx->dialog_token = dialog_token;
        tid_agg_rx->ssn = start_seq_num;
        tid_agg_rx->head_seq_num = start_seq_num;
diff --combined net/mac80211/agg-tx.c
index 96d25348aa59dcd830a03f521b3dc817397d7d5c,6bb4d0a1e5c5a6e725a605cf723455ed2d4feb55..608063f11797ba2d0a6021a6673c455b042552a8
@@@ -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"
@@@ -215,6 -214,8 +215,8 @@@ int ieee80211_start_tx_ba_session(struc
        int ret = 0;
        u16 start_seq_num;
  
+       trace_api_start_tx_ba_session(pubsta, tid);
        if (WARN_ON(!local->ops->ampdu_action))
                return -EINVAL;
  
                return -EINVAL;
        }
  
-       if (test_sta_flags(sta, WLAN_STA_SUSPEND)) {
+       if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
  #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Suspend in progress. "
                       "Denying BA session request\n");
@@@ -415,7 -416,7 +417,7 @@@ static void ieee80211_agg_tx_operationa
                                         struct sta_info *sta, u16 tid)
  {
  #ifdef CONFIG_MAC80211_HT_DEBUG
-       printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
+       printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid);
  #endif
  
        spin_lock(&local->ampdu_lock);
@@@ -441,6 -442,8 +443,8 @@@ void ieee80211_start_tx_ba_cb(struct ie
        struct sta_info *sta;
        u8 *state;
  
+       trace_api_start_tx_ba_cb(sdata, ra, tid);
        if (tid >= STA_TID_NUM) {
  #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
@@@ -542,6 -545,8 +546,8 @@@ int ieee80211_stop_tx_ba_session(struc
        struct ieee80211_sub_if_data *sdata = sta->sdata;
        struct ieee80211_local *local = sdata->local;
  
+       trace_api_stop_tx_ba_session(pubsta, tid, initiator);
        if (!local->ops->ampdu_action)
                return -EINVAL;
  
@@@ -559,6 -564,8 +565,8 @@@ void ieee80211_stop_tx_ba_cb(struct iee
        struct sta_info *sta;
        u8 *state;
  
+       trace_api_stop_tx_ba_cb(sdata, ra, tid);
        if (tid >= STA_TID_NUM) {
  #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
@@@ -675,7 -682,7 +683,7 @@@ void ieee80211_process_addba_resp(struc
        del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
  
  #ifdef CONFIG_MAC80211_HT_DEBUG
-       printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
+       printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid);
  #endif /* CONFIG_MAC80211_HT_DEBUG */
  
        if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
diff --combined net/mac80211/cfg.c
index c41aaba839fa3be73fffbeeb521abd9ca51174f2,4edd73cbf0524172fe74a2b902093468b9cf43f6..7dd7cda75cfa986cf7aa83b8d15719638f7d77bf
@@@ -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>
@@@ -1137,6 -1136,10 +1137,10 @@@ static int ieee80211_set_txq_params(str
                return -EINVAL;
        }
  
+       /* enable WMM or activate new settings */
+       local->hw.conf.flags |= IEEE80211_CONF_QOS;
+       drv_config(local, IEEE80211_CONF_CHANGE_QOS);
        return 0;
  }
  
@@@ -1412,9 -1415,6 +1416,6 @@@ static int ieee80211_set_cqm_rssi_confi
        struct ieee80211_vif *vif = &sdata->vif;
        struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
  
-       if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI))
-               return -EOPNOTSUPP;
        if (rssi_thold == bss_conf->cqm_rssi_thold &&
            rssi_hyst == bss_conf->cqm_rssi_hyst)
                return 0;
        bss_conf->cqm_rssi_thold = rssi_thold;
        bss_conf->cqm_rssi_hyst = rssi_hyst;
  
+       if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) {
+               if (sdata->vif.type != NL80211_IFTYPE_STATION)
+                       return -EOPNOTSUPP;
+               return 0;
+       }
        /* tell the driver upon association, unless already associated */
        if (sdata->u.mgd.associated)
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
index 83d4289d954bfacd1db317ec71b709623b44fa82,623e6644b80c964e0fed21f7199f5c7f4c60d7cc..20b2998fa0ed07b68b410f77a82d0f159603d79e
@@@ -13,7 -13,6 +13,7 @@@
  #include <linux/interrupt.h>
  #include <linux/netdevice.h>
  #include <linux/rtnetlink.h>
 +#include <linux/slab.h>
  #include <linux/notifier.h>
  #include <net/mac80211.h>
  #include <net/cfg80211.h>
@@@ -100,6 -99,14 +100,14 @@@ static ssize_t ieee80211_if_fmt_##name
        return scnprintf(buf, buflen, "%pM\n", sdata->field);           \
  }
  
+ #define IEEE80211_IF_FMT_DEC_DIV_16(name, field)                      \
+ static ssize_t ieee80211_if_fmt_##name(                                       \
+       const struct ieee80211_sub_if_data *sdata,                      \
+       char *buf, int buflen)                                          \
+ {                                                                     \
+       return scnprintf(buf, buflen, "%d\n", sdata->field / 16);       \
+ }
  #define __IEEE80211_IF_FILE(name, _write)                             \
  static ssize_t ieee80211_if_read_##name(struct file *file,            \
                                        char __user *userbuf,           \
@@@ -140,6 -147,8 +148,8 @@@ IEEE80211_IF_FILE(rc_rateidx_mask_5ghz
  /* STA attributes */
  IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
  IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
+ IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC);
+ IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16);
  
  static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
                              enum ieee80211_smps_mode smps_mode)
@@@ -276,6 -285,8 +286,8 @@@ static void add_sta_files(struct ieee80
  
        DEBUGFS_ADD(bssid);
        DEBUGFS_ADD(aid);
+       DEBUGFS_ADD(last_beacon);
+       DEBUGFS_ADD(ave_beacon);
        DEBUGFS_ADD_MODE(smps, 0600);
  }
  
index 7fdacf9408b192388cca13dbfa5455c24a4bced9,4e73660ebe99ab92a3d46e0c4fc629c4cd319919..c9712f35e59639e121317aaaa09496408a90b740
@@@ -317,6 -317,7 +317,7 @@@ enum ieee80211_sta_flags 
        IEEE80211_STA_MFP_ENABLED       = BIT(6),
        IEEE80211_STA_UAPSD_ENABLED     = BIT(7),
        IEEE80211_STA_NULLFUNC_ACKED    = BIT(8),
+       IEEE80211_STA_RESET_SIGNAL_AVE  = BIT(9),
  };
  
  struct ieee80211_if_managed {
        int wmm_last_param_set;
  
        u8 use_4addr;
+       /* Signal strength from the last Beacon frame in the current BSS. */
+       int last_beacon_signal;
+       /*
+        * Weighted average of the signal strength from Beacon frames in the
+        * current BSS. This is in units of 1/16 of the signal unit to maintain
+        * accuracy and to speed up calculations, i.e., the value need to be
+        * divided by 16 to get the actual value.
+        */
+       int ave_beacon_signal;
+       /*
+        * Last Beacon frame signal strength average (ave_beacon_signal / 16)
+        * that triggered a cqm event. 0 indicates that no event has been
+        * generated for the current association.
+        */
+       int last_cqm_event_signal;
  };
  
  enum ieee80211_ibss_request {
@@@ -646,7 -665,8 +665,7 @@@ struct ieee80211_local 
        struct work_struct recalc_smps;
  
        /* aggregated multicast list */
 -      struct dev_addr_list *mc_list;
 -      int mc_count;
 +      struct netdev_hw_addr_list mc_list;
  
        bool tim_in_locked_section; /* see ieee80211_beacon_get() */
  
@@@ -1078,8 -1098,6 +1097,6 @@@ int ieee80211_send_smps_action(struct i
                               enum ieee80211_smps_mode smps, const u8 *da,
                               const u8 *bssid);
  
- void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da,
-                               u16 tid, u16 initiator, u16 reason);
  void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
                                    u16 initiator, u16 reason);
  void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta);
diff --combined net/mac80211/main.c
index 50c1b1ada8848f8c6ba7ce9d530deca940c9e562,4afe851cf8dc0359cae81027bfa8150d632c3b73..011ee85bcd5782a6867457baacaee72bcdd8b9c0
@@@ -71,7 -71,7 +71,7 @@@ void ieee80211_configure_filter(struct 
        spin_lock_bh(&local->filter_lock);
        changed_flags = local->filter_flags ^ new_flags;
  
 -      mc = drv_prepare_multicast(local, local->mc_count, local->mc_list);
 +      mc = drv_prepare_multicast(local, &local->mc_list);
        spin_unlock_bh(&local->filter_lock);
  
        /* be a bit nasty */
@@@ -309,6 -309,8 +309,8 @@@ void ieee80211_restart_hw(struct ieee80
  {
        struct ieee80211_local *local = hw_to_local(hw);
  
+       trace_api_restart_hw(local);
        /* use this reason, __ieee80211_resume will unblock it */
        ieee80211_stop_queues_by_reason(hw,
                IEEE80211_QUEUE_STOP_REASON_SUSPEND);
@@@ -388,9 -390,6 +390,9 @@@ struct ieee80211_hw *ieee80211_alloc_hw
        local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
  
        INIT_LIST_HEAD(&local->interfaces);
 +
 +      __hw_addr_init(&local->mc_list);
 +
        mutex_init(&local->iflist_mtx);
        mutex_init(&local->scan_mtx);
  
diff --combined net/mac80211/mesh.c
index 859ee5f3d94146a5103b5c2188847da3a302d12d,2669fbf8c812a988929227ab0481c2e3450f79f3..7e93524459fcb36994b6bde65f92a04b9ff89984
@@@ -8,7 -8,6 +8,7 @@@
   * published by the Free Software Foundation.
   */
  
 +#include <linux/slab.h>
  #include <asm/unaligned.h>
  #include "ieee80211_i.h"
  #include "mesh.h"
@@@ -601,10 -600,10 +601,10 @@@ static void ieee80211_mesh_rx_mgmt_acti
                                          struct ieee80211_rx_status *rx_status)
  {
        switch (mgmt->u.action.category) {
-       case MESH_PLINK_CATEGORY:
+       case WLAN_CATEGORY_MESH_PLINK:
                mesh_rx_plink_frame(sdata, mgmt, len, rx_status);
                break;
-       case MESH_PATH_SEL_CATEGORY:
+       case WLAN_CATEGORY_MESH_PATH_SEL:
                mesh_rx_path_sel_frame(sdata, mgmt, len);
                break;
        }
diff --combined net/mac80211/mesh_hwmp.c
index fefc45c4b4e8cad4a792d9f6787284270f3510bd,36141d6e701ba0932ff69ed180d62172780e4651..d89ed7f2592b3a87393a96af9172b9f4fba1f7e2
@@@ -7,7 -7,6 +7,7 @@@
   * published by the Free Software Foundation.
   */
  
 +#include <linux/slab.h>
  #include "mesh.h"
  
  #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG
@@@ -132,7 -131,7 +132,7 @@@ static int mesh_path_sel_frame_tx(enum 
        memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
        /* BSSID == SA */
        memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
-       mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
+       mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL;
        mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
  
        switch (action) {
@@@ -225,7 -224,7 +225,7 @@@ int mesh_path_error_tx(u8 ttl, u8 *targ
        memcpy(mgmt->da, ra, ETH_ALEN);
        memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
        /* BSSID is left zeroed, wildcard value */
-       mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
+       mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL;
        mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
        ie_len = 15;
        pos = skb_put(skb, 2 + ie_len);
index 7b7080e2b49f47a1dcac316432341b89b3a9a5cb,c384154ac89506d3b153792c1440909d9abb78ca..3cd5f7b5d693be131e75baeb8f7474fb4ab2bef3
@@@ -6,7 -6,6 +6,7 @@@
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
 +#include <linux/gfp.h>
  #include <linux/kernel.h>
  #include <linux/random.h>
  #include "ieee80211_i.h"
@@@ -172,7 -171,7 +172,7 @@@ static int mesh_plink_frame_tx(struct i
        memcpy(mgmt->da, da, ETH_ALEN);
        memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
        /* BSSID is left zeroed, wildcard value */
-       mgmt->u.action.category = MESH_PLINK_CATEGORY;
+       mgmt->u.action.category = WLAN_CATEGORY_MESH_PLINK;
        mgmt->u.action.u.plink_action.action_code = action;
  
        if (action == PLINK_CLOSE)
@@@ -745,7 -744,7 +745,7 @@@ void mesh_rx_plink_frame(struct ieee802
                break;
        default:
                /* should not get here, PLINK_BLOCKED is dealt with at the
 -               * beggining of the function
 +               * beginning of the function
                 */
                spin_unlock_bh(&sta->lock);
                break;
diff --combined net/mac80211/mlme.c
index 71ff42a0465bd8b8158ffb9b05c11116acf4d82d,d11a54c289a273e98cf77f7dcb4d2f40cb5719ce..35d850223a75f9a16af592a2659a035d70c8258d
@@@ -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>
  
   */
  #define IEEE80211_PROBE_WAIT          (HZ / 2)
  
+ /*
+  * Weight given to the latest Beacon frame when calculating average signal
+  * strength for Beacon frames received in the current BSS. This must be
+  * between 1 and 15.
+  */
+ #define IEEE80211_SIGNAL_AVE_WEIGHT   3
  #define TMR_RUNNING_TIMER     0
  #define TMR_RUNNING_CHANSW    1
  
@@@ -204,7 -210,7 +211,7 @@@ static u32 ieee80211_enable_ht(struct i
  
  static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
                                           const u8 *bssid, u16 stype, u16 reason,
-                                          void *cookie)
+                                          void *cookie, bool send_frame)
  {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
                        cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
        if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
                IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
-       ieee80211_tx_skb(sdata, skb);
+       if (send_frame)
+               ieee80211_tx_skb(sdata, skb);
+       else
+               kfree_skb(skb);
  }
  
  void ieee80211_send_pspoll(struct ieee80211_local *local,
@@@ -590,6 -600,9 +601,9 @@@ static void ieee80211_sta_wmm_params(st
        int count;
        u8 *pos, uapsd_queues = 0;
  
+       if (!local->ops->conf_tx)
+               return;
        if (local->hw.queues < 4)
                return;
  
                       params.aifs, params.cw_min, params.cw_max, params.txop,
                       params.uapsd);
  #endif
-               if (drv_conf_tx(local, queue, &params) && local->ops->conf_tx)
+               if (drv_conf_tx(local, queue, &params))
                        printk(KERN_DEBUG "%s: failed to set TX queue "
                               "parameters for queue %d\n",
                               wiphy_name(local->hw.wiphy), queue);
        }
+       /* enable WMM or activate new settings */
+       local->hw.conf.flags |= IEEE80211_CONF_QOS;
+       drv_config(local, IEEE80211_CONF_CHANGE_QOS);
  }
  
  static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
@@@ -729,6 -746,8 +747,8 @@@ static void ieee80211_set_associated(st
        sdata->u.mgd.associated = cbss;
        memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
  
+       sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;
        /* just to be sure */
        sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
                                IEEE80211_STA_BEACON_POLL);
        netif_carrier_on(sdata->dev);
  }
  
- static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
+ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
+                                  bool remove_sta)
  {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_local *local = sdata->local;
        changed |= BSS_CHANGED_BSSID;
        ieee80211_bss_info_change_notify(sdata, changed);
  
-       sta_info_destroy_addr(sdata, bssid);
+       if (remove_sta)
+               sta_info_destroy_addr(sdata, bssid);
  }
  
  void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@@ -956,7 -977,7 +978,7 @@@ static void __ieee80211_connection_loss
  
        printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
  
-       ieee80211_set_disassoc(sdata);
+       ieee80211_set_disassoc(sdata, true);
        ieee80211_recalc_idle(local);
        mutex_unlock(&ifmgd->mtx);
        /*
        ieee80211_send_deauth_disassoc(sdata, bssid,
                                       IEEE80211_STYPE_DEAUTH,
                                       WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
-                                      NULL);
+                                      NULL, true);
  }
  
  void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@@ -986,6 -1007,8 +1008,8 @@@ void ieee80211_beacon_loss(struct ieee8
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
        struct ieee80211_hw *hw = &sdata->local->hw;
  
+       trace_api_beacon_loss(sdata);
        WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR);
        ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
  }
@@@ -996,6 -1019,8 +1020,8 @@@ void ieee80211_connection_loss(struct i
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
        struct ieee80211_hw *hw = &sdata->local->hw;
  
+       trace_api_connection_loss(sdata);
        WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR));
        ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
  }
@@@ -1022,7 -1047,7 +1048,7 @@@ ieee80211_rx_mgmt_deauth(struct ieee802
        printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
                        sdata->name, bssid, reason_code);
  
-       ieee80211_set_disassoc(sdata);
+       ieee80211_set_disassoc(sdata, true);
        ieee80211_recalc_idle(sdata->local);
  
        return RX_MGMT_CFG80211_DEAUTH;
@@@ -1052,7 -1077,7 +1078,7 @@@ ieee80211_rx_mgmt_disassoc(struct ieee8
        printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
                        sdata->name, mgmt->sa, reason_code);
  
-       ieee80211_set_disassoc(sdata);
+       ieee80211_set_disassoc(sdata, true);
        ieee80211_recalc_idle(sdata->local);
        return RX_MGMT_CFG80211_DISASSOC;
  }
@@@ -1344,6 -1369,7 +1370,7 @@@ static void ieee80211_rx_mgmt_beacon(st
                                     struct ieee80211_rx_status *rx_status)
  {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
        size_t baselen;
        struct ieee802_11_elems elems;
        struct ieee80211_local *local = sdata->local;
        if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)
                return;
  
+       /* Track average RSSI from the Beacon frames of the current AP */
+       ifmgd->last_beacon_signal = rx_status->signal;
+       if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
+               ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
+               ifmgd->ave_beacon_signal = rx_status->signal;
+               ifmgd->last_cqm_event_signal = 0;
+       } else {
+               ifmgd->ave_beacon_signal =
+                       (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 +
+                        (16 - IEEE80211_SIGNAL_AVE_WEIGHT) *
+                        ifmgd->ave_beacon_signal) / 16;
+       }
+       if (bss_conf->cqm_rssi_thold &&
+           !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) {
+               int sig = ifmgd->ave_beacon_signal / 16;
+               int last_event = ifmgd->last_cqm_event_signal;
+               int thold = bss_conf->cqm_rssi_thold;
+               int hyst = bss_conf->cqm_rssi_hyst;
+               if (sig < thold &&
+                   (last_event == 0 || sig < last_event - hyst)) {
+                       ifmgd->last_cqm_event_signal = sig;
+                       ieee80211_cqm_rssi_notify(
+                               &sdata->vif,
+                               NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+                               GFP_KERNEL);
+               } else if (sig > thold &&
+                          (last_event == 0 || sig > last_event + hyst)) {
+                       ifmgd->last_cqm_event_signal = sig;
+                       ieee80211_cqm_rssi_notify(
+                               &sdata->vif,
+                               NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+                               GFP_KERNEL);
+               }
+       }
        if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) {
  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
                if (net_ratelimit()) {
@@@ -1664,7 -1725,7 +1726,7 @@@ static void ieee80211_sta_work(struct w
                        printk(KERN_DEBUG "No probe response from AP %pM"
                                " after %dms, disconnecting.\n",
                                bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
-                       ieee80211_set_disassoc(sdata);
+                       ieee80211_set_disassoc(sdata, true);
                        ieee80211_recalc_idle(local);
                        mutex_unlock(&ifmgd->mtx);
                        /*
                        ieee80211_send_deauth_disassoc(sdata, bssid,
                                        IEEE80211_STYPE_DEAUTH,
                                        WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
-                                       NULL);
+                                       NULL, true);
                        mutex_lock(&ifmgd->mtx);
                }
        }
@@@ -1858,6 -1919,9 +1920,9 @@@ int ieee80211_mgd_auth(struct ieee80211
        struct ieee80211_work *wk;
        u16 auth_alg;
  
+       if (req->local_state_change)
+               return 0; /* no need to update mac80211 state */
        switch (req->auth_type) {
        case NL80211_AUTHTYPE_OPEN_SYSTEM:
                auth_alg = WLAN_AUTH_OPEN;
@@@ -1966,7 -2030,7 +2031,7 @@@ int ieee80211_mgd_assoc(struct ieee8021
                }
  
                /* Trying to reassociate - clear previous association state */
-               ieee80211_set_disassoc(sdata);
+               ieee80211_set_disassoc(sdata, true);
        }
        mutex_unlock(&ifmgd->mtx);
  
@@@ -2070,7 -2134,7 +2135,7 @@@ int ieee80211_mgd_deauth(struct ieee802
  
        if (ifmgd->associated == req->bss) {
                bssid = req->bss->bssid;
-               ieee80211_set_disassoc(sdata);
+               ieee80211_set_disassoc(sdata, true);
                mutex_unlock(&ifmgd->mtx);
        } else {
                bool not_auth_yet = false;
        printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
               sdata->name, bssid, req->reason_code);
  
-       ieee80211_send_deauth_disassoc(sdata, bssid,
-                       IEEE80211_STYPE_DEAUTH, req->reason_code,
-                       cookie);
+       ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH,
+                                      req->reason_code, cookie,
+                                      !req->local_state_change);
  
        ieee80211_recalc_idle(sdata->local);
  
@@@ -2127,6 -2191,7 +2192,7 @@@ int ieee80211_mgd_disassoc(struct ieee8
                           void *cookie)
  {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       u8 bssid[ETH_ALEN];
  
        mutex_lock(&ifmgd->mtx);
  
        printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
               sdata->name, req->bss->bssid, req->reason_code);
  
-       ieee80211_set_disassoc(sdata);
+       memcpy(bssid, req->bss->bssid, ETH_ALEN);
+       ieee80211_set_disassoc(sdata, false);
  
        mutex_unlock(&ifmgd->mtx);
  
        ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
                        IEEE80211_STYPE_DISASSOC, req->reason_code,
-                       cookie);
+                       cookie, !req->local_state_change);
+       sta_info_destroy_addr(sdata, bssid);
  
        ieee80211_recalc_idle(sdata->local);
  
@@@ -2198,6 -2265,8 +2266,8 @@@ void ieee80211_cqm_rssi_notify(struct i
  {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
  
+       trace_api_cqm_rssi_notify(sdata, rssi_event);
        cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
  }
  EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
diff --combined net/mac80211/rx.c
index e0c944fb6fc97576db1b3a1a0d2b11be859ce6a6,8ee7db193269766946b29e941e1e8a7145f9f923..72efbd87c1ebdd51a5f752d0c3a892810ed9b619
@@@ -10,7 -10,6 +10,7 @@@
   */
  
  #include <linux/jiffies.h>
 +#include <linux/slab.h>
  #include <linux/kernel.h>
  #include <linux/skbuff.h>
  #include <linux/netdevice.h>
@@@ -39,7 -38,7 +39,7 @@@ static struct sk_buff *remove_monitor_i
  {
        if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
                if (likely(skb->len > FCS_LEN))
-                       skb_trim(skb, skb->len - FCS_LEN);
+                       __pskb_trim(skb, skb->len - FCS_LEN);
                else {
                        /* driver bug */
                        WARN_ON(1);
@@@ -228,6 -227,12 +228,12 @@@ ieee80211_rx_monitor(struct ieee80211_l
        if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
                present_fcs_len = FCS_LEN;
  
+       /* make sure hdr->frame_control is on the linear part */
+       if (!pskb_may_pull(origskb, 2)) {
+               dev_kfree_skb(origskb);
+               return NULL;
+       }
        if (!local->monitors) {
                if (should_drop_frame(origskb, present_fcs_len)) {
                        dev_kfree_skb(origskb);
@@@ -485,7 -490,7 +491,7 @@@ ieee80211_rx_mesh_check(struct ieee8021
  
                if (ieee80211_is_action(hdr->frame_control)) {
                        mgmt = (struct ieee80211_mgmt *)hdr;
-                       if (mgmt->u.action.category != MESH_PLINK_CATEGORY)
+                       if (mgmt->u.action.category != WLAN_CATEGORY_MESH_PLINK)
                                return RX_DROP_MONITOR;
                        return RX_CONTINUE;
                }
@@@ -715,14 -720,16 +721,16 @@@ static void ieee80211_rx_reorder_ampdu(
  
        tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
  
-       if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
-               goto dont_reorder;
+       spin_lock(&sta->lock);
+       if (!sta->ampdu_mlme.tid_active_rx[tid])
+               goto dont_reorder_unlock;
  
        tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
  
        /* qos null data frames are excluded */
        if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
-               goto dont_reorder;
+               goto dont_reorder_unlock;
  
        /* new, potentially un-ordered, ampdu frame - process it */
  
        /* if this mpdu is fragmented - terminate rx aggregation session */
        sc = le16_to_cpu(hdr->seq_ctrl);
        if (sc & IEEE80211_SCTL_FRAG) {
-               ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
-                       tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
+               spin_unlock(&sta->lock);
+               __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
+                                              WLAN_REASON_QSTA_REQUIRE_SETUP);
                dev_kfree_skb(skb);
                return;
        }
  
-       if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames))
+       if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) {
+               spin_unlock(&sta->lock);
                return;
+       }
  
+  dont_reorder_unlock:
+       spin_unlock(&sta->lock);
   dont_reorder:
        __skb_queue_tail(frames, skb);
  }
@@@ -889,6 -901,7 +902,7 @@@ ieee80211_rx_h_decrypt(struct ieee80211
                        rx->key = key;
                return RX_CONTINUE;
        } else {
+               u8 keyid;
                /*
                 * The device doesn't give us the IV so we won't be
                 * able to look up the key. That's ok though, we
                 * no need to call ieee80211_wep_get_keyidx,
                 * it verifies a bunch of things we've done already
                 */
-               keyidx = rx->skb->data[hdrlen + 3] >> 6;
+               skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
+               keyidx = keyid >> 6;
  
                rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
  
                return RX_DROP_MONITOR;
        }
  
+       if (skb_linearize(rx->skb))
+               return RX_DROP_UNUSABLE;
+       hdr = (struct ieee80211_hdr *)rx->skb->data;
        /* Check for weak IVs if possible */
        if (rx->sta && rx->key->conf.alg == ALG_WEP &&
            ieee80211_is_data(hdr->frame_control) &&
@@@ -1232,6 -1251,9 +1252,9 @@@ ieee80211_rx_h_defragment(struct ieee80
        }
        I802_DEBUG_INC(rx->local->rx_handlers_fragments);
  
+       if (skb_linearize(rx->skb))
+               return RX_DROP_UNUSABLE;
        seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
  
        if (frag == 0) {
@@@ -1397,21 -1419,24 +1420,24 @@@ static in
  ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
  {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
        __le16 fc = hdr->frame_control;
-       int res;
  
-       res = ieee80211_drop_unencrypted(rx, fc);
-       if (unlikely(res))
-               return res;
+       /*
+        * Pass through unencrypted frames if the hardware has
+        * decrypted them already.
+        */
+       if (status->flag & RX_FLAG_DECRYPTED)
+               return 0;
  
        if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
-               if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
+               if (unlikely(!ieee80211_has_protected(fc) &&
+                            ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
                             rx->key))
                        return -EACCES;
                /* BIP does not use Protected field, so need to check MMIE */
                if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) &&
-                            ieee80211_get_mmie_keyidx(rx->skb) < 0 &&
-                            rx->key))
+                            ieee80211_get_mmie_keyidx(rx->skb) < 0))
                        return -EACCES;
                /*
                 * When using MFP, Action frames are not allowed prior to
@@@ -1589,6 -1614,9 +1615,9 @@@ ieee80211_rx_h_amsdu(struct ieee80211_r
        skb->dev = dev;
        __skb_queue_head_init(&frame_list);
  
+       if (skb_linearize(skb))
+               return RX_DROP_UNUSABLE;
        ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
                                 rx->sdata->vif.type,
                                 rx->local->hw.extra_tx_headroom);
@@@ -1787,10 -1815,12 +1816,12 @@@ ieee80211_rx_h_ctrl(struct ieee80211_rx
        if (ieee80211_is_back_req(bar->frame_control)) {
                if (!rx->sta)
                        return RX_DROP_MONITOR;
+               spin_lock(&rx->sta->lock);
                tid = le16_to_cpu(bar->control) >> 12;
-               if (rx->sta->ampdu_mlme.tid_state_rx[tid]
-                                       != HT_AGG_STATE_OPERATIONAL)
+               if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) {
+                       spin_unlock(&rx->sta->lock);
                        return RX_DROP_MONITOR;
+               }
                tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
  
                start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
                ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num,
                                                 frames);
                kfree_skb(skb);
+               spin_unlock(&rx->sta->lock);
                return RX_QUEUED;
        }
  
@@@ -1965,8 -1996,8 +1997,8 @@@ ieee80211_rx_h_action(struct ieee80211_
                        goto handled;
                }
                break;
-       case MESH_PLINK_CATEGORY:
-       case MESH_PATH_SEL_CATEGORY:
+       case WLAN_CATEGORY_MESH_PLINK:
+       case WLAN_CATEGORY_MESH_PATH_SEL:
                if (ieee80211_vif_is_mesh(&sdata->vif))
                        return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
                break;
@@@ -2363,29 -2394,42 +2395,42 @@@ static void __ieee80211_rx_handle_packe
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_hdr *hdr;
+       __le16 fc;
        struct ieee80211_rx_data rx;
        int prepares;
        struct ieee80211_sub_if_data *prev = NULL;
        struct sk_buff *skb_new;
        struct sta_info *sta, *tmp;
        bool found_sta = false;
+       int err = 0;
  
-       hdr = (struct ieee80211_hdr *)skb->data;
+       fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
        memset(&rx, 0, sizeof(rx));
        rx.skb = skb;
        rx.local = local;
  
-       if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control))
+       if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
                local->dot11ReceivedFragmentCount++;
  
        if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
                     test_bit(SCAN_OFF_CHANNEL, &local->scanning)))
                rx.flags |= IEEE80211_RX_IN_SCAN;
  
+       if (ieee80211_is_mgmt(fc))
+               err = skb_linearize(skb);
+       else
+               err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
+       if (err) {
+               dev_kfree_skb(skb);
+               return;
+       }
+       hdr = (struct ieee80211_hdr *)skb->data;
        ieee80211_parse_qos(&rx);
        ieee80211_verify_alignment(&rx);
  
-       if (ieee80211_is_data(hdr->frame_control)) {
+       if (ieee80211_is_data(fc)) {
                for_each_sta_info(local, hdr->addr2, sta, tmp) {
                        rx.sta = sta;
                        found_sta = true;
diff --combined net/mac80211/scan.c
index 1ce4ce8af80fb8f2ea3a327d126a422c57cf828f,eb86a5f6e6454bbfa0a62d5a2a69527da550db18..e1a3defdf581c5a0b7bfd62fcc992b01ea40bf68
@@@ -16,7 -16,6 +16,7 @@@
  #include <linux/rtnetlink.h>
  #include <linux/pm_qos_params.h>
  #include <net/sch_generic.h>
 +#include <linux/slab.h>
  #include <net/mac80211.h>
  
  #include "ieee80211_i.h"
@@@ -248,6 -247,8 +248,8 @@@ void ieee80211_scan_completed(struct ie
        struct ieee80211_local *local = hw_to_local(hw);
        bool was_hw_scan;
  
+       trace_api_scan_completed(local, aborted);
        mutex_lock(&local->scan_mtx);
  
        /*
diff --combined net/mac80211/work.c
index 15e1ba931b87616ab1303ff50eb13f2b3c120fc2,7bd8670379dea4c4ce4dd246191c48fa4b979ee7..bdb1d05b16fc7fd3e3cb0a65e248b9cb3b475d39
@@@ -19,7 -19,6 +19,7 @@@
  #include <linux/if_arp.h>
  #include <linux/etherdevice.h>
  #include <linux/crc32.h>
 +#include <linux/slab.h>
  #include <net/mac80211.h>
  #include <asm/unaligned.h>
  
@@@ -920,11 -919,16 +920,16 @@@ static void ieee80211_work_work(struct 
                run_again(local, jiffies + HZ/2);
        }
  
-       if (list_empty(&local->work_list) && local->scan_req)
+       mutex_lock(&local->scan_mtx);
+       if (list_empty(&local->work_list) && local->scan_req &&
+           !local->scanning)
                ieee80211_queue_delayed_work(&local->hw,
                                             &local->scan_work,
                                             round_jiffies_relative(0));
  
+       mutex_unlock(&local->scan_mtx);
        mutex_unlock(&local->work_mtx);
  
        ieee80211_recalc_idle(local);
diff --combined net/wireless/mlme.c
index 4bb734a95f57c23536bff9df27f06b02115cdb1f,387dd2a27d2f5a9a91d8e3d9b111336b8545c03d..48ead6f0426dc9763cc49819f7ac6e613aa36a76
@@@ -8,7 -8,6 +8,7 @@@
  #include <linux/module.h>
  #include <linux/netdevice.h>
  #include <linux/nl80211.h>
 +#include <linux/slab.h>
  #include <linux/wireless.h>
  #include <net/cfg80211.h>
  #include <net/iw_handler.h>
@@@ -378,7 -377,8 +378,8 @@@ int __cfg80211_mlme_auth(struct cfg8021
                         const u8 *bssid,
                         const u8 *ssid, int ssid_len,
                         const u8 *ie, int ie_len,
-                        const u8 *key, int key_len, int key_idx)
+                        const u8 *key, int key_len, int key_idx,
+                        bool local_state_change)
  {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_auth_request req;
  
        memset(&req, 0, sizeof(req));
  
+       req.local_state_change = local_state_change;
        req.ie = ie;
        req.ie_len = ie_len;
        req.auth_type = auth_type;
                goto out;
        }
  
-       wdev->authtry_bsses[slot] = bss;
+       if (local_state_change)
+               wdev->auth_bsses[slot] = bss;
+       else
+               wdev->authtry_bsses[slot] = bss;
        cfg80211_hold_bss(bss);
  
        err = rdev->ops->auth(&rdev->wiphy, dev, &req);
        if (err) {
-               wdev->authtry_bsses[slot] = NULL;
+               if (local_state_change)
+                       wdev->auth_bsses[slot] = NULL;
+               else
+                       wdev->authtry_bsses[slot] = NULL;
                cfg80211_unhold_bss(bss);
        }
  
@@@ -454,14 -461,15 +462,15 @@@ int cfg80211_mlme_auth(struct cfg80211_
                       enum nl80211_auth_type auth_type, const u8 *bssid,
                       const u8 *ssid, int ssid_len,
                       const u8 *ie, int ie_len,
-                      const u8 *key, int key_len, int key_idx)
+                      const u8 *key, int key_len, int key_idx,
+                      bool local_state_change)
  {
        int err;
  
        wdev_lock(dev->ieee80211_ptr);
        err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
                                   ssid, ssid_len, ie, ie_len,
-                                  key, key_len, key_idx);
+                                  key, key_len, key_idx, local_state_change);
        wdev_unlock(dev->ieee80211_ptr);
  
        return err;
@@@ -555,7 -563,8 +564,8 @@@ int cfg80211_mlme_assoc(struct cfg80211
  
  int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
                           struct net_device *dev, const u8 *bssid,
-                          const u8 *ie, int ie_len, u16 reason)
+                          const u8 *ie, int ie_len, u16 reason,
+                          bool local_state_change)
  {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_deauth_request req;
  
        memset(&req, 0, sizeof(req));
        req.reason_code = reason;
+       req.local_state_change = local_state_change;
        req.ie = ie;
        req.ie_len = ie_len;
        if (wdev->current_bss &&
  
  int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
                         struct net_device *dev, const u8 *bssid,
-                        const u8 *ie, int ie_len, u16 reason)
+                        const u8 *ie, int ie_len, u16 reason,
+                        bool local_state_change)
  {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        int err;
  
        wdev_lock(wdev);
-       err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason);
+       err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason,
+                                    local_state_change);
        wdev_unlock(wdev);
  
        return err;
  
  static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
                                    struct net_device *dev, const u8 *bssid,
-                                   const u8 *ie, int ie_len, u16 reason)
+                                   const u8 *ie, int ie_len, u16 reason,
+                                   bool local_state_change)
  {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_disassoc_request req;
  
        memset(&req, 0, sizeof(req));
        req.reason_code = reason;
+       req.local_state_change = local_state_change;
        req.ie = ie;
        req.ie_len = ie_len;
        if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
  
  int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
                           struct net_device *dev, const u8 *bssid,
-                          const u8 *ie, int ie_len, u16 reason)
+                          const u8 *ie, int ie_len, u16 reason,
+                          bool local_state_change)
  {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        int err;
  
        wdev_lock(wdev);
-       err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason);
+       err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason,
+                                      local_state_change);
        wdev_unlock(wdev);
  
        return err;
diff --combined net/wireless/nl80211.c
index 596bf189549a0b17b481e56525daeccad152fff6,df5505b3930c49b70934db9c865dc7ac7003556b..356a84a5daeeb8a0aeaf5706583aac297450635d
@@@ -7,7 -7,6 +7,7 @@@
  #include <linux/if.h>
  #include <linux/module.h>
  #include <linux/err.h>
 +#include <linux/slab.h>
  #include <linux/list.h>
  #include <linux/if_ether.h>
  #include <linux/ieee80211.h>
@@@ -151,6 -150,7 +151,7 @@@ static const struct nla_policy nl80211_
        [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
        [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 },
        [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
+       [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
  };
  
  /* policy for the attributes */
@@@ -2097,7 -2097,8 +2098,8 @@@ static int nl80211_del_station(struct s
                goto out_rtnl;
  
        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) {
+           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
+           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
                err = -EINVAL;
                goto out;
        }
@@@ -3393,6 -3394,7 +3395,7 @@@ static int nl80211_authenticate(struct 
        int err, ssid_len, ie_len = 0;
        enum nl80211_auth_type auth_type;
        struct key_parse key;
+       bool local_state_change;
  
        if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
                return -EINVAL;
                goto out;
        }
  
+       local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
        err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
                                 ssid, ssid_len, ie, ie_len,
-                                key.p.key, key.p.key_len, key.idx);
+                                key.p.key, key.p.key_len, key.idx,
+                                local_state_change);
  
  out:
        cfg80211_unlock_rdev(rdev);
@@@ -3650,6 -3655,7 +3656,7 @@@ static int nl80211_deauthenticate(struc
        const u8 *ie = NULL, *bssid;
        int err, ie_len = 0;
        u16 reason_code;
+       bool local_state_change;
  
        if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
                return -EINVAL;
                ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        }
  
-       err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code);
+       local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
+       err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
+                                  local_state_change);
  
  out:
        cfg80211_unlock_rdev(rdev);
@@@ -3712,6 -3721,7 +3722,7 @@@ static int nl80211_disassociate(struct 
        const u8 *ie = NULL, *bssid;
        int err, ie_len = 0;
        u16 reason_code;
+       bool local_state_change;
  
        if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
                return -EINVAL;
                ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        }
  
-       err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code);
+       local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
+       err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
+                                    local_state_change);
  
  out:
        cfg80211_unlock_rdev(rdev);
diff --combined net/wireless/reg.c
index 422da20d1e5b8a0bad63c8677b2631612905be9e,496348c48506f3c1b19b850d00a77b5457e6f9ab..8f0d97dd3109c54cd85fe01095308171d34d9f01
@@@ -33,7 -33,6 +33,7 @@@
   *
   */
  #include <linux/kernel.h>
 +#include <linux/slab.h>
  #include <linux/list.h>
  #include <linux/random.h>
  #include <linux/nl80211.h>
@@@ -2356,10 -2355,10 +2356,10 @@@ static void print_regdomain(const struc
                                        rdev->country_ie_alpha2[1]);
                        } else
                                printk(KERN_INFO "cfg80211: Current regulatory "
-                                       "domain intersected: \n");
+                                       "domain intersected:\n");
                } else
-                               printk(KERN_INFO "cfg80211: Current regulatory "
-                                       "domain intersected: \n");
+                       printk(KERN_INFO "cfg80211: Current regulatory "
+                               "domain intersected:\n");
        } else if (is_world_regdom(rd->alpha2))
                printk(KERN_INFO "cfg80211: World regulatory "
                        "domain updated:\n");
diff --combined net/wireless/sme.c
index f4dfd5f5f2ea429cb3a6e1d541f419813063ef45,17465777eb476578487d495abc28efa3d163ab66..c2735775ec19d87e2dbf7872a409d5e9d852c51b
@@@ -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>
@@@ -171,7 -170,7 +171,7 @@@ static int cfg80211_conn_do_work(struc
                                            params->ssid, params->ssid_len,
                                            NULL, 0,
                                            params->key, params->key_len,
-                                           params->key_idx);
+                                           params->key_idx, false);
        case CFG80211_CONN_ASSOCIATE_NEXT:
                BUG_ON(!rdev->ops->assoc);
                wdev->conn->state = CFG80211_CONN_ASSOCIATING;
                if (err)
                        __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
                                               NULL, 0,
-                                              WLAN_REASON_DEAUTH_LEAVING);
+                                              WLAN_REASON_DEAUTH_LEAVING,
+                                              false);
                return err;
        case CFG80211_CONN_DEAUTH_ASSOC_FAIL:
                __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
                                       NULL, 0,
-                                      WLAN_REASON_DEAUTH_LEAVING);
+                                      WLAN_REASON_DEAUTH_LEAVING, false);
                /* return an error so that we call __cfg80211_connect_result() */
                return -EINVAL;
        default:
@@@ -676,7 -676,8 +677,8 @@@ void __cfg80211_disconnected(struct net
                                continue;
                        bssid = wdev->auth_bsses[i]->pub.bssid;
                        ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
-                                               WLAN_REASON_DEAUTH_LEAVING);
+                                               WLAN_REASON_DEAUTH_LEAVING,
+                                               false);
                        WARN(ret, "deauth failed: %d\n", ret);
                }
        }
@@@ -935,7 -936,7 +937,7 @@@ int __cfg80211_disconnect(struct cfg802
                /* wdev->conn->params.bssid must be set if > SCANNING */
                err = __cfg80211_mlme_deauth(rdev, dev,
                                             wdev->conn->params.bssid,
-                                            NULL, 0, reason);
+                                            NULL, 0, reason, false);
                if (err)
                        return err;
        } else {
@@@ -991,7 -992,8 +993,8 @@@ void cfg80211_sme_disassoc(struct net_d
  
        memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN);
        if (__cfg80211_mlme_deauth(rdev, dev, bssid,
-                                  NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) {
+                                  NULL, 0, WLAN_REASON_DEAUTH_LEAVING,
+                                  false)) {
                /* whatever -- assume gone anyway */
                cfg80211_unhold_bss(wdev->auth_bsses[idx]);
                cfg80211_put_bss(&wdev->auth_bsses[idx]->pub);
diff --combined net/wireless/util.c
index d3574a4eb3ba1ab837d564c819c50c328aaf2f7e,7acb81b9675dc66597f2f1048ab2675542191939..3416373a9c0c80e91c21f687eb61ec7b91daa626
@@@ -5,7 -5,6 +5,7 @@@
   */
  #include <linux/bitops.h>
  #include <linux/etherdevice.h>
 +#include <linux/slab.h>
  #include <net/cfg80211.h>
  #include <net/ip.h>
  #include "core.h"
@@@ -331,11 -330,18 +331,18 @@@ int ieee80211_data_to_8023(struct sk_bu
                if (iftype == NL80211_IFTYPE_MESH_POINT) {
                        struct ieee80211s_hdr *meshdr =
                                (struct ieee80211s_hdr *) (skb->data + hdrlen);
-                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
+                       /* make sure meshdr->flags is on the linear part */
+                       if (!pskb_may_pull(skb, hdrlen + 1))
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
-                               memcpy(dst, meshdr->eaddr1, ETH_ALEN);
-                               memcpy(src, meshdr->eaddr2, ETH_ALEN);
+                               skb_copy_bits(skb, hdrlen +
+                                       offsetof(struct ieee80211s_hdr, eaddr1),
+                                       dst, ETH_ALEN);
+                               skb_copy_bits(skb, hdrlen +
+                                       offsetof(struct ieee80211s_hdr, eaddr2),
+                                       src, ETH_ALEN);
                        }
+                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
                }
                break;
        case cpu_to_le16(IEEE80211_FCTL_FROMDS):
                if (iftype == NL80211_IFTYPE_MESH_POINT) {
                        struct ieee80211s_hdr *meshdr =
                                (struct ieee80211s_hdr *) (skb->data + hdrlen);
-                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
+                       /* make sure meshdr->flags is on the linear part */
+                       if (!pskb_may_pull(skb, hdrlen + 1))
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A4)
-                               memcpy(src, meshdr->eaddr1, ETH_ALEN);
+                               skb_copy_bits(skb, hdrlen +
+                                       offsetof(struct ieee80211s_hdr, eaddr1),
+                                       src, ETH_ALEN);
+                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
                }
                break;
        case cpu_to_le16(0):
                break;
        }
  
-       if (unlikely(skb->len - hdrlen < 8))
+       if (!pskb_may_pull(skb, hdrlen + 8))
                return -1;
  
        payload = skb->data + hdrlen;