blob: fb38f6a9ca39529dcd78cc8d4683f46f4b326627 [file] [log] [blame]
developer14ab3112024-03-21 07:21:44 +08001From 2caf106ced738d65640e21d284e3fee9cb04c611 Mon Sep 17 00:00:00 2001
developerc2cfe0f2023-09-22 04:11:09 +08002From: mtk27745 <rex.lu@mediatek.com>
3Date: Thu, 8 Jun 2023 20:21:04 +0800
developer07b5baf2024-01-10 04:38:47 +08004Subject: [PATCH 1019/1044] mtk: wifi: mt76: mt7996: add vendor subcmd EDCCA
developer5f4e6c32023-12-20 06:12:53 +08005 ctrl enable
developerc2cfe0f2023-09-22 04:11:09 +08006
7---
developerc2cfe0f2023-09-22 04:11:09 +08008 mt7996/mcu.h | 2 +
9 mt7996/mt7996.h | 11 ++++
developer5f4e6c32023-12-20 06:12:53 +080010 mt7996/mtk_mcu.c | 87 +++++++++++++++++++++++++++++++
developerc2cfe0f2023-09-22 04:11:09 +080011 mt7996/mtk_mcu.h | 15 ++++++
12 mt7996/vendor.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++
13 mt7996/vendor.h | 33 ++++++++++++
developer5f4e6c32023-12-20 06:12:53 +080014 6 files changed, 280 insertions(+)
developerc2cfe0f2023-09-22 04:11:09 +080015
developerc2cfe0f2023-09-22 04:11:09 +080016diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer5f4e6c32023-12-20 06:12:53 +080017index 35f757dc..34fdfb26 100644
developerc2cfe0f2023-09-22 04:11:09 +080018--- a/mt7996/mcu.h
19+++ b/mt7996/mcu.h
developer5f4e6c32023-12-20 06:12:53 +080020@@ -845,6 +845,8 @@ mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
developerc2cfe0f2023-09-22 04:11:09 +080021
22 enum {
23 UNI_BAND_CONFIG_RADIO_ENABLE,
24+ UNI_BAND_CONFIG_EDCCA_ENABLE = 0x05,
25+ UNI_BAND_CONFIG_EDCCA_THRESHOLD = 0x06,
26 UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
27 };
28
29diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer07b5baf2024-01-10 04:38:47 +080030index 7ca9d57e..cfa50bfe 100644
developerc2cfe0f2023-09-22 04:11:09 +080031--- a/mt7996/mt7996.h
32+++ b/mt7996/mt7996.h
developer07b5baf2024-01-10 04:38:47 +080033@@ -786,6 +786,17 @@ int mt7996_vendor_amnt_sta_remove(struct mt7996_phy *phy,
developerc2cfe0f2023-09-22 04:11:09 +080034 struct ieee80211_sta *sta);
35 #endif
36
37+int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable);
38+int mt7996_mcu_edcca_threshold_ctrl(struct mt7996_phy *phy, u8 *value, bool set);
39+
40+enum edcca_bw_id {
41+ EDCCA_BW_20 = 0,
42+ EDCCA_BW_40,
43+ EDCCA_BW_80,
44+ EDCCA_BW_160,
45+ EDCCA_MAX_BW_NUM,
46+};
47+
48 #ifdef CONFIG_MTK_DEBUG
49 int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
developer5f4e6c32023-12-20 06:12:53 +080050 int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val);
developerc2cfe0f2023-09-22 04:11:09 +080051diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
developer5f4e6c32023-12-20 06:12:53 +080052index e56ddd8f..5c54d02c 100644
developerc2cfe0f2023-09-22 04:11:09 +080053--- a/mt7996/mtk_mcu.c
54+++ b/mt7996/mtk_mcu.c
developer5f4e6c32023-12-20 06:12:53 +080055@@ -59,4 +59,91 @@ int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val)
56 return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &req,
57 sizeof(req), true);
developerc2cfe0f2023-09-22 04:11:09 +080058 }
developer5f4e6c32023-12-20 06:12:53 +080059+
developerc2cfe0f2023-09-22 04:11:09 +080060+int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable)
61+{
62+ struct mt7996_dev *dev = phy->dev;
63+ struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
64+ enum nl80211_band band = chandef->chan->band;
65+ struct {
66+ u8 band_idx;
67+ u8 _rsv[3];
68+
69+ __le16 tag;
70+ __le16 len;
71+ u8 enable;
72+ u8 std;
73+ u8 _rsv2[2];
74+ } __packed req = {
75+ .band_idx = phy->mt76->band_idx,
76+ .tag = cpu_to_le16(UNI_BAND_CONFIG_EDCCA_ENABLE),
77+ .len = cpu_to_le16(sizeof(req) - 4),
78+ .enable = enable,
79+ .std = EDCCA_DEFAULT,
80+ };
81+
82+ switch (dev->mt76.region) {
83+ case NL80211_DFS_JP:
84+ req.std = EDCCA_JAPAN;
85+ break;
86+ case NL80211_DFS_FCC:
87+ if (band == NL80211_BAND_6GHZ)
88+ req.std = EDCCA_FCC;
89+ break;
90+ case NL80211_DFS_ETSI:
91+ if (band == NL80211_BAND_6GHZ)
92+ req.std = EDCCA_ETSI;
93+ break;
94+ default:
95+ break;
96+ }
97+
98+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
99+ &req, sizeof(req), true);
100+}
101+
102+int mt7996_mcu_edcca_threshold_ctrl(struct mt7996_phy *phy, u8 *value, bool set)
103+{
104+ struct {
105+ u8 band_idx;
106+ u8 _rsv[3];
107+
108+ __le16 tag;
109+ __le16 len;
110+ u8 threshold[4];
111+ bool init;
112+ } __packed *res, req = {
113+ .band_idx = phy->mt76->band_idx,
114+ .tag = cpu_to_le16(UNI_BAND_CONFIG_EDCCA_THRESHOLD),
115+ .len = cpu_to_le16(sizeof(req) - 4),
116+ .init = false,
117+ };
118+ struct sk_buff *skb;
119+ int ret;
120+ int i;
121+
122+ for (i = 0; i < EDCCA_MAX_BW_NUM; i++)
123+ req.threshold[i] = value[i];
124+
125+ if (set)
126+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
127+ &req, sizeof(req), true);
128+
129+ ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76,
130+ MCU_WM_UNI_CMD_QUERY(BAND_CONFIG),
131+ &req, sizeof(req), true, &skb);
132+
133+ if (ret)
134+ return ret;
135+
136+ res = (void *)skb->data;
137+
138+ for (i = 0; i < EDCCA_MAX_BW_NUM; i++)
139+ value[i] = res->threshold[i];
140+
141+ dev_kfree_skb(skb);
142+
143+ return 0;
144+}
145+
146 #endif
147diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
developer07b5baf2024-01-10 04:38:47 +0800148index c30418ca..36a58ad6 100644
developerc2cfe0f2023-09-22 04:11:09 +0800149--- a/mt7996/mtk_mcu.h
150+++ b/mt7996/mtk_mcu.h
developer07b5baf2024-01-10 04:38:47 +0800151@@ -106,6 +106,21 @@ enum txpower_event {
developerc2cfe0f2023-09-22 04:11:09 +0800152 UNI_TXPOWER_PHY_RATE_INFO = 5,
153 };
154
155+enum {
156+ EDCCA_CTRL_SET_EN = 0,
157+ EDCCA_CTRL_SET_THRES,
158+ EDCCA_CTRL_GET_EN,
159+ EDCCA_CTRL_GET_THRES,
160+ EDCCA_CTRL_NUM,
161+};
162+
163+enum {
164+ EDCCA_DEFAULT = 0,
165+ EDCCA_FCC = 1,
166+ EDCCA_ETSI = 2,
167+ EDCCA_JAPAN = 3
168+};
169+
170 #endif
171
172 #endif
173diff --git a/mt7996/vendor.c b/mt7996/vendor.c
developer5f4e6c32023-12-20 06:12:53 +0800174index 39101577..9f333d0e 100644
developerc2cfe0f2023-09-22 04:11:09 +0800175--- a/mt7996/vendor.c
176+++ b/mt7996/vendor.c
177@@ -40,6 +40,26 @@ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL] = {
178 [MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
179 };
180
181+static const struct nla_policy
182+edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
183+ [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
184+ [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
185+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL] = { .type = NLA_U8 },
186+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] = { .type = NLA_U8 },
187+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] = { .type = NLA_U8 },
188+ [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_S8 },
189+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL] = { .type = NLA_U8 },
190+};
191+
192+static const struct nla_policy
193+edcca_dump_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP] = {
194+ [MTK_VENDOR_ATTR_EDCCA_DUMP_MODE] = { .type = NLA_U8 },
195+ [MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL] = { .type = NLA_U8 },
196+ [MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL] = { .type = NLA_U8 },
197+ [MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL] = { .type = NLA_U8 },
198+ [MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL] = { .type = NLA_U8 },
199+};
200+
201 struct mt7996_amnt_data {
202 u8 idx;
203 u8 addr[ETH_ALEN];
204@@ -436,6 +456,106 @@ mt7996_vendor_bss_color_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev
205 return len;
206 }
207
208+static int mt7996_vendor_edcca_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
209+ const void *data, int data_len)
210+{
211+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
212+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
213+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL];
214+ int err;
215+ u8 edcca_mode;
216+ u8 edcca_value[EDCCA_MAX_BW_NUM];
217+
218+ err = nla_parse(tb, MTK_VENDOR_ATTR_EDCCA_CTRL_MAX, data, data_len,
219+ edcca_ctrl_policy, NULL);
220+ if (err)
221+ return err;
222+
223+ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE])
224+ return -EINVAL;
225+
226+ edcca_mode = nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE]);
227+ if (edcca_mode == EDCCA_CTRL_SET_EN) {
228+ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL])
229+ return -EINVAL;
230+
231+ edcca_value[0] =
232+ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL]);
233+
234+ err = mt7996_mcu_edcca_enable(phy, !!edcca_value[0]);
235+ if (err)
236+ return err;
237+ } else if (edcca_mode == EDCCA_CTRL_SET_THRES) {
238+ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] ||
239+ !tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] ||
240+ !tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] ||
241+ !tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL]) {
242+ return -EINVAL;
243+ }
244+ edcca_value[EDCCA_BW_20] =
245+ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL]);
246+ edcca_value[EDCCA_BW_40] =
247+ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL]);
248+ edcca_value[EDCCA_BW_80] =
249+ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL]);
250+ edcca_value[EDCCA_BW_160] =
251+ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL]);
252+
253+ err = mt7996_mcu_edcca_threshold_ctrl(phy, edcca_value, true);
254+
255+ if (err)
256+ return err;
257+ } else {
258+ return -EINVAL;
259+ }
260+
261+ return 0;
262+}
263+
264+
265+static int
266+mt7996_vendor_edcca_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
267+ struct sk_buff *skb, const void *data, int data_len,
268+ unsigned long *storage)
269+{
270+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
271+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
272+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL];
273+ int err;
274+ u8 edcca_mode;
275+ u8 value[EDCCA_MAX_BW_NUM];
276+
277+ if (*storage == 1)
278+ return -ENOENT;
279+ *storage = 1;
280+
281+ err = nla_parse(tb, MTK_VENDOR_ATTR_EDCCA_CTRL_MAX, data, data_len,
282+ edcca_ctrl_policy, NULL);
283+ if (err)
284+ return err;
285+
286+ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE])
287+ return -EINVAL;
288+
289+ edcca_mode = nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE]);
290+
291+ if (edcca_mode != EDCCA_CTRL_GET_THRES)
292+ return -EINVAL;
293+
294+ err = mt7996_mcu_edcca_threshold_ctrl(phy, value, false);
295+
296+ if (err)
297+ return err;
298+
299+ if (nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL, value[EDCCA_BW_20]) ||
300+ nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL, value[EDCCA_BW_40]) ||
301+ nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL, value[EDCCA_BW_80]) ||
302+ nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL, value[EDCCA_BW_160]))
303+ return -ENOMEM;
304+
305+ return EDCCA_MAX_BW_NUM;
306+}
307+
308 static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
309 {
310 .info = {
311@@ -472,6 +592,18 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
312 .policy = bss_color_ctrl_policy,
313 .maxattr = MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
314 },
315+ {
316+ .info = {
317+ .vendor_id = MTK_NL80211_VENDOR_ID,
318+ .subcmd = MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL,
319+ },
320+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
321+ WIPHY_VENDOR_CMD_NEED_RUNNING,
322+ .doit = mt7996_vendor_edcca_ctrl,
323+ .dumpit = mt7996_vendor_edcca_ctrl_dump,
324+ .policy = edcca_ctrl_policy,
325+ .maxattr = MTK_VENDOR_ATTR_EDCCA_CTRL_MAX,
326+ },
327 };
328
329 void mt7996_vendor_register(struct mt7996_phy *phy)
330diff --git a/mt7996/vendor.h b/mt7996/vendor.h
developer5f4e6c32023-12-20 06:12:53 +0800331index eec9e74a..4465bc9d 100644
developerc2cfe0f2023-09-22 04:11:09 +0800332--- a/mt7996/vendor.h
333+++ b/mt7996/vendor.h
334@@ -6,9 +6,42 @@
335 enum mtk_nl80211_vendor_subcmds {
336 MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae,
337 MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
338+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
339 MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
340 };
341
342+enum mtk_vendor_attr_edcca_ctrl {
343+ MTK_VENDOR_ATTR_EDCCA_THRESHOLD_INVALID = 0,
344+
345+ MTK_VENDOR_ATTR_EDCCA_CTRL_MODE,
346+ MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL,
347+ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL,
348+ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL,
349+ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL,
350+ MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE,
351+ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL,
352+
353+ /* keep last */
354+ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL,
355+ MTK_VENDOR_ATTR_EDCCA_CTRL_MAX =
356+ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL - 1
357+};
358+
359+enum mtk_vendor_attr_edcca_dump {
360+ MTK_VENDOR_ATTR_EDCCA_DUMP_UNSPEC = 0,
361+
362+ MTK_VENDOR_ATTR_EDCCA_DUMP_MODE,
363+ MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL,
364+ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL,
365+ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL,
366+ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL,
367+
368+ /* keep last */
369+ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP,
370+ MTK_VENDOR_ATTR_EDCCA_DUMP_MAX =
371+ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP - 1
372+};
373+
374 enum mtk_vendor_attr_mu_ctrl {
375 MTK_VENDOR_ATTR_MU_CTRL_UNSPEC,
376
377--
developer7e2761e2023-10-12 08:11:13 +08003782.18.0
developerc2cfe0f2023-09-22 04:11:09 +0800379