diff mbox series

[2/3] wifi: mt76: mt7915: enable .sta_set_txpwr support

Message ID c843e72587751adf0438f6e85de9e9c5b8323bf4.1668973479.git.ryder.lee@mediatek.com
State Superseded
Headers show
Series [1/3] wifi: mt76: mt7915: add basedband Txpower info into debugfs | expand

Commit Message

Ryder Lee Nov. 20, 2022, 7:51 p.m. UTC
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 <ryder.lee@mediatek.com>
---
 .../net/wireless/mediatek/mt76/mt7915/init.c  |  3 +
 .../net/wireless/mediatek/mt76/mt7915/main.c  | 33 +++++++
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 92 +++++++++++++++++--
 .../net/wireless/mediatek/mt76/mt7915/mcu.h   |  8 ++
 .../wireless/mediatek/mt76/mt7915/mt7915.h    |  4 +
 5 files changed, 134 insertions(+), 6 deletions(-)

Comments

Lorenzo Bianconi Nov. 20, 2022, 9:21 p.m. UTC | #1
> 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.

Very cool, iiuc the hw/fw is capable of adjusting tx power according to the trasmitted
frame, right? Is it possible to specify it on per-packet basis or just
per-station?

> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  .../net/wireless/mediatek/mt76/mt7915/init.c  |  3 +
>  .../net/wireless/mediatek/mt76/mt7915/main.c  | 33 +++++++
>  .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 92 +++++++++++++++++--
>  .../net/wireless/mediatek/mt76/mt7915/mcu.h   |  8 ++
>  .../wireless/mediatek/mt76/mt7915/mt7915.h    |  4 +
>  5 files changed, 134 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
> index b48c2ba9273d..79bd7bf93f33 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
> @@ -355,6 +355,9 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
>  	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
>  	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
>  
> +	if (!is_mt7915(&dev->mt76))
> +		wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
> +
>  	if (!mdev->dev->of_node ||
>  	    !of_property_read_bool(mdev->dev->of_node,
>  				   "mediatek,disable-radar-background"))
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> index a29cbdb47801..9792831090c7 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
> @@ -1126,6 +1126,38 @@ static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,
>  	mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
>  }
>  
> +static int mt7915_sta_set_txpwr(struct ieee80211_hw *hw,
> +				struct ieee80211_vif *vif,
> +				struct ieee80211_sta *sta)
> +{
> +	struct mt7915_phy *phy = mt7915_hw_phy(hw);
> +	struct mt7915_dev *dev = mt7915_hw_dev(hw);
> +	s16 txpower = sta->deflink.txpwr.power;
> +	int ret;
> +
> +	if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC)
> +		txpower = 0;
> +
> +	mutex_lock(&dev->mt76.mutex);
> +
> +	/* NOTE: temporarily use 0 as minimum limit, which is a
> +	 * global setting and will be applied to all stations.
> +	 */
> +	ret = mt7915_mcu_set_txpower_frame_min(phy, 0);
> +	if (ret)

we need to relase the lock here

Regards,
Lorenzo

