[][MAC80211][WiFi6][mt76][Add rssi & sku_en in testmode]

[Description]
Add rssi dump in dump stats
Add sku_en in testmode for txpower testing

[Release-log]
N/A

Change-Id: I8fce551b41a70f0f7065bed232293e99fe79e0f8
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/8026336
diff --git a/autobuild_mac80211_release/package/kernel/mt76/patches/1009-wifi-mt76-testmode-additional-supports.patch b/autobuild_mac80211_release/package/kernel/mt76/patches/1009-wifi-mt76-testmode-additional-supports.patch
index 5c888b7..ca61e6e 100644
--- a/autobuild_mac80211_release/package/kernel/mt76/patches/1009-wifi-mt76-testmode-additional-supports.patch
+++ b/autobuild_mac80211_release/package/kernel/mt76/patches/1009-wifi-mt76-testmode-additional-supports.patch
@@ -1,32 +1,32 @@
-From e587f57b16368389f7868b5572e97e3cc494e3fd Mon Sep 17 00:00:00 2001
+From 555abaed13e0426eb3295c7f7b02de57320a63e6 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Thu, 21 Apr 2022 15:43:19 +0800
-Subject: [PATCH 1009/1040] wifi: mt76: testmode: additional supports
+Subject: [PATCH] wifi: mt76: testmode: additional supports
 
 Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
  dma.c             |    3 +-
  mac80211.c        |   12 +
- mt76.h            |  108 +++-
+ mt76.h            |  110 +++-
  mt76_connac_mcu.c |    4 +
  mt76_connac_mcu.h |    2 +
  mt7915/eeprom.c   |    2 +-
  mt7915/init.c     |    2 +-
- mt7915/mac.c      |   39 +-
+ mt7915/mac.c      |   40 +-
  mt7915/main.c     |    2 +-
  mt7915/mcu.c      |   22 +-
  mt7915/mcu.h      |   29 +-
  mt7915/mmio.c     |    2 +
- mt7915/mt7915.h   |   16 +-
+ mt7915/mt7915.h   |   17 +-
  mt7915/regs.h     |    3 +
- mt7915/testmode.c | 1222 ++++++++++++++++++++++++++++++++++++++++++---
- mt7915/testmode.h |  278 +++++++++++
- testmode.c        |  282 +++++++++--
- testmode.h        |   75 +++
- tools/fields.c    |   84 +++-
+ mt7915/testmode.c | 1238 ++++++++++++++++++++++++++++++++++++++++++---
+ mt7915/testmode.h |  278 ++++++++++
+ testmode.c        |  287 +++++++++--
+ testmode.h        |   79 +++
+ tools/fields.c    |   90 +++-
  tx.c              |    3 +-
- 20 files changed, 2024 insertions(+), 166 deletions(-)
+ 20 files changed, 2058 insertions(+), 167 deletions(-)
 
 diff --git a/dma.c b/dma.c
 index 24b44e7..8049830 100644
