blob: 2e967b5d466ba8b9587c8e676ece529c0a899bf5 [file] [log] [blame]
developerc2cfe0f2023-09-22 04:11:09 +08001From 10d7c82abb8af232334700ded00d7ee4bb580077 Mon Sep 17 00:00:00 2001
developer064da3c2023-06-13 15:57:26 +08002From: MeiChia Chiu <meichia.chiu@mediatek.com>
3Date: Tue, 13 Dec 2022 15:17:43 +0800
developerc2cfe0f2023-09-22 04:11:09 +08004Subject: [PATCH 1007/1024] wifi: mt76: mt7996: add mu vendor command support
developer064da3c2023-06-13 15:57:26 +08005
6Change-Id: I4599bd97917651aaea51d7ff186ffff73a07e4ce
7---
8 mt7996/Makefile | 3 +-
developerc2cfe0f2023-09-22 04:11:09 +08009 mt7996/init.c | 9 ++++++
10 mt7996/mcu.c | 37 ++++++++++++++++++---
developer064da3c2023-06-13 15:57:26 +080011 mt7996/mcu.h | 12 +++++++
developerc2cfe0f2023-09-22 04:11:09 +080012 mt7996/mt7996.h | 6 ++++
13 mt7996/vendor.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
developer064da3c2023-06-13 15:57:26 +080014 mt7996/vendor.h | 22 +++++++++++++
developerc2cfe0f2023-09-22 04:11:09 +080015 7 files changed, 168 insertions(+), 6 deletions(-)
developer064da3c2023-06-13 15:57:26 +080016 create mode 100644 mt7996/vendor.c
17 create mode 100644 mt7996/vendor.h
18
19diff --git a/mt7996/Makefile b/mt7996/Makefile
developerc2cfe0f2023-09-22 04:11:09 +080020index 7bb17f440..6643c7a38 100644
developer064da3c2023-06-13 15:57:26 +080021--- a/mt7996/Makefile
22+++ b/mt7996/Makefile
23@@ -1,11 +1,12 @@
24 # SPDX-License-Identifier: ISC
25 EXTRA_CFLAGS += -DCONFIG_MT76_LEDS
26 EXTRA_CFLAGS += -DCONFIG_MTK_DEBUG
27+EXTRA_CFLAGS += -DCONFIG_MTK_VENDOR
28
29 obj-$(CONFIG_MT7996E) += mt7996e.o
30
31 mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
32- debugfs.o mmio.o
33+ debugfs.o mmio.o vendor.o
34
35 mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
developerc2cfe0f2023-09-22 04:11:09 +080036 mt7996e-$(CONFIG_NL80211_TESTMODE) += testmode.o
developer064da3c2023-06-13 15:57:26 +080037diff --git a/mt7996/init.c b/mt7996/init.c
developerc2cfe0f2023-09-22 04:11:09 +080038index f76fe6ea7..5644bba4a 100644
developer064da3c2023-06-13 15:57:26 +080039--- a/mt7996/init.c
40+++ b/mt7996/init.c
developerc2cfe0f2023-09-22 04:11:09 +080041@@ -585,6 +585,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
developer064da3c2023-06-13 15:57:26 +080042 if (ret)
43 goto error;
44
45+#ifdef CONFIG_MTK_VENDOR
46+ mt7996_vendor_register(phy);
47+#endif
48+
49 ret = mt76_register_phy(mphy, true, mt76_rates,
50 ARRAY_SIZE(mt76_rates));
51 if (ret)
developerc2cfe0f2023-09-22 04:11:09 +080052@@ -1088,6 +1092,11 @@ int mt7996_register_device(struct mt7996_dev *dev)
53 #ifdef CONFIG_NL80211_TESTMODE
developer064da3c2023-06-13 15:57:26 +080054 dev->mt76.test_ops = &mt7996_testmode_ops;
55 #endif
developerc2cfe0f2023-09-22 04:11:09 +080056+
developer064da3c2023-06-13 15:57:26 +080057+#ifdef CONFIG_MTK_VENDOR
58+ mt7996_vendor_register(&dev->phy);
59+#endif
60+
61 ret = mt76_register_device(&dev->mt76, true, mt76_rates,
62 ARRAY_SIZE(mt76_rates));
63 if (ret)
64diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developerc2cfe0f2023-09-22 04:11:09 +080065index db3cab39c..554f40ca2 100644
developer064da3c2023-06-13 15:57:26 +080066--- a/mt7996/mcu.c
67+++ b/mt7996/mcu.c
developerc2cfe0f2023-09-22 04:11:09 +080068@@ -1263,6 +1263,8 @@ static void
developer064da3c2023-06-13 15:57:26 +080069 mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
70 struct ieee80211_vif *vif, struct ieee80211_sta *sta)
71 {
72+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
73+ struct mt7996_phy *phy = mvif->phy;
74 struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
75 struct sta_rec_muru *muru;
76 struct tlv *tlv;
developerc2cfe0f2023-09-22 04:11:09 +080077@@ -1274,11 +1276,14 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
developer064da3c2023-06-13 15:57:26 +080078 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
79
80 muru = (struct sta_rec_muru *)tlv;
81- muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer ||
82- vif->bss_conf.he_mu_beamformer ||
83- vif->bss_conf.vht_mu_beamformer ||
84- vif->bss_conf.vht_mu_beamformee;
85- muru->cfg.ofdma_dl_en = true;
86+ muru->cfg.mimo_dl_en = (vif->bss_conf.eht_mu_beamformer ||
87+ vif->bss_conf.he_mu_beamformer ||
88+ vif->bss_conf.vht_mu_beamformer ||
89+ vif->bss_conf.vht_mu_beamformee) &&
90+ !!(phy->muru_onoff & MUMIMO_DL);
91+ muru->cfg.mimo_ul_en = !!(phy->muru_onoff & MUMIMO_UL);
92+ muru->cfg.ofdma_dl_en = !!(phy->muru_onoff & OFDMA_DL);
93+ muru->cfg.ofdma_ul_en = !!(phy->muru_onoff & OFDMA_UL);
94
95 if (sta->deflink.vht_cap.vht_supported)
96 muru->mimo_dl.vht_mu_bfee =
developerc2cfe0f2023-09-22 04:11:09 +080097@@ -4477,3 +4482,25 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
developer064da3c2023-06-13 15:57:26 +080098 return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS),
99 &req, sizeof(req), false);
100 }
101+
102+#ifdef CONFIG_MTK_VENDOR
103+void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
104+{
105+ u8 mode, val;
106+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
107+ struct mt7996_phy *phy = mvif->phy;
108+
109+ mode = FIELD_GET(RATE_CFG_MODE, *((u32 *)data));
110+ val = FIELD_GET(RATE_CFG_VAL, *((u32 *)data));
111+
112+ switch (mode) {
113+ case RATE_PARAM_AUTO_MU:
114+ if (val < 0 || val > 15) {
115+ printk("Wrong value! The value is between 0-15.\n");
116+ break;
117+ }
118+ phy->muru_onoff = val;
119+ break;
120+ }
121+}
122+#endif
123diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developerc2cfe0f2023-09-22 04:11:09 +0800124index 3a1b957c4..1d7748771 100644
developer064da3c2023-06-13 15:57:26 +0800125--- a/mt7996/mcu.h
126+++ b/mt7996/mcu.h
developerc2cfe0f2023-09-22 04:11:09 +0800127@@ -686,8 +686,20 @@ enum {
developer064da3c2023-06-13 15:57:26 +0800128 RATE_PARAM_FIXED_MCS,
129 RATE_PARAM_FIXED_GI = 11,
130 RATE_PARAM_AUTO = 20,
131+#ifdef CONFIG_MTK_VENDOR
132+ RATE_PARAM_AUTO_MU = 32,
133+#endif
134 };
135
136+#define RATE_CFG_MODE GENMASK(15, 8)
137+#define RATE_CFG_VAL GENMASK(7, 0)
138+
139+/* MURU */
140+#define OFDMA_DL BIT(0)
141+#define OFDMA_UL BIT(1)
142+#define MUMIMO_DL BIT(2)
143+#define MUMIMO_UL BIT(3)
144+
145 enum {
146 BF_SOUNDING_ON = 1,
147 BF_HW_EN_UPDATE = 17,
148diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developerc2cfe0f2023-09-22 04:11:09 +0800149index 7bd8abe79..88ccb3060 100644
developer064da3c2023-06-13 15:57:26 +0800150--- a/mt7996/mt7996.h
151+++ b/mt7996/mt7996.h
developerc2cfe0f2023-09-22 04:11:09 +0800152@@ -213,6 +213,7 @@ struct mt7996_phy {
developer064da3c2023-06-13 15:57:26 +0800153
developerc2cfe0f2023-09-22 04:11:09 +0800154 struct mt7996_scs_ctrl scs_ctrl;
developer064da3c2023-06-13 15:57:26 +0800155
developerc2cfe0f2023-09-22 04:11:09 +0800156+ u8 muru_onoff;
157 #ifdef CONFIG_NL80211_TESTMODE
158 struct {
159 u32 *reg_backup;
160@@ -620,6 +621,11 @@ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer064da3c2023-06-13 15:57:26 +0800161 struct ieee80211_sta *sta, struct dentry *dir);
162 #endif
163
164+#ifdef CONFIG_MTK_VENDOR
165+void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
166+void mt7996_vendor_register(struct mt7996_phy *phy);
167+#endif
168+
169 #ifdef CONFIG_MTK_DEBUG
170 int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
171 #endif
172diff --git a/mt7996/vendor.c b/mt7996/vendor.c
173new file mode 100644
developerc2cfe0f2023-09-22 04:11:09 +0800174index 000000000..b5ecbdf1d
developer064da3c2023-06-13 15:57:26 +0800175--- /dev/null
176+++ b/mt7996/vendor.c
developerc2cfe0f2023-09-22 04:11:09 +0800177@@ -0,0 +1,85 @@
developer064da3c2023-06-13 15:57:26 +0800178+// SPDX-License-Identifier: ISC
179+/*
180+ * Copyright (C) 2020, MediaTek Inc. All rights reserved.
181+ */
182+
183+#include <net/netlink.h>
184+
185+#include "mt7996.h"
186+#include "mcu.h"
187+#include "vendor.h"
developerc2cfe0f2023-09-22 04:11:09 +0800188+#include "mtk_mcu.h"
developer064da3c2023-06-13 15:57:26 +0800189+
190+static const struct nla_policy
191+mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
192+ [MTK_VENDOR_ATTR_MU_CTRL_ONOFF] = {.type = NLA_U8 },
193+ [MTK_VENDOR_ATTR_MU_CTRL_DUMP] = {.type = NLA_U8 },
194+};
195+
196+static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy,
197+ struct wireless_dev *wdev,
198+ const void *data,
199+ int data_len)
200+{
201+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
202+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_MU_CTRL];
203+ int err;
204+ u8 val8;
205+ u32 val32 = 0;
206+
207+ err = nla_parse(tb, MTK_VENDOR_ATTR_MU_CTRL_MAX, data, data_len,
208+ mu_ctrl_policy, NULL);
209+ if (err)
210+ return err;
211+
212+ if (tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]) {
213+ val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]);
214+ val32 |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_AUTO_MU) |
215+ FIELD_PREP(RATE_CFG_VAL, val8);
216+ ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
217+ mt7996_set_wireless_vif, &val32);
218+ }
219+
220+ return 0;
221+}
222+
223+static int
224+mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
225+ struct sk_buff *skb, const void *data, int data_len,
226+ unsigned long *storage)
227+{
228+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
229+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
230+ int len = 0;
231+
232+ if (*storage == 1)
233+ return -ENOENT;
234+ *storage = 1;
235+
236+ if (nla_put_u8(skb, MTK_VENDOR_ATTR_MU_CTRL_DUMP, phy->muru_onoff))
237+ return -ENOMEM;
238+ len += 1;
239+
240+ return len;
241+}
242+
243+static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
244+ {
245+ .info = {
246+ .vendor_id = MTK_NL80211_VENDOR_ID,
247+ .subcmd = MTK_NL80211_VENDOR_SUBCMD_MU_CTRL,
248+ },
249+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
250+ WIPHY_VENDOR_CMD_NEED_RUNNING,
251+ .doit = mt7996_vendor_mu_ctrl,
252+ .dumpit = mt7996_vendor_mu_ctrl_dump,
253+ .policy = mu_ctrl_policy,
254+ .maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
255+ },
256+};
257+
258+void mt7996_vendor_register(struct mt7996_phy *phy)
259+{
260+ phy->mt76->hw->wiphy->vendor_commands = mt7996_vendor_commands;
261+ phy->mt76->hw->wiphy->n_vendor_commands = ARRAY_SIZE(mt7996_vendor_commands);
262+}
263diff --git a/mt7996/vendor.h b/mt7996/vendor.h
264new file mode 100644
developerc2cfe0f2023-09-22 04:11:09 +0800265index 000000000..8ac3ba8ed
developer064da3c2023-06-13 15:57:26 +0800266--- /dev/null
267+++ b/mt7996/vendor.h
268@@ -0,0 +1,22 @@
269+#ifndef __MT7996_VENDOR_H
270+#define __MT7996_VENDOR_H
271+
272+#define MTK_NL80211_VENDOR_ID 0x0ce7
273+
274+enum mtk_nl80211_vendor_subcmds {
275+ MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
276+};
277+
278+enum mtk_vendor_attr_mu_ctrl {
279+ MTK_VENDOR_ATTR_MU_CTRL_UNSPEC,
280+
281+ MTK_VENDOR_ATTR_MU_CTRL_ONOFF,
282+ MTK_VENDOR_ATTR_MU_CTRL_DUMP,
283+
284+ /* keep last */
285+ NUM_MTK_VENDOR_ATTRS_MU_CTRL,
286+ MTK_VENDOR_ATTR_MU_CTRL_MAX =
287+ NUM_MTK_VENDOR_ATTRS_MU_CTRL - 1
288+};
289+
290+#endif
291--
2922.39.2
293