Merge ssh://master.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
authorJohn W. Linville <linville@tuxdriver.com>
Fri, 18 Feb 2011 22:03:41 +0000 (17:03 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 18 Feb 2011 22:03:41 +0000 (17:03 -0500)
Conflicts:
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c

18 files changed:
1  2 
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/wl1251/main.c
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/status.c
net/mac80211/tx.c
net/mac80211/util.c

  
  #define VERSION "1.0"
  
 +#define ATH3K_DNLOAD                          0x01
 +#define ATH3K_GETSTATE                                0x05
 +#define ATH3K_SET_NORMAL_MODE                 0x07
 +#define ATH3K_GETVERSION                      0x09
 +#define USB_REG_SWITCH_VID_PID                        0x0a
 +
 +#define ATH3K_MODE_MASK                               0x3F
 +#define ATH3K_NORMAL_MODE                     0x0E
 +
 +#define ATH3K_PATCH_UPDATE                    0x80
 +#define ATH3K_SYSCFG_UPDATE                   0x40
 +
 +#define ATH3K_XTAL_FREQ_26M                   0x00
 +#define ATH3K_XTAL_FREQ_40M                   0x01
 +#define ATH3K_XTAL_FREQ_19P2                  0x02
 +#define ATH3K_NAME_LEN                                0xFF
 +
 +struct ath3k_version {
 +      unsigned int    rom_version;
 +      unsigned int    build_version;
 +      unsigned int    ram_version;
 +      unsigned char   ref_clock;
 +      unsigned char   reserved[0x07];
 +};
  
  static struct usb_device_id ath3k_table[] = {
        /* Atheros AR3011 */
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03F0, 0x311D) },
  
 +      /* Atheros AR3012 with sflash firmware*/
 +      { USB_DEVICE(0x0CF3, 0x3004) },
 +
+       /* Atheros AR5BBU12 with sflash firmware */
+       { USB_DEVICE(0x0489, 0xE02C) },
++
        { }     /* Terminating entry */
  };
  
  MODULE_DEVICE_TABLE(usb, ath3k_table);
  
 +#define BTUSB_ATH3012         0x80
 +/* This table is to load patch and sysconfig files
 + * for AR3012 */
 +static struct usb_device_id ath3k_blist_tbl[] = {
 +
 +      /* Atheros AR3012 with sflash firmware*/
 +      { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
 +
 +      { }     /* Terminating entry */
 +};
 +
  #define USB_REQ_DFU_DNLOAD    1
  #define BULK_SIZE             4096
 +#define FW_HDR_SIZE           20
  
  static int ath3k_load_firmware(struct usb_device *udev,
                                const struct firmware *firmware)
@@@ -143,265 -106,28 +146,265 @@@ error
        return err;
  }
  
 +static int ath3k_get_state(struct usb_device *udev, unsigned char *state)
 +{
 +      int pipe = 0;
 +
 +      pipe = usb_rcvctrlpipe(udev, 0);
 +      return usb_control_msg(udev, pipe, ATH3K_GETSTATE,
 +                      USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
 +                      state, 0x01, USB_CTRL_SET_TIMEOUT);
 +}
 +
 +static int ath3k_get_version(struct usb_device *udev,
 +                      struct ath3k_version *version)
 +{
 +      int pipe = 0;
 +
 +      pipe = usb_rcvctrlpipe(udev, 0);
 +      return usb_control_msg(udev, pipe, ATH3K_GETVERSION,
 +                      USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version,
 +                      sizeof(struct ath3k_version),
 +                      USB_CTRL_SET_TIMEOUT);
 +}
 +
 +static int ath3k_load_fwfile(struct usb_device *udev,
 +              const struct firmware *firmware)
 +{
 +      u8 *send_buf;
 +      int err, pipe, len, size, count, sent = 0;
 +      int ret;
 +
 +      count = firmware->size;
 +
 +      send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
 +      if (!send_buf) {
 +              BT_ERR("Can't allocate memory chunk for firmware");
 +              return -ENOMEM;
 +      }
 +
 +      size = min_t(uint, count, FW_HDR_SIZE);
 +      memcpy(send_buf, firmware->data, size);
 +
 +      pipe = usb_sndctrlpipe(udev, 0);
 +      ret = usb_control_msg(udev, pipe, ATH3K_DNLOAD,
 +                      USB_TYPE_VENDOR, 0, 0, send_buf,
 +                      size, USB_CTRL_SET_TIMEOUT);
 +      if (ret < 0) {
 +              BT_ERR("Can't change to loading configuration err");
 +              kfree(send_buf);
 +              return ret;
 +      }
 +
 +      sent += size;
 +      count -= size;
 +
 +      while (count) {
 +              size = min_t(uint, count, BULK_SIZE);
 +              pipe = usb_sndbulkpipe(udev, 0x02);
 +
 +              memcpy(send_buf, firmware->data + sent, size);
 +
 +              err = usb_bulk_msg(udev, pipe, send_buf, size,
 +                                      &len, 3000);
 +              if (err || (len != size)) {
 +                      BT_ERR("Error in firmware loading err = %d,"
 +                              "len = %d, size = %d", err, len, size);
 +                      kfree(send_buf);
 +                      return err;
 +              }
 +              sent  += size;
 +              count -= size;
 +      }
 +
 +      kfree(send_buf);
 +      return 0;
 +}
 +
 +static int ath3k_switch_pid(struct usb_device *udev)
 +{
 +      int pipe = 0;
 +
 +      pipe = usb_sndctrlpipe(udev, 0);
 +      return usb_control_msg(udev, pipe, USB_REG_SWITCH_VID_PID,
 +                      USB_TYPE_VENDOR, 0, 0,
 +                      NULL, 0, USB_CTRL_SET_TIMEOUT);
 +}
 +
 +static int ath3k_set_normal_mode(struct usb_device *udev)
 +{
 +      unsigned char fw_state;
 +      int pipe = 0, ret;
 +
 +      ret = ath3k_get_state(udev, &fw_state);
 +      if (ret < 0) {
 +              BT_ERR("Can't get state to change to normal mode err");
 +              return ret;
 +      }
 +
 +      if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) {
 +              BT_DBG("firmware was already in normal mode");
 +              return 0;
 +      }
 +
 +      pipe = usb_sndctrlpipe(udev, 0);
 +      return usb_control_msg(udev, pipe, ATH3K_SET_NORMAL_MODE,
 +                      USB_TYPE_VENDOR, 0, 0,
 +                      NULL, 0, USB_CTRL_SET_TIMEOUT);
 +}
 +
 +static int ath3k_load_patch(struct usb_device *udev)
 +{
 +      unsigned char fw_state;
 +      char filename[ATH3K_NAME_LEN] = {0};
 +      const struct firmware *firmware;
 +      struct ath3k_version fw_version, pt_version;
 +      int ret;
 +
 +      ret = ath3k_get_state(udev, &fw_state);
 +      if (ret < 0) {
 +              BT_ERR("Can't get state to change to load ram patch err");
 +              return ret;
 +      }
 +
 +      if (fw_state & ATH3K_PATCH_UPDATE) {
 +              BT_DBG("Patch was already downloaded");
 +              return 0;
 +      }
 +
 +      ret = ath3k_get_version(udev, &fw_version);
 +      if (ret < 0) {
 +              BT_ERR("Can't get version to change to load ram patch err");
 +              return ret;
 +      }
 +
 +      snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
 +              fw_version.rom_version);
 +
 +      ret = request_firmware(&firmware, filename, &udev->dev);
 +      if (ret < 0) {
 +              BT_ERR("Patch file not found %s", filename);
 +              return ret;
 +      }
 +
 +      pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8);
 +      pt_version.build_version = *(int *)
 +              (firmware->data + firmware->size - 4);
 +
 +      if ((pt_version.rom_version != fw_version.rom_version) ||
 +              (pt_version.build_version <= fw_version.build_version)) {
 +              BT_ERR("Patch file version did not match with firmware");
 +              release_firmware(firmware);
 +              return -EINVAL;
 +      }
 +
 +      ret = ath3k_load_fwfile(udev, firmware);
 +      release_firmware(firmware);
 +
 +      return ret;
 +}
 +
 +static int ath3k_load_syscfg(struct usb_device *udev)
 +{
 +      unsigned char fw_state;
 +      char filename[ATH3K_NAME_LEN] = {0};
 +      const struct firmware *firmware;
 +      struct ath3k_version fw_version;
 +      int clk_value, ret;
 +
 +      ret = ath3k_get_state(udev, &fw_state);
 +      if (ret < 0) {
 +              BT_ERR("Can't get state to change to load configration err");
 +              return -EBUSY;
 +      }
 +
 +      ret = ath3k_get_version(udev, &fw_version);
 +      if (ret < 0) {
 +              BT_ERR("Can't get version to change to load ram patch err");
 +              return ret;
 +      }
 +
 +      switch (fw_version.ref_clock) {
 +
 +      case ATH3K_XTAL_FREQ_26M:
 +              clk_value = 26;
 +              break;
 +      case ATH3K_XTAL_FREQ_40M:
 +              clk_value = 40;
 +              break;
 +      case ATH3K_XTAL_FREQ_19P2:
 +              clk_value = 19;
 +              break;
 +      default:
 +              clk_value = 0;
 +              break;
 +      }
 +
 +      snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
 +              fw_version.rom_version, clk_value, ".dfu");
 +
 +      ret = request_firmware(&firmware, filename, &udev->dev);
 +      if (ret < 0) {
 +              BT_ERR("Configuration file not found %s", filename);
 +              return ret;
 +      }
 +
 +      ret = ath3k_load_fwfile(udev, firmware);
 +      release_firmware(firmware);
 +
 +      return ret;
 +}
 +
  static int ath3k_probe(struct usb_interface *intf,
                        const struct usb_device_id *id)
  {
        const struct firmware *firmware;
        struct usb_device *udev = interface_to_usbdev(intf);
 +      int ret;
  
        BT_DBG("intf %p id %p", intf, id);
  
        if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
                return -ENODEV;
  
 -      if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) {
 -              return -EIO;
 +      /* match device ID in ath3k blacklist table */
 +      if (!id->driver_info) {
 +              const struct usb_device_id *match;
 +              match = usb_match_id(intf, ath3k_blist_tbl);
 +              if (match)
 +                      id = match;
        }
  
 -      if (ath3k_load_firmware(udev, firmware)) {
 -              release_firmware(firmware);
 +      /* load patch and sysconfig files for AR3012 */
 +      if (id->driver_info & BTUSB_ATH3012) {
 +              ret = ath3k_load_patch(udev);
 +              if (ret < 0) {
 +                      BT_ERR("Loading patch file failed");
 +                      return ret;
 +              }
 +              ret = ath3k_load_syscfg(udev);
 +              if (ret < 0) {
 +                      BT_ERR("Loading sysconfig file failed");
 +                      return ret;
 +              }
 +              ret = ath3k_set_normal_mode(udev);
 +              if (ret < 0) {
 +                      BT_ERR("Set normal mode failed");
 +                      return ret;
 +              }
 +              ath3k_switch_pid(udev);
 +              return 0;
 +      }
 +
 +      if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) {
 +              BT_ERR("Error loading firmware");
                return -EIO;
        }
 +
 +      ret = ath3k_load_firmware(udev, firmware);
        release_firmware(firmware);
  
 -      return 0;
 +      return ret;
  }
  
  static void ath3k_disconnect(struct usb_interface *intf)
@@@ -105,9 -105,9 +105,12 @@@ static struct usb_device_id blacklist_t
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
  
 +      /* Atheros 3012 with sflash firmware */
 +      { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_IGNORE },
 +
