blob: f1c18904b44f2c942423453c70cc2a519e3318a7 [file] [log] [blame]
From 456a6bddcbec9ba8c18648735327542b837dae0d Mon Sep 17 00:00:00 2001
From: Allen Ye <allen.ye@mediatek.com>
Date: Thu, 25 Jan 2024 10:57:08 +0800
Subject: [PATCH 2025/2032] mtk: wifi: mt76: mt7996: Porting wifi6 txpower fix
to eagle
Refactor txpower flow.
1. Fix wrong bbp CR address
2. Ignore RegDB power limit when we have single sku table. And dump more informaiton in debugfs.
3. Refactor get_txpower ops flow, we only consider CCK and OFDM power value as maximum.
4. Remove sku_disable due to SQC is over and default enable both sku tables.
Fix wrong power value when user set limit close to path table limit.
---
eeprom.c | 20 ++++----
mt7996/init.c | 14 ++++-
mt7996/main.c | 11 ++--
mt7996/mcu.c | 41 ++++++++++++---
mt7996/mt7996.h | 3 ++
mt7996/mtk_debugfs.c | 120 ++++++++++++++++++++++++++++---------------
mt7996/regs.h | 10 ++--
7 files changed, 149 insertions(+), 70 deletions(-)
diff --git a/eeprom.c b/eeprom.c
index adb87924..57b9b769 100644
--- a/eeprom.c
+++ b/eeprom.c
@@ -336,9 +336,10 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data,
static void
mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
const __be32 *data, size_t len, s8 target_power,
- s8 nss_delta, s8 *max_power)
+ s8 nss_delta)
{
int i, cur;
+ s8 max_power = -128;
if (!data)
return;
@@ -350,7 +351,7 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
break;
mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1,
- target_power, nss_delta, max_power);
+ target_power, nss_delta, &max_power);
if (--cur > 0)
continue;
@@ -433,17 +434,17 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
val = mt76_get_of_array(np, "rates-mcs", &len, mcs_rates + 1);
mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
ARRAY_SIZE(dest->mcs), val, len,
- target_power, txs_delta, &max_power);
+ target_power, txs_delta);
val = mt76_get_of_array(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1);
mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
ARRAY_SIZE(dest->ru), val, len,
- target_power, txs_delta, &max_power);
+ target_power, txs_delta);
val = mt76_get_of_array(np, "rates-eht", &len, ARRAY_SIZE(dest->eht[0]) + 1);
mt76_apply_multi_array_limit(dest->eht[0], ARRAY_SIZE(dest->eht[0]),
ARRAY_SIZE(dest->eht), val, len,
- target_power, txs_delta, &max_power);
+ target_power, txs_delta);
if (dest_path == NULL)
return max_power;
@@ -465,17 +466,14 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
val = mt76_get_of_array(np, "paths-ru", &len, ARRAY_SIZE(dest_path->ru[0]) + 1);
mt76_apply_multi_array_limit(dest_path->ru[0], ARRAY_SIZE(dest_path->ru[0]),
ARRAY_SIZE(dest_path->ru), val, len,
- target_power_combine, txs_delta, &max_power_backoff);
+ target_power_combine, txs_delta);
val = mt76_get_of_array(np, "paths-ru-bf", &len, ARRAY_SIZE(dest_path->ru_bf[0]) + 1);
mt76_apply_multi_array_limit(dest_path->ru_bf[0], ARRAY_SIZE(dest_path->ru_bf[0]),
ARRAY_SIZE(dest_path->ru_bf), val, len,
- target_power_combine, txs_delta, &max_power_backoff);
+ target_power_combine, txs_delta);
- if (max_power_backoff == target_power_combine)
- return max_power;
-
- return max_power_backoff;
+ return max_power;
}
EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits);
diff --git a/mt7996/init.c b/mt7996/init.c
index 85fedca6..bc8cfdbd 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
@@ -296,7 +296,11 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy,
int pwr_delta = mt7996_eeprom_get_power_delta(dev, sband->band);
struct mt76_power_limits limits;
struct mt76_power_path_limits limits_path;
+ struct device_node *np;
+ phy->sku_limit_en = true;
+ phy->sku_path_en = true;
+ np = mt76_find_power_limits_node(&dev->mt76);
for (i = 0; i < sband->n_channels; i++) {
struct ieee80211_channel *chan = &sband->channels[i];
int target_power = mt7996_eeprom_get_target_power(dev, chan);
@@ -306,10 +310,16 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy,
&limits,
&limits_path,
target_power);
+ if (!limits_path.ofdm[0])
+ phy->sku_path_en = false;
+
target_power += nss_delta;
target_power = DIV_ROUND_UP(target_power, 2);
- chan->max_power = min_t(int, chan->max_reg_power,
- target_power);
+ if (!np)
+ chan->max_power = min_t(int, chan->max_reg_power,
+ target_power);
+ else
+ chan->max_power = target_power;
chan->orig_mpwr = target_power;
}
}
diff --git a/mt7996/main.c b/mt7996/main.c
index 91c06cfb..ca8e6125 100644
--- a/mt7996/main.c
+++ b/mt7996/main.c
@@ -84,11 +84,16 @@ int mt7996_run(struct ieee80211_hw *hw)
phy->sr_enable = true;
phy->enhanced_sr_enable = true;
phy->thermal_protection_enable = true;
-
ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL,
- !dev->dbg.sku_disable);
+ dev->dbg.sku_disable ? 0 : phy->sku_limit_en);
+
+ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL,
+ dev->dbg.sku_disable ? 0 : phy->sku_path_en);
#else
- ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL, true);
+ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL,
+ phy->sku_limit_en);
+ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL,
+ phy->sku_path_en);
#endif
if (ret)
goto out;
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
index 6405c2fa..52651693 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -5126,6 +5126,27 @@ int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id)
sizeof(req), true);
}
+static void
+mt7996_update_max_txpower_cur(struct mt7996_phy *phy, int tx_power)
+{
+ struct mt76_phy *mphy = phy->mt76;
+ struct ieee80211_channel *chan = mphy->main_chan;
+ int e2p_power_limit = 0;
+
+ if (chan == NULL) {
+ mphy->txpower_cur = tx_power;
+ return;
+ }
+
+ e2p_power_limit = mt7996_eeprom_get_target_power(phy->dev, chan);
+ e2p_power_limit += mt7996_eeprom_get_power_delta(phy->dev, chan->band);
+
+ if (phy->sku_limit_en)
+ mphy->txpower_cur = min_t(int, e2p_power_limit, tx_power);
+ else
+ mphy->txpower_cur = e2p_power_limit;
+}
+
int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
{
#define TX_POWER_LIMIT_TABLE_RATE 0
@@ -5151,12 +5172,20 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
struct mt76_power_limits la = {};
struct mt76_power_path_limits la_path = {};
struct sk_buff *skb;
- int i, ret, tx_power;
+ int i, ret, txpower_limit;
+
+ if (hw->conf.power_level == INT_MIN)
+ hw->conf.power_level = 127;
+ txpower_limit = mt7996_get_power_bound(phy, hw->conf.power_level);
- tx_power = mt7996_get_power_bound(phy, hw->conf.power_level);
- tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
- &la, &la_path, tx_power);
- mphy->txpower_cur = tx_power;
+ if (phy->sku_limit_en) {
+ txpower_limit = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
+ &la, &la_path, txpower_limit);
+ mt7996_update_max_txpower_cur(phy, txpower_limit);
+ } else {
+ mt7996_update_max_txpower_cur(phy, txpower_limit);
+ return 0;
+ }
skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
sizeof(req) + MT7996_SKU_PATH_NUM);
@@ -5192,7 +5221,7 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
return ret;
/* only set per-path power table when it's configured */
- if (!la_path.ofdm[0])
+ if (!phy->sku_path_en)
return 0;
skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
index b5673bdd..f1308112 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
@@ -461,6 +461,9 @@ struct mt7996_phy {
u8 muru_onoff;
+ bool sku_limit_en;
+ bool sku_path_en;
+
#ifdef CONFIG_NL80211_TESTMODE
struct {
u32 *reg_backup;
diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
index 25c21f37..3f82b58c 100644
--- a/mt7996/mtk_debugfs.c
+++ b/mt7996/mtk_debugfs.c
@@ -2454,6 +2454,7 @@ mt7996_get_txpower_info(struct file *file, char __user *user_buf,
struct mt7996_phy *phy = file->private_data;
struct mt7996_mcu_txpower_event *event;
struct txpower_basic_info *basic_info;
+ struct device_node *np;
static const size_t size = 2048;
int len = 0;
ssize_t ret;
@@ -2510,7 +2511,10 @@ mt7996_get_txpower_info(struct file *file, char __user *user_buf,
len += scnprintf(buf + len, size - len,
" Theraml Compensation Value: %d\n",
basic_info->thermal_compensate_value);
-
+ np = mt76_find_power_limits_node(phy->mt76->dev);
+ len += scnprintf(buf + len, size - len,
+ " RegDB: %s\n",
+ !np ? "enable" : "disable");
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
out:
@@ -2526,9 +2530,9 @@ static const struct file_operations mt7996_txpower_info_fops = {
.llseek = default_llseek,
};
-#define mt7996_txpower_puts(rate) \
+#define mt7996_txpower_puts(rate, _len) \
({ \
- len += scnprintf(buf + len, size - len, "%-21s:", #rate " (TMAC)"); \
+ len += scnprintf(buf + len, size - len, "%-*s:", _len, #rate " (TMAC)"); \
for (i = 0; i < mt7996_sku_group_len[SKU_##rate]; i++, offs++) \
len += scnprintf(buf + len, size - len, " %6d", \
event->phy_rate_info.frame_power[offs][band_idx]); \
@@ -2542,9 +2546,15 @@ mt7996_get_txpower_sku(struct file *file, char __user *user_buf,
struct mt7996_phy *phy = file->private_data;
struct mt7996_dev *dev = phy->dev;
struct mt7996_mcu_txpower_event *event;
+ struct ieee80211_channel *chan = phy->mt76->chandef.chan;
+ struct ieee80211_supported_band sband;
u8 band_idx = phy->mt76->band_idx;
static const size_t size = 5120;
int i, offs = 0, len = 0;
+ u32 target_power = 0;
+ int n_chains = hweight16(phy->mt76->chainmask);
+ int nss_delta = mt76_tx_power_nss_delta(n_chains);
+ int pwr_delta;
ssize_t ret;
char *buf;
u32 reg;
@@ -2566,41 +2576,45 @@ mt7996_get_txpower_sku(struct file *file, char __user *user_buf,
band_idx, phy->mt76->chandef.chan->hw_value);
len += scnprintf(buf + len, size - len, "%-21s %6s %6s %6s %6s\n",
" ", "1m", "2m", "5m", "11m");
- mt7996_txpower_puts(CCK);
+ mt7996_txpower_puts(CCK, 21);
len += scnprintf(buf + len, size - len,
"%-21s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "6m", "9m", "12m", "18m", "24m", "36m", "48m",
"54m");
- mt7996_txpower_puts(OFDM);
+ mt7996_txpower_puts(OFDM, 21);
len += scnprintf(buf + len, size - len,
"%-21s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4",
"mcs5", "mcs6", "mcs7");
- mt7996_txpower_puts(HT20);
+ mt7996_txpower_puts(HT20, 21);
len += scnprintf(buf + len, size - len,
"%-21s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
"mcs6", "mcs7", "mcs32");
- mt7996_txpower_puts(HT40);
+ mt7996_txpower_puts(HT40, 21);
len += scnprintf(buf + len, size - len,
"%-21s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
"mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
- mt7996_txpower_puts(VHT20);
- mt7996_txpower_puts(VHT40);
- mt7996_txpower_puts(VHT80);
- mt7996_txpower_puts(VHT160);
- mt7996_txpower_puts(HE26);
- mt7996_txpower_puts(HE52);
- mt7996_txpower_puts(HE106);
- mt7996_txpower_puts(HE242);
- mt7996_txpower_puts(HE484);
- mt7996_txpower_puts(HE996);
- mt7996_txpower_puts(HE2x996);
+ mt7996_txpower_puts(VHT20, 21);
+ mt7996_txpower_puts(VHT40, 21);
+ mt7996_txpower_puts(VHT80, 21);
+ mt7996_txpower_puts(VHT160, 21);
+ mt7996_txpower_puts(HE26, 21);
+ mt7996_txpower_puts(HE52, 21);
+ mt7996_txpower_puts(HE106, 21);
+ len += scnprintf(buf + len, size - len, "BW20/");
+ mt7996_txpower_puts(HE242, 16);
+ len += scnprintf(buf + len, size - len, "BW40/");
+ mt7996_txpower_puts(HE484, 16);
+ len += scnprintf(buf + len, size - len, "BW80/");
+ mt7996_txpower_puts(HE996, 16);
+ len += scnprintf(buf + len, size - len, "BW160/");
+ mt7996_txpower_puts(HE2x996, 15);
len += scnprintf(buf + len, size - len,
"%-21s %6s %6s %6s %6s %6s %6s %6s %6s ",
@@ -2608,22 +2622,27 @@ mt7996_get_txpower_sku(struct file *file, char __user *user_buf,
len += scnprintf(buf + len, size - len,
"%6s %6s %6s %6s %6s %6s %6s %6s\n",
"mcs8", "mcs9", "mcs10", "mcs11", "mcs12", "mcs13", "mcs14", "mcs15");
- mt7996_txpower_puts(EHT26);
- mt7996_txpower_puts(EHT52);
- mt7996_txpower_puts(EHT106);
- mt7996_txpower_puts(EHT242);
- mt7996_txpower_puts(EHT484);
- mt7996_txpower_puts(EHT996);
- mt7996_txpower_puts(EHT2x996);
- mt7996_txpower_puts(EHT4x996);
- mt7996_txpower_puts(EHT26_52);
- mt7996_txpower_puts(EHT26_106);
- mt7996_txpower_puts(EHT484_242);
- mt7996_txpower_puts(EHT996_484);
- mt7996_txpower_puts(EHT996_484_242);
- mt7996_txpower_puts(EHT2x996_484);
- mt7996_txpower_puts(EHT3x996);
- mt7996_txpower_puts(EHT3x996_484);
+ mt7996_txpower_puts(EHT26, 21);
+ mt7996_txpower_puts(EHT52, 21);
+ mt7996_txpower_puts(EHT106, 21);
+ len += scnprintf(buf + len, size - len, "BW20/");
+ mt7996_txpower_puts(EHT242, 16);
+ len += scnprintf(buf + len, size - len, "BW40/");
+ mt7996_txpower_puts(EHT484, 16);
+ len += scnprintf(buf + len, size - len, "BW80/");
+ mt7996_txpower_puts(EHT996, 16);
+ len += scnprintf(buf + len, size - len, "BW160/");
+ mt7996_txpower_puts(EHT2x996, 15);
+ len += scnprintf(buf + len, size - len, "BW320/");
+ mt7996_txpower_puts(EHT4x996, 15);
+ mt7996_txpower_puts(EHT26_52, 21);
+ mt7996_txpower_puts(EHT26_106, 21);
+ mt7996_txpower_puts(EHT484_242, 21);
+ mt7996_txpower_puts(EHT996_484, 21);
+ mt7996_txpower_puts(EHT996_484_242, 21);
+ mt7996_txpower_puts(EHT2x996_484, 21);
+ mt7996_txpower_puts(EHT3x996, 21);
+ mt7996_txpower_puts(EHT3x996_484, 21);
len += scnprintf(buf + len, size - len, "\nePA Gain: %d\n",
event->phy_rate_info.epa_gain);
@@ -2632,16 +2651,33 @@ mt7996_get_txpower_sku(struct file *file, char __user *user_buf,
len += scnprintf(buf + len, size - len, "Min Power Bound: %d\n",
event->phy_rate_info.min_power_bound);
- reg = MT_WF_PHYDFE_BAND_TPC_CTRL_STAT0(band_idx);
+ reg = MT_WF_PHYDFE_TSSI_TXCTRL01(band_idx);
len += scnprintf(buf + len, size - len,
- "BBP TX Power (target power from TMAC) : %6ld [0.5 dBm]\n",
- mt76_get_field(dev, reg, MT_WF_PHY_TPC_POWER_TMAC));
+ "\nBBP TX Power (target power from TMAC) : %6ld [0.5 dBm]\n",
+ mt76_get_field(dev, reg, MT_WF_PHYDFE_TSSI_TXCTRL_POWER_TMAC));
len += scnprintf(buf + len, size - len,
- "BBP TX Power (target power from RMAC) : %6ld [0.5 dBm]\n",
- mt76_get_field(dev, reg, MT_WF_PHY_TPC_POWER_RMAC));
+ "RegDB maximum power:\t%d [dBm]\n",
+ chan->max_reg_power);
+
+ if (chan->band == NL80211_BAND_2GHZ)
+ sband = phy->mt76->sband_2g.sband;
+ else if (chan->band == NL80211_BAND_5GHZ)
+ sband = phy->mt76->sband_5g.sband;
+ else if (chan->band == NL80211_BAND_6GHZ)
+ sband = phy->mt76->sband_6g.sband;
+
+ pwr_delta = mt7996_eeprom_get_power_delta(dev, sband.band);
+
+ target_power = max_t(u32, target_power, mt7996_eeprom_get_target_power(dev, chan));
+ target_power += pwr_delta + nss_delta;
+ target_power = DIV_ROUND_UP(target_power, 2);
+ len += scnprintf(buf + len, size - len,
+ "eeprom maximum power:\t%d [dBm]\n",
+ target_power);
+
len += scnprintf(buf + len, size - len,
- "BBP TX Power (TSSI module power input) : %6ld [0.5 dBm]\n",
- mt76_get_field(dev, reg, MT_WF_PHY_TPC_POWER_TSSI));
+ "nss_delta:\t%d [0.5 dBm]\n",
+ nss_delta);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
@@ -2660,7 +2696,7 @@ static const struct file_operations mt7996_txpower_sku_fops = {
#define mt7996_txpower_path_puts(rate, arr_length) \
({ \
- len += scnprintf(buf + len, size - len, "%-23s:", #rate " (TMAC)"); \
+ len += scnprintf(buf + len, size - len, "%23s:", #rate " (TMAC)"); \
for (i = 0; i < arr_length; i++, offs++) \
len += scnprintf(buf + len, size - len, " %4d", \
event->backoff_table_info.frame_power[offs]); \
diff --git a/mt7996/regs.h b/mt7996/regs.h
index 050637c1..a0e4b3e1 100644
--- a/mt7996/regs.h
+++ b/mt7996/regs.h
@@ -718,6 +718,10 @@ enum offs_rev {
((_wf) << 16) + (ofs))
#define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000)
+/* PHYDFE CTRL */
+#define MT_WF_PHYDFE_TSSI_TXCTRL01(_band) MT_WF_PHYRX_CSD(_band, 0, 0xc718)
+#define MT_WF_PHYDFE_TSSI_TXCTRL_POWER_TMAC GENMASK(31, 24)
+
/* PHY CTRL */
#define MT_WF_PHY_BAND_BASE 0x83080000
#define MT_WF_PHY_BAND(_band, ofs) (MT_WF_PHY_BAND_BASE + \
@@ -735,12 +739,6 @@ enum offs_rev {
#define MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN GENMASK(2, 0)
#define MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN GENMASK(11, 9)
-/* PHYDFE CTRL */
-#define MT_WF_PHYDFE_BAND_TPC_CTRL_STAT0(_phy) MT_WF_PHY_BAND(_phy, 0xe7a0)
-#define MT_WF_PHY_TPC_POWER_TMAC GENMASK(15, 8)
-#define MT_WF_PHY_TPC_POWER_RMAC GENMASK(23, 16)
-#define MT_WF_PHY_TPC_POWER_TSSI GENMASK(31, 24)
-
/* PHYRX CSD BAND */
#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHY_BAND(_band, 0x8230)
#define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18)
--
2.18.0