Commit 8b537686 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by John W. Linville

ath9k: add TPC capability to TX descriptor path

Add TPC capability to TX descriptor path. Cap per-packet TX power according to
TX power per-rate tables. Currently TPC is supported just by AR9003 based chips
Signed-off-by: default avatarLorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 23f53dd3
...@@ -281,7 +281,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ...@@ -281,7 +281,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen) ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(i->txpower, AR_XmitPower0) | SM(i->txpower[0], AR_XmitPower0)
| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
...@@ -307,9 +307,9 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ...@@ -307,9 +307,9 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
| set11nRateFlags(i->rates, 3) | set11nRateFlags(i->rates, 3)
| SM(i->rtscts_rate, AR_RTSCTSRate); | SM(i->rtscts_rate, AR_RTSCTSRate);
ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower, AR_XmitPower1); ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower[1], AR_XmitPower1);
ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower, AR_XmitPower2); ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower[2], AR_XmitPower2);
ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower, AR_XmitPower3); ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower[3], AR_XmitPower3);
} }
static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
......
...@@ -101,7 +101,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ...@@ -101,7 +101,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen) ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(i->txpower, AR_XmitPower0) | SM(i->txpower[0], AR_XmitPower0)
| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0) | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
...@@ -152,9 +152,9 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ...@@ -152,9 +152,9 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding; ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
ACCESS_ONCE(ads->ctl20) = SM(i->txpower, AR_XmitPower1); ACCESS_ONCE(ads->ctl20) = SM(i->txpower[1], AR_XmitPower1);
ACCESS_ONCE(ads->ctl21) = SM(i->txpower, AR_XmitPower2); ACCESS_ONCE(ads->ctl21) = SM(i->txpower[2], AR_XmitPower2);
ACCESS_ONCE(ads->ctl22) = SM(i->txpower, AR_XmitPower3); ACCESS_ONCE(ads->ctl22) = SM(i->txpower[3], AR_XmitPower3);
} }
static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
......
...@@ -189,6 +189,7 @@ struct ath_frame_info { ...@@ -189,6 +189,7 @@ struct ath_frame_info {
u8 rtscts_rate; u8 rtscts_rate;
u8 retries : 7; u8 retries : 7;
u8 baw_tracked : 1; u8 baw_tracked : 1;
u8 tx_power;
}; };
struct ath_rxbuf { struct ath_rxbuf {
......
...@@ -78,7 +78,7 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif, ...@@ -78,7 +78,7 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
struct ath_tx_info info; struct ath_tx_info info;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
u8 chainmask = ah->txchainmask; u8 chainmask = ah->txchainmask;
u8 rate = 0; u8 i, rate = 0;
sband = &common->sbands[sc->cur_chandef.chan->band]; sband = &common->sbands[sc->cur_chandef.chan->band];
rate = sband->bitrates[rateidx].hw_value; rate = sband->bitrates[rateidx].hw_value;
...@@ -88,7 +88,8 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif, ...@@ -88,7 +88,8 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
info.pkt_len = skb->len + FCS_LEN; info.pkt_len = skb->len + FCS_LEN;
info.type = ATH9K_PKT_TYPE_BEACON; info.type = ATH9K_PKT_TYPE_BEACON;
info.txpower = MAX_RATE_POWER; for (i = 0; i < 4; i++)
info.txpower[i] = MAX_RATE_POWER;
info.keyix = ATH9K_TXKEYIX_INVALID; info.keyix = ATH9K_TXKEYIX_INVALID;
info.keytype = ATH9K_KEY_TYPE_CLEAR; info.keytype = ATH9K_KEY_TYPE_CLEAR;
info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_CLRDMASK; info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_CLRDMASK;
......
...@@ -704,7 +704,7 @@ struct ath_tx_info { ...@@ -704,7 +704,7 @@ struct ath_tx_info {
enum ath9k_pkt_type type; enum ath9k_pkt_type type;
enum ath9k_key_type keytype; enum ath9k_key_type keytype;
u8 keyix; u8 keyix;
u8 txpower; u8 txpower[4];
}; };
struct ath_hw; struct ath_hw;
......
...@@ -1096,6 +1096,37 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop) ...@@ -1096,6 +1096,37 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop)
} }
} }
static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
u8 rateidx)
{
u8 max_power;
struct ath_hw *ah = sc->sc_ah;
if (sc->tx99_state)
return MAX_RATE_POWER;
if (!AR_SREV_9300_20_OR_LATER(ah)) {
/* ar9002 is not sipported for the moment */
return MAX_RATE_POWER;
}
if (!bf->bf_state.bfs_paprd) {
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ath_frame_info *fi = get_frame_info(skb);
if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC))
max_power = min(ah->tx_power_stbc[rateidx],
fi->tx_power);
else
max_power = min(ah->tx_power[rateidx], fi->tx_power);
} else {
max_power = ah->paprd_training_power;
}
return max_power;
}
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_info *info, int len, bool rts) struct ath_tx_info *info, int len, bool rts)
{ {
...@@ -1166,6 +1197,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, ...@@ -1166,6 +1197,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
is_40, is_sgi, is_sp); is_40, is_sgi, is_sp);
if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC; info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix);
continue; continue;
} }
...@@ -1193,6 +1226,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, ...@@ -1193,6 +1226,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
phy, rate->bitrate * 100, len, rix, is_sp); phy, rate->bitrate * 100, len, rix, is_sp);
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix);
} }
/* For AR5416 - RTS cannot be followed by a frame larger than 8K */ /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
...@@ -1239,7 +1274,6 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, ...@@ -1239,7 +1274,6 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
info.is_first = true; info.is_first = true;
info.is_last = true; info.is_last = true;
info.txpower = MAX_RATE_POWER;
info.qcu = txq->axq_qnum; info.qcu = txq->axq_qnum;
while (bf) { while (bf) {
...@@ -2063,6 +2097,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, ...@@ -2063,6 +2097,7 @@ static void setup_frame_info(struct ieee80211_hw *hw,
fi->keyix = ATH9K_TXKEYIX_INVALID; fi->keyix = ATH9K_TXKEYIX_INVALID;
fi->keytype = keytype; fi->keytype = keytype;
fi->framelen = framelen; fi->framelen = framelen;
fi->tx_power = MAX_RATE_POWER;
if (!rate) if (!rate)
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment