blob: 38754fa772802163c20ddc40896acdb945dd686c [file] [log] [blame]
developer7e2761e2023-10-12 08:11:13 +08001From 6c7addb48070af33da842ede744264149f2a9110 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
developer7e2761e2023-10-12 08:11:13 +08004Subject: [PATCH 40/98] wifi: mt76: mt7996: add mu vendor command support
developer064da3c2023-06-13 15:57:26 +08005
6Change-Id: I4599bd97917651aaea51d7ff186ffff73a07e4ce
7---
8 mt7996/Makefile | 3 +-
developer7e2761e2023-10-12 08:11:13 +08009 mt7996/init.c | 8 +++++
developerc2cfe0f2023-09-22 04:11:09 +080010 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 +++++++++++++
developer7e2761e2023-10-12 08:11:13 +080015 7 files changed, 167 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
developer7e2761e2023-10-12 08:11:13 +080020index 7bb17f4..6643c7a 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
developer7e2761e2023-10-12 08:11:13 +080038index f393e04..1f4e84d 100644
developer064da3c2023-06-13 15:57:26 +080039--- a/mt7996/init.c
40+++ b/mt7996/init.c
developer7e2761e2023-10-12 08:11:13 +080041@@ -597,6 +597,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)
developer7e2761e2023-10-12 08:11:13 +080052@@ -1230,6 +1234,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
developer064da3c2023-06-13 15:57:26 +080053 dev->mt76.test_ops = &mt7996_testmode_ops;
54 #endif
developer7e2761e2023-10-12 08:11:13 +080055
developer064da3c2023-06-13 15:57:26 +080056+#ifdef CONFIG_MTK_VENDOR
57+ mt7996_vendor_register(&dev->phy);
58+#endif
59+
60 ret = mt76_register_device(&dev->mt76, true, mt76_rates,
61 ARRAY_SIZE(mt76_rates));
62 if (ret)
63diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developer7e2761e2023-10-12 08:11:13 +080064index 6cedc39..a008c08 100644
developer064da3c2023-06-13 15:57:26 +080065--- a/mt7996/mcu.c
66+++ b/mt7996/mcu.c
developer7e2761e2023-10-12 08:11:13 +080067@@ -1266,6 +1266,8 @@ static void
developer064da3c2023-06-13 15:57:26 +080068 mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
69 struct ieee80211_vif *vif, struct ieee80211_sta *sta)
70 {
71+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
72+ struct mt7996_phy *phy = mvif->phy;
73 struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
74 struct sta_rec_muru *muru;
75 struct tlv *tlv;
developer7e2761e2023-10-12 08:11:13 +080076@@ -1277,11 +1279,14 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
developer064da3c2023-06-13 15:57:26 +080077 tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
78
79 muru = (struct sta_rec_muru *)tlv;
80- muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer ||
81- vif->bss_conf.he_mu_beamformer ||
82- vif->bss_conf.vht_mu_beamformer ||
83- vif->bss_conf.vht_mu_beamformee;
84- muru->cfg.ofdma_dl_en = true;
85+ muru->cfg.mimo_dl_en = (vif->bss_conf.eht_mu_beamformer ||
86+ vif->bss_conf.he_mu_beamformer ||
87+ vif->bss_conf.vht_mu_beamformer ||
88+ vif->bss_conf.vht_mu_beamformee) &&
89+ !!(phy->muru_onoff & MUMIMO_DL);
90+ muru->cfg.mimo_ul_en = !!(phy->muru_onoff & MUMIMO_UL);
91+ muru->cfg.ofdma_dl_en = !!(phy->muru_onoff & OFDMA_DL);
92+ muru->cfg.ofdma_ul_en = !!(phy->muru_onoff & OFDMA_UL);
93
94 if (sta->deflink.vht_cap.vht_supported)
95 muru->mimo_dl.vht_mu_bfee =
developer7e2761e2023-10-12 08:11:13 +080096@@ -4469,3 +4474,25 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
developer064da3c2023-06-13 15:57:26 +080097 return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS),
98 &req, sizeof(req), false);
99 }
100+
101+#ifdef CONFIG_MTK_VENDOR
102+void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
103+{
104+ u8 mode, val;
105+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
106+ struct mt7996_phy *phy = mvif->phy;
107+
108+ mode = FIELD_GET(RATE_CFG_MODE, *((u32 *)data));
109+ val = FIELD_GET(RATE_CFG_VAL, *((u32 *)data));
110+
111+ switch (mode) {
112+ case RATE_PARAM_AUTO_MU:
113+ if (val < 0 || val > 15) {
114+ printk("Wrong value! The value is between 0-15.\n");
115+ break;
116+ }
117+ phy->muru_onoff = val;
118+ break;
119+ }
120+}
121+#endif
122diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer7e2761e2023-10-12 08:11:13 +0800123index 71dc165..c5c0a44 100644
developer064da3c2023-06-13 15:57:26 +0800124--- a/mt7996/mcu.h
125+++ b/mt7996/mcu.h
developer7e2761e2023-10-12 08:11:13 +0800126@@ -683,8 +683,20 @@ enum {
developer064da3c2023-06-13 15:57:26 +0800127 RATE_PARAM_FIXED_MCS,
128 RATE_PARAM_FIXED_GI = 11,
129 RATE_PARAM_AUTO = 20,
130+#ifdef CONFIG_MTK_VENDOR
131+ RATE_PARAM_AUTO_MU = 32,
132+#endif
133 };
134
135+#define RATE_CFG_MODE GENMASK(15, 8)
136+#define RATE_CFG_VAL GENMASK(7, 0)
137+
138+/* MURU */
139+#define OFDMA_DL BIT(0)
140+#define OFDMA_UL BIT(1)
141+#define MUMIMO_DL BIT(2)
142+#define MUMIMO_UL BIT(3)
143+
144 enum {
145 BF_SOUNDING_ON = 1,
146 BF_HW_EN_UPDATE = 17,
147diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer7e2761e2023-10-12 08:11:13 +0800148index 23d1614..013122f 100644
developer064da3c2023-06-13 15:57:26 +0800149--- a/mt7996/mt7996.h
150+++ b/mt7996/mt7996.h
developer7e2761e2023-10-12 08:11:13 +0800151@@ -249,6 +249,7 @@ struct mt7996_phy {
developer064da3c2023-06-13 15:57:26 +0800152
developerc2cfe0f2023-09-22 04:11:09 +0800153 struct mt7996_scs_ctrl scs_ctrl;
developer064da3c2023-06-13 15:57:26 +0800154
developerc2cfe0f2023-09-22 04:11:09 +0800155+ u8 muru_onoff;
156 #ifdef CONFIG_NL80211_TESTMODE
157 struct {
158 u32 *reg_backup;
developer7e2761e2023-10-12 08:11:13 +0800159@@ -683,6 +684,11 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
160 bool hif2, int *irq);
161 u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
developer064da3c2023-06-13 15:57:26 +0800162
163+#ifdef CONFIG_MTK_VENDOR
164+void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
165+void mt7996_vendor_register(struct mt7996_phy *phy);
166+#endif
167+
168 #ifdef CONFIG_MTK_DEBUG
169 int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
170 #endif
171diff --git a/mt7996/vendor.c b/mt7996/vendor.c
172new file mode 100644
developer7e2761e2023-10-12 08:11:13 +0800173index 0000000..b5ecbdf
developer064da3c2023-06-13 15:57:26 +0800174--- /dev/null
175+++ b/mt7996/vendor.c
developerc2cfe0f2023-09-22 04:11:09 +0800176@@ -0,0 +1,85 @@
developer064da3c2023-06-13 15:57:26 +0800177+// SPDX-License-Identifier: ISC
178+/*
179+ * Copyright (C) 2020, MediaTek Inc. All rights reserved.
180+ */
181+
182+#include <net/netlink.h>
183+
184+#include "mt7996.h"
185+#include "mcu.h"
186+#include "vendor.h"
developerc2cfe0f2023-09-22 04:11:09 +0800187+#include "mtk_mcu.h"
developer064da3c2023-06-13 15:57:26 +0800188+
189+static const struct nla_policy
190+mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
191+ [MTK_VENDOR_ATTR_MU_CTRL_ONOFF] = {.type = NLA_U8 },
192+ [MTK_VENDOR_ATTR_MU_CTRL_DUMP] = {.type = NLA_U8 },
193+};
194+
195+static int mt7996_vendor_mu_ctrl(struct wiphy *wiphy,
196+ struct wireless_dev *wdev,
197+ const void *data,
198+ int data_len)
199+{
200+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
201+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_MU_CTRL];
202+ int err;
203+ u8 val8;
204+ u32 val32 = 0;
205+
206+ err = nla_parse(tb, MTK_VENDOR_ATTR_MU_CTRL_MAX, data, data_len,
207+ mu_ctrl_policy, NULL);
208+ if (err)
209+ return err;
210+
211+ if (tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]) {
212+ val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_MU_CTRL_ONOFF]);
213+ val32 |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_AUTO_MU) |
214+ FIELD_PREP(RATE_CFG_VAL, val8);
215+ ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
216+ mt7996_set_wireless_vif, &val32);
217+ }
218+
219+ return 0;
220+}
221+
222+static int
223+mt7996_vendor_mu_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
224+ struct sk_buff *skb, const void *data, int data_len,
225+ unsigned long *storage)
226+{
227+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
228+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
229+ int len = 0;
230+
231+ if (*storage == 1)
232+ return -ENOENT;
233+ *storage = 1;
234+
235+ if (nla_put_u8(skb, MTK_VENDOR_ATTR_MU_CTRL_DUMP, phy->muru_onoff))
236+ return -ENOMEM;
237+ len += 1;
238+
239+ return len;
240+}
241+
242+static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
243+ {
244+ .info = {
245+ .vendor_id = MTK_NL80211_VENDOR_ID,
246+ .subcmd = MTK_NL80211_VENDOR_SUBCMD_MU_CTRL,
247+ },
248+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
249+ WIPHY_VENDOR_CMD_NEED_RUNNING,
250+ .doit = mt7996_vendor_mu_ctrl,
251+ .dumpit = mt7996_vendor_mu_ctrl_dump,
252+ .policy = mu_ctrl_policy,
253+ .maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
254+ },
255+};
256+
257+void mt7996_vendor_register(struct mt7996_phy *phy)
258+{
259+ phy->mt76->hw->wiphy->vendor_commands = mt7996_vendor_commands;
260+ phy->mt76->hw->wiphy->n_vendor_commands = ARRAY_SIZE(mt7996_vendor_commands);
261+}
262diff --git a/mt7996/vendor.h b/mt7996/vendor.h
263new file mode 100644
developer7e2761e2023-10-12 08:11:13 +0800264index 0000000..8ac3ba8
developer064da3c2023-06-13 15:57:26 +0800265--- /dev/null
266+++ b/mt7996/vendor.h
267@@ -0,0 +1,22 @@
268+#ifndef __MT7996_VENDOR_H
269+#define __MT7996_VENDOR_H
270+
271+#define MTK_NL80211_VENDOR_ID 0x0ce7
272+
273+enum mtk_nl80211_vendor_subcmds {
274+ MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
275+};
276+
277+enum mtk_vendor_attr_mu_ctrl {
278+ MTK_VENDOR_ATTR_MU_CTRL_UNSPEC,
279+
280+ MTK_VENDOR_ATTR_MU_CTRL_ONOFF,
281+ MTK_VENDOR_ATTR_MU_CTRL_DUMP,
282+
283+ /* keep last */
284+ NUM_MTK_VENDOR_ATTRS_MU_CTRL,
285+ MTK_VENDOR_ATTR_MU_CTRL_MAX =
286+ NUM_MTK_VENDOR_ATTRS_MU_CTRL - 1
287+};
288+
289+#endif
290--
developer7e2761e2023-10-12 08:11:13 +08002912.18.0
developer064da3c2023-06-13 15:57:26 +0800292