mt76x2: add TPC support

add per-packet tx power adjustment support

Signed-off-by: Lorenzo Bianconi <[email protected]>
This commit is contained in:
Lorenzo Bianconi
2016-08-25 12:57:47 +02:00
committed by Felix Fietkau
parent 3d36d4b649
commit aa77eadf0e
6 changed files with 67 additions and 0 deletions
+1
View File
@@ -126,6 +126,7 @@ struct mt76_wcid {
__le16 tx_rate;
bool tx_rate_set;
u8 tx_rate_nss;
s8 max_txpwr_adj;
};
struct mt76_txq {
+4
View File
@@ -210,4 +210,8 @@ void mt76x2_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
void mt76x2_update_channel(struct mt76_dev *dev);
s8 mt76x3_tx_get_max_txpwr_adj(struct mt76x2_dev *dev,
const struct ieee80211_tx_rate *rate);
s8 mt76x2_tx_get_txpwr_adj(struct mt76x2_dev *dev, s8 txpwr, s8 max_txpwr_adj);
#endif
+7
View File
@@ -163,6 +163,7 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
u16 rate_ht_mask = MT76_SET(MT_RXWI_RATE_PHY, BIT(1) | BIT(2));
u16 txwi_flags = 0;
u8 nss;
s8 txpwr_adj, max_txpwr_adj;
memset(txwi, 0, sizeof(*txwi));
@@ -176,12 +177,18 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
spin_lock_bh(&dev->mt76.lock);
if (rate->idx < 0 || !rate->count) {
txwi->rate = wcid->tx_rate;
max_txpwr_adj = wcid->max_txpwr_adj;
nss = wcid->tx_rate_nss;
} else {
txwi->rate = mt76x2_mac_tx_rate_val(dev, rate, &nss);
max_txpwr_adj = mt76x3_tx_get_max_txpwr_adj(dev, rate);
}
spin_unlock_bh(&dev->mt76.lock);
txpwr_adj = mt76x2_tx_get_txpwr_adj(dev, dev->txpower_conf,
max_txpwr_adj);
txwi->ctl2 = MT76_SET(MT_TX_PWR_ADJ, txpwr_adj);
if (mt76xx_rev(dev) >= MT76XX_REV_E4)
txwi->txstream = 0x13;
else if (mt76xx_rev(dev) >= MT76XX_REV_E3 &&
+2
View File
@@ -108,6 +108,8 @@ struct mt76x2_rxwi {
#define MT_RATE_INDEX_VHT_IDX GENMASK(3, 0)
#define MT_RATE_INDEX_VHT_NSS GENMASK(5, 4)
#define MT_TX_PWR_ADJ GENMASK(3, 0)
enum mt76x2_phy_bandwith {
MT_PHY_BW_20,
MT_PHY_BW_40,
+1
View File
@@ -478,6 +478,7 @@ mt76x2_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
rate.idx = rates->rate[0].idx;
rate.flags = rates->rate[0].flags;
mt76x2_mac_wcid_set_rate(dev, &msta->wcid, &rate);
msta->wcid.max_txpwr_adj = mt76x3_tx_get_max_txpwr_adj(dev, &rate);
}
static void mt76x2_set_coverage_class(struct ieee80211_hw *hw,
+52
View File
@@ -58,6 +58,58 @@ void mt76x2_tx_complete(struct mt76x2_dev *dev, struct sk_buff *skb)
}
}
s8 mt76x3_tx_get_max_txpwr_adj(struct mt76x2_dev *dev,
const struct ieee80211_tx_rate *rate)
{
s8 max_txpwr;
if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
u8 mcs = ieee80211_rate_get_vht_mcs(rate);
if (mcs == 8 || mcs == 9) {
max_txpwr = dev->rate_power.vht[8];
} else {
u8 nss, idx;
nss = ieee80211_rate_get_vht_nss(rate);
idx = ((nss - 1) << 3) + mcs;
max_txpwr = dev->rate_power.ht[idx & 0xf];
}
} else if (rate->flags & IEEE80211_TX_RC_MCS) {
max_txpwr = dev->rate_power.ht[rate->idx & 0xf];
} else {
enum nl80211_band band = dev->mt76.chandef.chan->band;
if (band == NL80211_BAND_2GHZ) {
const struct ieee80211_rate *r;
struct wiphy *wiphy = mt76_hw(dev)->wiphy;
struct mt76_rate_power *rp = &dev->rate_power;
r = &wiphy->bands[band]->bitrates[rate->idx];
if (r->flags & IEEE80211_RATE_SHORT_PREAMBLE)
max_txpwr = rp->cck[r->hw_value & 0x3];
else
max_txpwr = rp->ofdm[r->hw_value & 0x7];
} else {
max_txpwr = dev->rate_power.ofdm[rate->idx & 0x7];
}
}
return max_txpwr;
}
s8 mt76x2_tx_get_txpwr_adj(struct mt76x2_dev *dev, s8 txpwr, s8 max_txpwr_adj)
{
txpwr = min_t(s8, txpwr, dev->txpower_conf);
txpwr -= (dev->target_power + dev->target_power_delta[0]);
txpwr = min_t(s8, txpwr, max_txpwr_adj);
if (txpwr >= 0)
return min_t(s8, txpwr, 7);
else
return (txpwr < -16) ? 8 : (txpwr + 32) / 2;
}
int mt76x2_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
struct sk_buff *skb, struct mt76_queue *q,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,