Skip to content

Commit 66b181b

Browse files
ryderlee1110nbd168
authored andcommitted
wifi: mt76: mt7915: enable .sta_set_txpwr support
This adds support for adjusting the Txpower level while pushing traffic to an associated station. The allowed range is from 0 to the maximum power of channel. Signed-off-by: Ryder Lee <[email protected]> Signed-off-by: Felix Fietkau <[email protected]>
1 parent bd2404d commit 66b181b

File tree

5 files changed

+137
-6
lines changed

5 files changed

+137
-6
lines changed

drivers/net/wireless/mediatek/mt76/mt7915/init.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
355355
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
356356
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
357357

358+
if (!is_mt7915(&dev->mt76))
359+
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
360+
358361
if (!mdev->dev->of_node ||
359362
!of_property_read_bool(mdev->dev->of_node,
360363
"mediatek,disable-radar-background"))

drivers/net/wireless/mediatek/mt76/mt7915/main.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,39 @@ static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,
11341134
mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
11351135
}
11361136

1137+
static int mt7915_sta_set_txpwr(struct ieee80211_hw *hw,
1138+
struct ieee80211_vif *vif,
1139+
struct ieee80211_sta *sta)
1140+
{
1141+
struct mt7915_phy *phy = mt7915_hw_phy(hw);
1142+
struct mt7915_dev *dev = mt7915_hw_dev(hw);
1143+
s16 txpower = sta->deflink.txpwr.power;
1144+
int ret;
1145+
1146+
if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC)
1147+
txpower = 0;
1148+
1149+
mutex_lock(&dev->mt76.mutex);
1150+
1151+
/* NOTE: temporarily use 0 as minimum limit, which is a
1152+
* global setting and will be applied to all stations.
1153+
*/
1154+
ret = mt7915_mcu_set_txpower_frame_min(phy, 0);
1155+
if (ret)
1156+
goto out;
1157+
1158+
/* This only applies to data frames while pushing traffic,
1159+
* whereas the management frames or other packets that are
1160+
* using fixed rate can be configured via TxD.
1161+
*/
1162+
ret = mt7915_mcu_set_txpower_frame(phy, vif, sta, txpower);
1163+
1164+
out:
1165+
mutex_unlock(&dev->mt76.mutex);
1166+
1167+
return ret;
1168+
}
1169+
11371170
static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {
11381171
"tx_ampdu_cnt",
11391172
"tx_stop_q_empty_cnt",
@@ -1499,6 +1532,7 @@ const struct ieee80211_ops mt7915_ops = {
14991532
.set_bitrate_mask = mt7915_set_bitrate_mask,
15001533
.set_coverage_class = mt7915_set_coverage_class,
15011534
.sta_statistics = mt7915_sta_statistics,
1535+
.sta_set_txpwr = mt7915_sta_set_txpwr,
15021536
.sta_set_4addr = mt7915_sta_set_4addr,
15031537
.sta_set_decap_offload = mt7915_sta_set_decap_offload,
15041538
.add_twt_setup = mt7915_mac_add_twt_setup,

drivers/net/wireless/mediatek/mt76/mt7915/mcu.c

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3105,6 +3105,88 @@ int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)
31053105
&req, sizeof(req), false);
31063106
}
31073107