> +		return ret;
> +
> +	/* This only applies to data frames while pushing traffic,
> +	 * whereas the management frames or other packets that are
> +	 * using fixed rate can be configured via TxD.
> +	 */
> +	ret = mt7915_mcu_set_txpower_frame(phy, vif, sta, txpower);
> +
> +	mutex_unlock(&dev->mt76.mutex);
> +
> +	return ret;
> +}
> +
>  static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {
>  	"tx_ampdu_cnt",
>  	"tx_stop_q_empty_cnt",
> @@ -1491,6 +1523,7 @@ const struct ieee80211_ops mt7915_ops = {
>  	.set_bitrate_mask = mt7915_set_bitrate_mask,
>  	.set_coverage_class = mt7915_set_coverage_class,
>  	.sta_statistics = mt7915_sta_statistics,
> +	.sta_set_txpwr = mt7915_sta_set_txpwr,
>  	.sta_set_4addr = mt7915_sta_set_4addr,
>  	.sta_set_decap_offload = mt7915_sta_set_decap_offload,
>  	.add_twt_setup = mt7915_mac_add_twt_setup,
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> index 3a0d97dad96f..d911512f31a6 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> @@ -3083,6 +3083,86 @@ int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)
>  				 &req, sizeof(req), false);
>  }
>  
> +int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower)
> +{
> +	struct mt7915_dev *dev = phy->dev;
> +	struct {
> +		u8 format_id;
> +		u8 rsv;
> +		u8 band_idx;
> +		s8 txpower_min;
> +	} __packed req = {
> +		.format_id = TX_POWER_LIMIT_FRAME_MIN,
> +		.band_idx = phy != &dev->phy,
> +		.txpower_min = txpower * 2, /* 0.5db */
> +	};
> +
> +	return mt76_mcu_send_msg(&dev->mt76,
> +				 MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
> +				 sizeof(req), true);
> +}
> +
> +int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
> +				 struct ieee80211_vif *vif,
> +				 struct ieee80211_sta *sta, s8 txpower)
> +{
> +	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
> +	struct mt7915_dev *dev = phy->dev;
> +	struct {
> +		u8 format_id;
> +		u8 rsv[3];
> +		u8 band_idx;
> +		s8 txpower_max;
> +		__le16 wcid;
> +		s8 txpower_offs[48];
> +	} __packed req = {
> +		.format_id = TX_POWER_LIMIT_FRAME,
> +		.band_idx = phy != &dev->phy,
> +		.txpower_max = DIV_ROUND_UP(phy->mt76->txpower_cur, 2),
> +		.wcid = cpu_to_le16(msta->wcid.idx),
> +	};
> +	int ret;
> +	s8 txpower_sku[MT7915_SKU_RATE_NUM];
> +
> +	ret = mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku));
> +	if (ret)
> +		return ret;
> +
> +	if (txpower > req.txpower_max || txpower < 0)
> +		return -EINVAL;
> +
> +	if (txpower) {
> +		u32 offs, len, i;
> +
> +		if (sta->deflink.ht_cap.ht_supported) {
> +			const u8 *sku_len = mt7915_sku_group_len;
> +
> +			offs = sku_len[SKU_CCK] + sku_len[SKU_OFDM];
> +			len = sku_len[SKU_HT_BW20] + sku_len[SKU_HT_BW40];
> +
> +			if (sta->deflink.vht_cap.vht_supported) {
> +				offs += len;
> +				len = sku_len[SKU_VHT_BW20] * 4;
> +
> +				if (sta->deflink.he_cap.has_he) {
> +					offs += len + sku_len[SKU_HE_RU26] * 3;
> +					len = sku_len[SKU_HE_RU242] * 4;
> +				}
> +			}
> +		} else {
> +			return -EINVAL;
> +		}
> +
> +		for (i = 0; i < len; i++, offs++)
> +			req.txpower_offs[i] =
> +				txpower - DIV_ROUND_UP(txpower_sku[offs], 2);
> +	}
> +
> +	return mt76_mcu_send_msg(&dev->mt76,
> +				 MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
> +				 sizeof(req), true);
> +}
> +
>  int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
>  {
>  	struct mt7915_dev *dev = phy->dev;
> @@ -3094,7 +3174,7 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
>  		u8 dbdc_idx;
>  		s8 val[MT7915_SKU_RATE_NUM];
>  	} __packed req = {
> -		.format_id = 4,
> +		.format_id = TX_POWER_LIMIT_TABLE,
>  		.dbdc_idx = phy != &dev->phy,
>  	};
>  	struct mt76_power_limits limits_array;
> @@ -3144,11 +3224,11 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
>  		u8 band;
>  		u8 _rsv;
>  	} __packed req = {
> -		.format_id = 7,
> +		.format_id = TX_POWER_LIMIT_INFO,
>  		.category = RATE_POWER_INFO,
>  		.band = phy != &dev->phy,
>  	};
> -	s8 res[MT7915_SKU_RATE_NUM][2];
> +	s8 txpower_sku[MT7915_SKU_RATE_NUM][2];
>  	struct sk_buff *skb;
>  	int ret, i;
>  
> @@ -3158,9 +3238,9 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
>  	if (ret)
>  		return ret;
>  
> -	memcpy(res, skb->data + 4, sizeof(res));
> +	memcpy(txpower_sku, skb->data + 4, sizeof(txpower_sku));
>  	for (i = 0; i < len; i++)
> -		txpower[i] = res[i][req.band];
> +		txpower[i] = txpower_sku[i][req.band_idx];
>  
>  	dev_kfree_skb(skb);
>  
> @@ -3198,7 +3278,7 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
>  		u8 dbdc_idx;
>  		u8 rsv;
>  	} __packed req = {
> -		.format_id = 0,
> +		.format_id = TX_POWER_LIMIT_ENABLE,
>  		.dbdc_idx = phy != &dev->phy,
>  		.sku_enable = enable,
>  	};
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> index 2fc09fd53777..46c517e50ae4 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> @@ -419,6 +419,14 @@ enum {
>  #define RATE_CFG_PHY_TYPE		GENMASK(27, 24)
>  #define RATE_CFG_HE_LTF			GENMASK(31, 28)
>  
> +enum {
> +	TX_POWER_LIMIT_ENABLE,
> +	TX_POWER_LIMIT_TABLE = 0x4,
> +	TX_POWER_LIMIT_INFO = 0x7,
> +	TX_POWER_LIMIT_FRAME = 0x11,
> +	TX_POWER_LIMIT_FRAME_MIN = 0x12,
> +};
> +
>  enum {
>  	SPR_ENABLE = 0x1,
>  	SPR_ENABLE_SD = 0x3,
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
> index 0bad78cf32c7..015c7190d79f 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
> @@ -526,6 +526,10 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band);
>  int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable);
>  int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy);
>  int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len);
> +int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower);
> +int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
> +				 struct ieee80211_vif *vif,
> +				 struct ieee80211_sta *sta, s8 txpower);
>  int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action);
>  int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val);
>  int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev,
> -- 
> 2.36.1
>
Ryder Lee Nov. 21, 2022, 1:14 a.m. UTC | #2
On Sun, 2022-11-20 at 22:21 +0100, Lorenzo Bianconi wrote:
> > 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.
> 
> Very cool, iiuc the hw/fw is capable of adjusting tx power according
> to the trasmitted
> frame, right? Is it possible to specify it on per-packet basis or
> just
> per-station?

