]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Wed, 24 Nov 2010 21:19:24 +0000 (16:19 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 24 Nov 2010 21:19:24 +0000 (16:19 -0500)
19 files changed:
1  2 
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/carl9170/usb.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/libertas/dev.h
drivers/net/wireless/libertas/main.c
include/linux/pci_ids.h
include/net/cfg80211.h
net/wireless/nl80211.c

index be9c8d3b33374d220c70258af5b02ab2c24c4161,170d44a35ccbd2ca06886be2be2ed8c1cd5dcf25..6f90acc5cca76296d7bcc7b7cb31797c7ffcfb59
@@@ -86,19 -86,33 +86,19 @@@ struct ath_config 
  /**
   * enum buffer_type - Buffer type flags
   *
 - * @BUF_HT: Send this buffer using HT capabilities
   * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
   * @BUF_AGGR: Indicates whether the buffer can be aggregated
   *    (used in aggregation scheduling)
 - * @BUF_RETRY: Indicates whether the buffer is retried
   * @BUF_XRETRY: To denote excessive retries of the buffer
   */
  enum buffer_type {
 -      BUF_HT                  = BIT(1),
        BUF_AMPDU               = BIT(2),
        BUF_AGGR                = BIT(3),
 -      BUF_RETRY               = BIT(4),
        BUF_XRETRY              = BIT(5),
  };
  
 -#define bf_nframes            bf_state.bfs_nframes
 -#define bf_al                 bf_state.bfs_al
 -#define bf_frmlen             bf_state.bfs_frmlen
 -#define bf_retries            bf_state.bfs_retries
 -#define bf_seqno              bf_state.bfs_seqno
 -#define bf_tidno              bf_state.bfs_tidno
 -#define bf_keyix                bf_state.bfs_keyix
 -#define bf_keytype            bf_state.bfs_keytype
 -#define bf_isht(bf)           (bf->bf_state.bf_type & BUF_HT)
  #define bf_isampdu(bf)                (bf->bf_state.bf_type & BUF_AMPDU)
  #define bf_isaggr(bf)         (bf->bf_state.bf_type & BUF_AGGR)
 -#define bf_isretried(bf)      (bf->bf_state.bf_type & BUF_RETRY)
  #define bf_isxretried(bf)     (bf->bf_state.bf_type & BUF_XRETRY)
  
  #define ATH_TXSTATUS_RING_SIZE 64
@@@ -163,8 -177,8 +163,8 @@@ void ath_descdma_cleanup(struct ath_sof
  
  /* returns delimiter padding required given the packet length */
  #define ATH_AGGR_GET_NDELIM(_len)                                     \
 -      (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?           \
 -        (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
 +       (((_len) >= ATH_AGGR_MINPLEN) ? 0 :                             \
 +        DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ))
  
  #define BAW_WITHIN(_start, _bawsz, _seqno) \
        ((((_seqno) - (_start)) & 4095) < (_bawsz))
@@@ -181,6 -195,7 +181,6 @@@ enum ATH_AGGR_STATUS 
  
  #define ATH_TXFIFO_DEPTH 8
  struct ath_txq {
 -      int axq_class;
        u32 axq_qnum;
        u32 *axq_link;
        struct list_head axq_q;
        struct list_head txq_fifo_pending;
        u8 txq_headidx;
        u8 txq_tailidx;
 +      int pending_frames;
  };
  
  struct ath_atx_ac {
 +      struct ath_txq *txq;
        int sched;
 -      int qnum;
        struct list_head list;
        struct list_head tid_q;
  };
  
 +struct ath_frame_info {
 +      int framelen;
 +      u32 keyix;
 +      enum ath9k_key_type keytype;
 +      u8 retries;
 +      u16 seqno;
 +};
 +
  struct ath_buf_state {
 -      int bfs_nframes;
 -      u16 bfs_al;
 -      u16 bfs_frmlen;
 -      int bfs_seqno;
 -      int bfs_tidno;
 -      int bfs_retries;
        u8 bf_type;
        u8 bfs_paprd;
 -      unsigned long bfs_paprd_timestamp;
 -      u32 bfs_keyix;
 -      enum ath9k_key_type bfs_keytype;
 +      enum ath9k_internal_frame_type bfs_ftype;
  };
  
  struct ath_buf {
        dma_addr_t bf_daddr;            /* physical addr of desc */
        dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
        bool bf_stale;
 -      bool bf_tx_aborted;
        u16 bf_flags;
        struct ath_buf_state bf_state;
        struct ath_wiphy *aphy;
@@@ -255,6 -270,7 +255,6 @@@ struct ath_node 
        struct ath_atx_ac ac[WME_NUM_AC];
        u16 maxampdu;
        u8 mpdudensity;
 -      int last_rssi;
  };
  
  #define AGGR_CLEANUP         BIT(1)
  
  struct ath_tx_control {
        struct ath_txq *txq;
 +      struct ath_node *an;
        int if_id;
        enum ath9k_internal_frame_type frame_type;
        u8 paprd;
  struct ath_tx {
        u16 seq_no;
        u32 txqsetup;
 -      int hwq_map[WME_NUM_AC];
        spinlock_t txbuflock;
        struct list_head txbuf;
        struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
        struct ath_descdma txdma;
 -      int pending_frames[WME_NUM_AC];
 +      struct ath_txq *txq_map[WME_NUM_AC];
  };
  
  struct ath_rx_edma {
@@@ -294,6 -310,7 +294,6 @@@ struct ath_rx 
        u8 rxotherant;
        u32 *rxlink;
        unsigned int rxfilter;
 -      spinlock_t pcu_lock;
        spinlock_t rxbuflock;
        struct list_head rxbuf;
        struct ath_descdma rxdma;
@@@ -310,6 -327,7 +310,6 @@@ void ath_rx_cleanup(struct ath_softc *s
  int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
  struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
  void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
 -int ath_tx_setup(struct ath_softc *sc, int haltype);
  void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
  void ath_draintxq(struct ath_softc *sc,
                     struct ath_txq *txq, bool retry_tx);
@@@ -324,6 -342,7 +324,6 @@@ int ath_tx_start(struct ieee80211_hw *h
                 struct ath_tx_control *txctl);
  void ath_tx_tasklet(struct ath_softc *sc);
  void ath_tx_edma_tasklet(struct ath_softc *sc);
 -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
  int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
                      u16 tid, u16 *ssn);
  void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
@@@ -581,14 -600,13 +581,14 @@@ struct ath_softc 
        struct ath_hw *sc_ah;
        void __iomem *mem;
        int irq;
 -      spinlock_t sc_resetlock;
        spinlock_t sc_serial_rw;
        spinlock_t sc_pm_lock;
 +      spinlock_t sc_pcu_lock;
        struct mutex mutex;
        struct work_struct paprd_work;
        struct work_struct hw_check_work;
        struct completion paprd_complete;
 +      bool paprd_pending;
  
        u32 intrstatus;
        u32 sc_flags; /* SC_OP_* */
@@@ -644,11 -662,11 +644,11 @@@ struct ath_wiphy 
        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_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
  int ath_cabq_update(struct ath_softc *);
  
  static inline void ath_read_cachesize(struct ath_common *common, int *csz)
  }
  
  extern struct ieee80211_ops ath9k_ops;
+ extern struct pm_qos_request_list ath9k_pm_qos_req;
  extern int modparam_nohwcrypt;
  extern int led_blink;
  
@@@ -697,7 -716,7 +698,7 @@@ void ath9k_ps_restore(struct ath_softc 
  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);
 +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);
index 34a588837d4d6b9b908ef2d079f08e7edb862d7f,195406db3bd899b28f96c7b8214428822c3735db..e75697858ae8b724597da31470fa7921ae3ebb2b
@@@ -37,7 -37,7 +37,7 @@@ static bool ath9k_hw_ar9287_fill_eeprom
        int addr, eep_start_loc;
        eep_data = (u16 *)eep;
  
-       if (ah->hw_version.devid == 0x7015)
+       if (AR9287_HTC_DEVID(ah))
                eep_start_loc = AR9287_HTC_EEP_START_LOC;
        else
                eep_start_loc = AR9287_EEP_START_LOC;
@@@ -626,13 -626,13 +626,13 @@@ static void ath9k_hw_set_ar9287_power_p
        struct cal_target_power_ht targetPowerHt20,
                                    targetPowerHt40 = {0, {0, 0, 0, 0} };
        u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
 -      u16 ctlModesFor11g[] = {CTL_11B,
 -                              CTL_11G,
 -                              CTL_2GHT20,
 -                              CTL_11B_EXT,
 -                              CTL_11G_EXT,
 -                              CTL_2GHT40};
 -      u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq;
 +      static const u16 ctlModesFor11g[] = {
 +              CTL_11B, CTL_11G, CTL_2GHT20,
 +              CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
 +      };
 +      u16 numCtlModes = 0;
 +      const u16 *pCtlMode = NULL;
 +      u16 ctlMode, freq;
        struct chan_centers centers;
        int tx_chainmask;
        u16 twiceMinEdgePower;
@@@ -853,7 -853,7 +853,7 @@@ static void ath9k_hw_ar9287_set_txpower
                                        struct ath9k_channel *chan, u16 cfgCtl,
                                        u8 twiceAntennaReduction,
                                        u8 twiceMaxRegulatoryPower,
 -                                      u8 powerLimit)
 +                                      u8 powerLimit, bool test)
  {
        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
  
        ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
  
 +      regulatory->max_power_level = 0;
        for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
                ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
                if (ratesArray[i] > AR9287_MAX_RATE_POWER)
                        ratesArray[i] = AR9287_MAX_RATE_POWER;
 +
 +              if (ratesArray[i] > regulatory->max_power_level)
 +                      regulatory->max_power_level = ratesArray[i];
        }
  
 +      if (test)
 +              return;
 +
 +      if (IS_CHAN_2GHZ(chan))
 +              i = rate1l;
 +      else
 +              i = rate6mb;
 +
 +      regulatory->max_power_level = ratesArray[i];
 +
        if (AR_SREV_9280_20_OR_LATER(ah)) {
                for (i = 0; i < Ar5416RateSize; i++)
                        ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
                          | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
                          | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
        }
 -
 -      if (IS_CHAN_2GHZ(chan))
 -              i = rate1l;
 -      else
 -              i = rate6mb;
 -
 -      if (AR_SREV_9280_20_OR_LATER(ah))
 -              regulatory->max_power_level =
 -                      ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
 -      else
 -              regulatory->max_power_level = ratesArray[i];
  }
  
  static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
