developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 1 | From bfa596387e89377dec2121b5548b44b419463fb0 Mon Sep 17 00:00:00 2001 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 2 | From: Allen Ye <allen.ye@mediatek.com> |
| 3 | Date: Fri, 24 Mar 2023 23:35:30 +0800 |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 4 | Subject: [PATCH 031/199] mtk: mt76: mt7996: add txpower support |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 5 | |
| 6 | Add single sku and default enable sku. |
| 7 | |
| 8 | mtk: wifi: mt76: mt7996: Porting wifi6 txpower fix to eagle |
| 9 | |
| 10 | Refactor txpower flow. |
| 11 | 1. Fix wrong bbp CR address |
| 12 | 2. Ignore RegDB power limit when we have single sku table. And dump more informaiton in debugfs. |
| 13 | 3. Refactor get_txpower ops flow, we only consider CCK and OFDM power value as maximum. |
| 14 | 4. Remove sku_disable due to SQC is over and default enable both sku tables. |
| 15 | |
| 16 | Fix wrong power value when user set limit close to path table limit. |
| 17 | |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 18 | Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com> |
| 19 | Signed-off-by: Allen Ye <allen.ye@mediatek.com> |
| 20 | --- |
| 21 | eeprom.c | 54 ++++++- |
| 22 | mt76.h | 9 ++ |
| 23 | mt76_connac_mcu.c | 2 +- |
| 24 | mt7996/eeprom.c | 34 ++++ |
| 25 | mt7996/eeprom.h | 42 +++++ |
| 26 | mt7996/init.c | 16 +- |
| 27 | mt7996/main.c | 15 ++ |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 28 | mt7996/mcu.c | 69 +++++++- |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 29 | mt7996/mcu.h | 2 + |
| 30 | mt7996/mt7996.h | 4 + |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 31 | mt7996/mtk_debugfs.c | 363 +++++++++++++++++++++++++++++++++++++++++++ |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 32 | mt7996/mtk_mcu.c | 23 +++ |
| 33 | mt7996/mtk_mcu.h | 92 +++++++++++ |
| 34 | mt7996/regs.h | 27 ++-- |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 35 | 14 files changed, 725 insertions(+), 27 deletions(-) |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 36 | |
| 37 | diff --git a/eeprom.c b/eeprom.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 38 | index a0047d79..11efe293 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 39 | --- a/eeprom.c |
| 40 | +++ b/eeprom.c |
| 41 | @@ -305,9 +305,10 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data, |
| 42 | static void |
| 43 | mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num, |
| 44 | const __be32 *data, size_t len, s8 target_power, |
| 45 | - s8 nss_delta, s8 *max_power) |
| 46 | + s8 nss_delta) |
| 47 | { |
| 48 | int i, cur; |
| 49 | + s8 max_power = -128; |
| 50 | |
| 51 | if (!data) |
| 52 | return; |
| 53 | @@ -319,7 +320,7 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num, |
| 54 | break; |
| 55 | |
| 56 | mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1, |
| 57 | - target_power, nss_delta, max_power); |
| 58 | + target_power, nss_delta, &max_power); |
| 59 | if (--cur > 0) |
| 60 | continue; |
| 61 | |
| 62 | @@ -335,6 +336,7 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num, |
| 63 | s8 mt76_get_rate_power_limits(struct mt76_phy *phy, |
| 64 | struct ieee80211_channel *chan, |
| 65 | struct mt76_power_limits *dest, |
| 66 | + struct mt76_power_path_limits *dest_path, |
| 67 | s8 target_power) |
| 68 | { |
| 69 | struct mt76_dev *dev = phy->dev; |
| 70 | @@ -342,16 +344,20 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, |
| 71 | const __be32 *val; |
| 72 | char name[16]; |
| 73 | u32 mcs_rates = dev->drv->mcs_rates; |
| 74 | - u32 ru_rates = ARRAY_SIZE(dest->ru[0]); |
| 75 | char band; |
| 76 | size_t len; |
| 77 | - s8 max_power = 0; |
| 78 | + s8 max_power = -127; |
| 79 | + s8 max_power_backoff = -127; |
| 80 | s8 txs_delta; |
| 81 | + int n_chains = hweight16(phy->chainmask); |
| 82 | + s8 target_power_combine = target_power + mt76_tx_power_nss_delta(n_chains); |
| 83 | |
| 84 | if (!mcs_rates) |
| 85 | - mcs_rates = 10; |
| 86 | + mcs_rates = 12; |
| 87 | |
| 88 | memset(dest, target_power, sizeof(*dest)); |
| 89 | + if (dest_path != NULL) |
| 90 | + memset(dest_path, 0, sizeof(*dest_path)); |
| 91 | |
| 92 | if (!IS_ENABLED(CONFIG_OF)) |
| 93 | return target_power; |
| 94 | @@ -397,12 +403,44 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, |
| 95 | val = mt76_get_of_array(np, "rates-mcs", &len, mcs_rates + 1); |
| 96 | mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]), |
| 97 | ARRAY_SIZE(dest->mcs), val, len, |
| 98 | - target_power, txs_delta, &max_power); |
| 99 | + target_power, txs_delta); |
| 100 | |
| 101 | - val = mt76_get_of_array(np, "rates-ru", &len, ru_rates + 1); |
| 102 | + val = mt76_get_of_array(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1); |
| 103 | mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]), |
| 104 | ARRAY_SIZE(dest->ru), val, len, |
| 105 | - target_power, txs_delta, &max_power); |
| 106 | + target_power, txs_delta); |
| 107 | + |
| 108 | + val = mt76_get_of_array(np, "rates-eht", &len, ARRAY_SIZE(dest->eht[0]) + 1); |
| 109 | + mt76_apply_multi_array_limit(dest->eht[0], ARRAY_SIZE(dest->eht[0]), |
| 110 | + ARRAY_SIZE(dest->eht), val, len, |
| 111 | + target_power, txs_delta); |
| 112 | + |
| 113 | + if (dest_path == NULL) |
| 114 | + return max_power; |
| 115 | + |
| 116 | + max_power_backoff = max_power; |
| 117 | + |
| 118 | + val = mt76_get_of_array(np, "paths-cck", &len, ARRAY_SIZE(dest_path->cck)); |
| 119 | + mt76_apply_array_limit(dest_path->cck, ARRAY_SIZE(dest_path->cck), val, |
| 120 | + target_power_combine, txs_delta, &max_power_backoff); |
| 121 | + |
| 122 | + val = mt76_get_of_array(np, "paths-ofdm", &len, ARRAY_SIZE(dest_path->ofdm)); |
| 123 | + mt76_apply_array_limit(dest_path->ofdm, ARRAY_SIZE(dest_path->ofdm), val, |
| 124 | + target_power_combine, txs_delta, &max_power_backoff); |
| 125 | + |
| 126 | + val = mt76_get_of_array(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest_path->ofdm_bf)); |
| 127 | + mt76_apply_array_limit(dest_path->ofdm_bf, ARRAY_SIZE(dest_path->ofdm_bf), val, |
| 128 | + target_power_combine, txs_delta, &max_power_backoff); |
| 129 | + |
| 130 | + val = mt76_get_of_array(np, "paths-ru", &len, ARRAY_SIZE(dest_path->ru[0]) + 1); |
| 131 | + mt76_apply_multi_array_limit(dest_path->ru[0], ARRAY_SIZE(dest_path->ru[0]), |
| 132 | + ARRAY_SIZE(dest_path->ru), val, len, |
| 133 | + target_power_combine, txs_delta); |
| 134 | + |
| 135 | + val = mt76_get_of_array(np, "paths-ru-bf", &len, ARRAY_SIZE(dest_path->ru_bf[0]) + 1); |
| 136 | + mt76_apply_multi_array_limit(dest_path->ru_bf[0], ARRAY_SIZE(dest_path->ru_bf[0]), |
| 137 | + ARRAY_SIZE(dest_path->ru_bf), val, len, |
| 138 | + target_power_combine, txs_delta); |
| 139 | |
| 140 | return max_power; |
| 141 | } |
| 142 | diff --git a/mt76.h b/mt76.h |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 143 | index 362243f6..2236bc6b 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 144 | --- a/mt76.h |
| 145 | +++ b/mt76.h |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 146 | @@ -1064,6 +1064,14 @@ struct mt76_power_limits { |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 147 | s8 eht[16][16]; |
| 148 | }; |
| 149 | |
| 150 | +struct mt76_power_path_limits { |
| 151 | + s8 cck[5]; |
| 152 | + s8 ofdm[5]; |
| 153 | + s8 ofdm_bf[4]; |
| 154 | + s8 ru[16][15]; |
| 155 | + s8 ru_bf[16][15]; |
| 156 | +}; |
| 157 | + |
| 158 | struct mt76_ethtool_worker_info { |
| 159 | u64 *data; |
| 160 | int idx; |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 161 | @@ -1678,6 +1686,7 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan); |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 162 | s8 mt76_get_rate_power_limits(struct mt76_phy *phy, |
| 163 | struct ieee80211_channel *chan, |
| 164 | struct mt76_power_limits *dest, |
| 165 | + struct mt76_power_path_limits *dest_path, |
| 166 | s8 target_power); |
| 167 | |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 168 | static inline bool mt76_queue_is_rx(struct mt76_dev *dev, struct mt76_queue *q) |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 169 | diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 170 | index a1deeacd..33cbf4c2 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 171 | --- a/mt76_connac_mcu.c |
| 172 | +++ b/mt76_connac_mcu.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 173 | @@ -2158,7 +2158,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 174 | sar_power = mt76_get_sar_power(phy, &chan, reg_power); |
| 175 | |
| 176 | mt76_get_rate_power_limits(phy, &chan, limits, |
| 177 | - sar_power); |
| 178 | + NULL, sar_power); |
| 179 | |
| 180 | tx_power_tlv.last_msg = ch_list[idx] == last_ch; |
| 181 | sku_tlbv.channel = ch_list[idx]; |
| 182 | diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 183 | index 454df971..17485bfc 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 184 | --- a/mt7996/eeprom.c |
| 185 | +++ b/mt7996/eeprom.c |
| 186 | @@ -408,3 +408,37 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band) |
| 187 | |
| 188 | return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta; |
| 189 | } |
| 190 | + |
| 191 | +const u8 mt7996_sku_group_len[] = { |
| 192 | + [SKU_CCK] = 4, |
| 193 | + [SKU_OFDM] = 8, |
| 194 | + [SKU_HT20] = 8, |
| 195 | + [SKU_HT40] = 9, |
| 196 | + [SKU_VHT20] = 12, |
| 197 | + [SKU_VHT40] = 12, |
| 198 | + [SKU_VHT80] = 12, |
| 199 | + [SKU_VHT160] = 12, |
| 200 | + [SKU_HE26] = 12, |
| 201 | + [SKU_HE52] = 12, |
| 202 | + [SKU_HE106] = 12, |
| 203 | + [SKU_HE242] = 12, |
| 204 | + [SKU_HE484] = 12, |
| 205 | + [SKU_HE996] = 12, |
| 206 | + [SKU_HE2x996] = 12, |
| 207 | + [SKU_EHT26] = 16, |
| 208 | + [SKU_EHT52] = 16, |
| 209 | + [SKU_EHT106] = 16, |
| 210 | + [SKU_EHT242] = 16, |
| 211 | + [SKU_EHT484] = 16, |
| 212 | + [SKU_EHT996] = 16, |
| 213 | + [SKU_EHT2x996] = 16, |
| 214 | + [SKU_EHT4x996] = 16, |
| 215 | + [SKU_EHT26_52] = 16, |
| 216 | + [SKU_EHT26_106] = 16, |
| 217 | + [SKU_EHT484_242] = 16, |
| 218 | + [SKU_EHT996_484] = 16, |
| 219 | + [SKU_EHT996_484_242] = 16, |
| 220 | + [SKU_EHT2x996_484] = 16, |
| 221 | + [SKU_EHT3x996] = 16, |
| 222 | + [SKU_EHT3x996_484] = 16, |
| 223 | +}; |
| 224 | diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 225 | index 58179c0c..b19ff068 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 226 | --- a/mt7996/eeprom.h |
| 227 | +++ b/mt7996/eeprom.h |
| 228 | @@ -125,4 +125,46 @@ mt7996_get_channel_group_6g(int channel) |
| 229 | return DIV_ROUND_UP(channel - 29, 32); |
| 230 | } |
| 231 | |
| 232 | +enum mt7996_sku_rate_group { |
| 233 | + SKU_CCK, |
| 234 | + SKU_OFDM, |
| 235 | + |
| 236 | + SKU_HT20, |
| 237 | + SKU_HT40, |
| 238 | + |
| 239 | + SKU_VHT20, |
| 240 | + SKU_VHT40, |
| 241 | + SKU_VHT80, |
| 242 | + SKU_VHT160, |
| 243 | + |
| 244 | + SKU_HE26, |
| 245 | + SKU_HE52, |
| 246 | + SKU_HE106, |
| 247 | + SKU_HE242, |
| 248 | + SKU_HE484, |
| 249 | + SKU_HE996, |
| 250 | + SKU_HE2x996, |
| 251 | + |
| 252 | + SKU_EHT26, |
| 253 | + SKU_EHT52, |
| 254 | + SKU_EHT106, |
| 255 | + SKU_EHT242, |
| 256 | + SKU_EHT484, |
| 257 | + SKU_EHT996, |
| 258 | + SKU_EHT2x996, |
| 259 | + SKU_EHT4x996, |
| 260 | + SKU_EHT26_52, |
| 261 | + SKU_EHT26_106, |
| 262 | + SKU_EHT484_242, |
| 263 | + SKU_EHT996_484, |
| 264 | + SKU_EHT996_484_242, |
| 265 | + SKU_EHT2x996_484, |
| 266 | + SKU_EHT3x996, |
| 267 | + SKU_EHT3x996_484, |
| 268 | + |
| 269 | + MAX_SKU_RATE_GROUP_NUM, |
| 270 | +}; |
| 271 | + |
| 272 | +extern const u8 mt7996_sku_group_len[MAX_SKU_RATE_GROUP_NUM]; |
| 273 | + |
| 274 | #endif |
| 275 | diff --git a/mt7996/init.c b/mt7996/init.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 276 | index 7e813960..3b816070 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 277 | --- a/mt7996/init.c |
| 278 | +++ b/mt7996/init.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 279 | @@ -297,7 +297,12 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy, |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 280 | int nss_delta = mt76_tx_power_nss_delta(nss); |
| 281 | int pwr_delta = mt7996_eeprom_get_power_delta(dev, sband->band); |
| 282 | struct mt76_power_limits limits; |
| 283 | + struct mt76_power_path_limits limits_path; |
| 284 | + struct device_node *np; |
| 285 | |
| 286 | + phy->sku_limit_en = true; |
| 287 | + phy->sku_path_en = true; |
| 288 | + np = mt76_find_power_limits_node(&dev->mt76); |
| 289 | for (i = 0; i < sband->n_channels; i++) { |
| 290 | struct ieee80211_channel *chan = &sband->channels[i]; |
| 291 | int target_power = mt7996_eeprom_get_target_power(dev, chan); |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 292 | @@ -305,11 +310,18 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy, |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 293 | target_power += pwr_delta; |
| 294 | target_power = mt76_get_rate_power_limits(phy->mt76, chan, |
| 295 | &limits, |
| 296 | + &limits_path, |
| 297 | target_power); |
| 298 | + if (!limits_path.ofdm[0]) |
| 299 | + phy->sku_path_en = false; |
| 300 | + |
| 301 | target_power += nss_delta; |
| 302 | target_power = DIV_ROUND_UP(target_power, 2); |
| 303 | - chan->max_power = min_t(int, chan->max_reg_power, |
| 304 | - target_power); |
| 305 | + if (!np) |
| 306 | + chan->max_power = min_t(int, chan->max_reg_power, |
| 307 | + target_power); |
| 308 | + else |
| 309 | + chan->max_power = target_power; |
| 310 | chan->orig_mpwr = target_power; |
| 311 | } |
| 312 | } |
| 313 | diff --git a/mt7996/main.c b/mt7996/main.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 314 | index 22acd04e..5a6ba6a6 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 315 | --- a/mt7996/main.c |
| 316 | +++ b/mt7996/main.c |
| 317 | @@ -85,6 +85,21 @@ int mt7996_run(struct ieee80211_hw *hw) |
| 318 | if (ret) |
| 319 | goto out; |
| 320 | |
| 321 | +#ifdef CONFIG_MTK_DEBUG |
| 322 | + ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL, |
| 323 | + dev->dbg.sku_disable ? 0 : phy->sku_limit_en); |
| 324 | + |
| 325 | + ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL, |
| 326 | + dev->dbg.sku_disable ? 0 : phy->sku_path_en); |
| 327 | +#else |
| 328 | + ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_SKU_POWER_LIMIT_CTRL, |
| 329 | + phy->sku_limit_en); |
| 330 | + ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL, |
| 331 | + phy->sku_path_en); |
| 332 | +#endif |
| 333 | + if (ret) |
| 334 | + goto out; |
| 335 | + |
| 336 | set_bit(MT76_STATE_RUNNING, &phy->mt76->state); |
| 337 | |
| 338 | ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, |
| 339 | diff --git a/mt7996/mcu.c b/mt7996/mcu.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 340 | index 8f725307..3b4c45bb 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 341 | --- a/mt7996/mcu.c |
| 342 | +++ b/mt7996/mcu.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 343 | @@ -4668,9 +4668,31 @@ int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id) |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 344 | sizeof(req), true); |
| 345 | } |
| 346 | |
| 347 | +static void |
| 348 | +mt7996_update_max_txpower_cur(struct mt7996_phy *phy, int tx_power) |
| 349 | +{ |
| 350 | + struct mt76_phy *mphy = phy->mt76; |
| 351 | + struct ieee80211_channel *chan = mphy->main_chan; |
| 352 | + int e2p_power_limit = 0; |
| 353 | + |
| 354 | + if (chan == NULL) { |
| 355 | + mphy->txpower_cur = tx_power; |
| 356 | + return; |
| 357 | + } |
| 358 | + |
| 359 | + e2p_power_limit = mt7996_eeprom_get_target_power(phy->dev, chan); |
| 360 | + e2p_power_limit += mt7996_eeprom_get_power_delta(phy->dev, chan->band); |
| 361 | + |
| 362 | + if (phy->sku_limit_en) |
| 363 | + mphy->txpower_cur = min_t(int, e2p_power_limit, tx_power); |
| 364 | + else |
| 365 | + mphy->txpower_cur = e2p_power_limit; |
| 366 | +} |
| 367 | + |
| 368 | int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) |
| 369 | { |
| 370 | #define TX_POWER_LIMIT_TABLE_RATE 0 |
| 371 | +#define TX_POWER_LIMIT_TABLE_PATH 1 |
| 372 | struct mt7996_dev *dev = phy->dev; |
| 373 | struct mt76_phy *mphy = phy->mt76; |
| 374 | struct ieee80211_hw *hw = mphy->hw; |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 375 | @@ -4690,13 +4712,22 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 376 | .band_idx = phy->mt76->band_idx, |
| 377 | }; |
| 378 | struct mt76_power_limits la = {}; |
| 379 | + struct mt76_power_path_limits la_path = {}; |
| 380 | struct sk_buff *skb; |
| 381 | - int i, tx_power; |
| 382 | + int i, ret, txpower_limit; |
| 383 | + |
| 384 | + if (hw->conf.power_level == INT_MIN) |
| 385 | + hw->conf.power_level = 127; |
| 386 | + txpower_limit = mt7996_get_power_bound(phy, hw->conf.power_level); |
| 387 | |
| 388 | - tx_power = mt7996_get_power_bound(phy, hw->conf.power_level); |
| 389 | - tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan, |
| 390 | - &la, tx_power); |
| 391 | - mphy->txpower_cur = tx_power; |
| 392 | + if (phy->sku_limit_en) { |
| 393 | + txpower_limit = mt76_get_rate_power_limits(mphy, mphy->chandef.chan, |
| 394 | + &la, &la_path, txpower_limit); |
| 395 | + mt7996_update_max_txpower_cur(phy, txpower_limit); |
| 396 | + } else { |
| 397 | + mt7996_update_max_txpower_cur(phy, txpower_limit); |
| 398 | + return 0; |
| 399 | + } |
| 400 | |
| 401 | skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, |
| 402 | sizeof(req) + MT7996_SKU_PATH_NUM); |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 403 | @@ -4726,6 +4757,34 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 404 | /* padding */ |
| 405 | skb_put_zero(skb, MT7996_SKU_PATH_NUM - MT7996_SKU_RATE_NUM); |
| 406 | |
| 407 | + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, |
| 408 | + MCU_WM_UNI_CMD(TXPOWER), true); |
| 409 | + if (ret) |
| 410 | + return ret; |
| 411 | + |
| 412 | + /* only set per-path power table when it's configured */ |
| 413 | + if (!phy->sku_path_en) |
| 414 | + return 0; |
| 415 | + |
| 416 | + skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, |
| 417 | + sizeof(req) + MT7996_SKU_PATH_NUM); |
| 418 | + if (!skb) |
| 419 | + return -ENOMEM; |
| 420 | + req.power_limit_type = TX_POWER_LIMIT_TABLE_PATH; |
| 421 | + |
| 422 | + skb_put_data(skb, &req, sizeof(req)); |
| 423 | + skb_put_data(skb, &la_path.cck, sizeof(la_path.cck)); |
| 424 | + skb_put_data(skb, &la_path.ofdm, sizeof(la_path.ofdm)); |
| 425 | + skb_put_data(skb, &la_path.ofdm_bf, sizeof(la_path.ofdm_bf)); |
| 426 | + |
| 427 | + for (i = 0; i < 32; i++) { |
| 428 | + bool bf = i % 2; |
| 429 | + u8 idx = i / 2; |
| 430 | + s8 *buf = bf ? la_path.ru_bf[idx] : la_path.ru[idx]; |
| 431 | + |
| 432 | + skb_put_data(skb, buf, sizeof(la_path.ru[0])); |
| 433 | + } |
| 434 | + |
| 435 | return mt76_mcu_skb_send_msg(&dev->mt76, skb, |
| 436 | MCU_WM_UNI_CMD(TXPOWER), true); |
| 437 | } |
| 438 | diff --git a/mt7996/mcu.h b/mt7996/mcu.h |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 439 | index f889cb8b..1ed05d7e 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 440 | --- a/mt7996/mcu.h |
| 441 | +++ b/mt7996/mcu.h |
| 442 | @@ -911,6 +911,7 @@ struct tx_power_ctrl { |
| 443 | bool ate_mode_enable; |
| 444 | bool percentage_ctrl_enable; |
| 445 | bool bf_backoff_enable; |
| 446 | + u8 show_info_category; |
| 447 | u8 power_drop_level; |
| 448 | }; |
| 449 | u8 band_idx; |
| 450 | @@ -924,6 +925,7 @@ enum { |
| 451 | UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL = 3, |
| 452 | UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4, |
| 453 | UNI_TXPOWER_ATE_MODE_CTRL = 6, |
| 454 | + UNI_TXPOWER_SHOW_INFO = 7, |
| 455 | }; |
| 456 | |
| 457 | enum { |
| 458 | diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 459 | index d5050d6d..ff7edcd8 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 460 | --- a/mt7996/mt7996.h |
| 461 | +++ b/mt7996/mt7996.h |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 462 | @@ -295,6 +295,9 @@ struct mt7996_phy { |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 463 | |
| 464 | struct mt7996_scs_ctrl scs_ctrl; |
| 465 | |
| 466 | + bool sku_limit_en; |
| 467 | + bool sku_path_en; |
| 468 | + |
| 469 | #ifdef CONFIG_NL80211_TESTMODE |
| 470 | struct { |
| 471 | u32 *reg_backup; |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 472 | @@ -616,6 +619,7 @@ int mt7996_mcu_apply_tx_dpd(struct mt7996_phy *phy); |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 473 | #ifdef CONFIG_NL80211_TESTMODE |
| 474 | void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb); |
| 475 | #endif |
| 476 | +int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event); |
| 477 | int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable); |
| 478 | void mt7996_mcu_scs_sta_poll(struct work_struct *work); |
| 479 | |
| 480 | diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 481 | index 8c576bac..3558641c 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 482 | --- a/mt7996/mtk_debugfs.c |
| 483 | +++ b/mt7996/mtk_debugfs.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 484 | @@ -2439,6 +2439,364 @@ mt7996_scs_enable_set(void *data, u64 val) |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 485 | DEFINE_DEBUGFS_ATTRIBUTE(fops_scs_enable, NULL, |
| 486 | mt7996_scs_enable_set, "%lld\n"); |
| 487 | |
| 488 | +static int |
| 489 | +mt7996_txpower_level_set(void *data, u64 val) |
| 490 | +{ |
| 491 | + struct mt7996_phy *phy = data; |
| 492 | + int ret; |
| 493 | + |
| 494 | + if (val > 100) |
| 495 | + return -EINVAL; |
| 496 | + |
| 497 | + ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_PERCENTAGE_CTRL, !!val); |
| 498 | + if (ret) |
| 499 | + return ret; |
| 500 | + |
| 501 | + return mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_PERCENTAGE_DROP_CTRL, val); |
| 502 | +} |
| 503 | + |
| 504 | +DEFINE_DEBUGFS_ATTRIBUTE(fops_txpower_level, NULL, |
| 505 | + mt7996_txpower_level_set, "%lld\n"); |
| 506 | + |
| 507 | +static ssize_t |
| 508 | +mt7996_get_txpower_info(struct file *file, char __user *user_buf, |
| 509 | + size_t count, loff_t *ppos) |
| 510 | +{ |
| 511 | + struct mt7996_phy *phy = file->private_data; |
| 512 | + struct mt7996_mcu_txpower_event *event; |
| 513 | + struct txpower_basic_info *basic_info; |
| 514 | + struct device_node *np; |
| 515 | + static const size_t size = 2048; |
| 516 | + int len = 0; |
| 517 | + ssize_t ret; |
| 518 | + char *buf; |
| 519 | + |
| 520 | + buf = kzalloc(size, GFP_KERNEL); |
| 521 | + event = kzalloc(sizeof(*event), GFP_KERNEL); |
| 522 | + if (!buf || !event) { |
| 523 | + ret = -ENOMEM; |
| 524 | + goto out; |
| 525 | + } |
| 526 | + |
| 527 | + ret = mt7996_mcu_get_tx_power_info(phy, BASIC_INFO, event); |
| 528 | + if (ret || |
| 529 | + le32_to_cpu(event->basic_info.category) != UNI_TXPOWER_BASIC_INFO) |
| 530 | + goto out; |
| 531 | + |
| 532 | + basic_info = &event->basic_info; |
| 533 | + |
| 534 | + len += scnprintf(buf + len, size - len, |
| 535 | + "======================== BASIC INFO ========================\n"); |
| 536 | + len += scnprintf(buf + len, size - len, " Band Index: %d, Channel Band: %d\n", |
| 537 | + basic_info->band_idx, basic_info->band); |
| 538 | + len += scnprintf(buf + len, size - len, " PA Type: %s\n", |
| 539 | + basic_info->is_epa ? "ePA" : "iPA"); |
| 540 | + len += scnprintf(buf + len, size - len, " LNA Type: %s\n", |
| 541 | + basic_info->is_elna ? "eLNA" : "iLNA"); |
| 542 | + |
| 543 | + len += scnprintf(buf + len, size - len, |
| 544 | + "------------------------------------------------------------\n"); |
| 545 | + len += scnprintf(buf + len, size - len, " SKU: %s\n", |
| 546 | + basic_info->sku_enable ? "enable" : "disable"); |
| 547 | + len += scnprintf(buf + len, size - len, " Percentage Control: %s\n", |
| 548 | + basic_info->percentage_ctrl_enable ? "enable" : "disable"); |
| 549 | + len += scnprintf(buf + len, size - len, " Power Drop: %d [dBm]\n", |
| 550 | + basic_info->power_drop_level >> 1); |
| 551 | + len += scnprintf(buf + len, size - len, " Backoff: %s\n", |
| 552 | + basic_info->bf_backoff_enable ? "enable" : "disable"); |
| 553 | + len += scnprintf(buf + len, size - len, " TX Front-end Loss: %d, %d, %d, %d\n", |
| 554 | + basic_info->front_end_loss_tx[0], basic_info->front_end_loss_tx[1], |
| 555 | + basic_info->front_end_loss_tx[2], basic_info->front_end_loss_tx[3]); |
| 556 | + len += scnprintf(buf + len, size - len, " RX Front-end Loss: %d, %d, %d, %d\n", |
| 557 | + basic_info->front_end_loss_rx[0], basic_info->front_end_loss_rx[1], |
| 558 | + basic_info->front_end_loss_rx[2], basic_info->front_end_loss_rx[3]); |
| 559 | + len += scnprintf(buf + len, size - len, |
| 560 | + " MU TX Power Mode: %s\n", |
| 561 | + basic_info->mu_tx_power_manual_enable ? "manual" : "auto"); |
| 562 | + len += scnprintf(buf + len, size - len, |
| 563 | + " MU TX Power (Auto / Manual): %d / %d [0.5 dBm]\n", |
| 564 | + basic_info->mu_tx_power_auto, basic_info->mu_tx_power_manual); |
| 565 | + len += scnprintf(buf + len, size - len, |
| 566 | + " Thermal Compensation: %s\n", |
| 567 | + basic_info->thermal_compensate_enable ? "enable" : "disable"); |
| 568 | + len += scnprintf(buf + len, size - len, |
| 569 | + " Theraml Compensation Value: %d\n", |
| 570 | + basic_info->thermal_compensate_value); |
| 571 | + np = mt76_find_power_limits_node(phy->mt76->dev); |
| 572 | + len += scnprintf(buf + len, size - len, |
| 573 | + " RegDB: %s\n", |
| 574 | + !np ? "enable" : "disable"); |
| 575 | + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); |
| 576 | + |
| 577 | +out: |
| 578 | + kfree(buf); |
| 579 | + kfree(event); |
| 580 | + return ret; |
| 581 | +} |
| 582 | + |
| 583 | +static const struct file_operations mt7996_txpower_info_fops = { |
| 584 | + .read = mt7996_get_txpower_info, |
| 585 | + .open = simple_open, |
| 586 | + .owner = THIS_MODULE, |
| 587 | + .llseek = default_llseek, |
| 588 | +}; |
| 589 | + |
| 590 | +#define mt7996_txpower_puts(rate, _len) \ |
| 591 | +({ \ |
| 592 | + len += scnprintf(buf + len, size - len, "%-*s:", _len, #rate " (TMAC)"); \ |
| 593 | + for (i = 0; i < mt7996_sku_group_len[SKU_##rate]; i++, offs++) \ |
| 594 | + len += scnprintf(buf + len, size - len, " %6d", \ |
| 595 | + event->phy_rate_info.frame_power[offs][band_idx]); \ |
| 596 | + len += scnprintf(buf + len, size - len, "\n"); \ |
| 597 | +}) |
| 598 | + |
| 599 | +static ssize_t |
| 600 | +mt7996_get_txpower_sku(struct file *file, char __user *user_buf, |
| 601 | + size_t count, loff_t *ppos) |
| 602 | +{ |
| 603 | + struct mt7996_phy *phy = file->private_data; |
| 604 | + struct mt7996_dev *dev = phy->dev; |
| 605 | + struct mt7996_mcu_txpower_event *event; |
| 606 | + struct ieee80211_channel *chan = phy->mt76->chandef.chan; |
| 607 | + struct ieee80211_supported_band sband; |
| 608 | + u8 band_idx = phy->mt76->band_idx; |
| 609 | + static const size_t size = 5120; |
| 610 | + int i, offs = 0, len = 0; |
| 611 | + u32 target_power = 0; |
| 612 | + int n_chains = hweight16(phy->mt76->chainmask); |
| 613 | + int nss_delta = mt76_tx_power_nss_delta(n_chains); |
| 614 | + int pwr_delta; |
| 615 | + ssize_t ret; |
| 616 | + char *buf; |
| 617 | + u32 reg; |
| 618 | + |
| 619 | + buf = kzalloc(size, GFP_KERNEL); |
| 620 | + event = kzalloc(sizeof(*event), GFP_KERNEL); |
| 621 | + if (!buf || !event) { |
| 622 | + ret = -ENOMEM; |
| 623 | + goto out; |
| 624 | + } |
| 625 | + |
| 626 | + ret = mt7996_mcu_get_tx_power_info(phy, PHY_RATE_INFO, event); |
| 627 | + if (ret || |
| 628 | + le32_to_cpu(event->phy_rate_info.category) != UNI_TXPOWER_PHY_RATE_INFO) |
| 629 | + goto out; |
| 630 | + |
| 631 | + len += scnprintf(buf + len, size - len, |
| 632 | + "\nPhy %d TX Power Table (Channel %d)\n", |
| 633 | + band_idx, phy->mt76->chandef.chan->hw_value); |
| 634 | + len += scnprintf(buf + len, size - len, "%-21s %6s %6s %6s %6s\n", |
| 635 | + " ", "1m", "2m", "5m", "11m"); |
| 636 | + mt7996_txpower_puts(CCK, 21); |
| 637 | + |
| 638 | + len += scnprintf(buf + len, size - len, |
| 639 | + "%-21s %6s %6s %6s %6s %6s %6s %6s %6s\n", |
| 640 | + " ", "6m", "9m", "12m", "18m", "24m", "36m", "48m", |
| 641 | + "54m"); |
| 642 | + mt7996_txpower_puts(OFDM, 21); |
| 643 | + |
| 644 | + len += scnprintf(buf + len, size - len, |
| 645 | + "%-21s %6s %6s %6s %6s %6s %6s %6s %6s\n", |
| 646 | + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", |
| 647 | + "mcs5", "mcs6", "mcs7"); |
| 648 | + mt7996_txpower_puts(HT20, 21); |
| 649 | + |
| 650 | + len += scnprintf(buf + len, size - len, |
| 651 | + "%-21s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", |
| 652 | + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", |
| 653 | + "mcs6", "mcs7", "mcs32"); |
| 654 | + mt7996_txpower_puts(HT40, 21); |
| 655 | + |
| 656 | + len += scnprintf(buf + len, size - len, |
| 657 | + "%-21s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", |
| 658 | + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", |
| 659 | + "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11"); |
| 660 | + mt7996_txpower_puts(VHT20, 21); |
| 661 | + mt7996_txpower_puts(VHT40, 21); |
| 662 | + mt7996_txpower_puts(VHT80, 21); |
| 663 | + mt7996_txpower_puts(VHT160, 21); |
| 664 | + mt7996_txpower_puts(HE26, 21); |
| 665 | + mt7996_txpower_puts(HE52, 21); |
| 666 | + mt7996_txpower_puts(HE106, 21); |
| 667 | + len += scnprintf(buf + len, size - len, "BW20/"); |
| 668 | + mt7996_txpower_puts(HE242, 16); |
| 669 | + len += scnprintf(buf + len, size - len, "BW40/"); |
| 670 | + mt7996_txpower_puts(HE484, 16); |
| 671 | + len += scnprintf(buf + len, size - len, "BW80/"); |
| 672 | + mt7996_txpower_puts(HE996, 16); |
| 673 | + len += scnprintf(buf + len, size - len, "BW160/"); |
| 674 | + mt7996_txpower_puts(HE2x996, 15); |
| 675 | + |
| 676 | + len += scnprintf(buf + len, size - len, |
| 677 | + "%-21s %6s %6s %6s %6s %6s %6s %6s %6s ", |
| 678 | + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", "mcs6", "mcs7"); |
| 679 | + len += scnprintf(buf + len, size - len, |
| 680 | + "%6s %6s %6s %6s %6s %6s %6s %6s\n", |
| 681 | + "mcs8", "mcs9", "mcs10", "mcs11", "mcs12", "mcs13", "mcs14", "mcs15"); |
| 682 | + mt7996_txpower_puts(EHT26, 21); |
| 683 | + mt7996_txpower_puts(EHT52, 21); |
| 684 | + mt7996_txpower_puts(EHT106, 21); |
| 685 | + len += scnprintf(buf + len, size - len, "BW20/"); |
| 686 | + mt7996_txpower_puts(EHT242, 16); |
| 687 | + len += scnprintf(buf + len, size - len, "BW40/"); |
| 688 | + mt7996_txpower_puts(EHT484, 16); |
| 689 | + len += scnprintf(buf + len, size - len, "BW80/"); |
| 690 | + mt7996_txpower_puts(EHT996, 16); |
| 691 | + len += scnprintf(buf + len, size - len, "BW160/"); |
| 692 | + mt7996_txpower_puts(EHT2x996, 15); |
| 693 | + len += scnprintf(buf + len, size - len, "BW320/"); |
| 694 | + mt7996_txpower_puts(EHT4x996, 15); |
| 695 | + mt7996_txpower_puts(EHT26_52, 21); |
| 696 | + mt7996_txpower_puts(EHT26_106, 21); |
| 697 | + mt7996_txpower_puts(EHT484_242, 21); |
| 698 | + mt7996_txpower_puts(EHT996_484, 21); |
| 699 | + mt7996_txpower_puts(EHT996_484_242, 21); |
| 700 | + mt7996_txpower_puts(EHT2x996_484, 21); |
| 701 | + mt7996_txpower_puts(EHT3x996, 21); |
| 702 | + mt7996_txpower_puts(EHT3x996_484, 21); |
| 703 | + |
| 704 | + len += scnprintf(buf + len, size - len, "\nePA Gain: %d\n", |
| 705 | + event->phy_rate_info.epa_gain); |
| 706 | + len += scnprintf(buf + len, size - len, "Max Power Bound: %d\n", |
| 707 | + event->phy_rate_info.max_power_bound); |
| 708 | + len += scnprintf(buf + len, size - len, "Min Power Bound: %d\n", |
| 709 | + event->phy_rate_info.min_power_bound); |
| 710 | + |
| 711 | + reg = MT_WF_PHYDFE_TSSI_TXCTRL01(band_idx); |
| 712 | + len += scnprintf(buf + len, size - len, |
| 713 | + "\nBBP TX Power (target power from TMAC) : %6ld [0.5 dBm]\n", |
| 714 | + mt76_get_field(dev, reg, MT_WF_PHYDFE_TSSI_TXCTRL_POWER_TMAC)); |
| 715 | + len += scnprintf(buf + len, size - len, |
| 716 | + "RegDB maximum power:\t%d [dBm]\n", |
| 717 | + chan->max_reg_power); |
| 718 | + |
| 719 | + if (chan->band == NL80211_BAND_2GHZ) |
| 720 | + sband = phy->mt76->sband_2g.sband; |
| 721 | + else if (chan->band == NL80211_BAND_5GHZ) |
| 722 | + sband = phy->mt76->sband_5g.sband; |
| 723 | + else if (chan->band == NL80211_BAND_6GHZ) |
| 724 | + sband = phy->mt76->sband_6g.sband; |
| 725 | + |
| 726 | + pwr_delta = mt7996_eeprom_get_power_delta(dev, sband.band); |
| 727 | + |
| 728 | + target_power = max_t(u32, target_power, mt7996_eeprom_get_target_power(dev, chan)); |
| 729 | + target_power += pwr_delta + nss_delta; |
| 730 | + target_power = DIV_ROUND_UP(target_power, 2); |
| 731 | + len += scnprintf(buf + len, size - len, |
| 732 | + "eeprom maximum power:\t%d [dBm]\n", |
| 733 | + target_power); |
| 734 | + |
| 735 | + len += scnprintf(buf + len, size - len, |
| 736 | + "nss_delta:\t%d [0.5 dBm]\n", |
| 737 | + nss_delta); |
| 738 | + |
| 739 | + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); |
| 740 | + |
| 741 | +out: |
| 742 | + kfree(buf); |
| 743 | + kfree(event); |
| 744 | + return ret; |
| 745 | +} |
| 746 | + |
| 747 | +static const struct file_operations mt7996_txpower_sku_fops = { |
| 748 | + .read = mt7996_get_txpower_sku, |
| 749 | + .open = simple_open, |
| 750 | + .owner = THIS_MODULE, |
| 751 | + .llseek = default_llseek, |
| 752 | +}; |
| 753 | + |
| 754 | +#define mt7996_txpower_path_puts(rate, arr_length) \ |
| 755 | +({ \ |
| 756 | + len += scnprintf(buf + len, size - len, "%23s:", #rate " (TMAC)"); \ |
| 757 | + for (i = 0; i < arr_length; i++, offs++) \ |
| 758 | + len += scnprintf(buf + len, size - len, " %4d", \ |
| 759 | + event->backoff_table_info.frame_power[offs]); \ |
| 760 | + len += scnprintf(buf + len, size - len, "\n"); \ |
| 761 | +}) |
| 762 | + |
| 763 | +static ssize_t |
| 764 | +mt7996_get_txpower_path(struct file *file, char __user *user_buf, |
| 765 | + size_t count, loff_t *ppos) |
| 766 | +{ |
| 767 | + struct mt7996_phy *phy = file->private_data; |
| 768 | + struct mt7996_mcu_txpower_event *event; |
| 769 | + static const size_t size = 5120; |
| 770 | + int i, offs = 0, len = 0; |
| 771 | + ssize_t ret; |
| 772 | + char *buf; |
| 773 | + |
| 774 | + buf = kzalloc(size, GFP_KERNEL); |
| 775 | + event = kzalloc(sizeof(*event), GFP_KERNEL); |
| 776 | + if (!buf || !event) { |
| 777 | + ret = -ENOMEM; |
| 778 | + goto out; |
| 779 | + } |
| 780 | + |
| 781 | + ret = mt7996_mcu_get_tx_power_info(phy, BACKOFF_TABLE_INFO, event); |
| 782 | + if (ret || |
| 783 | + le32_to_cpu(event->phy_rate_info.category) != UNI_TXPOWER_BACKOFF_TABLE_SHOW_INFO) |
| 784 | + goto out; |
| 785 | + |
| 786 | + len += scnprintf(buf + len, size - len, "\n%*c", 25, ' '); |
| 787 | + len += scnprintf(buf + len, size - len, "1T1S/2T1S/3T1S/4T1S/5T1S/2T2S/3T2S/4T2S/5T2S/" |
| 788 | + "3T3S/4T3S/5T3S/4T4S/5T4S/5T5S\n"); |
| 789 | + |
| 790 | + mt7996_txpower_path_puts(CCK, 5); |
| 791 | + mt7996_txpower_path_puts(OFDM, 5); |
| 792 | + mt7996_txpower_path_puts(BF-OFDM, 4); |
| 793 | + |
| 794 | + mt7996_txpower_path_puts(RU26, 15); |
| 795 | + mt7996_txpower_path_puts(BF-RU26, 15); |
| 796 | + mt7996_txpower_path_puts(RU52, 15); |
| 797 | + mt7996_txpower_path_puts(BF-RU52, 15); |
| 798 | + mt7996_txpower_path_puts(RU26_52, 15); |
| 799 | + mt7996_txpower_path_puts(BF-RU26_52, 15); |
| 800 | + mt7996_txpower_path_puts(RU106, 15); |
| 801 | + mt7996_txpower_path_puts(BF-RU106, 15); |
| 802 | + mt7996_txpower_path_puts(RU106_52, 15); |
| 803 | + mt7996_txpower_path_puts(BF-RU106_52, 15); |
| 804 | + |
| 805 | + mt7996_txpower_path_puts(BW20/RU242, 15); |
| 806 | + mt7996_txpower_path_puts(BF-BW20/RU242, 15); |
| 807 | + mt7996_txpower_path_puts(BW40/RU484, 15); |
| 808 | + mt7996_txpower_path_puts(BF-BW40/RU484, 15); |
| 809 | + mt7996_txpower_path_puts(RU242_484, 15); |
| 810 | + mt7996_txpower_path_puts(BF-RU242_484, 15); |
| 811 | + mt7996_txpower_path_puts(BW80/RU996, 15); |
| 812 | + mt7996_txpower_path_puts(BF-BW80/RU996, 15); |
| 813 | + mt7996_txpower_path_puts(RU484_996, 15); |
| 814 | + mt7996_txpower_path_puts(BF-RU484_996, 15); |
| 815 | + mt7996_txpower_path_puts(RU242_484_996, 15); |
| 816 | + mt7996_txpower_path_puts(BF-RU242_484_996, 15); |
| 817 | + mt7996_txpower_path_puts(BW160/RU996x2, 15); |
| 818 | + mt7996_txpower_path_puts(BF-BW160/RU996x2, 15); |
| 819 | + mt7996_txpower_path_puts(RU484_996x2, 15); |
| 820 | + mt7996_txpower_path_puts(BF-RU484_996x2, 15); |
| 821 | + mt7996_txpower_path_puts(RU996x3, 15); |
| 822 | + mt7996_txpower_path_puts(BF-RU996x3, 15); |
| 823 | + mt7996_txpower_path_puts(RU484_996x3, 15); |
| 824 | + mt7996_txpower_path_puts(BF-RU484_996x3, 15); |
| 825 | + mt7996_txpower_path_puts(BW320/RU996x4, 15); |
| 826 | + mt7996_txpower_path_puts(BF-BW320/RU996x4, 15); |
| 827 | + |
| 828 | + len += scnprintf(buf + len, size - len, "\nBackoff table: %s\n", |
| 829 | + event->backoff_table_info.backoff_en ? "enable" : "disable"); |
| 830 | + |
| 831 | + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); |
| 832 | + |
| 833 | +out: |
| 834 | + kfree(buf); |
| 835 | + kfree(event); |
| 836 | + return ret; |
| 837 | +} |
| 838 | + |
| 839 | +static const struct file_operations mt7996_txpower_path_fops = { |
| 840 | + .read = mt7996_get_txpower_path, |
| 841 | + .open = simple_open, |
| 842 | + .owner = THIS_MODULE, |
| 843 | + .llseek = default_llseek, |
| 844 | +}; |
| 845 | + |
| 846 | int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir) |
| 847 | { |
| 848 | struct mt7996_dev *dev = phy->dev; |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 849 | @@ -2503,6 +2861,11 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir) |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 850 | debugfs_create_devm_seqfile(dev->mt76.dev, "tr_info", dir, |
| 851 | mt7996_trinfo_read); |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 852 | |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 853 | + debugfs_create_file("txpower_level", 0600, dir, phy, &fops_txpower_level); |
| 854 | + debugfs_create_file("txpower_info", 0600, dir, phy, &mt7996_txpower_info_fops); |
| 855 | + debugfs_create_file("txpower_sku", 0600, dir, phy, &mt7996_txpower_sku_fops); |
| 856 | + debugfs_create_file("txpower_path", 0600, dir, phy, &mt7996_txpower_path_fops); |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 857 | + |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 858 | debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir, |
| 859 | mt7996_wtbl_read); |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 860 | |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 861 | diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 862 | index c16b25ab..e56ddd8f 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 863 | --- a/mt7996/mtk_mcu.c |
| 864 | +++ b/mt7996/mtk_mcu.c |
| 865 | @@ -12,8 +12,31 @@ |
| 866 | |
| 867 | #ifdef CONFIG_MTK_DEBUG |
| 868 | |
| 869 | +int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event) |
| 870 | +{ |
| 871 | + struct mt7996_dev *dev = phy->dev; |
| 872 | + struct tx_power_ctrl req = { |
| 873 | + .tag = cpu_to_le16(UNI_TXPOWER_SHOW_INFO), |
| 874 | + .len = cpu_to_le16(sizeof(req) - 4), |
| 875 | + .power_ctrl_id = UNI_TXPOWER_SHOW_INFO, |
| 876 | + .show_info_category = category, |
| 877 | + .band_idx = phy->mt76->band_idx, |
| 878 | + }; |
| 879 | + struct sk_buff *skb; |
| 880 | + int ret; |
| 881 | |
| 882 | + ret = mt76_mcu_send_and_get_msg(&dev->mt76, |
| 883 | + MCU_WM_UNI_CMD_QUERY(TXPOWER), |
| 884 | + &req, sizeof(req), true, &skb); |
| 885 | + if (ret) |
| 886 | + return ret; |
| 887 | |
| 888 | + memcpy(event, skb->data, sizeof(struct mt7996_mcu_txpower_event)); |
| 889 | + |
| 890 | + dev_kfree_skb(skb); |
| 891 | + |
| 892 | + return 0; |
| 893 | +} |
| 894 | |
| 895 | int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val) |
| 896 | { |
| 897 | diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 898 | index 7f4d4e02..c30418ca 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 899 | --- a/mt7996/mtk_mcu.h |
| 900 | +++ b/mt7996/mtk_mcu.h |
| 901 | @@ -14,6 +14,98 @@ enum { |
| 902 | UNI_CMD_MURU_DBG_INFO = 0x18, |
| 903 | }; |
| 904 | |
| 905 | +struct txpower_basic_info { |
| 906 | + u8 category; |
| 907 | + u8 rsv1; |
| 908 | + |
| 909 | + /* basic info */ |
| 910 | + u8 band_idx; |
| 911 | + u8 band; |
| 912 | + |
| 913 | + /* board type info */ |
| 914 | + bool is_epa; |
| 915 | + bool is_elna; |
| 916 | + |
| 917 | + /* power percentage info */ |
| 918 | + bool percentage_ctrl_enable; |
| 919 | + s8 power_drop_level; |
| 920 | + |
| 921 | + /* frond-end loss TX info */ |
| 922 | + s8 front_end_loss_tx[4]; |
| 923 | + |
| 924 | + /* frond-end loss RX info */ |
| 925 | + s8 front_end_loss_rx[4]; |
| 926 | + |
| 927 | + /* thermal info */ |
| 928 | + bool thermal_compensate_enable; |
| 929 | + s8 thermal_compensate_value; |
| 930 | + u8 rsv2; |
| 931 | + |
| 932 | + /* TX power max/min limit info */ |
| 933 | + s8 max_power_bound; |
| 934 | + s8 min_power_bound; |
| 935 | + |
| 936 | + /* power limit info */ |
| 937 | + bool sku_enable; |
| 938 | + bool bf_backoff_enable; |
| 939 | + |
| 940 | + /* MU TX power info */ |
| 941 | + bool mu_tx_power_manual_enable; |
| 942 | + s8 mu_tx_power_auto; |
| 943 | + s8 mu_tx_power_manual; |
| 944 | + u8 rsv3; |
| 945 | +}; |
| 946 | + |
| 947 | +struct txpower_phy_rate_info { |
| 948 | + u8 category; |
| 949 | + u8 band_idx; |
| 950 | + u8 band; |
| 951 | + u8 epa_gain; |
| 952 | + |
| 953 | + /* rate power info [dBm] */ |
| 954 | + s8 frame_power[MT7996_SKU_RATE_NUM][__MT_MAX_BAND]; |
| 955 | + |
| 956 | + /* TX power max/min limit info */ |
| 957 | + s8 max_power_bound; |
| 958 | + s8 min_power_bound; |
| 959 | + u8 rsv1; |
| 960 | +}; |
| 961 | + |
| 962 | +struct txpower_backoff_table_info { |
| 963 | + u8 category; |
| 964 | + u8 band_idx; |
| 965 | + u8 band; |
| 966 | + u8 backoff_en; |
| 967 | + |
| 968 | + s8 frame_power[MT7996_SKU_PATH_NUM]; |
| 969 | + u8 rsv[3]; |
| 970 | +}; |
| 971 | + |
| 972 | +struct mt7996_mcu_txpower_event { |
| 973 | + u8 _rsv[4]; |
| 974 | + |
| 975 | + __le16 tag; |
| 976 | + __le16 len; |
| 977 | + |
| 978 | + union { |
| 979 | + struct txpower_basic_info basic_info; |
| 980 | + struct txpower_phy_rate_info phy_rate_info; |
| 981 | + struct txpower_backoff_table_info backoff_table_info; |
| 982 | + }; |
| 983 | +}; |
| 984 | + |
| 985 | +enum txpower_category { |
| 986 | + BASIC_INFO, |
| 987 | + BACKOFF_TABLE_INFO, |
| 988 | + PHY_RATE_INFO, |
| 989 | +}; |
| 990 | + |
| 991 | +enum txpower_event { |
| 992 | + UNI_TXPOWER_BASIC_INFO = 0, |
| 993 | + UNI_TXPOWER_BACKOFF_TABLE_SHOW_INFO = 3, |
| 994 | + UNI_TXPOWER_PHY_RATE_INFO = 5, |
| 995 | +}; |
| 996 | + |
| 997 | #endif |
| 998 | |
| 999 | #endif |
| 1000 | diff --git a/mt7996/regs.h b/mt7996/regs.h |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 1001 | index 4c20a67d..8ec1dc1c 100644 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 1002 | --- a/mt7996/regs.h |
| 1003 | +++ b/mt7996/regs.h |
| 1004 | @@ -693,24 +693,29 @@ enum offs_rev { |
| 1005 | ((_wf) << 16) + (ofs)) |
| 1006 | #define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000) |
| 1007 | |
| 1008 | -/* PHYRX CTRL */ |
| 1009 | -#define MT_WF_PHYRX_BAND_BASE 0x83080000 |
| 1010 | -#define MT_WF_PHYRX_BAND(_band, ofs) (MT_WF_PHYRX_BAND_BASE + \ |
| 1011 | +/* PHYDFE CTRL */ |
| 1012 | +#define MT_WF_PHYDFE_TSSI_TXCTRL01(_band) MT_WF_PHYRX_CSD(_band, 0, 0xc718) |
| 1013 | +#define MT_WF_PHYDFE_TSSI_TXCTRL_POWER_TMAC GENMASK(31, 24) |
| 1014 | + |
| 1015 | +/* PHY CTRL */ |
| 1016 | +#define MT_WF_PHY_BAND_BASE 0x83080000 |
| 1017 | +#define MT_WF_PHY_BAND(_band, ofs) (MT_WF_PHY_BAND_BASE + \ |
| 1018 | ((_band) << 20) + (ofs)) |
| 1019 | |
| 1020 | -#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHYRX_BAND(_band, 0x1054) |
| 1021 | -#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHYRX_BAND(_band, 0x1058) |
| 1022 | -#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHYRX_BAND(_band, 0x105c) |
| 1023 | -#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHYRX_BAND(_band, 0x1060) |
| 1024 | -#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHYRX_BAND(_band, 0x1064) |
| 1025 | -#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHYRX_BAND(_band, 0x1068) |
| 1026 | +#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHY_BAND(_band, 0x1054) |
| 1027 | +#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHY_BAND(_band, 0x1058) |
| 1028 | +#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHY_BAND(_band, 0x105c) |
| 1029 | +#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHY_BAND(_band, 0x1060) |
| 1030 | +#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHY_BAND(_band, 0x1064) |
| 1031 | +#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHY_BAND(_band, 0x1068) |
| 1032 | |
| 1033 | -#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHYRX_BAND(_band, 0x2004) |
| 1034 | +/* PHYRX CTRL */ |
| 1035 | +#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHY_BAND(_band, 0x2004) |
| 1036 | #define MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN GENMASK(2, 0) |
| 1037 | #define MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN GENMASK(11, 9) |
| 1038 | |
| 1039 | /* PHYRX CSD BAND */ |
| 1040 | -#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHYRX_BAND(_band, 0x8230) |
| 1041 | +#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHY_BAND(_band, 0x8230) |
| 1042 | #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18) |
| 1043 | #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29) |
| 1044 | |
| 1045 | -- |
developer | 9237f44 | 2024-06-14 17:13:04 +0800 | [diff] [blame] | 1046 | 2.18.0 |
developer | 66e89bc | 2024-04-23 14:50:01 +0800 | [diff] [blame] | 1047 | |