[rdkb][common][bsp][Refactor and sync wifi from openwrt]

[Description]
bb1ab020 [MAC80211][WiFi6][mt76][Fix STA channel switch reason during auth/assoc for DFS channel]
e1340c0f [MAC80211][WiFi6][core][Fix STA channel switch reason during auth/assoc for DFS channel]
cf503970 [MAC80211][WiFi7][misc][Remove testmode default eeprom bin]
b37abd10 [MAC80211][WiFi6/7][Misc][Fix build fail because of mt76 version upgradation]
b7b7f0c4 [MAC80211][WiFi6][core][Fix build fail]
8097da40 [MAC80211][wifi6][MT76][Rebase mt76 to 2024-03-18]
c0f79602 [MAC80211][WiFi7][app][Add ibf ver2 command support in iwpriv wrapper]
36839dc7 [MAC80211][WiFi6][core][Sync wifi7 cert SQC fix to wifi6]
159f6fc1 [MAC82011][Wifi6][MT76][Fix power on sequence]
0e60d7d6 [MAC80211][wifi6][MT76][Add adie id and version in debugfs]
0dfc6240 [MAC80211][WiFi6][core][Refactor STA CSA paring flow]
d2f1ea53 [MAC80211][mt76][fix issue that when one phy is scanning and another phy occur packet loss]
eae6a6c1 [MAC80211][WED][Fix Eagle mlo tx T.P too low issue]
4c3ca8f0 [MAC80211][WiFi6][mt76][Fix HE Phy cap IE for station mode]
602ca651 [MAC80211][WiFi6][mt76][Add ZWDFS foolproof mechanism during radar trigger & detection]
df0ebcec [MAC80211][WiFi7][misc][Add WiFi7 MLO autobuild folder]
e318c6da [mac80211][wifi6][mt76][Remove unnecessary register settings]
c6a3c4c3 [MAC80211][WiFi6][mt76][Add background radar hw cap checking mechanism]
c25db7a0 [MAC80211][WiFi6][Misc][Fix default /etc/config/wireless setting and backport wpa_supp patch of CVE-2023-52160]
839f446d [MAC80211][WiFi6][Rebase Patches][Fix patch fail]
66194787 [MAC80211][wifi6][mt76][Add per-band token limits and debugfs]
85e8e415 [MAC80211][WiFi6][Misc][Change default WiFi 5GHz setting to BW160 expect for MT7915]
64256fee [MAC80211][WED][Fix kite RX T.P ~0 due to sync upstream]
6be2154a [MAC80211][WiFi6][core][fix AP mgmt not encrypted in WDS mode with PMF on]
92223c79 [MAC80211][mt76][sync SER patch.]
0c7cec54 [MAC80211][WiFi7][MT76][Sync internal patches to release build]
421f7b74 [MAC80211][WiFi6][mt76][Refactor backaward patch due to wed sync to upstream]
0471b20c [MAC80211][WED][Refactor and sync wed patches from upstream]
e0ab6314 [mac80211][wifi6][mt76][Fix unusual Tx/Rx airtime duration values]
632ed0a5 [MAC80211][WiFi7][core][Sync to backports-6.6.15]

[Release-log]