index f214e8e581ca7fd1b58a2c471135b1d6e6b5805a,7c8a38d04561c26754147bea9e447724a9e8eb42..cba904a3e320757978ab13253af264d57fed7d23
@@@ -249,6 -249,8 +249,8 @@@ static int ath9k_init_htc_services(stru
        case 0x7010:
        case 0x7015:
        case 0x9018:
+       case 0xA704:
+       case 0x1200:
                priv->htc->credits = 45;
                break;
        default:
@@@ -306,7 -308,7 +308,7 @@@ static void ath9k_regwrite_single(void 
        struct ath_hw *ah = (struct ath_hw *) hw_priv;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
 -      __be32 buf[2] = {
 +      const __be32 buf[2] = {
                cpu_to_be32(reg_offset),
                cpu_to_be32(val),
        };
@@@ -639,7 -641,6 +641,7 @@@ static int ath9k_init_priv(struct ath9k
  
        ah->hw_version.devid = devid;
        ah->hw_version.subsysid = 0; /* FIXME */
 +      ah->ah_flags |= AH_USE_EEPROM;
        priv->ah = ah;
  
        common = ath9k_hw_common(ah);
index 5324ffd96ec76e18cbd951a1581cbacf041896d8,29d80ca783933684b7c5c531cbb970ee7e006cda..77958675b55f6eeaf56ad2e59810f7bf667359c6
  /* TX */
  /******/
  
 +static const int subtype_txq_to_hwq[] = {
 +      [WME_AC_BE] = ATH_TXQ_AC_BE,
 +      [WME_AC_BK] = ATH_TXQ_AC_BK,
 +      [WME_AC_VI] = ATH_TXQ_AC_VI,
 +      [WME_AC_VO] = ATH_TXQ_AC_VO,
 +};
 +
  #define ATH9K_HTC_INIT_TXQ(subtype) do {                      \
 -              qi.tqi_subtype = subtype;                       \
 +              qi.tqi_subtype = subtype_txq_to_hwq[subtype];   \
                qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;             \
                qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;            \
                qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;            \
@@@ -128,7 -121,7 +128,7 @@@ int ath9k_htc_tx_start(struct ath9k_htc
                        tx_hdr.data_type = ATH9K_HTC_NORMAL;
                }
  
-               if (ieee80211_is_data(fc)) {
+               if (ieee80211_is_data_qos(fc)) {
                        qc = ieee80211_get_qos_ctl(hdr);
                        tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
                }
index c686987c4840bb254c11845575289e183d76bbdd,6ebc68bca91f0a999614572b38f69452df49645d..ce9e59f4cd3dbf9cae16e2086bc419a1a150da47
@@@ -310,9 -310,10 +310,9 @@@ static bool ath9k_hw_chip_test(struct a
        struct ath_common *common = ath9k_hw_common(ah);
        u32 regAddr[2] = { AR_STA_ID0 };
        u32 regHold[2];
 -      u32 patternData[4] = { 0x55555555,
 -                             0xaaaaaaaa,
 -                             0x66666666,
 -                             0x99999999 };
 +      static const u32 patternData[4] = {
 +              0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999
 +      };
        int i, j, loop_max;
  
        if (!AR_SREV_9300_20_OR_LATER(ah)) {
@@@ -418,6 -419,10 +418,6 @@@ static void ath9k_hw_init_defaults(stru
        ah->hw_version.magic = AR5416_MAGIC;
        ah->hw_version.subvendorid = 0;
  
 -      ah->ah_flags = 0;
 -      if (!AR_SREV_9100(ah))
 -              ah->ah_flags = AH_USE_EEPROM;
 -
        ah->atim_window = 0;
        ah->sta_id1_defaults =
                AR_STA_ID1_CRPT_MIC_ENABLE |
@@@ -435,7 -440,7 +435,7 @@@ static int ath9k_hw_init_macaddr(struc
        u32 sum;
        int i;
        u16 eeval;
 -      u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
 +      static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
  
        sum = 0;
        for (i = 0; i < 3; i++) {
@@@ -479,6 -484,7 +479,7 @@@ static int ath9k_hw_post_init(struct at
                ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
                          "Failed allocating banks for "
                          "external radio\n");
+               ath9k_hw_rf_free_ext_banks(ah);
                return ecode;
        }
  
@@@ -947,9 -953,12 +948,12 @@@ static void ath9k_hw_set_operating_mode
                REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
                break;
        case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_MONITOR:
                REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
                break;
+       default:
+               if (ah->is_monitoring)
+                       REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
+               break;
        }
  }
  
@@@ -1161,7 -1170,7 +1165,7 @@@ static bool ath9k_hw_channel_change(str
                             channel->max_antenna_gain * 2,
                             channel->max_power * 2,
                             min((u32) MAX_RATE_POWER,
 -                           (u32) regulatory->power_limit));
 +                           (u32) regulatory->power_limit), false);
  
        ath9k_hw_rfbus_done(ah);
  
@@@ -1629,7 -1638,6 +1633,6 @@@ void ath9k_hw_beaconinit(struct ath_hw 
  
        switch (ah->opmode) {
        case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_MONITOR:
                REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
                REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
                REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
                        AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
                break;
        default:
+               if (ah->is_monitoring) {
+                       REG_WRITE(ah, AR_NEXT_TBTT_TIMER,
+                                       TU_TO_USEC(next_beacon));
+                       REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
+                       REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
+                       flags |= AR_TBTT_TIMER_EN;
+                       break;
+               }
                ath_print(ath9k_hw_common(ah), ATH_DBG_BEACON,
                          "%s: unsupported opmode: %d\n",
                          __func__, ah->opmode);
@@@ -1817,10 -1833,6 +1828,10 @@@ int ath9k_hw_fill_cap_info(struct ath_h
  
        ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
  
 +      /* enable key search for every frame in an aggregate */
 +      if (AR_SREV_9300_20_OR_LATER(ah))
 +              ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
 +
        pCap->low_2ghz_chan = 2312;
        pCap->high_2ghz_chan = 2732;
  
        if (AR_SREV_9300_20_OR_LATER(ah))
                pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
  
 +      if (AR_SREV_9300_20_OR_LATER(ah))
 +              ah->ent_mode = REG_READ(ah, AR_ENT_OTP);
 +
        if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
                pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
  
@@@ -2167,7 -2176,7 +2178,7 @@@ bool ath9k_hw_disable(struct ath_hw *ah
  }
  EXPORT_SYMBOL(ath9k_hw_disable);
  
 -void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
 +void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
  {
        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ath9k_channel *chan = ah->curchan;
                                 channel->max_antenna_gain * 2,
                                 channel->max_power * 2,
                                 min((u32) MAX_RATE_POWER,
 -                               (u32) regulatory->power_limit));
 +                               (u32) regulatory->power_limit), test);
  }
  EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
  
@@@ -2314,10 -2323,11 +2325,10 @@@ static u32 rightmost_index(struct ath_g
        return timer_table->gen_timer_index[b];
  }
  
 -u32 ath9k_hw_gettsf32(struct ath_hw *ah)
 +static u32 ath9k_hw_gettsf32(struct ath_hw *ah)
  {
        return REG_READ(ah, AR_TSF_L32);
  }
 -EXPORT_SYMBOL(ath9k_hw_gettsf32);
  
  struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
                                          void (*trigger)(void *),
index d5e68347ef728c624ddc2f159edf1d84578911d4,d47d1b4b6002f2650cba8c80401cd52089800cc6..cc8f3b9af71f7152b31634b942ef5d6c50f68187
  #define PAPRD_GAIN_TABLE_ENTRIES    32
  #define PAPRD_TABLE_SZ              24
  
 +enum ath_hw_txq_subtype {
 +      ATH_TXQ_AC_BE = 0,
 +      ATH_TXQ_AC_BK = 1,
 +      ATH_TXQ_AC_VI = 2,
 +      ATH_TXQ_AC_VO = 3,
 +};
 +
  enum ath_ini_subsys {
        ATH_INI_PRE = 0,
        ATH_INI_CORE,
@@@ -484,40 -477,6 +484,40 @@@ struct ath_hw_antcomb_conf 
        u8 fast_div_bias;
  };
  
 +/**
 + * struct ath_hw_radar_conf - radar detection initialization parameters
 + *
 + * @pulse_inband: threshold for checking the ratio of in-band power
 + *    to total power for short radar pulses (half dB steps)
 + * @pulse_inband_step: threshold for checking an in-band power to total
 + *    power ratio increase for short radar pulses (half dB steps)
 + * @pulse_height: threshold for detecting the beginning of a short
 + *    radar pulse (dB step)
 + * @pulse_rssi: threshold for detecting if a short radar pulse is
 + *    gone (dB step)
 + * @pulse_maxlen: maximum pulse length (0.8 us steps)
 + *
 + * @radar_rssi: RSSI threshold for starting long radar detection (dB steps)
 + * @radar_inband: threshold for checking the ratio of in-band power
 + *    to total power for long radar pulses (half dB steps)
 + * @fir_power: threshold for detecting the end of a long radar pulse (dB)
 + *
 + * @ext_channel: enable extension channel radar detection
 + */
 +struct ath_hw_radar_conf {
 +      unsigned int pulse_inband;
 +      unsigned int pulse_inband_step;
 +      unsigned int pulse_height;
 +      unsigned int pulse_rssi;
 +      unsigned int pulse_maxlen;
 +
 +      unsigned int radar_rssi;
 +      unsigned int radar_inband;
 +      int fir_power;
 +
 +      bool ext_channel;
 +};
 +
  /**
   * struct ath_hw_private_ops - callbacks used internally by hardware code
   *
@@@ -583,8 -542,6 +583,8 @@@ struct ath_hw_private_ops 
        bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
                            int param);
        void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
 +      void (*set_radar_params)(struct ath_hw *ah,
 +                               struct ath_hw_radar_conf *conf);
  
        /* ANI */
        void (*ani_cache_ini_regs)(struct ath_hw *ah);
@@@ -665,6 -622,7 +665,7 @@@ struct ath_hw 
  
        bool sw_mgmt_crypto;
        bool is_pciexpress;
+       bool is_monitoring;
        bool need_an_top2_fixup;
        u16 tx_trig_level;
  
        u8 txchainmask;
        u8 rxchainmask;
  
 +      struct ath_hw_radar_conf radar_conf;
 +
        u32 originalGain[22];
        int initPDADC;
        int PDADCdelta;
         * this register when in sleep states.
         */
        u32 WARegVal;
 +
 +      /* Enterprise mode cap */
 +      u32 ent_mode;
  };
  
  static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
@@@ -866,6 -819,12 +867,6 @@@ static inline struct ath_hw_ops *ath9k_
        return &ah->ops;
  }
  
 -static inline int sign_extend(int val, const int nbits)
 -{
 -      int order = BIT(nbits-1);
 -      return (val ^ order) - order;
 -}
 -
  /* Initialization, Detach, Reset */
  const char *ath9k_hw_probe(u16 vendorid, u16 devid);
  void ath9k_hw_deinit(struct ath_hw *ah);
@@@ -902,7 -861,7 +903,7 @@@ u32 ath9k_hw_getrxfilter(struct ath_hw 
  void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
  bool ath9k_hw_phy_disable(struct ath_hw *ah);
  bool ath9k_hw_disable(struct ath_hw *ah);
 -void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
 +void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test);
  void ath9k_hw_setopmode(struct ath_hw *ah);
  void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
  void ath9k_hw_setbssidmask(struct ath_hw *ah);
@@@ -934,6 -893,7 +935,6 @@@ void ath9k_hw_gen_timer_stop(struct ath
  
  void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
  void ath_gen_timer_isr(struct ath_hw *hw);
 -u32 ath9k_hw_gettsf32(struct ath_hw *ah);
  
  void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
  
index e7764ce881df33dec180c0434946ae686e006390,92bc5c5f48768ac42ca4b1bd02690d9d38ebed80..7eef1faee668787fed775db0a1f751c24c44597f
@@@ -15,6 -15,7 +15,7 @@@
   */
  
  #include <linux/slab.h>
+ #include <linux/pm_qos_params.h>
  
  #include "ath9k.h"
  
@@@ -179,6 -180,8 +180,8 @@@ static const struct ath_ops ath9k_commo
        .write = ath9k_iowrite32,
  };
  
+ struct pm_qos_request_list ath9k_pm_qos_req;
  /**************************/
  /*     Initialization     */
  /**************************/
@@@ -395,8 -398,7 +398,8 @@@ static void ath9k_init_crypto(struct at
  
  static int ath9k_init_btcoex(struct ath_softc *sc)
  {
 -      int r, qnum;
 +      struct ath_txq *txq;
 +      int r;
  
        switch (sc->sc_ah->btcoex_hw.scheme) {
        case ATH_BTCOEX_CFG_NONE:
                r = ath_init_btcoex_timer(sc);
                if (r)
                        return -1;
 -              qnum = sc->tx.hwq_map[WME_AC_BE];
 -              ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum);
 +              txq = sc->tx.txq_map[WME_AC_BE];
 +              ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
                sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
                break;
        default:
  
  static int ath9k_init_queues(struct ath_softc *sc)
  {
 -      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        int i = 0;
  
 -      for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
 -              sc->tx.hwq_map[i] = -1;
 -
        sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
 -      if (sc->beacon.beaconq == -1) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup a beacon xmit queue\n");
 -              goto err;
 -      }
 -
        sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
 -      if (sc->beacon.cabq == NULL) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup CAB xmit queue\n");
 -              goto err;
 -      }
  
        sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
        ath_cabq_update(sc);
  
 -      if (!ath_tx_setup(sc, WME_AC_BK)) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup xmit queue for BK traffic\n");
 -              goto err;
 -      }
 -
 -      if (!ath_tx_setup(sc, WME_AC_BE)) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup xmit queue for BE traffic\n");
 -              goto err;
 -      }
 -      if (!ath_tx_setup(sc, WME_AC_VI)) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup xmit queue for VI traffic\n");
 -              goto err;
 -      }
 -      if (!ath_tx_setup(sc, WME_AC_VO)) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup xmit queue for VO traffic\n");
 -              goto err;
 -      }
 +      for (i = 0; i < WME_NUM_AC; i++)
 +              sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
  
        return 0;
 -
 -err:
 -      for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
 -              if (ATH_TXQ_SETUP(sc, i))
 -                      ath_tx_cleanupq(sc, &sc->tx.txq[i]);
 -
 -      return -EIO;
  }
  
  static int ath9k_init_channels_rates(struct ath_softc *sc)
