[PATCH] wifi: mt76: connac3: add fixedrate and autorate debugfs for rate control
JB Tsai <[email protected]>
| Newsgroups | org.infradead.lists.linux-mediatek,org.kernel.vger.linux-wireless |
|---|---|
| Message-ID | <[email protected]> |
From: Charlie-cy Wu <[email protected]> Add two debugfs interfaces to manually control the per-STA rate adaptation via the UNI_CMD_RA firmware command: - fixedrate: lock a STA to a fixed TX rate (SET_FIXED_RATE tag). The value is a packed hex field describing the full PHY rate: 0x[WCID(2)][Mode][BW][MCS][Nss][SGI][Preamble] [STBC][LDPC][SPE_EN][HeLtf] - autorate: re-enable/disable firmware rate adaptation for a STA (SET_AUTO_RATE tag): 0x[WCID(2)][En][Mode] Key changes: - Add mt7925_mcu_set_fixed_rate() sending the SET_FIXED_RATE(0x0F) TLV - Add mt7925_mcu_set_auto_rate() sending the SET_AUTO_RATE(0x11) TLV - Add RA command TLV structures (mt7925_ra_hdr, mt7925_ra_fixed_rate_tlv/_v1, mt7925_ra_auto_rate_tlv) and the UNI_CMD_RA tag enum - Register fixedrate/autorate debugfs files and store the last value in mt792x_dev for read back - Translate the LDPC input to the FW's "on" value (7) Note: EHT modes require HeLtf=1, otherwise the firmware drops all TX. Usage: echo 0x1D372000101 > /sys/kernel/debug/ieee80211/phyX/mt76/fixedrate echo 0x110 > /sys/kernel/debug/ieee80211/phyX/mt76/autorate Signed-off-by: Charlie-cy Wu <[email protected]> --- .../wireless/mediatek/mt76/mt7925/debugfs.c | 97 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7925/mcu.c | 40 ++++++++ .../net/wireless/mediatek/mt76/mt7925/mcu.h | 42 ++++++++ drivers/net/wireless/mediatek/mt76/mt792x.h | 3 + 4 files changed, 182 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c index 3db564d63c15..4a043855a049 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c @@ -427,6 +427,101 @@ static int mt7925_chip_reset(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7925_chip_reset, "%lld\n"); +/* fixedrate input format (12 hex digits): + * 0x[WCID(2)][Mode][BW][MCS][Nss][SGI][Preamble][STBC][LDPC][SPE_EN][HeLtf] + * The RA tag is fixed to SET_FIXED_RATE internally. + * WCID is 2 nibbles, all others are 1 nibble. + * + * [WCID] Wireless Client ID + * [Mode] CCK=0, OFDM=1, HT=2, GF=3, VHT=4, PLR=5, HE_SU=8, HE_ER_SU=9, + * HE_TRIG=10, HE_MU=11, EHT_ER=13, EHT_TB=14, EHT_SU and EHT_MU=15 + * [BW] BW20=0, BW40=1, BW80=2, BW160=3, BW320=4 + * [MCS] CCK=0~3, OFDM=0~7, HT=0~32, VHT=0~9, HE=0~11, EHT=0~13, EHT_ER=14~15 + * [Nss] 1~8 + * [GI] HT/VHT: 0=Long, 1=Short; HE/EHT: 0=0.8us, 1=1.6us, 2=3.2us + * [Preamble] Long=0, Short=other + * [STBC] Enable=1, Disable=0 + * [LDPC] BCC=0, LDPC=1 (driver sends the FW's "on" value 7) + * [SPE_EN] spatial extension index + * [HeLtf] 1X=0, 2X=1, 4X=2 (NOTE: EHT modes require HeLtf=1) + */ +static int +mt7925_fixedrate_set(void *data, u64 val) +{ + struct mt792x_dev *dev = data; + struct mt7925_ra_fixed_rate_v1 rate = {}; + + dev->fixed_rate = val; + + rate.wlan_idx = cpu_to_le16((val >> 40) & 0xff); + rate.phy_mode = (val >> 36) & 0xf; + rate.bw = (val >> 32) & 0xf; + rate.mcs = (val >> 28) & 0xf; + rate.nss = (val >> 24) & 0xf; + rate.short_gi = cpu_to_le16((val >> 20) & 0xf); + rate.short_preamble = (val >> 16) & 0xf; + rate.stbc = (val >> 12) & 0xf; + rate.ecc = ((val >> 8) & 0xf) ? 7 : 0; + rate.spe = (val >> 4) & 0xf; + rate.he_ltf = cpu_to_le16((val >> 0) & 0xf); + + mt792x_mutex_acquire(dev); + mt7925_mcu_set_fixed_rate(dev, &rate); + mt792x_mutex_release(dev); + + return 0; +} + +static int +mt7925_fixedrate_get(void *data, u64 *val) +{ + struct mt792x_dev *dev = data; + + *val = dev->fixed_rate; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(fops_fixedrate, mt7925_fixedrate_get, + mt7925_fixedrate_set, "0x%llx\n"); + +/* autorate input format (6 hex digits): + * 0x[Tag(2)][WCID(2)][En][Mode] + * The RA tag is fixed to SET_AUTO_RATE internally. + * WCID is 2 nibbles, En and Mode are 1 nibble each. + * + * [WCID] Wireless Client ID + * [En] Auto rate: Enable=1, Disable=0 + * [Mode] don't care (RA picks the rate) + */ +static int +mt7925_autorate_set(void *data, u64 val) +{ + struct mt792x_dev *dev = data; + u16 wlan_idx = (val >> 8) & 0xff; + bool enable = (val >> 4) & 0xf; + u8 mode = val & 0xf; + + dev->auto_rate = val; + + mt792x_mutex_acquire(dev); + mt7925_mcu_set_auto_rate(dev, wlan_idx, enable, mode); + mt792x_mutex_release(dev); + + return 0; +} + +static int +mt7925_autorate_get(void *data, u64 *val) +{ + struct mt792x_dev *dev = data; + + *val = dev->auto_rate; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(fops_autorate, mt7925_autorate_get, + mt7925_autorate_set, "0x%llx\n"); + int mt7925_init_debugfs(struct mt792x_dev *dev) { struct dentry *dir; @@ -461,6 +556,8 @@ int mt7925_init_debugfs(struct mt792x_dev *dev) debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir, mt792x_pm_stats); debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds); + debugfs_create_file("fixedrate", 0600, dir, dev, &fops_fixedrate); + debugfs_create_file("autorate", 0600, dir, dev, &fops_autorate); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c index 7162eca8e23e..b8062eb91ba5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c @@ -4113,3 +4113,43 @@ int mt7925_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(RSSI_MONITOR), &req, sizeof(req), false); } + +int mt7925_mcu_set_fixed_rate(struct mt792x_dev *dev, + struct mt7925_ra_fixed_rate_v1 *rate) +{ + struct { + struct mt7925_ra_hdr hdr; + struct mt7925_ra_fixed_rate_tlv tlv; + struct mt7925_ra_fixed_rate_v1 v1; + } __packed req = { + .tlv = { + .tag = cpu_to_le16(UNI_CMD_RA_TAG_SET_FIXED_RATE), + .len = cpu_to_le16(sizeof(req.tlv) + sizeof(req.v1)), + .version = cpu_to_le16(0), + }, + .v1 = *rate, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(RA), &req, + sizeof(req), true); +} + +int mt7925_mcu_set_auto_rate(struct mt792x_dev *dev, u16 wlan_idx, + bool enable, u8 mode) +{ + struct { + struct mt7925_ra_hdr hdr; + struct mt7925_ra_auto_rate_tlv tlv; + } __packed req = { + .tlv = { + .tag = cpu_to_le16(UNI_CMD_RA_TAG_SET_AUTO_RATE), + .len = cpu_to_le16(sizeof(req.tlv)), + .wlan_idx = cpu_to_le16(wlan_idx), + .auto_rate_en = enable, + .mode = mode, + }, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(RA), &req, + sizeof(req), true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h index 754db84200d8..855613f0b29d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h @@ -61,6 +61,44 @@ struct mt7925_mcu_ant_id_config { u8 ant_id[4]; } __packed; +enum { + UNI_CMD_RA_TAG_SET_FIXED_RATE = 0x0F, + UNI_CMD_RA_TAG_SET_AUTO_RATE = 0x11, +}; + +struct mt7925_ra_hdr { + u8 _rsv[4]; +} __packed; + +struct mt7925_ra_fixed_rate_tlv { + __le16 tag; + __le16 len; + __le16 version; +} __packed; + +struct mt7925_ra_fixed_rate_v1 { + __le16 wlan_idx; + u8 phy_mode; + u8 stbc; + __le16 short_gi; + u8 bw; + u8 ecc; + u8 mcs; + u8 nss; + __le16 he_ltf; + u8 spe; + u8 short_preamble; + __le16 _rsv; +} __packed; + +struct mt7925_ra_auto_rate_tlv { + __le16 tag; + __le16 len; + __le16 wlan_idx; + u8 auto_rate_en; + u8 mode; +} __packed; + struct mt7925_txpwr_req { u8 _rsv[4]; __le16 tag; @@ -758,4 +796,8 @@ int mt7925_mcu_update_arp_filter(struct mt76_dev *dev, int mt7925_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_bss_conf *link_conf, bool enable); +int mt7925_mcu_set_fixed_rate(struct mt792x_dev *dev, + struct mt7925_ra_fixed_rate_v1 *rate); +int mt7925_mcu_set_auto_rate(struct mt792x_dev *dev, u16 wlan_idx, + bool enable, u8 mode); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index fbe1793e5598..eecd0b1a5d0e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -283,6 +283,9 @@ struct mt792x_dev { u8 fw_features; u8 txpwr_tbl; + u64 fixed_rate; + u64 auto_rate; + struct mt76_connac_pm pm; struct mt76_connac_coredump coredump; const struct mt792x_hif_ops *hif_ops; -- 2.18.0