+ }
+
+@@ -980,7 +987,6 @@ int ath_reset(struct ath_softc *sc, bool
+ del_timer_sync(&common->ani.timer);
+
+ ath9k_ps_wakeup(sc);
+- spin_lock_bh(&sc->sc_pcu_lock);
+
+ ieee80211_stop_queues(hw);
+
+@@ -1023,7 +1029,6 @@ int ath_reset(struct ath_softc *sc, bool
+ }
+
+ ieee80211_wake_queues(hw);
+- spin_unlock_bh(&sc->sc_pcu_lock);
+
+ /* Start ANI */
+ if (!common->disable_ani)
+@@ -2326,9 +2331,9 @@ static void ath9k_flush(struct ieee80211
+ ath9k_ps_wakeup(sc);
+ spin_lock_bh(&sc->sc_pcu_lock);
+ drain_txq = ath_drain_all_txq(sc, false);
+- spin_unlock_bh(&sc->sc_pcu_lock);
+ if (!drain_txq)
+ ath_reset(sc, false);
++ spin_unlock_bh(&sc->sc_pcu_lock);
+ ath9k_ps_restore(sc);
+ ieee80211_wake_queues(hw);
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -565,11 +565,8 @@ static void ath_tx_complete_aggr(struct
+
+ rcu_read_unlock();
+
+- if (needreset) {
+- spin_unlock_bh(&sc->sc_pcu_lock);
++ if (needreset)
+ ath_reset(sc, false);
+- spin_lock_bh(&sc->sc_pcu_lock);
+- }
+ }
+
+ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
+@@ -664,7 +661,8 @@ static int ath_compute_num_delims(struct
+ * TODO - this could be improved to be dependent on the rate.
+ * The hardware can keep up at lower rates, but not higher rates
+ */
+- if (fi->keyix != ATH9K_TXKEYIX_INVALID)
++ if ((fi->keyix != ATH9K_TXKEYIX_INVALID) &&
++ !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))
+ ndelim += ATH_AGGR_ENCRYPTDELIM;
+
+ /*
+@@ -2169,7 +2167,9 @@ static void ath_tx_complete_poll_work(st
+ if (needreset) {
+ ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
+ "tx hung, resetting the chip\n");
++ spin_lock_bh(&sc->sc_pcu_lock);
+ ath_reset(sc, true);
++ spin_unlock_bh(&sc->sc_pcu_lock);
+ }
+
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+@@ -236,7 +236,7 @@ static void ar9003_paprd_get_gain_table(
+ memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
+ memset(index, 0, sizeof(ah->paprd_gain_table_index));
+
+- for (i = 0; i < 32; i++) {
++ for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
+ entry[i] = REG_READ(ah, reg);
+ index[i] = (entry[i] >> 24) & 0xff;
+ reg += 4;
+@@ -246,13 +246,13 @@ static void ar9003_paprd_get_gain_table(
+ static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
+ int target_power)
+ {
+- int olpc_gain_delta = 0;
++ int olpc_gain_delta = 0, cl_gain_mod;
+ int alpha_therm, alpha_volt;
+ int therm_cal_value, volt_cal_value;
+ int therm_value, volt_value;
+ int thermal_gain_corr, voltage_gain_corr;
+ int desired_scale, desired_gain = 0;
+- u32 reg;
++ u32 reg_olpc = 0, reg_cl_gain = 0;
+
+ REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+ AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+@@ -271,15 +271,29 @@ static unsigned int ar9003_get_desired_g
+ volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
+ AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE);
+
+- if (chain == 0)
+- reg = AR_PHY_TPC_11_B0;
+- else if (chain == 1)
+- reg = AR_PHY_TPC_11_B1;
+- else
+- reg = AR_PHY_TPC_11_B2;
++ switch (chain) {
++ case 0:
++ reg_olpc = AR_PHY_TPC_11_B0;
++ reg_cl_gain = AR_PHY_CL_TAB_0;
++ break;
++ case 1:
++ reg_olpc = AR_PHY_TPC_11_B1;
++ reg_cl_gain = AR_PHY_CL_TAB_1;
++ break;
++ case 2:
++ reg_olpc = AR_PHY_TPC_11_B2;
++ reg_cl_gain = AR_PHY_CL_TAB_2;
++ break;
++ default:
++ ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
++ "Invalid chainmask: %d\n", chain);
++ break;
++ }
+
+- olpc_gain_delta = REG_READ_FIELD(ah, reg,
++ olpc_gain_delta = REG_READ_FIELD(ah, reg_olpc,
+ AR_PHY_TPC_11_OLPC_GAIN_DELTA);
++ cl_gain_mod = REG_READ_FIELD(ah, reg_cl_gain,
++ AR_PHY_CL_TAB_CL_GAIN_MOD);
+
+ if (olpc_gain_delta >= 128)
+ olpc_gain_delta = olpc_gain_delta - 256;
+@@ -289,7 +303,7 @@ static unsigned int ar9003_get_desired_g
+ voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +
+ (128 / 2)) / 128;
+ desired_gain = target_power - olpc_gain_delta - thermal_gain_corr -
+- voltage_gain_corr + desired_scale;
++ voltage_gain_corr + desired_scale + cl_gain_mod;
+
+ return desired_gain;
+ }
+@@ -727,7 +741,7 @@ int ar9003_paprd_setup_gain_table(struct
+ desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
+
+ gain_index = 0;
+- for (i = 0; i < 32; i++) {
++ for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
+ if (ah->paprd_gain_table_index[i] >= desired_gain)
+ break;
+ gain_index++;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+@@ -1121,6 +1121,9 @@
+ #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5 0x3F00
+ #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S 8
+
++#define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f
++#define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0
++
+ void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
+
+ #endif /* AR9003_PHY_H */
+--- a/drivers/net/wireless/ath/ath5k/eeprom.c
++++ b/drivers/net/wireless/ath/ath5k/eeprom.c
+@@ -691,14 +691,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k
+ if (!chinfo[pier].pd_curves)
+ continue;
+
+- for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
++ for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) {
+ struct ath5k_pdgain_info *pd =
+ &chinfo[pier].pd_curves[pdg];
+
+- if (pd != NULL) {
+- kfree(pd->pd_step);
+- kfree(pd->pd_pwr);
+- }
++ kfree(pd->pd_step);
++ kfree(pd->pd_pwr);
+ }
+
+ kfree(chinfo[pier].pd_curves);
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -229,6 +229,7 @@ static void ar9003_hw_fill_txdesc(struct
+ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
+ struct ath_tx_status *ts)
+ {
++ struct ar9003_txc *txc = (struct ar9003_txc *) ds;
+ struct ar9003_txs *ads;
+ u32 status;
+
+@@ -238,7 +239,11 @@ static int ar9003_hw_proc_txdesc(struct
+ if ((status & AR_TxDone) == 0)
+ return -EINPROGRESS;
+
+- ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
++ ts->qid = MS(ads->ds_info, AR_TxQcuNum);
++ if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
++ ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
++ else
++ return -ENOENT;
+
+ if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
+ (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
+@@ -254,7 +259,6 @@ static int ar9003_hw_proc_txdesc(struct
+ ts->ts_seqnum = MS(status, AR_SeqNum);
+ ts->tid = MS(status, AR_TxTid);
+
+- ts->qid = MS(ads->ds_info, AR_TxQcuNum);
+ ts->desc_id = MS(ads->status1, AR_TxDescId);
+ ts->ts_tstamp = ads->status4;
+ ts->ts_status = 0;
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -15,6 +15,7 @@
+ #include <linux/gfp.h>
+ #include <asm/unaligned.h>
+ #include <net/mac80211.h>
++#include <crypto/aes.h>
+
+ #include "ieee80211_i.h"
+ #include "michael.h"
+@@ -86,6 +87,11 @@ ieee80211_rx_h_michael_mic_verify(struct
+ struct sk_buff *skb = rx->skb;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++ int queue = rx->queue;
++
++ /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
++ if (rx->queue == NUM_RX_DATA_QUEUES - 1)
++ queue = 0;
+
+ /*
+ * it makes no sense to check for MIC errors on anything other
+@@ -148,8 +154,8 @@ ieee80211_rx_h_michael_mic_verify(struct
+
+ update_iv:
+ /* update IV in key information to be able to detect replays */
+- rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32;
+- rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16;
++ rx->key->u.tkip.rx[queue].iv32 = rx->tkip_iv32;
++ rx->key->u.tkip.rx[queue].iv16 = rx->tkip_iv16;
+
+ return RX_CONTINUE;
+
+@@ -165,6 +171,7 @@ static int tkip_encrypt_skb(struct ieee8
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_key *key = tx->key;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++ unsigned long flags;
+ unsigned int hdrlen;
+ int len, tail;
+ u8 *pos;
+@@ -192,11 +199,12 @@ static int tkip_encrypt_skb(struct ieee8
+ pos += hdrlen;
+
+ /* Increase IV for the frame */
++ spin_lock_irqsave(&key->u.tkip.txlock, flags);
+ key->u.tkip.tx.iv16++;
+ if (key->u.tkip.tx.iv16 == 0)
+ key->u.tkip.tx.iv32++;
+-
+- pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
++ pos = ieee80211_tkip_add_iv(pos, key);
++ spin_unlock_irqrestore(&key->u.tkip.txlock, flags);