@@@ -530,9 -573,6 +533,9 @@@ static int ath9k_init_softc(u16 devid, 
        ah->hw_version.subsysid = subsysid;
        sc->sc_ah = ah;
  
 +      if (!sc->dev->platform_data)
 +              ah->ah_flags |= AH_USE_EEPROM;
 +
        common = ath9k_hw_common(ah);
        common->ops = &ath9k_common_ops;
        common->bus_ops = bus_ops;
        spin_lock_init(&common->cc_lock);
  
        spin_lock_init(&sc->wiphy_lock);
 -      spin_lock_init(&sc->sc_resetlock);
        spin_lock_init(&sc->sc_serial_rw);
        spin_lock_init(&sc->sc_pm_lock);
        mutex_init(&sc->mutex);
@@@ -604,37 -645,6 +607,37 @@@ err_hw
        return ret;
  }
  
 +static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
 +{
 +      struct ieee80211_supported_band *sband;
 +      struct ieee80211_channel *chan;
 +      struct ath_hw *ah = sc->sc_ah;
 +      struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
 +      int i;
 +
 +      sband = &sc->sbands[band];
 +      for (i = 0; i < sband->n_channels; i++) {
 +              chan = &sband->channels[i];
 +              ah->curchan = &ah->channels[chan->hw_value];
 +              ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
 +              ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
 +              chan->max_power = reg->max_power_level / 2;
 +      }
 +}
 +
 +static void ath9k_init_txpower_limits(struct ath_softc *sc)
 +{
 +      struct ath_hw *ah = sc->sc_ah;
 +      struct ath9k_channel *curchan = ah->curchan;
 +
 +      if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
 +              ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
 +      if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
 +              ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
 +
 +      ah->curchan = curchan;
 +}
 +
  void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
  {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@@ -696,7 -706,6 +699,7 @@@ 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;
        if (error != 0)
                goto error_rx;
  
 +      ath9k_init_txpower_limits(sc);
 +
        /* Register with mac80211 */
        error = ieee80211_register_hw(hw);
        if (error)
        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;
  
        ath_init_leds(sc);
        ath_start_rfkill_poll(sc);
  
+       pm_qos_add_request(&ath9k_pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
+                          PM_QOS_DEFAULT_VALUE);
        return 0;
  
  error_world:
@@@ -821,6 -830,7 +827,7 @@@ void ath9k_deinit_device(struct ath_sof
        }
  
        ieee80211_unregister_hw(hw);
+       pm_qos_remove_request(&ath9k_pm_qos_req);
        ath_rx_cleanup(sc);
        ath_tx_cleanup(sc);
        ath9k_deinit_softc(sc);
index dede9a9aa68906408911c5310482f5b45ce6a7c8,25d3ef4c338e1eb45800b45fec112fc064c095af..50bdb5db23b4e1292fe20d55072353105a72fcda
@@@ -15,6 -15,7 +15,7 @@@
   */
  
  #include <linux/nl80211.h>
+ #include <linux/pm_qos_params.h>
  #include "ath9k.h"
  #include "btcoex.h"
  
@@@ -23,7 -24,7 +24,7 @@@ static void ath_update_txpow(struct ath
        struct ath_hw *ah = sc->sc_ah;
  
        if (sc->curtxpow != sc->config.txpowlimit) {
 -              ath9k_hw_set_txpowerlimit(ah, 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;
        }
@@@ -93,11 -94,13 +94,13 @@@ void ath9k_ps_wakeup(struct ath_softc *
  {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        unsigned long flags;
+       enum ath9k_power_mode power_mode;
  
        spin_lock_irqsave(&sc->sc_pm_lock, flags);
        if (++sc->ps_usecount != 1)
                goto unlock;
  
+       power_mode = sc->sc_ah->power_mode;
        ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
  
        /*
         * useful data. Better clear them now so that they don't mess up
         * survey data results.
         */
-       spin_lock(&common->cc_lock);
-       ath_hw_cycle_counters_update(common);
-       memset(&common->cc_survey, 0, sizeof(common->cc_survey));
-       spin_unlock(&common->cc_lock);
+       if (power_mode != ATH9K_PM_AWAKE) {
+               spin_lock(&common->cc_lock);
+               ath_hw_cycle_counters_update(common);
+               memset(&common->cc_survey, 0, sizeof(common->cc_survey));
+               spin_unlock(&common->cc_lock);
+       }
  
   unlock:
        spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
@@@ -230,8 -235,6 +235,8 @@@ int ath_set_channel(struct ath_softc *s
  
        ath9k_ps_wakeup(sc);
  
 +      spin_lock_bh(&sc->sc_pcu_lock);
 +
        /*
         * This is only performed if the channel settings have
         * actually changed.
         * hardware at the new frequency, and then re-enable
         * the relevant bits of the h/w.
         */
 -      ath9k_hw_set_interrupts(ah, 0);
 +      ath9k_hw_disable_interrupts(ah);
        ath_drain_all_txq(sc, false);
  
 -      spin_lock_bh(&sc->rx.pcu_lock);
 -
        stopped = ath_stoprecv(sc);
  
        /* XXX: do not flush receive queue here. We don't want
                  channel->center_freq, conf_is_ht40(conf),
                  fastcc);
  
 -      spin_lock_bh(&sc->sc_resetlock);
 -
        r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
        if (r) {
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to reset channel (%u MHz), "
                          "reset status %d\n",
                          channel->center_freq, r);
 -              spin_unlock_bh(&sc->sc_resetlock);
 -              spin_unlock_bh(&sc->rx.pcu_lock);
                goto ps_restore;
        }
 -      spin_unlock_bh(&sc->sc_resetlock);
  
        if (ath_startrecv(sc) != 0) {
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to restart recv logic\n");
                r = -EIO;
 -              spin_unlock_bh(&sc->rx.pcu_lock);
                goto ps_restore;
        }
  
 -      spin_unlock_bh(&sc->rx.pcu_lock);
 -
        ath_update_txpow(sc);
        ath9k_hw_set_interrupts(ah, ah->imask);
  
        }
  
   ps_restore:
 +      spin_unlock_bh(&sc->sc_pcu_lock);
 +
        ath9k_ps_restore(sc);
        return r;
  }
@@@ -330,7 -341,7 +335,7 @@@ void ath_paprd_calibrate(struct work_st
        struct ath_tx_control txctl;
        struct ath9k_hw_cal_data *caldata = ah->caldata;
        struct ath_common *common = ath9k_hw_common(ah);
 -      int qnum, ftype;
 +      int ftype;
        int chain_ok = 0;
        int chain;
        int len = 1800;
        memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
  
        memset(&txctl, 0, sizeof(txctl));
 -      qnum = sc->tx.hwq_map[WME_AC_BE];
 -      txctl.txq = &sc->tx.txq[qnum];
 +      txctl.txq = sc->tx.txq_map[WME_AC_BE];
  
        ath9k_ps_wakeup(sc);
        ar9003_paprd_init_table(ah);
                }
  
                init_completion(&sc->paprd_complete);
 +              sc->paprd_pending = true;
                ar9003_paprd_setup_gain_table(ah, chain);
                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_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
                                  "Timeout waiting for paprd training on "
@@@ -557,6 -567,7 +562,6 @@@ static void ath_node_attach(struct ath_
                an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
                                     sta->ht_cap.ampdu_factor);
                an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
 -              an->last_rssi = ATH_RSSI_DUMMY_MARKER;
        }
  }
  
@@@ -604,8 -615,6 +609,8 @@@ void ath9k_tasklet(unsigned long data
                return;
        }
  
 +      spin_lock_bh(&sc->sc_pcu_lock);
 +
        if (!ath9k_hw_check_alive(ah))
                ieee80211_queue_work(sc->hw, &sc->hw_check_work);
  
                rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
  
        if (status & rxmask) {
 -              spin_lock_bh(&sc->rx.pcu_lock);
 -
                /* Check for high priority Rx first */
                if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
                    (status & ATH9K_INT_RXHP))
                        ath_rx_tasklet(sc, 0, true);
  
                ath_rx_tasklet(sc, 0, false);
 -              spin_unlock_bh(&sc->rx.pcu_lock);
        }
  
        if (status & ATH9K_INT_TX) {
                        ath_gen_timer_isr(sc->sc_ah);
  
        /* re-enable hardware interrupt */
 -      ath9k_hw_set_interrupts(ah, ah->imask);
 +      ath9k_hw_enable_interrupts(ah);
 +
 +      spin_unlock_bh(&sc->sc_pcu_lock);
        ath9k_ps_restore(sc);
  }
  
@@@ -747,7 -757,7 +752,7 @@@ irqreturn_t ath_isr(int irq, void *dev
                 * interrupt; otherwise it will continue to
                 * fire.
                 */
 -              ath9k_hw_set_interrupts(ah, 0);
 +              ath9k_hw_disable_interrupts(ah);
                /*
                 * Let the hal handle the event. We assume
                 * it will clear whatever condition caused
                spin_lock(&common->cc_lock);
                ath9k_hw_proc_mib_event(ah);
                spin_unlock(&common->cc_lock);
 -              ath9k_hw_set_interrupts(ah, ah->imask);
 +              ath9k_hw_enable_interrupts(ah);
        }
  
        if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
@@@ -773,8 -783,8 +778,8 @@@ chip_reset
        ath_debug_stat_interrupt(sc, status);
  
        if (sched) {
 -              /* turn off every interrupt except SWBA */
 -              ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA));
 +              /* turn off every interrupt */
 +              ath9k_hw_disable_interrupts(ah);
                tasklet_schedule(&sc->intr_tq);
        }
  
@@@ -826,11 -836,9 +831,11 @@@ static u32 ath_get_extchanmode(struct a
  }
  
  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->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
  
                sc->sc_flags |= SC_OP_ANI_RUN;
@@@ -876,13 -883,13 +881,13 @@@ void ath_radio_enable(struct ath_softc 
        int r;
  
        ath9k_ps_wakeup(sc);
 +      spin_lock_bh(&sc->sc_pcu_lock);
 +
        ath9k_hw_configpcipowersave(ah, 0, 0);
  
        if (!ah->curchan)
                ah->curchan = ath_get_curchannel(sc, sc->hw);
  
 -      spin_lock_bh(&sc->rx.pcu_lock);
 -      spin_lock_bh(&sc->sc_resetlock);
        r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
        if (r) {
                ath_print(common, ATH_DBG_FATAL,
                          "reset status %d\n",
                          channel->center_freq, r);
        }
 -      spin_unlock_bh(&sc->sc_resetlock);
  
        ath_update_txpow(sc);
        if (ath_startrecv(sc) != 0) {
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to restart recv logic\n");
 -              spin_unlock_bh(&sc->rx.pcu_lock);
 +              spin_unlock_bh(&sc->sc_pcu_lock);
                return;
        }
 -      spin_unlock_bh(&sc->rx.pcu_lock);
 -
        if (sc->sc_flags & SC_OP_BEACONS)
                ath_beacon_config(sc, NULL);    /* restart beacons */
  
        ath9k_hw_set_gpio(ah, ah->led_pin, 0);
  
        ieee80211_wake_queues(hw);
 +      spin_unlock_bh(&sc->sc_pcu_lock);
 +
        ath9k_ps_restore(sc);
  }
  
@@@ -922,8 -930,6 +927,8 @@@ void ath_radio_disable(struct ath_soft
        int r;
  
        ath9k_ps_wakeup(sc);
 +      spin_lock_bh(&sc->sc_pcu_lock);
 +
        ieee80211_stop_queues(hw);
  
        /*
        }
  
        /* Disable interrupts */
 -      ath9k_hw_set_interrupts(ah, 0);
 +      ath9k_hw_disable_interrupts(ah);
  
        ath_drain_all_txq(sc, false);   /* clear pending tx frames */
  
 -      spin_lock_bh(&sc->rx.pcu_lock);
 -
        ath_stoprecv(sc);               /* turn off frame recv */
        ath_flushrecv(sc);              /* flush recv queue */
  
        if (!ah->curchan)
                ah->curchan = ath_get_curchannel(sc, hw);
  
 -      spin_lock_bh(&sc->sc_resetlock);
        r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
        if (r) {
                ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
                          "reset status %d\n",
                          channel->center_freq, r);
        }
 -      spin_unlock_bh(&sc->sc_resetlock);
  
        ath9k_hw_phy_disable(ah);
  
 -      spin_unlock_bh(&sc->rx.pcu_lock);
 -
        ath9k_hw_configpcipowersave(ah, 1, 1);
 +
 +      spin_unlock_bh(&sc->sc_pcu_lock);
        ath9k_ps_restore(sc);
 +
        ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
  }
  
@@@ -974,25 -983,29 +979,25 @@@ int ath_reset(struct ath_softc *sc, boo
        /* Stop ANI */
        del_timer_sync(&common->ani.timer);
  
 +      spin_lock_bh(&sc->sc_pcu_lock);
 +
        ieee80211_stop_queues(hw);
  
 -      ath9k_hw_set_interrupts(ah, 0);
 +      ath9k_hw_disable_interrupts(ah);
        ath_drain_all_txq(sc, retry_tx);
  
 -      spin_lock_bh(&sc->rx.pcu_lock);
 -
        ath_stoprecv(sc);
        ath_flushrecv(sc);
  
 -      spin_lock_bh(&sc->sc_resetlock);
        r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
        if (r)
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to reset hardware; reset status %d\n", r);
 -      spin_unlock_bh(&sc->sc_resetlock);
  
        if (ath_startrecv(sc) != 0)
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to start recv logic\n");
  
 -      spin_unlock_bh(&sc->rx.pcu_lock);
 -
        /*
         * We may be doing a reset in response to a request
         * that changes the channel so update any state that
        }
  
        ieee80211_wake_queues(hw);
 +      spin_unlock_bh(&sc->sc_pcu_lock);
  
        /* Start ANI */
        ath_start_ani(common);
        return r;
  }
  
 -static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
 -{
 -      int qnum;
 -
 -      switch (queue) {
 -      case 0:
 -              qnum = sc->tx.hwq_map[WME_AC_VO];
 -              break;
 -      case 1:
 -              qnum = sc->tx.hwq_map[WME_AC_VI];
 -              break;
 -      case 2:
 -              qnum = sc->tx.hwq_map[WME_AC_BE];
 -              break;
 -      case 3:
 -              qnum = sc->tx.hwq_map[WME_AC_BK];
 -              break;
 -      default:
 -              qnum = sc->tx.hwq_map[WME_AC_BE];
 -              break;
 -      }
 -
 -      return qnum;
 -}
 -
 -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
 -{
 -      int qnum;
 -
 -      switch (queue) {
 -      case WME_AC_VO:
 -              qnum = 0;
 -              break;
 -      case WME_AC_VI:
 -              qnum = 1;
 -              break;
 -      case WME_AC_BE:
 -              qnum = 2;
 -              break;
 -      case WME_AC_BK:
 -              qnum = 3;
 -              break;
 -      default:
 -              qnum = -1;
 -              break;
 -      }
 -
 -      return qnum;
 -}
 -
  /* 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,
@@@ -1106,16 -1168,19 +1111,16 @@@ static int ath9k_start(struct ieee80211
         * be followed by initialization of the appropriate bits
         * and then setup of the interrupt mask.
         */
 -      spin_lock_bh(&sc->rx.pcu_lock);
 -      spin_lock_bh(&sc->sc_resetlock);
 +      spin_lock_bh(&sc->sc_pcu_lock);
        r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
        if (r) {
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to reset hardware; reset status %d "
                          "(freq %u MHz)\n", r,
                          curchan->center_freq);
 -              spin_unlock_bh(&sc->sc_resetlock);
 -              spin_unlock_bh(&sc->rx.pcu_lock);
 +              spin_unlock_bh(&sc->sc_pcu_lock);
                goto mutex_unlock;
        }
 -      spin_unlock_bh(&sc->sc_resetlock);
  
        /*
         * This is needed only to setup initial state
                ath_print(common, ATH_DBG_FATAL,
                          "Unable to start recv logic\n");
                r = -EIO;
 -              spin_unlock_bh(&sc->rx.pcu_lock);
 +              spin_unlock_bh(&sc->sc_pcu_lock);
                goto mutex_unlock;
        }
 -      spin_unlock_bh(&sc->rx.pcu_lock);
 +      spin_unlock_bh(&sc->sc_pcu_lock);
  
        /* Setup our intr mask. */
        ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
                ah->imask |= ATH9K_INT_CST;
  
        sc->sc_flags &= ~SC_OP_INVALID;