@@ -73,7 +73,7 @@
  
  static const struct ieee80211_channel mt76_channels_6ghz[] = {
 diff --git a/mt76.h b/mt76.h
-index d66f4d0..3d86702 100644
+index d66f4d0..597488d 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -670,6 +670,21 @@ struct mt76_testmode_ops {
@@ -98,11 +98,13 @@
  };
  
  #define MT_TM_FW_RX_COUNT	BIT(0)
-@@ -678,16 +693,11 @@ struct mt76_testmode_data {
+@@ -678,16 +693,13 @@ struct mt76_testmode_data {
  	enum mt76_testmode_state state;
  
  	u32 param_set[DIV_ROUND_UP(NUM_MT76_TM_ATTRS, 32)];
 -	struct sk_buff *tx_skb;
++
++	u8 sku_en;
  
  	u32 tx_count;
 -	u16 tx_mpdu_len;
@@ -115,7 +117,7 @@
  	u8 tx_rate_stbc;
  	u8 tx_ltf;
  
-@@ -703,10 +713,37 @@ struct mt76_testmode_data {
+@@ -703,10 +715,37 @@ struct mt76_testmode_data {
  	u8 tx_power[4];
  	u8 tx_power_control;
  
@@ -154,7 +156,7 @@
  	u32 tx_pending;
  	u32 tx_queued;
  	u16 tx_queued_limit;
-@@ -1276,6 +1313,59 @@ static inline bool mt76_testmode_enabled(struct mt76_phy *phy)
+@@ -1276,6 +1315,59 @@ static inline bool mt76_testmode_enabled(struct mt76_phy *phy)
  #endif
  }
  
@@ -214,7 +216,7 @@
  static inline bool mt76_is_testmode_skb(struct mt76_dev *dev,
  					struct sk_buff *skb,
  					struct ieee80211_hw **hw)
-@@ -1286,7 +1376,8 @@ static inline bool mt76_is_testmode_skb(struct mt76_dev *dev,
+@@ -1286,7 +1378,8 @@ static inline bool mt76_is_testmode_skb(struct mt76_dev *dev,
  	for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
  		struct mt76_phy *phy = dev->phys[i];
  
@@ -224,7 +226,7 @@
  			*hw = dev->phys[i]->hw;
  			return true;
  		}
-@@ -1388,7 +1479,8 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -1388,7 +1481,8 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
  		       struct netlink_callback *cb, void *data, int len);
  int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state);
@@ -303,10 +305,18 @@
  	mt7915_txbf_init(dev);
  }
 diff --git a/mt7915/mac.c b/mt7915/mac.c
-index f1c78ec..bd0efd5 100644
+index f1c78ec..06a5fb1 100644
 --- a/mt7915/mac.c
 +++ b/mt7915/mac.c
-@@ -604,16 +604,38 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
+@@ -579,6 +579,7 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
+ 			wb_rssi = le32_to_cpu(rxv[9]);
+ 
+ 		phy->test.last_rcpi[i] = rcpi & 0xff;
++		phy->test.last_rssi[i] = to_rssi(GENMASK(7, 0), rcpi);
+ 		phy->test.last_ib_rssi[i] = ib_rssi & 0xff;
+ 		phy->test.last_wb_rssi[i] = wb_rssi & 0xff;
+ 	}
+@@ -604,16 +605,38 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
  {
  #ifdef CONFIG_NL80211_TESTMODE
  	struct mt76_testmode_data *td = &phy->mt76->test;
@@ -348,7 +358,7 @@
  
  	switch (td->tx_rate_mode) {
  	case MT76_TM_TX_MODE_HT:
-@@ -644,7 +666,7 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
+@@ -644,7 +667,7 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
  			rate_idx += 4;
  
  		r = &phy->mt76->hw->wiphy->bands[band]->bitrates[rate_idx];
@@ -357,7 +367,7 @@
  
  		mode = val >> 8;
  		rate_idx = val & 0xff;
-@@ -703,13 +725,14 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
+@@ -703,13 +726,14 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
  	if (mode >= MT_PHY_TYPE_HE_SU)
  		val |= FIELD_PREP(MT_TXD6_HELTF, td->tx_ltf);
  
@@ -375,7 +385,7 @@
  #endif
  }
  
-@@ -1415,7 +1438,7 @@ mt7915_mac_restart(struct mt7915_dev *dev)
+@@ -1415,7 +1439,7 @@ mt7915_mac_restart(struct mt7915_dev *dev)
  		goto out;
  
  	/* set the necessary init items */
@@ -557,10 +567,16 @@
  	[AGG_PCR0]		= 0x040,
  	[AGG_ACR0]		= 0x054,
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index ab3c8f7..7526a8f 100644
+index ab3c8f7..b91af94 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
-@@ -272,6 +272,9 @@ struct mt7915_phy {
+@@ -267,11 +267,15 @@ struct mt7915_phy {
+ 
+ 		s32 last_freq_offset;
+ 		u8 last_rcpi[4];
++		s8 last_rssi[4];
+ 		s8 last_ib_rssi[4];
+ 		s8 last_wb_rssi[4];
  		u8 last_snr;
  
  		u8 spe_idx;
@@ -570,7 +586,7 @@
  	} test;
  #endif
  
-@@ -371,6 +374,14 @@ struct mt7915_dev {
+@@ -371,6 +375,14 @@ struct mt7915_dev {
  	void __iomem *dcm;
  	void __iomem *sku;
  
@@ -585,7 +601,7 @@
  #ifdef MTK_DEBUG
  	u16 wlan_idx;
  	struct {
-@@ -542,8 +553,8 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
+@@ -542,8 +554,8 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
  				   struct ieee80211_vif *vif,
  				   struct ieee80211_sta *sta,
  				   void *data, u32 field);
@@ -596,7 +612,7 @@
  int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num);
  int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
  		       bool hdr_trans);
-@@ -582,6 +593,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
+@@ -582,6 +594,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
  int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
  void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
  void mt7915_mcu_exit(struct mt7915_dev *dev);
@@ -626,30 +642,32 @@
  							  (_n) * 4))
  #define MT_AGG_PCR0(_band, _n)		MT_WF_AGG(_band, (__OFFS(AGG_PCR0) +	\
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 4693919..e5d0ef9 100644
+index 4693919..8367204 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
-@@ -9,6 +9,9 @@
+@@ -9,6 +9,10 @@
  enum {
  	TM_CHANGED_TXPOWER,
  	TM_CHANGED_FREQ_OFFSET,
++	TM_CHANGED_SKU_EN,
 +	TM_CHANGED_AID,
 +	TM_CHANGED_CFG,
 +	TM_CHANGED_TXBF_ACT,
  
  	/* must be last */
  	NUM_TM_CHANGED
-@@ -17,6 +20,9 @@ enum {
+@@ -17,6 +21,10 @@ enum {
  static const u8 tm_change_map[] = {
  	[TM_CHANGED_TXPOWER] = MT76_TM_ATTR_TX_POWER,
  	[TM_CHANGED_FREQ_OFFSET] = MT76_TM_ATTR_FREQ_OFFSET,
++	[TM_CHANGED_SKU_EN] = MT76_TM_ATTR_SKU_EN,
 +	[TM_CHANGED_AID] = MT76_TM_ATTR_AID,
 +	[TM_CHANGED_CFG] = MT76_TM_ATTR_CFG,
 +	[TM_CHANGED_TXBF_ACT] = MT76_TM_ATTR_TXBF_ACT,
  };
  
  struct reg_band {
-@@ -33,6 +39,57 @@ struct reg_band {
+@@ -33,6 +41,57 @@ struct reg_band {
  #define TM_REG_MAX_ID	20
  static struct reg_band reg_backup_list[TM_REG_MAX_ID];
  
@@ -707,7 +725,7 @@
  
  static int
  mt7915_tm_set_tx_power(struct mt7915_phy *phy)
-@@ -119,18 +176,28 @@ mt7915_tm_set_trx(struct mt7915_phy *phy, int type, bool en)
+@@ -119,18 +178,28 @@ mt7915_tm_set_trx(struct mt7915_phy *phy, int type, bool en)
  }
  
  static int
@@ -740,7 +758,7 @@
  }
  
  static int
-@@ -141,7 +208,7 @@ mt7915_tm_set_phy_count(struct mt7915_phy *phy, u8 control)
+@@ -141,7 +210,7 @@ mt7915_tm_set_phy_count(struct mt7915_phy *phy, u8 control)
  		.testmode_en = 1,
  		.param_idx = MCU_ATE_SET_PHY_COUNT,
  		.param.cfg.enable = control,
@@ -749,7 +767,7 @@
  	};
  
  	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
-@@ -182,12 +249,739 @@ mt7915_tm_set_tam_arb(struct mt7915_phy *phy, bool enable, bool mu)
+@@ -182,12 +251,739 @@ mt7915_tm_set_tam_arb(struct mt7915_phy *phy, bool enable, bool mu)
  	return mt7915_mcu_set_muru_ctrl(dev, MURU_SET_ARB_OP_MODE, op_mode);
  }
  
@@ -1491,7 +1509,7 @@
  	struct edca *e = &req.edca[0];
  
  	e->queue = qid + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;
-@@ -263,7 +1057,8 @@ done:
+@@ -263,7 +1059,8 @@ done:
  
  	return mt7915_tm_set_wmm_qid(phy,
  				     mt76_connac_lmac_mapping(IEEE80211_AC_BE),
@@ -1501,7 +1519,7 @@
  }
  
  static int
-@@ -339,7 +1134,7 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
+@@ -339,7 +1136,7 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
  	bitrate = cfg80211_calculate_bitrate(&rate);
  	tx_len = bitrate * tx_time / 10 / 8;
  
@@ -1510,7 +1528,7 @@
  	if (ret)
  		return ret;
  
-@@ -458,64 +1253,227 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en)
+@@ -458,64 +1255,227 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en)
  
  	phy->mt76->test.flag |= MT_TM_FW_RX_COUNT;
  
@@ -1769,7 +1787,7 @@
  
  	mt7915_tm_set_trx(phy, TM_MAC_TX, en);
  }