+       /* Atheros AR5BBU12 with sflash firmware */
+       { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
        /* Broadcom BCM2035 */
        { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
        { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
@@@ -714,11 -714,15 +717,11 @@@ static int btusb_send_frame(struct sk_b
                pipe = usb_sndisocpipe(data->udev,
                                        data->isoc_tx_ep->bEndpointAddress);
  
 -              urb->dev      = data->udev;
 -              urb->pipe     = pipe;
 -              urb->context  = skb;
 -              urb->complete = btusb_isoc_tx_complete;
 -              urb->interval = data->isoc_tx_ep->bInterval;
 +              usb_fill_int_urb(urb, data->udev, pipe,
 +                              skb->data, skb->len, btusb_isoc_tx_complete,
 +                              skb, data->isoc_tx_ep->bInterval);
  
                urb->transfer_flags  = URB_ISO_ASAP;
 -              urb->transfer_buffer = skb->data;
 -              urb->transfer_buffer_length = skb->len;
  
                __fill_isoc_descriptor(urb, skb->len,
                                le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
@@@ -828,7 -832,7 +831,7 @@@ static void btusb_work(struct work_stru
  
        if (hdev->conn_hash.sco_num > 0) {
                if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
-                       err = usb_autopm_get_interface(data->isoc);
+                       err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf);
                        if (err < 0) {
                                clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
                                usb_kill_anchored_urbs(&data->isoc_anchor);
  
                __set_isoc_interface(hdev, 0);
                if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
-                       usb_autopm_put_interface(data->isoc);
+                       usb_autopm_put_interface(data->isoc ? data->isoc : data->intf);
        }
  }
  
@@@ -282,34 -282,6 +282,34 @@@ int ath5k_hw_phy_disable(struct ath5k_h
        return 0;
  }
  
 +/*
 + * Wait for synth to settle
 + */
 +static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah,
 +                      struct ieee80211_channel *channel)
 +{
 +      /*
 +       * On 5211+ read activation -> rx delay
 +       * and use it (100ns steps).
 +       */
 +      if (ah->ah_version != AR5K_AR5210) {
 +              u32 delay;
 +              delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
 +                      AR5K_PHY_RX_DELAY_M;
 +              delay = (channel->hw_value & CHANNEL_CCK) ?
 +                      ((delay << 2) / 22) : (delay / 10);
 +              if (ah->ah_bwmode == AR5K_BWMODE_10MHZ)
 +                      delay = delay << 1;
 +              if (ah->ah_bwmode == AR5K_BWMODE_5MHZ)
 +                      delay = delay << 2;
 +              /* XXX: /2 on turbo ? Let's be safe
 +               * for now */
 +              udelay(100 + delay);
 +      } else {
 +              mdelay(1);
 +      }
 +}
 +
  
  /**********************\
  * RF Gain optimization *
@@@ -1281,6 -1253,7 +1281,7 @@@ static int ath5k_hw_channel(struct ath5
        case AR5K_RF5111:
                ret = ath5k_hw_rf5111_channel(ah, channel);
                break;
+       case AR5K_RF2317:
        case AR5K_RF2425:
                ret = ath5k_hw_rf2425_channel(ah, channel);
                break;
@@@ -3265,13 -3238,6 +3266,13 @@@ int ath5k_hw_phy_init(struct ath5k_hw *
                /* Failed */
                if (i >= 100)
                        return -EIO;
 +
 +              /* Set channel and wait for synth */
 +              ret = ath5k_hw_channel(ah, channel);
 +              if (ret)
 +                      return ret;
 +
 +              ath5k_hw_wait_for_synth(ah, channel);
        }
  
        /*
        if (ret)
                return ret;
  
 +      /* Write OFDM timings on 5212*/
 +      if (ah->ah_version == AR5K_AR5212 &&
 +              channel->hw_value & CHANNEL_OFDM) {
 +
 +              ret = ath5k_hw_write_ofdm_timings(ah, channel);
 +              if (ret)
 +                      return ret;
 +
 +              /* Spur info is available only from EEPROM versions
 +               * greater than 5.3, but the EEPROM routines will use
 +               * static values for older versions */
 +              if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
 +                      ath5k_hw_set_spur_mitigation_filter(ah,
 +                                                          channel);
 +      }
 +
 +      /* If we used fast channel switching
 +       * we are done, release RF bus and
 +       * fire up NF calibration.
 +       *
 +       * Note: Only NF calibration due to
 +       * channel change, not AGC calibration
 +       * since AGC is still running !
 +       */
 +      if (fast) {
 +              /*
 +               * Release RF Bus grant
 +               */
 +              AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
 +                                  AR5K_PHY_RFBUS_REQ_REQUEST);
 +
 +              /*
 +               * Start NF calibration
 +               */
 +              AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
 +                                      AR5K_PHY_AGCCTL_NF);
 +
 +              return ret;
 +      }
 +
        /*
         * For 5210 we do all initialization using
         * initvals, so we don't have to modify
         * any settings (5210 also only supports
         * a/aturbo modes)
         */
 -      if ((ah->ah_version != AR5K_AR5210) && !fast) {
 +      if (ah->ah_version != AR5K_AR5210) {
  
                /*
                 * Write initial RF gain settings
                if (ret)
                        return ret;
  
 -              /* Write OFDM timings on 5212*/
 -              if (ah->ah_version == AR5K_AR5212 &&
 -                      channel->hw_value & CHANNEL_OFDM) {
 -
 -                      ret = ath5k_hw_write_ofdm_timings(ah, channel);
 -                      if (ret)
 -                              return ret;
 -
 -                      /* Spur info is available only from EEPROM versions
 -                       * greater than 5.3, but the EEPROM routines will use
 -                       * static values for older versions */
 -                      if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
 -                              ath5k_hw_set_spur_mitigation_filter(ah,
 -                                                                  channel);
 -              }
 -
                /*Enable/disable 802.11b mode on 5111
                (enable 2111 frequency converter + CCK)*/
                if (ah->ah_radio == AR5K_RF5111) {
         */
        ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
  
 +      ath5k_hw_wait_for_synth(ah, channel);
 +
        /*
 -       * On 5211+ read activation -> rx delay
 -       * and use it.
 +       * Perform ADC test to see if baseband is ready
 +       * Set tx hold and check adc test register
         */
 -      if (ah->ah_version != AR5K_AR5210) {
 -              u32 delay;
 -              delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
 -                      AR5K_PHY_RX_DELAY_M;
 -              delay = (channel->hw_value & CHANNEL_CCK) ?
 -                      ((delay << 2) / 22) : (delay / 10);
 -              if (ah->ah_bwmode == AR5K_BWMODE_10MHZ)
 -                      delay = delay << 1;
 -              if (ah->ah_bwmode == AR5K_BWMODE_5MHZ)
 -                      delay = delay << 2;
 -              /* XXX: /2 on turbo ? Let's be safe
 -               * for now */
 -              udelay(100 + delay);
 -      } else {
 -              mdelay(1);
 -      }
 -
 -      if (fast)
 -              /*
 -               * Release RF Bus grant
 -               */
 -              AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
 -                                  AR5K_PHY_RFBUS_REQ_REQUEST);
 -      else {
 -              /*
 -               * Perform ADC test to see if baseband is ready
 -               * Set tx hold and check adc test register
 -               */
 -              phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
 -              ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
 -              for (i = 0; i <= 20; i++) {
 -                      if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
 -                              break;
 -                      udelay(200);
 -              }
 -              ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
 +      phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
 +      ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
 +      for (i = 0; i <= 20; i++) {
 +              if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
 +                      break;
 +              udelay(200);
        }
 +      ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
  
        /*
         * Start automatic gain control calibration
@@@ -21,7 -21,6 +21,6 @@@
  #include <linux/device.h>
  #include <linux/leds.h>
  #include <linux/completion.h>
- #include <linux/pm_qos_params.h>
  
  #include "debug.h"
  #include "common.h"
@@@ -57,8 -56,6 +56,6 @@@ struct ath_node
  
  #define A_MAX(a, b) ((a) > (b) ? (a) : (b))
  
- #define ATH9K_PM_QOS_DEFAULT_VALUE    55
  #define TSF_TO_TU(_h,_l) \
        ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
  
@@@ -95,9 -92,9 +92,9 @@@ struct ath_config 
   * @BUF_XRETRY: To denote excessive retries of the buffer
   */
  enum buffer_type {
 -      BUF_AMPDU               = BIT(2),
 -      BUF_AGGR                = BIT(3),
 -      BUF_XRETRY              = BIT(5),
 +      BUF_AMPDU               = BIT(0),
 +      BUF_AGGR                = BIT(1),
 +      BUF_XRETRY              = BIT(2),
  };
  
  #define bf_isampdu(bf)                (bf->bf_state.bf_type & BUF_AMPDU)
@@@ -137,6 -134,7 +134,6 @@@ void ath_descdma_cleanup(struct ath_sof
         (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
         WME_AC_VO)
  
 -#define ADDBA_EXCHANGE_ATTEMPTS    10
  #define ATH_AGGR_DELIM_SZ          4
  #define ATH_AGGR_MINPLEN           256 /* in bytes, minimum packet length */
  /* number of delimiters for encryption padding */
@@@ -183,8 -181,7 +180,8 @@@ enum ATH_AGGR_STATUS 
  
  #define ATH_TXFIFO_DEPTH 8
  struct ath_txq {
 -      u32 axq_qnum;
 +      int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
 +      u32 axq_qnum; /* ath9k hardware queue number */
        u32 *axq_link;
        struct list_head axq_q;
        spinlock_t axq_lock;
@@@ -218,6 -215,7 +215,7 @@@ struct ath_frame_info 
  struct ath_buf_state {
        u8 bf_type;
        u8 bfs_paprd;
+       unsigned long bfs_paprd_timestamp;
        enum ath9k_internal_frame_type bfs_ftype;
  };
  
@@@ -233,6 -231,7 +231,6 @@@ struct ath_buf 
        bool bf_stale;
        u16 bf_flags;
        struct ath_buf_state bf_state;
 -      struct ath_wiphy *aphy;
  };
  
  struct ath_atx_tid {
  };
  
  struct ath_node {
 -      struct ath_common *common;
 +#ifdef CONFIG_ATH9K_DEBUGFS
 +      struct list_head list; /* for sc->nodes */
 +      struct ieee80211_sta *sta; /* station struct we're part of */
 +#endif
        struct ath_atx_tid tid[WME_NUM_TID];
        struct ath_atx_ac ac[WME_NUM_AC];
        u16 maxampdu;
@@@ -279,11 -275,6 +277,11 @@@ struct ath_tx_control 
  #define ATH_TX_XRETRY       0x02
  #define ATH_TX_BAR          0x04
  
 +/**
 + * @txq_map:  Index is mac80211 queue number.  This is
 + *  not necessarily the same as the hardware queue number
 + *  (axq_qnum).
 + */
  struct ath_tx {
        u16 seq_no;
        u32 txqsetup;
@@@ -310,8 -301,6 +308,8 @@@ struct ath_rx 
        struct ath_descdma rxdma;
        struct ath_buf *rx_bufptr;
        struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
 +
 +      struct sk_buff *frag;
  };
  
  int ath_startrecv(struct ath_softc *sc);
@@@ -348,10 -337,10 +346,10 @@@ void ath_tx_aggr_resume(struct ath_soft
  
  struct ath_vif {
        int av_bslot;
 +      bool is_bslot_active;
        __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
        enum nl80211_iftype av_opmode;
        struct ath_buf *av_bcbuf;
 -      struct ath_tx_control av_btxctl;
        u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */
  };
  
  #define IEEE80211_MS_TO_TU(x)           (((x) * 1000) / 1024)
  
  struct ath_beacon_config {
 -      u16 beacon_interval;
 +      int beacon_interval;
        u16 listen_interval;
        u16 dtim_period;
        u16 bmiss_timeout;
@@@ -390,6 -379,7 +388,6 @@@ struct ath_beacon 
        u32 ast_be_xmit;
        u64 bc_tstamp;
        struct ieee80211_vif *bslot[ATH_BCBUF];
 -      struct ath_wiphy *bslot_aphy[ATH_BCBUF];
        int slottime;
        int slotupdate;
        struct ath9k_tx_queue_info beacon_qi;
  
  void ath_beacon_tasklet(unsigned long data);
  void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
 -int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif);
 +int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif);
  void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
  int ath_beaconq_config(struct ath_softc *sc);
 +void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
  
  /*******/
  /* ANI */
@@@ -538,6 -527,7 +536,6 @@@ struct ath_ant_comb 
  #define ATH_CABQ_READY_TIME     80      /* % of beacon interval */
  #define ATH_MAX_SW_RETRIES      10
  #define ATH_CHAN_MAX            255
 -#define IEEE80211_WEP_NKID      4       /* number of key ids */
  
  #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
  #define ATH_RATE_DUMMY_MARKER   0
  #define PS_WAIT_FOR_TX_ACK        BIT(3)
  #define PS_BEACON_SYNC            BIT(4)
  
 -struct ath_wiphy;
  struct ath_rate_table;
  
 +struct ath9k_vif_iter_data {
 +      const u8 *hw_macaddr; /* phy's hardware address, set
 +                             * before starting iteration for
 +                             * valid bssid mask.
 +                             */
 +      u8 mask[ETH_ALEN]; /* bssid mask */
 +      int naps;      /* number of AP vifs */
 +      int nmeshes;   /* number of mesh vifs */
 +      int nstations; /* number of station vifs */
 +      int nwds;      /* number of nwd vifs */
 +      int nadhocs;   /* number of adhoc vifs */
 +      int nothers;   /* number of vifs not specified above. */
 +};
 +
  struct ath_softc {
        struct ieee80211_hw *hw;
        struct device *dev;
  
 -      spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
 -      struct ath_wiphy *pri_wiphy;
 -      struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
 -                                     * have NULL entries */
 -      int num_sec_wiphy; /* number of sec_wiphy pointers in the array */
        int chan_idx;
        int chan_is_ht;
 -      struct ath_wiphy *next_wiphy;
 -      struct work_struct chan_work;
 -      int wiphy_select_failures;
 -      unsigned long wiphy_select_first_fail;
 -      struct delayed_work wiphy_work;
 -      unsigned long wiphy_scheduler_int;
 -      int wiphy_scheduler_index;
        struct survey_info *cur_survey;
        struct survey_info survey[ATH9K_NUM_CHANNELS];
  
        struct work_struct paprd_work;
        struct work_struct hw_check_work;
        struct completion paprd_complete;
-       bool paprd_pending;
  
 +      unsigned int hw_busy_count;
 +
        u32 intrstatus;
        u32 sc_flags; /* SC_OP_* */
        u16 ps_flags; /* PS_* */
        u16 curtxpow;
 -      u8 nbcnvifs;
 -      u16 nvifs;
        bool ps_enabled;
        bool ps_idle;
 +      short nbcnvifs;
 +      short nvifs;
        unsigned long ps_usecount;
  
        struct ath_config config;
        int led_on_cnt;
        int led_off_cnt;
  
 -      int beacon_interval;
 +      struct ath9k_hw_cal_data caldata;
 +      int last_rssi;
  
  #ifdef CONFIG_ATH9K_DEBUGFS
        struct ath9k_debug debug;
 +      spinlock_t nodes_lock;
 +      struct list_head nodes; /* basically, stations */
 +      unsigned int tx_complete_poll_work_seen;
  #endif
        struct ath_beacon_config cur_beacon_conf;
        struct delayed_work tx_complete_work;
 +      struct delayed_work hw_pll_work;
        struct ath_btcoex btcoex;
  
        struct ath_descdma txsdma;
  
        struct ath_ant_comb ant_comb;
-       struct pm_qos_request_list pm_qos_req;
  };
  
 -struct ath_wiphy {
 -      struct ath_softc *sc; /* shared for all virtual wiphys */
 -      struct ieee80211_hw *hw;
 -      struct ath9k_hw_cal_data caldata;
 -      enum ath_wiphy_state {
 -              ATH_WIPHY_INACTIVE,
 -              ATH_WIPHY_ACTIVE,
 -              ATH_WIPHY_PAUSING,
 -              ATH_WIPHY_PAUSED,
 -              ATH_WIPHY_SCAN,
 -      } state;
 -      bool idle;
 -      int chan_idx;
 -      int chan_is_ht;
 -      int last_rssi;
 -};
 -
  void ath9k_tasklet(unsigned long data);
  int ath_reset(struct ath_softc *sc, bool retry_tx);
  int ath_cabq_update(struct ath_softc *);
@@@ -665,7 -661,6 +660,6 @@@ static inline void ath_read_cachesize(s
  extern struct ieee80211_ops ath9k_ops;
  extern int ath9k_modparam_nohwcrypt;
  extern int led_blink;
- extern int ath9k_pm_qos_value;
  extern bool is_ath9k_unloaded;
  
  irqreturn_t ath_isr(int irq, void *dev);
@@@ -674,13 -669,14 +668,13 @@@ int ath9k_init_device(u16 devid, struc
                    const struct ath_bus_ops *bus_ops);
  void ath9k_deinit_device(struct ath_softc *sc);
  void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
 -void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
 -                         struct ath9k_channel *ichan);
  int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
                    struct ath9k_channel *hchan);
  
  void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
  void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
  bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
 +bool ath9k_uses_beacons(int type);
  
  #ifdef CONFIG_PCI
  int ath_pci_init(void);
@@@ -704,12 -700,26 +698,12 @@@ void ath9k_ps_restore(struct ath_softc 
  u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
  
  void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 -int ath9k_wiphy_add(struct ath_softc *sc);
 -int ath9k_wiphy_del(struct ath_wiphy *aphy);
 -void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype);
 -int ath9k_wiphy_pause(struct ath_wiphy *aphy);
 -int ath9k_wiphy_unpause(struct ath_wiphy *aphy);
 -int ath9k_wiphy_select(struct ath_wiphy *aphy);
 -void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int);
 -void ath9k_wiphy_chan_work(struct work_struct *work);
 -bool ath9k_wiphy_started(struct ath_softc *sc);
 -void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
 -                                struct ath_wiphy *selected);
 -bool ath9k_wiphy_scanning(struct ath_softc *sc);
 -void ath9k_wiphy_work(struct work_struct *work);
 -bool ath9k_all_wiphys_idle(struct ath_softc *sc);
 -void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle);
 -
 -void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue);
 -bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue);
  
  void ath_start_rfkill_poll(struct ath_softc *sc);
  extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
 +void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
 +                             struct ieee80211_vif *vif,
 +                             struct ath9k_vif_iter_data *iter_data);
 +
  
  #endif /* ATH9K_H */
@@@ -41,10 -41,6 +41,6 @@@ static int ath9k_btcoex_enable
  module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
  MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
  
- int ath9k_pm_qos_value = ATH9K_PM_QOS_DEFAULT_VALUE;
- module_param_named(pmqos, ath9k_pm_qos_value, int, S_IRUSR | S_IRGRP | S_IROTH);
- MODULE_PARM_DESC(pmqos, "User specified PM-QOS value");
  bool is_ath9k_unloaded;
  /* We use the hw_value as an index into our private channel structure */
  
@@@ -254,7 -250,8 +250,7 @@@ static int ath9k_reg_notifier(struct wi
                              struct regulatory_request *request)
  {
        struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah);
  
        return ath_reg_notifier_apply(wiphy, request, reg);
@@@ -441,10 -438,9 +437,10 @@@ static int ath9k_init_queues(struct ath
        sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
        ath_cabq_update(sc);
  
 -      for (i = 0; i < WME_NUM_AC; i++)
 +      for (i = 0; i < WME_NUM_AC; i++) {
                sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
 -
 +              sc->tx.txq_map[i]->mac80211_qnum = i;
 +      }
        return 0;
  }
  
@@@ -516,8 -512,10 +512,8 @@@ static void ath9k_init_misc(struct ath_
  
        sc->beacon.slottime = ATH9K_SLOT_TIME_9;
  
 -      for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
 +      for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
                sc->beacon.bslot[i] = NULL;
 -              sc->beacon.bslot_aphy[i] = NULL;
 -      }
  
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
                sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
@@@ -535,7 -533,6 +531,7 @@@ static int ath9k_init_softc(u16 devid, 
        if (!ah)
                return -ENOMEM;
  
 +      ah->hw = sc->hw;
        ah->hw_version.devid = devid;
        ah->hw_version.subsysid = subsysid;
        sc->sc_ah = ah;
        common->btcoex_enabled = ath9k_btcoex_enable == 1;
        spin_lock_init(&common->cc_lock);
  
 -      spin_lock_init(&sc->wiphy_lock);
        spin_lock_init(&sc->sc_serial_rw);
        spin_lock_init(&sc->sc_pm_lock);
        mutex_init(&sc->mutex);
 +#ifdef CONFIG_ATH9K_DEBUGFS
 +      spin_lock_init(&sc->nodes_lock);
 +      INIT_LIST_HEAD(&sc->nodes);
 +#endif
        tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
        tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
                     (unsigned long)sc);