Only for those fixed rate packets we can appy the offset through TxD,
whereas other data frames are hard to scale to per-packet basis but you
can continusly apply offsets for batch adjustment.

Ryder
diff mbox series

Patch

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index b48c2ba9273d..79bd7bf93f33 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -355,6 +355,9 @@  mt7915_init_wiphy(struct ieee80211_hw *hw)
 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
 
+	if (!is_mt7915(&dev->mt76))
+		wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
+
 	if (!mdev->dev->of_node ||
 	    !of_property_read_bool(mdev->dev->of_node,
 				   "mediatek,disable-radar-background"))
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index a29cbdb47801..9792831090c7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -1126,6 +1126,38 @@  static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,
 	mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
 }
 
+static int mt7915_sta_set_txpwr(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_sta *sta)
+{
+	struct mt7915_phy *phy = mt7915_hw_phy(hw);
+	struct mt7915_dev *dev = mt7915_hw_dev(hw);
+	s16 txpower = sta->deflink.txpwr.power;
+	int ret;
+
+	if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC)
+		txpower = 0;
+
+	mutex_lock(&dev->mt76.mutex);
+
+	/* NOTE: temporarily use 0 as minimum limit, which is a
+	 * global setting and will be applied to all stations.
+	 */
+	ret = mt7915_mcu_set_txpower_frame_min(phy, 0);
+	if (ret)
+		return ret;
+
+	/* This only applies to data frames while pushing traffic,
+	 * whereas the management frames or other packets that are
+	 * using fixed rate can be configured via TxD.
+	 */
+	ret = mt7915_mcu_set_txpower_frame(phy, vif, sta, txpower);
+
+	mutex_unlock(&dev->mt76.mutex);
+
+	return ret;
+}
+
 static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {
 	"tx_ampdu_cnt",
 	"tx_stop_q_empty_cnt",
@@ -1491,6 +1523,7 @@  const struct ieee80211_ops mt7915_ops = {
 	.set_bitrate_mask = mt7915_set_bitrate_mask,
 	.set_coverage_class = mt7915_set_coverage_class,
 	.sta_statistics = mt7915_sta_statistics,
+	.sta_set_txpwr = mt7915_sta_set_txpwr,
 	.sta_set_4addr = mt7915_sta_set_4addr,
 	.sta_set_decap_offload = mt7915_sta_set_decap_offload,
 	.add_twt_setup = mt7915_mac_add_twt_setup,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 3a0d97dad96f..d911512f31a6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -3083,6 +3083,86 @@  int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)
 				 &req, sizeof(req), false);
 }
 
