[rdkb][common][bsp][Refactor and sync wifi from openwrt]
[Description]
d34487c3 [MAC80211][WiFi6][mt76][Add mt7981 mt7916 mt7915 fw_wm_info support]
327eaf76 [MAC80211][wifi7][Release][Update WiFi7 Filogic680/660 Firmware]
fa03d7ea [MAC80211][WiFi6][hostapd][Fix 2/6G channel switch fail issue]
c0bf67d9 [MAC80211][misc][Add Filogic 880 Non-MLO SDK Release]
e5d03217 [MAC80211][WiFi6][Rebase Patches][Refactor set_offchan_ctrl]
6cad79ae [MAC80211][WiFi6][hostapd][Add support for DFS channel switch with CSA sent]
cde50012 [MAC80211][WiFi6][core][Add DFS channel CSA flow]
0142fd16 [MAC80211][WiFi6][mt76][Add post channel switch callback for DFS channel switch support]
cb3f4c58 [MAC80211][WiFi6][mt76][Update Connac2 CSI Feature]
1b66ac4c [MAC80211][WiFi6][mt76][Refactor precal loading and binfile mode to align upstream]
0ece467b [MAC80211][WiFi6][mt76][Fix scs feature calltrace issue]
1dca03f1 [MAC80211][WiFi6/7][Misc][Change group mgmt cipher setting to align group cipher]
0aa52762 [MAC80211][WiFi6][mt76][Fix muru_onoff as all enabled by default]
c3e5f505 [MAC80211][WiFi6][hostapd][Fix mu_onoff was overwritten with unexpected values]
7090eabe [MAC80211][WiFi6/7][core][Add tx_burst option in wireless configuration file for Kite]
669d3071 [MAC80211][WiFi6][mt76][rebase patches]
c5d6b3e7 [mac80211][mt76][Fix patch fail]
55ef4059 [MAC80211][WiFi6][mt76][Fix TxS ACK is incorrectly reported]
e166eae1 [MAC80211][WiFi6][Misc][Add Filogic 820 Build]
118ffd7e [mac80211][wifi6][mt76][Fix crash caused by per-BSS counter updating]
68015098 [MAC80211][WiFi7][mt76][Add Eagle 2adie TBTC default bin]
eae6e8c0 [MAC80211][WiFi7][mt76][Add Eagle 2adie TBTC support in mt76 Makefile]
cccc8eb9 [MAC80211[WiFi6][hostapd][Fix wds AP interface adding issue]
173fe3b0 [MAC80211][WiFi6][mt76][Add scs feature for connac2 mt76]
1b8af8d9 [MAC80211][WiFi6][mt76][rebase patches]
6dc40325 [MAC80211][WiFi7][misc][fix hostapd udebug init fail]
aa4b39ae [[mt76][csi][mt7915][mt7986] update csi feature]
7d458da2 [MAC80211][WiFi6][hostapd][Auto Channel Selection channel time issue]
f0b5502f [MAC80211][WiFi7][misc][fix build error]
b63c9cf6 [MAC80211][WiFi6/7][misc][fix ucode and backport 6.5 patch fail]
ce056dc7 [mac80211][wifi6][mt76][Add variant support for Cheetah MT76]
c5ae3f9c [MAC80211][WiFi6/7][Misc][Add country setting consistent check before enable AP.]
d57d9c5a [mac80211][misc][wifi6/7][Update libubox to the latest version]
be7dbf21 [mac80211][misc][wifi7][Revert libubox to 20230523 to prevent build fail]
ae9b4428 [MAC80211][WiFi6][mt76][Add cal free data support]
52fd5d80 [MAC80211][WiFi7][Misc][Adjust MU EDCA timer in mac80211.sh]
66c649de [mac80211][hostapd][netifd][Revert udebug for build pass]
136c7f11 [MAC80211][hostapd][wifi7][Fix build fail]
8911e727 [MAC80211][WiFi6][hostapd][Auto Channel Selection issue and patch sync]
75161456 [MAC80211][WiFi7][mt76][Fix issue for testmode bit in eagle defaut bin]
4dc2d646 [MAC80211][WiFi6][mt76][Fix cheetah 5G ibf issue]
d4561158 [MAC80211][WiFi6][Misc][Add Filogic 820 Build]
2e5a1997 [MAC80211][WiFi6][hostapd][Backport hostapd ACS patches and some ACS fixes]
b0305b6e [MAC80211][WiFi6/7][Misc][Add 6g band default enable mbo IE]
[Release-log]
Change-Id: I872b422c1fc56ebd3a1cff3252cb403a2015eabe
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/1030-mtk-wifi-mt76-mt7996-support-BF-MIMO-debug-commands.patch b/recipes-wifi/linux-mt76/files/patches-3.x/1030-mtk-wifi-mt76-mt7996-support-BF-MIMO-debug-commands.patch
new file mode 100644
index 0000000..3048405
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/1030-mtk-wifi-mt76-mt7996-support-BF-MIMO-debug-commands.patch
@@ -0,0 +1,1204 @@
+From 05cf83b4947264a8afca95116afd98cb4519a9d5 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Tue, 3 Jan 2023 09:42:07 +0800
+Subject: [PATCH 1030/1041] mtk: wifi: mt76: mt7996: support BF/MIMO debug
+ commands
+
+This commit includes the following commands:
+1. starec_bf_read
+2. txbf_snd_info: start/stop sounding and set sounding period
+3. fbkRptInfo
+4. fix muru rate
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+fix the wrong wlan_idx for user3
+
+Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
+---
+ mt7996/mcu.c | 5 +
+ mt7996/mcu.h | 4 +
+ mt7996/mt7996.h | 5 +
+ mt7996/mtk_debugfs.c | 120 +++++++++
+ mt7996/mtk_mcu.c | 626 +++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mtk_mcu.h | 342 +++++++++++++++++++++++
+ 6 files changed, 1102 insertions(+)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 726d2adf..d3dab186 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -741,6 +741,11 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ case MCU_UNI_EVENT_TESTMODE_CTRL:
+ mt7996_tm_rf_test_event(dev, skb);
+ break;
++#endif
++#if defined CONFIG_NL80211_TESTMODE || defined CONFIG_MTK_DEBUG
++ case MCU_UNI_EVENT_BF:
++ mt7996_mcu_rx_bf_event(dev, skb);
++ break;
+ #endif
+ default:
+ break;
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 34fdfb26..347893c8 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -770,8 +770,12 @@ enum {
+
+ enum {
+ BF_SOUNDING_ON = 1,
++ BF_PFMU_TAG_READ = 5,
++ BF_STA_REC_READ = 11,
+ BF_HW_EN_UPDATE = 17,
+ BF_MOD_EN_CTRL = 20,
++ BF_FBRPT_DBG_INFO_READ = 23,
++ BF_TXSND_INFO = 24,
+ };
+
+ enum {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 71602b9b..a321e8e8 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -809,6 +809,11 @@ int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
+ int mt7996_mcu_set_sr_enable(struct mt7996_phy *phy, u8 action, u64 val, bool set);
+ void mt7996_mcu_rx_sr_event(struct mt7996_dev *dev, struct sk_buff *skb);
+ int mt7996_mcu_set_dup_wtbl(struct mt7996_dev *dev);
++int mt7996_mcu_set_txbf_internal(struct mt7996_phy *phy, u8 action, int idx);
++void mt7996_mcu_rx_bf_event(struct mt7996_dev *dev, struct sk_buff *skb);
++int mt7996_mcu_set_muru_fixed_rate_enable(struct mt7996_dev *dev, u8 action, int val);
++int mt7996_mcu_set_muru_fixed_rate_parameter(struct mt7996_dev *dev, u8 action, void *para);
++int mt7996_mcu_set_txbf_snd_info(struct mt7996_phy *phy, void *para);
+ #endif
+
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
+index e1689605..938da645 100644
+--- a/mt7996/mtk_debugfs.c
++++ b/mt7996/mtk_debugfs.c
+@@ -2798,6 +2798,117 @@ static int mt7996_rx_counters(struct seq_file *s, void *data)
+ return 0;
+ }
+
++static int
++mt7996_starec_bf_read_set(void *data, u64 wlan_idx)
++{
++ struct mt7996_phy *phy = data;
++
++ return mt7996_mcu_set_txbf_internal(phy, BF_STA_REC_READ, wlan_idx);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_starec_bf_read, NULL,
++ mt7996_starec_bf_read_set, "%lld\n");
++
++static ssize_t
++mt7996_bf_txsnd_info_set(struct file *file,
++ const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct mt7996_phy *phy = file->private_data;
++ char buf[40];
++ int ret;
++
++ if (count >= sizeof(buf))
++ return -EINVAL;
++
++ if (copy_from_user(buf, user_buf, count))
++ return -EFAULT;
++
++ if (count && buf[count - 1] == '\n')
++ buf[count - 1] = '\0';
++ else
++ buf[count] = '\0';
++
++ ret = mt7996_mcu_set_txbf_snd_info(phy, buf);
++
++ if (ret) return -EFAULT;
++
++ return count;
++}
++
++static const struct file_operations fops_bf_txsnd_info = {
++ .write = mt7996_bf_txsnd_info_set,
++ .read = NULL,
++ .open = simple_open,
++ .llseek = default_llseek,
++};
++
++static int
++mt7996_bf_fbk_rpt_set(void *data, u64 wlan_idx)
++{
++ struct mt7996_phy *phy = data;
++
++ return mt7996_mcu_set_txbf_internal(phy, BF_FBRPT_DBG_INFO_READ, wlan_idx);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_bf_fbk_rpt, NULL,
++ mt7996_bf_fbk_rpt_set, "%lld\n");
++
++static int
++mt7996_bf_pfmu_tag_read_set(void *data, u64 wlan_idx)
++{
++ struct mt7996_phy *phy = data;
++
++ return mt7996_mcu_set_txbf_internal(phy, BF_PFMU_TAG_READ, wlan_idx);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_bf_pfmu_tag_read, NULL,
++ mt7996_bf_pfmu_tag_read_set, "%lld\n");
++
++static int
++mt7996_muru_fixed_rate_set(void *data, u64 val)
++{
++ struct mt7996_dev *dev = data;
++
++ return mt7996_mcu_set_muru_fixed_rate_enable(dev, UNI_CMD_MURU_FIXED_RATE_CTRL,
++ val);
++}
++DEFINE_DEBUGFS_ATTRIBUTE(fops_muru_fixed_rate_enable, NULL,
++ mt7996_muru_fixed_rate_set, "%lld\n");
++
++static ssize_t
++mt7996_muru_fixed_rate_parameter_set(struct file *file,
++ const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct mt7996_dev *dev = file->private_data;
++ char buf[40];
++ int ret;
++
++ if (count >= sizeof(buf))
++ return -EINVAL;
++
++ if (copy_from_user(buf, user_buf, count))
++ return -EFAULT;
++
++ if (count && buf[count - 1] == '\n')
++ buf[count - 1] = '\0';
++ else
++ buf[count] = '\0';
++
++
++ ret = mt7996_mcu_set_muru_fixed_rate_parameter(dev, UNI_CMD_MURU_FIXED_GROUP_RATE_CTRL,
++ buf);
++
++ if (ret) return -EFAULT;
++
++ return count;
++}
++
++static const struct file_operations fops_muru_fixed_group_rate = {
++ .write = mt7996_muru_fixed_rate_parameter_set,
++ .read = NULL,
++ .open = simple_open,
++ .llseek = default_llseek,
++};
++
+ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ {
+ struct mt7996_dev *dev = phy->dev;
+@@ -2883,6 +2994,15 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
+ debugfs_create_file("sr_stats", 0400, dir, phy, &mt7996_sr_stats_fops);
+ debugfs_create_file("sr_scene_cond", 0400, dir, phy, &mt7996_sr_scene_cond_fops);
+
++ debugfs_create_file("muru_fixed_rate_enable", 0600, dir, dev,
++ &fops_muru_fixed_rate_enable);
++ debugfs_create_file("muru_fixed_group_rate", 0600, dir, dev,
++ &fops_muru_fixed_group_rate);
++ debugfs_create_file("bf_txsnd_info", 0600, dir, phy, &fops_bf_txsnd_info);
++ debugfs_create_file("bf_starec_read", 0600, dir, phy, &fops_starec_bf_read);
++ debugfs_create_file("bf_fbk_rpt", 0600, dir, phy, &fops_bf_fbk_rpt);
++ debugfs_create_file("pfmu_tag_read", 0600, dir, phy, &fops_bf_pfmu_tag_read);
++
+ return 0;
+ }
+
+diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
+index ea4e5bf2..67419cd9 100644
+--- a/mt7996/mtk_mcu.c
++++ b/mt7996/mtk_mcu.c
+@@ -280,4 +280,630 @@ int mt7996_mcu_set_dup_wtbl(struct mt7996_dev *dev)
+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(CHIP_CONFIG), &req,
+ sizeof(req), true);
+ }
++
++static struct tlv *
++__mt7996_mcu_add_uni_tlv(struct sk_buff *skb, u16 tag, u16 len)
++{
++ struct tlv *ptlv, tlv = {
++ .tag = cpu_to_le16(tag),
++ .len = cpu_to_le16(len),
++ };
++
++ ptlv = skb_put(skb, len);
++ memcpy(ptlv, &tlv, sizeof(tlv));
++
++ return ptlv;
++}
++
++int mt7996_mcu_set_txbf_internal(struct mt7996_phy *phy, u8 action, int idx)
++{
++ struct mt7996_dev *dev = phy->dev;
++#define MT7996_MTK_BF_MAX_SIZE sizeof(struct bf_starec_read)
++ struct uni_header hdr;
++ struct sk_buff *skb;
++ struct tlv *tlv;
++ int len = sizeof(hdr) + MT7996_MTK_BF_MAX_SIZE;
++
++ memset(&hdr, 0, sizeof(hdr));
++
++ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, len);
++ if (!skb)
++ return -ENOMEM;
++
++ skb_put_data(skb, &hdr, sizeof(hdr));
++
++ switch (action) {
++ case BF_PFMU_TAG_READ: {
++ struct bf_pfmu_tag *req;
++
++ tlv = __mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req));
++ req = (struct bf_pfmu_tag *)tlv;
++#define BFER 1
++ req->pfmu_id = idx;
++ req->bfer = BFER;
++ req->band_idx = phy->mt76->band_idx;
++ break;
++ }
++ case BF_STA_REC_READ: {
++ struct bf_starec_read *req;
++
++ tlv = __mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req));
++ req = (struct bf_starec_read *)tlv;
++ req->wlan_idx = idx;
++ break;
++ }
++ case BF_FBRPT_DBG_INFO_READ: {
++ struct bf_fbk_rpt_info *req;
++
++ if (idx != 0) {
++ dev_info(dev->mt76.dev, "Invalid input");
++ return 0;
++ }
++
++ tlv = __mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req));
++ req = (struct bf_fbk_rpt_info *)tlv;
++ req->action = idx;
++ req->band_idx = phy->mt76->band_idx;
++ break;
++ }
++ default:
++ return -EINVAL;
++ }
++
++ return mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, MCU_WM_UNI_CMD(BF), false);
++}
++
++int mt7996_mcu_set_txbf_snd_info(struct mt7996_phy *phy, void *para)
++{
++ char *buf = (char *)para;
++ __le16 input[5] = {0};
++ u8 recv_arg = 0;
++ struct bf_txsnd_info *req;
++ struct uni_header hdr;
++ struct sk_buff *skb;
++ struct tlv *tlv;
++ int len = sizeof(hdr) + MT7996_MTK_BF_MAX_SIZE;
++
++ memset(&hdr, 0, sizeof(hdr));
++
++ skb = mt76_mcu_msg_alloc(&phy->dev->mt76, NULL, len);
++ if (!skb)
++ return -ENOMEM;
++
++ skb_put_data(skb, &hdr, sizeof(hdr));
++
++ recv_arg = sscanf(buf, "%hx:%hx:%hx:%hx:%hx", &input[0], &input[1], &input[2],
++ &input[3], &input[4]);
++
++ if (!recv_arg)
++ return -EINVAL;
++
++ tlv = __mt7996_mcu_add_uni_tlv(skb, BF_TXSND_INFO, sizeof(*req));
++ req = (struct bf_txsnd_info *)tlv;
++ req->action = input[0];
++
++ switch (req->action) {
++ case BF_SND_READ_INFO: {
++ req->read_clr = input[1];
++ break;
++ }
++ case BF_SND_CFG_OPT: {
++ req->vht_opt = input[1];
++ req->he_opt = input[2];
++ req->glo_opt = input[3];
++ break;
++ }
++ case BF_SND_CFG_INTV: {
++ req->wlan_idx = input[1];
++ req->snd_intv = input[2];
++ break;
++ }
++ case BF_SND_STA_STOP: {
++ req->wlan_idx = input[1];
++ req->snd_stop = input[2];
++ break;
++ }
++ case BF_SND_CFG_MAX_STA: {
++ req->max_snd_stas = input[1];
++ break;
++ }
++ case BF_SND_CFG_BFRP: {
++ req->man = input[1];
++ req->tx_time = input[2];
++ req->mcs = input[3];
++ req->ldpc = input[4];
++ break;
++ }
++ case BF_SND_CFG_INF: {
++ req->inf = input[1];
++ break;
++ }
++ case BF_SND_CFG_TXOP_SND: {
++ req->man = input[1];
++ req->ac_queue = input[2];
++ req->sxn_protect = input[3];
++ req->direct_fbk = input[4];
++ break;
++ }
++ default:
++ return -EINVAL;
++ }
++
++ return mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, MCU_WM_UNI_CMD(BF), false);
++}
++
++void
++mt7996_mcu_rx_bf_event(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++#define HE_MODE 3
++ struct mt7996_mcu_bf_basic_event *event;
++
++ event = (struct mt7996_mcu_bf_basic_event *)skb->data;
++
++ dev_info(dev->mt76.dev, " bf_event tag = %d\n", event->tag);
++
++ switch (event->tag) {
++ case UNI_EVENT_BF_PFMU_TAG: {
++
++ struct mt7996_pfmu_tag_event *tag;
++ u32 *raw_t1, *raw_t2;
++
++ tag = (struct mt7996_pfmu_tag_event *) skb->data;
++
++ raw_t1 = (u32 *)&tag->t1;
++ raw_t2 = (u32 *)&tag->t2;
++
++ dev_info(dev->mt76.dev, "=================== TXBf Profile Tag1 Info ==================\n");
++ dev_info(dev->mt76.dev,
++ "DW0 = 0x%08x, DW1 = 0x%08x, DW2 = 0x%08x\n",
++ raw_t1[0], raw_t1[1], raw_t1[2]);
++ dev_info(dev->mt76.dev,
++ "DW4 = 0x%08x, DW5 = 0x%08x, DW6 = 0x%08x\n\n",
++ raw_t1[3], raw_t1[4], raw_t1[5]);
++ dev_info(dev->mt76.dev, "PFMU ID = %d Invalid status = %d\n",
++ tag->t1.pfmu_idx, tag->t1.invalid_prof);
++ dev_info(dev->mt76.dev, "iBf/eBf = %d\n\n", tag->t1.ebf);
++ dev_info(dev->mt76.dev, "DBW = %d\n", tag->t1.data_bw);
++ dev_info(dev->mt76.dev, "SU/MU = %d\n", tag->t1.is_mu);
++ dev_info(dev->mt76.dev,
++ "nrow = %d, ncol = %d, ng = %d, LM = %d, CodeBook = %d MobCalEn = %d\n",
++ tag->t1.nr, tag->t1.nc, tag->t1.ngroup, tag->t1.lm, tag->t1.codebook,
++ tag->t1.mob_cal_en);
++
++ if (tag->t1.lm <= HE_MODE) {
++ dev_info(dev->mt76.dev, "RU start = %d, RU end = %d\n",
++ tag->t1.field.ru_start_id, tag->t1.field.ru_end_id);
++ } else {
++ dev_info(dev->mt76.dev, "PartialBW = %d\n",
++ tag->t1.bw_info.partial_bw_info);
++ }
++
++ dev_info(dev->mt76.dev, "Mem Col1 = %d, Mem Row1 = %d, Mem Col2 = %d, Mem Row2 = %d\n",
++ tag->t1.col_id1, tag->t1.row_id1, tag->t1.col_id2, tag->t1.row_id2);
++ dev_info(dev->mt76.dev, "Mem Col3 = %d, Mem Row3 = %d, Mem Col4 = %d, Mem Row4 = %d\n\n",
++ tag->t1.col_id3, tag->t1.row_id3, tag->t1.col_id4, tag->t1.row_id4);
++ dev_info(dev->mt76.dev,
++ "STS0_SNR = 0x%02x, STS1_SNR = 0x%02x, STS2_SNR = 0x%02x, STS3_SNR = 0x%02x\n",
++ tag->t1.snr_sts0, tag->t1.snr_sts1, tag->t1.snr_sts2, tag->t1.snr_sts3);
++ dev_info(dev->mt76.dev,
++ "STS4_SNR = 0x%02x, STS5_SNR = 0x%02x, STS6_SNR = 0x%02x, STS7_SNR = 0x%02x\n",
++ tag->t1.snr_sts4, tag->t1.snr_sts5, tag->t1.snr_sts6, tag->t1.snr_sts7);
++ dev_info(dev->mt76.dev, "=============================================================\n");
++
++ dev_info(dev->mt76.dev, "=================== TXBf Profile Tag2 Info ==================\n");
++ dev_info(dev->mt76.dev,
++ "DW0 = 0x%08x, DW1 = 0x%08x, DW2 = 0x%08x\n",
++ raw_t2[0], raw_t2[1], raw_t2[2]);
++ dev_info(dev->mt76.dev,
++ "DW3 = 0x%08x, DW4 = 0x%08x, DW5 = 0x%08x\n\n",
++ raw_t2[3], raw_t2[4], raw_t2[5]);
++ dev_info(dev->mt76.dev, "Smart antenna ID = 0x%x, SE index = %d\n",
++ tag->t2.smart_ant, tag->t2.se_idx);
++ dev_info(dev->mt76.dev, "Timeout = 0x%x\n", tag->t2.ibf_timeout);
++ dev_info(dev->mt76.dev, "Desired BW = %d, Desired Ncol = %d, Desired Nrow = %d\n",
++ tag->t2.ibf_data_bw, tag->t2.ibf_nc, tag->t2.ibf_nr);
++ dev_info(dev->mt76.dev, "Desired RU Allocation = %d\n", tag->t2.ibf_ru);
++ dev_info(dev->mt76.dev, "Mobility DeltaT = %d, Mobility LQ = %d\n",
++ tag->t2.mob_delta_t, tag->t2.mob_lq_result);
++ dev_info(dev->mt76.dev, "=============================================================\n");
++ break;
++ }
++ case UNI_EVENT_BF_STAREC: {
++
++ struct mt7996_mcu_bf_starec_read *r;
++
++ r = (struct mt7996_mcu_bf_starec_read *)skb->data;
++ dev_info(dev->mt76.dev, "=================== BF StaRec ===================\n"
++ "rStaRecBf.u2PfmuId = %d\n"
++ "rStaRecBf.fgSU_MU = %d\n"
++ "rStaRecBf.u1TxBfCap = %d\n"
++ "rStaRecBf.ucSoundingPhy = %d\n"
++ "rStaRecBf.ucNdpaRate = %d\n"
++ "rStaRecBf.ucNdpRate = %d\n"
++ "rStaRecBf.ucReptPollRate= %d\n"
++ "rStaRecBf.ucTxMode = %d\n"
++ "rStaRecBf.ucNc = %d\n"
++ "rStaRecBf.ucNr = %d\n"
++ "rStaRecBf.ucCBW = %d\n"
++ "rStaRecBf.ucMemRequire20M = %d\n"
++ "rStaRecBf.ucMemRow0 = %d\n"
++ "rStaRecBf.ucMemCol0 = %d\n"
++ "rStaRecBf.ucMemRow1 = %d\n"
++ "rStaRecBf.ucMemCol1 = %d\n"
++ "rStaRecBf.ucMemRow2 = %d\n"
++ "rStaRecBf.ucMemCol2 = %d\n"
++ "rStaRecBf.ucMemRow3 = %d\n"
++ "rStaRecBf.ucMemCol3 = %d\n",
++ r->pfmu_id,
++ r->is_su_mu,
++ r->txbf_cap,
++ r->sounding_phy,
++ r->ndpa_rate,
++ r->ndp_rate,
++ r->rpt_poll_rate,
++ r->tx_mode,
++ r->nc,
++ r->nr,
++ r->bw,
++ r->mem_require_20m,
++ r->mem_row0,
++ r->mem_col0,
++ r->mem_row1,
++ r->mem_col1,
++ r->mem_row2,
++ r->mem_col2,
++ r->mem_row3,
++ r->mem_col3);
++
++ dev_info(dev->mt76.dev, "rStaRecBf.u2SmartAnt = 0x%x\n"
++ "rStaRecBf.ucSEIdx = %d\n"
++ "rStaRecBf.uciBfTimeOut = 0x%x\n"
++ "rStaRecBf.uciBfDBW = %d\n"
++ "rStaRecBf.uciBfNcol = %d\n"
++ "rStaRecBf.uciBfNrow = %d\n"
++ "rStaRecBf.nr_bw160 = %d\n"
++ "rStaRecBf.nc_bw160 = %d\n"
++ "rStaRecBf.ru_start_idx = %d\n"
++ "rStaRecBf.ru_end_idx = %d\n"
++ "rStaRecBf.trigger_su = %d\n"
++ "rStaRecBf.trigger_mu = %d\n"
++ "rStaRecBf.ng16_su = %d\n"
++ "rStaRecBf.ng16_mu = %d\n"
++ "rStaRecBf.codebook42_su = %d\n"
++ "rStaRecBf.codebook75_mu = %d\n"
++ "rStaRecBf.he_ltf = %d\n"
++ "rStaRecBf.pp_fd_val = %d\n"
++ "======================================\n",
++ r->smart_ant,
++ r->se_idx,
++ r->bf_timeout,
++ r->bf_dbw,
++ r->bf_ncol,
++ r->bf_nrow,
++ r->nr_lt_bw80,
++ r->nc_lt_bw80,
++ r->ru_start_idx,
++ r->ru_end_idx,
++ r->trigger_su,
++ r->trigger_mu,
++ r->ng16_su,
++ r->ng16_mu,
++ r->codebook42_su,
++ r->codebook75_mu,
++ r->he_ltf,
++ r->pp_fd_val);
++ break;
++ }
++ case UNI_EVENT_BF_FBK_INFO: {
++ struct mt7996_mcu_txbf_fbk_info *info;
++ __le32 total, i;
++
++ info = (struct mt7996_mcu_txbf_fbk_info *)skb->data;
++
++ total = info->u4PFMUWRDoneCnt + info->u4PFMUWRFailCnt;
++ total += info->u4PFMUWRTimeoutFreeCnt + info->u4FbRptPktDropCnt;
++
++ dev_info(dev->mt76.dev, "\n");
++ dev_info(dev->mt76.dev, "\x1b[32m =================================\x1b[m\n");
++ dev_info(dev->mt76.dev, "\x1b[32m PFMUWRDoneCnt = %u\x1b[m\n",
++ info->u4PFMUWRDoneCnt);
++ dev_info(dev->mt76.dev, "\x1b[32m PFMUWRFailCnt = %u\x1b[m\n",
++ info->u4PFMUWRFailCnt);
++ dev_info(dev->mt76.dev, "\x1b[32m PFMUWRTimeOutCnt = %u\x1b[m\n",
++ info->u4PFMUWRTimeOutCnt);
++ dev_info(dev->mt76.dev, "\x1b[32m PFMUWRTimeoutFreeCnt = %u\x1b[m\n",
++ info->u4PFMUWRTimeoutFreeCnt);
++ dev_info(dev->mt76.dev, "\x1b[32m FbRptPktDropCnt = %u\x1b[m\n",
++ info->u4FbRptPktDropCnt);
++ dev_info(dev->mt76.dev, "\x1b[32m TotalFbRptPkt = %u\x1b[m\n", total);
++ dev_info(dev->mt76.dev, "\x1b[32m PollPFMUIntrStatTimeOut = %u(micro-sec)\x1b[m\n",
++ info->u4PollPFMUIntrStatTimeOut);
++ dev_info(dev->mt76.dev, "\x1b[32m FbRptDeQInterval = %u(milli-sec)\x1b[m\n",
++ info->u4DeQInterval);
++ dev_info(dev->mt76.dev, "\x1b[32m PktCntInFbRptTimeOutQ = %u\x1b[m\n",
++ info->u4RptPktTimeOutListNum);
++ dev_info(dev->mt76.dev, "\x1b[32m PktCntInFbRptQ = %u\x1b[m\n",
++ info->u4RptPktListNum);
++
++ // [ToDo] Check if it is valid entry
++ for (i = 0; ((i < 5) && (i < CFG_BF_STA_REC_NUM)); i++) {
++
++ // [ToDo] AID needs to be refined
++ dev_info(dev->mt76.dev,"\x1b[32m AID%u RxFbRptCnt = %u\x1b[m\n"
++ , i, info->au4RxPerStaFbRptCnt[i]);
++ }
++
++ break;
++ }
++ case UNI_EVENT_BF_TXSND_INFO: {
++ struct mt7996_mcu_tx_snd_info *info;
++ struct uni_event_bf_txsnd_sta_info *snd_sta_info;
++ int Idx;
++ int max_wtbl_size = mt7996_wtbl_size(dev);
++
++ info = (struct mt7996_mcu_tx_snd_info *)skb->data;
++ dev_info(dev->mt76.dev, "=================== Global Setting ===================\n");
++
++ dev_info(dev->mt76.dev, "VhtOpt = 0x%02X, HeOpt = 0x%02X, GloOpt = 0x%02X\n",
++ info->vht_opt, info->he_opt, info->glo_opt);
++
++ for (Idx = 0; Idx < BF_SND_CTRL_STA_DWORD_CNT; Idx++) {
++ dev_info(dev->mt76.dev, "SuSta[%d] = 0x%08X,", Idx,
++ info->snd_rec_su_sta[Idx]);
++ if ((Idx & 0x03) == 0x03)
++ dev_info(dev->mt76.dev, "\n");
++ }
++
++ if ((Idx & 0x03) != 0x03)
++ dev_info(dev->mt76.dev, "\n");
++
++
++ for (Idx = 0; Idx < BF_SND_CTRL_STA_DWORD_CNT; Idx++) {
++ dev_info(dev->mt76.dev, "VhtMuSta[%d] = 0x%08X,", Idx, info->snd_rec_vht_mu_sta[Idx]);
++ if ((Idx & 0x03) == 0x03)
++ dev_info(dev->mt76.dev, "\n");
++ }
++
++ if ((Idx & 0x03) != 0x03)
++ dev_info(dev->mt76.dev, "\n");
++
++ for (Idx = 0; Idx < BF_SND_CTRL_STA_DWORD_CNT; Idx++) {
++ dev_info(dev->mt76.dev, "HeTBSta[%d] = 0x%08X,", Idx, info->snd_rec_he_tb_sta[Idx]);
++ if ((Idx & 0x03) == 0x03)
++ dev_info(dev->mt76.dev, "\n");
++ }
++
++ if ((Idx & 0x03) != 0x03)
++ dev_info(dev->mt76.dev, "\n");
++
++ for (Idx = 0; Idx < BF_SND_CTRL_STA_DWORD_CNT; Idx++) {
++ dev_info(dev->mt76.dev, "EhtTBSta[%d] = 0x%08X,", Idx, info->snd_rec_eht_tb_sta[Idx]);
++ if ((Idx & 0x03) == 0x03)
++ dev_info(dev->mt76.dev, "\n");
++ }
++
++ if ((Idx & 0x03) != 0x03)
++ dev_info(dev->mt76.dev, "\n");
++
++ for (Idx = 0; Idx < CFG_WIFI_RAM_BAND_NUM; Idx++) {
++ dev_info(dev->mt76.dev, "Band%u:\n", Idx);
++ dev_info(dev->mt76.dev, " Wlan Idx For VHT MC Sounding = %u\n", info->wlan_idx_for_mc_snd[Idx]);
++ dev_info(dev->mt76.dev, " Wlan Idx For HE TB Sounding = %u\n", info->wlan_idx_for_he_tb_snd[Idx]);
++ dev_info(dev->mt76.dev, " Wlan Idx For EHT TB Sounding = %u\n", info->wlan_idx_for_eht_tb_snd[Idx]);
++ }
++
++ dev_info(dev->mt76.dev, "ULLen = %d, ULMcs = %d, ULLDCP = %d\n",
++ info->ul_length, info->mcs, info->ldpc);
++
++ dev_info(dev->mt76.dev, "=================== STA Info ===================\n");
++
++ for (Idx = 1; (Idx < 5 && (Idx < CFG_BF_STA_REC_NUM)); Idx++) {
++ snd_sta_info = &info->snd_sta_info[Idx];
++ dev_info(dev->mt76.dev, "Idx%2u Interval = %d, interval counter = %d, TxCnt = %d, StopReason = 0x%02X\n",
++ Idx,
++ snd_sta_info->snd_intv,
++ snd_sta_info->snd_intv_cnt,
++ snd_sta_info->snd_tx_cnt,
++ snd_sta_info->snd_stop_reason);
++ }
++
++ dev_info(dev->mt76.dev, "=================== STA Info Connected ===================\n");
++ // [ToDo] How to iterate and get AID info of station
++ // Check UniEventBFCtrlTxSndHandle() on Logan
++
++ //hardcode max_wtbl_size as 5
++ max_wtbl_size = 5;
++ for (Idx = 1; ((Idx < max_wtbl_size) && (Idx < CFG_BF_STA_REC_NUM)); Idx++) {
++
++ // [ToDo] We do not show AID info here
++ snd_sta_info = &info->snd_sta_info[Idx];
++ dev_info(dev->mt76.dev, " Interval = %d (%u ms), interval counter = %d (%u ms), TxCnt = %d, StopReason = 0x%02X\n",
++ snd_sta_info->snd_intv,
++ snd_sta_info->snd_intv * 10,
++ snd_sta_info->snd_intv_cnt,
++ snd_sta_info->snd_intv_cnt * 10,
++ snd_sta_info->snd_tx_cnt,
++ snd_sta_info->snd_stop_reason);
++ }
++
++ dev_info(dev->mt76.dev, "======================================\n");
++
++ break;
++ }
++ default:
++ dev_info(dev->mt76.dev, "%s: unknown bf event tag %d\n",
++ __func__, event->tag);
++ }
++
++}
++
++
++int mt7996_mcu_set_muru_fixed_rate_enable(struct mt7996_dev *dev, u8 action, int val)
++{
++ struct {
++ u8 _rsv[4];
++
++ __le16 tag;
++ __le16 len;
++
++ __le16 value;
++ __le16 rsv;
++ } __packed data = {
++ .tag = cpu_to_le16(action),
++ .len = cpu_to_le16(sizeof(data) - 4),
++ .value = cpu_to_le16(!!val),
++ };
++
++ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &data, sizeof(data),
++ false);
++}
++
++int mt7996_mcu_set_muru_fixed_rate_parameter(struct mt7996_dev *dev, u8 action, void *para)
++{
++ char *buf = (char *)para;
++ u8 num_user = 0, recv_arg = 0, max_mcs = 0, usr_mcs[4] = {0};
++ __le16 bw;
++ int i;
++ struct {
++ u8 _rsv[4];
++
++ __le16 tag;
++ __le16 len;
++
++ u8 cmd_version;
++ u8 cmd_revision;
++ __le16 rsv;
++
++ struct uni_muru_mum_set_group_tbl_entry entry;
++ } __packed data = {
++ .tag = cpu_to_le16(action),
++ .len = cpu_to_le16(sizeof(data) - 4),
++ };
++
++#define __RUALLOC_TYPE_CHECK_HE(BW) ((BW == RUALLOC_BW20) || (BW == RUALLOC_BW40) || (BW == RUALLOC_BW80) || (BW == RUALLOC_BW160))
++#define __RUALLOC_TYPE_CHECK_EHT(BW) (__RUALLOC_TYPE_CHECK_HE(BW) || (BW == RUALLOC_BW320))
++ /* [Num of user] - 1~4
++ * [RUAlloc] - BW320: 395, BW160: 137, BW80: 134, BW40: 130, BW20: 122
++ * [LTF/GI] - For VHT, short GI: 0, Long GI: 1; *
++ * For HE/EHT, 4xLTF+3.2us: 0, 4xLTF+0.8us: 1, 2xLTF+0.8us:2
++ * [Phy/FullBW] - VHT: 0 / HEFullBw: 1 / HEPartialBw: 2 / EHTFullBW: 3, EHTPartialBW: 4
++ * [DL/UL] DL: 0, UL: 1, DL_UL: 2
++ * [Wcid User0] - WCID 0
++ * [MCS of WCID0] - For HE/VHT, 0-11: 1ss MCS0-MCS11, 12-23: 2SS MCS0-MCS11
++ * For EHT, 0-13: 1ss MCS0-MCS13, 14-27: 2SS MCS0-MCS13
++ * [WCID 1]
++ * [MCS of WCID1]
++ * [WCID 2]
++ * [MCS of WCID2]
++ * [WCID 3]
++ * [MCS of WCID3]
++ */
++
++ recv_arg = sscanf(buf, "%hhu %hu %hhu %hhu %hhu %hu %hhu %hu %hhu %hu %hhu %hu %hhu",
++ &num_user, &bw, &data.entry.gi, &data.entry.capa, &data.entry.dl_ul,
++ &data.entry.wlan_idx0, &usr_mcs[0],
++ &data.entry.wlan_idx1, &usr_mcs[1],
++ &data.entry.wlan_idx2, &usr_mcs[2],
++ &data.entry.wlan_idx3, &usr_mcs[3]);
++
++ if (recv_arg != (5 + (2 * num_user))) {
++ dev_err(dev->mt76.dev, "The number of argument is invalid\n");
++ goto error;
++ }
++
++ if (num_user > 0 && num_user < 5)
++ data.entry.num_user = num_user - 1;
++ else {
++ dev_err(dev->mt76.dev, "The number of user count is invalid\n");
++ goto error;
++ }
++
++ /**
++ * Older chip shall be set as HE. Refer to getHWSupportByChip() in Logan
++ * driver to know the value for differnt chips
++ */
++ data.cmd_version = UNI_CMD_MURU_VER_EHT;
++
++ if (data.cmd_version == UNI_CMD_MURU_VER_EHT)
++ max_mcs = UNI_MAX_MCS_SUPPORT_EHT;
++ else
++ max_mcs = UNI_MAX_MCS_SUPPORT_HE;
++
++
++ // Parameter Check
++ if (data.cmd_version != UNI_CMD_MURU_VER_EHT) {
++ if ((data.entry.capa > MAX_MODBF_HE) || (bw == RUALLOC_BW320))
++ goto error;
++ } else {
++ if ((data.entry.capa <= MAX_MODBF_HE) && (bw == RUALLOC_BW320))
++ goto error;
++ }
++
++ if (data.entry.capa <= MAX_MODBF_HE)
++ max_mcs = UNI_MAX_MCS_SUPPORT_HE;
++
++ if (__RUALLOC_TYPE_CHECK_EHT(bw)) {
++ data.entry.ru_alloc = (u8)(bw & 0xFF);
++ if (bw == RUALLOC_BW320)
++ data.entry.ru_alloc_ext = (u8)(bw >> 8);
++ } else {
++ dev_err(dev->mt76.dev, "RU_ALLOC argument is invalid\n");
++ goto error;
++ }
++
++ if ((data.entry.gi > 2) ||
++ ((data.entry.gi > 1) && (data.entry.capa == MAX_MODBF_VHT))) {
++ dev_err(dev->mt76.dev, "GI argument is invalid\n");
++ goto error;
++ }
++
++ if (data.entry.dl_ul > 2) {
++ dev_err(dev->mt76.dev, "DL_UL argument is invalid\n");
++ goto error;
++ }
++
++#define __mcs_handler(_n) \
++ do { \
++ if (usr_mcs[_n] > max_mcs) { \
++ usr_mcs[_n] -= (max_mcs + 1); \
++ data.entry.nss##_n = 1; \
++ if (usr_mcs[_n] > max_mcs) \
++ usr_mcs[_n] = max_mcs; \
++ } \
++ if ((data.entry.dl_ul & 0x1) == 0) \
++ data.entry.dl_mcs_user##_n = usr_mcs[_n]; \
++ if ((data.entry.dl_ul & 0x3) > 0) \
++ data.entry.ul_mcs_user##_n = usr_mcs[_n]; \
++ } \
++ while (0)
++
++ for (i=0; i<= data.entry.num_user; i++) {
++ switch (i) {
++ case 0:
++ __mcs_handler(0);
++ break;
++ case 1:
++ __mcs_handler(1);
++ break;
++ case 2:
++ __mcs_handler(2);
++ break;
++ case 3:
++ __mcs_handler(3);
++ break;
++ default:
++ break;
++ }
++ }
++#undef __mcs_handler
++
++
++ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &data,
++ sizeof(data), false);
++
++error:
++ dev_err(dev->mt76.dev, "Command failed!\n");
++ return -EINVAL;
++}
++
+ #endif
+diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
+index cc2de8f4..519ffe1c 100644
+--- a/mt7996/mtk_mcu.h
++++ b/mt7996/mtk_mcu.h
+@@ -106,6 +106,348 @@ enum {
+ EDCCA_FCC = 1,
+ EDCCA_ETSI = 2,
+ EDCCA_JAPAN = 3
++
++struct bf_pfmu_tag {
++ __le16 tag;
++ __le16 len;
++
++ u8 pfmu_id;
++ bool bfer;
++ u8 band_idx;
++ u8 __rsv[5];
++ u8 buf[56];
++} __packed;
++
++struct bf_starec_read {
++ __le16 tag;
++ __le16 len;
++
++ __le16 wlan_idx;
++ u8 __rsv[2];
++} __packed;
++
++struct bf_fbk_rpt_info {
++ __le16 tag;
++ __le16 len;
++
++ __le16 wlan_idx; // Only need for dynamic_pfmu_update 0x4
++ u8 action;
++ u8 band_idx;
++ u8 __rsv[4];
++
++} __packed;
++
++struct bf_txsnd_info {
++ __le16 tag;
++ __le16 len;
++
++ u8 action;
++ u8 read_clr;
++ u8 vht_opt;
++ u8 he_opt;
++ __le16 wlan_idx;
++ u8 glo_opt;
++ u8 snd_intv;
++ u8 snd_stop;
++ u8 max_snd_stas;
++ u8 tx_time;
++ u8 mcs;
++ u8 ldpc;
++ u8 inf;
++ u8 man;
++ u8 ac_queue;
++ u8 sxn_protect;
++ u8 direct_fbk;
++ u8 __rsv[2];
++} __packed;
++
++struct mt7996_mcu_bf_basic_event {
++ struct mt7996_mcu_rxd rxd;
++
++ u8 __rsv1[4];
++
++ __le16 tag;
++ __le16 len;
++};
++
++struct mt7996_mcu_bf_starec_read {
++
++ struct mt7996_mcu_bf_basic_event event;
++
++ __le16 pfmu_id;
++ bool is_su_mu;
++ u8 txbf_cap;
++ u8 sounding_phy;
++ u8 ndpa_rate;
++ u8 ndp_rate;
++ u8 rpt_poll_rate;
++ u8 tx_mode;
++ u8 nc;
++ u8 nr;
++ u8 bw;
++ u8 total_mem_require;
++ u8 mem_require_20m;
++ u8 mem_row0;
++ u8 mem_col0:6;
++ u8 mem_row0_msb:2;
++ u8 mem_row1;
++ u8 mem_col1:6;
++ u8 mem_row1_msb:2;
++ u8 mem_row2;
++ u8 mem_col2:6;
++ u8 mem_row2_msb:2;
++ u8 mem_row3;
++ u8 mem_col3:6;
++ u8 mem_row3_msb:2;
++
++ __le16 smart_ant;
++ u8 se_idx;
++ u8 auto_sounding_ctrl;
++
++ u8 bf_timeout;
++ u8 bf_dbw;
++ u8 bf_ncol;
++ u8 bf_nrow;
++
++ u8 nr_lt_bw80;
++ u8 nc_lt_bw80;
++ u8 ru_start_idx;
++ u8 ru_end_idx;
++
++ bool trigger_su;
++ bool trigger_mu;
++
++ bool ng16_su;
++ bool ng16_mu;
++
++ bool codebook42_su;
++ bool codebook75_mu;
++
++ u8 he_ltf;
++ u8 pp_fd_val;
++};
++
++#define TXBF_PFMU_ID_NUM_MAX 48
++
++#define TXBF_PFMU_ID_NUM_MAX_TBTC_BAND0 TXBF_PFMU_ID_NUM_MAX
++#define TXBF_PFMU_ID_NUM_MAX_TBTC_BAND1 TXBF_PFMU_ID_NUM_MAX
++#define TXBF_PFMU_ID_NUM_MAX_TBTC_BAND2 TXBF_PFMU_ID_NUM_MAX
++
++/* CFG_BF_STA_REC shall be varied based on BAND Num */
++#define CFG_BF_STA_REC_NUM (TXBF_PFMU_ID_NUM_MAX_TBTC_BAND0 + TXBF_PFMU_ID_NUM_MAX_TBTC_BAND1 + TXBF_PFMU_ID_NUM_MAX_TBTC_BAND2)
++
++#define BF_SND_CTRL_STA_DWORD_CNT ((CFG_BF_STA_REC_NUM + 0x1F) >> 5)
++
++#ifndef ALIGN_4
++ #define ALIGN_4(_value) (((_value) + 3) & ~3u)
++#endif /* ALIGN_4 */
++
++#define CFG_WIFI_RAM_BAND_NUM 3
++
++struct uni_event_bf_txsnd_sta_info {
++ u8 snd_intv; /* Sounding interval upper bound, unit:15ms */
++ u8 snd_intv_cnt; /* Sounding interval counter */
++ u8 snd_tx_cnt; /* Tx sounding count for debug */
++ u8 snd_stop_reason; /* Bitwise reason to put in Stop Queue */
++};
++
++struct mt7996_mcu_tx_snd_info {
++
++ struct mt7996_mcu_bf_basic_event event;
++
++ u8 vht_opt;
++ u8 he_opt;
++ u8 glo_opt;
++ u8 __rsv;
++ __le32 snd_rec_su_sta[BF_SND_CTRL_STA_DWORD_CNT];
++ __le32 snd_rec_vht_mu_sta[BF_SND_CTRL_STA_DWORD_CNT];
++ __le32 snd_rec_he_tb_sta[BF_SND_CTRL_STA_DWORD_CNT];
++ __le32 snd_rec_eht_tb_sta[BF_SND_CTRL_STA_DWORD_CNT];
++ __le16 wlan_idx_for_mc_snd[ALIGN_4(CFG_WIFI_RAM_BAND_NUM)];
++ __le16 wlan_idx_for_he_tb_snd[ALIGN_4(CFG_WIFI_RAM_BAND_NUM)];
++ __le16 wlan_idx_for_eht_tb_snd[ALIGN_4(CFG_WIFI_RAM_BAND_NUM)];
++ __le16 ul_length;
++ u8 mcs;
++ u8 ldpc;
++ struct uni_event_bf_txsnd_sta_info snd_sta_info[CFG_BF_STA_REC_NUM];
++};
++
++struct mt7996_mcu_txbf_fbk_info {
++
++ struct mt7996_mcu_bf_basic_event event;
++
++ __le32 u4DeQInterval; /* By ms */
++ __le32 u4PollPFMUIntrStatTimeOut; /* micro-sec */
++ __le32 u4RptPktTimeOutListNum;
++ __le32 u4RptPktListNum;
++ __le32 u4PFMUWRTimeOutCnt;
++ __le32 u4PFMUWRFailCnt;
++ __le32 u4PFMUWRDoneCnt;
++ __le32 u4PFMUWRTimeoutFreeCnt;
++ __le32 u4FbRptPktDropCnt;
++ __le32 au4RxPerStaFbRptCnt[CFG_BF_STA_REC_NUM];
++};
++
++struct pfmu_ru_field {
++ __le32 ru_start_id:7;
++ __le32 _rsv1:1;
++ __le32 ru_end_id:7;
++ __le32 _rsv2:1;
++} __packed;
++
++struct pfmu_partial_bw_info {
++ __le32 partial_bw_info:9;
++ __le32 _rsv1:7;
++} __packed;
++
++struct mt7996_pfmu_tag1 {
++ __le32 pfmu_idx:10;
++ __le32 ebf:1;
++ __le32 data_bw:3;
++ __le32 lm:3;
++ __le32 is_mu:1;
++ __le32 nr:3;
++ __le32 nc:3;
++ __le32 codebook:2;
++ __le32 ngroup:2;
++ __le32 invalid_prof:1;
++ __le32 _rsv:3;
++
++ __le32 col_id1:7, row_id1:9;
++ __le32 col_id2:7, row_id2:9;
++ __le32 col_id3:7, row_id3:9;
++ __le32 col_id4:7, row_id4:9;
++
++ union {
++ struct pfmu_ru_field field;
++ struct pfmu_partial_bw_info bw_info;
++ };
++ __le32 mob_cal_en:1;
++ __le32 _rsv2:3;
++ __le32 mob_ru_alloc:9; /* EHT profile uses full 9 bit */
++ __le32 _rsv3:3;
++
++ __le32 snr_sts0:8, snr_sts1:8, snr_sts2:8, snr_sts3:8;
++ __le32 snr_sts4:8, snr_sts5:8, snr_sts6:8, snr_sts7:8;
++
++ __le32 _rsv4;
++} __packed;
++
++struct mt7996_pfmu_tag2 {
++ __le32 smart_ant:24;
++ __le32 se_idx:5;
++ __le32 _rsv:3;
++
++ __le32 _rsv1:16;
++ __le32 ibf_timeout:8;
++ __le32 _rsv2:8;
++
++ __le32 ibf_data_bw:3;
++ __le32 ibf_nc:3;
++ __le32 ibf_nr:3;
++ __le32 ibf_ru:9;
++ __le32 _rsv3:14;
++
++ __le32 mob_delta_t:8;
++ __le32 mob_lq_result:7;
++ __le32 _rsv5:1;
++ __le32 _rsv6:16;
++
++ __le32 _rsv7;
++} __packed;
++
++struct mt7996_pfmu_tag_event {
++ struct mt7996_mcu_bf_basic_event event;
++
++ u8 bfer;
++ u8 __rsv[3];
++
++ struct mt7996_pfmu_tag1 t1;
++ struct mt7996_pfmu_tag2 t2;
++};
++
++enum {
++ UNI_EVENT_BF_PFMU_TAG = 0x5,
++ UNI_EVENT_BF_PFMU_DATA = 0x7,
++ UNI_EVENT_BF_STAREC = 0xB,
++ UNI_EVENT_BF_CAL_PHASE = 0xC,
++ UNI_EVENT_BF_FBK_INFO = 0x17,
++ UNI_EVENT_BF_TXSND_INFO = 0x18,
++ UNI_EVENT_BF_PLY_INFO = 0x19,
++ UNI_EVENT_BF_METRIC_INFO = 0x1A,
++ UNI_EVENT_BF_TXCMD_CFG_INFO = 0x1B,
++ UNI_EVENT_BF_SND_CNT_INFO = 0x1D,
++ UNI_EVENT_BF_MAX_NUM
++};
++
++enum {
++ UNI_CMD_MURU_FIXED_RATE_CTRL = 0x11,
++ UNI_CMD_MURU_FIXED_GROUP_RATE_CTRL,
++};
++
++struct uni_muru_mum_set_group_tbl_entry {
++ __le16 wlan_idx0;
++ __le16 wlan_idx1;
++ __le16 wlan_idx2;
++ __le16 wlan_idx3;
++
++ u8 dl_mcs_user0:4;
++ u8 dl_mcs_user1:4;
++ u8 dl_mcs_user2:4;
++ u8 dl_mcs_user3:4;
++ u8 ul_mcs_user0:4;
++ u8 ul_mcs_user1:4;
++ u8 ul_mcs_user2:4;
++ u8 ul_mcs_user3:4;
++
++ u8 num_user:2;
++ u8 rsv:6;
++ u8 nss0:2;
++ u8 nss1:2;
++ u8 nss2:2;
++ u8 nss3:2;
++ u8 ru_alloc;
++ u8 ru_alloc_ext;
++
++ u8 capa;
++ u8 gi;
++ u8 dl_ul;
++ u8 _rsv2;
++};
++
++enum UNI_CMD_MURU_VER_T {
++ UNI_CMD_MURU_VER_LEG = 0,
++ UNI_CMD_MURU_VER_HE,
++ UNI_CMD_MURU_VER_EHT,
++ UNI_CMD_MURU_VER_MAX
++};
++
++#define UNI_MAX_MCS_SUPPORT_HE 11
++#define UNI_MAX_MCS_SUPPORT_EHT 13
++
++enum {
++ RUALLOC_BW20 = 122,
++ RUALLOC_BW40 = 130,
++ RUALLOC_BW80 = 134,
++ RUALLOC_BW160 = 137,
++ RUALLOC_BW320 = 395,
++};
++
++enum {
++ MAX_MODBF_VHT = 0,
++ MAX_MODBF_HE = 2,
++ MAX_MODBF_EHT = 4,
++};
++
++enum {
++ BF_SND_READ_INFO = 0,
++ BF_SND_CFG_OPT,
++ BF_SND_CFG_INTV,
++ BF_SND_STA_STOP,
++ BF_SND_CFG_MAX_STA,
++ BF_SND_CFG_BFRP,
++ BF_SND_CFG_INF,
++ BF_SND_CFG_TXOP_SND
+ };
+
+ enum {
+--
+2.18.0
+