@@@ -701,6 -695,7 +697,6 @@@ int ath9k_init_device(u16 devid, struc
                    const struct ath_bus_ops *bus_ops)
  {
        struct ieee80211_hw *hw = sc->hw;
 -      struct ath_wiphy *aphy = hw->priv;
        struct ath_common *common;
        struct ath_hw *ah;
        int error = 0;
  
        INIT_WORK(&sc->hw_check_work, ath_hw_check);
        INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
 -      INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
 -      INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
 -      sc->wiphy_scheduler_int = msecs_to_jiffies(500);
 -      aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
 +      sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
  
        ath_init_leds(sc);
        ath_start_rfkill_poll(sc);
  
-       pm_qos_add_request(&sc->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
-                          PM_QOS_DEFAULT_VALUE);
        return 0;
  
  error_world:
@@@ -810,6 -805,7 +803,6 @@@ static void ath9k_deinit_softc(struct a
  void ath9k_deinit_device(struct ath_softc *sc)
  {
        struct ieee80211_hw *hw = sc->hw;
 -      int i = 0;
  
        ath9k_ps_wakeup(sc);
  
  
        ath9k_ps_restore(sc);
  
 -      for (i = 0; i < sc->num_sec_wiphy; i++) {
 -              struct ath_wiphy *aphy = sc->sec_wiphy[i];
 -              if (aphy == NULL)
 -                      continue;
 -              sc->sec_wiphy[i] = NULL;
 -              ieee80211_unregister_hw(aphy->hw);
 -              ieee80211_free_hw(aphy->hw);
 -      }
 -
        ieee80211_unregister_hw(hw);
-       pm_qos_remove_request(&sc->pm_qos_req);
        ath_rx_cleanup(sc);
        ath_tx_cleanup(sc);
        ath9k_deinit_softc(sc);
 -      kfree(sc->sec_wiphy);
  }
  
  void ath_descdma_cleanup(struct ath_softc *sc,
  #include "ath9k.h"
  #include "btcoex.h"
  
 -static void ath_update_txpow(struct ath_softc *sc)
 -{
 -      struct ath_hw *ah = sc->sc_ah;
 -
 -      if (sc->curtxpow != sc->config.txpowlimit) {
 -              ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
 -              /* read back in case value is clamped */
 -              sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
 -      }
 -}
 -
  static u8 parse_mpdudensity(u8 mpdudensity)
  {
        /*
        }
  }
  
 -static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc,
 -                                              struct ieee80211_hw *hw)
 -{
 -      struct ieee80211_channel *curchan = hw->conf.channel;
 -      struct ath9k_channel *channel;
 -      u8 chan_idx;
 -
 -      chan_idx = curchan->hw_value;
 -      channel = &sc->sc_ah->channels[chan_idx];
 -      ath9k_update_ichannel(sc, hw, channel);
 -      return channel;
 -}
 -
  bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
  {
        unsigned long flags;
@@@ -153,12 -177,7 +153,12 @@@ static void ath_update_survey_nf(struc
        }
  }
  
 -static void ath_update_survey_stats(struct ath_softc *sc)
 +/*
 + * Updates the survey statistics and returns the busy time since last
 + * update in %, if the measurement duration was long enough for the
 + * result to be useful, -1 otherwise.
 + */
 +static int ath_update_survey_stats(struct ath_softc *sc)
  {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct survey_info *survey = &sc->survey[pos];
        struct ath_cycle_counters *cc = &common->cc_survey;
        unsigned int div = common->clockrate * 1000;
 +      int ret = 0;
  
        if (!ah->curchan)
 -              return;
 +              return -1;
  
        if (ah->power_mode == ATH9K_PM_AWAKE)
                ath_hw_cycle_counters_update(common);
                survey->channel_time_rx += cc->rx_frame / div;
                survey->channel_time_tx += cc->tx_frame / div;
        }
 +
 +      if (cc->cycles < div)
 +              return -1;
 +
 +      if (cc->cycles > 0)
 +              ret = cc->rx_busy * 100 / cc->cycles;
 +
        memset(cc, 0, sizeof(*cc));
  
        ath_update_survey_nf(sc, pos);
 +
 +      return ret;
  }
  
  /*
  int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
                    struct ath9k_channel *hchan)
  {
 -      struct ath_wiphy *aphy = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ieee80211_conf *conf = &common->hw->conf;
        if (sc->sc_flags & SC_OP_INVALID)
                return -EIO;
  
 +      sc->hw_busy_count = 0;
 +
        del_timer_sync(&common->ani.timer);
        cancel_work_sync(&sc->paprd_work);
        cancel_work_sync(&sc->hw_check_work);
        cancel_delayed_work_sync(&sc->tx_complete_work);
 +      cancel_delayed_work_sync(&sc->hw_pll_work);
  
        ath9k_ps_wakeup(sc);
  
        if (!ath_stoprecv(sc))
                stopped = false;
  
 +      if (!ath9k_hw_check_alive(ah))
 +              stopped = false;
 +
        /* XXX: do not flush receive queue here. We don't want
         * to flush data frames already in queue because of
         * changing channel. */
                fastcc = false;
  
        if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
 -              caldata = &aphy->caldata;
 +              caldata = &sc->caldata;
  
        ath_dbg(common, ATH_DBG_CONFIG,
                "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
                goto ps_restore;
        }
  
 -      ath_update_txpow(sc);
 +      ath9k_cmn_update_txpow(ah, sc->curtxpow,
 +                             sc->config.txpowlimit, &sc->curtxpow);
        ath9k_hw_set_interrupts(ah, ah->imask);
  
        if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
                if (sc->sc_flags & SC_OP_BEACONS)
                        ath_beacon_config(sc, NULL);
                ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
 +              ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
                ath_start_ani(common);
        }
  
   ps_restore:
 +      ieee80211_wake_queues(hw);
 +
        spin_unlock_bh(&sc->sc_pcu_lock);
  
        ath9k_ps_restore(sc);
@@@ -342,7 -342,6 +342,6 @@@ static bool ath_paprd_send_frame(struc
        tx_info->control.rates[1].idx = -1;
  
        init_completion(&sc->paprd_complete);
-       sc->paprd_pending = true;
        txctl.paprd = BIT(chain);
  
        if (ath_tx_start(hw, skb, &txctl) != 0) {
  
        time_left = wait_for_completion_timeout(&sc->paprd_complete,
                        msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
-       sc->paprd_pending = false;
  
        if (!time_left)
                ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE,
@@@ -551,12 -549,6 +549,12 @@@ static void ath_node_attach(struct ath_
        struct ath_hw *ah = sc->sc_ah;
        an = (struct ath_node *)sta->drv_priv;
  
 +#ifdef CONFIG_ATH9K_DEBUGFS
 +      spin_lock(&sc->nodes_lock);
 +      list_add(&an->list, &sc->nodes);
 +      spin_unlock(&sc->nodes_lock);
 +      an->sta = sta;
 +#endif
        if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM)
                sc->sc_flags |= SC_OP_ENABLE_APM;
  
@@@ -572,13 -564,6 +570,13 @@@ static void ath_node_detach(struct ath_
  {
        struct ath_node *an = (struct ath_node *)sta->drv_priv;
  
 +#ifdef CONFIG_ATH9K_DEBUGFS
 +      spin_lock(&sc->nodes_lock);
 +      list_del(&an->list);
 +      spin_unlock(&sc->nodes_lock);
 +      an->sta = NULL;
 +#endif
 +
        if (sc->sc_flags & SC_OP_TXAGGR)
                ath_tx_node_cleanup(sc, an);
  }
  void ath_hw_check(struct work_struct *work)
  {
        struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
 -      int i;
 +      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 +      unsigned long flags;
 +      int busy;
  
        ath9k_ps_wakeup(sc);
 +      if (ath9k_hw_check_alive(sc->sc_ah))
 +              goto out;
  
 -      for (i = 0; i < 3; i++) {
 -              if (ath9k_hw_check_alive(sc->sc_ah))
 -                      goto out;
 +      spin_lock_irqsave(&common->cc_lock, flags);
 +      busy = ath_update_survey_stats(sc);
 +      spin_unlock_irqrestore(&common->cc_lock, flags);
  
 -              msleep(1);
 -      }
 -      ath_reset(sc, true);
 +      ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
 +              "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
 +      if (busy >= 99) {
 +              if (++sc->hw_busy_count >= 3)
 +                      ath_reset(sc, true);
 +      } else if (busy >= 0)
 +              sc->hw_busy_count = 0;
  
  out:
        ath9k_ps_restore(sc);
@@@ -627,15 -604,7 +625,15 @@@ void ath9k_tasklet(unsigned long data
        ath9k_ps_wakeup(sc);
        spin_lock(&sc->sc_pcu_lock);
  
 -      if (!ath9k_hw_check_alive(ah))
 +      /*
 +       * Only run the baseband hang check if beacons stop working in AP or
 +       * IBSS mode, because it has a high false positive rate. For station
 +       * mode it should not be necessary, since the upper layers will detect
 +       * this through a beacon miss automatically and the following channel
 +       * change will trigger a hardware reset anyway
 +       */
 +      if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0 &&
 +          !ath9k_hw_check_alive(ah))
                ieee80211_queue_work(sc->hw, &sc->hw_check_work);
  
        if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
@@@ -814,11 -783,54 +812,11 @@@ chip_reset
  #undef SCHED_INTR
  }
  
 -static u32 ath_get_extchanmode(struct ath_softc *sc,
 -                             struct ieee80211_channel *chan,
 -                             enum nl80211_channel_type channel_type)
 -{
 -      u32 chanmode = 0;
 -
 -      switch (chan->band) {
 -      case IEEE80211_BAND_2GHZ:
 -              switch(channel_type) {
 -              case NL80211_CHAN_NO_HT:
 -              case NL80211_CHAN_HT20:
 -                      chanmode = CHANNEL_G_HT20;
 -                      break;
 -              case NL80211_CHAN_HT40PLUS:
 -                      chanmode = CHANNEL_G_HT40PLUS;
 -                      break;
 -              case NL80211_CHAN_HT40MINUS:
 -                      chanmode = CHANNEL_G_HT40MINUS;
 -                      break;
 -              }
 -              break;
 -      case IEEE80211_BAND_5GHZ:
 -              switch(channel_type) {
 -              case NL80211_CHAN_NO_HT:
 -              case NL80211_CHAN_HT20:
 -                      chanmode = CHANNEL_A_HT20;
 -                      break;
 -              case NL80211_CHAN_HT40PLUS:
 -                      chanmode = CHANNEL_A_HT40PLUS;
 -                      break;
 -              case NL80211_CHAN_HT40MINUS:
 -                      chanmode = CHANNEL_A_HT40MINUS;
 -                      break;
 -              }
 -              break;
 -      default:
 -              break;
 -      }
 -
 -      return chanmode;
 -}
 -
  static void ath9k_bss_assoc_info(struct ath_softc *sc,
                                 struct ieee80211_hw *hw,
                                 struct ieee80211_vif *vif,
                                 struct ieee80211_bss_conf *bss_conf)
  {
 -      struct ath_wiphy *aphy = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
  
                ath_beacon_config(sc, vif);
  
                /* Reset rssi stats */
 -              aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
 +              sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
                sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
  
                sc->sc_flags |= SC_OP_ANI_RUN;
@@@ -869,7 -881,7 +867,7 @@@ void ath_radio_enable(struct ath_softc 
        ath9k_hw_configpcipowersave(ah, 0, 0);
  
        if (!ah->curchan)
 -              ah->curchan = ath_get_curchannel(sc, sc->hw);
 +              ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah);
  
        r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
        if (r) {
                        channel->center_freq, r);
        }
  
 -      ath_update_txpow(sc);
 +      ath9k_cmn_update_txpow(ah, sc->curtxpow,
 +                             sc->config.txpowlimit, &sc->curtxpow);
        if (ath_startrecv(sc) != 0) {
                ath_err(common, "Unable to restart recv logic\n");
                goto out;
@@@ -931,7 -942,7 +929,7 @@@ void ath_radio_disable(struct ath_soft
        ath_flushrecv(sc);              /* flush recv queue */
  
        if (!ah->curchan)
 -              ah->curchan = ath_get_curchannel(sc, hw);
 +              ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
  
        r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
        if (r) {
@@@ -955,8 -966,6 +953,8 @@@ int ath_reset(struct ath_softc *sc, boo
        struct ieee80211_hw *hw = sc->hw;
        int r;
  
 +      sc->hw_busy_count = 0;
 +
        /* Stop ANI */
        del_timer_sync(&common->ani.timer);
  
         * that changes the channel so update any state that
         * might change as a result.
         */
 -      ath_update_txpow(sc);
 +      ath9k_cmn_update_txpow(ah, sc->curtxpow,
 +                             sc->config.txpowlimit, &sc->curtxpow);
  
        if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
                ath_beacon_config(sc, NULL);    /* restart beacons */
        return r;
  }
  
 -/* XXX: Remove me once we don't depend on ath9k_channel for all
 - * this redundant data */
 -void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
 -                         struct ath9k_channel *ichan)
 -{
 -      struct ieee80211_channel *chan = hw->conf.channel;
 -      struct ieee80211_conf *conf = &hw->conf;
 -
 -      ichan->channel = chan->center_freq;
 -      ichan->chan = chan;
 -
 -      if (chan->band == IEEE80211_BAND_2GHZ) {
 -              ichan->chanmode = CHANNEL_G;
 -              ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G;
 -      } else {
 -              ichan->chanmode = CHANNEL_A;
 -              ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
 -      }
 -
 -      if (conf_is_ht(conf))
 -              ichan->chanmode = ath_get_extchanmode(sc, chan,
 -                                          conf->channel_type);
 -}
 -
  /**********************/
  /* mac80211 callbacks */
  /**********************/
  
  static int ath9k_start(struct ieee80211_hw *hw)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ieee80211_channel *curchan = hw->conf.channel;
  
        mutex_lock(&sc->mutex);
  
 -      if (ath9k_wiphy_started(sc)) {
 -              if (sc->chan_idx == curchan->hw_value) {
 -                      /*
 -                       * Already on the operational channel, the new wiphy
 -                       * can be marked active.
 -                       */
 -                      aphy->state = ATH_WIPHY_ACTIVE;
 -                      ieee80211_wake_queues(hw);
 -              } else {
 -                      /*
 -                       * Another wiphy is on another channel, start the new
 -                       * wiphy in paused state.
 -                       */
 -                      aphy->state = ATH_WIPHY_PAUSED;
 -                      ieee80211_stop_queues(hw);
 -              }
 -              mutex_unlock(&sc->mutex);
 -              return 0;
 -      }
 -      aphy->state = ATH_WIPHY_ACTIVE;
 -
        /* setup initial channel */
 -
        sc->chan_idx = curchan->hw_value;
  
 -      init_channel = ath_get_curchannel(sc, hw);
 +      init_channel = ath9k_cmn_get_curchannel(hw, ah);
  
        /* Reset SERDES registers */
        ath9k_hw_configpcipowersave(ah, 0, 0);
         * This is needed only to setup initial state
         * but it's best done after a reset.
         */
 -      ath_update_txpow(sc);
 +      ath9k_cmn_update_txpow(ah, sc->curtxpow,
 +                      sc->config.txpowlimit, &sc->curtxpow);
  
        /*
         * Setup the hardware after reset:
                        ath9k_btcoex_timer_resume(sc);
        }
  
-       /* User has the option to provide pm-qos value as a module
-        * parameter rather than using the default value of
-        * 'ATH9K_PM_QOS_DEFAULT_VALUE'.
-        */
-       pm_qos_update_request(&sc->pm_qos_req, ath9k_pm_qos_value);
        if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
                common->bus_ops->extn_synch_en(common);
  
@@@ -1137,11 -1185,19 +1129,11 @@@ mutex_unlock
  static int ath9k_tx(struct ieee80211_hw *hw,
                    struct sk_buff *skb)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_tx_control txctl;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
  
 -      if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
 -              ath_dbg(common, ATH_DBG_XMIT,
 -                      "ath9k: %s: TX in unexpected wiphy state %d\n",
 -                      wiphy_name(hw->wiphy), aphy->state);
 -              goto exit;
 -      }
 -
        if (sc->ps_enabled) {
                /*
                 * mac80211 does not set PM field for normal data frames, so we
@@@ -1200,26 -1256,44 +1192,26 @@@ exit
  
  static void ath9k_stop(struct ieee80211_hw *hw)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
 -      int i;
  
        mutex_lock(&sc->mutex);
  
 -      aphy->state = ATH_WIPHY_INACTIVE;
 -
        if (led_blink)
                cancel_delayed_work_sync(&sc->ath_led_blink_work);
  
        cancel_delayed_work_sync(&sc->tx_complete_work);
 +      cancel_delayed_work_sync(&sc->hw_pll_work);
        cancel_work_sync(&sc->paprd_work);
        cancel_work_sync(&sc->hw_check_work);
  
 -      for (i = 0; i < sc->num_sec_wiphy; i++) {
 -              if (sc->sec_wiphy[i])
 -                      break;
 -      }
 -
 -      if (i == sc->num_sec_wiphy) {
 -              cancel_delayed_work_sync(&sc->wiphy_work);
 -              cancel_work_sync(&sc->chan_work);
 -      }
 -
        if (sc->sc_flags & SC_OP_INVALID) {
                ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
                mutex_unlock(&sc->mutex);
                return;
        }
  
 -      if (ath9k_wiphy_started(sc)) {
 -              mutex_unlock(&sc->mutex);
 -              return; /* another wiphy still in use */
 -      }
 -
        /* Ensure HW is awake when we try to shut it down. */
        ath9k_ps_wakeup(sc);
  
        } else
                sc->rx.rxlink = NULL;
  
 +      if (sc->rx.frag) {
 +              dev_kfree_skb_any(sc->rx.frag);
 +              sc->rx.frag = NULL;
 +      }
 +
        /* disable HAL and put h/w to sleep */
        ath9k_hw_disable(ah);
        ath9k_hw_configpcipowersave(ah, 1, 1);
        ath9k_ps_restore(sc);
  
        sc->ps_idle = true;
 -      ath9k_set_wiphy_idle(aphy, true);
        ath_radio_disable(sc, hw);
  
        sc->sc_flags |= SC_OP_INVALID;
  
-       pm_qos_update_request(&sc->pm_qos_req, PM_QOS_DEFAULT_VALUE);
        mutex_unlock(&sc->mutex);
  
        ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n");
  }
  
 -static int ath9k_add_interface(struct ieee80211_hw *hw,
 -                             struct ieee80211_vif *vif)
 +bool ath9k_uses_beacons(int type)
 +{
 +      switch (type) {
 +      case NL80211_IFTYPE_AP:
 +      case NL80211_IFTYPE_ADHOC:
 +      case NL80211_IFTYPE_MESH_POINT:
 +              return true;
 +      default:
 +              return false;
 +      }
 +}
 +
 +static void ath9k_reclaim_beacon(struct ath_softc *sc,
 +                               struct ieee80211_vif *vif)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 -      struct ath_hw *ah = sc->sc_ah;
 -      struct ath_common *common = ath9k_hw_common(ah);
        struct ath_vif *avp = (void *)vif->drv_priv;
 -      enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
 -      int ret = 0;
  
 -      mutex_lock(&sc->mutex);
 +      ath9k_set_beaconing_status(sc, false);
 +      ath_beacon_return(sc, avp);
 +      ath9k_set_beaconing_status(sc, true);
 +      sc->sc_flags &= ~SC_OP_BEACONS;
 +}
 +
 +static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 +{
 +      struct ath9k_vif_iter_data *iter_data = data;
 +      int i;
 +
 +      if (iter_data->hw_macaddr)
 +              for (i = 0; i < ETH_ALEN; i++)
 +                      iter_data->mask[i] &=
 +                              ~(iter_data->hw_macaddr[i] ^ mac[i]);
  
        switch (vif->type) {
 -      case NL80211_IFTYPE_STATION:
 -              ic_opmode = NL80211_IFTYPE_STATION;
 +      case NL80211_IFTYPE_AP:
 +              iter_data->naps++;
                break;
 -      case NL80211_IFTYPE_WDS:
 -              ic_opmode = NL80211_IFTYPE_WDS;
 +      case NL80211_IFTYPE_STATION:
 +              iter_data->nstations++;
                break;
        case NL80211_IFTYPE_ADHOC:
 -      case NL80211_IFTYPE_AP:
 +              iter_data->nadhocs++;
 +              break;
        case NL80211_IFTYPE_MESH_POINT:
 -              if (sc->nbcnvifs >= ATH_BCBUF) {
 -                      ret = -ENOBUFS;
 -                      goto out;
 -              }
 -              ic_opmode = vif->type;
 +              iter_data->nmeshes++;
 +              break;
 +      case NL80211_IFTYPE_WDS:
 +              iter_data->nwds++;
                break;
        default:
 -              ath_err(common, "Interface type %d not yet supported\n",
 -                      vif->type);
 -              ret = -EOPNOTSUPP;
 -              goto out;
 +              iter_data->nothers++;
 +              break;
        }
 +}
  
 -      ath_dbg(common, ATH_DBG_CONFIG,
 -              "Attach a VIF of type: %d\n", ic_opmode);
 +/* Called with sc->mutex held. */
 +void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
 +                             struct ieee80211_vif *vif,
 +                             struct ath9k_vif_iter_data *iter_data)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_hw *ah = sc->sc_ah;
 +      struct ath_common *common = ath9k_hw_common(ah);
  
 -      /* Set the VIF opmode */
 -      avp->av_opmode = ic_opmode;
 -      avp->av_bslot = -1;
 +      /*
 +       * Use the hardware MAC address as reference, the hardware uses it
 +       * together with the BSSID mask when matching addresses.
 +       */
 +      memset(iter_data, 0, sizeof(*iter_data));
 +      iter_data->hw_macaddr = common->macaddr;
 +      memset(&iter_data->mask, 0xff, ETH_ALEN);
  
 -      sc->nvifs++;
 +      if (vif)
 +              ath9k_vif_iter(iter_data, vif->addr, vif);
 +
 +      /* Get list of all active MAC addresses */
 +      ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
 +                                                 iter_data);
 +}
 +
 +/* Called with sc->mutex held. */
 +static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
 +                                        struct ieee80211_vif *vif)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_hw *ah = sc->sc_ah;
 +      struct ath_common *common = ath9k_hw_common(ah);
 +      struct ath9k_vif_iter_data iter_data;
  
 -      ath9k_set_bssid_mask(hw, vif);
 +      ath9k_calculate_iter_data(hw, vif, &iter_data);
  
 -      if (sc->nvifs > 1)
 -              goto out; /* skip global settings for secondary vif */
 +      ath9k_ps_wakeup(sc);
 +      /* Set BSSID mask. */
 +      memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
 +      ath_hw_setbssidmask(common);
  
 -      if (ic_opmode == NL80211_IFTYPE_AP) {
 +      /* Set op-mode & TSF */
 +      if (iter_data.naps > 0) {
                ath9k_hw_set_tsfadjust(ah, 1);
                sc->sc_flags |= SC_OP_TSF_RESET;
 -      }
 +              ah->opmode = NL80211_IFTYPE_AP;
 +      } else {
 +              ath9k_hw_set_tsfadjust(ah, 0);
 +              sc->sc_flags &= ~SC_OP_TSF_RESET;
  
 -      /* Set the device opmode */
 -      ah->opmode = ic_opmode;
 +              if (iter_data.nwds + iter_data.nmeshes)
 +                      ah->opmode = NL80211_IFTYPE_AP;
 +              else if (iter_data.nadhocs)
 +                      ah->opmode = NL80211_IFTYPE_ADHOC;
 +              else
 +                      ah->opmode = NL80211_IFTYPE_STATION;
 +      }
  
        /*
         * Enable MIB interrupts when there are hardware phy counters.
 -       * Note we only do this (at the moment) for station mode.
         */
 -      if ((vif->type == NL80211_IFTYPE_STATION) ||
 -          (vif->type == NL80211_IFTYPE_ADHOC) ||
 -          (vif->type == NL80211_IFTYPE_MESH_POINT)) {
 +      if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) {
                if (ah->config.enable_ani)
                        ah->imask |= ATH9K_INT_MIB;
                ah->imask |= ATH9K_INT_TSFOOR;
 +      } else {
 +              ah->imask &= ~ATH9K_INT_MIB;
 +              ah->imask &= ~ATH9K_INT_TSFOOR;
        }
  
        ath9k_hw_set_interrupts(ah, ah->imask);
 +      ath9k_ps_restore(sc);
  
 -      if (vif->type == NL80211_IFTYPE_AP    ||
 -          vif->type == NL80211_IFTYPE_ADHOC) {
 +      /* Set up ANI */
 +      if ((iter_data.naps + iter_data.nadhocs) > 0) {
                sc->sc_flags |= SC_OP_ANI_RUN;
                ath_start_ani(common);
 +      } else {
 +              sc->sc_flags &= ~SC_OP_ANI_RUN;
 +              del_timer_sync(&common->ani.timer);
        }
 +}
  
 -out:
 -      mutex_unlock(&sc->mutex);
 -      return ret;
 +/* Called with sc->mutex held, vif counts set up properly. */
 +static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw,
 +                                 struct ieee80211_vif *vif)
 +{
 +      struct ath_softc *sc = hw->priv;
 +
 +      ath9k_calculate_summary_state(hw, vif);
 +
 +      if (ath9k_uses_beacons(vif->type)) {
 +              int error;
 +              /* This may fail because upper levels do not have beacons
 +               * properly configured yet.  That's OK, we assume it
 +               * will be properly configured and then we will be notified
 +               * in the info_changed method and set up beacons properly
 +               * there.
 +               */
 +              ath9k_set_beaconing_status(sc, false);
 +              error = ath_beacon_alloc(sc, vif);
 +              if (!error)
 +                      ath_beacon_config(sc, vif);
 +              ath9k_set_beaconing_status(sc, true);
 +      }
  }
  
 -static void ath9k_reclaim_beacon(struct ath_softc *sc,
 -                               struct ieee80211_vif *vif)
 +
 +static int ath9k_add_interface(struct ieee80211_hw *hw,
 +                             struct ieee80211_vif *vif)
  {
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_hw *ah = sc->sc_ah;
 +      struct ath_common *common = ath9k_hw_common(ah);
        struct ath_vif *avp = (void *)vif->drv_priv;
 +      int ret = 0;
  
 -      /* Disable SWBA interrupt */
 -      sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
 -      ath9k_ps_wakeup(sc);
 -      ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
 -      ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
 -      tasklet_kill(&sc->bcon_tasklet);
 -      ath9k_ps_restore(sc);
 +      mutex_lock(&sc->mutex);
  
 -      ath_beacon_return(sc, avp);
 -      sc->sc_flags &= ~SC_OP_BEACONS;
 +      switch (vif->type) {
 +      case NL80211_IFTYPE_STATION:
 +      case NL80211_IFTYPE_WDS:
 +      case NL80211_IFTYPE_ADHOC:
 +      case NL80211_IFTYPE_AP:
 +      case NL80211_IFTYPE_MESH_POINT:
 +              break;
 +      default:
 +              ath_err(common, "Interface type %d not yet supported\n",
 +                      vif->type);
 +              ret = -EOPNOTSUPP;
 +              goto out;
 +      }
  
 -      if (sc->nbcnvifs > 0) {
 -              /* Re-enable beaconing */
 -              sc->sc_ah->imask |= ATH9K_INT_SWBA;
 -              ath9k_ps_wakeup(sc);
 -              ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
 -              ath9k_ps_restore(sc);
 +      if (ath9k_uses_beacons(vif->type)) {
 +              if (sc->nbcnvifs >= ATH_BCBUF) {
 +                      ath_err(common, "Not enough beacon buffers when adding"
 +                              " new interface of type: %i\n",
 +                              vif->type);
 +                      ret = -ENOBUFS;
 +                      goto out;
 +              }
 +      }
 +
 +      if ((vif->type == NL80211_IFTYPE_ADHOC) &&
 +          sc->nvifs > 0) {
 +              ath_err(common, "Cannot create ADHOC interface when other"
 +                      " interfaces already exist.\n");
 +              ret = -EINVAL;
 +              goto out;
        }
 +
 +      ath_dbg(common, ATH_DBG_CONFIG,
 +              "Attach a VIF of type: %d\n", vif->type);
 +
 +      /* Set the VIF opmode */
 +      avp->av_opmode = vif->type;
 +      avp->av_bslot = -1;
 +
 +      sc->nvifs++;
 +
 +      ath9k_do_vif_add_setup(hw, vif);
 +out:
 +      mutex_unlock(&sc->mutex);
 +      return ret;
  }
  
  static int ath9k_change_interface(struct ieee80211_hw *hw,
                                  enum nl80211_iftype new_type,
                                  bool p2p)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        int ret = 0;
  
        ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
        mutex_lock(&sc->mutex);
  
 -      switch (new_type) {
 -      case NL80211_IFTYPE_AP:
 -      case NL80211_IFTYPE_ADHOC:
 +      /* See if new interface type is valid. */
 +      if ((new_type == NL80211_IFTYPE_ADHOC) &&
 +          (sc->nvifs > 1)) {
 +              ath_err(common, "When using ADHOC, it must be the only"
 +                      " interface.\n");
 +              ret = -EINVAL;
 +              goto out;
 +      }
 +
 +      if (ath9k_uses_beacons(new_type) &&
 +          !ath9k_uses_beacons(vif->type)) {
                if (sc->nbcnvifs >= ATH_BCBUF) {
                        ath_err(common, "No beacon slot available\n");
                        ret = -ENOBUFS;
                        goto out;
                }
 -              break;
 -      case NL80211_IFTYPE_STATION:
 -              /* Stop ANI */
 -              sc->sc_flags &= ~SC_OP_ANI_RUN;
 -              del_timer_sync(&common->ani.timer);
 -              if ((vif->type == NL80211_IFTYPE_AP) ||
 -                  (vif->type == NL80211_IFTYPE_ADHOC))
 -                      ath9k_reclaim_beacon(sc, vif);
 -              break;
 -      default:
 -              ath_err(common, "Interface type %d not yet supported\n",
 -                              vif->type);
 -              ret = -ENOTSUPP;
 -              goto out;
        }
 +
 +      /* Clean up old vif stuff */
 +      if (ath9k_uses_beacons(vif->type))
 +              ath9k_reclaim_beacon(sc, vif);
 +
 +      /* Add new settings */
        vif->type = new_type;
        vif->p2p = p2p;
  
 +      ath9k_do_vif_add_setup(hw, vif);
  out:
        mutex_unlock(&sc->mutex);
        return ret;
  static void ath9k_remove_interface(struct ieee80211_hw *hw,
                                   struct ieee80211_vif *vif)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
  
        ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
  
        mutex_lock(&sc->mutex);
  
 -      /* Stop ANI */
 -      sc->sc_flags &= ~SC_OP_ANI_RUN;
 -      del_timer_sync(&common->ani.timer);
 +      sc->nvifs--;
  
        /* Reclaim beacon resources */
 -      if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
 -          (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
 -          (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT))
 +      if (ath9k_uses_beacons(vif->type))
                ath9k_reclaim_beacon(sc, vif);
  
 -      sc->nvifs--;
 +      ath9k_calculate_summary_state(hw, NULL);
  
        mutex_unlock(&sc->mutex);
  }
@@@ -1598,11 -1558,12 +1588,11 @@@ static void ath9k_disable_ps(struct ath
  
  static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ieee80211_conf *conf = &hw->conf;
 -      bool disable_radio;
 +      bool disable_radio = false;
  
        mutex_lock(&sc->mutex);
  
         * the end.
         */
        if (changed & IEEE80211_CONF_CHANGE_IDLE) {
 -              bool enable_radio;
 -              bool all_wiphys_idle;
 -              bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 -
 -              spin_lock_bh(&sc->wiphy_lock);
 -              all_wiphys_idle =  ath9k_all_wiphys_idle(sc);
 -              ath9k_set_wiphy_idle(aphy, idle);
 -
 -              enable_radio = (!idle && all_wiphys_idle);
 -
 -              /*
 -               * After we unlock here its possible another wiphy
 -               * can be re-renabled so to account for that we will
 -               * only disable the radio toward the end of this routine
 -               * if by then all wiphys are still idle.
 -               */
 -              spin_unlock_bh(&sc->wiphy_lock);
 -
 -              if (enable_radio) {
 -                      sc->ps_idle = false;
 +              sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 +              if (!sc->ps_idle) {
                        ath_radio_enable(sc, hw);
                        ath_dbg(common, ATH_DBG_CONFIG,
                                "not-idle: enabling radio\n");
 +              } else {
 +                      disable_radio = true;
                }
        }
  
                if (ah->curchan)
                        old_pos = ah->curchan - &ah->channels[0];
  
 -              aphy->chan_idx = pos;
 -              aphy->chan_is_ht = conf_is_ht(conf);
                if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
                        sc->sc_flags |= SC_OP_OFFCHANNEL;
                else
                        sc->sc_flags &= ~SC_OP_OFFCHANNEL;
  
 -              if (aphy->state == ATH_WIPHY_SCAN ||
 -                  aphy->state == ATH_WIPHY_ACTIVE)
 -                      ath9k_wiphy_pause_all_forced(sc, aphy);
 -              else {
 -                      /*
 -                       * Do not change operational channel based on a paused
 -                       * wiphy changes.
 -                       */
 -                      goto skip_chan_change;
 -              }
 -
 -              ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
 -                      curchan->center_freq);
 +              ath_dbg(common, ATH_DBG_CONFIG,
 +                      "Set channel: %d MHz type: %d\n",
 +                      curchan->center_freq, conf->channel_type);
  
 -              /* XXX: remove me eventualy */
 -              ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]);
 +              ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
 +                                        curchan, conf->channel_type);
  
                /* update survey stats for the old channel before switching */
                spin_lock_irqsave(&common->cc_lock, flags);
                        ath_update_survey_nf(sc, old_pos);
        }
  
 -skip_chan_change:
        if (changed & IEEE80211_CONF_CHANGE_POWER) {
 +              ath_dbg(common, ATH_DBG_CONFIG,
 +                      "Set power: %d\n", conf->power_level);
                sc->config.txpowlimit = 2 * conf->power_level;
                ath9k_ps_wakeup(sc);
 -              ath_update_txpow(sc);
 +              ath9k_cmn_update_txpow(ah, sc->curtxpow,
 +                                     sc->config.txpowlimit, &sc->curtxpow);
                ath9k_ps_restore(sc);
        }
  
 -      spin_lock_bh(&sc->wiphy_lock);
 -      disable_radio = ath9k_all_wiphys_idle(sc);
 -      spin_unlock_bh(&sc->wiphy_lock);
 -
        if (disable_radio) {
                ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
 -              sc->ps_idle = true;
                ath_radio_disable(sc, hw);
        }
  