-@@ -544,10 +1502,6 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
+@@ -544,10 +1504,6 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
  		return ret;
  
  	rs_band = (struct mt7915_tm_rx_stat_band *)skb->data;
@@ -1780,7 +1798,7 @@
  
  	if (!clear) {
  		enum mt76_rxq_id q = req.band ? MT_RXQ_BAND1 : MT_RXQ_MAIN;
-@@ -562,13 +1516,61 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
+@@ -562,13 +1518,61 @@ mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear)
  	return 0;
  }
  
@@ -1843,7 +1861,7 @@
  
  		/* read-clear */
  		mt7915_tm_get_rx_stats(phy, true);
-@@ -576,9 +1578,12 @@ mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
+@@ -576,9 +1580,12 @@ mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
  		/* clear fw count */
  		mt7915_tm_set_phy_count(phy, 0);
  		mt7915_tm_set_phy_count(phy, 1);
@@ -1858,7 +1876,7 @@
  }
  
  static int
-@@ -617,34 +1622,7 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
+@@ -617,34 +1624,7 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
  	tx_cont->tx_ant = td->tx_antenna_mask;
  	tx_cont->band = band;
  
@@ -1894,10 +1912,14 @@
  
  	if (!en) {
  		req.op.rf.param.func_data = cpu_to_le32(band);
-@@ -728,6 +1706,12 @@ mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
+@@ -728,6 +1708,16 @@ mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
  		mt7915_tm_set_freq_offset(phy, en, en ? td->freq_offset : 0);
  	if (changed & BIT(TM_CHANGED_TXPOWER))
  		mt7915_tm_set_tx_power(phy);
++	if (changed & BIT(TM_CHANGED_SKU_EN)) {
++		mt7915_mcu_set_sku_en(phy, td->sku_en);
++		mt7915_mcu_set_txpower_sku(phy);
++	}
 +	if (changed & BIT(TM_CHANGED_AID))
 +		mt7915_tm_set_entry(phy);
 +	if (changed & BIT(TM_CHANGED_CFG))
@@ -1907,7 +1929,7 @@
  }
  
  static int
