[PATCH] wifi: mt76: mt7925: add MT7928 debugfs txpower_sku with power table selection
JB Tsai
jb.tsai at mediatek.com
Fri Jul 24 01:52:02 PDT 2026
From: Charlie-cy Wu <Charlie-cy.Wu at mediatek.com>
Add MT7928-specific debugfs interface for txpower_sku that supports
multiple power table selection. MT7928 extends the power structure with
additional OFDM bandwidth variants (OFDM20/40/80/160) compared to MT7925.
Key changes:
- Add struct mt7928_txpwr with OFDM20/40/80/160 support
- Implement mt7928_txpwr() handler for MT7928-specific power display
- Add txpower_tbl debugfs control for selecting power tables:
* 0: STA_SISO
* 1: STA_CDD
* 2: STA_MIMO
* 3: P2P_SISO
* 4: P2P_CDD
* 5: P2P_MIMO
- Extend mt7925_txpwr_req with power_tbl field for FW communication
- Add mt7928_txpwr_event structure for handling FW responses
- Store txpwr_tbl in mt792x_dev for per-device power table tracking
Usage:
echo 0 > /sys/kernel/debug/ieee80211/phy0/mt76/txpower_tbl
cat /sys/kernel/debug/ieee80211/phy0/mt76/txpower_sku
Signed-off-by: Charlie-cy Wu <Charlie-cy.Wu at mediatek.com>
---
.../wireless/mediatek/mt76/mt7925/debugfs.c | 151 +++++++++++++++++-
.../net/wireless/mediatek/mt76/mt7925/mcu.c | 27 ++++
.../net/wireless/mediatek/mt76/mt7925/mcu.h | 20 ++-
.../wireless/mediatek/mt76/mt7925/mt7925.h | 39 +++++
drivers/net/wireless/mediatek/mt76/mt792x.h | 1 +
5 files changed, 235 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c
index e2498659c884..3db564d63c15 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c
@@ -178,6 +178,147 @@ mt7925_txpwr(struct seq_file *s, void *data)
return ret;
}
+static inline void
+mt7928_eht_txpwr(struct seq_file *s, struct mt7928_txpwr *txpwr, u8 band_idx)
+{
+ seq_printf(s, "%-22s %6s %6s %6s %6s %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",
+ "mcs12", "mcs13", "mcs14", "mcs15");
+ mt7925_print_txpwr_entry(EHT26, eht26, band_idx);
+ mt7925_print_txpwr_entry(EHT52, eht52, band_idx);
+ mt7925_print_txpwr_entry(EHT106, eht106, band_idx);
+ mt7925_print_txpwr_entry(EHT242, eht242, band_idx);
+ mt7925_print_txpwr_entry(EHT484, eht484, band_idx);
+
+ mt7925_print_txpwr_entry(EHT996, eht996, band_idx);
+ mt7925_print_txpwr_entry(EHT996x2, eht996x2, band_idx);
+ mt7925_print_txpwr_entry(EHT996x4, eht996x4, band_idx);
+ mt7925_print_txpwr_entry(EHT26_52, eht26_52, band_idx);
+ mt7925_print_txpwr_entry(EHT26_106, eht26_106, band_idx);
+ mt7925_print_txpwr_entry(EHT484_242, eht484_242, band_idx);
+ mt7925_print_txpwr_entry(EHT996_484, eht996_484, band_idx);
+ mt7925_print_txpwr_entry(EHT996_484_242, eht996_484_242, band_idx);
+ mt7925_print_txpwr_entry(EHT996x2_484, eht996x2_484, band_idx);
+ mt7925_print_txpwr_entry(EHT996x3, eht996x3, band_idx);
+ mt7925_print_txpwr_entry(EHT996x3_484, eht996x3_484, band_idx);
+}
+
+static int
+mt7928_txpwr(struct seq_file *s, void *data)
+{
+ struct mt792x_dev *dev = dev_get_drvdata(s->private);
+ struct mt7928_txpwr *txpwr = NULL;
+ u8 band_idx = dev->mphy.band_idx;
+ int ret = 0;
+
+ txpwr = devm_kmalloc(dev->mt76.dev, sizeof(*txpwr), GFP_KERNEL);
+
+ if (!txpwr)
+ return -ENOMEM;
+
+ mt792x_mutex_acquire(dev);
+ ret = mt7928_get_txpwr_info(dev, band_idx, dev->txpwr_tbl, txpwr);
+ mt792x_mutex_release(dev);
+
+ if (ret)
+ goto out;
+
+ /* Display power table name based on the index */
+ switch (dev->txpwr_tbl) {
+ case 0:
+ seq_printf(s, "Power Table: %d (STA_SISO)\n", dev->txpwr_tbl);
+ break;
+ case 1:
+ seq_printf(s, "Power Table: %d (STA_CDD)\n", dev->txpwr_tbl);
+ break;
+ case 2:
+ seq_printf(s, "Power Table: %d (STA_MIMO)\n", dev->txpwr_tbl);
+ break;
+ case 3:
+ seq_printf(s, "Power Table: %d (P2P_SISO)\n", dev->txpwr_tbl);
+ break;
+ case 4:
+ seq_printf(s, "Power Table: %d (P2P_CDD)\n", dev->txpwr_tbl);
+ break;
+ case 5:
+ seq_printf(s, "Power Table: %d (P2P_MIMO)\n", dev->txpwr_tbl);
+ break;
+ default:
+ seq_printf(s, "Power Table: %d (Unknown)\n", dev->txpwr_tbl);
+ break;
+ }
+
+ seq_printf(s, "%-22s %6s %6s %6s %6s\n",
+ " ", "1m", "2m", "5m", "11m");
+ mt7925_print_txpwr_entry(CCK, cck, band_idx);
+
+ seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s\n",
+ " ", "6m", "9m", "12m", "18m", "24m", "36m",
+ "48m", "54m");
+ mt7925_print_txpwr_entry(OFDM20, ofdm20, band_idx);
+ mt7925_print_txpwr_entry(OFDM40, ofdm40, band_idx);
+ mt7925_print_txpwr_entry(OFDM80, ofdm80, band_idx);
+ mt7925_print_txpwr_entry(OFDM160, ofdm160, band_idx);
+
+ seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s\n",
+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
+ "mcs6", "mcs7");
+ mt7925_print_txpwr_entry(HT20, ht20, band_idx);
+
+ seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
+ "mcs6", "mcs7", "mcs32");
+ mt7925_print_txpwr_entry(HT40, ht40, band_idx);
+
+ seq_printf(s, "%-22s %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");
+ mt7925_print_txpwr_entry(VHT20, vht20, band_idx);
+ mt7925_print_txpwr_entry(VHT40, vht40, band_idx);
+
+ mt7925_print_txpwr_entry(VHT80, vht80, band_idx);
+ mt7925_print_txpwr_entry(VHT160, vht160, band_idx);
+
+ mt7925_print_txpwr_entry(HE26, he26, band_idx);
+ mt7925_print_txpwr_entry(HE52, he52, band_idx);
+ mt7925_print_txpwr_entry(HE106, he106, band_idx);
+ mt7925_print_txpwr_entry(HE242, he242, band_idx);
+ mt7925_print_txpwr_entry(HE484, he484, band_idx);
+
+ mt7925_print_txpwr_entry(HE996, he996, band_idx);
+ mt7925_print_txpwr_entry(HE996x2, he996x2, band_idx);
+
+ mt7928_eht_txpwr(s, txpwr, band_idx);
+
+out:
+ devm_kfree(dev->mt76.dev, txpwr);
+ return ret;
+}
+
+static int
+mt7928_txpwr_tbl_set(void *data, u64 val)
+{
+ struct mt792x_dev *dev = data;
+
+ dev->txpwr_tbl = (u8)val;
+
+ return 0;
+}
+
+static int
+mt7928_txpwr_tbl_get(void *data, u64 *val)
+{
+ struct mt792x_dev *dev = data;
+
+ *val = dev->txpwr_tbl;
+
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_txpwr_tbl, mt7928_txpwr_tbl_get,
+ mt7928_txpwr_tbl_set, "%lld\n");
+
static int
mt7925_pm_set(void *data, u64 val)
{
@@ -303,8 +444,14 @@ int mt7925_init_debugfs(struct mt792x_dev *dev)
debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
mt792x_queues_acq);
- debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
- mt7925_txpwr);
+ if (is_mt7928(&dev->mt76)) {
+ debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
+ mt7928_txpwr);
+ debugfs_create_file("txpower_tbl", 0600, dir, dev, &fops_txpwr_tbl);
+ } else {
+ debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
+ mt7925_txpwr);
+ }
debugfs_create_file("tx_stats", 0400, dir, dev, &mt792x_tx_stats_fops);
debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 37502d8a0e7d..7162eca8e23e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -2211,6 +2211,33 @@ int mt7925_get_txpwr_info(struct mt792x_dev *dev, u8 band_idx, struct mt7925_txp
return 0;
}
+int mt7928_get_txpwr_info(struct mt792x_dev *dev, u8 band_idx, u8 power_tbl,
+ struct mt7928_txpwr *txpwr)
+{
+ struct mt7928_txpwr_event *event;
+ struct mt7925_txpwr_req req = {
+ .tag = cpu_to_le16(TX_POWER_SHOW_INFO),
+ .len = cpu_to_le16(sizeof(req) - 4),
+ .catg = TXPOWER_ALL_RATE_POWER_INFO,
+ .band_idx = band_idx,
+ .power_tbl = power_tbl,
+ };
+ struct sk_buff *skb;
+ int ret;
+
+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(TXPOWER),
+ &req, sizeof(req), true, &skb);
+ if (ret)
+ return ret;
+
+ event = (struct mt7928_txpwr_event *)skb->data;
+ memcpy(txpwr, &event->txpwr, sizeof(*txpwr));
+
+ dev_kfree_skb(skb);
+
+ return 0;
+}
+
int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif,
bool enable)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
index 1613c4765186..754db84200d8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
@@ -69,7 +69,7 @@ struct mt7925_txpwr_req {
u8 format_id;
u8 catg;
u8 band_idx;
- u8 _rsv1;
+ u8 power_tbl;
} __packed;
struct mt7925_txpwr_event {
@@ -90,6 +90,24 @@ struct mt7925_txpwr_event {
u8 rsv1;
} __packed;
+struct mt7928_txpwr_event {
+ u8 rsv[4];
+ __le16 tag;
+ __le16 len;
+
+ u8 catg;
+ u8 band_idx;
+ u8 ch_band;
+ u8 format; /* 0:Legacy, 1:HE */
+
+ /* Rate power info */
+ struct mt7928_txpwr txpwr;
+
+ s8 pwr_max;
+ s8 pwr_min;
+ u8 rsv1;
+} __packed;
+
enum {
TM_SWITCH_MODE,
TM_SET_AT_CMD,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
index e3fef41cbb33..b06f17b2fd8c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
@@ -260,6 +260,43 @@ struct mt7925_txpwr {
s8 eht996x3_484[16][2];
};
+struct mt7928_txpwr {
+ s8 cck[4][2];
+ s8 ofdm20[8][2];
+ s8 ofdm40[8][2];
+ s8 ofdm80[8][2];
+ s8 ofdm160[8][2];
+ s8 ht20[8][2];
+ s8 ht40[9][2];
+ s8 vht20[12][2];
+ s8 vht40[12][2];
+ s8 vht80[12][2];
+ s8 vht160[12][2];
+ s8 he26[12][2];
+ s8 he52[12][2];
+ s8 he106[12][2];
+ s8 he242[12][2];
+ s8 he484[12][2];
+ s8 he996[12][2];
+ s8 he996x2[12][2];
+ s8 eht26[16][2];
+ s8 eht52[16][2];
+ s8 eht106[16][2];
+ s8 eht242[16][2];
+ s8 eht484[16][2];
+ s8 eht996[16][2];
+ s8 eht996x2[16][2];
+ s8 eht996x4[16][2];
+ s8 eht26_52[16][2];
+ s8 eht26_106[16][2];
+ s8 eht484_242[16][2];
+ s8 eht996_484[16][2];
+ s8 eht996_484_242[16][2];
+ s8 eht996x2_484[16][2];
+ s8 eht996x3[16][2];
+ s8 eht996x3_484[16][2];
+};
+
static inline u8 mt7927_band_idx(enum nl80211_band band)
{
switch (band) {
@@ -339,6 +376,8 @@ int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev,
void mt7925_coredump_work(struct work_struct *work);
int mt7925_get_txpwr_info(struct mt792x_dev *dev, u8 band_idx,
struct mt7925_txpwr *txpwr);
+int mt7928_get_txpwr_info(struct mt792x_dev *dev, u8 band_idx, u8 power_tbl,
+ struct mt7928_txpwr *txpwr);
void mt7925_mac_set_fixed_rate_table(struct mt792x_dev *dev,
u8 tbl_idx, u16 rate_idx);
void mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 5a1ba1cfc5a3..fbe1793e5598 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -281,6 +281,7 @@ struct mt792x_dev {
u8 fw_debug;
u8 fw_features;
+ u8 txpwr_tbl;
struct mt76_connac_pm pm;
struct mt76_connac_coredump coredump;
--
2.18.0
More information about the Linux-mediatek
mailing list