+       sc->sc_ah->is_monitoring = false;
  
        /* Disable BMISS interrupt when we're not associated */
        ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
                        ath9k_btcoex_timer_resume(sc);
        }
  
+       pm_qos_update_request(&ath9k_pm_qos_req, 55);
  mutex_unlock:
        mutex_unlock(&sc->mutex);
  
  static int ath9k_tx(struct ieee80211_hw *hw,
                    struct sk_buff *skb)
  {
 -      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ath_wiphy *aphy = hw->priv;
        struct ath_softc *sc = aphy->sc;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_tx_control txctl;
 -      int padpos, padsize;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 -      int qnum;
  
        if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
                ath_print(common, ATH_DBG_XMIT,
        }
  
        memset(&txctl, 0, sizeof(struct ath_tx_control));
 -
 -      /*
 -       * As a temporary workaround, assign seq# here; this will likely need
 -       * to be cleaned up to work better with Beacon transmission and virtual
 -       * BSSes.
 -       */
 -      if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
 -              if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
 -                      sc->tx.seq_no += 0x10;
 -              hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
 -              hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
 -      }
 -
 -      /* Add the padding after the header if this is not already done */
 -      padpos = ath9k_cmn_padpos(hdr->frame_control);
 -      padsize = padpos & 3;
 -      if (padsize && skb->len>padpos) {
 -              if (skb_headroom(skb) < padsize)
 -                      return -1;
 -              skb_push(skb, padsize);
 -              memmove(skb->data, skb->data + padsize, padpos);
 -      }
 -
 -      qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
 -      txctl.txq = &sc->tx.txq[qnum];
 +      txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
  
        ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
  