-@@ -737,6 +1721,11 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+@@ -737,6 +1727,11 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
  	struct mt7915_phy *phy = mphy->priv;
  	enum mt76_testmode_state prev_state = td->state;
  
@@ -1919,7 +1941,7 @@
  	mphy->test.state = state;
  
  	if (prev_state == MT76_TM_STATE_TX_FRAMES ||
-@@ -757,7 +1746,7 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+@@ -757,7 +1752,7 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
  	    (state == MT76_TM_STATE_OFF &&
  	     prev_state == MT76_TM_STATE_IDLE)) {
  		u32 changed = 0;
@@ -1928,7 +1950,7 @@
  
  		for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
  			u16 cur = tm_change_map[i];
-@@ -766,6 +1755,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+@@ -766,6 +1761,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
  				changed |= BIT(i);
  		}
  
@@ -1939,7 +1961,7 @@
  		mt7915_tm_update_params(phy, changed);
  	}
  
-@@ -778,10 +1771,8 @@ mt7915_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb,
+@@ -778,10 +1777,8 @@ mt7915_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb,
  {
  	struct mt76_testmode_data *td = &mphy->test;
  	struct mt7915_phy *phy = mphy->priv;
@@ -1952,7 +1974,7 @@
  
  	BUILD_BUG_ON(NUM_TM_CHANGED >= 32);
  
-@@ -789,9 +1780,9 @@ mt7915_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb,
+@@ -789,9 +1786,9 @@ mt7915_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb,
  	    td->state == MT76_TM_STATE_OFF)
  		return 0;
  
@@ -1965,7 +1987,7 @@
  
  	for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
  		if (tb[tm_change_map[i]])
-@@ -807,6 +1798,7 @@ static int
+@@ -807,6 +1804,7 @@ static int
  mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
  {
  	struct mt7915_phy *phy = mphy->priv;
@@ -1973,7 +1995,24 @@
  	void *rx, *rssi;
  	int i;
  
-@@ -852,11 +1844,75 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
+@@ -827,6 +1825,16 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
+ 
+ 	nla_nest_end(msg, rssi);
+ 
++	rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RSSI);
++	if (!rssi)
++		return -ENOMEM;
++
++	for (i = 0; i < ARRAY_SIZE(phy->test.last_rssi); i++)
++		if (nla_put_s8(msg, i, phy->test.last_rssi[i]))
++			return -ENOMEM;
++
++	nla_nest_end(msg, rssi);
++
+ 	rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_IB_RSSI);
+ 	if (!rssi)
+ 		return -ENOMEM;
+@@ -852,11 +1860,75 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
  
  	nla_nest_end(msg, rx);
  
@@ -2365,10 +2404,18 @@
 +
  #endif
 diff --git a/testmode.c b/testmode.c
-index 1b37392..d2cef5b 100644
+index 1b37392..b39fef4 100644
 --- a/testmode.c
 +++ b/testmode.c
