[][MAC80211][mt76][Implement iBF command mode support in testmode]

[Description]
Add mt76-test iBF commands and update iwpriv wrapper for iBF commands.

[Release-log]
N/A

Change-Id: Ic9dac7cfa2f60ee232efde677156bf1241b4c6e8
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6502057
diff --git a/autobuild_mac80211_release/package/kernel/mt76/patches/1113-mt76-testmode-add-iBF-command-mode-support.patch b/autobuild_mac80211_release/package/kernel/mt76/patches/1113-mt76-testmode-add-iBF-command-mode-support.patch
new file mode 100644
index 0000000..2cdeaae
--- /dev/null
+++ b/autobuild_mac80211_release/package/kernel/mt76/patches/1113-mt76-testmode-add-iBF-command-mode-support.patch
@@ -0,0 +1,243 @@
+From ec1151e292e2c753543f509a8817760d00aecf89 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 12 Sep 2022 18:16:54 +0800
+Subject: [PATCH 1113/1124] mt76: testmode: add iBF command mode support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: I7eea1d6412563f889e5774e787e58ce9eba001bd
+---
+ mt7915/testmode.c | 21 ++++++++++++++-------
+ testmode.c        | 41 +++++++++++++++++++++++++++++++++++++++++
+ testmode.h        |  2 ++
+ tools/fields.c    | 28 ++++++++++++++++++++++++++++
+ 4 files changed, 85 insertions(+), 7 deletions(-)
+
+diff --git a/mt7915/testmode.c b/mt7915/testmode.c
+index 7a49608..0a58ad9 100644
+--- a/mt7915/testmode.c
++++ b/mt7915/testmode.c
+@@ -701,6 +701,7 @@ mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf)
+ 	struct ieee80211_vif *vif = phy->monitor_vif;
+ 	struct mt7915_tm_pfmu_tag *tag = phy->dev->test.txbf_pfmu_tag;
+ 	u8 pfmu_idx = val[0], nc = val[2], nr;
++	bool is_atenl = val[6];
+ 	int ret;
+ 
+ 	if (td->tx_antenna_mask == 3)
+@@ -748,7 +749,7 @@ mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf)
+ 	if (ret)
+ 		return ret;
+ 
+-	if (!ebf)
++	if (!ebf && is_atenl)
+ 		return mt7915_tm_txbf_apply_tx(phy, 1, false, true, true);
+ 
+ 	return 0;
+@@ -775,7 +776,7 @@ mt7915_tm_txbf_phase_cal(struct mt7915_phy *phy, u16 *val)
+ 		.group_l_m_n = val[1],
+ 		.sx2 = val[2],
+ 		.cal_type = val[3],
+-		.lna_gain_level = 0, /* for test purpose */
++		.lna_gain_level = val[4],
+ 	};
+ 	struct mt7915_tm_txbf_phase *phase =
+ 		(struct mt7915_tm_txbf_phase *)dev->test.txbf_phase_cal;
+@@ -814,6 +815,8 @@ int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb)
+ 			phase = &phase[cal->group];
+ 			memcpy(&phase->phase, cal->buf + 16, sizeof(phase->phase));
+ 			phase->status = cal->status;
++			/* for passing iTest script */
++			dev_info(dev->mt76.dev, "Calibrated result = %d\n", phase->status);
+ 			break;
+ 		case IBF_PHASE_CAL_VERIFY:
+ 		case IBF_PHASE_CAL_VERIFY_INSTRUMENT:
+@@ -865,7 +868,6 @@ mt7915_tm_txbf_profile_update_all(struct mt7915_phy *phy, u16 *val)
+ 	pfmu_data->phi11 = cpu_to_le16(phi11);
+ 	pfmu_data->phi21 = cpu_to_le16(phi21);
+ 	pfmu_data->phi31 = cpu_to_le16(phi31);
+-
+ 	if (subc_id == 63) {
+ 		struct mt7915_dev *dev = phy->dev;
+ 		struct {
+@@ -923,8 +925,8 @@ mt7915_tm_set_txbf(struct mt7915_phy *phy)
+ 	struct mt76_testmode_data *td = &phy->mt76->test;
+ 	u16 *val = td->txbf_param;
+ 
+-	pr_info("ibf cal process: act = %u, val = %u, %u, %u, %u, %u\n",
+-		td->txbf_act, val[0], val[1], val[2], val[3], val[4]);
++	pr_info("ibf cal process: act = %u, val = %u, %u, %u, %u, %u, %u\n",
++		td->txbf_act, val[0], val[1], val[2], val[3], val[4], val[5]);
+ 
+ 	switch (td->txbf_act) {
+ 	case MT76_TM_TXBF_ACT_INIT:
+@@ -942,10 +944,17 @@ mt7915_tm_set_txbf(struct mt7915_phy *phy)
+ 		return mt7915_tm_txbf_profile_update(phy, val, true);
+ 	case MT76_TM_TXBF_ACT_PHASE_CAL:
+ 		return mt7915_tm_txbf_phase_cal(phy, val);
++	case MT76_TM_TXBF_ACT_PROF_UPDATE_ALL_CMD:
+ 	case MT76_TM_TXBF_ACT_PROF_UPDATE_ALL:
+ 		return mt7915_tm_txbf_profile_update_all(phy, val);
+ 	case MT76_TM_TXBF_ACT_E2P_UPDATE:
+ 		return mt7915_tm_txbf_e2p_update(phy);
++	case MT76_TM_TXBF_ACT_APPLY_TX: {
++		u16 wlan_idx = val[0];
++		bool ebf = !!val[1], ibf = !!val[2], phase_cal = !!val[4];
++
++		return mt7915_tm_txbf_apply_tx(phy, wlan_idx, ebf, ibf, phase_cal);
++	}
+ 	default:
+ 		break;
+ 	};
+@@ -1071,7 +1080,6 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
+ 		rate.legacy = sband->bitrates[rate.mcs].bitrate;
+ 		break;
+ 	case MT76_TM_TX_MODE_HT:
+-		rate.mcs += rate.nss * 8;
+ 		flags |= RATE_INFO_FLAGS_MCS;
+ 
+ 		if (td->tx_rate_sgi)
+@@ -1435,7 +1443,6 @@ mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en)
+ 			if (duty_cycle < 100)
+ 				tx_time = duty_cycle * ipg / (100 - duty_cycle);
+ 		}
+-
+ 		mt7915_tm_set_ipg_params(phy, ipg, td->tx_rate_mode);
+ 		mt7915_tm_set_tx_len(phy, tx_time);
+ 
+diff --git a/testmode.c b/testmode.c
+index 82b8e98..aa874a8 100644
+--- a/testmode.c
++++ b/testmode.c
+@@ -530,6 +530,42 @@ out:
+ 	return err;
+ }
+ 
++static int
++mt76_testmode_txbf_profile_update_all_cmd(struct mt76_phy *phy, struct nlattr **tb, u32 state)
++{
++#define PARAM_UNIT	5
++	static u8 pfmu_idx;
++	struct mt76_testmode_data *td = &phy->test;
++	struct mt76_dev *dev = phy->dev;
++	struct nlattr *cur;
++	u16 tmp_val[PARAM_UNIT], *val = td->txbf_param;
++	int idx, rem, ret, i = 0;
++
++	memset(td->txbf_param, 0, sizeof(td->txbf_param));
++	nla_for_each_nested(cur, tb[MT76_TM_ATTR_TXBF_PARAM], rem) {
++		if (nla_len(cur) != 2)
++			return -EINVAL;
++		idx = i % PARAM_UNIT;
++		tmp_val[idx] = nla_get_u16(cur);
++		if (idx == 1 && (tmp_val[idx] == 0xf0 || tmp_val[idx] == 0xff)) {
++			pfmu_idx = tmp_val[0];
++			return 0;
++		}
++		if (idx == PARAM_UNIT - 1) {
++			val[0] = pfmu_idx;
++			memcpy(val + 1, tmp_val, sizeof(tmp_val));
++			if (dev->test_ops->set_params) {
++				ret = dev->test_ops->set_params(phy, tb, state);
++				if (ret)
++					return ret;
++			}
++		}
++		i++;
++	}
++
++	return 0;
++}
++
+ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 		      void *data, int len)
+ {
+@@ -668,6 +704,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 		    0, MT76_TM_TXBF_ACT_MAX))
+ 			goto out;
+ 
++		if (td->txbf_act == MT76_TM_TXBF_ACT_PROF_UPDATE_ALL_CMD) {
++			err = mt76_testmode_txbf_profile_update_all_cmd(phy, tb, state);
++			goto out;
++		}
++
+ 		memset(td->txbf_param, 0, sizeof(td->txbf_param));
+ 		nla_for_each_nested(cur, tb[MT76_TM_ATTR_TXBF_PARAM], rem) {
+ 			if (nla_len(cur) != 2 ||
+diff --git a/testmode.h b/testmode.h
+index e2190e7..5d1fe79 100644
+--- a/testmode.h
++++ b/testmode.h
+@@ -281,8 +281,10 @@ enum mt76_testmode_txbf_act {
+ 	MT76_TM_TXBF_ACT_TX_PREP,
+ 	MT76_TM_TXBF_ACT_IBF_PROF_UPDATE,
+ 	MT76_TM_TXBF_ACT_EBF_PROF_UPDATE,
++	MT76_TM_TXBF_ACT_APPLY_TX,
+ 	MT76_TM_TXBF_ACT_PHASE_CAL,
+ 	MT76_TM_TXBF_ACT_PROF_UPDATE_ALL,
++	MT76_TM_TXBF_ACT_PROF_UPDATE_ALL_CMD,
+ 	MT76_TM_TXBF_ACT_E2P_UPDATE,
+ 
+ 	/* keep last */
+diff --git a/tools/fields.c b/tools/fields.c
+index 1be1ffd..47fc69f 100644
+--- a/tools/fields.c
++++ b/tools/fields.c
+@@ -32,6 +32,20 @@ static const char * const testmode_tx_mode[] = {
+ 	[MT76_TM_TX_MODE_HE_MU] = "he_mu",
+ };
+ 
++static const char * const testmode_txbf_act[] = {
++	[MT76_TM_TXBF_ACT_INIT] = "init",
++	[MT76_TM_TXBF_ACT_UPDATE_CH] = "update_ch",
++	[MT76_TM_TXBF_ACT_PHASE_COMP] = "phase_comp",
++	[MT76_TM_TXBF_ACT_TX_PREP] = "tx_prep",
++	[MT76_TM_TXBF_ACT_IBF_PROF_UPDATE] = "ibf_prof_update",
++	[MT76_TM_TXBF_ACT_EBF_PROF_UPDATE] = "ebf_prof_update",
++	[MT76_TM_TXBF_ACT_APPLY_TX] = "apply_tx",
++	[MT76_TM_TXBF_ACT_PHASE_CAL] = "phase_cal",
++	[MT76_TM_TXBF_ACT_PROF_UPDATE_ALL] = "prof_update",
++	[MT76_TM_TXBF_ACT_PROF_UPDATE_ALL_CMD] = "prof_update_all",
++	[MT76_TM_TXBF_ACT_E2P_UPDATE] = "e2p_update",
++};
++
+ static void print_enum(const struct tm_field *field, struct nlattr *attr)
+ {
+ 	unsigned int i = nla_get_u8(attr);
+@@ -82,6 +96,17 @@ static void print_s8(const struct tm_field *field, struct nlattr *attr)
+ 	printf("%d", (int8_t)nla_get_u8(attr));
+ }
+ 
++static bool parse_u16_hex(const struct tm_field *field, int idx,
++			  struct nl_msg *msg, const char *val)
++{
++	return !nla_put_u16(msg, idx, strtoul(val, NULL, 16));
++}
++
++static void print_u16_hex(const struct tm_field *field, struct nlattr *attr)
++{
++	printf("%d", nla_get_u16(attr));
++}
++
+ static bool parse_u32(const struct tm_field *field, int idx,
+ 		      struct nl_msg *msg, const char *val)
+ {
+@@ -384,6 +409,8 @@ static const struct tm_field testdata_fields[NUM_MT76_TM_ATTRS] = {
+ 	FIELD(u8, AID, "aid"),
+ 	FIELD(u8, RU_ALLOC, "ru_alloc"),
+ 	FIELD(u8, RU_IDX, "ru_idx"),
++	FIELD_ENUM(TXBF_ACT, "txbf_act", testmode_txbf_act),
++	FIELD_ARRAY(u16_hex, TXBF_PARAM, "txbf_param"),
+ 	FIELD_MAC(MAC_ADDRS, "mac_addrs"),
+ 	FIELD_NESTED_RO(STATS, stats, "",
+ 			.print_extra = print_extra_stats),
+@@ -414,6 +441,7 @@ static struct nla_policy testdata_policy[NUM_MT76_TM_ATTRS] = {
+ 	[MT76_TM_ATTR_RU_ALLOC] = { .type = NLA_U8 },
+ 	[MT76_TM_ATTR_RU_IDX] = { .type = NLA_U8 },
+ 	[MT76_TM_ATTR_STATS] = { .type = NLA_NESTED },
++	[MT76_TM_ATTR_TXBF_ACT] = { .type = NLA_U8 },
+ };
+ 
+ const struct tm_field msg_field = {
+-- 
+2.18.0
+