@@@ -1305,25 -1400,22 +1313,25 @@@ static void ath9k_stop(struct ieee80211
                        ath9k_btcoex_timer_pause(sc);
        }
  
 +      spin_lock_bh(&sc->sc_pcu_lock);
 +
        /* make sure h/w will not generate any interrupt
         * before setting the invalid flag. */
 -      ath9k_hw_set_interrupts(ah, 0);
 +      ath9k_hw_disable_interrupts(ah);
  
 -      spin_lock_bh(&sc->rx.pcu_lock);
        if (!(sc->sc_flags & SC_OP_INVALID)) {
                ath_drain_all_txq(sc, false);
                ath_stoprecv(sc);
                ath9k_hw_phy_disable(ah);
        } else
                sc->rx.rxlink = NULL;
 -      spin_unlock_bh(&sc->rx.pcu_lock);
  
        /* disable HAL and put h/w to sleep */
        ath9k_hw_disable(ah);
        ath9k_hw_configpcipowersave(ah, 1, 1);
 +
 +      spin_unlock_bh(&sc->sc_pcu_lock);
 +
        ath9k_ps_restore(sc);
  
        /* Finally, put the chip in FULL SLEEP mode */
  
        sc->sc_flags |= SC_OP_INVALID;
  
+       pm_qos_update_request(&ath9k_pm_qos_req, PM_QOS_DEFAULT_VALUE);
        mutex_unlock(&sc->mutex);
  
        ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
@@@ -1409,8 -1503,7 +1419,7 @@@ static int ath9k_add_interface(struct i
        ath9k_hw_set_interrupts(ah, ah->imask);
  
        if (vif->type == NL80211_IFTYPE_AP    ||
-           vif->type == NL80211_IFTYPE_ADHOC ||
-           vif->type == NL80211_IFTYPE_MONITOR) {
+           vif->type == NL80211_IFTYPE_ADHOC) {
                sc->sc_flags |= SC_OP_ANI_RUN;
                ath_start_ani(common);
        }
@@@ -1560,8 -1653,12 +1569,12 @@@ static int ath9k_config(struct ieee8021
        if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
                if (conf->flags & IEEE80211_CONF_MONITOR) {
                        ath_print(common, ATH_DBG_CONFIG,
-                                 "HW opmode set to Monitor mode\n");
-                       sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR;
+                                 "Monitor mode is enabled\n");
+                       sc->sc_ah->is_monitoring = true;
+               } else {
+                       ath_print(common, ATH_DBG_CONFIG,
+                                 "Monitor mode is disabled\n");
+                       sc->sc_ah->is_monitoring = false;
                }
        }
  
@@@ -1725,15 -1822,12 +1738,15 @@@ static int ath9k_conf_tx(struct ieee802
        struct ath_wiphy *aphy = hw->priv;
        struct ath_softc *sc = aphy->sc;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 +      struct ath_txq *txq;
        struct ath9k_tx_queue_info qi;
 -      int ret = 0, qnum;
 +      int ret = 0;
  
        if (queue >= WME_NUM_AC)
                return 0;
  
 +      txq = sc->tx.txq_map[queue];
 +
        mutex_lock(&sc->mutex);
  
        memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
        qi.tqi_cwmin = params->cw_min;
        qi.tqi_cwmax = params->cw_max;
        qi.tqi_burstTime = params->txop;
 -      qnum = ath_get_hal_qnum(queue, sc);
  
        ath_print(common, ATH_DBG_CONFIG,
                  "Configure tx [queue/halq] [%d/%d],  "
                  "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
 -                queue, qnum, params->aifs, params->cw_min,
 +                queue, txq->axq_qnum, params->aifs, params->cw_min,
                  params->cw_max, params->txop);
  
 -      ret = ath_txq_update(sc, qnum, &qi);
 +      ret = ath_txq_update(sc, txq->axq_qnum, &qi);
        if (ret)
                ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
  
        if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
 -              if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret)
 +              if (queue == WME_AC_BE && !ret)
                        ath_beaconq_config(sc);
  
        mutex_unlock(&sc->mutex);
@@@ -1916,7 -2011,7 +1929,7 @@@ static void ath9k_bss_info_changed(stru
        if (changed & BSS_CHANGED_ASSOC) {
                ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
                        bss_conf->assoc);
 -              ath9k_bss_assoc_info(sc, vif, bss_conf);
 +              ath9k_bss_assoc_info(sc, hw, vif, bss_conf);
        }
  
        mutex_unlock(&sc->mutex);
