aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c23
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) {};
695void ath9k_ps_wakeup(struct ath_softc *sc); 696void ath9k_ps_wakeup(struct ath_softc *sc);
696void ath9k_ps_restore(struct ath_softc *sc); 697void ath9k_ps_restore(struct ath_softc *sc);
697 698
699u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
700
698void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 701void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
699int ath9k_wiphy_add(struct ath_softc *sc); 702int ath9k_wiphy_add(struct ath_softc *sc);
700int ath9k_wiphy_del(struct ath_wiphy *aphy); 703int 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
273enum ar5416_rates { 274enum 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
192struct ath9k_hw_capabilities { 193struct 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)
554static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) 554static 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
1509u8 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
1509static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) 1521static 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 }