-@@ -28,28 +28,16 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
+@@ -8,6 +8,7 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
+ 	[MT76_TM_ATTR_RESET] = { .type = NLA_FLAG },
+ 	[MT76_TM_ATTR_STATE] = { .type = NLA_U8 },
+ 	[MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 },
++	[MT76_TM_ATTR_SKU_EN] = { .type = NLA_U8 },
+ 	[MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 },
+ 	[MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 },
+ 	[MT76_TM_ATTR_TX_RATE_NSS] = { .type = NLA_U8 },
+@@ -28,28 +29,16 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
  };
  EXPORT_SYMBOL_GPL(mt76_tm_policy);
  
@@ -2403,7 +2450,7 @@
  	       q->queued < q->ndesc / 2) {
  		int ret;
  
-@@ -58,13 +46,68 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy)
+@@ -58,13 +47,68 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy)
  		if (ret < 0)
  			break;
  
@@ -2473,7 +2520,7 @@
  }
  
  static u32
-@@ -90,15 +133,31 @@ mt76_testmode_max_mpdu_len(struct mt76_phy *phy, u8 tx_rate_mode)
+@@ -90,15 +134,31 @@ mt76_testmode_max_mpdu_len(struct mt76_phy *phy, u8 tx_rate_mode)
  }
  
  static void
@@ -2509,7 +2556,7 @@
  {
  #define MT_TXP_MAX_LEN	4095
  	u16 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
-@@ -119,7 +178,8 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+@@ -119,7 +179,8 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
  	nfrags = len / MT_TXP_MAX_LEN;
  	head_len = nfrags ? MT_TXP_MAX_LEN : len;
  
@@ -2519,7 +2566,7 @@
  		fc |= IEEE80211_STYPE_QOS_DATA;
  
  	head = alloc_skb(head_len, GFP_KERNEL);
-@@ -128,9 +188,9 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+@@ -128,9 +189,9 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
  
  	hdr = __skb_put_zero(head, sizeof(*hdr));
  	hdr->frame_control = cpu_to_le16(fc);
@@ -2532,7 +2579,7 @@
  	skb_set_queue_mapping(head, IEEE80211_AC_BE);
  	get_random_bytes(__skb_put(head, head_len - sizeof(*hdr)),
  			 head_len - sizeof(*hdr));
-@@ -154,7 +214,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+@@ -154,7 +215,7 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
  
  		frag = alloc_skb(frag_len, GFP_KERNEL);
  		if (!frag) {
@@ -2541,7 +2588,7 @@
  			dev_kfree_skb(head);
  			return -ENOMEM;
  		}
-@@ -167,15 +227,14 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
+@@ -167,15 +228,14 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
  		frag_tail = &(*frag_tail)->next;
  	}
  
@@ -2561,7 +2608,7 @@
  {
  	struct mt76_testmode_data *td = &phy->test;
  	struct ieee80211_tx_info *info;
-@@ -183,7 +242,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
+@@ -183,7 +243,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
  	u8 max_nss = hweight8(phy->antenna_mask);
  	int ret;
  
@@ -2570,7 +2617,7 @@
  	if (ret)
  		return ret;
  
-@@ -193,7 +252,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
+@@ -193,7 +253,7 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
  	if (td->tx_antenna_mask)
  		max_nss = min_t(u8, max_nss, hweight8(td->tx_antenna_mask));
  
@@ -2579,7 +2626,7 @@
  	rate = &info->control.rates[0];
  	rate->count = 1;
  	rate->idx = td->tx_rate_idx;
-@@ -265,6 +324,25 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
+@@ -265,6 +325,25 @@ mt76_testmode_tx_init(struct mt76_phy *phy)
  out:
  	return 0;
  }
@@ -2605,7 +2652,7 @@
  
  static void
  mt76_testmode_tx_start(struct mt76_phy *phy)
-@@ -275,6 +353,14 @@ mt76_testmode_tx_start(struct mt76_phy *phy)
+@@ -275,6 +354,14 @@ mt76_testmode_tx_start(struct mt76_phy *phy)
  	td->tx_queued = 0;
  	td->tx_done = 0;
  	td->tx_pending = td->tx_count;
@@ -2620,7 +2667,7 @@
  	mt76_worker_schedule(&dev->tx_worker);
  }
  
-@@ -293,7 +379,7 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
+@@ -293,7 +380,7 @@ mt76_testmode_tx_stop(struct mt76_phy *phy)
  	wait_event_timeout(dev->tx_wait, td->tx_done == td->tx_queued,
  			   MT76_TM_TIMEOUT * HZ);
  