@@@ -1979,9 -2074,6 +1992,9 @@@ static int ath9k_ampdu_action(struct ie
        case IEEE80211_AMPDU_RX_STOP:
                break;
        case IEEE80211_AMPDU_TX_START:
 +              if (!(sc->sc_flags & SC_OP_TXAGGR))
 +                      return -EOPNOTSUPP;
 +
                ath9k_ps_wakeup(sc);
                ret = ath_tx_aggr_start(sc, sta, tid, ssn);
                if (!ret)
index 60300b225b6d693604744cbbc769da71ecf76f71,1a62e351ec77c217598a46fae7bdbcc84c1c6050..262c81595f6d4a9eec218a4039e540c463a94ce1
@@@ -317,7 -317,7 +317,7 @@@ int ath_rx_init(struct ath_softc *sc, i
        struct ath_buf *bf;
        int error = 0;
  
 -      spin_lock_init(&sc->rx.pcu_lock);
 +      spin_lock_init(&sc->sc_pcu_lock);
        sc->sc_flags &= ~SC_OP_RXFLUSH;
        spin_lock_init(&sc->rx.rxbuflock);
  
@@@ -441,7 -441,7 +441,7 @@@ u32 ath_calcrxfilter(struct ath_softc *
         */
        if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) &&
             (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
-           (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR))
+           (sc->sc_ah->is_monitoring))
                rfilt |= ATH9K_RX_FILTER_PROM;
  
        if (sc->rx.rxfilter & FIF_CONTROL)
@@@ -518,7 -518,7 +518,7 @@@ bool ath_stoprecv(struct ath_softc *sc
        bool stopped;
  
        spin_lock_bh(&sc->rx.rxbuflock);
-       ath9k_hw_stoppcurecv(ah);
+       ath9k_hw_abortpcurecv(ah);
        ath9k_hw_setrxfilter(ah, 0);
        stopped = ath9k_hw_stopdmarecv(ah);
  
                sc->rx.rxlink = NULL;
        spin_unlock_bh(&sc->rx.rxbuflock);
  
 +      ATH_DBG_WARN(!stopped, "Could not stop RX, we could be "
 +                   "confusing the DMA engine when we start RX up\n");
        return stopped;
  }
  
@@@ -899,7 -897,7 +899,7 @@@ static bool ath9k_rx_accept(struct ath_
                 * decryption and MIC failures. For monitor mode,
                 * we also ignore the CRC error.
                 */
-               if (ah->opmode == NL80211_IFTYPE_MONITOR) {
+               if (ah->is_monitoring) {
                        if (rx_stats->rs_status &
                            ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
                              ATH9K_RXERR_CRC))
@@@ -964,23 -962,36 +964,23 @@@ static void ath9k_process_rssi(struct a
                               struct ieee80211_hdr *hdr,
                               struct ath_rx_status *rx_stats)
  {
 +      struct ath_wiphy *aphy = hw->priv;
        struct ath_hw *ah = common->ah;
 -      struct ieee80211_sta *sta;
 -      struct ath_node *an;
 -      int last_rssi = ATH_RSSI_DUMMY_MARKER;
 +      int last_rssi;
        __le16 fc;
  
 +      if (ah->opmode != NL80211_IFTYPE_STATION)
 +              return;
 +
        fc = hdr->frame_control;
 +      if (!ieee80211_is_beacon(fc) ||
 +          compare_ether_addr(hdr->addr3, common->curbssid))
 +              return;
  
 -      rcu_read_lock();
 -      /*
 -       * XXX: use ieee80211_find_sta! This requires quite a bit of work
 -       * under the current ath9k virtual wiphy implementation as we have
 -       * no way of tying a vif to wiphy. Typically vifs are attached to
 -       * at least one sdata of a wiphy on mac80211 but with ath9k virtual
 -       * wiphy you'd have to iterate over every wiphy and each sdata.
 -       */
 -      if (is_multicast_ether_addr(hdr->addr1))
 -              sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
 -      else
 -              sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
 -
 -      if (sta) {
 -              an = (struct ath_node *) sta->drv_priv;
 -              if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
 -                 !rx_stats->rs_moreaggr)
 -                      ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
 -              last_rssi = an->last_rssi;
 -      }
 -      rcu_read_unlock();
 +      if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
 +              ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
  
 +      last_rssi = aphy->last_rssi;
        if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
                rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
                                              ATH_RSSI_EP_MULTIPLIER);
                rx_stats->rs_rssi = 0;
  
        /* Update Beacon RSSI, this is used by ANI. */
 -      if (ieee80211_is_beacon(fc))
 -              ah->stats.avgbrssi = rx_stats->rs_rssi;
 +      ah->stats.avgbrssi = rx_stats->rs_rssi;
  }
  
  /*
index f6058b439fb306d205ed7638ec11fe7f34c99a1b,dddf579aacf1c391dfb3e9e73675de1a781760da..f1bbc7560c86d608491e2ba1590d8ab6b02f4be2
  #define AR_WA_RESET_EN                  (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
  #define AR_WA_ANALOG_SHIFT              (1 << 20)
  #define AR_WA_POR_SHORT                 (1 << 21) /* PCI-E Phy reset control */
+ #define AR_WA_BIT22                   (1 << 22)
  #define AR9285_WA_DEFAULT             0x004a050b
  #define AR9280_WA_DEFAULT             0x0040073b
  #define AR_WA_DEFAULT                 0x0000073f
  #define AR_DEVID_7010(_ah) \
        (((_ah)->hw_version.devid == 0x7010) || \
         ((_ah)->hw_version.devid == 0x7015) || \
-        ((_ah)->hw_version.devid == 0x9018))
+        ((_ah)->hw_version.devid == 0x9018) || \
+        ((_ah)->hw_version.devid == 0xA704) || \
+        ((_ah)->hw_version.devid == 0x1200))
+ #define AR9287_HTC_DEVID(_ah) \
+       (((_ah)->hw_version.devid == 0x7015) || \
+        ((_ah)->hw_version.devid == 0x1200))
  
  #define AR_RADIO_SREV_MAJOR                   0xf0
  #define AR_RAD5133_SREV_MAJOR                 0xc0
@@@ -1065,9 -1072,6 +1072,9 @@@ enum 
  #define AR_INTR_PRIO_ASYNC_MASK   0x40c8
  #define AR_INTR_PRIO_SYNC_MASK    0x40cc
  #define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4
 +#define AR_ENT_OTP              0x40d8
 +#define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000
 +#define AR_ENT_OTP_MPSD               0x00800000
  
  #define AR_RTC_9300_PLL_DIV          0x000003ff
  #define AR_RTC_9300_PLL_DIV_S        0
  #define AR_PCU_TBTT_PROTECT        0x00200000
  #define AR_PCU_CLEAR_VMF           0x01000000
  #define AR_PCU_CLEAR_BA_VALID      0x04000000
 +#define AR_PCU_ALWAYS_PERFORM_KEYSEARCH 0x10000000
  
  #define AR_PCU_BT_ANT_PREVENT_RX   0x00100000
  #define AR_PCU_BT_ANT_PREVENT_RX_S 20
index 4ae6a584907618d4b45b0273615c606c33600267,a314c2c2bfbea433849dc60ae7f44f67c2785358..511dbe3caf58bdc517cdff1d8399f07bb0881997
@@@ -428,7 -428,6 +428,7 @@@ static void carl9170_cancel_worker(stru
        cancel_delayed_work_sync(&ar->led_work);
  #endif /* CONFIG_CARL9170_LEDS */
        cancel_work_sync(&ar->ps_work);
 +      cancel_work_sync(&ar->ping_work);
        cancel_work_sync(&ar->ampdu_work);
  }
  
@@@ -534,21 -533,6 +534,21 @@@ void carl9170_restart(struct ar9170 *ar
         */
  }
  
 +static void carl9170_ping_work(struct work_struct *work)
 +{
 +      struct ar9170 *ar = container_of(work, struct ar9170, ping_work);
 +      int err;
 +
 +      if (!IS_STARTED(ar))
 +              return;
 +
 +      mutex_lock(&ar->mutex);
 +      err = carl9170_echo_test(ar, 0xdeadbeef);
 +      if (err)
 +              carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE);
 +      mutex_unlock(&ar->mutex);
 +}
 +
  static int carl9170_init_interface(struct ar9170 *ar,
                                   struct ieee80211_vif *vif)
  {
@@@ -663,7 -647,7 +663,7 @@@ init
        }
  
  unlock:
-       if (err && (vif_id != -1)) {
+       if (err && (vif_id >= 0)) {
                vif_priv->active = false;
                bitmap_release_region(&ar->vif_bitmap, vif_id, 0);
                ar->vifs--;
@@@ -1630,7 -1614,6 +1630,7 @@@ void *carl9170_alloc(size_t priv_size
                skb_queue_head_init(&ar->tx_pending[i]);
        }
        INIT_WORK(&ar->ps_work, carl9170_ps_work);
 +      INIT_WORK(&ar->ping_work, carl9170_ping_work);
        INIT_WORK(&ar->restart_work, carl9170_restart_work);
        INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
        INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
@@@ -1845,7 -1828,7 +1845,7 @@@ int carl9170_register(struct ar9170 *ar
        err = carl9170_led_register(ar);
        if (err)
                goto err_unreg;
 -#endif /* CONFIG_CAR9L170_LEDS */
 +#endif /* CONFIG_CARL9170_LEDS */
  
  #ifdef CONFIG_CARL9170_WPC
        err = carl9170_register_wps_button(ar);
index ddf5373ee689cff0f166cfffd8c744a4cf61dff4,7504ed14c72575a7befb91b0c0d9dd2684660af9..a268053e18e5e1e2f430deb19d2edc1ab158fd1d
@@@ -82,9 -82,11 +82,11 @@@ static struct usb_device_id carl9170_us
        { USB_DEVICE(0x07d1, 0x3c10) },
        /* D-Link DWA 160 A2 */
        { USB_DEVICE(0x07d1, 0x3a09) },
+       /* D-Link DWA 130 D */
+       { USB_DEVICE(0x07d1, 0x3a0f) },
        /* Netgear WNA1000 */
        { USB_DEVICE(0x0846, 0x9040) },
-       /* Netgear WNDA3100 */
+       /* Netgear WNDA3100 (v1) */
        { USB_DEVICE(0x0846, 0x9010) },
        /* Netgear WN111 v2 */
        { USB_DEVICE(0x0846, 0x9001), .driver_info = CARL9170_ONE_LED },
@@@ -431,7 -433,7 +433,7 @@@ static void carl9170_usb_rx_complete(st
                         * device.
                         */
  
 -                      carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
 +                      ieee80211_queue_work(ar->hw, &ar->ping_work);
                }
        } else {
                /*
@@@ -551,12 -553,12 +553,12 @@@ static int carl9170_usb_flush(struct ar
                usb_free_urb(urb);
        }
  
-       ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, HZ);
+       ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, 1000);
        if (ret == 0)
                err = -ETIMEDOUT;
  
        /* lets wait a while until the tx - queues are dried out */
-       ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, HZ);
+       ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, 1000);
        if (ret == 0)
                err = -ETIMEDOUT;
  
index c3ebc04cbd002247a13727dac2d0a9c9e3c9b97a,7edf8c2fb8c7c6072294854281ba40f416f1423a..8eb1393506bc2e91e9eb6e891cdb2e854d35c951
@@@ -61,7 -61,6 +61,7 @@@
  #include "iwl-helpers.h"
  #include "iwl-dev.h"
  #include "iwl-spectrum.h"
 +#include "iwl-legacy.h"
  
  /*
   * module name, copyright, version, etc.
@@@ -475,7 -474,7 +475,7 @@@ static int iwl3945_tx_skb(struct iwl_pr
        dma_addr_t phys_addr;
        dma_addr_t txcmd_phys;
        int txq_id = skb_get_queue_mapping(skb);
 -      u16 len, idx, len_org, hdr_len; /* TODO: len_org is not used */
 +      u16 len, idx, hdr_len;
        u8 id;
        u8 unicast;
        u8 sta_id;
         */
        len = sizeof(struct iwl3945_tx_cmd) +
                        sizeof(struct iwl_cmd_header) + hdr_len;
 -
 -      len_org = len;
        len = (len + 3) & ~3;
  
 -      if (len_org != len)
 -              len_org = 1;
 -      else
 -              len_org = 0;
 -
        /* Physical address of this Tx command's header (not MAC header!),
         * within command buffer array. */
        txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
                        spin_unlock_irqrestore(&priv->lock, flags);
                }
  
 -              iwl_stop_queue(priv, skb_get_queue_mapping(skb));
 +              iwl_stop_queue(priv, txq);
        }
  
        return 0;
