[rdkb][common][bsp][Refactor and sync wifi from openwrt]
[Description]
cc3c51c7 [MAC80211][wifi6][Release][Update MT7986 Firmware]
ea393925 [MAC80211[WiFi6/7]][hostapd][Avoid unnecessary beacon update]
6763be22 [MAC80211][wifi7][Misc][Sync Internal patches to External Release Folder]
d3ed9bc8 [mac80211][wifi7][mt76][Rebase WED patch due to Cheetah MT76 modifications]
2f4b03c3 [mac80211][wifi6][mt76][Bring-up hardware path for Cheetah MT76]
cb573d78 [MAC80211][WiFi7][app][Add ibf atenl support for eagle]
04fe6893 [mac80211][wifi6][mt76][Fix rebase errors]
c301e69a [MAC80211][WiFi7][mt76][Update Kite EEPROM bin files]
463b00fb [MAC80211][WiFi7][infra][Add slot1 for kite]
8774388d [MAC80211][WiFi7][misc][Prevent deadlock in a multiple AP+STA mode]
68d43fea [MAC80211][hostapd][show acs channels config]
5aca83c6 [MAC80211][hostapd][Prevent hostapd from setting beacon too frequently]
636da369 [MAC80211][wifi6/7][misc][use current epoch date]
9eb3456f [MAC80211][hostapd][refactor AP/STA CSA handling flow]
5543f3d8 [MAC80211][WiFi6][mt76][Refactor assignment of STA BSS group]
c5631fc2 [mac80211][mt76][wifi6][Add debugfs knob for RTS threshold]
6a92a2d4 [mac80211][wifi6][mt76][Bring-up software path for Cheetah MT76]
bf66c519 [MAC80211][netifd][Remove unnecessary netifd patch]
2f141c75 [mac80211][mt76][wifi6/7][Fix build failed]
cf30db1e [mac80211[hostapd][wifi7][Fix build fial]
dc391fc0 [MAC80211][wifi6][Release][Update MT7986 Firmware]
71a7b95a [MAC80211][WiFi7][mt76][Add kite fw & eeprom to eagle codebase]
5a7bd025 [MAC80211][WiFi6][misc][Add mt7981 default eeprom bin]
e40da697 [MAC80211][WED][Fix reinsert wifi module cause memory leak issue]
0a22f8f4 [MAC80211][WiFi7][misc][fix mt7988-mt7996-mac980211 release build fail]
25f3fe1c [[Eagle][SQC3.0][BE19000][MT7996][E2][MT7976_MT7977][256][ePA][MT7988A][WiFi] [MAP][SnS][Muti-client][UES]Traffic stuck in Agent2 with invalid tid 8 found]
f59b5dad [MAC80211][WiFi6][mt76][Add additional chain signal info in station dump for merlin]
fada400d [MAC80211][WiFi6/7][mt76][Add HT40- capab when enable ACS]
98e273af [MAC80211][WiFi6/7][app][Add SKU_EN & RSSI ATTR in atenl]
aaa8eb14 [MAC80211][WiFi6][mt76][Add rssi & sku_en in testmode]
eda14aac [MAC80211][core][Remove wrong assignment on the variable "changed" when changing beacon]
000329aa [MAC80211][netifd][Move netifd patch for wifi7 used only]
57bfe0c7 [MAC80211][WiFi6][misc][fix build fail due to mt76 upgration]
fa29bb39 [MAC80211][wifi6/7][mt76][update mt76 Makefile]
56f497ec [MAC80211][netifd][not to cache previous config to avoid wifi down failure]
be9abd4d [MAC80211][WiFi6][misc][fix build fail due to netifd]
af71e303 [MAC80211][WiFi6][mt76][Fix inconsistent BSS group setting of STA for VoW]
3e42972a [MAC80211][WiFi6][mt76][Fix txpower bbp CR]
81a68c03 [MAC80211][wifi7][hostapd][rebase internal hostapd patches]
336300b7 [MAC80211][WiFi6/7][hostapd][MAX 48 mbss 6G 连线概率连不上 ]
6bebc554 [MAC80211][wifi7][core][update for backports v6.5]
19daecfd [MAC80211][wifi7][ucode][Bandwidth Synchronization in AP/STA Mode]
ddf64afb [MAC80211][mt76][add debug log in SER flow]
44611a77 [mac80211][wifi6][mt76][Enhance debug log]
[Release-log]
Change-Id: Ibf5e835de5563fff4101a77e81056f696286670b
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-mt7996-add-txpower-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-mt7996-add-txpower-support.patch
new file mode 100644
index 0000000..0a0d376
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1006-wifi-mt76-mt7996-add-txpower-support.patch
@@ -0,0 +1,573 @@
+From 1c1dd57bde8919fdf04ef914b781eb6183582562 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 24 Mar 2023 23:35:30 +0800
+Subject: [PATCH 39/98] wifi: mt76: mt7996: add txpower support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: Ic3e7b17f3664fa7f774137572f885359fa2ec93b
+---
+ mt7996/eeprom.c | 34 +++++++
+ mt7996/eeprom.h | 42 ++++++++
+ mt7996/mcu.h | 2 +
+ mt7996/mt7996.h | 3 +
+ mt7996/mtk_debugfs.c | 229 +++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mtk_mcu.c | 23 +++++
+ mt7996/mtk_mcu.h | 78 +++++++++++++++
+ mt7996/regs.h | 29 +++---
+ 8 files changed, 429 insertions(+), 11 deletions(-)
+
+diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
+index 3276740..e4c4b86 100644
+--- a/mt7996/eeprom.c
++++ b/mt7996/eeprom.c
+@@ -296,3 +296,37 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
+
+ return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
+ }
++
++const u8 mt7996_sku_group_len[] = {
++ [SKU_CCK] = 4,
++ [SKU_OFDM] = 8,
++ [SKU_HT20] = 8,
++ [SKU_HT40] = 9,
++ [SKU_VHT20] = 12,
++ [SKU_VHT40] = 12,
++ [SKU_VHT80] = 12,
++ [SKU_VHT160] = 12,
++ [SKU_HE26] = 12,
++ [SKU_HE52] = 12,
++ [SKU_HE106] = 12,
++ [SKU_HE242] = 12,
++ [SKU_HE484] = 12,
++ [SKU_HE996] = 12,
++ [SKU_HE2x996] = 12,
++ [SKU_EHT26] = 16,
++ [SKU_EHT52] = 16,
++ [SKU_EHT106] = 16,
++ [SKU_EHT242] = 16,
++ [SKU_EHT484] = 16,
++ [SKU_EHT996] = 16,
++ [SKU_EHT2x996] = 16,
++ [SKU_EHT4x996] = 16,
++ [SKU_EHT26_52] = 16,
++ [SKU_EHT26_106] = 16,
++ [SKU_EHT484_242] = 16,
++ [SKU_EHT996_484] = 16,
++ [SKU_EHT996_484_242] = 16,
++ [SKU_EHT2x996_484] = 16,
++ [SKU_EHT3x996] = 16,
++ [SKU_EHT3x996_484] = 16,
++};
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 9ea3667..343e65e 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -75,4 +75,46 @@ mt7996_get_channel_group_6g(int channel)
+ return DIV_ROUND_UP(channel - 29, 32);
+ }
+
++enum mt7996_sku_rate_group {
++ SKU_CCK,
++ SKU_OFDM,
++
++ SKU_HT20,
++ SKU_HT40,
++
++ SKU_VHT20,
++ SKU_VHT40,
++ SKU_VHT80,
++ SKU_VHT160,
++
++ SKU_HE26,
++ SKU_HE52,
++ SKU_HE106,
++ SKU_HE242,
++ SKU_HE484,
++ SKU_HE996,
++ SKU_HE2x996,
++
++ SKU_EHT26,
++ SKU_EHT52,
++ SKU_EHT106,
++ SKU_EHT242,
++ SKU_EHT484,
++ SKU_EHT996,
++ SKU_EHT2x996,
++ SKU_EHT4x996,
++ SKU_EHT26_52,
++ SKU_EHT26_106,
++ SKU_EHT484_242,
++ SKU_EHT996_484,
++ SKU_EHT996_484_242,
++ SKU_EHT2x996_484,
++ SKU_EHT3x996,
++ SKU_EHT3x996_484,
++
++ MAX_SKU_RATE_GROUP_NUM,
++};
++
++extern const u8 mt7996_sku_group_len[MAX_SKU_RATE_GROUP_NUM];
++
+ #endif
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index ff9cc9c..71dc165 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -826,6 +826,7 @@ struct tx_power_ctrl {
+ bool ate_mode_enable;
+ bool percentage_ctrl_enable;
+ bool bf_backoff_enable;
++ u8 show_info_category;
+ u8 power_drop_level;
+ };
+ u8 band_idx;
+@@ -839,6 +840,7 @@ enum {
+ UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL = 3,
+ UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4,
+ UNI_TXPOWER_ATE_MODE_CTRL = 6,
++ UNI_TXPOWER_SHOW_INFO = 7,
+ };
+
+ enum {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index eb48dbd..23d1614 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -63,6 +63,8 @@
+
+ #define MT7996_BUILD_TIME_LEN 24
+
++#define MT7996_SKU_RATE_NUM 417
++
+ #define MT7996_RRO_MAX_SESSION 1024
+ #define MT7996_RRO_WINDOW_MAX_LEN 1024
+ #define MT7996_RRO_ADDR_ELEM_LEN 128
+@@ -568,6 +570,7 @@ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ void mt7996_mcu_exit(struct mt7996_dev *dev);
+ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
+ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data);
++int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
+ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
+ void mt7996_mcu_scs_sta_poll(struct work_struct *work);
+
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index 5aa5c94..57fcbab 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2325,6 +2325,232 @@ static int mt7996_sta_info(struct seq_file *s, void *data)
+ return 0;
+ }
+
++static int
++mt7996_txpower_level_set(void *data, u64 val)
++{
++ struct mt7996_phy *phy = data;
++ int ret;
++
++ if (val > 100)
++ return -EINVAL;
++
++ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_PERCENTAGE_CTRL, !!val);
++ if (ret)
++ return ret;
++
++ return mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_PERCENTAGE_DROP_CTRL, val);
++}
++
++DEFINE_DEBUGFS_ATTRIBUTE(fops_txpower_level, NULL,
++ mt7996_txpower_level_set, "%lld\n");
++
++static ssize_t
++mt7996_get_txpower_info(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct mt7996_phy *phy = file->private_data;
++ struct mt7996_mcu_txpower_event *event;
++ struct txpower_basic_info *basic_info;
++ static const size_t size = 2048;
++ int len = 0;
++ ssize_t ret;
++ char *buf;
++
++ buf = kzalloc(size, GFP_KERNEL);
++ event = kzalloc(sizeof(*event), GFP_KERNEL);
++ if (!buf || !event)
++ return -ENOMEM;
++
++ ret = mt7996_mcu_get_tx_power_info(phy, BASIC_INFO, event);
++ if (ret ||
++ le32_to_cpu(event->basic_info.category) != UNI_TXPOWER_BASIC_INFO)
++ goto out;
++
++ basic_info = &event->basic_info;
++
++ len += scnprintf(buf + len, size - len,
++ "======================== BASIC INFO ========================\n");
++ len += scnprintf(buf + len, size - len, " Band Index: %d, Channel Band: %d\n",
++ basic_info->band_idx, basic_info->band);
++ len += scnprintf(buf + len, size - len, " PA Type: %s\n",
++ basic_info->is_epa ? "ePA" : "iPA");
++ len += scnprintf(buf + len, size - len, " LNA Type: %s\n",
++ basic_info->is_elna ? "eLNA" : "iLNA");
++
++ len += scnprintf(buf + len, size - len,
++ "------------------------------------------------------------\n");
++ len += scnprintf(buf + len, size - len, " SKU: %s\n",
++ basic_info->sku_enable ? "enable" : "disable");
++ len += scnprintf(buf + len, size - len, " Percentage Control: %s\n",
++ basic_info->percentage_ctrl_enable ? "enable" : "disable");
++ len += scnprintf(buf + len, size - len, " Power Drop: %d [dBm]\n",
++ basic_info->power_drop_level >> 1);
++ len += scnprintf(buf + len, size - len, " Backoff: %s\n",
++ basic_info->bf_backoff_enable ? "enable" : "disable");
++ len += scnprintf(buf + len, size - len, " TX Front-end Loss: %d, %d, %d, %d\n",
++ basic_info->front_end_loss_tx[0], basic_info->front_end_loss_tx[1],
++ basic_info->front_end_loss_tx[2], basic_info->front_end_loss_tx[3]);
++ len += scnprintf(buf + len, size - len, " RX Front-end Loss: %d, %d, %d, %d\n",
++ basic_info->front_end_loss_rx[0], basic_info->front_end_loss_rx[1],
++ basic_info->front_end_loss_rx[2], basic_info->front_end_loss_rx[3]);
++ len += scnprintf(buf + len, size - len,
++ " MU TX Power Mode: %s\n",
++ basic_info->mu_tx_power_manual_enable ? "manual" : "auto");
++ len += scnprintf(buf + len, size - len,
++ " MU TX Power (Auto / Manual): %d / %d [0.5 dBm]\n",
++ basic_info->mu_tx_power_auto, basic_info->mu_tx_power_manual);
++ len += scnprintf(buf + len, size - len,
++ " Thermal Compensation: %s\n",
++ basic_info->thermal_compensate_enable ? "enable" : "disable");
++ len += scnprintf(buf + len, size - len,
++ " Theraml Compensation Value: %d\n",
++ basic_info->thermal_compensate_value);
++
++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
++
++out:
++ kfree(buf);
++ kfree(event);
++ return ret;
++}
++
++static const struct file_operations mt7996_txpower_info_fops = {
++ .read = mt7996_get_txpower_info,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++#define mt7996_txpower_puts(rate) \
++({ \
++ len += scnprintf(buf + len, size - len, "%-21s:", #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]); \
++ len += scnprintf(buf + len, size - len, "\n"); \
++})
++
++static ssize_t
++mt7996_get_txpower_sku(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct mt7996_phy *phy = file->private_data;
++ struct mt7996_dev *dev = phy->dev;
++ struct mt7996_mcu_txpower_event *event;
++ u8 band_idx = phy->mt76->band_idx;
++ static const size_t size = 5120;
++ int i, offs = 0, len = 0;
++ ssize_t ret;
++ char *buf;
++ u32 reg;
++
++ buf = kzalloc(size, GFP_KERNEL);
++ event = kzalloc(sizeof(*event), GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ ret = mt7996_mcu_get_tx_power_info(phy, PHY_RATE_INFO, event);
++ if (ret ||
++ le32_to_cpu(event->phy_rate_info.category) != UNI_TXPOWER_PHY_RATE_INFO)
++ goto out;
++
++ len += scnprintf(buf + len, size - len,
++ "\nPhy %d TX Power Table (Channel %d)\n",
++ 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);
++
++ 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);
++
++ 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);
++
++ 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);
++
++ 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);
++
++ len += scnprintf(buf + len, size - len,
++ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s ",
++ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", "mcs6", "mcs7");
++ 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);
++
++ len += scnprintf(buf + len, size - len, "\nePA Gain: %d\n",
++ event->phy_rate_info.epa_gain);
++ len += scnprintf(buf + len, size - len, "Max Power Bound: %d\n",
++ event->phy_rate_info.max_power_bound);
++ 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);
++ 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));
++ 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));
++ 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));
++
++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
++
++out:
++ kfree(buf);
++ kfree(event);
++ return ret;
++}
++
++static const struct file_operations mt7996_txpower_sku_fops = {
++ .read = mt7996_get_txpower_sku,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ struct mt7996_dev *dev = phy->dev;
+@@ -2367,6 +2593,9 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+
+ debugfs_create_devm_seqfile(dev->mt76.dev, "tr_info", dir,
+ mt7996_trinfo_read);
++ debugfs_create_file("txpower_level", 0600, dir, phy, &fops_txpower_level);
++ debugfs_create_file("txpower_info", 0600, dir, phy, &mt7996_txpower_info_fops);
++ debugfs_create_file("txpower_sku", 0600, dir, phy, &mt7996_txpower_sku_fops);
+
+ debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
+ mt7996_wtbl_read);
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index e887016..f772243 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -12,7 +12,30 @@
+
+ #ifdef CONFIG_MTK_DEBUG
+
++int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event)
++{
++ struct mt7996_dev *dev = phy->dev;
++ struct tx_power_ctrl req = {
++ .tag = cpu_to_le16(UNI_TXPOWER_SHOW_INFO),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ .power_ctrl_id = UNI_TXPOWER_SHOW_INFO,
++ .show_info_category = category,
++ .band_idx = phy->mt76->band_idx,
++ };
++ struct sk_buff *skb;
++ int ret;
+
++ ret = mt76_mcu_send_and_get_msg(&dev->mt76,
++ MCU_WM_UNI_CMD_QUERY(TXPOWER),
++ &req, sizeof(req), true, &skb);
++ if (ret)
++ return ret;
+
++ memcpy(event, skb->data, sizeof(struct mt7996_mcu_txpower_event));
++
++ dev_kfree_skb(skb);
++
++ return 0;
++}
+
+ #endif
+diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
+index e741aa2..beb1aba 100644
+--- a/mt7996/mtk_mcu.h
++++ b/mt7996/mtk_mcu.h
+@@ -10,6 +10,84 @@
+
+ #ifdef CONFIG_MTK_DEBUG
+
++struct txpower_basic_info {
++ u8 category;
++ u8 rsv1;
++
++ /* basic info */
++ u8 band_idx;
++ u8 band;
++
++ /* board type info */
++ bool is_epa;
++ bool is_elna;
++
++ /* power percentage info */
++ bool percentage_ctrl_enable;
++ s8 power_drop_level;
++
++ /* frond-end loss TX info */
++ s8 front_end_loss_tx[4];
++
++ /* frond-end loss RX info */
++ s8 front_end_loss_rx[4];
++
++ /* thermal info */
++ bool thermal_compensate_enable;
++ s8 thermal_compensate_value;
++ u8 rsv2;
++
++ /* TX power max/min limit info */
++ s8 max_power_bound;
++ s8 min_power_bound;
++
++ /* power limit info */
++ bool sku_enable;
++ bool bf_backoff_enable;
++
++ /* MU TX power info */
++ bool mu_tx_power_manual_enable;
++ s8 mu_tx_power_auto;
++ s8 mu_tx_power_manual;
++ u8 rsv3;
++};
++
++struct txpower_phy_rate_info {
++ u8 category;
++ u8 band_idx;
++ u8 band;
++ u8 epa_gain;
++
++ /* rate power info [dBm] */
++ s8 frame_power[MT7996_SKU_RATE_NUM][__MT_MAX_BAND];
++
++ /* TX power max/min limit info */
++ s8 max_power_bound;
++ s8 min_power_bound;
++ u8 rsv1;
++};
++
++struct mt7996_mcu_txpower_event {
++ u8 _rsv[4];
++
++ __le16 tag;
++ __le16 len;
++
++ union {
++ struct txpower_basic_info basic_info;
++ struct txpower_phy_rate_info phy_rate_info;
++ };
++};
++
++enum txpower_category {
++ BASIC_INFO,
++ PHY_RATE_INFO = 2,
++};
++
++enum txpower_event {
++ UNI_TXPOWER_BASIC_INFO = 0,
++ UNI_TXPOWER_PHY_RATE_INFO = 5,
++};
+
+ #endif
+
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index de5df91..565022a 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -672,24 +672,31 @@ enum offs_rev {
+ ((_wf) << 16) + (ofs))
+ #define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000)
+
+-/* PHYRX CTRL */
+-#define MT_WF_PHYRX_BAND_BASE 0x83080000
+-#define MT_WF_PHYRX_BAND(_band, ofs) (MT_WF_PHYRX_BAND_BASE + \
++/* PHY CTRL */
++#define MT_WF_PHY_BAND_BASE 0x83080000
++#define MT_WF_PHY_BAND(_band, ofs) (MT_WF_PHY_BAND_BASE + \
+ ((_band) << 20) + (ofs))
+
+-#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHYRX_BAND(_band, 0x1054)
+-#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHYRX_BAND(_band, 0x1058)
+-#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHYRX_BAND(_band, 0x105c)
+-#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHYRX_BAND(_band, 0x1060)
+-#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHYRX_BAND(_band, 0x1064)
+-#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHYRX_BAND(_band, 0x1068)
++#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHY_BAND(_band, 0x1054)
++#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHY_BAND(_band, 0x1058)
++#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHY_BAND(_band, 0x105c)
++#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHY_BAND(_band, 0x1060)
++#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHY_BAND(_band, 0x1064)
++#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHY_BAND(_band, 0x1068)
+
+-#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHYRX_BAND(_band, 0x2004)
++/* PHYRX CTRL */
++#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHY_BAND(_band, 0x2004)
+ #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_PHYRX_BAND(_band, 0x8230)
++#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)
+ #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29)
+
+--
+2.18.0
+