@@@ -1748,7 -1740,8 +1738,7 @@@ static void ath9k_configure_filter(stru
                                   unsigned int *total_flags,
                                   u64 multicast)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        u32 rfilt;
  
        changed_flags &= SUPPORTED_FILTERS;
@@@ -1768,7 -1761,8 +1758,7 @@@ static int ath9k_sta_add(struct ieee802
                         struct ieee80211_vif *vif,
                         struct ieee80211_sta *sta)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
  
        ath_node_attach(sc, sta);
  
@@@ -1779,7 -1773,8 +1769,7 @@@ static int ath9k_sta_remove(struct ieee
                            struct ieee80211_vif *vif,
                            struct ieee80211_sta *sta)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
  
        ath_node_detach(sc, sta);
  
  static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
                         const struct ieee80211_tx_queue_params *params)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_txq *txq;
        struct ath9k_tx_queue_info qi;
@@@ -1833,7 -1829,8 +1823,7 @@@ static int ath9k_set_key(struct ieee802
                         struct ieee80211_sta *sta,
                         struct ieee80211_key_conf *key)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        int ret = 0;
  
@@@ -1877,8 -1874,8 +1867,8 @@@ static void ath9k_bss_info_changed(stru
                                   struct ieee80211_bss_conf *bss_conf,
                                   u32 changed)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath_vif *avp = (void *)vif->drv_priv;
        /* Enable transmission of beacons (AP, IBSS, MESH) */
        if ((changed & BSS_CHANGED_BEACON) ||
            ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) {
 -              ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
 -              error = ath_beacon_alloc(aphy, vif);
 +              ath9k_set_beaconing_status(sc, false);
 +              error = ath_beacon_alloc(sc, vif);
                if (!error)
                        ath_beacon_config(sc, vif);
 +              ath9k_set_beaconing_status(sc, true);
        }
  
        if (changed & BSS_CHANGED_ERP_SLOT) {
        }
  
        /* Disable transmission of beacons */
 -      if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon)
 -              ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
 +      if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
 +          !bss_conf->enable_beacon) {
 +              ath9k_set_beaconing_status(sc, false);
 +              avp->is_bslot_active = false;
 +              ath9k_set_beaconing_status(sc, true);
 +      }
  
        if (changed & BSS_CHANGED_BEACON_INT) {
 -              sc->beacon_interval = bss_conf->beacon_int;
 +              cur_conf->beacon_interval = bss_conf->beacon_int;
                /*
                 * In case of AP mode, the HW TSF has to be reset
                 * when the beacon interval changes.
                 */
                if (vif->type == NL80211_IFTYPE_AP) {
                        sc->sc_flags |= SC_OP_TSF_RESET;
 -                      ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
 -                      error = ath_beacon_alloc(aphy, vif);
 +                      ath9k_set_beaconing_status(sc, false);
 +                      error = ath_beacon_alloc(sc, vif);
                        if (!error)
                                ath_beacon_config(sc, vif);
 +                      ath9k_set_beaconing_status(sc, true);
                } else {
                        ath_beacon_config(sc, vif);
                }
  
  static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
  {
 +      struct ath_softc *sc = hw->priv;
        u64 tsf;
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
  
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
  
  static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
  
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
  
  static void ath9k_reset_tsf(struct ieee80211_hw *hw)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
  
        mutex_lock(&sc->mutex);
  
@@@ -2029,9 -2023,10 +2019,9 @@@ static int ath9k_ampdu_action(struct ie
                              struct ieee80211_vif *vif,
                              enum ieee80211_ampdu_mlme_action action,
                              struct ieee80211_sta *sta,
 -                            u16 tid, u16 *ssn)
 +                            u16 tid, u16 *ssn, u8 buf_size)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        int ret = 0;
  
        local_bh_disable();
  static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
                             struct survey_info *survey)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ieee80211_supported_band *sband;
        struct ieee80211_channel *chan;
        return 0;
  }
  
 -static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
 -{
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 -
 -      mutex_lock(&sc->mutex);
 -      if (ath9k_wiphy_scanning(sc)) {
 -              /*
 -               * There is a race here in mac80211 but fixing it requires
 -               * we revisit how we handle the scan complete callback.
 -               * After mac80211 fixes we will not have configured hardware
 -               * to the home channel nor would we have configured the RX
 -               * filter yet.
 -               */
 -              mutex_unlock(&sc->mutex);
 -              return;
 -      }
 -
 -      aphy->state = ATH_WIPHY_SCAN;
 -      ath9k_wiphy_pause_all_forced(sc, aphy);
 -      mutex_unlock(&sc->mutex);
 -}
 -
 -/*
 - * XXX: this requires a revisit after the driver
 - * scan_complete gets moved to another place/removed in mac80211.
 - */
 -static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
 -{
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 -
 -      mutex_lock(&sc->mutex);
 -      aphy->state = ATH_WIPHY_ACTIVE;
 -      mutex_unlock(&sc->mutex);
 -}
 -
  static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
  
        mutex_lock(&sc->mutex);
@@@ -2140,6 -2174,8 +2130,6 @@@ struct ieee80211_ops ath9k_ops = 
        .reset_tsf          = ath9k_reset_tsf,
        .ampdu_action       = ath9k_ampdu_action,
        .get_survey         = ath9k_get_survey,
 -      .sw_scan_start      = ath9k_sw_scan_start,
 -      .sw_scan_complete   = ath9k_sw_scan_complete,
        .rfkill_poll        = ath9k_rfkill_poll_state,
        .set_coverage_class = ath9k_set_coverage_class,
  };
@@@ -19,6 -19,7 +19,6 @@@
  
  #define BITS_PER_BYTE           8
  #define OFDM_PLCP_BITS          22
 -#define HT_RC_2_MCS(_rc)        ((_rc) & 0x1f)
  #define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
  #define L_STF                   8
  #define L_LTF                   8
@@@ -31,6 -32,7 +31,6 @@@
  #define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
  #define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
  
 -#define OFDM_SIFS_TIME            16
  
  static u16 bits_per_symbol[][2] = {
        /* 20MHz 40MHz */
@@@ -55,9 -57,8 +55,9 @@@ static void ath_tx_complete_buf(struct 
  static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
                             struct list_head *head);
  static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
 -static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
 -                           int nframes, int nbad, int txok, bool update_rc);
 +static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
 +                           struct ath_tx_status *ts, int nframes, int nbad,
 +                           int txok, bool update_rc);
  static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
                              int seqno);
  
@@@ -168,7 -169,7 +168,7 @@@ static void ath_tx_flush_tid(struct ath
                        ath_tx_update_baw(sc, tid, fi->seqno);
                        ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
                } else {
 -                      ath_tx_send_normal(sc, txq, tid, &bf_head);
 +                      ath_tx_send_normal(sc, txq, NULL, &bf_head);
                }
                spin_lock_bh(&txq->axq_lock);
        }