@@@ -3051,22 -3057,22 +3051,22 @@@ static void iwl3945_bg_rx_replenish(str
        mutex_unlock(&priv->mutex);
  }
  
 -void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
 +void iwl3945_post_associate(struct iwl_priv *priv)
  {
        int rc = 0;
        struct ieee80211_conf *conf = NULL;
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
  
 -      if (!vif || !priv->is_open)
 +      if (!ctx->vif || !priv->is_open)
                return;
  
 -      if (vif->type == NL80211_IFTYPE_AP) {
 +      if (ctx->vif->type == NL80211_IFTYPE_AP) {
                IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
                return;
        }
  
        IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
 -                      vif->bss_conf.aid, ctx->active.bssid_addr);
 +                      ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
  
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
  
        ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
  
 -      ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
 +      ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
  
        IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
 -                      vif->bss_conf.aid, vif->bss_conf.beacon_int);
 +                      ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
  
 -      if (vif->bss_conf.use_short_preamble)
 +      if (ctx->vif->bss_conf.use_short_preamble)
                ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
        else
                ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
  
        if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
 -              if (vif->bss_conf.use_short_slot)
 +              if (ctx->vif->bss_conf.use_short_slot)
                        ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
                else
                        ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
  
        iwl3945_commit_rxon(priv, ctx);
  
 -      switch (vif->type) {
 +      switch (ctx->vif->type) {
        case NL80211_IFTYPE_STATION:
                iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
                break;
                break;
        default:
                IWL_ERR(priv, "%s Should not be called in %d mode\n",
 -                      __func__, vif->type);
 +                      __func__, ctx->vif->type);
                break;
        }
  }
