<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">From 243c22b7b407e726fa5a6766728c86dc389ce41f Mon Sep 17 00:00:00 2001
From: Evelyn Tsai &lt;evelyn.tsai@mediatek.com&gt;
Date: Tue, 2 May 2023 06:39:48 +0800
Subject: [PATCH 3004/3010] wifi: mt76: mt7996: add wifi5 cert patch

Signed-off-by: Fang Zhao &lt;fang.zhao@mediatek.com&gt;
Signed-off-by: Evelyn Tsai &lt;evelyn.tsai@mediatek.com&gt;
---
 mt7996/mac.c    |  10 ++++-
 mt7996/mcu.c    |  33 ++++++++++++++++
 mt7996/mcu.h    |   2 +
 mt7996/mt7996.h |   5 +++
 mt7996/vendor.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++
 mt7996/vendor.h |  66 +++++++++++++++++++++++++++++++
 6 files changed, 215 insertions(+), 2 deletions(-)

diff --git a/mt7996/mac.c b/mt7996/mac.c
index 8ae03a1..e7e7298 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
@@ -1391,7 +1391,10 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
 static void
 mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
 {
-	struct mt7996_sta *msta;
+	struct mt7996_sta *msta = (struct mt7996_sta *)sta-&gt;drv_priv;
+#ifdef CONFIG_MTK_VENDOR
+	struct mt7996_dev *dev = msta-&gt;vif-&gt;phy-&gt;dev;
+#endif
 	u16 fc, tid;
 	u32 val;
 
@@ -1399,7 +1402,11 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
 		return;
 
 	tid = le32_get_bits(txwi[1], MT_TXD1_TID);
+#ifdef CONFIG_MTK_VENDOR
+	if (!dev-&gt;cert_mode &amp;&amp; tid &gt;= 6) /* skip VO queue */
+#else
 	if (tid &gt;= 6) /* skip VO queue */
+#endif
 		return;
 
 	val = le32_to_cpu(txwi[2]);
@@ -1408,7 +1415,6 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
 	if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
 		return;
 
-	msta = (struct mt7996_sta *)sta-&gt;drv_priv;
 	if (!test_and_set_bit(tid, &amp;msta-&gt;ampdu_state))
 		ieee80211_start_tx_ba_session(sta, tid, 0);
 }
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
index 319cd24..3b2df70 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -1167,6 +1167,10 @@ mt7996_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
 {
 	struct sta_rec_vht *vht;
 	struct tlv *tlv;
+#ifdef CONFIG_MTK_VENDOR
+	struct mt7996_sta *msta = (struct mt7996_sta *)sta-&gt;drv_priv;
+	struct mt7996_phy *phy = (struct mt7996_phy *)msta-&gt;vif-&gt;phy;
+#endif
 
 	/* For 6G band, this tlv is necessary to let hw work normally */
 	if (!sta-&gt;deflink.he_6ghz_capa.capa &amp;&amp; !sta-&gt;deflink.vht_cap.vht_supported)
@@ -1178,6 +1182,9 @@ mt7996_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
 	vht-&gt;vht_cap = cpu_to_le32(sta-&gt;deflink.vht_cap.cap);
 	vht-&gt;vht_rx_mcs_map = sta-&gt;deflink.vht_cap.vht_mcs.rx_mcs_map;
 	vht-&gt;vht_tx_mcs_map = sta-&gt;deflink.vht_cap.vht_mcs.tx_mcs_map;
+#ifdef CONFIG_MTK_VENDOR
+	vht-&gt;rts_bw_sig = phy-&gt;rts_bw_sig;
+#endif
 }
 
 static void
@@ -1202,6 +1209,11 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
 	amsdu-&gt;amsdu_en = true;
 	msta-&gt;wcid.amsdu = true;
 
+#ifdef CONFIG_MTK_VENDOR
+	if (dev-&gt;cert_mode)
+		sta-&gt;deflink.agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
+#endif
+
 	switch (sta-&gt;deflink.agg.max_amsdu_len) {
 	case IEEE80211_MAX_MPDU_LEN_VHT_11454:
 		amsdu-&gt;max_mpdu_size =
@@ -4379,6 +4391,27 @@ int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val)
 				 &amp;req, sizeof(req), true);
 }
 