@@ -2629,7 +2676,7 @@
  }
  
  static inline void
-@@ -324,6 +410,8 @@ mt76_testmode_init_defaults(struct mt76_phy *phy)
+@@ -324,6 +411,8 @@ mt76_testmode_init_defaults(struct mt76_phy *phy)
  	memcpy(td->addr[0], phy->macaddr, ETH_ALEN);
  	memcpy(td->addr[1], phy->macaddr, ETH_ALEN);
  	memcpy(td->addr[2], phy->macaddr, ETH_ALEN);
@@ -2638,7 +2685,7 @@
  }
  
  static int
-@@ -333,8 +421,12 @@ __mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
+@@ -333,8 +422,12 @@ __mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
  	struct mt76_dev *dev = phy->dev;
  	int err;
  
@@ -2652,7 +2699,7 @@
  
  	if (state == MT76_TM_STATE_TX_FRAMES) {
  		err = mt76_testmode_tx_init(phy);
-@@ -404,6 +496,44 @@ mt76_tm_get_u8(struct nlattr *attr, u8 *dest, u8 min, u8 max)
+@@ -404,6 +497,44 @@ mt76_tm_get_u8(struct nlattr *attr, u8 *dest, u8 min, u8 max)
  	return 0;
  }
  
@@ -2697,7 +2744,7 @@
  int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  		      void *data, int len)
  {
-@@ -427,6 +557,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -427,6 +558,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  
  	mutex_lock(&dev->mutex);
  
@@ -2709,7 +2756,17 @@
  	if (tb[MT76_TM_ATTR_RESET]) {
  		mt76_testmode_set_state(phy, MT76_TM_STATE_OFF);
  		memset(td, 0, sizeof(*td));
-@@ -453,7 +588,10 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -434,6 +570,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 
+ 	mt76_testmode_init_defaults(phy);
+ 
++	if (tb[MT76_TM_ATTR_SKU_EN])
++		td->sku_en = nla_get_u8(tb[MT76_TM_ATTR_SKU_EN]);
++
+ 	if (tb[MT76_TM_ATTR_TX_COUNT])
+ 		td->tx_count = nla_get_u32(tb[MT76_TM_ATTR_TX_COUNT]);
+ 
+@@ -453,7 +592,10 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_DUTY_CYCLE],
  			   &td->tx_duty_cycle, 0, 99) ||
  	    mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL],
@@ -2721,7 +2778,7 @@
  		goto out;
  
  	if (tb[MT76_TM_ATTR_TX_LENGTH]) {
-@@ -485,8 +623,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -485,8 +627,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  
  	if (tb[MT76_TM_ATTR_TX_POWER]) {
  		struct nlattr *cur;
@@ -2731,7 +2788,7 @@
  
  		nla_for_each_nested(cur, tb[MT76_TM_ATTR_TX_POWER], rem) {
  			if (nla_len(cur) != 1 ||
-@@ -506,11 +643,45 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -506,11 +647,45 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  			if (nla_len(cur) != ETH_ALEN || idx >= 3)
  				goto out;
  
@@ -2778,7 +2835,7 @@
  	if (dev->test_ops->set_params) {
  		err = dev->test_ops->set_params(phy, tb, state);
  		if (err)
-@@ -575,6 +746,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -575,6 +750,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
  	struct mt76_phy *phy = hw->priv;
  	struct mt76_dev *dev = phy->dev;
  	struct mt76_testmode_data *td = &phy->test;
@@ -2786,7 +2843,7 @@
  	struct nlattr *tb[NUM_MT76_TM_ATTRS] = {};
  	int err = 0;
  	void *a;
-@@ -607,6 +779,19 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -607,6 +783,19 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
  		goto out;
  	}
  
@@ -2806,11 +2863,12 @@
  	mt76_testmode_init_defaults(phy);
  
  	err = -EMSGSIZE;
-@@ -619,12 +804,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -619,12 +808,9 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
  		goto out;
  
  	if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
 -	    nla_put_u32(msg, MT76_TM_ATTR_TX_LENGTH, td->tx_mpdu_len) ||
++	    nla_put_u8(msg, MT76_TM_ATTR_SKU_EN, td->sku_en) ||
  	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_MODE, td->tx_rate_mode) ||
 -	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_NSS, td->tx_rate_nss) ||
 -	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_IDX, td->tx_rate_idx) ||
@@ -2819,7 +2877,7 @@
  	    nla_put_u8(msg, MT76_TM_ATTR_TX_RATE_STBC, td->tx_rate_stbc) ||
  	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_LTF) &&
  	     nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
