blob: fe75034655e714bc124f2ba1897c78dfdd5fb074 [file] [log] [blame]
developer064da3c2023-06-13 15:57:26 +08001From 55619fa44187b6ed841f94c2bedbc4779457e3f9 Mon Sep 17 00:00:00 2001
2From: MeiChia Chiu <meichia.chiu@mediatek.com>
3Date: Tue, 13 Dec 2022 15:17:43 +0800
4Subject: [PATCH 1002/1015] wifi: mt76: mt7996: add mu vendor command support
5
6Change-Id: I4599bd97917651aaea51d7ff186ffff73a07e4ce
7---
8 mt7996/Makefile | 3 +-
9 mt7996/init.c | 8 +++++
10 mt7996/mcu.c | 37 +++++++++++++++++++---
11 mt7996/mcu.h | 12 +++++++
12 mt7996/mt7996.h | 7 +++++
13 mt7996/vendor.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
14 mt7996/vendor.h | 22 +++++++++++++
15 7 files changed, 167 insertions(+), 6 deletions(-)
16 create mode 100644 mt7996/vendor.c
17 create mode 100644 mt7996/vendor.h
18
19diff --git a/mt7996/Makefile b/mt7996/Makefile
20index df131869..8dbbc34c 100644
21--- 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
36
37diff --git a/mt7996/init.c b/mt7996/init.c
38index 96c4bb01..1d4359f0 100644
39--- a/mt7996/init.c
40+++ b/mt7996/init.c
41@@ -579,6 +579,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
42 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)
52@@ -1082,6 +1086,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
53 dev->mt76.test_ops = &mt7996_testmode_ops;
54 #endif
55
56+#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
64index 58893348..91f3103a 100644
65--- a/mt7996/mcu.c
66+++ b/mt7996/mcu.c
67@@ -1158,6 +1158,8 @@ static void
68 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;
76@@ -1169,11 +1171,14 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
77 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 =
96@@ -4353,3 +4358,25 @@ int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable)
97 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
123index 5d52b0b7..baffbcd7 100644
124--- a/mt7996/mcu.h
125+++ b/mt7996/mcu.h
126@@ -568,8 +568,20 @@ enum {
127 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
148index 085307ab..b9f3dd8e 100644
149--- a/mt7996/mt7996.h
150+++ b/mt7996/mt7996.h
151@@ -263,6 +263,8 @@ struct mt7996_phy {
152 u32 rx_ampdu_ts;
153 u32 ampdu_ref;
154
155+ u8 muru_onoff;
156+
157 struct mib_stats mib;
158 struct mt76_channel_state state_ts;
159
160@@ -672,6 +674,11 @@ void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
161 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
174index 00000000..08ecc2b3
175--- /dev/null
176+++ b/mt7996/vendor.c
177@@ -0,0 +1,84 @@
178+// 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"
188+
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
264index 00000000..8ac3ba8e
265--- /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--
2912.39.2
292