[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
+