Change-Id: I8731a065c32a92b78d3cb8ac6fc292f493d1be65
diff --git a/recipes-wifi/linux-mt76/files/patches/1009-wifi-mt76-testmode-add-pre-cal-support.patch b/recipes-wifi/linux-mt76/files/patches/1009-wifi-mt76-testmode-add-pre-cal-support.patch
new file mode 100644
index 0000000..811d441
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches/1009-wifi-mt76-testmode-add-pre-cal-support.patch
@@ -0,0 +1,740 @@
+From 4ce9209f811922ef634475db68a446803d822ab0 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Wed, 31 Aug 2022 20:06:52 +0800
+Subject: [PATCH 1009/1051] wifi: mt76: testmode: add pre-cal support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ eeprom.c          |   6 +-
+ mt76.h            |   1 +
+ mt76_connac_mcu.h |   1 +
+ mt7915/mcu.c      |   3 +
+ mt7915/mt7915.h   |   1 +
+ mt7915/testmode.c | 425 +++++++++++++++++++++++++++++++++++++++++++++-
+ mt7915/testmode.h |  36 ++++
+ testmode.c        |  15 +-
+ testmode.h        |  17 ++
+ tools/fields.c    |   8 +
+ 10 files changed, 506 insertions(+), 7 deletions(-)
+
+diff --git a/eeprom.c b/eeprom.c
+index a2673978..3625b169 100644
+--- a/eeprom.c
++++ b/eeprom.c
+@@ -94,8 +94,10 @@ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int l
+ 	}
+ 
+ #ifdef CONFIG_NL80211_TESTMODE
+-	dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
+-	dev->test_mtd.offset = offset;
++	if (len == dev->eeprom.size) {
++		dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
++		dev->test_mtd.offset = offset;
++	}
+ #endif
+ 
+ out_put_node:
+diff --git a/mt76.h b/mt76.h
+index 3fe18cd1..22d76bb1 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -708,6 +708,7 @@ struct mt76_testmode_ops {
+ 			  enum mt76_testmode_state new_state);
+ 	int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
+ 	int (*set_eeprom)(struct mt76_phy *phy, u32 offset, u8 *val, u8 action);
++	int (*dump_precal)(struct mt76_phy *phy, struct sk_buff *msg, int flag, int type);
+ };
+ 
+ struct mt76_testmode_entry_data {
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 49a3406d..1a32268b 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1012,6 +1012,7 @@ enum {
+ 
+ /* ext event table */
+ enum {
++	MCU_EXT_EVENT_RF_TEST = 0x4,
+ 	MCU_EXT_EVENT_PS_SYNC = 0x5,
+ 	MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13,
+ 	MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
+diff --git a/mt7915/mcu.c b/mt7915/mcu.c
+index 233411ca..ad58e3b6 100644
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -482,6 +482,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
+ 	case MCU_EXT_EVENT_BF_STATUS_READ:
+ 		mt7915_tm_txbf_status_read(dev, skb);
+ 		break;
++	case MCU_EXT_EVENT_RF_TEST:
++		mt7915_tm_rf_test_event(dev, skb);
++		break;
+ #endif
+ 	case MCU_EXT_EVENT_BSS_ACQ_PKT_CNT:
+ 		mt7915_mcu_rx_bss_acq_pkt_cnt(dev, skb);
+diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
+index 1846e2f9..dd2e80b8 100644
+--- a/mt7915/mt7915.h
++++ b/mt7915/mt7915.h
+@@ -654,6 +654,7 @@ 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);
+ int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb);
++void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb);
+ void mt7915_mcu_wmm_pbc_work(struct work_struct *work);
+ 
+ static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
+diff --git a/mt7915/testmode.c b/mt7915/testmode.c
+index 32dc85cd..4b344303 100644
+--- a/mt7915/testmode.c
++++ b/mt7915/testmode.c
+@@ -5,6 +5,7 @@
+ #include "mac.h"
+ #include "mcu.h"
+ #include "testmode.h"
++#include "eeprom.h"
+ 
+ enum {
+ 	TM_CHANGED_TXPOWER,
+@@ -1604,18 +1605,16 @@ mt7915_tm_rf_switch_mode(struct mt7915_dev *dev, u32 oper)
+ static int
+ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
+ {
+-#define TX_CONT_START	0x05
+-#define TX_CONT_STOP	0x06
+ 	struct mt7915_dev *dev = phy->dev;
+ 	struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
+ 	int freq1 = ieee80211_frequency_to_channel(chandef->center_freq1);
+ 	struct mt76_testmode_data *td = &phy->mt76->test;
+-	u32 func_idx = en ? TX_CONT_START : TX_CONT_STOP;
++	u32 func_idx = en ? RF_TEST_TX_CONT_START : RF_TEST_TX_CONT_STOP;
+ 	u8 rate_idx = td->tx_rate_idx, mode;
+ 	u8 band = phy->mt76->band_idx;
+ 	u16 rateval;
+ 	struct mt7915_tm_rf_test req = {
+-		.action = 1,
++		.action = RF_ACT_IN_RFTEST,
+ 		.icap_len = 120,
+ 		.op.rf.func_idx = cpu_to_le32(func_idx),
+ 	};
+@@ -1700,6 +1699,316 @@ out:
+ 				 sizeof(req), true);
+ }
+ 
++static int
++mt7915_tm_group_prek(struct mt7915_phy *phy, enum mt76_testmode_state state)
++{
++	u8 *eeprom;
++	u32 i, group_size, dpd_size, size, offs, *pre_cal;
++	int ret = 0;
++	struct mt7915_dev *dev = phy->dev;
++	struct mt76_dev *mdev = &dev->mt76;
++	struct mt7915_tm_rf_test req = {
++		.action = RF_ACT_IN_RFTEST,
++		.icap_len = 8,
++		.op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
++	};
++
++	if (!dev->flash_mode && !dev->bin_file_mode) {
++		dev_err(dev->mt76.dev, "Currently not in FLASH or BIN MODE,return!\n");
++		return 1;
++	}
++
++	eeprom = mdev->eeprom.data;
++	dev->cur_prek_offset = 0;
++	group_size = mt7915_get_cal_group_size(dev);
++	dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2;
++	size = group_size + dpd_size;
++	offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
++
++	switch (state) {
++	case MT76_TM_STATE_GROUP_PREK:
++		req.op.rf.param.cal_param.func_data = cpu_to_le32(RF_PRE_CAL);
++
++		if (!dev->cal) {
++			dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
++			if (!dev->cal)
++				return -ENOMEM;
++		}
++
++		ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
++					sizeof(req), true);
++
++		if (!ret)
++			eeprom[offs] |= MT_EE_WIFI_CAL_GROUP;
++		break;
++	case MT76_TM_STATE_GROUP_PREK_DUMP:
++		pre_cal = (u32 *)dev->cal;
++		if (!pre_cal) {
++			dev_info(dev->mt76.dev, "Not group pre-cal yet!\n");
++			return ret;
++		}
++		dev_info(dev->mt76.dev, "Group Pre-Cal:\n");
++		for (i = 0; i < (group_size / sizeof(u32)); i += 4) {
++			dev_info(dev->mt76.dev, "[0x%08lx] 0x%8x 0x%8x 0x%8x 0x%8x\n",
++				 i * sizeof(u32), pre_cal[i], pre_cal[i + 1],
++				 pre_cal[i + 2], pre_cal[i + 3]);
++		}
++		break;
++	case MT76_TM_STATE_GROUP_PREK_CLEAN:
++		pre_cal = (u32 *)dev->cal;
++		if (!pre_cal)
++			return ret;
++		memset(pre_cal, 0, group_size);
++		eeprom[offs] &= ~MT_EE_WIFI_CAL_GROUP;
++		break;
++	default:
++		return -EINVAL;
++	}
++	return ret;
++}
++
++static int
++mt7915_tm_dpd_prek(struct mt7915_phy *phy, enum mt76_testmode_state state)
++{
++#define DPD_2G_CH_BW20_BITMAP_0         0x444
++#define DPD_5G_CH_BW20_BITMAP_0         0xffffc0ff
++#define DPD_5G_CH_BW20_BITMAP_1         0x3
++#define DPD_5G_CH_BW20_BITMAP_7915_0    0x7dffc0ff
++#define DPD_6G_CH_BW20_BITMAP_0         0xffffffff
++#define DPD_6G_CH_BW20_BITMAP_1         0x07ffffff
++	bool is_set = false;
++	u8 band, do_precal, *eeprom;
++	u16 bw20_size, bw160_size;
++	u32 i, j, *bw160_freq, bw160_5g_freq[] = {5250, 5570, 5815};
++	u32 bw160_6g_freq[] = {6025, 6185, 6345, 6505, 6665, 6825, 6985};
++	u32 shift, freq, group_size, dpd_size, size, offs, *pre_cal, dpd_ch_bw20_bitmap[2] = {0};
++	__le32 func_data = 0;
++	int ret = 0;
++	struct mt7915_dev *dev = phy->dev;
++	struct mt76_dev *mdev = &dev->mt76;
++	struct mt76_phy *mphy = phy->mt76;
++	struct cfg80211_chan_def chandef_backup, *chandef = &mphy->chandef;
++	struct ieee80211_channel chan_backup, chan, *bw20_ch;
++	struct mt7915_tm_rf_test req = {
++		.action = RF_ACT_IN_RFTEST,
++		.icap_len = 8,
++		.op.rf.func_idx = cpu_to_le32(RF_TEST_RE_CAL),
++	};
++
++	if (!dev->flash_mode && !dev->bin_file_mode) {
++		dev_err(dev->mt76.dev, "Currently not in FLASH or BIN MODE,return!\n");
++		return -EOPNOTSUPP;
++	}
++
++	eeprom = mdev->eeprom.data;
++	dev->cur_prek_offset = 0;
++	group_size = mt7915_get_cal_group_size(dev);
++	dev->dpd_chan_num_2g = hweight32(DPD_2G_CH_BW20_BITMAP_0);
++	if (is_mt7915(&dev->mt76)) {
++		dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_7915_0);
++		dev->dpd_chan_num_6g = 0;
++		dpd_size = MT_EE_CAL_DPD_SIZE_V1;
++		offs = MT_EE_DO_PRE_CAL;
++	} else {
++		dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_0) +
++				       hweight32(DPD_5G_CH_BW20_BITMAP_1) +
++				       ARRAY_SIZE(bw160_5g_freq);
++		dev->dpd_chan_num_6g = hweight32(DPD_6G_CH_BW20_BITMAP_0) +
++				       hweight32(DPD_6G_CH_BW20_BITMAP_1) +
++				       ARRAY_SIZE(bw160_6g_freq);
++		dpd_size = MT_EE_CAL_DPD_SIZE_V2;
++		offs = MT_EE_DO_PRE_CAL_V2;
++	}
++	size = group_size + dpd_size;
++
++	switch (state) {
++	case MT76_TM_STATE_DPD_2G:
++		if (!is_set) {
++			func_data = cpu_to_le32(RF_DPD_FLAT_CAL);
++			dpd_ch_bw20_bitmap[0] = DPD_2G_CH_BW20_BITMAP_0;
++			bw20_ch = mphy->sband_2g.sband.channels;
++			bw160_freq = NULL;
++			bw160_size = 0;
++			band = NL80211_BAND_2GHZ;
++			do_precal = MT_EE_WIFI_CAL_DPD_2G;
++			is_set = true;
++		}
++		fallthrough;
++	case MT76_TM_STATE_DPD_5G:
++		if (!is_set) {
++			if (is_mt7915(&dev->mt76)) {
++				func_data = cpu_to_le32(RF_DPD_FLAT_CAL);
++				dpd_ch_bw20_bitmap[0] = DPD_5G_CH_BW20_BITMAP_7915_0;
++				bw160_size = 0;
++				dev->cur_prek_offset -= dev->dpd_chan_num_5g * MT_EE_CAL_UNIT * 2;
++			} else {
++				func_data = cpu_to_le32(RF_DPD_FLAT_5G_CAL);
++				dpd_ch_bw20_bitmap[0] = DPD_5G_CH_BW20_BITMAP_0;
++				dpd_ch_bw20_bitmap[1] = DPD_5G_CH_BW20_BITMAP_1;
++				bw160_size = ARRAY_SIZE(bw160_5g_freq);
++			}
++			bw20_ch = mphy->sband_5g.sband.channels;
++			bw160_freq = bw160_5g_freq;
++			band = NL80211_BAND_5GHZ;
++			do_precal = MT_EE_WIFI_CAL_DPD_5G;
++			is_set = true;
++		}
++		fallthrough;
++	case MT76_TM_STATE_DPD_6G:
++		if (!is_set) {
++			func_data = cpu_to_le32(RF_DPD_FLAT_6G_CAL);
++			dpd_ch_bw20_bitmap[0] = DPD_6G_CH_BW20_BITMAP_0;
++			dpd_ch_bw20_bitmap[1] = DPD_6G_CH_BW20_BITMAP_1;
++			bw20_ch = mphy->sband_6g.sband.channels;
++			bw160_freq = bw160_6g_freq;
++			bw160_size = ARRAY_SIZE(bw160_6g_freq);
++			band = NL80211_BAND_6GHZ;
++			do_precal = MT_EE_WIFI_CAL_DPD_6G;
++			is_set = true;
++		}
++
++		if (!bw20_ch)
++			return -EOPNOTSUPP;
++		if (!dev->cal) {
++			dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
++			if (!dev->cal)
++				return -ENOMEM;
++		}
++
++		req.op.rf.param.cal_param.func_data = func_data;
++		req.op.rf.param.cal_param.band_idx = phy->mt76->band_idx;
++
++		memcpy(&chan_backup, chandef->chan, sizeof(struct ieee80211_channel));
++		memcpy(&chandef_backup, chandef, sizeof(struct cfg80211_chan_def));
++
++		bw20_size = hweight32(dpd_ch_bw20_bitmap[0]) + hweight32(dpd_ch_bw20_bitmap[1]);
++		for (i = 0, j = 0; i < bw20_size + bw160_size; i++) {
++			if (i < bw20_size) {
++				freq = dpd_ch_bw20_bitmap[0] ? 0 : 1;
++				shift = ffs(dpd_ch_bw20_bitmap[freq]);
++				j += shift;
++				memcpy(&chan, &bw20_ch[j - 1], sizeof(struct ieee80211_channel));
++				chandef->width = NL80211_CHAN_WIDTH_20;
++				dpd_ch_bw20_bitmap[0] >>= shift;
++			} else {
++				freq = bw160_freq[i - bw20_size];
++				chan.center_freq = freq;
++				chan.hw_value = ieee80211_frequency_to_channel(freq);
++				chan.band = band;
++				chandef->width = NL80211_CHAN_WIDTH_160;
++			}
++
++			memcpy(chandef->chan, &chan, sizeof(struct ieee80211_channel));
++			if (is_mt7915(&dev->mt76))
++				mphy->hw->conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
++			else
++				mphy->hw->conf.flags |= IEEE80211_CONF_OFFCHANNEL;
++
++			mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
++
++			ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
++						sizeof(req), true);
++			if (ret) {
++				dev_err(dev->mt76.dev, "DPD Pre-cal: mcu send msg failed!\n");
++				break;
++			}
++		}
++		memcpy(chandef, &chandef_backup, sizeof(struct cfg80211_chan_def));
++		memcpy(chandef->chan, &chan_backup, sizeof(struct ieee80211_channel));
++		mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
++
++		if (!ret)
++			eeprom[offs] |= do_precal;
++
++		break;
++	case MT76_TM_STATE_DPD_DUMP:
++		pre_cal = (u32 *)dev->cal;
++		if (!dev->cal) {
++			dev_info(dev->mt76.dev, "Not DPD pre-cal yet!\n");
++			return ret;
++		}
++		dev_info(dev->mt76.dev, "DPD Pre-Cal:\n");
++		for (i = 0; i < dpd_size / sizeof(u32); i += 4) {
++			j = i + (group_size / sizeof(u32));
++			dev_info(dev->mt76.dev, "[0x%08lx] 0x%8x 0x%8x 0x%8x 0x%8x\n",
++				 j * sizeof(u32), pre_cal[j], pre_cal[j + 1],
++				 pre_cal[j + 2], pre_cal[j + 3]);
++		}
++		break;
++	case MT76_TM_STATE_DPD_CLEAN:
++		pre_cal = (u32 *)dev->cal;
++		if (!pre_cal)
++			return ret;
++		memset(pre_cal + (group_size / sizeof(u32)), 0, dpd_size);
++		do_precal = MT_EE_WIFI_CAL_DPD;
++		eeprom[offs] &= ~do_precal;
++		break;
++	default:
++		return -EINVAL;
++	}
++	return ret;
++}
++
++void mt7915_tm_re_cal_event(struct mt7915_dev *dev, struct mt7915_tm_rf_test_result *result,
++			    struct mt7915_tm_rf_test_data *data)
++{
++#define DPD_PER_CHAN_SIZE_7915	2
++#define DPD_PER_CHAN_SIZE_7986	3
++	u32 base, dpd_offest_2g, dpd_offest_5g, cal_idx = 0, cal_type = 0, len = 0;
++	u8 *pre_cal;
++
++	pre_cal = dev->cal;
++	dpd_offest_5g = dev->dpd_chan_num_6g * DPD_PER_CHAN_SIZE_7986 * MT_EE_CAL_UNIT;
++	dpd_offest_2g = dpd_offest_5g + dev->dpd_chan_num_5g * MT_EE_CAL_UNIT *
++			(is_mt7915(&dev->mt76) ? DPD_PER_CHAN_SIZE_7915 : DPD_PER_CHAN_SIZE_7986);
++	cal_idx = le32_to_cpu(data->cal_idx);
++	cal_type = le32_to_cpu(data->cal_type);
++	len = le32_to_cpu(result->payload_len);
++	len = len - sizeof(struct mt7915_tm_rf_test_data);
++
++	switch (cal_type) {
++	case RF_PRE_CAL:
++		base = 0;
++		break;
++	case RF_DPD_FLAT_CAL:
++		base = mt7915_get_cal_group_size(dev) + dpd_offest_2g;
++		break;
++	case RF_DPD_FLAT_5G_CAL:
++		base = mt7915_get_cal_group_size(dev) + dpd_offest_5g;
++		break;
++	case RF_DPD_FLAT_6G_CAL:
++		base = mt7915_get_cal_group_size(dev);
++		break;
++	default:
++		dev_info(dev->mt76.dev, "Unknown calibration type!\n");
++		return;
++	}
++	pre_cal += (base + dev->cur_prek_offset);
++
++	memcpy(pre_cal, data->data, len);
++	dev->cur_prek_offset += len;
++}
++
++void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb)
++{
++	struct mt7915_tm_rf_test_result *result;
++	struct mt7915_tm_rf_test_data *data;
++	static u32 event_type;
++
++	result = (struct mt7915_tm_rf_test_result *)skb->data;
++	data = (struct mt7915_tm_rf_test_data *)result->event;
++
++	event_type = le32_to_cpu(result->func_idx);
++
++	switch (event_type) {
++	case RF_TEST_RE_CAL:
++		mt7915_tm_re_cal_event(dev, result, data);
++		break;
++	default:
++		break;
++	}
++}
++
+ static void
+ mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
+ {
+@@ -1750,6 +2059,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+ 	else if (prev_state == MT76_TM_STATE_OFF ||
+ 		 state == MT76_TM_STATE_OFF)
+ 		mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));
++	else if (state >= MT76_TM_STATE_GROUP_PREK && state <= MT76_TM_STATE_GROUP_PREK_CLEAN)
++		return mt7915_tm_group_prek(phy, state);
++	else if (state >= MT76_TM_STATE_DPD_2G && state <= MT76_TM_STATE_DPD_CLEAN)
++		return mt7915_tm_dpd_prek(phy, state);
+ 
+ 	if ((state == MT76_TM_STATE_IDLE &&
+ 	     prev_state == MT76_TM_STATE_OFF) ||
+@@ -1930,9 +2243,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
+ 	return ret;
+ }
+ 
++static int
++mt7915_tm_dump_precal(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int type)
++{
++#define DPD_PER_CHAN_SIZE_MASK		GENMASK(31, 30)
++#define DPD_CHAN_NUM_2G_MASK		GENMASK(29, 20)
++#define DPD_CHAN_NUM_5G_MASK		GENMASK(19, 10)
++#define DPD_CHAN_NUM_6G_MASK		GENMASK(9, 0)
++	struct mt7915_phy *phy = mphy->priv;
++	struct mt7915_dev *dev = phy->dev;
++	u32 i, group_size, dpd_size, total_size, dpd_per_chan_size, dpd_info = 0;
++	u32 base, size, total_chan_num, offs, transmit_size = 1000;
++	u8 *pre_cal, *eeprom;
++	void *precal;
++	enum prek_ops {
++		PREK_GET_INFO,
++		PREK_SYNC_ALL,
++		PREK_SYNC_GROUP,
++		PREK_SYNC_DPD_2G,
++		PREK_SYNC_DPD_5G,
++		PREK_SYNC_DPD_6G,
++		PREK_CLEAN_GROUP,
++		PREK_CLEAN_DPD,
++	};
++
++	if (!dev->cal) {
++		dev_info(dev->mt76.dev, "Not pre-cal yet!\n");
++		return 0;
++	}
++
++	group_size = mt7915_get_cal_group_size(dev);
++	dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2;
++	dpd_per_chan_size = is_mt7915(&dev->mt76) ? 2 : 3;
++	total_size = group_size + dpd_size;
++	pre_cal = dev->cal;
++	eeprom = dev->mt76.eeprom.data;
++	offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
++
++	total_chan_num = dev->dpd_chan_num_2g + dev->dpd_chan_num_5g + dev->dpd_chan_num_6g;
++
++	switch (type) {
++	case PREK_SYNC_ALL:
++		base = 0;
++		size = total_size;
++		break;
++	case PREK_SYNC_GROUP:
++		base = 0;
++		size = group_size;
++		break;
++	case PREK_SYNC_DPD_6G:
++		base = group_size;
++		size = dpd_size * dev->dpd_chan_num_6g / total_chan_num;
++		break;
++	case PREK_SYNC_DPD_5G:
++		base = group_size + dev->dpd_chan_num_6g * dpd_per_chan_size * MT_EE_CAL_UNIT;
++		size = dpd_size * dev->dpd_chan_num_5g / total_chan_num;
++		break;
++	case PREK_SYNC_DPD_2G:
++		base = group_size + (dev->dpd_chan_num_6g + dev->dpd_chan_num_5g) *
++			   dpd_per_chan_size * MT_EE_CAL_UNIT;
++		size = dpd_size * dev->dpd_chan_num_2g / total_chan_num;
++		break;
++	case PREK_GET_INFO:
++		break;
++	default:
++		return 0;
++	}
++
++	if (!flag) {
++		if (eeprom[offs] & MT_EE_WIFI_CAL_DPD) {
++			dpd_info |= u32_encode_bits(dpd_per_chan_size, DPD_PER_CHAN_SIZE_MASK) |
++				    u32_encode_bits(dev->dpd_chan_num_2g, DPD_CHAN_NUM_2G_MASK) |
++				    u32_encode_bits(dev->dpd_chan_num_5g, DPD_CHAN_NUM_5G_MASK) |
++				    u32_encode_bits(dev->dpd_chan_num_6g, DPD_CHAN_NUM_6G_MASK);
++		}
++		dev->cur_prek_offset = 0;
++		precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL_INFO);
++		if (!precal)
++			return -ENOMEM;
++		nla_put_u32(msg, 0, group_size);
++		nla_put_u32(msg, 1, dpd_size);
++		nla_put_u32(msg, 2, dpd_info);
++		nla_put_u32(msg, 3, transmit_size);
++		nla_put_u32(msg, 4, eeprom[offs]);
++		nla_nest_end(msg, precal);
++	} else {
++		precal = nla_nest_start(msg, MT76_TM_ATTR_PRECAL);
++		if (!precal)
++			return -ENOMEM;
++
++		transmit_size = (dev->cur_prek_offset + transmit_size < size) ?
++				transmit_size : (size - dev->cur_prek_offset);
++		for (i = 0; i < transmit_size; i++) {
++			if (nla_put_u8(msg, i, pre_cal[base + dev->cur_prek_offset + i]))
++				return -ENOMEM;
++		}
++		dev->cur_prek_offset += transmit_size;
++
++		nla_nest_end(msg, precal);
++	}
++
++	return 0;
++}
++
+ const struct mt76_testmode_ops mt7915_testmode_ops = {
+ 	.set_state = mt7915_tm_set_state,
+ 	.set_params = mt7915_tm_set_params,
+ 	.dump_stats = mt7915_tm_dump_stats,
+ 	.set_eeprom = mt7915_tm_set_eeprom,
++	.dump_precal = mt7915_tm_dump_precal,
+ };
+diff --git a/mt7915/testmode.h b/mt7915/testmode.h
+index eb0e0432..75698261 100644
+--- a/mt7915/testmode.h
++++ b/mt7915/testmode.h
+@@ -81,6 +81,11 @@ struct tm_tx_cont {
+ 	u8 txfd_mode;
+ };
+ 
++struct tm_cal_param {
++	__le32 func_data;
++	u8 band_idx;
++};
++
+ struct mt7915_tm_rf_test {
+ 	u8 action;
+ 	u8 icap_len;
+@@ -96,6 +101,7 @@ struct mt7915_tm_rf_test {
+ 				__le32 cal_dump;
+ 
+ 				struct tm_tx_cont tx_cont;
++				struct tm_cal_param cal_param;
+ 
+ 				u8 _pad[80];
+ 			} param;
+@@ -103,6 +109,20 @@ struct mt7915_tm_rf_test {
+ 	} op;
+ } __packed;
+ 
++struct mt7915_tm_rf_test_result {
++	struct mt76_connac2_mcu_rxd rxd;
++
++	u32 func_idx;
++	u32 payload_len;
++	u8 event[0];
++} __packed;
++
++struct mt7915_tm_rf_test_data {
++	u32 cal_idx;
++	u32 cal_type;
++	u8 data[0];
++} __packed;
++
+ enum {
+ 	RF_OPER_NORMAL,
+ 	RF_OPER_RF_TEST,
+@@ -111,6 +131,22 @@ enum {
+ 	RF_OPER_WIFI_SPECTRUM,
+ };
+ 
++enum {
++	RF_ACT_SWITCH_MODE,
++	RF_ACT_IN_RFTEST,
++};
++
++enum {
++	RF_TEST_RE_CAL = 0x01,
++	RF_TEST_TX_CONT_START = 0x05,
++	RF_TEST_TX_CONT_STOP = 0x06,
++};
++
++#define RF_DPD_FLAT_CAL		BIT(28)
++#define RF_PRE_CAL		BIT(29)
++#define RF_DPD_FLAT_5G_CAL	GENMASK(29, 28)
++#define RF_DPD_FLAT_6G_CAL	(BIT(30) | BIT(28))
++
+ enum {
+ 	TAM_ARB_OP_MODE_NORMAL = 1,
+ 	TAM_ARB_OP_MODE_TEST,
+diff --git a/testmode.c b/testmode.c
+index 75870478..070b296d 100644
+--- a/testmode.c
++++ b/testmode.c
+@@ -771,6 +771,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+ 
+ 	mutex_lock(&dev->mutex);
+ 
++	if (tb[MT76_TM_ATTR_PRECAL] || tb[MT76_TM_ATTR_PRECAL_INFO]) {
++		int flag, type;
++
++		err = -EINVAL;
++		flag = tb[MT76_TM_ATTR_PRECAL] ? 1 : 0;
++		type = flag ? nla_get_u8(tb[MT76_TM_ATTR_PRECAL_INFO]) : 0;
++		if (dev->test_ops->dump_precal)
++			err = dev->test_ops->dump_precal(phy, msg, flag, type);
++
++		goto out;
++	}
++
+ 	if (tb[MT76_TM_ATTR_STATS]) {
+ 		err = -EINVAL;
+ 
+@@ -804,7 +816,8 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
+ 
+ 	if (dev->test_mtd.name &&
+ 	    (nla_put_string(msg, MT76_TM_ATTR_MTD_PART, dev->test_mtd.name) ||
+-	     nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset)))
++	     nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset) ||
++	     nla_put_u8(msg, MT76_TM_ATTR_BAND_IDX, phy->band_idx)))
+ 		goto out;
+ 
+ 	if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
+diff --git a/testmode.h b/testmode.h
+index 7a686250..e4c1b521 100644
+--- a/testmode.h
++++ b/testmode.h
+@@ -19,6 +19,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_BAND_IDX: band idx of the chip (u8)
+  *
+  * @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
+@@ -41,6 +42,11 @@
+  *
+  * @MT76_TM_ATTR_STATS: statistics (nested, see &enum mt76_testmode_stats_attr)
+  *
++ * @MT76_TM_ATTR_PRECAL: Pre-cal data (u8)
++ * @MT76_TM_ATTR_PRECAL_INFO: group size, dpd size, dpd_info, transmit size,
++ *                            eeprom cal indicator (u32),
++ *                            dpd_info = [dpd_per_chan_size, chan_num_2g,
++ *                                        chan_num_5g, chan_num_6g]
+  * @MT76_TM_ATTR_TX_SPE_IDX: tx spatial extension index (u8)
+  *
+  * @MT76_TM_ATTR_TX_DUTY_CYCLE: packet tx duty cycle (u8)
+@@ -68,6 +74,7 @@ enum mt76_testmode_attr {
+ 
+ 	MT76_TM_ATTR_MTD_PART,
+ 	MT76_TM_ATTR_MTD_OFFSET,
++	MT76_TM_ATTR_BAND_IDX,
+ 
+ 	MT76_TM_ATTR_SKU_EN,
+ 	MT76_TM_ATTR_TX_COUNT,
+@@ -87,6 +94,8 @@ enum mt76_testmode_attr {
+ 	MT76_TM_ATTR_FREQ_OFFSET,
+ 
+ 	MT76_TM_ATTR_STATS,
++	MT76_TM_ATTR_PRECAL,
++	MT76_TM_ATTR_PRECAL_INFO,
+ 
+ 	MT76_TM_ATTR_TX_SPE_IDX,
+ 
+@@ -188,6 +197,14 @@ enum mt76_testmode_state {
+ 	MT76_TM_STATE_TX_FRAMES,
+ 	MT76_TM_STATE_RX_FRAMES,
+ 	MT76_TM_STATE_TX_CONT,
++	MT76_TM_STATE_GROUP_PREK,
++	MT76_TM_STATE_GROUP_PREK_DUMP,
++	MT76_TM_STATE_GROUP_PREK_CLEAN,
++	MT76_TM_STATE_DPD_2G,
++	MT76_TM_STATE_DPD_5G,
++	MT76_TM_STATE_DPD_6G,
++	MT76_TM_STATE_DPD_DUMP,
++	MT76_TM_STATE_DPD_CLEAN,
+ 	MT76_TM_STATE_ON,
+ 
+ 	/* keep last */
+diff --git a/tools/fields.c b/tools/fields.c
+index 406ba77c..27801dbe 100644
+--- a/tools/fields.c
++++ b/tools/fields.c
+@@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
+ 	[MT76_TM_STATE_TX_FRAMES] = "tx_frames",
+ 	[MT76_TM_STATE_RX_FRAMES] = "rx_frames",
+ 	[MT76_TM_STATE_TX_CONT] = "tx_cont",
++	[MT76_TM_STATE_GROUP_PREK] = "group_prek",
++	[MT76_TM_STATE_GROUP_PREK_DUMP] = "group_prek_dump",
++	[MT76_TM_STATE_GROUP_PREK_CLEAN] = "group_prek_clean",
++	[MT76_TM_STATE_DPD_2G] = "dpd_2g",
++	[MT76_TM_STATE_DPD_5G] = "dpd_5g",
++	[MT76_TM_STATE_DPD_6G] = "dpd_6g",
++	[MT76_TM_STATE_DPD_DUMP] = "dpd_dump",
++	[MT76_TM_STATE_DPD_CLEAN] = "dpd_clean",
+ };
+ 
+ static const char * const testmode_tx_mode[] = {
+-- 
+2.18.0
+