-@@ -641,7 +822,16 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+@@ -641,7 +827,16 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
  	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER_CONTROL) &&
  	     nla_put_u8(msg, MT76_TM_ATTR_TX_POWER_CONTROL, td->tx_power_control)) ||
  	    (mt76_testmode_param_present(td, MT76_TM_ATTR_FREQ_OFFSET) &&
@@ -2838,7 +2896,7 @@
  
  	if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER)) {
 diff --git a/testmode.h b/testmode.h
-index 8961326..8c55fa0 100644
+index 8961326..7a68625 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -6,6 +6,8 @@
@@ -2850,7 +2908,15 @@
  
  /**
   * enum mt76_testmode_attr - testmode attributes inside NL80211_ATTR_TESTDATA
-@@ -47,6 +49,15 @@
+@@ -18,6 +20,7 @@
+  * @MT76_TM_ATTR_MTD_PART: mtd partition used for eeprom data (string)
+  * @MT76_TM_ATTR_MTD_OFFSET: offset of eeprom data within the partition (u32)
+  *
++ * @MT76_TM_ATTR_SKU_EN: config txpower sku is enabled or disabled in testmode (u8)
+  * @MT76_TM_ATTR_TX_COUNT: configured number of frames to send when setting
+  *	state to MT76_TM_STATE_TX_FRAMES (u32)
+  * @MT76_TM_ATTR_TX_PENDING: pending frames during MT76_TM_STATE_TX_FRAMES (u32)
+@@ -47,6 +50,15 @@
   * @MT76_TM_ATTR_DRV_DATA: driver specific netlink attrs (nested)
   *
   * @MT76_TM_ATTR_MAC_ADDRS: array of nested MAC addresses (nested)
@@ -2866,7 +2932,15 @@
   */
  enum mt76_testmode_attr {
  	MT76_TM_ATTR_UNSPEC,
-@@ -84,6 +95,17 @@ enum mt76_testmode_attr {
+@@ -57,6 +69,7 @@ enum mt76_testmode_attr {
+ 	MT76_TM_ATTR_MTD_PART,
+ 	MT76_TM_ATTR_MTD_OFFSET,
+ 
++	MT76_TM_ATTR_SKU_EN,
+ 	MT76_TM_ATTR_TX_COUNT,
+ 	MT76_TM_ATTR_TX_LENGTH,
+ 	MT76_TM_ATTR_TX_RATE_MODE,
+@@ -84,6 +97,17 @@ enum mt76_testmode_attr {
  	MT76_TM_ATTR_DRV_DATA,
  
  	MT76_TM_ATTR_MAC_ADDRS,
@@ -2884,7 +2958,23 @@
  
  	/* keep last */
  	NUM_MT76_TM_ATTRS,
-@@ -198,4 +220,57 @@ enum mt76_testmode_tx_mode {
+@@ -128,6 +152,7 @@ enum mt76_testmode_stats_attr {
+  *
+  * @MT76_TM_RX_ATTR_FREQ_OFFSET: frequency offset (s32)
+  * @MT76_TM_RX_ATTR_RCPI: received channel power indicator (array, u8)
++ * @MT76_TM_RX_ATTR_RSSI: received signal strength indicator (array, s8)
+  * @MT76_TM_RX_ATTR_IB_RSSI: internal inband RSSI (array, s8)
+  * @MT76_TM_RX_ATTR_WB_RSSI: internal wideband RSSI (array, s8)
+  * @MT76_TM_RX_ATTR_SNR: signal-to-noise ratio (u8)
+@@ -137,6 +162,7 @@ enum mt76_testmode_rx_attr {
+ 
+ 	MT76_TM_RX_ATTR_FREQ_OFFSET,
+ 	MT76_TM_RX_ATTR_RCPI,
++	MT76_TM_RX_ATTR_RSSI,
+ 	MT76_TM_RX_ATTR_IB_RSSI,
+ 	MT76_TM_RX_ATTR_WB_RSSI,
+ 	MT76_TM_RX_ATTR_SNR,
+@@ -198,4 +224,57 @@ enum mt76_testmode_tx_mode {
  
  extern const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS];
  
@@ -2943,7 +3033,7 @@
 +
  #endif
 diff --git a/tools/fields.c b/tools/fields.c
-index e3f6908..7e564a3 100644
+index e3f6908..406ba77 100644
 --- a/tools/fields.c
 +++ b/tools/fields.c
 @@ -10,6 +10,7 @@ static const char * const testmode_state[] = {
@@ -2954,6 +3044,15 @@
  };
  
  static const char * const testmode_tx_mode[] = {
+@@ -65,7 +66,7 @@ static bool parse_u8(const struct tm_field *field, int idx,
+ 
+ static void print_u8(const struct tm_field *field, struct nlattr *attr)
+ {
+-	printf("%d", nla_get_u8(attr));
++	printf("%u", nla_get_u8(attr));
+ }
+ 
+ static void print_s8(const struct tm_field *field, struct nlattr *attr)
 @@ -86,12 +87,12 @@ static void print_s32(const struct tm_field *field, struct nlattr *attr)
  
  static void print_u32(const struct tm_field *field, struct nlattr *attr)
@@ -3033,7 +3132,7 @@
  
  #define FIELD_GENERIC(_field, _name, ...)	\
  	[FIELD_NAME(_field)] = {			\
-@@ -250,6 +308,13 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
+@@ -250,10 +308,18 @@ static void print_extra_stats(const struct tm_field *field, struct nlattr **tb)
  		 ##__VA_ARGS__				\
  	)
  
@@ -3047,7 +3146,28 @@
  #define FIELD_NAME(_field) MT76_TM_RX_ATTR_##_field
  static const struct tm_field rx_fields[NUM_MT76_TM_RX_ATTRS] = {
  	FIELD_RO(s32, FREQ_OFFSET, "freq_offset"),
-@@ -300,10 +365,18 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
+ 	FIELD_ARRAY_RO(u8, RCPI, "rcpi"),
++	FIELD_ARRAY_RO(s8, RSSI, "rssi"),
+ 	FIELD_ARRAY_RO(s8, IB_RSSI, "ib_rssi"),
+ 	FIELD_ARRAY_RO(s8, WB_RSSI, "wb_rssi"),
+ 	FIELD_RO(s8, SNR, "snr"),
+@@ -261,6 +327,7 @@ static const struct tm_field rx_fields[NUM_MT76_TM_RX_ATTRS] = {
+ static struct nla_policy rx_policy[NUM_MT76_TM_RX_ATTRS] = {
+ 	[MT76_TM_RX_ATTR_FREQ_OFFSET] = { .type = NLA_U32 },
+ 	[MT76_TM_RX_ATTR_RCPI] = { .type = NLA_NESTED },
++	[MT76_TM_RX_ATTR_RSSI] = { .type = NLA_NESTED },
+ 	[MT76_TM_RX_ATTR_IB_RSSI] = { .type = NLA_NESTED },
+ 	[MT76_TM_RX_ATTR_WB_RSSI] = { .type = NLA_NESTED },
+ 	[MT76_TM_RX_ATTR_SNR] = { .type = NLA_U8 },
+@@ -291,6 +358,7 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
+ 	FIELD_ENUM(STATE, "state", testmode_state),
+ 	FIELD_RO(string, MTD_PART, "mtd_part"),
+ 	FIELD_RO(u32, MTD_OFFSET, "mtd_offset"),
++	FIELD(u8, SKU_EN, "sku_en"),
+ 	FIELD(u32, TX_COUNT, "tx_count"),
+ 	FIELD(u32, TX_LENGTH, "tx_length"),
+ 	FIELD_ENUM(TX_RATE_MODE, "tx_rate_mode", testmode_tx_mode),
+@@ -300,10 +368,18 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
  	FIELD(u8, TX_RATE_LDPC, "tx_rate_ldpc"),
  	FIELD(u8, TX_RATE_STBC, "tx_rate_stbc"),
  	FIELD(u8, TX_LTF, "tx_ltf"),
@@ -3066,7 +3186,15 @@
  	FIELD_NESTED_RO(STATS, stats, "",
  			.print_extra = print_extra_stats),
  };
-@@ -322,9 +395,16 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
+@@ -313,6 +389,7 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
+ 	[MT76_TM_ATTR_STATE] = { .type = NLA_U8 },
+ 	[MT76_TM_ATTR_MTD_PART] = { .type = NLA_STRING },
+ 	[MT76_TM_ATTR_MTD_OFFSET] = { .type = NLA_U32 },
++	[MT76_TM_ATTR_SKU_EN] = { .type = NLA_U8 },
+ 	[MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 },
+ 	[MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 },
+ 	[MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 },
+@@ -322,9 +399,16 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
  	[MT76_TM_ATTR_TX_RATE_LDPC] = { .type = NLA_U8 },
  	[MT76_TM_ATTR_TX_RATE_STBC] = { .type = NLA_U8 },
  	[MT76_TM_ATTR_TX_LTF] = { .type = NLA_U8 },