diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_phy.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 23 |
9 files changed, 45 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 3161a5901a7a..4aecc10cb3a6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -3029,6 +3029,8 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, | |||
3029 | return le32_to_cpu(pBase->swreg); | 3029 | return le32_to_cpu(pBase->swreg); |
3030 | case EEP_PAPRD: | 3030 | case EEP_PAPRD: |
3031 | return !!(pBase->featureEnable & BIT(5)); | 3031 | return !!(pBase->featureEnable & BIT(5)); |
3032 | case EEP_CHAIN_MASK_REDUCE: | ||
3033 | return (pBase->miscConfiguration >> 0x3) & 0x1; | ||
3032 | default: | 3034 | default: |
3033 | return 0; | 3035 | return 0; |
3034 | } | 3036 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 656d8ce251a7..b34a9e91edd8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -487,7 +487,11 @@ void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) | |||
487 | break; | 487 | break; |
488 | } | 488 | } |
489 | 489 | ||
490 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); | 490 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) |
491 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); | ||
492 | else | ||
493 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); | ||
494 | |||
491 | if (tx == 0x5) { | 495 | if (tx == 0x5) { |
492 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | 496 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, |
493 | AR_PHY_SWAP_ALT_CHAIN); | 497 | AR_PHY_SWAP_ALT_CHAIN); |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 6f90acc5cca7..efba413561a4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -544,6 +544,7 @@ struct ath_ant_comb { | |||
544 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) | 544 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) |
545 | #define SC_OP_BT_SCAN BIT(13) | 545 | #define SC_OP_BT_SCAN BIT(13) |
546 | #define SC_OP_ANI_RUN BIT(14) | 546 | #define SC_OP_ANI_RUN BIT(14) |
547 | #define SC_OP_ENABLE_APM BIT(15) | ||
547 | 548 | ||
548 | /* Powersave flags */ | 549 | /* Powersave flags */ |
549 | #define PS_WAIT_FOR_BEACON BIT(0) | 550 | #define PS_WAIT_FOR_BEACON BIT(0) |
@@ -695,6 +696,8 @@ static inline void ath_ahb_exit(void) {}; | |||
695 | void ath9k_ps_wakeup(struct ath_softc *sc); | 696 | void ath9k_ps_wakeup(struct ath_softc *sc); |
696 | void ath9k_ps_restore(struct ath_softc *sc); | 697 | void ath9k_ps_restore(struct ath_softc *sc); |
697 | 698 | ||
699 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); | ||
700 | |||
698 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | 701 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
699 | int ath9k_wiphy_add(struct ath_softc *sc); | 702 | int ath9k_wiphy_add(struct ath_softc *sc); |
700 | int ath9k_wiphy_del(struct ath_wiphy *aphy); | 703 | int ath9k_wiphy_del(struct ath_wiphy *aphy); |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 30724a4e8bb2..47bedd82e9a9 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -103,7 +103,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
103 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); | 103 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); |
104 | series[0].Tries = 1; | 104 | series[0].Tries = 1; |
105 | series[0].Rate = rate; | 105 | series[0].Rate = rate; |
106 | series[0].ChSel = common->tx_chainmask; | 106 | series[0].ChSel = ath_txchainmask_reduction(sc, |
107 | common->tx_chainmask, series[0].Rate); | ||
107 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; | 108 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; |
108 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, | 109 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, |
109 | series, 4, 0); | 110 | series, 4, 0); |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 3c99830dab0c..7755fb996caa 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -268,6 +268,7 @@ enum eeprom_param { | |||
268 | EEP_PAPRD, | 268 | EEP_PAPRD, |
269 | EEP_MODAL_VER, | 269 | EEP_MODAL_VER, |
270 | EEP_ANT_DIV_CTL1, | 270 | EEP_ANT_DIV_CTL1, |
271 | EEP_CHAIN_MASK_REDUCE | ||
271 | }; | 272 | }; |
272 | 273 | ||
273 | enum ar5416_rates { | 274 | enum ar5416_rates { |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 883f6cc7b82c..b4396a9578e5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1974,6 +1974,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
1974 | if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) | 1974 | if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) |
1975 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; | 1975 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; |
1976 | } | 1976 | } |
1977 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
1978 | if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE)) | ||
1979 | pCap->hw_caps |= ATH9K_HW_CAP_APM; | ||
1980 | } | ||
1981 | |||
1982 | |||
1977 | 1983 | ||
1978 | return 0; | 1984 | return 0; |
1979 | } | 1985 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index cc8f3b9af71f..5fcfa48a45df 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -187,6 +187,7 @@ enum ath9k_hw_caps { | |||
187 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), | 187 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), |
188 | ATH9K_HW_CAP_2GHZ = BIT(13), | 188 | ATH9K_HW_CAP_2GHZ = BIT(13), |
189 | ATH9K_HW_CAP_5GHZ = BIT(14), | 189 | ATH9K_HW_CAP_5GHZ = BIT(14), |
190 | ATH9K_HW_CAP_APM = BIT(15), | ||
190 | }; | 191 | }; |
191 | 192 | ||
192 | struct ath9k_hw_capabilities { | 193 | struct ath9k_hw_capabilities { |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 50bdb5db23b4..df1bfcfeb734 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -554,9 +554,12 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht) | |||
554 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) | 554 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) |
555 | { | 555 | { |
556 | struct ath_node *an; | 556 | struct ath_node *an; |
557 | 557 | struct ath_hw *ah = sc->sc_ah; | |
558 | an = (struct ath_node *)sta->drv_priv; | 558 | an = (struct ath_node *)sta->drv_priv; |
559 | 559 | ||
560 | if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) | ||
561 | sc->sc_flags |= SC_OP_ENABLE_APM; | ||
562 | |||
560 | if (sc->sc_flags & SC_OP_TXAGGR) { | 563 | if (sc->sc_flags & SC_OP_TXAGGR) { |
561 | ath_tx_node_init(sc, an); | 564 | ath_tx_node_init(sc, an); |
562 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | 565 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 177a7b1de322..821d3679c6ff 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1506,6 +1506,18 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, | |||
1506 | return duration; | 1506 | return duration; |
1507 | } | 1507 | } |
1508 | 1508 | ||
1509 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) | ||
1510 | { | ||
1511 | struct ath_hw *ah = sc->sc_ah; | ||
1512 | struct ath9k_channel *curchan = ah->curchan; | ||
1513 | if ((sc->sc_flags & SC_OP_ENABLE_APM) && | ||
1514 | (curchan->channelFlags & CHANNEL_5GHZ) && | ||
1515 | (chainmask == 0x7) && (rate < 0x90)) | ||
1516 | return 0x3; | ||
1517 | else | ||
1518 | return chainmask; | ||
1519 | } | ||
1520 | |||
1509 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | 1521 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) |
1510 | { | 1522 | { |
1511 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1523 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -1546,7 +1558,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | |||
1546 | 1558 | ||
1547 | rix = rates[i].idx; | 1559 | rix = rates[i].idx; |
1548 | series[i].Tries = rates[i].count; | 1560 | series[i].Tries = rates[i].count; |
1549 | series[i].ChSel = common->tx_chainmask; | ||
1550 | 1561 | ||
1551 | if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || | 1562 | if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || |
1552 | (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { | 1563 | (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { |
@@ -1569,6 +1580,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | |||
1569 | if (rates[i].flags & IEEE80211_TX_RC_MCS) { | 1580 | if (rates[i].flags & IEEE80211_TX_RC_MCS) { |
1570 | /* MCS rates */ | 1581 | /* MCS rates */ |
1571 | series[i].Rate = rix | 0x80; | 1582 | series[i].Rate = rix | 0x80; |
1583 | series[i].ChSel = ath_txchainmask_reduction(sc, | ||
1584 | common->tx_chainmask, series[i].Rate); | ||
1572 | series[i].PktDuration = ath_pkt_duration(sc, rix, len, | 1585 | series[i].PktDuration = ath_pkt_duration(sc, rix, len, |
1573 | is_40, is_sgi, is_sp); | 1586 | is_40, is_sgi, is_sp); |
1574 | if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) | 1587 | if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) |
@@ -1576,7 +1589,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | |||
1576 | continue; | 1589 | continue; |
1577 | } | 1590 | } |
1578 | 1591 | ||
1579 | /* legcay rates */ | 1592 | /* legacy rates */ |
1580 | if ((tx_info->band == IEEE80211_BAND_2GHZ) && | 1593 | if ((tx_info->band == IEEE80211_BAND_2GHZ) && |
1581 | !(rate->flags & IEEE80211_RATE_ERP_G)) | 1594 | !(rate->flags & IEEE80211_RATE_ERP_G)) |
1582 | phy = WLAN_RC_PHY_CCK; | 1595 | phy = WLAN_RC_PHY_CCK; |
@@ -1592,6 +1605,12 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | |||
1592 | is_sp = false; | 1605 | is_sp = false; |
1593 | } | 1606 | } |
1594 | 1607 | ||
1608 | if (bf->bf_state.bfs_paprd) | ||
1609 | series[i].ChSel = common->tx_chainmask; | ||
1610 | else | ||
1611 | series[i].ChSel = ath_txchainmask_reduction(sc, | ||
1612 | common->tx_chainmask, series[i].Rate); | ||
1613 | |||
1595 | series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, | 1614 | series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, |
1596 | phy, rate->bitrate * 100, len, rix, is_sp); | 1615 | phy, rate->bitrate * 100, len, rix, is_sp); |
1597 | } | 1616 | } |