blob: 8867fe8c2853170dfd756f238d3bf1b13442f925 [file] [log] [blame]
developer43a264f2024-03-26 14:09:54 +08001From 940f89e5dd90f5554354036614dce057ade743e1 Mon Sep 17 00:00:00 2001
developer281084d2023-06-19 12:03:50 +08002From: MeiChia Chiu <meichia.chiu@mediatek.com>
3Date: Tue, 13 Dec 2022 15:17:43 +0800
developer8935fc12024-01-11 14:08:37 +08004Subject: [PATCH 1012/1044] mtk: wifi: mt76: mt7996: add mu vendor command
developerd243af02023-12-21 14:49:33 +08005 support
developer281084d2023-06-19 12:03:50 +08006
developerd243af02023-12-21 14:49:33 +08007mtk: wifi: mt76: fix muru_onoff as all enabled by default
8
9Fix muru_onoff default value as 0xF, which means all MU & RU are
10enabled. The purpose of this commit is to align muru_onoff value with
11hostapd and mt76 driver
12
13Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
developer281084d2023-06-19 12:03:50 +080014---
15 mt7996/Makefile | 3 +-
developerd243af02023-12-21 14:49:33 +080016 mt7996/init.c | 9 ++++++
developere35b8e42023-10-16 11:04:00 +080017 mt7996/mcu.c | 37 ++++++++++++++++++---
developer281084d2023-06-19 12:03:50 +080018 mt7996/mcu.h | 12 +++++++
developerd243af02023-12-21 14:49:33 +080019 mt7996/mt7996.h | 7 ++++
developere35b8e42023-10-16 11:04:00 +080020 mt7996/vendor.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
developer281084d2023-06-19 12:03:50 +080021 mt7996/vendor.h | 22 +++++++++++++
developerd243af02023-12-21 14:49:33 +080022 7 files changed, 169 insertions(+), 6 deletions(-)
developer281084d2023-06-19 12:03:50 +080023 create mode 100644 mt7996/vendor.c
24 create mode 100644 mt7996/vendor.h
25
26diff --git a/mt7996/Makefile b/mt7996/Makefile
developerd243af02023-12-21 14:49:33 +080027index 7bb17f44..6643c7a3 100644
developer281084d2023-06-19 12:03:50 +080028--- a/mt7996/Makefile
29+++ b/mt7996/Makefile
30@@ -1,11 +1,12 @@
31 # SPDX-License-Identifier: ISC
32 EXTRA_CFLAGS += -DCONFIG_MT76_LEDS
33 EXTRA_CFLAGS += -DCONFIG_MTK_DEBUG
34+EXTRA_CFLAGS += -DCONFIG_MTK_VENDOR
35
36 obj-$(CONFIG_MT7996E) += mt7996e.o
37
38 mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
39- debugfs.o mmio.o
40+ debugfs.o mmio.o vendor.o
41
42 mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
developere35b8e42023-10-16 11:04:00 +080043 mt7996e-$(CONFIG_NL80211_TESTMODE) += testmode.o
developer281084d2023-06-19 12:03:50 +080044diff --git a/mt7996/init.c b/mt7996/init.c
developerebda9012024-02-22 13:42:45 +080045index c135da9c..fba61c01 100644
developer281084d2023-06-19 12:03:50 +080046--- a/mt7996/init.c
47+++ b/mt7996/init.c
developerd243af02023-12-21 14:49:33 +080048@@ -368,6 +368,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
49
50 phy->slottime = 9;
51 phy->beacon_rate = -1;
52+ phy->muru_onoff = OFDMA_UL | OFDMA_DL | MUMIMO_DL | MUMIMO_UL;
53
54 hw->sta_data_size = sizeof(struct mt7996_sta);
55 hw->vif_data_size = sizeof(struct mt7996_vif);
developer8935fc12024-01-11 14:08:37 +080056@@ -616,6 +617,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
developer281084d2023-06-19 12:03:50 +080057 if (ret)
58 goto error;
59
60+#ifdef CONFIG_MTK_VENDOR
61+ mt7996_vendor_register(phy);
62+#endif
63+
64 ret = mt76_register_phy(mphy, true, mt76_rates,
65 ARRAY_SIZE(mt76_rates));
66 if (ret)
developer8935fc12024-01-11 14:08:37 +080067@@ -1401,6 +1406,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
developer281084d2023-06-19 12:03:50 +080068 dev->mt76.test_ops = &mt7996_testmode_ops;
69 #endif
developer36fe7092023-09-27 12:24:47 +080070
developer281084d2023-06-19 12:03:50 +080071+#ifdef CONFIG_MTK_VENDOR
72+ mt7996_vendor_register(&dev->phy);
73+#endif
74+
75 ret = mt76_register_device(&dev->mt76, true, mt76_rates,
76 ARRAY_SIZE(mt76_rates));
77 if (ret)
78diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developer43a264f2024-03-26 14:09:54 +080079index 0ee17ff9..8348d22a 100644
developer281084d2023-06-19 12:03:50 +080080--- a/mt7996/mcu.c
81+++ b/mt7996/mcu.c
developer43a264f2024-03-26 14:09:54 +080082@@ -1373,6 +1373,8 @@ static void
developer281084d2023-06-19 12:03:50 +080083 mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
84 struct ieee80211_vif *vif, struct ieee80211_sta *sta)
85 {
86+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
87+ struct mt7996_phy *phy = mvif->phy;
88 struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
89 struct sta_rec_muru *muru;
90 struct tlv *tlv;
developer43a264f2024-03-26 14:09:54 +080091@@ -1384,11 +1386,14 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
developer281084d2023-06-19 12:03:50 +080092 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
93
94 muru = (struct sta_rec_muru *)tlv;
95- muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer ||
96- vif->bss_conf.he_mu_beamformer ||
97- vif->bss_conf.vht_mu_beamformer ||
98- vif->bss_conf.vht_mu_beamformee;
99- muru->cfg.ofdma_dl_en = true;
100+ muru->cfg.mimo_dl_en = (vif->bss_conf.eht_mu_beamformer ||
101+ vif->bss_conf.he_mu_beamformer ||
102+ vif->bss_conf.vht_mu_beamformer ||
103+ vif->bss_conf.vht_mu_beamformee) &&
104+ !!(phy->muru_onoff & MUMIMO_DL);
105+ muru->cfg.mimo_ul_en = !!(phy->muru_onoff & MUMIMO_UL);
106+ muru->cfg.ofdma_dl_en = !!(phy->muru_onoff & OFDMA_DL);
107+ muru->cfg.ofdma_ul_en = !!(phy->muru_onoff & OFDMA_UL);
108
109 if (sta->deflink.vht_cap.vht_supported)
110 muru->mimo_dl.vht_mu_bfee =
developer43a264f2024-03-26 14:09:54 +0800111@@ -4919,3 +4924,25 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
developer281084d2023-06-19 12:03:50 +0800112 return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS),
113 &req, sizeof(req), false);
114 }
115+
116+#ifdef CONFIG_MTK_VENDOR
117+void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
118+{
119+ u8 mode, val;
120+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
121+ struct mt7996_phy *phy = mvif->phy;
122+
123+ mode = FIELD_GET(RATE_CFG_MODE, *((u32 *)data));
124+ val = FIELD_GET(RATE_CFG_VAL, *((u32 *)data));
125+
126+ switch (mode) {
127+ case RATE_PARAM_AUTO_MU:
128+ if (val < 0 || val > 15) {
129+ printk("Wrong value! The value is between 0-15.\n");
130+ break;
131+ }
132+ phy->muru_onoff = val;
133+ break;
134+ }
135+}
136+#endif
137diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developerd243af02023-12-21 14:49:33 +0800138index 887d9b49..68bf82fc 100644
developer281084d2023-06-19 12:03:50 +0800139--- a/mt7996/mcu.h
140+++ b/mt7996/mcu.h
developerd243af02023-12-21 14:49:33 +0800141@@ -754,8 +754,20 @@ enum {
developer281084d2023-06-19 12:03:50 +0800142 RATE_PARAM_FIXED_MCS,
143 RATE_PARAM_FIXED_GI = 11,
144 RATE_PARAM_AUTO = 20,
145+#ifdef CONFIG_MTK_VENDOR
146+ RATE_PARAM_AUTO_MU = 32,
147+#endif
148 };
149
150+#define RATE_CFG_MODE GENMASK(15, 8)
151+#define RATE_CFG_VAL GENMASK(7, 0)
152+
153+/* MURU */
154+#define OFDMA_DL BIT(0)
155+#define OFDMA_UL BIT(1)
156+#define MUMIMO_DL BIT(2)
157+#define MUMIMO_UL BIT(3)
158+
159 enum {
160 BF_SOUNDING_ON = 1,
161 BF_HW_EN_UPDATE = 17,
162diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developerd243af02023-12-21 14:49:33 +0800163index 2daca449..d0b425da 100644
developer281084d2023-06-19 12:03:50 +0800164--- a/mt7996/mt7996.h
165+++ b/mt7996/mt7996.h
developerd243af02023-12-21 14:49:33 +0800166@@ -295,6 +295,8 @@ struct mt7996_phy {
developer281084d2023-06-19 12:03:50 +0800167
developere35b8e42023-10-16 11:04:00 +0800168 struct mt7996_scs_ctrl scs_ctrl;
developer36fe7092023-09-27 12:24:47 +0800169
developere35b8e42023-10-16 11:04:00 +0800170+ u8 muru_onoff;
developerd243af02023-12-21 14:49:33 +0800171+
developere35b8e42023-10-16 11:04:00 +0800172 #ifdef CONFIG_NL80211_TESTMODE
173 struct {
174 u32 *reg_backup;
developerd243af02023-12-21 14:49:33 +0800175@@ -733,6 +735,11 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
developere35b8e42023-10-16 11:04:00 +0800176 bool hif2, int *irq);
177 u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
developer281084d2023-06-19 12:03:50 +0800178
179+#ifdef CONFIG_MTK_VENDOR
180+void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
181+void mt7996_vendor_register(struct mt7996_phy *phy);
182+#endif
183+
184 #ifdef CONFIG_MTK_DEBUG
185 int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
developerd243af02023-12-21 14:49:33 +0800186 int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
developer281084d2023-06-19 12:03:50 +0800187diff --git a/mt7996/vendor.c b/mt7996/vendor.c
188new file mode 100644
developerd243af02023-12-21 14:49:33 +0800189index 00000000..b5ecbdf1
developer281084d2023-06-19 12:03:50 +0800190--- /dev/null
191+++ b/mt7996/vendor.c
developere35b8e42023-10-16 11:04:00 +0800192@@ -0,0 +1,85 @@
developer281084d2023-06-19 12:03:50 +0800193+// SPDX-License-Identifier: ISC
194+/*
195+ * Copyright (C) 2020, MediaTek Inc. All rights reserved.
196+ */
197+
198+#include <net/netlink.h>
199+
200+#include "mt7996.h"
201+#include "mcu.h"
202+#include "vendor.h"
developere35b8e42023-10-16 11:04:00 +0800203+#include "mtk_mcu.h"
developer281084d2023-06-19 12:03:50 +0800204+
205+static const struct nla_policy
206+mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
207+ [MTK_VENDOR_ATTR_MU_CTRL_ONOFF] = {.type = NLA_U8 },
208+ [MTK_VENDOR_ATTR_MU_CTRL_DUMP] = {.type = NLA_U8 },
209+};
210+
211+static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy,
212+ struct wireless_dev *wdev,
213+ const void *data,
214+ int data_len)
215+{
216+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
217+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_MU_CTRL];
218+ int err;
219+ u8 val8;
220+ u32 val32 = 0;
221+
222+ err = nla_parse(tb, MTK_VENDOR_ATTR_MU_CTRL_MAX, data, data_len,
223+ mu_ctrl_policy, NULL);
224+ if (err)
225+ return err;
226+
227+ if (tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]) {
228+ val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]);
229+ val32 |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_AUTO_MU) |
230+ FIELD_PREP(RATE_CFG_VAL, val8);
231+ ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
232+ mt7996_set_wireless_vif, &val32);
233+ }
234+
235+ return 0;
236+}
237+
238+static int
239+mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
240+ struct sk_buff *skb, const void *data, int data_len,
241+ unsigned long *storage)
242+{
243+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
244+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
245+ int len = 0;
246+
247+ if (*storage == 1)
248+ return -ENOENT;
249+ *storage = 1;
250+
251+ if (nla_put_u8(skb, MTK_VENDOR_ATTR_MU_CTRL_DUMP, phy->muru_onoff))
252+ return -ENOMEM;
253+ len += 1;
254+
255+ return len;
256+}
257+
258+static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
259+ {
260+ .info = {
261+ .vendor_id = MTK_NL80211_VENDOR_ID,
262+ .subcmd = MTK_NL80211_VENDOR_SUBCMD_MU_CTRL,
263+ },
264+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
265+ WIPHY_VENDOR_CMD_NEED_RUNNING,
266+ .doit = mt7996_vendor_mu_ctrl,
267+ .dumpit = mt7996_vendor_mu_ctrl_dump,
268+ .policy = mu_ctrl_policy,
269+ .maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
270+ },
271+};
272+
273+void mt7996_vendor_register(struct mt7996_phy *phy)
274+{
275+ phy->mt76->hw->wiphy->vendor_commands = mt7996_vendor_commands;
276+ phy->mt76->hw->wiphy->n_vendor_commands = ARRAY_SIZE(mt7996_vendor_commands);
277+}
278diff --git a/mt7996/vendor.h b/mt7996/vendor.h
279new file mode 100644
developerd243af02023-12-21 14:49:33 +0800280index 00000000..8ac3ba8e
developer281084d2023-06-19 12:03:50 +0800281--- /dev/null
282+++ b/mt7996/vendor.h
283@@ -0,0 +1,22 @@
284+#ifndef __MT7996_VENDOR_H
285+#define __MT7996_VENDOR_H
286+
287+#define MTK_NL80211_VENDOR_ID 0x0ce7
288+
289+enum mtk_nl80211_vendor_subcmds {
290+ MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
291+};
292+
293+enum mtk_vendor_attr_mu_ctrl {
294+ MTK_VENDOR_ATTR_MU_CTRL_UNSPEC,
295+
296+ MTK_VENDOR_ATTR_MU_CTRL_ONOFF,
297+ MTK_VENDOR_ATTR_MU_CTRL_DUMP,
298+
299+ /* keep last */
300+ NUM_MTK_VENDOR_ATTRS_MU_CTRL,
301+ MTK_VENDOR_ATTR_MU_CTRL_MAX =
302+ NUM_MTK_VENDOR_ATTRS_MU_CTRL - 1
303+};
304+
305+#endif
306--
developere35b8e42023-10-16 11:04:00 +08003072.18.0
developer281084d2023-06-19 12:03:50 +0800308