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