+int mt7996_mcu_set_band_confg(struct mt7996_phy *phy, u16 option, bool enable)
+{
+	struct {
+		u8 band_idx;
+		u8 _rsv[3];
+
+		__le16 tag;
+		__le16 len;
+		bool enable;
+		u8 _rsv2[3];
+	} __packed req = {
+		.band_idx = phy-&gt;mt76-&gt;band_idx,
+		.tag = cpu_to_le16(option),
+		.len = cpu_to_le16(sizeof(req) - 4),
+		.enable = enable,
+	};
+
+	return mt76_mcu_send_msg(&amp;phy-&gt;dev-&gt;mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
+				 &amp;req, sizeof(req), true);
+}
+
 int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable)
 {
 	struct {
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
index d99791b..5a431dc 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
@@ -710,6 +710,8 @@ mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
 enum {
 	UNI_BAND_CONFIG_RADIO_ENABLE,
 	UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
+	UNI_BAND_CONFIG_RTS_SIGTA_EN = 0x09,
+	UNI_BAND_CONFIG_DIS_SECCH_CCA_DET = 0x0a,
 };
 
 enum {
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
index 881f97c..9c6bcf3 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
@@ -451,6 +451,7 @@ struct mt7996_phy {
 	} test;
 #endif
 #ifdef CONFIG_MTK_VENDOR
+	u8 rts_bw_sig;
 	spinlock_t amnt_lock;
 	struct mt7996_air_monitor_ctrl amnt_ctrl;
 #endif
@@ -567,6 +568,9 @@ struct mt7996_dev {
 		u32 pao_nbuf[MT7996_TX_PAO_NUM_MAX];
 	} dbg;
 #endif
+#ifdef CONFIG_MTK_VENDOR
+	bool cert_mode;
+#endif
 };
 
 enum {
@@ -774,6 +778,7 @@ void mt7996_mcu_scs_sta_poll(struct work_struct *work);
 #ifdef CONFIG_NL80211_TESTMODE
 void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
 #endif
+int mt7996_mcu_set_band_confg(struct mt7996_phy *phy, u16 option, bool enable);
 
 static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
 {
diff --git a/mt7996/vendor.c b/mt7996/vendor.c
index 170495d..d044929 100644
--- a/mt7996/vendor.c
+++ b/mt7996/vendor.c
@@ -9,12 +9,26 @@
 #include "mcu.h"
 #include "vendor.h"
 
+#ifdef CONFIG_MTK_VENDOR
 static const struct nla_policy
 mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
 	[MTK_VENDOR_ATTR_MU_CTRL_ONOFF] = {.type = NLA_U8 },
 	[MTK_VENDOR_ATTR_MU_CTRL_DUMP] = {.type = NLA_U8 },
 };
 
+static const struct nla_policy
+wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
+	[MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU] = {.type = NLA_U8 },
+	[MTK_VENDOR_ATTR_WIRELESS_CTRL_AMPDU] = {.type = NLA_U8 },
+	[MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT] = {.type = NLA_U8 },
+	[MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA] = {.type = NLA_U8 },
+};
+
+static const struct nla_policy
+wireless_dump_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP] = {
+	[MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU] = { .type = NLA_U8 },
+};
+
 static const struct nla_policy
 amnt_ctrl_policy[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL] = {
 	[MTK_VENDOR_ATTR_AMNT_CTRL_SET] = {.type = NLA_NESTED },
@@ -93,6 +107,80 @@ mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
 	return len;
 }
 
+void mt7996_set_wireless_cert(struct ieee80211_hw *hw, u8 en)
+{
+	struct mt7996_phy *phy = mt7996_hw_phy(hw);
+	struct mt7996_dev *dev = phy-&gt;dev;
+
+	dev-&gt;cert_mode = !!en;
+}
+
+void mt7996_set_wireless_rts_sigta(struct ieee80211_hw *hw, u8 value) {
+	struct mt7996_phy *phy = mt7996_hw_phy(hw);
+
+	switch (value) {
+	case BW_SIGNALING_STATIC:
+	case BW_SIGNALING_DYNAMIC:
+		mt7996_mcu_set_band_confg(phy, UNI_BAND_CONFIG_RTS_SIGTA_EN, true);
+		mt7996_mcu_set_band_confg(phy, UNI_BAND_CONFIG_DIS_SECCH_CCA_DET, false);
+		break;
+	default:
+		value = BW_SIGNALING_DISABLE;
+	case BW_SIGNALING_DISABLE:
+		mt7996_mcu_set_band_confg(phy, UNI_BAND_CONFIG_RTS_SIGTA_EN, false);
+		mt7996_mcu_set_band_confg(phy, UNI_BAND_CONFIG_DIS_SECCH_CCA_DET, true);
+		break;
+      }
+
+	phy-&gt;rts_bw_sig = value;
+
+	/* Set RTS Threshold to a lower Value */
+	mt7996_mcu_set_rts_thresh(phy, 500);
+}
+
+static int mt7996_vendor_wireless_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
+				       const void *data, int data_len)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL];
+	int err;
+	u8 val8;
+
+	err = nla_parse(tb, MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX, data, data_len,
+			wireless_ctrl_policy, NULL);
+	if (err)
+		return err;
+
+	if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT]) {
+		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT]);
+		mt7996_set_wireless_cert(hw, val8);
+	} else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA]) {
+		val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA]);
+		mt7996_set_wireless_rts_sigta(hw, val8);
+	}
+	return 0;
+}
+
+static int
+mt7996_vendor_wireless_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+				 struct sk_buff *skb, const void *data, int data_len,
+				 unsigned long *storage)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	int len = 0;
+
+	if (*storage == 1)
+		return -ENOENT;
+	*storage = 1;
+
+	if (nla_put_u8(skb, MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU,
+		       ieee80211_hw_check(hw, SUPPORTS_AMSDU_IN_AMPDU)))
+	return -ENOMEM;
+	len += 1;
+
+	return len;
+ }
+
 void mt7996_vendor_amnt_fill_rx(struct mt7996_phy *phy, struct sk_buff *skb)
 {
 	struct mt76_rx_status *status = (struct mt76_rx_status *)skb-&gt;cb;
@@ -448,6 +536,18 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
 		.policy = mu_ctrl_policy,
 		.maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
 	},