@@@ -296,6 -297,7 +296,6 @@@ static struct ath_buf* ath_clone_txbuf(
  
        ATH_TXBUF_RESET(tbf);
  
 -      tbf->aphy = bf->aphy;
        tbf->bf_mpdu = bf->bf_mpdu;
        tbf->bf_buf_addr = bf->bf_buf_addr;
        memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
@@@ -343,7 -345,7 +343,7 @@@ static void ath_tx_complete_aggr(struc
        struct ath_node *an = NULL;
        struct sk_buff *skb;
        struct ieee80211_sta *sta;
 -      struct ieee80211_hw *hw;
 +      struct ieee80211_hw *hw = sc->hw;
        struct ieee80211_hdr *hdr;
        struct ieee80211_tx_info *tx_info;
        struct ath_atx_tid *tid = NULL;
        hdr = (struct ieee80211_hdr *)skb->data;
  
        tx_info = IEEE80211_SKB_CB(skb);
 -      hw = bf->aphy->hw;
  
        memcpy(rates, tx_info->control.rates, sizeof(rates));
  
                            !bf->bf_stale || bf_next != NULL)
                                list_move_tail(&bf->list, &bf_head);
  
 -                      ath_tx_rc_status(bf, ts, 1, 1, 0, false);
 +                      ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
                        ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
                                0, 0);
  
  
        ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
        while (bf) {
 -              txfail = txpending = 0;
 +              txfail = txpending = sendbar = 0;
                bf_next = bf->bf_next;
  
                skb = bf->bf_mpdu;
  
                        if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
                                memcpy(tx_info->control.rates, rates, sizeof(rates));
 -                              ath_tx_rc_status(bf, ts, nframes, nbad, txok, true);
 +                              ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true);
                                rc_update = false;
                        } else {
 -                              ath_tx_rc_status(bf, ts, nframes, nbad, txok, false);
 +                              ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false);
                        }
  
                        ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
  
                                                bf->bf_state.bf_type |=
                                                        BUF_XRETRY;
 -                                              ath_tx_rc_status(bf, ts, nframes,
 +                                              ath_tx_rc_status(sc, bf, ts, nframes,
                                                                nbad, 0, false);
                                                ath_tx_complete_buf(sc, bf, txq,
                                                                    &bf_head,
  
        rcu_read_unlock();
  
 -      if (needreset)
 +      if (needreset) {
 +              spin_unlock_bh(&sc->sc_pcu_lock);
                ath_reset(sc, false);
 +              spin_lock_bh(&sc->sc_pcu_lock);
 +      }
  }
  
  static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
@@@ -856,10 -856,7 +856,10 @@@ int ath_tx_aggr_start(struct ath_softc 
  
        txtid->state |= AGGR_ADDBA_PROGRESS;
        txtid->paused = true;
 -      *ssn = txtid->seq_start;
 +      *ssn = txtid->seq_start = txtid->seq_next;
 +
 +      memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
 +      txtid->baw_head = txtid->baw_tail = 0;
  
        return 0;
  }
@@@ -945,7 -942,7 +945,7 @@@ struct ath_txq *ath_txq_setup(struct at
                [WME_AC_VI] = ATH_TXQ_AC_VI,
                [WME_AC_VO] = ATH_TXQ_AC_VO,
        };
 -      int qnum, i;
 +      int axq_qnum, i;
  
        memset(&qi, 0, sizeof(qi));
        qi.tqi_subtype = subtype_txq_to_hwq[subtype];
                        qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
                                        TXQ_FLAG_TXDESCINT_ENABLE;
        }
 -      qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
 -      if (qnum == -1) {
 +      axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
 +      if (axq_qnum == -1) {
                /*
                 * NB: don't print a message, this happens
                 * normally on parts with too few tx queues
                 */
                return NULL;
        }
 -      if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
 +      if (axq_qnum >= ARRAY_SIZE(sc->tx.txq)) {
                ath_err(common, "qnum %u out of range, max %zu!\n",
 -                      qnum, ARRAY_SIZE(sc->tx.txq));
 -              ath9k_hw_releasetxqueue(ah, qnum);
 +                      axq_qnum, ARRAY_SIZE(sc->tx.txq));
 +              ath9k_hw_releasetxqueue(ah, axq_qnum);
                return NULL;
        }
 -      if (!ATH_TXQ_SETUP(sc, qnum)) {
 -              struct ath_txq *txq = &sc->tx.txq[qnum];
 +      if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
 +              struct ath_txq *txq = &sc->tx.txq[axq_qnum];
  
 -              txq->axq_qnum = qnum;
 +              txq->axq_qnum = axq_qnum;
 +              txq->mac80211_qnum = -1;
                txq->axq_link = NULL;
                INIT_LIST_HEAD(&txq->axq_q);
                INIT_LIST_HEAD(&txq->axq_acq);
                txq->axq_depth = 0;
                txq->axq_ampdu_depth = 0;
                txq->axq_tx_inprogress = false;
 -              sc->tx.txqsetup |= 1<<qnum;
 +              sc->tx.txqsetup |= 1<<axq_qnum;
  
                txq->txq_headidx = txq->txq_tailidx = 0;
                for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
                        INIT_LIST_HEAD(&txq->txq_fifo[i]);
                INIT_LIST_HEAD(&txq->txq_fifo_pending);
        }
 -      return &sc->tx.txq[qnum];
 +      return &sc->tx.txq[axq_qnum];
  }
  
  int ath_txq_update(struct ath_softc *sc, int qnum,
  int ath_cabq_update(struct ath_softc *sc)
  {
        struct ath9k_tx_queue_info qi;
 +      struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
        int qnum = sc->beacon.cabq->axq_qnum;
  
        ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
        else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
                sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
  
 -      qi.tqi_readyTime = (sc->beacon_interval *
 +      qi.tqi_readyTime = (cur_conf->beacon_interval *
                            sc->config.cabqReadytime) / 100;
        ath_txq_update(sc, qnum, &qi);
  
@@@ -1210,17 -1205,8 +1210,17 @@@ bool ath_drain_all_txq(struct ath_soft
                ath_err(common, "Failed to stop TX DMA!\n");
  
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
 -              if (ATH_TXQ_SETUP(sc, i))
 -                      ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
 +              if (!ATH_TXQ_SETUP(sc, i))
 +                      continue;
 +
 +              /*
 +               * The caller will resume queues with ieee80211_wake_queues.
 +               * Mark the queue as not stopped to prevent ath_tx_complete
 +               * from waking the queue too early.
 +               */
 +              txq = &sc->tx.txq[i];
 +              txq->stopped = false;
 +              ath_draintxq(sc, txq, retry_tx);
        }
  
        return !npend;
@@@ -1232,59 -1218,46 +1232,59 @@@ void ath_tx_cleanupq(struct ath_softc *
        sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
  }
  
 +/* For each axq_acq entry, for each tid, try to schedule packets
 + * for transmit until ampdu_depth has reached min Q depth.
 + */
  void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
  {
 -      struct ath_atx_ac *ac;
 -      struct ath_atx_tid *tid;
 +      struct ath_atx_ac *ac, *ac_tmp, *last_ac;
 +      struct ath_atx_tid *tid, *last_tid;
  
 -      if (list_empty(&txq->axq_acq))
 +      if (list_empty(&txq->axq_acq) ||
 +          txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
                return;
  
        ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
 -      list_del(&ac->list);
 -      ac->sched = false;
 +      last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
  
 -      do {
 -              if (list_empty(&ac->tid_q))
 -                      return;
 +      list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
 +              last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
 +              list_del(&ac->list);
 +              ac->sched = false;
  
 -              tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list);
 -              list_del(&tid->list);
 -              tid->sched = false;
 +              while (!list_empty(&ac->tid_q)) {
 +                      tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
 +                                             list);
 +                      list_del(&tid->list);
 +                      tid->sched = false;
  
 -              if (tid->paused)
 -                      continue;
 +                      if (tid->paused)
 +                              continue;
  
 -              ath_tx_sched_aggr(sc, txq, tid);
 +                      ath_tx_sched_aggr(sc, txq, tid);
  
 -              /*
 -               * add tid to round-robin queue if more frames
 -               * are pending for the tid
 -               */
 -              if (!list_empty(&tid->buf_q))
 -                      ath_tx_queue_tid(txq, tid);
 +                      /*
 +                       * add tid to round-robin queue if more frames
 +                       * are pending for the tid
 +                       */
 +                      if (!list_empty(&tid->buf_q))
 +                              ath_tx_queue_tid(txq, tid);
  
 -              break;
 -      } while (!list_empty(&ac->tid_q));
 +                      if (tid == last_tid ||
 +                          txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
 +                              break;
 +              }
  
 -      if (!list_empty(&ac->tid_q)) {
 -              if (!ac->sched) {
 -                      ac->sched = true;
 -                      list_add_tail(&ac->list, &txq->axq_acq);
 +              if (!list_empty(&ac->tid_q)) {
 +                      if (!ac->sched) {
 +                              ac->sched = true;
 +                              list_add_tail(&ac->list, &txq->axq_acq);
 +                      }
                }
 +
 +              if (ac == last_ac ||
 +                  txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
 +                      return;
        }
  }
  
@@@ -1328,7 -1301,6 +1328,7 @@@ static void ath_tx_txqaddbuf(struct ath
                INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
                list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
                INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
 +              TX_STAT_INC(txq->axq_qnum, puttxbuf);
                ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
                ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
                        txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
                list_splice_tail_init(head, &txq->axq_q);
  
                if (txq->axq_link == NULL) {
 +                      TX_STAT_INC(txq->axq_qnum, puttxbuf);
                        ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
                        ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
                                txq->axq_qnum, ito64(bf->bf_daddr),
                }
                ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
                                       &txq->axq_link);
 +              TX_STAT_INC(txq->axq_qnum, txstart);
                ath9k_hw_txstart(ah, txq->axq_qnum);
        }
        txq->axq_depth++;
@@@ -1365,6 -1335,7 +1365,6 @@@ static void ath_tx_send_ampdu(struct at
        struct list_head bf_head;
  
        bf->bf_state.bf_type |= BUF_AMPDU;
 -      TX_STAT_INC(txctl->txq->axq_qnum, a_queued);
  
        /*
         * Do not queue to h/w when any of the following conditions is true:
                 * Add this frame to software queue for scheduling later
                 * for aggregation.
                 */
 +              TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
                list_add_tail(&bf->list, &tid->buf_q);
                ath_tx_queue_tid(txctl->txq, tid);
                return;
                ath_tx_addto_baw(sc, tid, fi->seqno);
  
        /* Queue to h/w without aggregation */
 +      TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
        bf->bf_lastbf = bf;
        ath_buf_set_rate(sc, bf, fi->framelen);
        ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
@@@ -1447,7 -1416,8 +1447,7 @@@ static enum ath9k_pkt_type get_hw_packe
  static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
                             int framelen)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ieee80211_sta *sta = tx_info->control.sta;
        struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
@@@ -1665,7 -1635,8 +1665,7 @@@ static struct ath_buf *ath_tx_setup_buf
                                           struct ath_txq *txq,
                                           struct sk_buff *skb)
  {
 -      struct ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_frame_info *fi = get_frame_info(skb);
  
        ATH_TXBUF_RESET(bf);
  
 -      bf->aphy = aphy;
        bf->bf_flags = setup_tx_flags(skb);
        bf->bf_mpdu = skb;
  
@@@ -1753,6 -1725,9 +1753,9 @@@ static void ath_tx_start_dma(struct ath
                        ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc,
                                                   bf->bf_state.bfs_paprd);
  
+               if (txctl->paprd)
+                       bf->bf_state.bfs_paprd_timestamp = jiffies;
                ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
        }
  
@@@ -1766,7 -1741,8 +1769,7 @@@ int ath_tx_start(struct ieee80211_hw *h
        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 ath_wiphy *aphy = hw->priv;
 -      struct ath_softc *sc = aphy->sc;
 +      struct ath_softc *sc = hw->priv;
        struct ath_txq *txq = txctl->txq;
        struct ath_buf *bf;
        int padpos, padsize;
        spin_lock_bh(&txq->axq_lock);
        if (txq == sc->tx.txq_map[q] &&
            ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
 -              ath_mac80211_stop_queue(sc, q);
 +              ieee80211_stop_queue(sc->hw, q);
                txq->stopped = 1;
        }
        spin_unlock_bh(&txq->axq_lock);
  /*****************/
  
  static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 -                          struct ath_wiphy *aphy, int tx_flags, int ftype,
 -                          struct ath_txq *txq)
 +                          int tx_flags, int ftype, struct ath_txq *txq)
  {
        struct ieee80211_hw *hw = sc->hw;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
  
        ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
  
 -      if (aphy)
 -              hw = aphy->hw;
 -
        if (tx_flags & ATH_TX_BAR)
                tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
  
                                        PS_WAIT_FOR_TX_ACK));
        }
  
 -      if (unlikely(ftype))
 -              ath9k_tx_status(hw, skb, ftype);
 -      else {
 -              q = skb_get_queue_mapping(skb);
 -              if (txq == sc->tx.txq_map[q]) {
 -                      spin_lock_bh(&txq->axq_lock);
 -                      if (WARN_ON(--txq->pending_frames < 0))
 -                              txq->pending_frames = 0;
 -                      spin_unlock_bh(&txq->axq_lock);
 -              }
 +      q = skb_get_queue_mapping(skb);
 +      if (txq == sc->tx.txq_map[q]) {
 +              spin_lock_bh(&txq->axq_lock);
 +              if (WARN_ON(--txq->pending_frames < 0))
 +                      txq->pending_frames = 0;
  
 -              ieee80211_tx_status(hw, skb);
 +              if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
 +                      ieee80211_wake_queue(sc->hw, q);
 +                      txq->stopped = 0;
 +              }
 +              spin_unlock_bh(&txq->axq_lock);
        }
 +
 +      ieee80211_tx_status(hw, skb);
  }
  
  static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
        bf->bf_buf_addr = 0;
  
        if (bf->bf_state.bfs_paprd) {
-               if (!sc->paprd_pending)
+               if (time_after(jiffies,
+                               bf->bf_state.bfs_paprd_timestamp +
+                               msecs_to_jiffies(ATH_PAPRD_TIMEOUT)))
                        dev_kfree_skb_any(skb);
                else
                        complete(&sc->paprd_complete);
        } else {
 -              ath_debug_stat_tx(sc, bf, ts);
 -              ath_tx_complete(sc, skb, bf->aphy, tx_flags,
 +              ath_debug_stat_tx(sc, bf, ts, txq);
 +              ath_tx_complete(sc, skb, tx_flags,
                                bf->bf_state.bfs_ftype, txq);
        }
        /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
        spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
  }
  
 -static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
 -                           int nframes, int nbad, int txok, bool update_rc)
 +static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
 +                           struct ath_tx_status *ts, int nframes, int nbad,
 +                           int txok, bool update_rc)
  {
        struct sk_buff *skb = bf->bf_mpdu;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 -      struct ieee80211_hw *hw = bf->aphy->hw;
 -      struct ath_softc *sc = bf->aphy->sc;
 +      struct ieee80211_hw *hw = sc->hw;
        struct ath_hw *ah = sc->sc_ah;
        u8 i, tx_rateindex;
  
        tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
  }
  
 -static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum)
 -{
 -      struct ath_txq *txq;
 -
 -      txq = sc->tx.txq_map[qnum];
 -      spin_lock_bh(&txq->axq_lock);
 -      if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
 -              if (ath_mac80211_start_queue(sc, qnum))
 -                      txq->stopped = 0;
 -      }
 -      spin_unlock_bh(&txq->axq_lock);
 -}
 -
  static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
  {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_tx_status ts;
        int txok;
        int status;
 -      int qnum;
  
        ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
                txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
                spin_lock_bh(&txq->axq_lock);
                if (list_empty(&txq->axq_q)) {
                        txq->axq_link = NULL;
 +                      if (sc->sc_flags & SC_OP_TXAGGR)
 +                              ath_txq_schedule(sc, txq);
                        spin_unlock_bh(&txq->axq_lock);
                        break;
                }
                        spin_unlock_bh(&txq->axq_lock);
                        break;
                }
 +              TX_STAT_INC(txq->axq_qnum, txprocdesc);
  
                /*
                 * Remove ath_buf's of the same transmit unit from txq,
                         */
                        if (ts.ts_status & ATH9K_TXERR_XRETRY)
                                bf->bf_state.bf_type |= BUF_XRETRY;
 -                      ath_tx_rc_status(bf, &ts, 1, txok ? 0 : 1, txok, true);
 +                      ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true);
                }
  
 -              qnum = skb_get_queue_mapping(bf->bf_mpdu);
 -
                if (bf_isampdu(bf))
                        ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
                                             true);
                else
                        ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
  
 -              if (txq == sc->tx.txq_map[qnum])
 -                      ath_wake_mac80211_queue(sc, qnum);
 -
                spin_lock_bh(&txq->axq_lock);
 +
                if (sc->sc_flags & SC_OP_TXAGGR)
                        ath_txq_schedule(sc, txq);
                spin_unlock_bh(&txq->axq_lock);
        }
  }
  
 +static void ath_hw_pll_work(struct work_struct *work)
 +{
 +      struct ath_softc *sc = container_of(work, struct ath_softc,
 +                                          hw_pll_work.work);
 +      static int count;
 +
 +      if (AR_SREV_9485(sc->sc_ah)) {
 +              if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) {
 +                      count++;
 +
 +                      if (count == 3) {
 +                              /* Rx is hung for more than 500ms. Reset it */
 +                              ath_reset(sc, true);
 +                              count = 0;
 +                      }
 +              } else
 +                      count = 0;
 +
 +              ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
 +      }
 +}
 +
  static void ath_tx_complete_poll_work(struct work_struct *work)
  {
        struct ath_softc *sc = container_of(work, struct ath_softc,
        struct ath_txq *txq;
        int i;
        bool needreset = false;
 +#ifdef CONFIG_ATH9K_DEBUGFS
 +      sc->tx_complete_poll_work_seen++;
 +#endif
  
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
                if (ATH_TXQ_SETUP(sc, i)) {
                                } else {
                                        txq->axq_tx_inprogress = true;
                                }
 +                      } else {
 +                              /* If the queue has pending buffers, then it
 +                               * should be doing tx work (and have axq_depth).
 +                               * Shouldn't get to this state I think..but
 +                               * we do.
 +                               */
 +                              if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) &&
 +                                  (txq->pending_frames > 0 ||
 +                                   !list_empty(&txq->axq_acq) ||
 +                                   txq->stopped)) {
 +                                      ath_err(ath9k_hw_common(sc->sc_ah),
 +                                              "txq: %p axq_qnum: %u,"
 +                                              " mac80211_qnum: %i"
 +                                              " axq_link: %p"
 +                                              " pending frames: %i"
 +                                              " axq_acq empty: %i"
 +                                              " stopped: %i"
 +                                              " axq_depth: 0  Attempting to"
 +                                              " restart tx logic.\n",
 +                                              txq, txq->axq_qnum,
 +                                              txq->mac80211_qnum,
 +                                              txq->axq_link,
 +                                              txq->pending_frames,
 +                                              list_empty(&txq->axq_acq),
 +                                              txq->stopped);
 +                                      ath_txq_schedule(sc, txq);
 +                              }
                        }
                        spin_unlock_bh(&txq->axq_lock);
                }
@@@ -2206,6 -2150,7 +2211,6 @@@ void ath_tx_edma_tasklet(struct ath_sof
        struct list_head bf_head;
        int status;
        int txok;
 -      int qnum;
  
        for (;;) {
                status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
                if (!bf_isampdu(bf)) {
                        if (txs.ts_status & ATH9K_TXERR_XRETRY)
                                bf->bf_state.bf_type |= BUF_XRETRY;
 -                      ath_tx_rc_status(bf, &txs, 1, txok ? 0 : 1, txok, true);
 +                      ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
                }
  
 -              qnum = skb_get_queue_mapping(bf->bf_mpdu);
 -
                if (bf_isampdu(bf))
                        ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
                                             txok, true);
                        ath_tx_complete_buf(sc, bf, txq, &bf_head,
                                            &txs, txok, 0);
  
 -              if (txq == sc->tx.txq_map[qnum])
 -                      ath_wake_mac80211_queue(sc, qnum);
 -
                spin_lock_bh(&txq->axq_lock);
 +
                if (!list_empty(&txq->txq_fifo_pending)) {
                        INIT_LIST_HEAD(&bf_head);
                        bf = list_first_entry(&txq->txq_fifo_pending,
@@@ -2336,7 -2285,6 +2341,7 @@@ int ath_tx_init(struct ath_softc *sc, i
        }
  
        INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
 +      INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
  
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
                error = ath_tx_edma_init(sc);
@@@ -594,11 -594,10 +594,11 @@@ static void iwl3945_rx_reply_rx(struct 
  
        rx_status.flag = 0;
        rx_status.mactime = le64_to_cpu(rx_end->timestamp);
 -      rx_status.freq =
 -              ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel));
        rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
                                IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
 +      rx_status.freq =
 +              ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel),
 +                                             rx_status.band);
  
        rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
        if (rx_status.band == IEEE80211_BAND_5GHZ)