@@@ -3228,10 -3234,9 +3228,10 @@@ static int iwl3945_mac_tx(struct ieee80
        return NETDEV_TX_OK;
  }
  
 -void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
 +void iwl3945_config_ap(struct iwl_priv *priv)
  {
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 +      struct ieee80211_vif *vif = ctx->vif;
        int rc = 0;
  
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@@ -3402,9 -3407,9 +3402,9 @@@ static void iwl3945_configure_filter(st
        ctx->staging.filter_flags |= filter_or;
  
        /*
 -       * Committing directly here breaks for some reason,
 -       * but we'll eventually commit the filter flags
 -       * change anyway.
 +       * Not committing directly because hardware can perform a scan,
 +       * but even if hw is ready, committing here breaks for some reason,
 +       * we'll eventually commit the filter flags change anyway.
         */
  
        mutex_unlock(&priv->mutex);
@@@ -3819,19 -3824,18 +3819,19 @@@ static struct attribute_group iwl3945_a
        .attrs = iwl3945_sysfs_entries,
  };
  
 -static struct ieee80211_ops iwl3945_hw_ops = {
 +struct ieee80211_ops iwl3945_hw_ops = {
        .tx = iwl3945_mac_tx,
        .start = iwl3945_mac_start,
        .stop = iwl3945_mac_stop,
        .add_interface = iwl_mac_add_interface,
        .remove_interface = iwl_mac_remove_interface,
 -      .config = iwl_mac_config,
 +      .change_interface = iwl_mac_change_interface,
 +      .config = iwl_legacy_mac_config,
        .configure_filter = iwl3945_configure_filter,
        .set_key = iwl3945_mac_set_key,
        .conf_tx = iwl_mac_conf_tx,
 -      .reset_tsf = iwl_mac_reset_tsf,
 -      .bss_info_changed = iwl_bss_info_changed,
 +      .reset_tsf = iwl_legacy_mac_reset_tsf,
 +      .bss_info_changed = iwl_legacy_mac_bss_info_changed,
        .hw_scan = iwl_mac_hw_scan,
        .sta_add = iwl3945_mac_sta_add,
        .sta_remove = iwl_mac_sta_remove,
@@@ -3862,7 -3866,6 +3862,7 @@@ static int iwl3945_init_drv(struct iwl_
        priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
  
        priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
 +      priv->tx_power_next = IWL_DEFAULT_TX_POWER;
  
        if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
                IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
@@@ -3962,7 -3965,7 +3962,7 @@@ static int iwl3945_pci_probe(struct pci
  
        /* mac80211 allocates memory for this device instance, including
         *   space for this driver's private structure */
 -      hw = iwl_alloc_all(cfg, &iwl3945_hw_ops);
 +      hw = iwl_alloc_all(cfg);
        if (hw == NULL) {
                pr_err("Can not allocate network device\n");
                err = -ENOMEM;
         * "the hard way", rather than using device's scan.
         */
        if (iwl3945_mod_params.disable_hw_scan) {
-               IWL_ERR(priv, "sw scan support is deprecated\n");
+               dev_printk(KERN_DEBUG, &(pdev->dev),
+                       "sw scan support is deprecated\n");
                iwl3945_hw_ops.hw_scan = NULL;
        }
  
  
        pci_enable_msi(priv->pci_dev);
  
 -      err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
 +      err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
                          IRQF_SHARED, DRV_NAME, priv);
        if (err) {
                IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
@@@ -4271,7 -4275,10 +4272,7 @@@ static struct pci_driver iwl3945_drive
        .id_table = iwl3945_hw_card_ids,
        .probe = iwl3945_pci_probe,
        .remove = __devexit_p(iwl3945_pci_remove),
 -#ifdef CONFIG_PM
 -      .suspend = iwl_pci_suspend,
 -      .resume = iwl_pci_resume,
 -#endif
 +      .driver.pm = IWL_PM_OPS,
  };
  
  static int __init iwl3945_init(void)
index a90953678b997b3d99b710c1ae267f3202f5b8d3,373930afc26b50f2d7cddeb9027b07f8e5ad7775..dee32d3681a5fe212aed6a1cbda87db4ee6609cb
@@@ -9,6 -9,8 +9,6 @@@
  #include <linux/sched.h>
  #include <linux/wait.h>
  #include <linux/slab.h>
 -#include <linux/sched.h>
 -#include <linux/wait.h>
  #include <linux/ieee80211.h>
  #include <net/cfg80211.h>
  #include <asm/unaligned.h>
@@@ -698,8 -700,9 +698,9 @@@ static void lbs_scan_worker(struct work
  
        if (priv->scan_channel < priv->scan_req->n_channels) {
                cancel_delayed_work(&priv->scan_work);
-               queue_delayed_work(priv->work_thread, &priv->scan_work,
-                       msecs_to_jiffies(300));
+               if (!priv->stopping)
+                       queue_delayed_work(priv->work_thread, &priv->scan_work,
+                               msecs_to_jiffies(300));
        }
  
        /* This is the final data we are about to send */
@@@ -2059,7 -2062,7 +2060,7 @@@ static void lbs_cfg_set_regulatory_hint
        };
  
        /* Section 5.17.2 */
 -      static struct region_code_mapping regmap[] = {
 +      static const struct region_code_mapping regmap[] = {
                {"US ", 0x10}, /* US FCC */
                {"CA ", 0x20}, /* Canada */
                {"EU ", 0x30}, /* ETSI   */
index f5a9851fc7ee79ca2960172d99d2f3bfe0faba52,cb14c38caf3aac8dc5dfc03fe6d77b0cd40bd42c..18dd9a02c459cea96c2158ac2bfc2764abed2087
@@@ -36,6 -36,7 +36,7 @@@ struct lbs_private 
        /* CFG80211 */
        struct wireless_dev *wdev;
        bool wiphy_registered;
+       bool stopping;
        struct cfg80211_scan_request *scan_req;
        u8 assoc_bss[ETH_ALEN];
        u8 disassoc_reason;
        uint32_t wol_criteria;
        uint8_t wol_gpio;
        uint8_t wol_gap;
 +      bool ehs_remove_supported;
  
        /* Transmitting */
        int tx_pending_len;             /* -1 while building packet */
index 6d7af91d52c27eeede1bd40f15c510f7070ebe7a,46b88b118c992c12764084233f8633a62a01a629..143473c5939323c75a2a15a915bfd1df5d9f315d
@@@ -104,6 -104,7 +104,7 @@@ static int lbs_dev_open(struct net_devi
        lbs_deb_enter(LBS_DEB_NET);
  
        spin_lock_irq(&priv->driver_lock);
+       priv->stopping = false;
  
        if (priv->connect_status == LBS_CONNECTED)
                netif_carrier_on(dev);
@@@ -131,10 -132,16 +132,16 @@@ static int lbs_eth_stop(struct net_devi
        lbs_deb_enter(LBS_DEB_NET);
  
        spin_lock_irq(&priv->driver_lock);
+       priv->stopping = true;
        netif_stop_queue(dev);
        spin_unlock_irq(&priv->driver_lock);
  
        schedule_work(&priv->mcast_work);
+       cancel_delayed_work_sync(&priv->scan_work);
+       if (priv->scan_req) {
+               cfg80211_scan_done(priv->scan_req, false);
+               priv->scan_req = NULL;
+       }
  
        lbs_deb_leave(LBS_DEB_NET);
        return 0;
@@@ -844,10 -851,9 +851,10 @@@ struct lbs_private *lbs_add_card(void *
        priv->work_thread = create_singlethread_workqueue("lbs_worker");
        INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
  
 -      priv->wol_criteria = 0xffffffff;
 +      priv->wol_criteria = EHS_REMOVE_WAKEUP;
        priv->wol_gpio = 0xff;
        priv->wol_gap = 20;
 +      priv->ehs_remove_supported = true;
  
        goto done;
  
diff --combined include/linux/pci_ids.h
index c6bcfe93b9cab9deeab76844ce8b76e2a2adf5bb,f29c25ede70d31f669acda5ae8d2af5c6d9a691a..32bd569496049f138b0e23c276fd8849982e935c
  #define PCI_DEVICE_ID_ELSA_MICROLINK  0x1000
  #define PCI_DEVICE_ID_ELSA_QS3000     0x3000
  
 +#define PCI_VENDOR_ID_STMICRO         0x104A
 +
  #define PCI_VENDOR_ID_BUSLOGIC                      0x104B
  #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
  #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER    0x1040
  #define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2    0x0348
  #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000       0x034C
  #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100         0x034E
 +#define PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V0      0x0360
 +#define PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V4      0x0364
  #define PCI_DEVICE_ID_NVIDIA_NVENET_15              0x0373
  #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA      0x03E7
  #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS           0x03EB
  #define PCI_DEVICE_ID_AFAVLAB_P030    0x2182
  #define PCI_SUBDEVICE_ID_AFAVLAB_P061         0x2150
  
+ #define PCI_VENDOR_ID_BCM_GVC          0x14a4
  #define PCI_VENDOR_ID_BROADCOM                0x14e4
  #define PCI_DEVICE_ID_TIGON3_5752     0x1600
  #define PCI_DEVICE_ID_TIGON3_5752M    0x1601
  
  #define PCI_VENDOR_ID_SILAN           0x1904
  
 +#define PCI_VENDOR_ID_RENESAS         0x1912
 +#define PCI_DEVICE_ID_RENESAS_SH7781  0x0001
 +#define PCI_DEVICE_ID_RENESAS_SH7780  0x0002
 +#define PCI_DEVICE_ID_RENESAS_SH7763  0x0004
 +#define PCI_DEVICE_ID_RENESAS_SH7785  0x0007
 +#define PCI_DEVICE_ID_RENESAS_SH7786  0x0010
 +
  #define PCI_VENDOR_ID_TDI               0x192E
  #define PCI_DEVICE_ID_TDI_EHCI          0x0101
  
  #define PCI_DEVICE_ID_INTEL_82375     0x0482
  #define PCI_DEVICE_ID_INTEL_82424     0x0483
  #define PCI_DEVICE_ID_INTEL_82378     0x0484
 +#define PCI_DEVICE_ID_INTEL_MRST_SD0  0x0807
 +#define PCI_DEVICE_ID_INTEL_MRST_SD1  0x0808
 +#define PCI_DEVICE_ID_INTEL_MFD_SD    0x0820
 +#define PCI_DEVICE_ID_INTEL_MFD_SDIO1 0x0821
 +#define PCI_DEVICE_ID_INTEL_MFD_SDIO2 0x0822
 +#define PCI_DEVICE_ID_INTEL_MFD_EMMC0 0x0823
 +#define PCI_DEVICE_ID_INTEL_MFD_EMMC1 0x0824
  #define PCI_DEVICE_ID_INTEL_I960      0x0960
  #define PCI_DEVICE_ID_INTEL_I960RM    0x0962
  #define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062
  #define PCI_DEVICE_ID_INTEL_82840_HB  0x1a21
  #define PCI_DEVICE_ID_INTEL_82845_HB  0x1a30
  #define PCI_DEVICE_ID_INTEL_IOAT      0x1a38
 -#define PCI_DEVICE_ID_INTEL_CPT_SMBUS 0x1c22
 -#define PCI_DEVICE_ID_INTEL_CPT_LPC_MIN       0x1c41
 -#define PCI_DEVICE_ID_INTEL_CPT_LPC_MAX       0x1c5f
 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN       0x1c41
 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX       0x1c5f
 +#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS    0x1d22
 +#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC      0x1d40
  #define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410
  #define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411
  #define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413
  #define PCI_DEVICE_ID_INTEL_ICH10_3   0x3a1a
  #define PCI_DEVICE_ID_INTEL_ICH10_4   0x3a30
  #define PCI_DEVICE_ID_INTEL_ICH10_5   0x3a60
 -#define PCI_DEVICE_ID_INTEL_PCH_LPC_MIN       0x3b00
 -#define PCI_DEVICE_ID_INTEL_PCH_LPC_MAX       0x3b1f
 -#define PCI_DEVICE_ID_INTEL_PCH_SMBUS 0x3b30
 +#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN     0x3b00
 +#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX     0x3b1f
 +#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS       0x3b30
  #define PCI_DEVICE_ID_INTEL_IOAT_SNB  0x402f
  #define PCI_DEVICE_ID_INTEL_5100_16   0x65f0
  #define PCI_DEVICE_ID_INTEL_5100_21   0x65f5
  #define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035
  #define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036
  #define PCI_DEVICE_ID_INTEL_IOAT_SCNB 0x65ff
 -#define PCI_DEVICE_ID_INTEL_TOLAPAI_0 0x5031
 -#define PCI_DEVICE_ID_INTEL_TOLAPAI_1 0x5032
 +#define PCI_DEVICE_ID_INTEL_EP80579_0 0x5031
 +#define PCI_DEVICE_ID_INTEL_EP80579_1 0x5032
  #define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
  #define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
  #define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020
diff --combined include/net/cfg80211.h
index 8fd9eebd0cc98d97e93d5e7b33d51cf270898156,97b8b7c9b63cf9854e3b8c2e83154c8ecb0bea06..91f099556ac1dc5d9793476c1af77624fd30087c
@@@ -923,7 -923,6 +923,7 @@@ struct cfg80211_disassoc_request 
   * @privacy: this is a protected network, keys will be configured
   *    after joining
   * @basic_rates: bitmap of basic rates to use when creating the IBSS
 + * @mcast_rate: multicast tx rate (in 100 kbps)
   */
  struct cfg80211_ibss_params {
        u8 *ssid;
        u32 basic_rates;
        bool channel_fixed;
        bool privacy;
 +      int mcast_rate;
  };
  
  /**
@@@ -1306,9 -1304,6 +1306,9 @@@ struct cfg80211_ops 
        void    (*mgmt_frame_register)(struct wiphy *wiphy,
                                       struct net_device *dev,
                                       u16 frame_type, bool reg);
 +
 +      int     (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
 +      int     (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
  };
  
  /*
   *    initiator is %REGDOM_SET_BY_CORE).
   * @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will
   *    ignore regulatory domain settings until it gets its own regulatory
 - *    domain via its regulatory_hint(). After its gets its own regulatory
 - *    domain it will only allow further regulatory domain settings to
 - *    further enhance compliance. For example if channel 13 and 14 are
 - *    disabled by this regulatory domain no user regulatory domain can
 - *    enable these channels at a later time. This can be used for devices
 - *    which do not have calibration information gauranteed for frequencies
 - *    or settings outside of its regulatory domain.
 + *    domain via its regulatory_hint() unless the regulatory hint is
 + *    from a country IE. After its gets its own regulatory domain it will
 + *    only allow further regulatory domain settings to further enhance
 + *    compliance. For example if channel 13 and 14 are disabled by this
 + *    regulatory domain no user regulatory domain can enable these channels
 + *    at a later time. This can be used for devices which do not have
 + *    calibration information guaranteed for frequencies or settings
 + *    outside of its regulatory domain.
   * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure
   *    that passive scan flags and beaconing flags may not be lifted by
   *    cfg80211 due to regulatory beacon hints. For more information on beacon
@@@ -1361,7 -1355,7 +1361,7 @@@ enum wiphy_flags 
        WIPHY_FLAG_4ADDR_AP                     = BIT(5),
        WIPHY_FLAG_4ADDR_STATION                = BIT(6),
        WIPHY_FLAG_CONTROL_PORT_PROTOCOL        = BIT(7),
-       WIPHY_FLAG_IBSS_RSN                     = BIT(7),
+       WIPHY_FLAG_IBSS_RSN                     = BIT(8),
  };
  
  struct mac_address {
diff --combined net/wireless/nl80211.c
index 6055538422262b1b53f7b4bf68b6ddfe5796439d,4e78e3f26798378bad69630679565b1909bfb370..b15eb77195d898daaef20cc9814f0a9829127f1c
@@@ -166,13 -166,7 +166,13 @@@ static const struct nla_policy nl80211_
  
        [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
        [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
 +
        [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
 +
 +      [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 },
 +      [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
 +
 +      [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
  };
  
  /* policy for the key attributes */
@@@ -230,8 -224,8 +230,8 @@@ static int nl80211_prepare_netdev_dump(
        }
  
        *rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
-       if (IS_ERR(dev)) {
-               err = PTR_ERR(dev);
+       if (IS_ERR(*rdev)) {
+               err = PTR_ERR(*rdev);
                goto out_rtnl;
        }
  
@@@ -532,6 -526,7 +532,6 @@@ static int nl80211_send_wiphy(struct sk
                    dev->wiphy.rts_threshold);
        NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
                    dev->wiphy.coverage_class);
 -
        NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
                   dev->wiphy.max_scan_ssids);
        NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
        if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL)
                NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE);
  
 +      if (dev->ops->get_antenna) {
 +              u32 tx_ant = 0, rx_ant = 0;
 +              int res;
 +              res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant);
 +              if (!res) {
 +                      NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, tx_ant);
 +                      NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, rx_ant);
 +              }
 +      }
 +
        nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
        if (!nl_modes)
                goto nla_put_failure;
@@@ -1039,22 -1024,6 +1039,22 @@@ static int nl80211_set_wiphy(struct sk_
                        goto bad_res;
        }
  
 +      if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
 +          info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
 +              u32 tx_ant, rx_ant;
 +              if (!rdev->ops->set_antenna) {
 +                      result = -EOPNOTSUPP;
 +                      goto bad_res;
 +              }
 +
 +              tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
 +              rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
 +
 +              result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant);
 +              if (result)
 +                      goto bad_res;
 +      }
 +
        changed = 0;
  
        if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
@@@ -3683,9 -3652,6 +3683,9 @@@ static int nl80211_join_ibss(struct sk_
                                return -EINVAL;
                }
        }
 +      if (info->attrs[NL80211_ATTR_MCAST_RATE])
 +              ibss.mcast_rate =
 +                      nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);
  
        if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
                connkeys = nl80211_parse_connkeys(rdev,