+	{
+		.info = {
+		        .vendor_id = MTK_NL80211_VENDOR_ID,
+		        .subcmd = MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL,
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
+		        WIPHY_VENDOR_CMD_NEED_RUNNING,
+		.doit = mt7996_vendor_wireless_ctrl,
+		.dumpit = mt7996_vendor_wireless_ctrl_dump,
+		.policy = wireless_ctrl_policy,
+		.maxattr = MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX,
+	},
 	{
 		.info = {
 			.vendor_id = MTK_NL80211_VENDOR_ID,
@@ -478,3 +578,4 @@ void mt7996_vendor_register(struct mt7996_phy *phy)
 	phy-&gt;mt76-&gt;hw-&gt;wiphy-&gt;vendor_commands = mt7996_vendor_commands;
 	phy-&gt;mt76-&gt;hw-&gt;wiphy-&gt;n_vendor_commands = ARRAY_SIZE(mt7996_vendor_commands);
 }
+#endif
\ No newline at end of file
diff --git a/mt7996/vendor.h b/mt7996/vendor.h
index eec9e74..2685b7b 100644
--- a/mt7996/vendor.h
+++ b/mt7996/vendor.h
@@ -3,8 +3,12 @@
 
 #define MTK_NL80211_VENDOR_ID	0x0ce7
 
+#ifdef CONFIG_MTK_VENDOR
+
 enum mtk_nl80211_vendor_subcmds {
 	MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae,
+	MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL = 0xc3,
+	MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL = 0xc4,
 	MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
 	MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
 };
@@ -21,6 +25,66 @@ enum mtk_vendor_attr_mu_ctrl {
 		NUM_MTK_VENDOR_ATTRS_MU_CTRL - 1
 };
 
+enum mtk_capi_control_changed {
+	CAPI_RFEATURE_CHANGED = BIT(16),
+	CAPI_WIRELESS_CHANGED = BIT(17),
+};
+
+enum mtk_vendor_attr_rfeature_ctrl {
+	MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
+
+	MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI,
+	MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF,
+	MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG,
+	MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN,
+	MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE,
+	MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY,
+	MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF,
+
+	/* keep last */
+	NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL,
+	MTK_VENDOR_ATTR_RFEATURE_CTRL_MAX =
+	NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL - 1
+};
+
+enum mtk_vendor_attr_wireless_ctrl {
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_UNSPEC,
+
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_OFDMA,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_AMPDU,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT = 9,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_MU_EDCA, /* reserve */
+
+	/* keep last */
+	NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
+	MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX =
+		NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL - 1
+};
+
+enum mtk_vendor_attr_wireless_dump {
+	MTK_VENDOR_ATTR_WIRELESS_DUMP_UNSPEC,
+
+	MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU,
+
+	/* keep last */
+	NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP,
+	MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX =
+		NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP - 1
+};
+
+enum bw_sig {
+	BW_SIGNALING_DISABLE,
+	BW_SIGNALING_STATIC,
+	BW_SIGNALING_DYNAMIC
+};
+
 enum mtk_vendor_attr_mnt_ctrl {
 	MTK_VENDOR_ATTR_AMNT_CTRL_UNSPEC,
 
@@ -70,3 +134,5 @@ enum mtk_vendor_attr_bss_color_ctrl {
 };
 
 #endif
+
+#endif
-- 
2.18.0

</pre></body></html>