@@@ -762,7 -761,8 +762,7 @@@ void iwl3945_hw_build_tx_cmd_rate(struc
  
        /* We need to figure out how to get the sta->supp_rates while
         * in this running context */
 -      rate_mask = IWL_RATES_MASK;
 -
 +      rate_mask = IWL_RATES_MASK_3945;
  
        /* Set retry limit on DATA packets and Probe Responses*/
        if (ieee80211_is_probe_resp(fc))
@@@ -1649,7 -1649,7 +1649,7 @@@ static int iwl3945_hw_reg_comp_txpower_
                                                              ref_temp);
  
                /* set tx power value for all rates, OFDM and CCK */
 -              for (rate_index = 0; rate_index < IWL_RATE_COUNT;
 +              for (rate_index = 0; rate_index < IWL_RATE_COUNT_3945;
                     rate_index++) {
                        int power_idx =
                            ch_info->power_info[rate_index].base_power_index;
@@@ -1889,7 -1889,7 +1889,7 @@@ int iwl3945_commit_rxon(struct iwl_pri
  
        /* If we issue a new RXON command which required a tune then we must
         * send a new TXPOWER command or we won't be able to Tx any frames */
 -      rc = priv->cfg->ops->lib->send_tx_power(priv);
 +      rc = iwl_set_tx_power(priv, priv->tx_power_next, true);
        if (rc) {
                IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
                return rc;
@@@ -2734,7 -2734,6 +2734,6 @@@ static struct iwl_lib_ops iwl3945_lib 
        .isr_ops = {
                .isr = iwl_isr_legacy,
        },
-       .check_plcp_health = iwl3945_good_plcp_health,
  
        .debugfs_ops = {
                .rx_stats_read = iwl3945_ucode_rx_stats_read,
  #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
  #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
  
 -#define IWL6000G2A_FW_PRE "iwlwifi-6000g2a-"
 -#define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode"
 -#define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api)
 +#define IWL6005_FW_PRE "iwlwifi-6000g2a-"
 +#define _IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode"
 +#define IWL6005_MODULE_FIRMWARE(api) _IWL6005_MODULE_FIRMWARE(api)
  
 -#define IWL6000G2B_FW_PRE "iwlwifi-6000g2b-"
 -#define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode"
 -#define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api)
 +#define IWL6030_FW_PRE "iwlwifi-6000g2b-"
 +#define _IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode"
 +#define IWL6030_MODULE_FIRMWARE(api) _IWL6030_MODULE_FIRMWARE(api)
  
  static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
  {
@@@ -90,7 -90,7 +90,7 @@@ static void iwl6050_additional_nic_conf
                                CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
  }
  
 -static void iwl6050g2_additional_nic_config(struct iwl_priv *priv)
 +static void iwl6150_additional_nic_config(struct iwl_priv *priv)
  {
        /* Indicate calibration version to uCode. */
        if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
@@@ -354,7 -354,7 +354,7 @@@ static struct iwl_lib_ops iwl6000_lib 
        }
  };
  
 -static struct iwl_lib_ops iwl6000g2b_lib = {
 +static struct iwl_lib_ops iwl6030_lib = {
        .set_hw_params = iwl6000_hw_set_hw_params,
        .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
        .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
@@@ -430,8 -430,8 +430,8 @@@ static struct iwl_nic_ops iwl6050_nic_o
        .additional_nic_config = &iwl6050_additional_nic_config,
  };
  
 -static struct iwl_nic_ops iwl6050g2_nic_ops = {
 -      .additional_nic_config = &iwl6050g2_additional_nic_config,
 +static struct iwl_nic_ops iwl6150_nic_ops = {
 +      .additional_nic_config = &iwl6150_additional_nic_config,
  };
  
  static const struct iwl_ops iwl6000_ops = {
@@@ -451,17 -451,17 +451,17 @@@ static const struct iwl_ops iwl6050_op
        .ieee80211_ops = &iwlagn_hw_ops,
  };
  
 -static const struct iwl_ops iwl6050g2_ops = {
 +static const struct iwl_ops iwl6150_ops = {
        .lib = &iwl6000_lib,
        .hcmd = &iwlagn_hcmd,
        .utils = &iwlagn_hcmd_utils,
        .led = &iwlagn_led_ops,
 -      .nic = &iwl6050g2_nic_ops,
 +      .nic = &iwl6150_nic_ops,
        .ieee80211_ops = &iwlagn_hw_ops,
  };
  
 -static const struct iwl_ops iwl6000g2b_ops = {
 -      .lib = &iwl6000g2b_lib,
 +static const struct iwl_ops iwl6030_ops = {
 +      .lib = &iwl6030_lib,
        .hcmd = &iwlagn_bt_hcmd,
        .utils = &iwlagn_hcmd_utils,
        .led = &iwlagn_led_ops,
@@@ -479,6 -479,7 +479,6 @@@ static struct iwl_base_params iwl6000_b
        .shadow_ram_support = true,
        .led_compensation = 51,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 -      .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@@ -502,6 -503,7 +502,6 @@@ static struct iwl_base_params iwl6050_b
        .shadow_ram_support = true,
        .led_compensation = 51,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 -      .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@@ -524,6 -526,7 +524,6 @@@ static struct iwl_base_params iwl6000_g
        .shadow_ram_support = true,
        .led_compensation = 57,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 -      .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@@ -552,11 -555,11 +552,11 @@@ static struct iwl_bt_params iwl6000_bt_
  };
  
  #define IWL_DEVICE_6005                                               \
 -      .fw_name_pre = IWL6000G2A_FW_PRE,                       \
 +      .fw_name_pre = IWL6005_FW_PRE,                  \
        .ucode_api_max = IWL6000G2_UCODE_API_MAX,               \
        .ucode_api_min = IWL6000G2_UCODE_API_MIN,               \
 -      .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,             \
 -      .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,     \
 +      .eeprom_ver = EEPROM_6005_EEPROM_VERSION,               \
 +      .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION,       \
        .ops = &iwl6000_ops,                                    \
        .mod_params = &iwlagn_mod_params,                       \
        .base_params = &iwl6000_g2_base_params,                 \
@@@ -581,12 -584,12 +581,12 @@@ struct iwl_cfg iwl6005_2bg_cfg = 
  };
  
  #define IWL_DEVICE_6030                                               \
 -      .fw_name_pre = IWL6000G2B_FW_PRE,                       \
 +      .fw_name_pre = IWL6030_FW_PRE,                  \
        .ucode_api_max = IWL6000G2_UCODE_API_MAX,               \
        .ucode_api_min = IWL6000G2_UCODE_API_MIN,               \
 -      .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,             \
 -      .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,     \
 -      .ops = &iwl6000g2b_ops,                                 \
 +      .eeprom_ver = EEPROM_6030_EEPROM_VERSION,               \
 +      .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION,       \
 +      .ops = &iwl6030_ops,                                    \
        .mod_params = &iwlagn_mod_params,                       \
        .base_params = &iwl6000_g2_base_params,                 \
        .bt_params = &iwl6000_bt_params,                        \
@@@ -678,6 -681,8 +678,8 @@@ struct iwl_cfg iwl6000i_2bg_cfg = 
        .fw_name_pre = IWL6050_FW_PRE,                          \
        .ucode_api_max = IWL6050_UCODE_API_MAX,                 \
        .ucode_api_min = IWL6050_UCODE_API_MIN,                 \
+       .valid_tx_ant = ANT_AB,         /* .cfg overwrite */    \
+       .valid_rx_ant = ANT_AB,         /* .cfg overwrite */    \
        .ops = &iwl6050_ops,                                    \
        .eeprom_ver = EEPROM_6050_EEPROM_VERSION,               \
        .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,       \
@@@ -703,9 -708,9 +705,9 @@@ struct iwl_cfg iwl6150_bgn_cfg = 
        .fw_name_pre = IWL6050_FW_PRE,
        .ucode_api_max = IWL6050_UCODE_API_MAX,
        .ucode_api_min = IWL6050_UCODE_API_MIN,
 -      .eeprom_ver = EEPROM_6050G2_EEPROM_VERSION,
 -      .eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION,
 -      .ops = &iwl6050g2_ops,
 +      .eeprom_ver = EEPROM_6150_EEPROM_VERSION,
 +      .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION,
 +      .ops = &iwl6150_ops,
        .mod_params = &iwlagn_mod_params,
        .base_params = &iwl6050_base_params,
        .ht_params = &iwl6000_ht_params,
@@@ -731,5 -736,5 +733,5 @@@ struct iwl_cfg iwl6000_3agn_cfg = 
  
  MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
  MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
 -MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
 -MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
 +MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
 +MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
@@@ -59,7 -59,6 +59,7 @@@
  #include "iwl-sta.h"
  #include "iwl-agn-calib.h"
  #include "iwl-agn.h"
 +#include "iwl-agn-led.h"
  
  
  /******************************************************************************
@@@ -462,12 -461,8 +462,12 @@@ static void iwl_rx_reply_alive(struct i
        if (palive->is_valid == UCODE_VALID_OK)
                queue_delayed_work(priv->workqueue, pwork,
                                   msecs_to_jiffies(5));
 -      else
 -              IWL_WARN(priv, "uCode did not respond OK.\n");
 +      else {
 +              IWL_WARN(priv, "%s uCode did not respond OK.\n",
 +                      (palive->ver_subtype == INITIALIZE_SUBTYPE) ?
 +                      "init" : "runtime");
 +              queue_work(priv->workqueue, &priv->restart);
 +      }
  }
  
  static void iwl_bg_beacon_update(struct work_struct *work)
@@@ -704,18 -699,18 +704,18 @@@ static void iwl_bg_ucode_trace(unsigne
        }
  }
  
 -static void iwl_rx_beacon_notif(struct iwl_priv *priv,
 -                              struct iwl_rx_mem_buffer *rxb)
 +static void iwlagn_rx_beacon_notif(struct iwl_priv *priv,
 +                                 struct iwl_rx_mem_buffer *rxb)
  {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
 -      struct iwl4965_beacon_notif *beacon =
 -              (struct iwl4965_beacon_notif *)pkt->u.raw;
 +      struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw;
  #ifdef CONFIG_IWLWIFI_DEBUG
 +      u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status);
        u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
  
 -      IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
 -              "tsf %d %d rate %d\n",
 -              le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
 +      IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d "
 +              "tsf:0x%.8x%.8x rate:%d\n",
 +              status & TX_STATUS_MSK,
                beacon->beacon_notify_hdr.failure_frame,
                le32_to_cpu(beacon->ibss_mgr_status),
                le32_to_cpu(beacon->high_tsf),
@@@ -818,7 -813,7 +818,7 @@@ static void iwl_setup_rx_handlers(struc
        priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
        priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
            iwl_rx_pm_debug_statistics_notif;
 -      priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
 +      priv->rx_handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif;
  
        /*
         * The same handler is used for both the REPLY to a discrete
   * the appropriate handlers, including command responses,
   * frame-received notifications, and other notifications.
   */
 -void iwl_rx_handle(struct iwl_priv *priv)
 +static void iwl_rx_handle(struct iwl_priv *priv)
  {
        struct iwl_rx_mem_buffer *rxb;
        struct iwl_rx_packet *pkt;
                        (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
                        (pkt->hdr.cmd != REPLY_TX);
  
 +              /*
 +               * Do the notification wait before RX handlers so
 +               * even if the RX handler consumes the RXB we have
 +               * access to it in the notification wait entry.
 +               */
 +              if (!list_empty(&priv->_agn.notif_waits)) {
 +                      struct iwl_notification_wait *w;
 +
 +                      spin_lock(&priv->_agn.notif_wait_lock);
 +                      list_for_each_entry(w, &priv->_agn.notif_waits, list) {
 +                              if (w->cmd == pkt->hdr.cmd) {
 +                                      w->triggered = true;
 +                                      if (w->fn)
 +                                              w->fn(priv, pkt);
 +                              }
 +                      }
 +                      spin_unlock(&priv->_agn.notif_wait_lock);
 +
 +                      wake_up_all(&priv->_agn.notif_waitq);
 +              }
 +
                /* Based on type of command response or notification,
                 *   handle those that need handling via function in
                 *   rx_handlers table.  See iwl_setup_rx_handlers() */
@@@ -1180,9 -1154,12 +1180,12 @@@ static void iwl_irq_tasklet_legacy(stru
        }
  
        /* Re-enable all interrupts */
 -      /* only Re-enable if diabled by irq */
 +      /* only Re-enable if disabled by irq */
        if (test_bit(STATUS_INT_ENABLED, &priv->status))
                iwl_enable_interrupts(priv);
+       /* Re-enable RF_KILL if it occurred */
+       else if (handled & CSR_INT_BIT_RF_KILL)
+               iwl_enable_rfkill_int(priv);
  
  #ifdef CONFIG_IWLWIFI_DEBUG
        if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
@@@ -1394,9 -1371,12 +1397,12 @@@ static void iwl_irq_tasklet(struct iwl_
        }
  
        /* Re-enable all interrupts */
 -      /* only Re-enable if diabled by irq */
 +      /* only Re-enable if disabled by irq */
        if (test_bit(STATUS_INT_ENABLED, &priv->status))
                iwl_enable_interrupts(priv);
+       /* Re-enable RF_KILL if it occurred */
+       else if (handled & CSR_INT_BIT_RF_KILL)
+               iwl_enable_rfkill_int(priv);
  }
  
  /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
  /**
   * 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
 + * When the ACK count ratio is low 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 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->_agn.statistics.tx.actual_ack_cnt);
 -      expected_ack_cnt_delta =
 -              le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) -
 -              le32_to_cpu(priv->_agn.statistics.tx.expected_ack_cnt);
 -      ba_timeout_delta =
 -              le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) -
 -              le32_to_cpu(priv->_agn.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);
 +      int actual_delta, expected_delta, ba_timeout_delta;
 +      struct statistics_tx *cur, *old;
 +
 +      if (priv->_agn.agg_tids_count)
 +              return true;
 +
 +      if (iwl_bt_statistics(priv)) {
 +              cur = &pkt->u.stats_bt.tx;
 +              old = &priv->_agn.statistics_bt.tx;
 +      } else {
 +              cur = &pkt->u.stats.tx;
 +              old = &priv->_agn.statistics.tx;
 +      }
 +
 +      actual_delta = le32_to_cpu(cur->actual_ack_cnt) -
 +                     le32_to_cpu(old->actual_ack_cnt);
 +      expected_delta = le32_to_cpu(cur->expected_ack_cnt) -
 +                       le32_to_cpu(old->expected_ack_cnt);
 +
 +      /* Values should not be negative, but we do not trust the firmware */
 +      if (actual_delta <= 0 || expected_delta <= 0)
 +              return true;
 +
 +      ba_timeout_delta = le32_to_cpu(cur->agg.ba_timeout) -
 +                         le32_to_cpu(old->agg.ba_timeout);
 +
 +      if ((actual_delta * 100 / expected_delta) < ACK_CNT_RATIO &&
 +          ba_timeout_delta > BA_TIMEOUT_CNT) {
 +              IWL_DEBUG_RADIO(priv, "deltas: actual %d expected %d ba_timeout %d\n",
 +                              actual_delta, expected_delta, ba_timeout_delta);
  
  #ifdef CONFIG_IWLWIFI_DEBUGFS
                /*
                 * statistics aren't available. If DEBUGFS is set but
                 * DEBUG is not, these will just compile out.
                 */
 -              IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta %d\n",
 +              IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta %d\n",
                                priv->_agn.delta_statistics.tx.rx_detected_cnt);
                IWL_DEBUG_RADIO(priv,
 -                              "ack_or_ba_timeout_collision delta = %d\n",
 -                              priv->_agn.delta_statistics.tx.
 -                              ack_or_ba_timeout_collision);
 +                              "ack_or_ba_timeout_collision delta %d\n",
 +                              priv->_agn.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;
 +
 +              if (ba_timeout_delta >= BA_TIMEOUT_MAX)
 +                      return false;
        }
 -      return rc;
 +
 +      return true;
  }
  
  
@@@ -2658,6 -2632,13 +2664,6 @@@ static void iwl_alive_start(struct iwl_
  
        IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
  
 -      if (priv->card_alive.is_valid != UCODE_VALID_OK) {
 -              /* We had an error bringing up the hardware, so take it
 -               * all the way back down so we can try again */
 -              IWL_DEBUG_INFO(priv, "Alive failed.\n");
 -              goto restart;
 -      }
 -
        /* Initialize uCode has loaded Runtime uCode ... verify inst image.
         * This is a paranoid check, because we would not have gotten the
         * "runtime" alive if code weren't properly loaded.  */
        /* At this point, the NIC is initialized and operational */
        iwl_rf_kill_ct_config(priv);
  
 -      iwl_leds_init(priv);
 -
        IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
        wake_up_interruptible(&priv->wait_command_queue);
  
@@@ -2786,6 -2769,7 +2792,6 @@@ static void __iwl_down(struct iwl_priv 
                         priv->cfg->bt_params->bt_init_traffic_load;
        else
                priv->bt_traffic_load = 0;
 -      priv->bt_sco_active = false;
        priv->bt_full_concurrent = false;
        priv->bt_ci_compliance = 0;
  
@@@ -3079,7 -3063,8 +3085,7 @@@ static void iwl_bg_run_time_calib_work(
        }
  
        if (priv->start_calib) {
 -              if (priv->cfg->bt_params &&
 -                  priv->cfg->bt_params->bt_statistics) {
 +              if (iwl_bt_statistics(priv)) {
                        iwl_chain_noise_calibration(priv,
                                        (void *)&priv->_agn.statistics_bt);
                        iwl_sensitivity_calibration(priv,
@@@ -3104,7 -3089,7 +3110,7 @@@ static void iwl_bg_restart(struct work_
  
        if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
                struct iwl_rxon_context *ctx;
 -              bool bt_sco, bt_full_concurrent;
 +              bool bt_full_concurrent;
                u8 bt_ci_compliance;
                u8 bt_load;
                u8 bt_status;
                 * re-configure the hw when we reconfigure the BT
                 * command.
                 */
 -              bt_sco = priv->bt_sco_active;
                bt_full_concurrent = priv->bt_full_concurrent;
                bt_ci_compliance = priv->bt_ci_compliance;
                bt_load = priv->bt_traffic_load;
  
                __iwl_down(priv);
  
 -              priv->bt_sco_active = bt_sco;
                priv->bt_full_concurrent = bt_full_concurrent;
                priv->bt_ci_compliance = bt_ci_compliance;
                priv->bt_traffic_load = bt_load;
@@@ -3191,8 -3178,6 +3197,8 @@@ static int iwl_mac_setup_register(struc
                    IEEE80211_HW_SPECTRUM_MGMT |
                    IEEE80211_HW_REPORTS_TX_ACK_STATUS;
  
 +      hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
 +
        if (!priv->cfg->base_params->broken_powersave)
                hw->flags |= IEEE80211_HW_SUPPORTS_PS |
                             IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
                hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
        }
  
 +      hw->wiphy->max_remain_on_channel_duration = 1000;
 +
        hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
 -                          WIPHY_FLAG_DISABLE_BEACON_HINTS;
 +                          WIPHY_FLAG_DISABLE_BEACON_HINTS |
 +                          WIPHY_FLAG_IBSS_RSN;
  
        /*
         * For now, disable PS by default because it affects
                priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &priv->bands[IEEE80211_BAND_5GHZ];
  
 +      iwl_leds_init(priv);
 +
        ret = ieee80211_register_hw(priv->hw);
        if (ret) {
                IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
@@@ -3283,7 -3263,7 +3289,7 @@@ int iwlagn_mac_start(struct ieee80211_h
                }
        }
  
 -      iwl_led_start(priv);
 +      iwlagn_led_enable(priv);
  
  out:
        priv->is_open = 1;
@@@ -3365,14 -3345,6 +3371,14 @@@ int iwlagn_mac_set_key(struct ieee80211
                return -EOPNOTSUPP;
        }
  
 +      /*
 +       * To support IBSS RSN, don't program group keys in IBSS, the
 +       * hardware will then not attempt to decrypt the frames.
 +       */
 +      if (vif->type == NL80211_IFTYPE_ADHOC &&
 +          !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
 +              return -EOPNOTSUPP;
 +
        sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
        if (sta_id == IWL_INVALID_STATION)
                return -EINVAL;
  int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
                            struct ieee80211_vif *vif,
                            enum ieee80211_ampdu_mlme_action action,
 -                          struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 +                          struct ieee80211_sta *sta, u16 tid, u16 *ssn,
 +                          u8 buf_size)
  {
        struct iwl_priv *priv = hw->priv;
        int ret = -EINVAL;
 +      struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
  
        IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
                     sta->addr, tid);
                }
                break;
        case IEEE80211_AMPDU_TX_OPERATIONAL:
 +              /*
 +               * If the limit is 0, then it wasn't initialised yet,
 +               * use the default. We can do that since we take the
 +               * minimum below, and we don't want to go above our
 +               * default due to hardware restrictions.
 +               */
 +              if (sta_priv->max_agg_bufsize == 0)
 +                      sta_priv->max_agg_bufsize =
 +                              LINK_QUAL_AGG_FRAME_LIMIT_DEF;
 +
 +              /*
 +               * Even though in theory the peer could have different
 +               * aggregation reorder buffer sizes for different sessions,
 +               * our ucode doesn't allow for that and has a global limit
 +               * for each station. Therefore, use the minimum of all the
 +               * aggregation sessions and our default value.
 +               */
 +              sta_priv->max_agg_bufsize =
 +                      min(sta_priv->max_agg_bufsize, buf_size);
 +
                if (priv->cfg->ht_params &&
                    priv->cfg->ht_params->use_rts_for_aggregation) {
 -                      struct iwl_station_priv *sta_priv =
 -                              (void *) sta->drv_priv;
 -
                        /*
                         * switch to RTS/CTS if it is the prefer protection
                         * method for HT traffic
  
                        sta_priv->lq_sta.lq.general_params.flags |=
                                LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
 -                      iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
 -                                      &sta_priv->lq_sta.lq, CMD_ASYNC, false);
                }
 +
 +              sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
 +                      sta_priv->max_agg_bufsize;
 +
 +              iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
 +                              &sta_priv->lq_sta.lq, CMD_ASYNC, false);
                ret = 0;
                break;
        }
@@@ -3760,97 -3709,6 +3766,97 @@@ done
        IWL_DEBUG_MAC80211(priv, "leave\n");
  }
  
 +static void iwlagn_disable_roc(struct iwl_priv *priv)
 +{
 +      struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
 +      struct ieee80211_channel *chan = ACCESS_ONCE(priv->hw->conf.channel);
 +
 +      lockdep_assert_held(&priv->mutex);
 +
 +      if (!ctx->is_active)
 +              return;
 +
 +      ctx->staging.dev_type = RXON_DEV_TYPE_2STA;
 +      ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 +      iwl_set_rxon_channel(priv, chan, ctx);
 +      iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
 +
 +      priv->_agn.hw_roc_channel = NULL;
 +
 +      iwlcore_commit_rxon(priv, ctx);
 +
 +      ctx->is_active = false;
 +}
 +
 +static void iwlagn_bg_roc_done(struct work_struct *work)
 +{
 +      struct iwl_priv *priv = container_of(work, struct iwl_priv,
 +                                           _agn.hw_roc_work.work);
 +
 +      mutex_lock(&priv->mutex);
 +      ieee80211_remain_on_channel_expired(priv->hw);
 +      iwlagn_disable_roc(priv);
 +      mutex_unlock(&priv->mutex);
 +}
 +
 +#ifdef CONFIG_IWL5000
 +static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
 +                                   struct ieee80211_channel *channel,
 +                                   enum nl80211_channel_type channel_type,
 +                                   int duration)
 +{
 +      struct iwl_priv *priv = hw->priv;
 +      int err = 0;
 +
 +      if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
 +              return -EOPNOTSUPP;
 +
 +      if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
 +                                      BIT(NL80211_IFTYPE_P2P_CLIENT)))
 +              return -EOPNOTSUPP;
 +
 +      mutex_lock(&priv->mutex);
 +
 +      if (priv->contexts[IWL_RXON_CTX_PAN].is_active ||
 +          test_bit(STATUS_SCAN_HW, &priv->status)) {
 +              err = -EBUSY;
 +              goto out;
 +      }
 +
 +      priv->contexts[IWL_RXON_CTX_PAN].is_active = true;
 +      priv->_agn.hw_roc_channel = channel;
 +      priv->_agn.hw_roc_chantype = channel_type;
 +      priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024);
 +      iwlcore_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
 +      queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work,
 +                         msecs_to_jiffies(duration + 20));
 +
 +      msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */
 +      ieee80211_ready_on_channel(priv->hw);
 +
 + out:
 +      mutex_unlock(&priv->mutex);
 +
 +      return err;
 +}
 +
 +static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
 +{
 +      struct iwl_priv *priv = hw->priv;
 +
 +      if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
 +              return -EOPNOTSUPP;
 +
 +      cancel_delayed_work_sync(&priv->_agn.hw_roc_work);
 +
 +      mutex_lock(&priv->mutex);
 +      iwlagn_disable_roc(priv);
 +      mutex_unlock(&priv->mutex);
 +
 +      return 0;
 +}
 +#endif
 +
  /*****************************************************************************
   *
   * driver setup and teardown
@@@ -3872,7 -3730,6 +3878,7 @@@ static void iwl_setup_deferred_work(str
        INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
        INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
        INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
 +      INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done);
  
        iwl_setup_scan_deferred_work(priv);
  
@@@ -4041,8 -3898,6 +4047,8 @@@ struct ieee80211_ops iwlagn_hw_ops = 
        .channel_switch = iwlagn_mac_channel_switch,
        .flush = iwlagn_mac_flush,
        .tx_last_beacon = iwl_mac_tx_last_beacon,
 +      .remain_on_channel = iwl_mac_remain_on_channel,
 +      .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,
  };
  #endif
  
@@@ -4170,10 -4025,6 +4176,10 @@@ static int iwl_pci_probe(struct pci_de
        priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
        priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
                BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
 +#ifdef CONFIG_IWL_P2P
 +      priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
 +              BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
 +#endif
        priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
        priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
        priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
@@@ -4421,9 -4272,6 +4427,9 @@@ static void __devexit iwl_pci_remove(st
         * we need to set STATUS_EXIT_PENDING bit.
         */
        set_bit(STATUS_EXIT_PENDING, &priv->status);
 +
 +      iwl_leds_exit(priv);
 +
        if (priv->mac80211_registered) {
                ieee80211_unregister_hw(priv->hw);
                priv->mac80211_registered = 0;
@@@ -4644,49 -4492,6 +4650,49 @@@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_c
        {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
        {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
  
 +/* 2x00 Series */
 +      {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
 +      {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
 +      {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
 +
 +/* 2x30 Series */
 +      {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
 +      {IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
 +      {IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
 +
 +/* 6x35 Series */
 +      {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
 +      {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
 +      {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
 +      {IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
 +      {IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
 +      {IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
 +      {IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
 +      {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
 +      {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
 +
 +/* 200 Series */
 +      {IWL_PCI_DEVICE(0x0894, 0x0022, iwl200_bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0895, 0x0222, iwl200_bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0894, 0x0422, iwl200_bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0894, 0x0026, iwl200_bg_cfg)},
 +      {IWL_PCI_DEVICE(0x0895, 0x0226, iwl200_bg_cfg)},
 +      {IWL_PCI_DEVICE(0x0894, 0x0426, iwl200_bg_cfg)},
 +
 +/* 230 Series */
 +      {IWL_PCI_DEVICE(0x0892, 0x0062, iwl230_bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0893, 0x0262, iwl230_bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0892, 0x0462, iwl230_bgn_cfg)},
 +      {IWL_PCI_DEVICE(0x0892, 0x0066, iwl230_bg_cfg)},
 +      {IWL_PCI_DEVICE(0x0893, 0x0266, iwl230_bg_cfg)},
 +      {IWL_PCI_DEVICE(0x0892, 0x0466, iwl230_bg_cfg)},
 +
  #endif /* CONFIG_IWL5000 */
  
        {0}
@@@ -200,22 -200,11 +200,22 @@@ static void rt2800pci_start_queue(struc
                rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
                break;
        case QID_BEACON:
 +              /*
 +               * Allow beacon tasklets to be scheduled for periodic
 +               * beacon updates.
 +               */
 +              tasklet_enable(&rt2x00dev->tbtt_tasklet);
 +              tasklet_enable(&rt2x00dev->pretbtt_tasklet);
 +
                rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
                rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 +
 +              rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
 +              rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
 +              rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
                break;
        default:
                break;
@@@ -261,16 -250,6 +261,16 @@@ static void rt2800pci_stop_queue(struc
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
                rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 +
 +              rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
 +              rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
 +              rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
 +
 +              /*
 +               * Wait for tbtt tasklets to finish.
 +               */
 +              tasklet_disable(&rt2x00dev->tbtt_tasklet);
 +              tasklet_disable(&rt2x00dev->pretbtt_tasklet);
                break;
        default:
                break;
@@@ -418,9 -397,9 +418,9 @@@ static int rt2800pci_init_queues(struc
  static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
                                 enum dev_state state)
  {
 -      int mask = (state == STATE_RADIO_IRQ_ON) ||
 -                 (state == STATE_RADIO_IRQ_ON_ISR);
 +      int mask = (state == STATE_RADIO_IRQ_ON);
        u32 reg;
 +      unsigned long flags;
  
        /*
         * When interrupts are being enabled, the interrupt registers
        if (state == STATE_RADIO_IRQ_ON) {
                rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
                rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 +
 +              /*
 +               * Enable tasklets. The beacon related tasklets are
 +               * enabled when the beacon queue is started.
 +               */
 +              tasklet_enable(&rt2x00dev->txstatus_tasklet);
 +              tasklet_enable(&rt2x00dev->rxdone_tasklet);
 +              tasklet_enable(&rt2x00dev->autowake_tasklet);
        }
  
 +      spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
        rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
        rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
        rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
        rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
        rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
        rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
 +      spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
 +
 +      if (state == STATE_RADIO_IRQ_OFF) {
 +              /*
 +               * Ensure that all tasklets are finished before
 +               * disabling the interrupts.
 +               */
 +              tasklet_disable(&rt2x00dev->txstatus_tasklet);
 +              tasklet_disable(&rt2x00dev->rxdone_tasklet);
 +              tasklet_disable(&rt2x00dev->autowake_tasklet);
 +      }
  }
  
  static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
@@@ -516,23 -475,39 +516,23 @@@ static int rt2800pci_enable_radio(struc
  
  static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
  {
 -      u32 reg;
 -
 -      rt2800_disable_radio(rt2x00dev);
 -
 -      rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
 -
 -      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);
 +      if (rt2x00_is_soc(rt2x00dev)) {
 +              rt2800_disable_radio(rt2x00dev);
 +              rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
 +              rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
 +      }
  }
  
  static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
                               enum dev_state state)
  {
 -      /*
 -       * Always put the device to sleep (even when we intend to wakeup!)
 -       * if the device is booting and wasn't asleep it will return
 -       * failure when attempting to wakeup.
 -       */
 -      rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
 -
        if (state == STATE_AWAKE) {
 -              rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
 +              rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);
                rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
 +      } else if (state == STATE_SLEEP) {
 +              rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff);
 +              rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff);
 +              rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);
        }
  
        return 0;
@@@ -563,7 -538,9 +563,7 @@@ static int rt2800pci_set_device_state(s
                rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
                break;
        case STATE_RADIO_IRQ_ON:
 -      case STATE_RADIO_IRQ_ON_ISR:
        case STATE_RADIO_IRQ_OFF:
 -      case STATE_RADIO_IRQ_OFF_ISR:
                rt2800pci_toggle_irq(rt2x00dev, state);
                break;
        case STATE_DEEP_SLEEP:
@@@ -675,12 -652,6 +675,12 @@@ static void rt2800pci_fill_rxdone(struc
                 */
                rxdesc->flags |= RX_FLAG_IV_STRIPPED;
  
 +              /*
 +               * The hardware has already checked the Michael Mic and has
 +               * stripped it from the frame. Signal this to mac80211.
 +               */
 +              rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
 +
                if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
                        rxdesc->flags |= RX_FLAG_DECRYPTED;
                else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
@@@ -755,60 -726,45 +755,60 @@@ static void rt2800pci_txdone(struct rt2
        }
  }
  
 -static void rt2800pci_txstatus_tasklet(unsigned long data)
 +static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
 +                                     struct rt2x00_field32 irq_field)
  {
 -      rt2800pci_txdone((struct rt2x00_dev *)data);
 -}
 -
 -static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
 -{
 -      struct rt2x00_dev *rt2x00dev = dev_instance;
 -      u32 reg = rt2x00dev->irqvalue[0];
 +      unsigned long flags;
 +      u32 reg;
  
        /*
 -       * 1 - Pre TBTT interrupt.
 +       * Enable a single interrupt. The interrupt mask register
 +       * access needs locking.
         */
 -      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
 -              rt2x00lib_pretbtt(rt2x00dev);
 +      spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
 +      rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 +      rt2x00_set_field32(&reg, irq_field, 1);
 +      rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
 +      spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
 +}
  
 -      /*
 -       * 2 - Beacondone interrupt.
 -       */
 -      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
 -              rt2x00lib_beacondone(rt2x00dev);
 +static void rt2800pci_txstatus_tasklet(unsigned long data)
 +{
 +      rt2800pci_txdone((struct rt2x00_dev *)data);
  
        /*
 -       * 3 - Rx ring done interrupt.
 +       * No need to enable the tx status interrupt here as we always
 +       * leave it enabled to minimize the possibility of a tx status
 +       * register overflow. See comment in interrupt handler.
         */
 -      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
 -              rt2x00pci_rxdone(rt2x00dev);
 +}
  
 -      /*
 -       * 4 - Auto wakeup interrupt.
 -       */
 -      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
 -              rt2800pci_wakeup(rt2x00dev);
 +static void rt2800pci_pretbtt_tasklet(unsigned long data)
 +{
 +      struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
 +      rt2x00lib_pretbtt(rt2x00dev);
 +      rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
 +}
  
 -      /* Enable interrupts again. */
 -      rt2x00dev->ops->lib->set_device_state(rt2x00dev,
 -                                            STATE_RADIO_IRQ_ON_ISR);
 +static void rt2800pci_tbtt_tasklet(unsigned long data)
 +{
 +      struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
 +      rt2x00lib_beacondone(rt2x00dev);
 +      rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
 +}
  
 -      return IRQ_HANDLED;
 +static void rt2800pci_rxdone_tasklet(unsigned long data)
 +{
 +      struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
 +      rt2x00pci_rxdone(rt2x00dev);
 +      rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
 +}
 +
 +static void rt2800pci_autowake_tasklet(unsigned long data)
 +{
 +      struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
 +      rt2800pci_wakeup(rt2x00dev);
 +      rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP);
  }
  
  static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
  static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
  {
        struct rt2x00_dev *rt2x00dev = dev_instance;
 -      u32 reg;
 -      irqreturn_t ret = IRQ_HANDLED;
 +      u32 reg, mask;
 +      unsigned long flags;
  
        /* Read status and ACK all interrupts */
        rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
        if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
                return IRQ_HANDLED;
  
 -      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
 -              rt2800pci_txstatus_interrupt(rt2x00dev);
 +      /*
 +       * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
 +       * for interrupts and interrupt masks we can just use the value of
 +       * INT_SOURCE_CSR to create the interrupt mask.
 +       */
 +      mask = ~reg;
  
 -      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT) ||
 -          rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT) ||
 -          rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE) ||
 -          rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) {
 +      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
 +              rt2800pci_txstatus_interrupt(rt2x00dev);
                /*
 -               * All other interrupts are handled in the interrupt thread.
 -               * Store irqvalue for use in the interrupt thread.
 +               * Never disable the TX_FIFO_STATUS interrupt.
                 */
 -              rt2x00dev->irqvalue[0] = reg;
 +              rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
 +      }
  
 -              /*
 -               * Disable interrupts, will be enabled again in the
 -               * interrupt thread.
 -              */
 -              rt2x00dev->ops->lib->set_device_state(rt2x00dev,
 -                                                    STATE_RADIO_IRQ_OFF_ISR);
 +      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
 +              tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
  
 -              /*
 -               * Leave the TX_FIFO_STATUS interrupt enabled to not lose any
 -               * tx status reports.
 -               */
 -              rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 -              rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
 -              rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
 +      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
 +              tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
  
 -              ret = IRQ_WAKE_THREAD;
 -      }
 +      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
 +              tasklet_schedule(&rt2x00dev->rxdone_tasklet);
  
 -      return ret;
 +      if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
 +              tasklet_schedule(&rt2x00dev->autowake_tasklet);
 +
 +      /*
 +       * Disable all interrupts for which a tasklet was scheduled right now,
 +       * the tasklet will reenable the appropriate interrupts.
 +       */
 +      spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
 +      rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 +      reg &= mask;
 +      rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
 +      spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
 +
 +      return IRQ_HANDLED;
  }
  
  /*
@@@ -1019,11 -969,8 +1019,11 @@@ static const struct rt2800_ops rt2800pc
  
  static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
        .irq_handler            = rt2800pci_interrupt,
 -      .irq_handler_thread     = rt2800pci_interrupt_thread,
 -      .txstatus_tasklet       = rt2800pci_txstatus_tasklet,
 +      .txstatus_tasklet       = rt2800pci_txstatus_tasklet,
 +      .pretbtt_tasklet        = rt2800pci_pretbtt_tasklet,
 +      .tbtt_tasklet           = rt2800pci_tbtt_tasklet,
 +      .rxdone_tasklet         = rt2800pci_rxdone_tasklet,
 +      .autowake_tasklet       = rt2800pci_autowake_tasklet,
        .probe_hw               = rt2800pci_probe_hw,
        .get_firmware_name      = rt2800pci_get_firmware_name,
        .check_firmware         = rt2800_check_firmware,
        .write_tx_desc          = rt2800pci_write_tx_desc,
        .write_tx_data          = rt2800_write_tx_data,
        .write_beacon           = rt2800_write_beacon,
 +      .clear_beacon           = rt2800_clear_beacon,
        .fill_rxdone            = rt2800pci_fill_rxdone,
        .config_shared_key      = rt2800_config_shared_key,
        .config_pairwise_key    = rt2800_config_pairwise_key,
@@@ -1119,6 -1065,8 +1119,8 @@@ static DEFINE_PCI_DEVICE_TABLE(rt2800pc
        { PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) },
  #endif
  #ifdef CONFIG_RT2800PCI_RT35XX
+       { PCI_DEVICE(0x1432, 0x7711), PCI_DEVICE_DATA(&rt2800pci_ops) },
+       { PCI_DEVICE(0x1432, 0x7722), PCI_DEVICE_DATA(&rt2800pci_ops) },
        { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
        { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
        { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) },
@@@ -502,7 -502,6 +502,7 @@@ static void wl1251_op_stop(struct ieee8
        wl->psm = 0;
        wl->tx_queue_stopped = false;
        wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
 +      wl->rssi_thold = 0;
        wl->channel = WL1251_DEFAULT_CHANNEL;
  
        wl1251_debugfs_reset(wl);
@@@ -960,16 -959,6 +960,16 @@@ static void wl1251_op_bss_info_changed(
        if (ret < 0)
                goto out;
  
 +      if (changed & BSS_CHANGED_CQM) {
 +              ret = wl1251_acx_low_rssi(wl, bss_conf->cqm_rssi_thold,
 +                                        WL1251_DEFAULT_LOW_RSSI_WEIGHT,
 +                                        WL1251_DEFAULT_LOW_RSSI_DEPTH,
 +                                        WL1251_ACX_LOW_RSSI_TYPE_EDGE);
 +              if (ret < 0)
 +                      goto out;
 +              wl->rssi_thold = bss_conf->cqm_rssi_thold;
 +      }
 +
        if (changed & BSS_CHANGED_BSSID) {
                memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
  
  
        if (changed & BSS_CHANGED_BEACON) {
                beacon = ieee80211_beacon_get(hw, vif);
+               if (!beacon)
+                       goto out_sleep;
                ret = wl1251_cmd_template_set(wl, CMD_BEACON, beacon->data,
                                              beacon->len);
  
@@@ -1321,11 -1313,9 +1324,11 @@@ int wl1251_init_ieee80211(struct wl125
        wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
                IEEE80211_HW_SUPPORTS_PS |
                IEEE80211_HW_BEACON_FILTER |
 -              IEEE80211_HW_SUPPORTS_UAPSD;
 +              IEEE80211_HW_SUPPORTS_UAPSD |
 +              IEEE80211_HW_SUPPORTS_CQM_RSSI;
  
 -      wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 +      wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 +                                       BIT(NL80211_IFTYPE_ADHOC);
        wl->hw->wiphy->max_scan_ssids = 1;
        wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz;
  
@@@ -1387,7 -1377,6 +1390,7 @@@ struct ieee80211_hw *wl1251_alloc_hw(vo
        wl->psm_requested = false;
        wl->tx_queue_stopped = false;
        wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
 +      wl->rssi_thold = 0;
        wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
        wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
        wl->vif = NULL;
diff --combined net/mac80211/cfg.c
@@@ -1215,9 -1215,6 +1215,9 @@@ static int ieee80211_set_channel(struc
  {
        struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata = NULL;
 +      struct ieee80211_channel *old_oper;
 +      enum nl80211_channel_type old_oper_type;
 +      enum nl80211_channel_type old_vif_oper_type= NL80211_CHAN_NO_HT;
  
        if (netdev)
                sdata = IEEE80211_DEV_TO_SUB_IF(netdev);
                break;
        }
  
 -      local->oper_channel = chan;
 +      if (sdata)
 +              old_vif_oper_type = sdata->vif.bss_conf.channel_type;
 +      old_oper_type = local->_oper_channel_type;
  
        if (!ieee80211_set_channel_type(local, sdata, channel_type))
                return -EBUSY;
  
 -      ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 -      if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR)
 +      old_oper = local->oper_channel;
 +      local->oper_channel = chan;
 +
 +      /* Update driver if changes were actually made. */
 +      if ((old_oper != local->oper_channel) ||
 +          (old_oper_type != local->_oper_channel_type))
 +              ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 +
 +      if ((sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) &&
 +          old_vif_oper_type != sdata->vif.bss_conf.channel_type)
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
  
        return 0;
@@@ -1287,11 -1274,8 +1287,11 @@@ static int ieee80211_scan(struct wiphy 
        case NL80211_IFTYPE_P2P_GO:
                if (sdata->local->ops->hw_scan)
                        break;
 -              /* FIXME: implement NoA while scanning in software */
 -              return -EOPNOTSUPP;
 +              /*
 +               * FIXME: implement NoA while scanning in software,
 +               * for now fall through to allow scanning only when
 +               * beaconing hasn't been configured yet
 +               */
        case NL80211_IFTYPE_AP:
                if (sdata->u.ap.beacon)
                        return -EOPNOTSUPP;
@@@ -1838,6 -1822,7 +1838,7 @@@ static int ieee80211_mgmt_tx(struct wip
                *cookie ^= 2;
                IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN;
                local->hw_roc_skb = skb;
+               local->hw_roc_skb_for_status = skb;
                mutex_unlock(&local->mtx);
  
                return 0;
  
        wk->type = IEEE80211_WORK_OFFCHANNEL_TX;
        wk->chan = chan;
 +      wk->chan_type = channel_type;
        wk->sdata = sdata;
        wk->done = ieee80211_offchan_tx_done;
        wk->offchan_tx.frame = skb;
@@@ -1892,6 -1876,7 +1893,7 @@@ static int ieee80211_mgmt_tx_cancel_wai
                if (ret == 0) {
                        kfree_skb(local->hw_roc_skb);
                        local->hw_roc_skb = NULL;
+                       local->hw_roc_skb_for_status = NULL;
                }
  
                mutex_unlock(&local->mtx);
@@@ -225,7 -225,6 +225,7 @@@ struct ieee80211_if_ap 
        struct sk_buff_head ps_bc_buf;
        atomic_t num_sta_ps; /* number of stations in PS mode */
        int dtim_count;
 +      bool dtim_bc_mc;
  };
  
  struct ieee80211_if_wds {
@@@ -655,6 -654,8 +655,6 @@@ struct tpt_led_trigger 
   *    well be on the operating channel
   * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to
   *    determine if we are on the operating channel or not
 - * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning,
 - *    gets only set in conjunction with SCAN_SW_SCANNING
   * @SCAN_COMPLETED: Set for our scan work function when the driver reported
   *    that the scan completed.
   * @SCAN_ABORTED: Set for our scan work function when the driver reported
  enum {
        SCAN_SW_SCANNING,
        SCAN_HW_SCANNING,
 -      SCAN_OFF_CHANNEL,
        SCAN_COMPLETED,
        SCAN_ABORTED,
  };
@@@ -951,7 -953,7 +951,7 @@@ struct ieee80211_local 
  
        struct ieee80211_channel *hw_roc_channel;
        struct net_device *hw_roc_dev;
-       struct sk_buff *hw_roc_skb;
+       struct sk_buff *hw_roc_skb, *hw_roc_skb_for_status;
        struct work_struct hw_roc_start, hw_roc_done;
        enum nl80211_channel_type hw_roc_channel_type;
        unsigned int hw_roc_duration;
@@@ -1066,6 -1068,8 +1066,6 @@@ void ieee80211_bss_info_change_notify(s
  void ieee80211_configure_filter(struct ieee80211_local *local);
  u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);
  
 -extern bool ieee80211_disable_40mhz_24ghz;
 -
  /* STA code */
  void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata);
  int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
@@@ -1143,14 -1147,10 +1143,14 @@@ void ieee80211_rx_bss_put(struct ieee80
                          struct ieee80211_bss *bss);
  
  /* off-channel helpers */
 -void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local);
 -void ieee80211_offchannel_stop_station(struct ieee80211_local *local);
 +bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local);
 +void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
 +                                      bool tell_ap);
 +void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
 +                                  bool offchannel_ps_enable);
  void ieee80211_offchannel_return(struct ieee80211_local *local,
 -                               bool enable_beaconing);
 +                               bool enable_beaconing,
 +                               bool offchannel_ps_disable);
  void ieee80211_hw_roc_setup(struct ieee80211_local *local);
  
  /* interface handling */
diff --combined net/mac80211/mlme.c
  #include "rate.h"
  #include "led.h"
  
 -#define IEEE80211_MAX_NULLFUNC_TRIES 2
 -#define IEEE80211_MAX_PROBE_TRIES 5
 +static int max_nullfunc_tries = 2;
 +module_param(max_nullfunc_tries, int, 0644);
 +MODULE_PARM_DESC(max_nullfunc_tries,
 +               "Maximum nullfunc tx tries before disconnecting (reason 4).");
 +
 +static int max_probe_tries = 5;
 +module_param(max_probe_tries, int, 0644);
 +MODULE_PARM_DESC(max_probe_tries,
 +               "Maximum probe tries before disconnecting (reason 4).");
  
  /*
   * Beacon loss timeout is calculated as N frames times the
   * a probe request because of beacon loss or for
   * checking the connection still works.
   */
 -#define IEEE80211_PROBE_WAIT          (HZ / 2)
 +static int probe_wait_ms = 500;
 +module_param(probe_wait_ms, int, 0644);
 +MODULE_PARM_DESC(probe_wait_ms,
 +               "Maximum time(ms) to wait for probe response"
 +               " before disconnecting (reason 4).");
  
  /*
   * Weight given to the latest Beacon frame when calculating average signal
@@@ -172,7 -161,6 +172,7 @@@ static u32 ieee80211_enable_ht(struct i
        struct ieee80211_supported_band *sband;
        struct sta_info *sta;
        u32 changed = 0;
 +      int hti_cfreq;
        u16 ht_opmode;
        bool enable_ht = true;
        enum nl80211_channel_type prev_chantype;
        if (!sband->ht_cap.ht_supported)
                enable_ht = false;
  
 -      /* check that channel matches the right operating channel */
 -      if (local->hw.conf.channel->center_freq !=
 -          ieee80211_channel_to_frequency(hti->control_chan))
 -              enable_ht = false;
 +      if (enable_ht) {
 +              hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan,
 +                                                         sband->band);
 +              /* check that channel matches the right operating channel */
 +              if (local->hw.conf.channel->center_freq != hti_cfreq) {
 +                      /* Some APs mess this up, evidently.
 +                       * Netgear WNDR3700 sometimes reports 4 higher than
 +                       * the actual channel, for instance.
 +                       */
 +                      printk(KERN_DEBUG
 +                             "%s: Wrong control channel in association"
 +                             " response: configured center-freq: %d"
 +                             " hti-cfreq: %d  hti->control_chan: %d"
 +                             " band: %d.  Disabling HT.\n",
 +                             sdata->name,
 +                             local->hw.conf.channel->center_freq,
 +                             hti_cfreq, hti->control_chan,
 +                             sband->band);
 +                      enable_ht = false;
 +              }
 +      }
  
        if (enable_ht) {
                channel_type = NL80211_CHAN_HT20;
@@@ -458,8 -429,7 +458,8 @@@ void ieee80211_sta_process_chanswitch(s
                container_of((void *)bss, struct cfg80211_bss, priv);
        struct ieee80211_channel *new_ch;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 -      int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);
 +      int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num,
 +                                                    cbss->channel->band);
  
        ASSERT_MGD_MTX(ifmgd);
  
@@@ -630,14 -600,6 +630,14 @@@ void ieee80211_recalc_ps(struct ieee802
        list_for_each_entry(sdata, &local->interfaces, list) {
                if (!ieee80211_sdata_running(sdata))
                        continue;
 +              if (sdata->vif.type == NL80211_IFTYPE_AP) {
 +                      /* If an AP vif is found, then disable PS
 +                       * by setting the count to zero thereby setting
 +                       * ps_sdata to NULL.
 +                       */
 +                      count = 0;
 +                      break;
 +              }
                if (sdata->vif.type != NL80211_IFTYPE_STATION)
                        continue;
                found = sdata;
@@@ -1071,6 -1033,12 +1071,12 @@@ void ieee80211_sta_rx_notify(struct iee
        if (is_multicast_ether_addr(hdr->addr1))
                return;
  
+       /*
+        * In case we receive frames after disassociation.
+        */
+       if (!sdata->u.mgd.associated)
+               return;
        ieee80211_sta_reset_conn_monitor(sdata);
  }
  
@@@ -1127,7 -1095,7 +1133,7 @@@ static void ieee80211_mgd_probe_ap_send
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        const u8 *ssid;
        u8 *dst = ifmgd->associated->bssid;
 -      u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3);
 +      u8 unicast_limit = max(1, max_probe_tries - 3);
  
        /*
         * Try sending broadcast probe requests for the last three
        }
  
        ifmgd->probe_send_count++;
 -      ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
 +      ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
        run_again(ifmgd, ifmgd->probe_timeout);
  }
  
@@@ -1254,8 -1222,7 +1260,8 @@@ static void __ieee80211_connection_loss
  
        memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
  
 -      printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
 +      printk(KERN_DEBUG "%s: Connection to AP %pM lost.\n",
 +             sdata->name, bssid);
  
        ieee80211_set_disassoc(sdata, true, true);
        mutex_unlock(&ifmgd->mtx);
@@@ -1558,8 -1525,7 +1564,8 @@@ static void ieee80211_rx_bss_info(struc
        }
  
        if (elems->ds_params && elems->ds_params_len == 1)
 -              freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
 +              freq = ieee80211_channel_to_frequency(elems->ds_params[0],
 +                                                    rx_status->band);
        else
                freq = rx_status->freq;
  
@@@ -2000,9 -1966,9 +2006,9 @@@ void ieee80211_sta_work(struct ieee8021
                memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
  
                if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
 -                      max_tries = IEEE80211_MAX_NULLFUNC_TRIES;
 +                      max_tries = max_nullfunc_tries;
                else
 -                      max_tries = IEEE80211_MAX_PROBE_TRIES;
 +                      max_tries = max_probe_tries;
  
                /* ACK received for nullfunc probing frame */
                if (!ifmgd->probe_send_count)
  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
                                wiphy_debug(local->hw.wiphy,
                                            "%s: No ack for nullfunc frame to"
 -                                          " AP %pM, try %d\n",
 +                                          " AP %pM, try %d/%i\n",
                                            sdata->name, bssid,
 -                                          ifmgd->probe_send_count);
 +                                          ifmgd->probe_send_count, max_tries);
  #endif
                                ieee80211_mgd_probe_ap_send(sdata);
                        } else {
                                    "%s: Failed to send nullfunc to AP %pM"
                                    " after %dms, disconnecting.\n",
                                    sdata->name,
 -                                  bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
 +                                  bssid, probe_wait_ms);
  #endif
                        ieee80211_sta_connection_lost(sdata, bssid);
                } else if (ifmgd->probe_send_count < max_tries) {
  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
                        wiphy_debug(local->hw.wiphy,
                                    "%s: No probe response from AP %pM"
 -                                  " after %dms, try %d\n",
 +                                  " after %dms, try %d/%i\n",
                                    sdata->name,
 -                                  bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ,
 -                                  ifmgd->probe_send_count);
 +                                  bssid, probe_wait_ms,
 +                                  ifmgd->probe_send_count, max_tries);
  #endif
                        ieee80211_mgd_probe_ap_send(sdata);
                } else {
                                    "%s: No probe response from AP %pM"
                                    " after %dms, disconnecting.\n",
                                    sdata->name,
 -                                  bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
 +                                  bssid, probe_wait_ms);
  
                        ieee80211_sta_connection_lost(sdata, bssid);
                }
@@@ -2294,7 -2260,6 +2300,7 @@@ int ieee80211_mgd_auth(struct ieee80211
        else
                wk->type = IEEE80211_WORK_DIRECT_PROBE;
        wk->chan = req->bss->channel;
 +      wk->chan_type = NL80211_CHAN_NO_HT;
        wk->sdata = sdata;
        wk->done = ieee80211_probe_auth_done;
  
@@@ -2444,7 -2409,6 +2450,7 @@@ int ieee80211_mgd_assoc(struct ieee8021
                memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN);
  
        wk->chan = req->bss->channel;
 +      wk->chan_type = NL80211_CHAN_NO_HT;
        wk->sdata = sdata;
        wk->done = ieee80211_assoc_done;
        if (!bss->dtim_period &&
diff --combined net/mac80211/status.c
@@@ -98,10 -98,6 +98,10 @@@ static void ieee80211_handle_filtered_f
         *  (b) always process RX events before TX status events if ordering
         *      can be unknown, for example with different interrupt status
         *      bits.
 +       *  (c) if PS mode transitions are manual (i.e. the flag
 +       *      %IEEE80211_HW_AP_LINK_PS is set), always process PS state
 +       *      changes before calling TX status events if ordering can be
 +       *      unknown.
         */
        if (test_sta_flags(sta, WLAN_STA_PS_STA) &&
            skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
@@@ -327,6 -323,7 +327,7 @@@ void ieee80211_tx_status(struct ieee802
  
        if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
                struct ieee80211_work *wk;
+               u64 cookie = (unsigned long)skb;
  
                rcu_read_lock();
                list_for_each_entry_rcu(wk, &local->work_list, list) {
                        break;
                }
                rcu_read_unlock();
+               if (local->hw_roc_skb_for_status == skb) {
+                       cookie = local->hw_roc_cookie ^ 2;
+                       local->hw_roc_skb_for_status = NULL;
+               }
                cfg80211_mgmt_tx_status(
-                       skb->dev, (unsigned long) skb, skb->data, skb->len,
+                       skb->dev, cookie, skb->data, skb->len,
                        !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
        }
  
diff --combined net/mac80211/tx.c
@@@ -236,7 -236,6 +236,7 @@@ ieee80211_tx_h_dynamic_ps(struct ieee80
        if (local->hw.conf.flags & IEEE80211_CONF_PS) {
                ieee80211_stop_queues_by_reason(&local->hw,
                                                IEEE80211_QUEUE_STOP_REASON_PS);
 +              ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
                ieee80211_queue_work(&local->hw,
                                     &local->dynamic_ps_disable_work);
        }
@@@ -258,8 -257,7 +258,8 @@@ ieee80211_tx_h_check_assoc(struct ieee8
        if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
                return TX_CONTINUE;
  
 -      if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) &&
 +      if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
 +          test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
            !ieee80211_is_probe_req(hdr->frame_control) &&
            !ieee80211_is_nullfunc(hdr->frame_control))
                /*
@@@ -1396,8 -1394,7 +1396,8 @@@ static int invoke_tx_handlers(struct ie
        /* handlers after fragment must be aware of tx info fragmentation! */
        CALL_TXH(ieee80211_tx_h_stats);
        CALL_TXH(ieee80211_tx_h_encrypt);
 -      CALL_TXH(ieee80211_tx_h_calculate_duration);
 +      if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
 +              CALL_TXH(ieee80211_tx_h_calculate_duration);
  #undef CALL_TXH
  
   txh_done:
@@@ -1550,7 -1547,7 +1550,7 @@@ static int ieee80211_skb_resize(struct 
                skb_orphan(skb);
        }
  
-       if (skb_header_cloned(skb))
+       if (skb_cloned(skb))
                I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
        else if (head_need || tail_need)
                I802_DEBUG_INC(local->tx_expand_skb_head);
@@@ -1753,7 -1750,7 +1753,7 @@@ netdev_tx_t ieee80211_subif_start_xmit(
        __le16 fc;
        struct ieee80211_hdr hdr;
        struct ieee80211s_hdr mesh_hdr __maybe_unused;
 -      struct mesh_path *mppath = NULL;
 +      struct mesh_path __maybe_unused *mppath = NULL;
        const u8 *encaps_data;
        int encaps_len, skip_header_bytes;
        int nh_pos, h_pos;
                        mppath = mpp_path_lookup(skb->data, sdata);
  
                /*
 -               * Do not use address extension, if it is a packet from
 -               * the same interface and the destination is not being
 -               * proxied by any other mest point.
 +               * Use address extension if it is a packet from
 +               * another interface or if we know the destination
 +               * is being proxied by a portal (i.e. portal address
 +               * differs from proxied address)
                 */
                if (compare_ether_addr(sdata->vif.addr,
                                       skb->data + ETH_ALEN) == 0 &&
 -                  (!mppath || !compare_ether_addr(mppath->mpp, skb->data))) {
 +                  !(mppath && compare_ether_addr(mppath->mpp, skb->data))) {
                        hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
                                        skb->data, skb->data + ETH_ALEN);
                        meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
                                        sdata, NULL, NULL);
                } else {
 -                      /* packet from other interface */
                        int is_mesh_mcast = 1;
                        const u8 *mesh_da;
  
@@@ -2181,8 -2178,6 +2181,8 @@@ static void ieee80211_beacon_add_tim(st
        if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
                aid0 = 1;
  
 +      bss->dtim_bc_mc = aid0 == 1;
 +
        if (have_bits) {
                /* Find largest even number N1 so that bits numbered 1 through
                 * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits
@@@ -2246,7 -2241,7 +2246,7 @@@ struct sk_buff *ieee80211_beacon_get_ti
        if (sdata->vif.type == NL80211_IFTYPE_AP) {
                ap = &sdata->u.ap;
                beacon = rcu_dereference(ap->beacon);
 -              if (ap && beacon) {
 +              if (beacon) {
                        /*
                         * headroom, head length,
                         * tail length and maximum TIM length
                struct ieee80211_mgmt *mgmt;
                u8 *pos;
  
 +#ifdef CONFIG_MAC80211_MESH
 +              if (!sdata->u.mesh.mesh_id_len)
 +                      goto out;
 +#endif
 +
                /* headroom, head length, tail length and maximum TIM length */
                skb = dev_alloc_skb(local->tx_headroom + 400 +
                                sdata->u.mesh.vendor_ie_len);
@@@ -2553,7 -2543,7 +2553,7 @@@ ieee80211_get_buffered_bc(struct ieee80
        if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head)
                goto out;
  
 -      if (bss->dtim_count != 0)
 +      if (bss->dtim_count != 0 || !bss->dtim_bc_mc)
                goto out; /* send buffered bc/mc only after DTIM beacon */
  
        while (1) {
diff --combined net/mac80211/util.c
@@@ -986,6 -986,12 +986,6 @@@ int ieee80211_build_preq_ies(struct iee
                u16 cap = sband->ht_cap.cap;
                __le16 tmp;
  
 -              if (ieee80211_disable_40mhz_24ghz &&
 -                  sband->band == IEEE80211_BAND_2GHZ) {
 -                      cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 -                      cap &= ~IEEE80211_HT_CAP_SGI_40;
 -              }
 -
                *pos++ = WLAN_EID_HT_CAPABILITY;
                *pos++ = sizeof(struct ieee80211_ht_cap);
                memset(pos, 0, sizeof(struct ieee80211_ht_cap));
@@@ -1204,7 -1210,9 +1204,9 @@@ int ieee80211_reconfig(struct ieee80211
                switch (sdata->vif.type) {
                case NL80211_IFTYPE_STATION:
                        changed |= BSS_CHANGED_ASSOC;
+                       mutex_lock(&sdata->u.mgd.mtx);
                        ieee80211_bss_info_change_notify(sdata, changed);
+                       mutex_unlock(&sdata->u.mgd.mtx);
                        break;
                case NL80211_IFTYPE_ADHOC:
                        changed |= BSS_CHANGED_IBSS;