3108+
int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower)
3109+
{
3110+
struct mt7915_dev *dev = phy->dev;
3111+
struct {
3112+
u8 format_id;
3113+
u8 rsv;
3114+
u8 band_idx;
3115+
s8 txpower_min;
3116+
} __packed req = {
3117+
.format_id = TX_POWER_LIMIT_FRAME_MIN,
3118+
.band_idx = phy->band_idx,
3119+
.txpower_min = txpower * 2, /* 0.5db */
3120+
};
3121+
3122+
return mt76_mcu_send_msg(&dev->mt76,
3123+
MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
3124+
sizeof(req), true);
3125+
}
3126+
3127+
int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
3128+
struct ieee80211_vif *vif,
3129+
struct ieee80211_sta *sta, s8 txpower)
3130+
{
3131+
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
3132+
struct mt7915_dev *dev = phy->dev;
3133+
struct mt76_phy *mphy = phy->mt76;
3134+
struct {
3135+
u8 format_id;
3136+
u8 rsv[3];
3137+
u8 band_idx;
3138+
s8 txpower_max;
3139+
__le16 wcid;
3140+
s8 txpower_offs[48];
3141+
} __packed req = {
3142+
.format_id = TX_POWER_LIMIT_FRAME,
3143+
.band_idx = phy->band_idx,
3144+
.txpower_max = DIV_ROUND_UP(mphy->txpower_cur, 2),
3145+
.wcid = cpu_to_le16(msta->wcid.idx),
3146+
};
3147+
int ret, n_chains = hweight8(mphy->antenna_mask);
3148+
s8 txpower_sku[MT7915_SKU_RATE_NUM];
3149+
3150+
ret = mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku));
3151+
if (ret)
3152+
return ret;
3153+
3154+
txpower = txpower * 2 - mt76_tx_power_nss_delta(n_chains);
3155+
if (txpower > mphy->txpower_cur || txpower < 0)
3156+
return -EINVAL;
3157+
3158+
if (txpower) {
3159+
u32 offs, len, i;
3160+
3161+
if (sta->deflink.ht_cap.ht_supported) {
3162+
const u8 *sku_len = mt7915_sku_group_len;
3163+
3164+
offs = sku_len[SKU_CCK] + sku_len[SKU_OFDM];
3165+
len = sku_len[SKU_HT_BW20] + sku_len[SKU_HT_BW40];
3166+
3167+
if (sta->deflink.vht_cap.vht_supported) {
3168+
offs += len;
3169+
len = sku_len[SKU_VHT_BW20] * 4;
3170+
3171+
if (sta->deflink.he_cap.has_he) {
3172+
offs += len + sku_len[SKU_HE_RU26] * 3;
3173+
len = sku_len[SKU_HE_RU242] * 4;
3174+
}
3175+
}
3176+
} else {
3177+
return -EINVAL;
3178+
}
3179+
3180+
for (i = 0; i < len; i++, offs++)
3181+
req.txpower_offs[i] =
3182+
DIV_ROUND_UP(txpower - txpower_sku[offs], 2);
3183+
}
3184+
3185+
return mt76_mcu_send_msg(&dev->mt76,
3186+
MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
3187+
sizeof(req), true);
3188+
}
3189+
31083190
int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
31093191
{
31103192
struct mt7915_dev *dev = phy->dev;
@@ -3116,7 +3198,7 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
31163198
u8 dbdc_idx;
31173199
s8 val[MT7915_SKU_RATE_NUM];
31183200
} __packed req = {
3119-
.format_id = 4,
3201+
.format_id = TX_POWER_LIMIT_TABLE,
31203202
.dbdc_idx = phy != &dev->phy,
31213203
};
31223204
struct mt76_power_limits limits_array;
@@ -3166,11 +3248,11 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
31663248
u8 band;
31673249
u8 _rsv;
31683250
} __packed req = {
3169-
.format_id = 7,
3251+
.format_id = TX_POWER_LIMIT_INFO,
31703252
.category = RATE_POWER_INFO,
31713253
.band = phy != &dev->phy,
31723254
};
3173-
s8 res[MT7915_SKU_RATE_NUM][2];
3255+
s8 txpower_sku[MT7915_SKU_RATE_NUM][2];
31743256
struct sk_buff *skb;
31753257
int ret, i;
31763258

@@ -3180,9 +3262,9 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
31803262
if (ret)
31813263
return ret;
31823264

3183-
memcpy(res, skb->data + 4, sizeof(res));
3265+
memcpy(txpower_sku, skb->data + 4, sizeof(txpower_sku));
31843266
for (i = 0; i < len; i++)
3185-
txpower[i] = res[i][req.band];
3267+
txpower[i] = txpower_sku[i][req.band_idx];
31863268

31873269
dev_kfree_skb(skb);
31883270

@@ -3220,7 +3302,7 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
32203302
u8 dbdc_idx;
32213303
u8 rsv;
32223304
} __packed req = {
3223-
.format_id = 0,
3305+
.format_id = TX_POWER_LIMIT_ENABLE,
32243306
.dbdc_idx = phy != &dev->phy,
32253307
.sku_enable = enable,
32263308
};

drivers/net/wireless/mediatek/mt76/mt7915/mcu.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,14 @@ enum {
419419
#define RATE_CFG_PHY_TYPE GENMASK(27, 24)
420420
#define RATE_CFG_HE_LTF GENMASK(31, 28)
421421

422+
enum {
423+
TX_POWER_LIMIT_ENABLE,
424+
TX_POWER_LIMIT_TABLE = 0x4,
425+
TX_POWER_LIMIT_INFO = 0x7,
426+
TX_POWER_LIMIT_FRAME = 0x11,
427+
TX_POWER_LIMIT_FRAME_MIN = 0x12,
428+
};
429+
422430
enum {
423431
SPR_ENABLE = 0x1,
424432
SPR_ENABLE_SD = 0x3,

drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,10 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band);
528528
int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable);
529529
int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy);
530530
int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len);
531+
int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower);
532+
int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
533+
struct ieee80211_vif *vif,
534+
struct ieee80211_sta *sta, s8 txpower);
531535
int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action);
532536
int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val);
533537
int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev,

0 commit comments

Comments
 (0)