X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/542d043d67e72f8944ceaee7fbd83c7fbb82373e..c4b1c8b260778ba1e78f3318b3475d80828cab29:/package/mac80211/patches/300-pending_work.patch diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch index d4a2f4ed5..fde95c940 100644 --- a/package/mac80211/patches/300-pending_work.patch +++ b/package/mac80211/patches/300-pending_work.patch @@ -1,567 +1,2862 @@ ---- a/net/wireless/reg.c -+++ b/net/wireless/reg.c -@@ -1456,7 +1456,8 @@ static void reg_process_hint(struct regu - * We only time out user hints, given that they should be the only - * source of bogus requests. - */ -- if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER) -+ if (r != -EALREADY && -+ reg_request->initiator == NL80211_REGDOM_SET_BY_USER) - schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); +--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c ++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c +@@ -170,33 +170,104 @@ static bool ar9002_hw_get_isr(struct ath + return true; + } + +-static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, +- bool is_firstseg, bool is_lastseg, +- const void *ds0, dma_addr_t buf_addr, +- unsigned int qcu) ++static void ++ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) + { + struct ar5416_desc *ads = AR5416DESC(ds); ++ u32 ctl1, ctl6; + +- ads->ds_data = buf_addr; +- +- if (is_firstseg) { +- ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore); +- } else if (is_lastseg) { +- ads->ds_ctl0 = 0; +- ads->ds_ctl1 = seglen; +- ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; +- ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; +- } else { +- ads->ds_ctl0 = 0; +- ads->ds_ctl1 = seglen | AR_TxMore; +- ads->ds_ctl2 = 0; +- ads->ds_ctl3 = 0; +- } + ads->ds_txstatus0 = ads->ds_txstatus1 = 0; + ads->ds_txstatus2 = ads->ds_txstatus3 = 0; + ads->ds_txstatus4 = ads->ds_txstatus5 = 0; + ads->ds_txstatus6 = ads->ds_txstatus7 = 0; + ads->ds_txstatus8 = ads->ds_txstatus9 = 0; ++ ++ ACCESS_ONCE(ads->ds_link) = i->link; ++ ACCESS_ONCE(ads->ds_data) = i->buf_addr[0]; ++ ++ ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore); ++ ctl6 = SM(i->keytype, AR_EncrType); ++ ++ if (AR_SREV_9285(ah)) { ++ ads->ds_ctl8 = 0; ++ ads->ds_ctl9 = 0; ++ ads->ds_ctl10 = 0; ++ ads->ds_ctl11 = 0; ++ } ++ ++ if ((i->is_first || i->is_last) && ++ i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) { ++ ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0) ++ | set11nTries(i->rates, 1) ++ | set11nTries(i->rates, 2) ++ | set11nTries(i->rates, 3) ++ | (i->dur_update ? AR_DurUpdateEna : 0) ++ | SM(0, AR_BurstDur); ++ ++ ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0) ++ | set11nRate(i->rates, 1) ++ | set11nRate(i->rates, 2) ++ | set11nRate(i->rates, 3); ++ } else { ++ ACCESS_ONCE(ads->ds_ctl2) = 0; ++ ACCESS_ONCE(ads->ds_ctl3) = 0; ++ } ++ ++ if (!i->is_first) { ++ ACCESS_ONCE(ads->ds_ctl0) = 0; ++ ACCESS_ONCE(ads->ds_ctl1) = ctl1; ++ ACCESS_ONCE(ads->ds_ctl6) = ctl6; ++ return; ++ } ++ ++ ctl1 |= (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0) ++ | SM(i->type, AR_FrameType) ++ | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) ++ | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) ++ | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); ++ ++ switch (i->aggr) { ++ case AGGR_BUF_FIRST: ++ ctl6 |= SM(i->aggr_len, AR_AggrLen); ++ /* fall through */ ++ case AGGR_BUF_MIDDLE: ++ ctl1 |= AR_IsAggr | AR_MoreAggr; ++ ctl6 |= SM(i->ndelim, AR_PadDelim); ++ break; ++ case AGGR_BUF_LAST: ++ ctl1 |= AR_IsAggr; ++ break; ++ case AGGR_BUF_NONE: ++ break; ++ } ++ ++ ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen) ++ | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) ++ | SM(i->txpower, AR_XmitPower) ++ | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) ++ | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) ++ | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) ++ | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) ++ | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : ++ (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0)); ++ ++ ACCESS_ONCE(ads->ds_ctl1) = ctl1; ++ ACCESS_ONCE(ads->ds_ctl6) = ctl6; ++ ++ if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST) ++ return; ++ ++ ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0) ++ | set11nPktDurRTSCTS(i->rates, 1); ++ ++ ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2) ++ | set11nPktDurRTSCTS(i->rates, 3); ++ ++ ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0) ++ | set11nRateFlags(i->rates, 1) ++ | set11nRateFlags(i->rates, 2) ++ | set11nRateFlags(i->rates, 3) ++ | SM(i->rtscts_rate, AR_RTSCTSRate); + } + + static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, +@@ -271,145 +342,6 @@ static int ar9002_hw_proc_txdesc(struct + return 0; } +-static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, +- u32 pktLen, enum ath9k_pkt_type type, +- u32 txPower, u8 keyIx, +- enum ath9k_key_type keyType, u32 flags) +-{ +- struct ar5416_desc *ads = AR5416DESC(ds); +- +- if (txPower > 63) +- txPower = 63; +- +- ads->ds_ctl0 = (pktLen & AR_FrameLen) +- | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) +- | SM(txPower, AR_XmitPower) +- | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) +- | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) +- | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); +- +- ads->ds_ctl1 = +- (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) +- | SM(type, AR_FrameType) +- | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) +- | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) +- | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); +- +- ads->ds_ctl6 = SM(keyType, AR_EncrType); +- +- if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { +- ads->ds_ctl8 = 0; +- ads->ds_ctl9 = 0; +- ads->ds_ctl10 = 0; +- ads->ds_ctl11 = 0; +- } +-} +- +-static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) +-{ +- struct ar5416_desc *ads = AR5416DESC(ds); +- +- if (val) +- ads->ds_ctl0 |= AR_ClrDestMask; +- else +- ads->ds_ctl0 &= ~AR_ClrDestMask; +-} +- +-static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, +- void *lastds, +- u32 durUpdateEn, u32 rtsctsRate, +- u32 rtsctsDuration, +- struct ath9k_11n_rate_series series[], +- u32 nseries, u32 flags) +-{ +- struct ar5416_desc *ads = AR5416DESC(ds); +- struct ar5416_desc *last_ads = AR5416DESC(lastds); +- u32 ds_ctl0; +- +- if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { +- ds_ctl0 = ads->ds_ctl0; +- +- if (flags & ATH9K_TXDESC_RTSENA) { +- ds_ctl0 &= ~AR_CTSEnable; +- ds_ctl0 |= AR_RTSEnable; +- } else { +- ds_ctl0 &= ~AR_RTSEnable; +- ds_ctl0 |= AR_CTSEnable; +- } +- +- ads->ds_ctl0 = ds_ctl0; +- } else { +- ads->ds_ctl0 = +- (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); +- } +- +- ads->ds_ctl2 = set11nTries(series, 0) +- | set11nTries(series, 1) +- | set11nTries(series, 2) +- | set11nTries(series, 3) +- | (durUpdateEn ? AR_DurUpdateEna : 0) +- | SM(0, AR_BurstDur); +- +- ads->ds_ctl3 = set11nRate(series, 0) +- | set11nRate(series, 1) +- | set11nRate(series, 2) +- | set11nRate(series, 3); +- +- ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) +- | set11nPktDurRTSCTS(series, 1); +- +- ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) +- | set11nPktDurRTSCTS(series, 3); +- +- ads->ds_ctl7 = set11nRateFlags(series, 0) +- | set11nRateFlags(series, 1) +- | set11nRateFlags(series, 2) +- | set11nRateFlags(series, 3) +- | SM(rtsctsRate, AR_RTSCTSRate); +- last_ads->ds_ctl2 = ads->ds_ctl2; +- last_ads->ds_ctl3 = ads->ds_ctl3; +-} +- +-static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, +- u32 aggrLen) +-{ +- struct ar5416_desc *ads = AR5416DESC(ds); +- +- ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); +- ads->ds_ctl6 &= ~AR_AggrLen; +- ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); +-} +- +-static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, +- u32 numDelims) +-{ +- struct ar5416_desc *ads = AR5416DESC(ds); +- unsigned int ctl6; +- +- ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); +- +- ctl6 = ads->ds_ctl6; +- ctl6 &= ~AR_PadDelim; +- ctl6 |= SM(numDelims, AR_PadDelim); +- ads->ds_ctl6 = ctl6; +-} +- +-static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) +-{ +- struct ar5416_desc *ads = AR5416DESC(ds); +- +- ads->ds_ctl1 |= AR_IsAggr; +- ads->ds_ctl1 &= ~AR_MoreAggr; +- ads->ds_ctl6 &= ~AR_PadDelim; +-} +- +-static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds) +-{ +- struct ar5416_desc *ads = AR5416DESC(ds); +- +- ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); +-} +- + void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 size, u32 flags) + { +@@ -433,13 +365,6 @@ void ar9002_hw_attach_mac_ops(struct ath + ops->rx_enable = ar9002_hw_rx_enable; + ops->set_desc_link = ar9002_hw_set_desc_link; + ops->get_isr = ar9002_hw_get_isr; +- ops->fill_txdesc = ar9002_hw_fill_txdesc; ++ ops->set_txdesc = ar9002_set_txdesc; + ops->proc_txdesc = ar9002_hw_proc_txdesc; +- ops->set11n_txdesc = ar9002_hw_set11n_txdesc; +- ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario; +- ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first; +- ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; +- ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; +- ops->clr11n_aggr = ar9002_hw_clr11n_aggr; +- ops->set_clrdmask = ar9002_hw_set_clrdmask; + } --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c -@@ -18,13 +18,13 @@ - #include "hw-ops.h" - #include "ar9003_phy.h" - --#define MPASS 3 - #define MAX_MEASUREMENT 8 --#define MAX_DIFFERENCE 10 -+#define MAX_MAG_DELTA 11 -+#define MAX_PHS_DELTA 10 - - struct coeff { -- int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; -- int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; -+ int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; -+ int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; - int iqc_coeff[2]; - }; +@@ -652,8 +652,9 @@ static void ar9003_hw_detect_outlier(int + outlier_idx = max_idx; + else + outlier_idx = min_idx; ++ ++ mp_coeff[outlier_idx] = mp_avg; + } +- mp_coeff[outlier_idx] = mp_avg; + } + + static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, +@@ -884,6 +885,7 @@ static bool ar9003_hw_init_cal(struct at + if (txiqcal_done) + ar9003_hw_tx_iq_cal_post_proc(ah); + ++ ath9k_hw_loadnf(ah, chan); + ath9k_hw_start_nfcal(ah, true); + + /* Initialize list pointers */ +--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c +@@ -21,6 +21,132 @@ static void ar9003_hw_rx_enable(struct a + REG_WRITE(hw, AR_CR, 0); + } -@@ -608,36 +608,48 @@ static bool ar9003_hw_calc_iq_corr(struc ++static void ++ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ++{ ++ struct ar9003_txc *ads = ds; ++ int checksum = 0; ++ u32 val, ctl12, ctl17; ++ ++ val = (ATHEROS_VENDOR_ID << AR_DescId_S) | ++ (1 << AR_TxRxDesc_S) | ++ (1 << AR_CtrlStat_S) | ++ (i->qcu << AR_TxQcuNum_S) | 0x17; ++ ++ checksum += val; ++ ACCESS_ONCE(ads->info) = val; ++ ++ checksum += i->link; ++ ACCESS_ONCE(ads->link) = i->link; ++ ++ checksum += i->buf_addr[0]; ++ ACCESS_ONCE(ads->data0) = i->buf_addr[0]; ++ checksum += i->buf_addr[1]; ++ ACCESS_ONCE(ads->data1) = i->buf_addr[1]; ++ checksum += i->buf_addr[2]; ++ ACCESS_ONCE(ads->data2) = i->buf_addr[2]; ++ checksum += i->buf_addr[3]; ++ ACCESS_ONCE(ads->data3) = i->buf_addr[3]; ++ ++ checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen); ++ ACCESS_ONCE(ads->ctl3) = val; ++ checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen); ++ ACCESS_ONCE(ads->ctl5) = val; ++ checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen); ++ ACCESS_ONCE(ads->ctl7) = val; ++ checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen); ++ ACCESS_ONCE(ads->ctl9) = val; ++ ++ checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff); ++ ACCESS_ONCE(ads->ctl10) = checksum; ++ ++ if (i->is_first || i->is_last) { ++ ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0) ++ | set11nTries(i->rates, 1) ++ | set11nTries(i->rates, 2) ++ | set11nTries(i->rates, 3) ++ | (i->dur_update ? AR_DurUpdateEna : 0) ++ | SM(0, AR_BurstDur); ++ ++ ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0) ++ | set11nRate(i->rates, 1) ++ | set11nRate(i->rates, 2) ++ | set11nRate(i->rates, 3); ++ } else { ++ ACCESS_ONCE(ads->ctl13) = 0; ++ ACCESS_ONCE(ads->ctl14) = 0; ++ } ++ ++ ads->ctl20 = 0; ++ ads->ctl21 = 0; ++ ads->ctl22 = 0; ++ ++ ctl17 = SM(i->keytype, AR_EncrType); ++ if (!i->is_first) { ++ ACCESS_ONCE(ads->ctl11) = 0; ++ ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore; ++ ACCESS_ONCE(ads->ctl15) = 0; ++ ACCESS_ONCE(ads->ctl16) = 0; ++ ACCESS_ONCE(ads->ctl17) = ctl17; ++ ACCESS_ONCE(ads->ctl18) = 0; ++ ACCESS_ONCE(ads->ctl19) = 0; ++ return; ++ } ++ ++ ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen) ++ | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) ++ | SM(i->txpower, AR_XmitPower) ++ | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) ++ | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) ++ | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0) ++ | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) ++ | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : ++ (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0)); ++ ++ ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ? ++ SM(i->keyix, AR_DestIdx) : 0) ++ | SM(i->type, AR_FrameType) ++ | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) ++ | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) ++ | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); ++ ++ ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0); ++ switch (i->aggr) { ++ case AGGR_BUF_FIRST: ++ ctl17 |= SM(i->aggr_len, AR_AggrLen); ++ /* fall through */ ++ case AGGR_BUF_MIDDLE: ++ ctl12 |= AR_IsAggr | AR_MoreAggr; ++ ctl17 |= SM(i->ndelim, AR_PadDelim); ++ break; ++ case AGGR_BUF_LAST: ++ ctl12 |= AR_IsAggr; ++ break; ++ case AGGR_BUF_NONE: ++ break; ++ } ++ ++ val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S; ++ ctl12 |= SM(val, AR_PAPRDChainMask); ++ ++ ACCESS_ONCE(ads->ctl12) = ctl12; ++ ACCESS_ONCE(ads->ctl17) = ctl17; ++ ++ ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0) ++ | set11nPktDurRTSCTS(i->rates, 1); ++ ++ ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2) ++ | set11nPktDurRTSCTS(i->rates, 3); ++ ++ ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0) ++ | set11nRateFlags(i->rates, 1) ++ | set11nRateFlags(i->rates, 2) ++ | set11nRateFlags(i->rates, 3) ++ | SM(i->rtscts_rate, AR_RTSCTSRate); ++ ++ ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding; ++} ++ + static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) + { + int checksum; +@@ -185,47 +311,6 @@ static bool ar9003_hw_get_isr(struct ath return true; } --static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg) -+static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, -+ int max_delta) - { -- int diff[MPASS]; +-static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, +- bool is_firstseg, bool is_lastseg, +- const void *ds0, dma_addr_t buf_addr, +- unsigned int qcu) +-{ +- struct ar9003_txc *ads = (struct ar9003_txc *) ds; +- unsigned int descid = 0; +- +- ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) | +- (1 << AR_TxRxDesc_S) | +- (1 << AR_CtrlStat_S) | +- (qcu << AR_TxQcuNum_S) | 0x17; +- +- ads->data0 = buf_addr; +- ads->data1 = 0; +- ads->data2 = 0; +- ads->data3 = 0; +- +- ads->ctl3 = (seglen << AR_BufLen_S); +- ads->ctl3 &= AR_BufLen; +- +- /* Fill in pointer checksum and descriptor id */ +- ads->ctl10 = ar9003_calc_ptr_chksum(ads); +- ads->ctl10 |= (descid << AR_TxDescId_S); +- +- if (is_firstseg) { +- ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore); +- } else if (is_lastseg) { +- ads->ctl11 = 0; +- ads->ctl12 = 0; +- ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13; +- ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14; +- } else { +- /* XXX Intermediate descriptor in a multi-descriptor frame.*/ +- ads->ctl11 = 0; +- ads->ctl12 = AR_TxMore; +- ads->ctl13 = 0; +- ads->ctl14 = 0; +- } +-} +- + static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, + struct ath_tx_status *ts) + { +@@ -310,161 +395,6 @@ static int ar9003_hw_proc_txdesc(struct + return 0; + } + +-static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, +- u32 pktlen, enum ath9k_pkt_type type, u32 txpower, +- u8 keyIx, enum ath9k_key_type keyType, u32 flags) +-{ +- struct ar9003_txc *ads = (struct ar9003_txc *) ds; +- +- if (txpower > ah->txpower_limit) +- txpower = ah->txpower_limit; +- +- if (txpower > 63) +- txpower = 63; +- +- ads->ctl11 = (pktlen & AR_FrameLen) +- | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) +- | SM(txpower, AR_XmitPower) +- | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) +- | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) +- | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); +- +- ads->ctl12 = +- (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) +- | SM(type, AR_FrameType) +- | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) +- | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) +- | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); +- +- ads->ctl17 = SM(keyType, AR_EncrType) | +- (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0); +- ads->ctl18 = 0; +- ads->ctl19 = AR_Not_Sounding; +- +- ads->ctl20 = 0; +- ads->ctl21 = 0; +- ads->ctl22 = 0; +-} +- +-static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) +-{ +- struct ar9003_txc *ads = (struct ar9003_txc *) ds; +- +- if (val) +- ads->ctl11 |= AR_ClrDestMask; +- else +- ads->ctl11 &= ~AR_ClrDestMask; +-} +- +-static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, +- void *lastds, +- u32 durUpdateEn, u32 rtsctsRate, +- u32 rtsctsDuration, +- struct ath9k_11n_rate_series series[], +- u32 nseries, u32 flags) +-{ +- struct ar9003_txc *ads = (struct ar9003_txc *) ds; +- struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds; +- u_int32_t ctl11; +- +- if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { +- ctl11 = ads->ctl11; +- +- if (flags & ATH9K_TXDESC_RTSENA) { +- ctl11 &= ~AR_CTSEnable; +- ctl11 |= AR_RTSEnable; +- } else { +- ctl11 &= ~AR_RTSEnable; +- ctl11 |= AR_CTSEnable; +- } +- +- ads->ctl11 = ctl11; +- } else { +- ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable)); +- } +- +- ads->ctl13 = set11nTries(series, 0) +- | set11nTries(series, 1) +- | set11nTries(series, 2) +- | set11nTries(series, 3) +- | (durUpdateEn ? AR_DurUpdateEna : 0) +- | SM(0, AR_BurstDur); +- +- ads->ctl14 = set11nRate(series, 0) +- | set11nRate(series, 1) +- | set11nRate(series, 2) +- | set11nRate(series, 3); +- +- ads->ctl15 = set11nPktDurRTSCTS(series, 0) +- | set11nPktDurRTSCTS(series, 1); +- +- ads->ctl16 = set11nPktDurRTSCTS(series, 2) +- | set11nPktDurRTSCTS(series, 3); +- +- ads->ctl18 = set11nRateFlags(series, 0) +- | set11nRateFlags(series, 1) +- | set11nRateFlags(series, 2) +- | set11nRateFlags(series, 3) +- | SM(rtsctsRate, AR_RTSCTSRate); +- ads->ctl19 = AR_Not_Sounding; +- +- last_ads->ctl13 = ads->ctl13; +- last_ads->ctl14 = ads->ctl14; +-} +- +-static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, +- u32 aggrLen) +-{ +- struct ar9003_txc *ads = (struct ar9003_txc *) ds; +- +- ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); +- +- ads->ctl17 &= ~AR_AggrLen; +- ads->ctl17 |= SM(aggrLen, AR_AggrLen); +-} +- +-static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, +- u32 numDelims) +-{ +- struct ar9003_txc *ads = (struct ar9003_txc *) ds; +- unsigned int ctl17; +- +- ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); +- +- /* +- * We use a stack variable to manipulate ctl6 to reduce uncached +- * read modify, modfiy, write. +- */ +- ctl17 = ads->ctl17; +- ctl17 &= ~AR_PadDelim; +- ctl17 |= SM(numDelims, AR_PadDelim); +- ads->ctl17 = ctl17; +-} +- +-static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) +-{ +- struct ar9003_txc *ads = (struct ar9003_txc *) ds; +- +- ads->ctl12 |= AR_IsAggr; +- ads->ctl12 &= ~AR_MoreAggr; +- ads->ctl17 &= ~AR_PadDelim; +-} +- +-static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds) +-{ +- struct ar9003_txc *ads = (struct ar9003_txc *) ds; +- +- ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr); +-} +- +-void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) +-{ +- struct ar9003_txc *ads = ds; +- +- ads->ctl12 |= SM(chains, AR_PAPRDChainMask); +-} +-EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc); +- + void ar9003_hw_attach_mac_ops(struct ath_hw *hw) + { + struct ath_hw_ops *ops = ath9k_hw_ops(hw); +@@ -472,15 +402,8 @@ void ar9003_hw_attach_mac_ops(struct ath + ops->rx_enable = ar9003_hw_rx_enable; + ops->set_desc_link = ar9003_hw_set_desc_link; + ops->get_isr = ar9003_hw_get_isr; +- ops->fill_txdesc = ar9003_hw_fill_txdesc; ++ ops->set_txdesc = ar9003_set_txdesc; + ops->proc_txdesc = ar9003_hw_proc_txdesc; +- ops->set11n_txdesc = ar9003_hw_set11n_txdesc; +- ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario; +- ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first; +- ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; +- ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; +- ops->clr11n_aggr = ar9003_hw_clr11n_aggr; +- ops->set_clrdmask = ar9003_hw_set_clrdmask; + } + + void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -87,17 +87,14 @@ struct ath_config { + * @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_XRETRY: To denote excessive retries of the buffer + */ + enum buffer_type { + BUF_AMPDU = BIT(0), + BUF_AGGR = BIT(1), +- BUF_XRETRY = BIT(2), + }; + + #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) + #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) +-#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) + + #define ATH_TXSTATUS_RING_SIZE 64 + +@@ -216,6 +213,7 @@ struct ath_frame_info { + struct ath_buf_state { + u8 bf_type; + u8 bfs_paprd; ++ u8 ndelim; + u16 seqno; + unsigned long bfs_paprd_timestamp; + }; +@@ -230,7 +228,6 @@ 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; +- u16 bf_flags; + struct ath_buf_state bf_state; + }; + +@@ -277,8 +274,7 @@ struct ath_tx_control { + }; + + #define ATH_TX_ERROR 0x01 +-#define ATH_TX_XRETRY 0x02 +-#define ATH_TX_BAR 0x04 ++#define ATH_TX_BAR 0x02 + + /** + * @txq_map: Index is mac80211 queue number. This is +--- a/drivers/net/wireless/ath/ath9k/beacon.c ++++ b/drivers/net/wireless/ath/ath9k/beacon.c +@@ -73,44 +73,39 @@ static void ath_beacon_setup(struct ath_ + struct sk_buff *skb = bf->bf_mpdu; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); +- struct ath_desc *ds; +- struct ath9k_11n_rate_series series[4]; +- int flags, ctsrate = 0, ctsduration = 0; ++ struct ath_tx_info info; + struct ieee80211_supported_band *sband; ++ u8 chainmask = ah->txchainmask; + u8 rate = 0; + + ath9k_reset_beacon_status(sc); + +- ds = bf->bf_desc; +- flags = ATH9K_TXDESC_NOACK; +- +- ds->ds_link = 0; +- + sband = &sc->sbands[common->hw->conf.channel->band]; + rate = sband->bitrates[rateidx].hw_value; + if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) + rate |= sband->bitrates[rateidx].hw_value_short; + +- ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, +- ATH9K_PKT_TYPE_BEACON, +- MAX_RATE_POWER, +- ATH9K_TXKEYIX_INVALID, +- ATH9K_KEY_TYPE_CLEAR, +- flags); +- +- /* NB: beacon's BufLen must be a multiple of 4 bytes */ +- ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), +- true, true, ds, bf->bf_buf_addr, +- sc->beacon.beaconq); +- +- memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); +- series[0].Tries = 1; +- series[0].Rate = rate; +- series[0].ChSel = ath_txchainmask_reduction(sc, +- ah->txchainmask, series[0].Rate); +- series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; +- ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, +- series, 4, 0); ++ memset(&info, 0, sizeof(info)); ++ info.pkt_len = skb->len + FCS_LEN; ++ info.type = ATH9K_PKT_TYPE_BEACON; ++ info.txpower = MAX_RATE_POWER; ++ info.keyix = ATH9K_TXKEYIX_INVALID; ++ info.keytype = ATH9K_KEY_TYPE_CLEAR; ++ info.flags = ATH9K_TXDESC_NOACK; ++ ++ info.buf_addr[0] = bf->bf_buf_addr; ++ info.buf_len[0] = roundup(skb->len, 4); ++ ++ info.is_first = true; ++ info.is_last = true; ++ ++ info.qcu = sc->beacon.beaconq; ++ ++ info.rates[0].Tries = 1; ++ info.rates[0].Rate = rate; ++ info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate); ++ ++ ath9k_hw_set_txdesc(ah, bf->bf_desc, &info); + } + + static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) +@@ -517,6 +512,7 @@ static void ath_beacon_config_ap(struct + /* Set the computed AP beacon timers */ + + ath9k_hw_disable_interrupts(ah); ++ sc->sc_flags |= SC_OP_TSF_RESET; + ath9k_beacon_init(sc, nexttbtt, intval); + sc->beacon.bmisscnt = 0; + ath9k_hw_set_interrupts(ah, ah->imask); +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -826,7 +826,8 @@ static ssize_t read_file_misc(struct fil + } + + void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, +- struct ath_tx_status *ts, struct ath_txq *txq) ++ struct ath_tx_status *ts, struct ath_txq *txq, ++ unsigned int flags) + { + #define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\ + [sc->debug.tsidx].c) +@@ -836,12 +837,12 @@ void ath_debug_stat_tx(struct ath_softc + sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; + + if (bf_isampdu(bf)) { +- if (bf_isxretried(bf)) ++ if (flags & ATH_TX_BAR) + TX_STAT_INC(qnum, a_xretries); + else + TX_STAT_INC(qnum, a_completed); + } else { +- if (bf_isxretried(bf)) ++ if (ts->ts_status & ATH9K_TXERR_XRETRY) + TX_STAT_INC(qnum, xretries); + else + TX_STAT_INC(qnum, completed); +--- a/drivers/net/wireless/ath/ath9k/debug.h ++++ b/drivers/net/wireless/ath/ath9k/debug.h +@@ -230,7 +230,8 @@ int ath9k_init_debug(struct ath_hw *ah); + void ath9k_debug_samp_bb_mac(struct ath_softc *sc); + void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); + void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, +- struct ath_tx_status *ts, struct ath_txq *txq); ++ struct ath_tx_status *ts, struct ath_txq *txq, ++ unsigned int flags); + void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); + + #else +@@ -252,7 +253,8 @@ static inline void ath_debug_stat_interr + static inline void ath_debug_stat_tx(struct ath_softc *sc, + struct ath_buf *bf, + struct ath_tx_status *ts, +- struct ath_txq *txq) ++ struct ath_txq *txq, ++ unsigned int flags) + { + } + +--- a/drivers/net/wireless/ath/ath9k/hw-ops.h ++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h +@@ -54,13 +54,10 @@ static inline bool ath9k_hw_getisr(struc + return ath9k_hw_ops(ah)->get_isr(ah, masked); + } + +-static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen, +- bool is_firstseg, bool is_lastseg, +- const void *ds0, dma_addr_t buf_addr, +- unsigned int qcu) ++static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds, ++ struct ath_tx_info *i) + { +- ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg, +- ds0, buf_addr, qcu); ++ return ath9k_hw_ops(ah)->set_txdesc(ah, ds, i); + } + + static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds, +@@ -69,55 +66,6 @@ static inline int ath9k_hw_txprocdesc(st + return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts); + } + +-static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds, +- u32 pktLen, enum ath9k_pkt_type type, +- u32 txPower, u32 keyIx, +- enum ath9k_key_type keyType, +- u32 flags) +-{ +- ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx, +- keyType, flags); +-} +- +-static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, +- void *lastds, +- u32 durUpdateEn, u32 rtsctsRate, +- u32 rtsctsDuration, +- struct ath9k_11n_rate_series series[], +- u32 nseries, u32 flags) +-{ +- ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn, +- rtsctsRate, rtsctsDuration, series, +- nseries, flags); +-} +- +-static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, +- u32 aggrLen) +-{ +- ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen); +-} +- +-static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, +- u32 numDelims) +-{ +- ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims); +-} +- +-static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) +-{ +- ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds); +-} +- +-static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds) +-{ +- ath9k_hw_ops(ah)->clr11n_aggr(ah, ds); +-} +- +-static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) +-{ +- ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); +-} +- + static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf) + { +@@ -233,11 +181,6 @@ static inline void ath9k_hw_restore_chai + return ath9k_hw_private_ops(ah)->restore_chainmask(ah); + } + +-static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value) +-{ +- return ath9k_hw_private_ops(ah)->set_diversity(ah, value); +-} +- + static inline bool ath9k_hw_ani_control(struct ath_hw *ah, + enum ath9k_ani_cmd cmd, int param) + { +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1496,14 +1496,16 @@ int ath9k_hw_reset(struct ath_hw *ah, st + } + ah->noise = ath9k_hw_getchan_noise(ah, chan); + ++ if ((AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) || ++ (AR_SREV_9300_20_OR_LATER(ah) && IS_CHAN_5GHZ(chan))) ++ bChannelChange = false; ++ + if (bChannelChange && + (ah->chip_fullsleep != true) && + (ah->curchan != NULL) && + (chan->channel != ah->curchan->channel) && + ((chan->channelFlags & CHANNEL_ALL) == +- (ah->curchan->channelFlags & CHANNEL_ALL)) && +- (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) { +- ++ (ah->curchan->channelFlags & CHANNEL_ALL))) { + if (ath9k_hw_channel_change(ah, chan)) { + ath9k_hw_loadnf(ah, ah->curchan); + ath9k_hw_start_nfcal(ah, true); +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -583,7 +583,6 @@ struct ath_hw_private_ops { + bool (*rfbus_req)(struct ath_hw *ah); + void (*rfbus_done)(struct ath_hw *ah); + void (*restore_chainmask)(struct ath_hw *ah); +- void (*set_diversity)(struct ath_hw *ah, bool value); + u32 (*compute_pll_control)(struct ath_hw *ah, + struct ath9k_channel *chan); + bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, +@@ -615,30 +614,10 @@ struct ath_hw_ops { + u8 rxchainmask, + bool longcal); + bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked); +- void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen, +- bool is_firstseg, bool is_is_lastseg, +- const void *ds0, dma_addr_t buf_addr, +- unsigned int qcu); ++ void (*set_txdesc)(struct ath_hw *ah, void *ds, ++ struct ath_tx_info *i); + int (*proc_txdesc)(struct ath_hw *ah, void *ds, + struct ath_tx_status *ts); +- void (*set11n_txdesc)(struct ath_hw *ah, void *ds, +- u32 pktLen, enum ath9k_pkt_type type, +- u32 txPower, u8 keyIx, +- enum ath9k_key_type keyType, +- u32 flags); +- void (*set11n_ratescenario)(struct ath_hw *ah, void *ds, +- void *lastds, +- u32 durUpdateEn, u32 rtsctsRate, +- u32 rtsctsDuration, +- struct ath9k_11n_rate_series series[], +- u32 nseries, u32 flags); +- void (*set11n_aggr_first)(struct ath_hw *ah, void *ds, +- u32 aggrLen); +- void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds, +- u32 numDelims); +- void (*set11n_aggr_last)(struct ath_hw *ah, void *ds); +- void (*clr11n_aggr)(struct ath_hw *ah, void *ds); +- void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); + void (*antdiv_comb_conf_get)(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf); + void (*antdiv_comb_conf_set)(struct ath_hw *ah, +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -62,18 +62,6 @@ void ath9k_hw_txstart(struct ath_hw *ah, + } + EXPORT_SYMBOL(ath9k_hw_txstart); + +-void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds) +-{ +- struct ar5416_desc *ads = AR5416DESC(ds); +- +- ads->ds_txstatus0 = ads->ds_txstatus1 = 0; +- ads->ds_txstatus2 = ads->ds_txstatus3 = 0; +- ads->ds_txstatus4 = ads->ds_txstatus5 = 0; +- ads->ds_txstatus6 = ads->ds_txstatus7 = 0; +- ads->ds_txstatus8 = ads->ds_txstatus9 = 0; +-} +-EXPORT_SYMBOL(ath9k_hw_cleartxdesc); +- + u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) + { + u32 npend; +@@ -596,7 +584,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a + else + rs->rs_keyix = ATH9K_RXKEYIX_INVALID; + +- rs->rs_rate = RXSTATUS_RATE(ah, (&ads)); ++ rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate); + rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; + + rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; +--- a/drivers/net/wireless/ath/ath9k/mac.h ++++ b/drivers/net/wireless/ath/ath9k/mac.h +@@ -17,10 +17,6 @@ + #ifndef MAC_H + #define MAC_H + +-#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \ +- MS(ads->ds_rxstatus0, AR_RxRate) : \ +- (ads->ds_rxstatus3 >> 2) & 0xFF) +- + #define set11nTries(_series, _index) \ + (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) + +@@ -263,7 +259,11 @@ struct ath_desc { + #define ATH9K_TXDESC_VMF 0x0100 + #define ATH9K_TXDESC_FRAG_IS_ON 0x0200 + #define ATH9K_TXDESC_LOWRXCHAIN 0x0400 +-#define ATH9K_TXDESC_LDPC 0x00010000 ++#define ATH9K_TXDESC_LDPC 0x0800 ++#define ATH9K_TXDESC_CLRDMASK 0x1000 ++ ++#define ATH9K_TXDESC_PAPRD 0x70000 ++#define ATH9K_TXDESC_PAPRD_S 16 + + #define ATH9K_RXDESC_INTREQ 0x0020 + +@@ -659,6 +659,13 @@ struct ath9k_11n_rate_series { + u32 RateFlags; + }; + ++enum aggr_type { ++ AGGR_BUF_NONE, ++ AGGR_BUF_FIRST, ++ AGGR_BUF_MIDDLE, ++ AGGR_BUF_LAST, ++}; ++ + enum ath9k_key_type { + ATH9K_KEY_TYPE_CLEAR, + ATH9K_KEY_TYPE_WEP, +@@ -666,6 +673,33 @@ enum ath9k_key_type { + ATH9K_KEY_TYPE_TKIP, + }; + ++struct ath_tx_info { ++ u8 qcu; ++ ++ bool is_first; ++ bool is_last; ++ ++ enum aggr_type aggr; ++ u8 ndelim; ++ u16 aggr_len; ++ ++ dma_addr_t link; ++ int pkt_len; ++ u32 flags; ++ ++ dma_addr_t buf_addr[4]; ++ int buf_len[4]; ++ ++ struct ath9k_11n_rate_series rates[4]; ++ u8 rtscts_rate; ++ bool dur_update; ++ ++ enum ath9k_pkt_type type; ++ enum ath9k_key_type keytype; ++ u8 keyix; ++ u8 txpower; ++}; ++ + struct ath_hw; + struct ath9k_channel; + enum ath9k_int; +@@ -673,7 +707,6 @@ enum ath9k_int; + u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); + void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); + void ath9k_hw_txstart(struct ath_hw *ah, u32 q); +-void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds); + u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); + bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); + bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q); +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -111,24 +111,29 @@ void ath9k_ps_wakeup(struct ath_softc *s + void ath9k_ps_restore(struct ath_softc *sc) + { + struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++ enum ath9k_power_mode mode; + unsigned long flags; + + spin_lock_irqsave(&sc->sc_pm_lock, flags); + if (--sc->ps_usecount != 0) + goto unlock; + +- spin_lock(&common->cc_lock); +- ath_hw_cycle_counters_update(common); +- spin_unlock(&common->cc_lock); +- + if (sc->ps_idle) +- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); ++ mode = ATH9K_PM_FULL_SLEEP; + else if (sc->ps_enabled && + !(sc->ps_flags & (PS_WAIT_FOR_BEACON | + PS_WAIT_FOR_CAB | + PS_WAIT_FOR_PSPOLL_DATA | + PS_WAIT_FOR_TX_ACK))) +- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); ++ mode = ATH9K_PM_NETWORK_SLEEP; ++ else ++ goto unlock; ++ ++ spin_lock(&common->cc_lock); ++ ath_hw_cycle_counters_update(common); ++ spin_unlock(&common->cc_lock); ++ ++ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); + + unlock: + spin_unlock_irqrestore(&sc->sc_pm_lock, flags); +@@ -247,8 +252,8 @@ static bool ath_prepare_reset(struct ath + + if (!flush) { + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) +- ath_rx_tasklet(sc, 0, true); +- ath_rx_tasklet(sc, 0, false); ++ ath_rx_tasklet(sc, 1, true); ++ ath_rx_tasklet(sc, 1, false); + } else { + ath_flushrecv(sc); + } +@@ -669,15 +674,15 @@ void ath9k_tasklet(unsigned long data) + u32 status = sc->intrstatus; + u32 rxmask; + ++ ath9k_ps_wakeup(sc); ++ spin_lock(&sc->sc_pcu_lock); ++ + if ((status & ATH9K_INT_FATAL) || + (status & ATH9K_INT_BB_WATCHDOG)) { + ieee80211_queue_work(sc->hw, &sc->hw_reset_work); +- return; ++ goto out; + } + +- ath9k_ps_wakeup(sc); +- spin_lock(&sc->sc_pcu_lock); +- + /* + * 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 +@@ -725,6 +730,7 @@ void ath9k_tasklet(unsigned long data) + if (status & ATH9K_INT_GENTIMER) + ath_gen_timer_isr(sc->sc_ah); + ++out: + /* re-enable hardware interrupt */ + ath9k_hw_enable_interrupts(ah); + +@@ -2015,6 +2021,7 @@ static void ath9k_config_bss(struct ath_ + /* Stop ANI */ + sc->sc_flags &= ~SC_OP_ANI_RUN; + del_timer_sync(&common->ani.timer); ++ memset(&sc->caldata, 0, sizeof(sc->caldata)); + } + } + +--- a/drivers/net/wireless/ath/ath9k/pci.c ++++ b/drivers/net/wireless/ath/ath9k/pci.c +@@ -332,16 +332,16 @@ static int ath_pci_resume(struct device + if ((val & 0x0000ff00) != 0) + pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); + ++ ath9k_ps_wakeup(sc); + /* Enable LED */ + ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); +- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); ++ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); + + /* + * Reset key cache to sane defaults (all entries cleared) instead of + * semi-random values after suspend/resume. + */ +- ath9k_ps_wakeup(sc); + ath9k_cmn_init_crypto(sc->sc_ah); + ath9k_ps_restore(sc); + +--- a/drivers/net/wireless/ath/ath9k/recv.c ++++ b/drivers/net/wireless/ath/ath9k/recv.c +@@ -1839,7 +1839,7 @@ int ath_rx_tasklet(struct ath_softc *sc, + * If we're asked to flush receive queue, directly + * chain it back at the queue without processing it. + */ +- if (flush) ++ if (sc->sc_flags & SC_OP_RXFLUSH) + goto requeue_drop_frag; + + retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, +@@ -1967,7 +1967,8 @@ requeue: + } else { + list_move_tail(&bf->list, &sc->rx.rxbuf); + ath_rx_buf_link(sc, bf); +- ath9k_hw_rxena(ah); ++ if (!flush) ++ ath9k_hw_rxena(ah); + } + } while (1); + +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -56,10 +56,9 @@ static void ath_tx_complete_buf(struct a + struct ath_tx_status *ts, int txok, int sendbar); + static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, + struct list_head *head, bool internal); +-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len); + 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); ++ int txok); + static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, + int seqno); + static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, +@@ -263,6 +262,7 @@ static void ath_tx_set_retry(struct ath_ + struct sk_buff *skb) + { + struct ath_frame_info *fi = get_frame_info(skb); ++ struct ath_buf *bf = fi->bf; + struct ieee80211_hdr *hdr; + + TX_STAT_INC(txq->axq_qnum, a_retries); +@@ -271,6 +271,8 @@ static void ath_tx_set_retry(struct ath_ + + hdr = (struct ieee80211_hdr *)skb->data; + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); ++ dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, ++ sizeof(*hdr), DMA_TO_DEVICE); + } + + static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) +@@ -390,11 +392,9 @@ static void ath_tx_complete_aggr(struct + while (bf) { + bf_next = bf->bf_next; + +- bf->bf_state.bf_type |= BUF_XRETRY; + if (!bf->bf_stale || bf_next != NULL) + list_move_tail(&bf->list, &bf_head); + +- ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false); + ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, + 0, 0); + +@@ -470,7 +470,6 @@ static void ath_tx_complete_aggr(struct + clear_filter = true; + txpending = 1; + } else { +- bf->bf_state.bf_type |= BUF_XRETRY; + txfail = 1; + sendbar = 1; + txfail_cnt++; +@@ -497,17 +496,14 @@ static void ath_tx_complete_aggr(struct + + if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { + memcpy(tx_info->control.rates, rates, sizeof(rates)); +- ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true); ++ ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok); + rc_update = false; +- } else { +- ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false); + } + + ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, + !txfail, sendbar); + } else { + /* retry the un-acked ones */ +- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false); + if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { + if (bf->bf_next == NULL && bf_last->bf_stale) { + struct ath_buf *tbf; +@@ -523,26 +519,13 @@ static void ath_tx_complete_aggr(struct + ath_tx_update_baw(sc, tid, seqno); + spin_unlock_bh(&txq->axq_lock); + +- bf->bf_state.bf_type |= +- BUF_XRETRY; +- ath_tx_rc_status(sc, bf, ts, nframes, +- nbad, 0, false); + ath_tx_complete_buf(sc, bf, txq, + &bf_head, +- ts, 0, 0); ++ ts, 0, 1); + break; + } + +- ath9k_hw_cleartxdesc(sc->sc_ah, +- tbf->bf_desc); + fi->bf = tbf; +- } else { +- /* +- * Clear descriptor status words for +- * software retry +- */ +- ath9k_hw_cleartxdesc(sc->sc_ah, +- bf->bf_desc); + } + } + +@@ -778,7 +761,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_ + if (!bf) + continue; + +- bf->bf_state.bf_type |= BUF_AMPDU; ++ bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; + seqno = bf->bf_state.seqno; + if (!bf_first) + bf_first = bf; +@@ -805,8 +788,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_ + } + + tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); +- if (nframes && ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) || +- !(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS))) ++ if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) + break; + + /* do not exceed subframe limit */ +@@ -828,20 +810,17 @@ static enum ATH_AGGR_STATUS ath_tx_form_ + + nframes++; + bf->bf_next = NULL; +- ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0); + + /* link buffers of this frame to the aggregate */ + if (!fi->retries) + ath_tx_addto_baw(sc, tid, seqno); +- ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); ++ bf->bf_state.ndelim = ndelim; + + __skb_unlink(skb, &tid->buf_q); + list_add_tail(&bf->list, bf_q); +- if (bf_prev) { ++ if (bf_prev) + bf_prev->bf_next = bf; +- ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc, +- bf->bf_daddr); +- } ++ + bf_prev = bf; + + } while (!skb_queue_empty(&tid->buf_q)); +@@ -852,12 +831,245 @@ static enum ATH_AGGR_STATUS ath_tx_form_ + #undef PADBYTES + } + ++/* ++ * rix - rate index ++ * pktlen - total bytes (delims + data + fcs + pads + pad delims) ++ * width - 0 for 20 MHz, 1 for 40 MHz ++ * half_gi - to use 4us v/s 3.6 us for symbol time ++ */ ++static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, ++ int width, int half_gi, bool shortPreamble) ++{ ++ u32 nbits, nsymbits, duration, nsymbols; ++ int streams; ++ ++ /* find number of symbols: PLCP + data */ ++ streams = HT_RC_2_STREAMS(rix); ++ nbits = (pktlen << 3) + OFDM_PLCP_BITS; ++ nsymbits = bits_per_symbol[rix % 8][width] * streams; ++ nsymbols = (nbits + nsymbits - 1) / nsymbits; ++ ++ if (!half_gi) ++ duration = SYMBOL_TIME(nsymbols); ++ else ++ duration = SYMBOL_TIME_HALFGI(nsymbols); ++ ++ /* addup duration for legacy/ht training and signal fields */ ++ duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); ++ ++ return duration; ++} ++ ++static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, ++ struct ath_tx_info *info, int len) ++{ ++ struct ath_hw *ah = sc->sc_ah; ++ struct sk_buff *skb; ++ struct ieee80211_tx_info *tx_info; ++ struct ieee80211_tx_rate *rates; ++ const struct ieee80211_rate *rate; ++ struct ieee80211_hdr *hdr; ++ int i; ++ u8 rix = 0; ++ ++ skb = bf->bf_mpdu; ++ tx_info = IEEE80211_SKB_CB(skb); ++ rates = tx_info->control.rates; ++ hdr = (struct ieee80211_hdr *)skb->data; ++ ++ /* set dur_update_en for l-sig computation except for PS-Poll frames */ ++ info->dur_update = !ieee80211_is_pspoll(hdr->frame_control); ++ ++ /* ++ * We check if Short Preamble is needed for the CTS rate by ++ * checking the BSS's global flag. ++ * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. ++ */ ++ rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info); ++ info->rtscts_rate = rate->hw_value; ++ if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ++ info->rtscts_rate |= rate->hw_value_short; ++ ++ for (i = 0; i < 4; i++) { ++ bool is_40, is_sgi, is_sp; ++ int phy; ++ ++ if (!rates[i].count || (rates[i].idx < 0)) ++ continue; ++ ++ rix = rates[i].idx; ++ info->rates[i].Tries = rates[i].count; ++ ++ if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) { ++ info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; ++ info->flags |= ATH9K_TXDESC_RTSENA; ++ } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { ++ info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; ++ info->flags |= ATH9K_TXDESC_CTSENA; ++ } ++ ++ if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ++ info->rates[i].RateFlags |= ATH9K_RATESERIES_2040; ++ if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) ++ info->rates[i].RateFlags |= ATH9K_RATESERIES_HALFGI; ++ ++ is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI); ++ is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH); ++ is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE); ++ ++ if (rates[i].flags & IEEE80211_TX_RC_MCS) { ++ /* MCS rates */ ++ info->rates[i].Rate = rix | 0x80; ++ info->rates[i].ChSel = ath_txchainmask_reduction(sc, ++ ah->txchainmask, info->rates[i].Rate); ++ info->rates[i].PktDuration = ath_pkt_duration(sc, rix, len, ++ is_40, is_sgi, is_sp); ++ if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) ++ info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC; ++ continue; ++ } ++ ++ /* legacy rates */ ++ if ((tx_info->band == IEEE80211_BAND_2GHZ) && ++ !(rate->flags & IEEE80211_RATE_ERP_G)) ++ phy = WLAN_RC_PHY_CCK; ++ else ++ phy = WLAN_RC_PHY_OFDM; ++ ++ rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx]; ++ info->rates[i].Rate = rate->hw_value; ++ if (rate->hw_value_short) { ++ if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ++ info->rates[i].Rate |= rate->hw_value_short; ++ } else { ++ is_sp = false; ++ } ++ ++ if (bf->bf_state.bfs_paprd) ++ info->rates[i].ChSel = ah->txchainmask; ++ else ++ info->rates[i].ChSel = ath_txchainmask_reduction(sc, ++ ah->txchainmask, info->rates[i].Rate); ++ ++ info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, ++ phy, rate->bitrate * 100, len, rix, is_sp); ++ } ++ ++ /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ ++ if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit)) ++ info->flags &= ~ATH9K_TXDESC_RTSENA; ++ ++ /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */ ++ if (info->flags & ATH9K_TXDESC_RTSENA) ++ info->flags &= ~ATH9K_TXDESC_CTSENA; ++} ++ ++static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) ++{ ++ struct ieee80211_hdr *hdr; ++ enum ath9k_pkt_type htype; ++ __le16 fc; ++ ++ hdr = (struct ieee80211_hdr *)skb->data; ++ fc = hdr->frame_control; ++ ++ if (ieee80211_is_beacon(fc)) ++ htype = ATH9K_PKT_TYPE_BEACON; ++ else if (ieee80211_is_probe_resp(fc)) ++ htype = ATH9K_PKT_TYPE_PROBE_RESP; ++ else if (ieee80211_is_atim(fc)) ++ htype = ATH9K_PKT_TYPE_ATIM; ++ else if (ieee80211_is_pspoll(fc)) ++ htype = ATH9K_PKT_TYPE_PSPOLL; ++ else ++ htype = ATH9K_PKT_TYPE_NORMAL; ++ ++ return htype; ++} ++ ++static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, ++ struct ath_txq *txq, int len) ++{ ++ struct ath_hw *ah = sc->sc_ah; ++ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); ++ struct ath_buf *bf_first = bf; ++ struct ath_tx_info info; ++ bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR); ++ ++ memset(&info, 0, sizeof(info)); ++ info.is_first = true; ++ info.is_last = true; ++ info.txpower = MAX_RATE_POWER; ++ info.qcu = txq->axq_qnum; ++ ++ info.flags = ATH9K_TXDESC_INTREQ; ++ if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) ++ info.flags |= ATH9K_TXDESC_NOACK; ++ if (tx_info->flags & IEEE80211_TX_CTL_LDPC) ++ info.flags |= ATH9K_TXDESC_LDPC; ++ ++ ath_buf_set_rate(sc, bf, &info, len); ++ ++ if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) ++ info.flags |= ATH9K_TXDESC_CLRDMASK; ++ ++ if (bf->bf_state.bfs_paprd) ++ info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S; ++ ++ ++ while (bf) { ++ struct sk_buff *skb = bf->bf_mpdu; ++ struct ath_frame_info *fi = get_frame_info(skb); ++ struct ieee80211_hdr *hdr; ++ int padpos, padsize; ++ ++ info.type = get_hw_packet_type(skb); ++ if (bf->bf_next) ++ info.link = bf->bf_next->bf_daddr; ++ else ++ info.link = 0; ++ ++ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { ++ hdr = (struct ieee80211_hdr *)skb->data; ++ padpos = ath9k_cmn_padpos(hdr->frame_control); ++ padsize = padpos & 3; ++ ++ info.buf_addr[0] = bf->bf_buf_addr; ++ info.buf_len[0] = padpos + padsize; ++ info.buf_addr[1] = info.buf_addr[0] + padpos; ++ info.buf_len[1] = skb->len - padpos; ++ } else { ++ info.buf_addr[0] = bf->bf_buf_addr; ++ info.buf_len[0] = skb->len; ++ } ++ ++ info.pkt_len = fi->framelen; ++ info.keyix = fi->keyix; ++ info.keytype = fi->keytype; ++ ++ if (aggr) { ++ if (bf == bf_first) ++ info.aggr = AGGR_BUF_FIRST; ++ else if (!bf->bf_next) ++ info.aggr = AGGR_BUF_LAST; ++ else ++ info.aggr = AGGR_BUF_MIDDLE; ++ ++ info.ndelim = bf->bf_state.ndelim; ++ info.aggr_len = len; ++ } ++ ++ ath9k_hw_set_txdesc(ah, bf->bf_desc, &info); ++ bf = bf->bf_next; ++ } ++} ++ + static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid) + { + struct ath_buf *bf; + enum ATH_AGGR_STATUS status; +- struct ath_frame_info *fi; ++ struct ieee80211_tx_info *tx_info; + struct list_head bf_q; + int aggr_len; + +@@ -878,34 +1090,25 @@ static void ath_tx_sched_aggr(struct ath + + bf = list_first_entry(&bf_q, struct ath_buf, list); + bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); ++ tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); + + if (tid->ac->clear_ps_filter) { + tid->ac->clear_ps_filter = false; +- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); ++ tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; ++ } else { ++ tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; + } + + /* if only one frame, send as non-aggregate */ + if (bf == bf->bf_lastbf) { +- fi = get_frame_info(bf->bf_mpdu); +- +- bf->bf_state.bf_type &= ~BUF_AGGR; +- ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); +- ath_buf_set_rate(sc, bf, fi->framelen); +- ath_tx_txqaddbuf(sc, txq, &bf_q, false); +- continue; ++ aggr_len = get_frame_info(bf->bf_mpdu)->framelen; ++ bf->bf_state.bf_type = BUF_AMPDU; ++ } else { ++ TX_STAT_INC(txq->axq_qnum, a_aggr); + } + +- /* setup first desc of aggregate */ +- bf->bf_state.bf_type |= BUF_AGGR; +- ath_buf_set_rate(sc, bf, aggr_len); +- ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len); - -- diff[0] = abs(mp_coeff[0] - mp_coeff[1]); -- diff[1] = abs(mp_coeff[1] - mp_coeff[2]); -- diff[2] = abs(mp_coeff[2] - mp_coeff[0]); +- /* anchor last desc of aggregate */ +- ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); - -- if (diff[0] > MAX_DIFFERENCE && -- diff[1] > MAX_DIFFERENCE && -- diff[2] > MAX_DIFFERENCE) -- return false; ++ ath_tx_fill_desc(sc, bf, txq, aggr_len); + ath_tx_txqaddbuf(sc, txq, &bf_q, false); +- TX_STAT_INC(txq->axq_qnum, a_aggr); - -- if (diff[0] <= diff[1] && diff[0] <= diff[2]) -- *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2; -- else if (diff[1] <= diff[2]) -- *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2; -- else -- *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2; -+ int mp_max = -64, max_idx = 0; -+ int mp_min = 63, min_idx = 0; -+ int mp_avg = 0, i, outlier_idx = 0; -+ -+ /* find min/max mismatch across all calibrated gains */ -+ for (i = 0; i < nmeasurement; i++) { -+ mp_avg += mp_coeff[i]; -+ if (mp_coeff[i] > mp_max) { -+ mp_max = mp_coeff[i]; -+ max_idx = i; -+ } else if (mp_coeff[i] < mp_min) { -+ mp_min = mp_coeff[i]; -+ min_idx = i; -+ } -+ } - -- return true; -+ /* find average (exclude max abs value) */ -+ for (i = 0; i < nmeasurement; i++) { -+ if ((abs(mp_coeff[i]) < abs(mp_max)) || -+ (abs(mp_coeff[i]) < abs(mp_min))) -+ mp_avg += mp_coeff[i]; -+ } -+ mp_avg /= (nmeasurement - 1); -+ -+ /* detect outlier */ -+ if (abs(mp_max - mp_min) > max_delta) { -+ if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg)) -+ outlier_idx = max_idx; -+ else -+ outlier_idx = min_idx; -+ } -+ mp_coeff[outlier_idx] = mp_avg; + } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH && + status != ATH_AGGR_BAW_CLOSED); } +@@ -1483,7 +1686,7 @@ static void ath_tx_send_ampdu(struct ath + if (!bf) + return; - static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, - u8 num_chains, - struct coeff *coeff) - { -- struct ath_common *common = ath9k_hw_common(ah); - int i, im, nmeasurement; -- int magnitude, phase; - u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; - - memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); -@@ -657,37 +669,28 @@ static void ar9003_hw_tx_iqcal_load_avg_ - - /* Load the average of 2 passes */ - for (i = 0; i < num_chains; i++) { -- if (AR_SREV_9485(ah)) -- nmeasurement = REG_READ_FIELD(ah, -- AR_PHY_TX_IQCAL_STATUS_B0_9485, -- AR_PHY_CALIBRATED_GAINS_0); -- else -- nmeasurement = REG_READ_FIELD(ah, -- AR_PHY_TX_IQCAL_STATUS_B0, -- AR_PHY_CALIBRATED_GAINS_0); -+ nmeasurement = REG_READ_FIELD(ah, -+ AR_PHY_TX_IQCAL_STATUS_B0, -+ AR_PHY_CALIBRATED_GAINS_0); - - if (nmeasurement > MAX_MEASUREMENT) - nmeasurement = MAX_MEASUREMENT; - -- for (im = 0; im < nmeasurement; im++) { -- /* -- * Determine which 2 passes are closest and compute avg -- * magnitude -- */ -- if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im], -- &magnitude)) -- goto disable_txiqcal; -+ /* detect outlier only if nmeasurement > 1 */ -+ if (nmeasurement > 1) { -+ /* Detect magnitude outlier */ -+ ar9003_hw_detect_outlier(coeff->mag_coeff[i], -+ nmeasurement, MAX_MAG_DELTA); -+ -+ /* Detect phase outlier */ -+ ar9003_hw_detect_outlier(coeff->phs_coeff[i], -+ nmeasurement, MAX_PHS_DELTA); -+ } +- bf->bf_state.bf_type |= BUF_AMPDU; ++ bf->bf_state.bf_type = BUF_AMPDU; + INIT_LIST_HEAD(&bf_head); + list_add(&bf->list, &bf_head); + +@@ -1493,7 +1696,7 @@ static void ath_tx_send_ampdu(struct ath + /* 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_fill_desc(sc, bf, txctl->txq, fi->framelen); + ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false); + } -- /* -- * Determine which 2 passes are closest and compute avg -- * phase -- */ -- if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im], -- &phase)) -- goto disable_txiqcal; -+ for (im = 0; im < nmeasurement; im++) { +@@ -1513,41 +1716,18 @@ static void ath_tx_send_normal(struct at -- coeff->iqc_coeff[0] = (magnitude & 0x7f) | -- ((phase & 0x7f) << 7); -+ coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) | -+ ((coeff->phs_coeff[i][im] & 0x7f) << 7); + INIT_LIST_HEAD(&bf_head); + list_add_tail(&bf->list, &bf_head); +- bf->bf_state.bf_type &= ~BUF_AMPDU; ++ bf->bf_state.bf_type = 0; - if ((im % 2) == 0) - REG_RMW_FIELD(ah, tx_corr_coeff[im][i], -@@ -707,141 +710,37 @@ static void ar9003_hw_tx_iqcal_load_avg_ + /* update starting sequence number for subsequent ADDBA request */ + if (tid) + INCR(tid->seq_start, IEEE80211_SEQ_MAX); - return; + bf->bf_lastbf = bf; +- ath_buf_set_rate(sc, bf, fi->framelen); ++ ath_tx_fill_desc(sc, bf, txq, fi->framelen); + ath_tx_txqaddbuf(sc, txq, &bf_head, false); + TX_STAT_INC(txq->axq_qnum, queued); + } --disable_txiqcal: -- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, -- AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0); -- REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, -- AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0); +-static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) +-{ +- struct ieee80211_hdr *hdr; +- enum ath9k_pkt_type htype; +- __le16 fc; +- +- hdr = (struct ieee80211_hdr *)skb->data; +- fc = hdr->frame_control; +- +- if (ieee80211_is_beacon(fc)) +- htype = ATH9K_PKT_TYPE_BEACON; +- else if (ieee80211_is_probe_resp(fc)) +- htype = ATH9K_PKT_TYPE_PROBE_RESP; +- else if (ieee80211_is_atim(fc)) +- htype = ATH9K_PKT_TYPE_ATIM; +- else if (ieee80211_is_pspoll(fc)) +- htype = ATH9K_PKT_TYPE_PSPOLL; +- else +- htype = ATH9K_PKT_TYPE_NORMAL; - -- ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n"); +- return htype; +-} +- + static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, + int framelen) + { +@@ -1575,51 +1755,6 @@ static void setup_frame_info(struct ieee + fi->framelen = framelen; } --static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) -+static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) +-static int setup_tx_flags(struct sk_buff *skb) +-{ +- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); +- int flags = 0; +- +- flags |= ATH9K_TXDESC_INTREQ; +- +- if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) +- flags |= ATH9K_TXDESC_NOACK; +- +- if (tx_info->flags & IEEE80211_TX_CTL_LDPC) +- flags |= ATH9K_TXDESC_LDPC; +- +- return flags; +-} +- +-/* +- * rix - rate index +- * pktlen - total bytes (delims + data + fcs + pads + pad delims) +- * width - 0 for 20 MHz, 1 for 40 MHz +- * half_gi - to use 4us v/s 3.6 us for symbol time +- */ +-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, +- int width, int half_gi, bool shortPreamble) +-{ +- u32 nbits, nsymbits, duration, nsymbols; +- int streams; +- +- /* find number of symbols: PLCP + data */ +- streams = HT_RC_2_STREAMS(rix); +- nbits = (pktlen << 3) + OFDM_PLCP_BITS; +- nsymbits = bits_per_symbol[rix % 8][width] * streams; +- nsymbols = (nbits + nsymbits - 1) / nsymbits; +- +- if (!half_gi) +- duration = SYMBOL_TIME(nsymbols); +- else +- duration = SYMBOL_TIME_HALFGI(nsymbols); +- +- /* addup duration for legacy/ht training and signal fields */ +- duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); +- +- return duration; +-} +- + u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) { - struct ath_common *common = ath9k_hw_common(ah); -- static const u32 txiqcal_status[AR9300_MAX_CHAINS] = { -- AR_PHY_TX_IQCAL_STATUS_B0, -- AR_PHY_TX_IQCAL_STATUS_B1, -- AR_PHY_TX_IQCAL_STATUS_B2, -- }; -- static const u32 chan_info_tab[] = { -- AR_PHY_CHAN_INFO_TAB_0, -- AR_PHY_CHAN_INFO_TAB_1, -- AR_PHY_CHAN_INFO_TAB_2, -- }; -- struct coeff coeff; -- s32 iq_res[6]; -- s32 i, j, ip, im, nmeasurement; -- u8 nchains = get_streams(common->tx_chainmask); -- -- for (ip = 0; ip < MPASS; ip++) { -- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, -- AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, -- DELPT); -- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, -- AR_PHY_TX_IQCAL_START_DO_CAL, -- AR_PHY_TX_IQCAL_START_DO_CAL); -- -- if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, -- AR_PHY_TX_IQCAL_START_DO_CAL, -- 0, AH_WAIT_TIMEOUT)) { -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "Tx IQ Cal not complete.\n"); -- goto TX_IQ_CAL_FAILED; -- } + struct ath_hw *ah = sc->sc_ah; +@@ -1632,118 +1767,6 @@ u8 ath_txchainmask_reduction(struct ath_ + return chainmask; + } + +-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) +-{ +- struct ath_hw *ah = sc->sc_ah; +- struct ath9k_11n_rate_series series[4]; +- struct sk_buff *skb; +- struct ieee80211_tx_info *tx_info; +- struct ieee80211_tx_rate *rates; +- const struct ieee80211_rate *rate; +- struct ieee80211_hdr *hdr; +- int i, flags = 0; +- u8 rix = 0, ctsrate = 0; +- bool is_pspoll; - -- nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, -- AR_PHY_CALIBRATED_GAINS_0); -- if (nmeasurement > MAX_MEASUREMENT) -- nmeasurement = MAX_MEASUREMENT; -- -- for (i = 0; i < nchains; i++) { -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "Doing Tx IQ Cal for chain %d.\n", i); -- for (im = 0; im < nmeasurement; im++) { -- if (REG_READ(ah, txiqcal_status[i]) & -- AR_PHY_TX_IQCAL_STATUS_FAILED) { -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "Tx IQ Cal failed for chain %d.\n", i); -- goto TX_IQ_CAL_FAILED; -- } +- memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); - -- for (j = 0; j < 3; j++) { -- u8 idx = 2 * j, -- offset = 4 * (3 * im + j); +- skb = bf->bf_mpdu; +- tx_info = IEEE80211_SKB_CB(skb); +- rates = tx_info->control.rates; +- hdr = (struct ieee80211_hdr *)skb->data; +- is_pspoll = ieee80211_is_pspoll(hdr->frame_control); - -- REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, -- AR_PHY_CHAN_INFO_TAB_S2_READ, -- 0); +- /* +- * We check if Short Preamble is needed for the CTS rate by +- * checking the BSS's global flag. +- * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. +- */ +- rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info); +- ctsrate = rate->hw_value; +- if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) +- ctsrate |= rate->hw_value_short; - -- /* 32 bits */ -- iq_res[idx] = REG_READ(ah, -- chan_info_tab[i] + -- offset); +- for (i = 0; i < 4; i++) { +- bool is_40, is_sgi, is_sp; +- int phy; - -- REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, -- AR_PHY_CHAN_INFO_TAB_S2_READ, -- 1); +- if (!rates[i].count || (rates[i].idx < 0)) +- continue; - -- /* 16 bits */ -- iq_res[idx+1] = 0xffff & REG_READ(ah, -- chan_info_tab[i] + -- offset); +- rix = rates[i].idx; +- series[i].Tries = rates[i].count; - -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", -- idx, iq_res[idx], idx+1, iq_res[idx+1]); -- } +- if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) { +- series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; +- flags |= ATH9K_TXDESC_RTSENA; +- } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { +- series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; +- flags |= ATH9K_TXDESC_CTSENA; +- } - -- if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, -- coeff.iqc_coeff)) { -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "Failed in calculation of IQ correction.\n"); -- goto TX_IQ_CAL_FAILED; -- } -- coeff.mag_coeff[i][im][ip] = -- coeff.iqc_coeff[0] & 0x7f; -- coeff.phs_coeff[i][im][ip] = -- (coeff.iqc_coeff[0] >> 7) & 0x7f; +- if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) +- series[i].RateFlags |= ATH9K_RATESERIES_2040; +- if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) +- series[i].RateFlags |= ATH9K_RATESERIES_HALFGI; - -- if (coeff.mag_coeff[i][im][ip] > 63) -- coeff.mag_coeff[i][im][ip] -= 128; -- if (coeff.phs_coeff[i][im][ip] > 63) -- coeff.phs_coeff[i][im][ip] -= 128; +- is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI); +- is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH); +- is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE); - -- } +- if (rates[i].flags & IEEE80211_TX_RC_MCS) { +- /* MCS rates */ +- series[i].Rate = rix | 0x80; +- series[i].ChSel = ath_txchainmask_reduction(sc, +- ah->txchainmask, series[i].Rate); +- series[i].PktDuration = ath_pkt_duration(sc, rix, len, +- is_40, is_sgi, is_sp); +- if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) +- series[i].RateFlags |= ATH9K_RATESERIES_STBC; +- continue; - } +- +- /* legacy rates */ +- if ((tx_info->band == IEEE80211_BAND_2GHZ) && +- !(rate->flags & IEEE80211_RATE_ERP_G)) +- phy = WLAN_RC_PHY_CCK; +- else +- phy = WLAN_RC_PHY_OFDM; +- +- rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx]; +- series[i].Rate = rate->hw_value; +- if (rate->hw_value_short) { +- if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) +- series[i].Rate |= rate->hw_value_short; +- } else { +- is_sp = false; +- } +- +- if (bf->bf_state.bfs_paprd) +- series[i].ChSel = ah->txchainmask; +- else +- series[i].ChSel = ath_txchainmask_reduction(sc, +- ah->txchainmask, series[i].Rate); +- +- series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, +- phy, rate->bitrate * 100, len, rix, is_sp); - } - -- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff); +- /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ +- if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit)) +- flags &= ~ATH9K_TXDESC_RTSENA; +- +- /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */ +- if (flags & ATH9K_TXDESC_RTSENA) +- flags &= ~ATH9K_TXDESC_CTSENA; - -- return; +- /* set dur_update_en for l-sig computation except for PS-Poll frames */ +- ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc, +- bf->bf_lastbf->bf_desc, +- !is_pspoll, ctsrate, +- 0, series, 4, flags); - --TX_IQ_CAL_FAILED: -- ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); -} - --static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) --{ - u8 tx_gain_forced; + /* + * Assign a descriptor (and sequence number if necessary, + * and map buffer for DMA. Frees skb on error +@@ -1753,13 +1776,10 @@ static struct ath_buf *ath_tx_setup_buff + struct ath_atx_tid *tid, + struct sk_buff *skb) + { +- 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); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ath_buf *bf; +- struct ath_desc *ds; +- int frm_type; + u16 seqno; + + bf = ath_tx_get_buffer(sc); +@@ -1777,7 +1797,6 @@ static struct ath_buf *ath_tx_setup_buff + bf->bf_state.seqno = seqno; + } + +- bf->bf_flags = setup_tx_flags(skb); + bf->bf_mpdu = skb; + + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, +@@ -1791,22 +1810,6 @@ static struct ath_buf *ath_tx_setup_buff + goto error; + } + +- frm_type = get_hw_packet_type(skb); +- +- ds = bf->bf_desc; +- ath9k_hw_set_desc_link(ah, ds, 0); +- +- ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER, +- fi->keyix, fi->keytype, bf->bf_flags); +- +- ath9k_hw_filltxdesc(ah, ds, +- skb->len, /* segment length */ +- true, /* first segment */ +- true, /* last segment */ +- ds, /* first descriptor */ +- bf->bf_buf_addr, +- txq->axq_qnum); +- + fi->bf = bf; + + return bf; +@@ -1849,16 +1852,9 @@ static void ath_tx_start_dma(struct ath_ + + bf->bf_state.bfs_paprd = txctl->paprd; + +- if (bf->bf_state.bfs_paprd) +- 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; -- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485, -- AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); - tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, - AR_PHY_TXGAIN_FORCE); - if (tx_gain_forced) - REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, - AR_PHY_TXGAIN_FORCE, 0); +- if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) +- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); +- + ath_tx_send_normal(sc, txctl->txq, tid, skb); + } + +@@ -1899,15 +1895,18 @@ int ath_tx_start(struct ieee80211_hw *hw + hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); + } -- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485, -- AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1); -+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, -+ AR_PHY_TX_IQCAL_START_DO_CAL, 1); +- /* 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 -ENOMEM; +- +- skb_push(skb, padsize); +- memmove(skb->data, skb->data + padsize, padpos); ++ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { ++ /* 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 -ENOMEM; + -+ if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, -+ AR_PHY_TX_IQCAL_START_DO_CAL, 0, -+ AH_WAIT_TIMEOUT)) { -+ ath_dbg(common, ATH_DBG_CALIBRATE, -+ "Tx IQ Cal is not completed.\n"); -+ return false; -+ } -+ return true; - } ++ skb_push(skb, padsize); ++ memmove(skb->data, skb->data + padsize, padpos); ++ hdr = (struct ieee80211_hdr *) skb->data; ++ } + } + + if ((vif && vif->type != NL80211_IFTYPE_AP && +@@ -1953,20 +1952,21 @@ static void ath_tx_complete(struct ath_s + if (tx_flags & ATH_TX_BAR) + tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + +- if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { ++ if (!(tx_flags & ATH_TX_ERROR)) + /* Frame was ACKed */ + tx_info->flags |= IEEE80211_TX_STAT_ACK; +- } - static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) +- padpos = ath9k_cmn_padpos(hdr->frame_control); +- padsize = padpos & 3; +- if (padsize && skb->len>padpos+padsize) { +- /* +- * Remove MAC header padding before giving the frame back to +- * mac80211. +- */ +- memmove(skb->data + padsize, skb->data, padpos); +- skb_pull(skb, padsize); ++ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { ++ padpos = ath9k_cmn_padpos(hdr->frame_control); ++ padsize = padpos & 3; ++ if (padsize && skb->len>padpos+padsize) { ++ /* ++ * Remove MAC header padding before giving the frame back to ++ * mac80211. ++ */ ++ memmove(skb->data + padsize, skb->data, padpos); ++ skb_pull(skb, padsize); ++ } + } + + if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { +@@ -2000,18 +2000,18 @@ static void ath_tx_complete_buf(struct a + struct ath_tx_status *ts, int txok, int sendbar) { - struct ath_common *common = ath9k_hw_common(ah); - const u32 txiqcal_status[AR9300_MAX_CHAINS] = { -- AR_PHY_TX_IQCAL_STATUS_B0_9485, -+ AR_PHY_TX_IQCAL_STATUS_B0, - AR_PHY_TX_IQCAL_STATUS_B1, - AR_PHY_TX_IQCAL_STATUS_B2, - }; -@@ -853,7 +752,7 @@ static void ar9003_hw_tx_iq_cal_post_pro - struct coeff coeff; - s32 iq_res[6]; - u8 num_chains = 0; -- int i, ip, im, j; -+ int i, im, j; - int nmeasurement; - - for (i = 0; i < AR9300_MAX_CHAINS; i++) { -@@ -861,71 +760,69 @@ static void ar9003_hw_tx_iq_cal_post_pro - num_chains++; + struct sk_buff *skb = bf->bf_mpdu; ++ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + unsigned long flags; + int tx_flags = 0; + + if (sendbar) + tx_flags = ATH_TX_BAR; + +- if (!txok) { ++ if (!txok) + tx_flags |= ATH_TX_ERROR; + +- if (bf_isxretried(bf)) +- tx_flags |= ATH_TX_XRETRY; +- } ++ if (ts->ts_status & ATH9K_TXERR_FILT) ++ tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + + dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); + bf->bf_buf_addr = 0; +@@ -2024,7 +2024,7 @@ static void ath_tx_complete_buf(struct a + else + complete(&sc->paprd_complete); + } else { +- ath_debug_stat_tx(sc, bf, ts, txq); ++ ath_debug_stat_tx(sc, bf, ts, txq, tx_flags); + ath_tx_complete(sc, skb, tx_flags, txq); } + /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't +@@ -2042,7 +2042,7 @@ static void ath_tx_complete_buf(struct a -- for (ip = 0; ip < MPASS; ip++) { -- for (i = 0; i < num_chains; i++) { -- nmeasurement = REG_READ_FIELD(ah, -- AR_PHY_TX_IQCAL_STATUS_B0_9485, -- AR_PHY_CALIBRATED_GAINS_0); -- if (nmeasurement > MAX_MEASUREMENT) -- nmeasurement = MAX_MEASUREMENT; -+ for (i = 0; i < num_chains; i++) { -+ nmeasurement = REG_READ_FIELD(ah, -+ AR_PHY_TX_IQCAL_STATUS_B0, -+ AR_PHY_CALIBRATED_GAINS_0); -+ if (nmeasurement > MAX_MEASUREMENT) -+ nmeasurement = MAX_MEASUREMENT; -+ -+ for (im = 0; im < nmeasurement; im++) { -+ ath_dbg(common, ATH_DBG_CALIBRATE, -+ "Doing Tx IQ Cal for chain %d.\n", i); - -- for (im = 0; im < nmeasurement; im++) { -+ if (REG_READ(ah, txiqcal_status[i]) & -+ AR_PHY_TX_IQCAL_STATUS_FAILED) { - ath_dbg(common, ATH_DBG_CALIBRATE, -- "Doing Tx IQ Cal for chain %d.\n", i); -- -- if (REG_READ(ah, txiqcal_status[i]) & -- AR_PHY_TX_IQCAL_STATUS_FAILED) { -- ath_dbg(common, ATH_DBG_CALIBRATE, - "Tx IQ Cal failed for chain %d.\n", i); -- goto tx_iqcal_fail; -- } -+ goto tx_iqcal_fail; -+ } - -- for (j = 0; j < 3; j++) { -- u32 idx = 2 * j, offset = 4 * (3 * im + j); -+ for (j = 0; j < 3; j++) { -+ u32 idx = 2 * j, offset = 4 * (3 * im + j); - -- REG_RMW_FIELD(ah, -+ REG_RMW_FIELD(ah, - AR_PHY_CHAN_INFO_MEMORY, - AR_PHY_CHAN_INFO_TAB_S2_READ, - 0); - -- /* 32 bits */ -- iq_res[idx] = REG_READ(ah, -- chan_info_tab[i] + -- offset); -+ /* 32 bits */ -+ iq_res[idx] = REG_READ(ah, -+ chan_info_tab[i] + -+ offset); - -- REG_RMW_FIELD(ah, -+ REG_RMW_FIELD(ah, - AR_PHY_CHAN_INFO_MEMORY, - AR_PHY_CHAN_INFO_TAB_S2_READ, - 1); - -- /* 16 bits */ -- iq_res[idx + 1] = 0xffff & REG_READ(ah, -- chan_info_tab[i] + offset); -- -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "IQ RES[%d]=0x%x" -- "IQ_RES[%d]=0x%x\n", -- idx, iq_res[idx], idx + 1, -- iq_res[idx + 1]); -- } -+ /* 16 bits */ -+ iq_res[idx + 1] = 0xffff & REG_READ(ah, -+ chan_info_tab[i] + offset); - -- if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, -- coeff.iqc_coeff)) { -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "Failed in calculation of IQ correction.\n"); -- goto tx_iqcal_fail; -- } -+ ath_dbg(common, ATH_DBG_CALIBRATE, -+ "IQ RES[%d]=0x%x" -+ "IQ_RES[%d]=0x%x\n", -+ idx, iq_res[idx], idx + 1, -+ iq_res[idx + 1]); -+ } - -- coeff.mag_coeff[i][im][ip] = -- coeff.iqc_coeff[0] & 0x7f; -- coeff.phs_coeff[i][im][ip] = -- (coeff.iqc_coeff[0] >> 7) & 0x7f; -- -- if (coeff.mag_coeff[i][im][ip] > 63) -- coeff.mag_coeff[i][im][ip] -= 128; -- if (coeff.phs_coeff[i][im][ip] > 63) -- coeff.phs_coeff[i][im][ip] -= 128; -+ if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, -+ coeff.iqc_coeff)) { -+ ath_dbg(common, ATH_DBG_CALIBRATE, -+ "Failed in calculation of \ -+ IQ correction.\n"); -+ goto tx_iqcal_fail; - } + 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) ++ int txok) + { + struct sk_buff *skb = bf->bf_mpdu; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +@@ -2057,9 +2057,7 @@ static void ath_tx_rc_status(struct ath_ + tx_rateindex = ts->ts_rateindex; + WARN_ON(tx_rateindex >= hw->max_rates); + +- if (ts->ts_status & ATH9K_TXERR_FILT) +- tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; +- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) { ++ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + tx_info->flags |= IEEE80211_TX_STAT_AMPDU; + + BUG_ON(nbad > nframes); +@@ -2069,7 +2067,7 @@ static void ath_tx_rc_status(struct ath_ + } + + if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && +- (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { ++ (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) { + /* + * If an underrun error is seen assume it as an excessive + * retry only if max frame trigger level has been reached +@@ -2082,9 +2080,9 @@ static void ath_tx_rc_status(struct ath_ + * successfully by eventually preferring slower rates. + * This itself should also alleviate congestion on the bus. + */ +- if (ieee80211_is_data(hdr->frame_control) && +- (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | +- ATH9K_TX_DELIM_UNDERRUN)) && ++ if (unlikely(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | ++ ATH9K_TX_DELIM_UNDERRUN)) && ++ ieee80211_is_data(hdr->frame_control) && + ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level) + tx_info->status.rates[tx_rateindex].count = + hw->max_rate_tries; +@@ -2115,13 +2113,7 @@ static void ath_tx_process_buffer(struct + spin_unlock_bh(&txq->axq_lock); + + if (!bf_isampdu(bf)) { +- /* +- * This frame is sent out as a single frame. +- * Use hardware retry status for this frame. +- */ +- if (ts->ts_status & ATH9K_TXERR_XRETRY) +- bf->bf_state.bf_type |= BUF_XRETRY; +- ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true); ++ ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); + ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0); + } else + ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true); +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -180,6 +180,8 @@ static void ieee80211_send_addba_resp(st + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); + else if (sdata->vif.type == NL80211_IFTYPE_STATION) + memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); ++ else if (sdata->vif.type == NL80211_IFTYPE_WDS) ++ memcpy(mgmt->bssid, da, ETH_ALEN); + + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); +--- a/net/mac80211/agg-tx.c ++++ b/net/mac80211/agg-tx.c +@@ -77,7 +77,8 @@ static void ieee80211_send_addba_request + memcpy(mgmt->da, da, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); + if (sdata->vif.type == NL80211_IFTYPE_AP || +- sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ++ sdata->vif.type == NL80211_IFTYPE_AP_VLAN || ++ sdata->vif.type == NL80211_IFTYPE_WDS) + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); + else if (sdata->vif.type == NL80211_IFTYPE_STATION) + memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); +@@ -397,7 +398,8 @@ int ieee80211_start_tx_ba_session(struct + */ + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_AP_VLAN && +- sdata->vif.type != NL80211_IFTYPE_AP) ++ sdata->vif.type != NL80211_IFTYPE_AP && ++ sdata->vif.type != NL80211_IFTYPE_WDS) + return -EINVAL; + + if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { +--- a/net/mac80211/debugfs_sta.c ++++ b/net/mac80211/debugfs_sta.c +@@ -59,7 +59,7 @@ static ssize_t sta_flags_read(struct fil + char buf[100]; + struct sta_info *sta = file->private_data; + u32 staflags = get_sta_flags(sta); +- int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s", ++ int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s", + staflags & WLAN_STA_AUTH ? "AUTH\n" : "", + staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "", + staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "", +@@ -67,7 +67,6 @@ static ssize_t sta_flags_read(struct fil + staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", + staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", + staflags & WLAN_STA_WME ? "WME\n" : "", +- staflags & WLAN_STA_WDS ? "WDS\n" : "", + staflags & WLAN_STA_MFP ? "MFP\n" : ""); + return simple_read_from_buffer(userbuf, count, ppos, buf, res); + } +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -178,7 +178,6 @@ static int ieee80211_do_open(struct net_ + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; +- struct sta_info *sta; + u32 changed = 0; + int res; + u32 hw_reconf_flags = 0; +@@ -290,27 +289,6 @@ static int ieee80211_do_open(struct net_ + + set_bit(SDATA_STATE_RUNNING, &sdata->state); + +- if (sdata->vif.type == NL80211_IFTYPE_WDS) { +- /* Create STA entry for the WDS peer */ +- sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, +- GFP_KERNEL); +- if (!sta) { +- res = -ENOMEM; +- goto err_del_interface; +- } +- +- /* no locking required since STA is not live yet */ +- sta->flags |= WLAN_STA_AUTHORIZED; +- +- res = sta_info_insert(sta); +- if (res) { +- /* STA has been freed */ +- goto err_del_interface; +- } +- +- rate_control_rate_init(sta); +- } +- + /* + * set_multicast_list will be invoked by the networking core + * which will check whether any increments here were done in +@@ -344,8 +322,7 @@ static int ieee80211_do_open(struct net_ + netif_tx_start_all_queues(dev); + + return 0; +- err_del_interface: +- drv_remove_interface(local, &sdata->vif); ++ + err_stop: + if (!local->open_count) + drv_stop(local); +@@ -718,6 +695,70 @@ static void ieee80211_if_setup(struct ne + dev->destructor = free_netdev; + } + ++static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_rx_status *rx_status; ++ struct ieee802_11_elems elems; ++ struct ieee80211_mgmt *mgmt; ++ struct sta_info *sta; ++ size_t baselen; ++ u32 rates = 0; ++ u16 stype; ++ bool new = false; ++ enum ieee80211_band band = local->hw.conf.channel->band; ++ struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; ++ ++ rx_status = IEEE80211_SKB_RXCB(skb); ++ mgmt = (struct ieee80211_mgmt *) skb->data; ++ stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; ++ ++ if (stype != IEEE80211_STYPE_BEACON) ++ return; ++ ++ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; ++ if (baselen > skb->len) ++ return; ++ ++ ieee802_11_parse_elems(mgmt->u.probe_resp.variable, ++ skb->len - baselen, &elems); ++ ++ rates = ieee80211_sta_get_rates(local, &elems, band); + -+ coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f; -+ coeff.phs_coeff[i][im] = -+ (coeff.iqc_coeff[0] >> 7) & 0x7f; ++ rcu_read_lock(); + -+ if (coeff.mag_coeff[i][im] > 63) -+ coeff.mag_coeff[i][im] -= 128; -+ if (coeff.phs_coeff[i][im] > 63) -+ coeff.phs_coeff[i][im] -= 128; ++ sta = sta_info_get(sdata, sdata->u.wds.remote_addr); ++ ++ if (!sta) { ++ rcu_read_unlock(); ++ sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, ++ GFP_KERNEL); ++ if (!sta) ++ return; ++ ++ new = true; ++ } ++ ++ sta->last_rx = jiffies; ++ sta->sta.supp_rates[local->hw.conf.channel->band] = rates; ++ ++ if (elems.ht_cap_elem) ++ ieee80211_ht_cap_ie_to_sta_ht_cap(sband, ++ elems.ht_cap_elem, &sta->sta.ht_cap); ++ ++ if (elems.wmm_param) ++ set_sta_flags(sta, WLAN_STA_WME); ++ ++ if (new) { ++ sta->flags = WLAN_STA_AUTHORIZED; ++ rate_control_rate_init(sta); ++ sta_info_insert_rcu(sta); ++ } ++ ++ rcu_read_unlock(); ++} ++ + static void ieee80211_iface_work(struct work_struct *work) + { + struct ieee80211_sub_if_data *sdata = +@@ -822,6 +863,9 @@ static void ieee80211_iface_work(struct + break; + ieee80211_mesh_rx_queued_mgmt(sdata, skb); + break; ++ case NL80211_IFTYPE_WDS: ++ ieee80211_wds_rx_queued_mgmt(sdata, skb); ++ break; + default: + WARN(1, "frame for unexpected interface type"); + break; +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2163,7 +2163,8 @@ ieee80211_rx_h_action(struct ieee80211_r + */ + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_AP_VLAN && +- sdata->vif.type != NL80211_IFTYPE_AP) ++ sdata->vif.type != NL80211_IFTYPE_AP && ++ sdata->vif.type != NL80211_IFTYPE_WDS) + break; + + /* verify action_code is present */ +@@ -2378,13 +2379,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_ + + if (!ieee80211_vif_is_mesh(&sdata->vif) && + sdata->vif.type != NL80211_IFTYPE_ADHOC && +- sdata->vif.type != NL80211_IFTYPE_STATION) ++ sdata->vif.type != NL80211_IFTYPE_STATION && ++ sdata->vif.type != NL80211_IFTYPE_WDS) + return RX_DROP_MONITOR; + + switch (stype) { + case cpu_to_le16(IEEE80211_STYPE_BEACON): + case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): +- /* process for all: mesh, mlme, ibss */ ++ /* process for all: mesh, mlme, ibss, wds */ + break; + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + case cpu_to_le16(IEEE80211_STYPE_DISASSOC): +@@ -2727,10 +2729,16 @@ static int prepare_for_handlers(struct i } + break; + case NL80211_IFTYPE_WDS: +- if (bssid || !ieee80211_is_data(hdr->frame_control)) +- return 0; + if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) + return 0; ++ ++ if (ieee80211_is_data(hdr->frame_control) || ++ ieee80211_is_action(hdr->frame_control)) { ++ if (compare_ether_addr(sdata->vif.addr, hdr->addr1)) ++ return 0; ++ } else if (!ieee80211_is_beacon(hdr->frame_control)) ++ return 0; ++ + break; + default: + /* should never get here */ +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -31,7 +31,6 @@ + * frames. + * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP. + * @WLAN_STA_WME: Station is a QoS-STA. +- * @WLAN_STA_WDS: Station is one of our WDS peers. + * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the + * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next + * frame to this station is transmitted. +@@ -54,7 +53,6 @@ enum ieee80211_sta_info_flags { + WLAN_STA_SHORT_PREAMBLE = 1<<4, + WLAN_STA_ASSOC_AP = 1<<5, + WLAN_STA_WME = 1<<6, +- WLAN_STA_WDS = 1<<7, + WLAN_STA_CLEAR_PS_FILT = 1<<9, + WLAN_STA_MFP = 1<<10, + WLAN_STA_BLOCK_BA = 1<<11, +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -278,17 +278,19 @@ void ieee80211_tx_status(struct ieee8021 + } + + if (!acked && ieee80211_is_back_req(fc)) { ++ u16 control; ++ + /* +- * BAR failed, let's tear down the BA session as a +- * last resort as some STAs (Intel 5100 on Windows) +- * can get stuck when the BA window isn't flushed +- * correctly. ++ * BAR failed, store the last SSN and retry sending ++ * the BAR when the next unicast transmission on the ++ * same TID succeeds. + */ + bar = (struct ieee80211_bar *) skb->data; +- if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) { ++ control = le16_to_cpu(bar->control); ++ if (!(control & IEEE80211_BAR_CTRL_MULTI_TID)) { + u16 ssn = le16_to_cpu(bar->start_seq_num); + +- tid = (bar->control & ++ tid = (control & + IEEE80211_BAR_CTRL_TID_INFO_MASK) >> + IEEE80211_BAR_CTRL_TID_INFO_SHIFT; + +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -704,8 +704,10 @@ static void ar5008_hw_override_ini(struc + REG_WRITE(ah, AR_PCU_MISC_MODE2, val); + } + +- if (!AR_SREV_5416_20_OR_LATER(ah) || +- AR_SREV_9280_20_OR_LATER(ah)) ++ REG_SET_BIT(ah, AR_PHY_CCK_DETECT, ++ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); ++ ++ if (AR_SREV_9280_20_OR_LATER(ah)) + return; + /* + * Disable BB clock gating +@@ -802,7 +804,8 @@ static int ar5008_hw_process_ini(struct + + /* Write ADDAC shifts */ + REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); +- ah->eep_ops->set_addac(ah, chan); ++ if (ah->eep_ops->set_addac) ++ ah->eep_ops->set_addac(ah, chan); + + if (AR_SREV_5416_22_OR_LATER(ah)) { + REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); +@@ -1007,24 +1010,6 @@ static void ar5008_restore_chainmask(str } - ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff); -@@ -941,6 +838,7 @@ static bool ar9003_hw_init_cal(struct at + } + +-static void ar5008_set_diversity(struct ath_hw *ah, bool value) +-{ +- u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); +- if (value) +- v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; +- else +- v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; +- REG_WRITE(ah, AR_PHY_CCK_DETECT, v); +-} +- +-static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah, +- struct ath9k_channel *chan) +-{ +- if (chan && IS_CHAN_5GHZ(chan)) +- return 0x1450; +- return 0x1458; +-} +- + static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah, + struct ath9k_channel *chan) { - struct ath_common *common = ath9k_hw_common(ah); - int val; -+ bool txiqcal_done = false; +@@ -1654,7 +1639,6 @@ void ar5008_hw_attach_phy_ops(struct ath + priv_ops->rfbus_req = ar5008_hw_rfbus_req; + priv_ops->rfbus_done = ar5008_hw_rfbus_done; + priv_ops->restore_chainmask = ar5008_restore_chainmask; +- priv_ops->set_diversity = ar5008_set_diversity; + priv_ops->do_getnf = ar5008_hw_do_getnf; + priv_ops->set_radar_params = ar5008_hw_set_radar_params; + +@@ -1664,9 +1648,7 @@ void ar5008_hw_attach_phy_ops(struct ath + } else + priv_ops->ani_control = ar5008_hw_ani_control_old; + +- if (AR_SREV_9100(ah)) +- priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; +- else if (AR_SREV_9160_10_OR_LATER(ah)) ++ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) + priv_ops->compute_pll_control = ar9160_hw_compute_pll_control; + else + priv_ops->compute_pll_control = ar5008_hw_compute_pll_control; +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -592,6 +592,9 @@ static void ar9003_hw_override_ini(struc + val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE); + REG_WRITE(ah, AR_PCU_MISC_MODE2, + val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE); ++ ++ REG_SET_BIT(ah, AR_PHY_CCK_DETECT, ++ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + } - val = REG_READ(ah, AR_ENT_OTP); - ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); -@@ -957,14 +855,22 @@ static bool ar9003_hw_init_cal(struct at - ar9003_hw_set_chain_masks(ah, 0x7, 0x7); + static void ar9003_hw_prog_ini(struct ath_hw *ah, +@@ -785,16 +788,6 @@ static void ar9003_hw_rfbus_done(struct + REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); + } - /* Do Tx IQ Calibration */ -- if (AR_SREV_9485(ah)) -- ar9003_hw_tx_iq_cal_run(ah); +-static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) +-{ +- u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); +- if (value) +- v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; - else -- ar9003_hw_tx_iq_cal(ah); -+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, -+ AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, -+ DELPT); - -- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); -- udelay(5); -- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); -+ /* -+ * For AR9485 or later chips, TxIQ cal runs as part of -+ * AGC calibration -+ */ -+ if (AR_SREV_9485_OR_LATER(ah)) -+ txiqcal_done = true; -+ else { -+ txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); -+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); -+ udelay(5); -+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); -+ } +- v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; +- REG_WRITE(ah, AR_PHY_CCK_DETECT, v); +-} +- + static bool ar9003_hw_ani_control(struct ath_hw *ah, + enum ath9k_ani_cmd cmd, int param) + { +@@ -1277,7 +1270,6 @@ void ar9003_hw_attach_phy_ops(struct ath + priv_ops->set_delta_slope = ar9003_hw_set_delta_slope; + priv_ops->rfbus_req = ar9003_hw_rfbus_req; + priv_ops->rfbus_done = ar9003_hw_rfbus_done; +- priv_ops->set_diversity = ar9003_hw_set_diversity; + priv_ops->ani_control = ar9003_hw_ani_control; + priv_ops->do_getnf = ar9003_hw_do_getnf; + priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; +--- a/drivers/net/wireless/ath/ath9k/eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom.c +@@ -456,12 +456,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs + pPdGainBoundaries[i] = + min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]); + +- if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { +- minDelta = pPdGainBoundaries[0] - 23; +- pPdGainBoundaries[0] = 23; +- } else { +- minDelta = 0; +- } ++ minDelta = 0; + + if (i == 0) { + if (AR_SREV_9280_20_OR_LATER(ah)) +--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +@@ -405,12 +405,7 @@ static void ath9k_hw_set_4k_power_cal_ta + REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); + + for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { +- if (AR_SREV_5416_20_OR_LATER(ah) && +- (ah->rxchainmask == 5 || ah->txchainmask == 5) && +- (i != 0)) { +- regChainOffset = (i == 1) ? 0x2000 : 0x1000; +- } else +- regChainOffset = i * 0x1000; ++ regChainOffset = i * 0x1000; + + if (pEepData->baseEepHeader.txMask & (1 << i)) { + pRawDataset = pEepData->calPierData2G[i]; +@@ -423,19 +418,17 @@ static void ath9k_hw_set_4k_power_cal_ta + + ENABLE_REGWRITE_BUFFER(ah); + +- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { +- REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, +- SM(pdGainOverlap_t2, +- AR_PHY_TPCRG5_PD_GAIN_OVERLAP) +- | SM(gainBoundaries[0], +- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) +- | SM(gainBoundaries[1], +- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) +- | SM(gainBoundaries[2], +- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) +- | SM(gainBoundaries[3], +- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); +- } ++ REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, ++ SM(pdGainOverlap_t2, ++ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) ++ | SM(gainBoundaries[0], ++ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) ++ | SM(gainBoundaries[1], ++ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) ++ | SM(gainBoundaries[2], ++ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) ++ | SM(gainBoundaries[3], ++ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + + regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; + for (j = 0; j < 32; j++) { +@@ -715,10 +708,8 @@ static void ath9k_hw_4k_set_txpower(stru + if (test) + return; + +- if (AR_SREV_9280_20_OR_LATER(ah)) { +- for (i = 0; i < Ar5416RateSize; i++) +- ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; +- } ++ for (i = 0; i < Ar5416RateSize; i++) ++ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; + + ENABLE_REGWRITE_BUFFER(ah); + +@@ -788,28 +779,6 @@ static void ath9k_hw_4k_set_txpower(stru + REGWRITE_BUFFER_FLUSH(ah); + } - /* Calibrate the AGC */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, -@@ -979,7 +885,7 @@ static bool ar9003_hw_init_cal(struct at - return false; +-static void ath9k_hw_4k_set_addac(struct ath_hw *ah, +- struct ath9k_channel *chan) +-{ +- struct modal_eep_4k_header *pModal; +- struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; +- u8 biaslevel; +- +- if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) +- return; +- +- if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) +- return; +- +- pModal = &eep->modalHeader; +- +- if (pModal->xpaBiasLvl != 0xff) { +- biaslevel = pModal->xpaBiasLvl; +- INI_RA(&ah->iniAddac, 7, 1) = +- (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3; +- } +-} +- + static void ath9k_hw_4k_set_gain(struct ath_hw *ah, + struct modal_eep_4k_header *pModal, + struct ar5416_eeprom_4k *eep, +@@ -877,6 +846,7 @@ static void ath9k_hw_4k_set_board_values + u8 txRxAttenLocal; + u8 ob[5], db1[5], db2[5]; + u8 ant_div_control1, ant_div_control2; ++ u8 bb_desired_scale; + u32 regVal; + + pModal = &eep->modalHeader; +@@ -1096,30 +1066,29 @@ static void ath9k_hw_4k_set_board_values + AR_PHY_SETTLING_SWITCH, + pModal->swSettleHt40); + } +- if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) { +- u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna & +- EEP_4K_BB_DESIRED_SCALE_MASK); +- if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { +- u32 pwrctrl, mask, clr; +- +- mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); +- pwrctrl = mask * bb_desired_scale; +- clr = mask * 0x1f; +- REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); +- REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); +- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); +- +- mask = BIT(0)|BIT(5)|BIT(15); +- pwrctrl = mask * bb_desired_scale; +- clr = mask * 0x1f; +- REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); +- +- mask = BIT(0)|BIT(5); +- pwrctrl = mask * bb_desired_scale; +- clr = mask * 0x1f; +- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); +- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); +- } ++ ++ bb_desired_scale = (pModal->bb_scale_smrt_antenna & ++ EEP_4K_BB_DESIRED_SCALE_MASK); ++ if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { ++ u32 pwrctrl, mask, clr; ++ ++ mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); ++ pwrctrl = mask * bb_desired_scale; ++ clr = mask * 0x1f; ++ REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); ++ REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); ++ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); ++ ++ mask = BIT(0)|BIT(5)|BIT(15); ++ pwrctrl = mask * bb_desired_scale; ++ clr = mask * 0x1f; ++ REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); ++ ++ mask = BIT(0)|BIT(5); ++ pwrctrl = mask * bb_desired_scale; ++ clr = mask * 0x1f; ++ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); ++ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); } + } -- if (AR_SREV_9485(ah)) -+ if (txiqcal_done) - ar9003_hw_tx_iq_cal_post_proc(ah); +@@ -1161,7 +1130,6 @@ const struct eeprom_ops eep_4k_ops = { + .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, + .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, + .set_board_values = ath9k_hw_4k_set_board_values, +- .set_addac = ath9k_hw_4k_set_addac, + .set_txpower = ath9k_hw_4k_set_txpower, + .get_spur_channel = ath9k_hw_4k_get_spur_channel + }; +--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c +@@ -851,10 +851,8 @@ static void ath9k_hw_ar9287_set_txpower( + if (test) + return; - /* Revert chainmasks to their original values before NF cal */ ---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h -+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h -@@ -548,15 +548,12 @@ - - #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) - --#define AR_PHY_TX_IQCAL_START_9485 (AR_SM_BASE + 0x3c4) --#define AR_PHY_TX_IQCAL_START_DO_CAL_9485 0x80000000 --#define AR_PHY_TX_IQCAL_START_DO_CAL_9485_S 31 --#define AR_PHY_TX_IQCAL_CONTROL_1_9485 (AR_SM_BASE + 0x3c8) --#define AR_PHY_TX_IQCAL_STATUS_B0_9485 (AR_SM_BASE + 0x3f0) -- --#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) --#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) --#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) -+#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \ -+ 0x3c8 : 0x448) -+#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \ -+ 0x3c4 : 0x440) -+#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + AR_SREV_9485(ah) ? \ -+ 0x3f0 : 0x48c) - #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \ - (AR_SREV_9485(ah) ? \ - 0x3d0 : 0x450) + ((_i) << 2)) -@@ -758,10 +755,10 @@ - #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 - #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 - #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 --#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 --#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 --#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 --#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 -+#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 -+#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 -+#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 -+#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 - - #define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001 - #define AR_PHY_CALIBRATED_GAINS_0 0x3e ---- a/drivers/net/wireless/ath/ath9k/ath9k.h -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -453,6 +453,7 @@ void ath9k_btcoex_timer_pause(struct ath +- if (AR_SREV_9280_20_OR_LATER(ah)) { +- for (i = 0; i < Ar5416RateSize; i++) +- ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; +- } ++ for (i = 0; i < Ar5416RateSize; i++) ++ ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; - #define ATH_LED_PIN_DEF 1 - #define ATH_LED_PIN_9287 8 -+#define ATH_LED_PIN_9300 10 - #define ATH_LED_PIN_9485 6 + ENABLE_REGWRITE_BUFFER(ah); - #ifdef CONFIG_MAC80211_LEDS ---- a/drivers/net/wireless/ath/ath9k/gpio.c -+++ b/drivers/net/wireless/ath/ath9k/gpio.c -@@ -46,6 +46,8 @@ void ath_init_leds(struct ath_softc *sc) - sc->sc_ah->led_pin = ATH_LED_PIN_9287; - else if (AR_SREV_9485(sc->sc_ah)) - sc->sc_ah->led_pin = ATH_LED_PIN_9485; -+ else if (AR_SREV_9300(sc->sc_ah)) -+ sc->sc_ah->led_pin = ATH_LED_PIN_9300; +@@ -944,11 +942,6 @@ static void ath9k_hw_ar9287_set_txpower( + REGWRITE_BUFFER_FLUSH(ah); + } + +-static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, +- struct ath9k_channel *chan) +-{ +-} +- + static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, + struct ath9k_channel *chan) + { +@@ -1100,7 +1093,6 @@ const struct eeprom_ops eep_ar9287_ops = + .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver, + .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, + .set_board_values = ath9k_hw_ar9287_set_board_values, +- .set_addac = ath9k_hw_ar9287_set_addac, + .set_txpower = ath9k_hw_ar9287_set_txpower, + .get_spur_channel = ath9k_hw_ar9287_get_spur_channel + }; +--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c +@@ -547,8 +547,7 @@ static void ath9k_hw_def_set_board_value + break; + } + +- if (AR_SREV_5416_20_OR_LATER(ah) && +- (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) ++ if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) + regChainOffset = (i == 1) ? 0x2000 : 0x1000; else - sc->sc_ah->led_pin = ATH_LED_PIN_DEF; + regChainOffset = i * 0x1000; +@@ -565,9 +564,8 @@ static void ath9k_hw_def_set_board_value + SM(pModal->iqCalQCh[i], + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + +- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) +- ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, +- regChainOffset, i); ++ ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, ++ regChainOffset, i); + } + + if (AR_SREV_9280_20_OR_LATER(ah)) { +@@ -893,8 +891,7 @@ static void ath9k_hw_set_def_power_cal_t + xpdGainValues[2]); + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { +- if (AR_SREV_5416_20_OR_LATER(ah) && +- (ah->rxchainmask == 5 || ah->txchainmask == 5) && ++ if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && + (i != 0)) { + regChainOffset = (i == 1) ? 0x2000 : 0x1000; + } else +@@ -935,27 +932,24 @@ static void ath9k_hw_set_def_power_cal_t + + ENABLE_REGWRITE_BUFFER(ah); + +- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { +- if (OLC_FOR_AR9280_20_LATER) { +- REG_WRITE(ah, +- AR_PHY_TPCRG5 + regChainOffset, +- SM(0x6, +- AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | +- SM_PD_GAIN(1) | SM_PD_GAIN(2) | +- SM_PD_GAIN(3) | SM_PD_GAIN(4)); +- } else { +- REG_WRITE(ah, +- AR_PHY_TPCRG5 + regChainOffset, +- SM(pdGainOverlap_t2, +- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| +- SM_PDGAIN_B(0, 1) | +- SM_PDGAIN_B(1, 2) | +- SM_PDGAIN_B(2, 3) | +- SM_PDGAIN_B(3, 4)); +- } ++ if (OLC_FOR_AR9280_20_LATER) { ++ REG_WRITE(ah, ++ AR_PHY_TPCRG5 + regChainOffset, ++ SM(0x6, ++ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | ++ SM_PD_GAIN(1) | SM_PD_GAIN(2) | ++ SM_PD_GAIN(3) | SM_PD_GAIN(4)); ++ } else { ++ REG_WRITE(ah, ++ AR_PHY_TPCRG5 + regChainOffset, ++ SM(pdGainOverlap_t2, ++ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| ++ SM_PDGAIN_B(0, 1) | ++ SM_PDGAIN_B(1, 2) | ++ SM_PDGAIN_B(2, 3) | ++ SM_PDGAIN_B(3, 4)); + } + +- + ath9k_adjust_pdadc_values(ah, pwr_table_offset, + diff, pdadcValues); + +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -506,7 +506,6 @@ static void ath9k_init_misc(struct ath_s + sc->sc_flags |= SC_OP_RXAGGR; } + +- ath9k_hw_set_diversity(sc->sc_ah, true); + sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); + + memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h -@@ -868,6 +868,8 @@ - #define AR_SREV_9485_11(_ah) \ - (AR_SREV_9485(_ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11)) -+#define AR_SREV_9485_OR_LATER(_ah) \ -+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) - - #define AR_SREV_9285E_20(_ah) \ - (AR_SREV_9285_12_OR_LATER(_ah) && \ ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -652,7 +652,7 @@ static void ieee80211_sta_reorder_releas - set_release_timer: +@@ -800,10 +800,6 @@ + #define AR_SREV_5416(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ + ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)) +-#define AR_SREV_5416_20_OR_LATER(_ah) \ +- (((AR_SREV_5416(_ah)) && \ +- ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \ +- ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) + #define AR_SREV_5416_22_OR_LATER(_ah) \ + (((AR_SREV_5416(_ah)) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \ +--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c ++++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c +@@ -869,6 +869,7 @@ static bool ar9002_hw_init_cal(struct at + ar9002_hw_pa_cal(ah, true); - mod_timer(&tid_agg_rx->reorder_timer, -- tid_agg_rx->reorder_time[j] + -+ tid_agg_rx->reorder_time[j] + 1 + - HT_RX_REORDER_BUF_TIMEOUT); - } else { - del_timer(&tid_agg_rx->reorder_timer); + /* Do NF Calibration after DC offset and other calibrations */ ++ ath9k_hw_loadnf(ah, chan); + ath9k_hw_start_nfcal(ah, true); + + if (ah->caldata) +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -671,7 +671,6 @@ enum queue_stop_reason { + IEEE80211_QUEUE_STOP_REASON_AGGREGATION, + IEEE80211_QUEUE_STOP_REASON_SUSPEND, + IEEE80211_QUEUE_STOP_REASON_SKB_ADD, +- IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE, + }; + + #ifdef CONFIG_MAC80211_LEDS +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1921,24 +1921,8 @@ static void ieee80211_rx_mgmt_beacon(str + + rcu_read_unlock(); + +- /* +- * Whenever the AP announces the HT mode change that can be +- * 40MHz intolerant or etc., it would be safer to stop tx +- * queues before doing hw config to avoid buffer overflow. +- */ +- ieee80211_stop_queues_by_reason(&sdata->local->hw, +- IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); +- +- /* flush out all packets */ +- synchronize_net(); +- +- drv_flush(local, false); +- + changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, + bssid, ap_ht_cap_flags); +- +- ieee80211_wake_queues_by_reason(&sdata->local->hw, +- IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); + } + + /* Note: country IE parsing is done for us by cfg80211 */ +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -1613,7 +1613,8 @@ static void handle_irq_beacon(struct b43 + u32 cmd, beacon0_valid, beacon1_valid; + + if (!b43_is_mode(wl, NL80211_IFTYPE_AP) && +- !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) ++ !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) && ++ !b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) + return; + + /* This is the bottom half of the asynchronous beacon update. */