+int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower)
+{
+	struct mt7915_dev *dev = phy->dev;
+	struct {
+		u8 format_id;
+		u8 rsv;
+		u8 band_idx;
+		s8 txpower_min;
+	} __packed req = {
+		.format_id = TX_POWER_LIMIT_FRAME_MIN,
+		.band_idx = phy != &dev->phy,
+		.txpower_min = txpower * 2, /* 0.5db */
+	};
+
+	return mt76_mcu_send_msg(&dev->mt76,
+				 MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
+				 sizeof(req), true);
+}
+
+int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
+				 struct ieee80211_vif *vif,
+				 struct ieee80211_sta *sta, s8 txpower)
+{
+	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+	struct mt7915_dev *dev = phy->dev;
+	struct {
+		u8 format_id;
+		u8 rsv[3];
+		u8 band_idx;
+		s8 txpower_max;
+		__le16 wcid;
+		s8 txpower_offs[48];
+	} __packed req = {
+		.format_id = TX_POWER_LIMIT_FRAME,
+		.band_idx = phy != &dev->phy,
+		.txpower_max = DIV_ROUND_UP(phy->mt76->txpower_cur, 2),
+		.wcid = cpu_to_le16(msta->wcid.idx),
+	};
+	int ret;
+	s8 txpower_sku[MT7915_SKU_RATE_NUM];
+
+	ret = mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku));
+	if (ret)
+		return ret;
+
+	if (txpower > req.txpower_max || txpower < 0)
+		return -EINVAL;
+
+	if (txpower) {
+		u32 offs, len, i;
+
+		if (sta->deflink.ht_cap.ht_supported) {
+			const u8 *sku_len = mt7915_sku_group_len;
+
+			offs = sku_len[SKU_CCK] + sku_len[SKU_OFDM];
+			len = sku_len[SKU_HT_BW20] + sku_len[SKU_HT_BW40];
+
+			if (sta->deflink.vht_cap.vht_supported) {
+				offs += len;
+				len = sku_len[SKU_VHT_BW20] * 4;
+
+				if (sta->deflink.he_cap.has_he) {
+					offs += len + sku_len[SKU_HE_RU26] * 3;
+					len = sku_len[SKU_HE_RU242] * 4;
+				}
+			}
+		} else {
+			return -EINVAL;
+		}
+
+		for (i = 0; i < len; i++, offs++)
+			req.txpower_offs[i] =
+				txpower - DIV_ROUND_UP(txpower_sku[offs], 2);
+	}
+
+	return mt76_mcu_send_msg(&dev->mt76,
+				 MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
+				 sizeof(req), true);
+}
+
 int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
 {
 	struct mt7915_dev *dev = phy->dev;
@@ -3094,7 +3174,7 @@  int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
 		u8 dbdc_idx;
 		s8 val[MT7915_SKU_RATE_NUM];
 	} __packed req = {
-		.format_id = 4,
+		.format_id = TX_POWER_LIMIT_TABLE,
 		.dbdc_idx = phy != &dev->phy,
 	};
 	struct mt76_power_limits limits_array;
@@ -3144,11 +3224,11 @@  int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
 		u8 band;
 		u8 _rsv;
 	} __packed req = {
-		.format_id = 7,
+		.format_id = TX_POWER_LIMIT_INFO,
 		.category = RATE_POWER_INFO,
 		.band = phy != &dev->phy,
 	};
-	s8 res[MT7915_SKU_RATE_NUM][2];
+	s8 txpower_sku[MT7915_SKU_RATE_NUM][2];
 	struct sk_buff *skb;
 	int ret, i;
 
@@ -3158,9 +3238,9 @@  int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
 	if (ret)
 		return ret;
 
-	memcpy(res, skb->data + 4, sizeof(res));
+	memcpy(txpower_sku, skb->data + 4, sizeof(txpower_sku));
 	for (i = 0; i < len; i++)
-		txpower[i] = res[i][req.band];
+		txpower[i] = txpower_sku[i][req.band_idx];
 
 	dev_kfree_skb(skb);
 
@@ -3198,7 +3278,7 @@  int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
 		u8 dbdc_idx;
 		u8 rsv;
 	} __packed req = {
-		.format_id = 0,
+		.format_id = TX_POWER_LIMIT_ENABLE,
 		.dbdc_idx = phy != &dev->phy,
 		.sku_enable = enable,
 	};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 2fc09fd53777..46c517e50ae4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -419,6 +419,14 @@  enum {
 #define RATE_CFG_PHY_TYPE		GENMASK(27, 24)
 #define RATE_CFG_HE_LTF			GENMASK(31, 28)
 
+enum {
+	TX_POWER_LIMIT_ENABLE,
+	TX_POWER_LIMIT_TABLE = 0x4,
+	TX_POWER_LIMIT_INFO = 0x7,
+	TX_POWER_LIMIT_FRAME = 0x11,
+	TX_POWER_LIMIT_FRAME_MIN = 0x12,
+};
+
 enum {
 	SPR_ENABLE = 0x1,
 	SPR_ENABLE_SD = 0x3,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 0bad78cf32c7..015c7190d79f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -526,6 +526,10 @@  int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band);
 int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable);
 int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy);
 int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len);
+int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower);
+int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
+				 struct ieee80211_vif *vif,
+				 struct ieee80211_sta *sta, s8 txpower);
 int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action);
 int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val);
 int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev,