blob: 06fc5e8b606997fd8a71e1b1bd41731c48785f4c [file] [log] [blame]
developer7e2761e2023-10-12 08:11:13 +08001From 140f810c788ffccc605fa979635c9be2db4b9748 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
developer7e2761e2023-10-12 08:11:13 +08004Subject: [PATCH 52/98] wifi: mt76: mt7996: add vendor subcmd EDCCA ctrl enable
developerc2cfe0f2023-09-22 04:11:09 +08005
6---
7 mt7996/main.c | 3 ++
8 mt7996/mcu.h | 2 +
9 mt7996/mt7996.h | 11 ++++
10 mt7996/mtk_mcu.c | 86 ++++++++++++++++++++++++++++++
11 mt7996/mtk_mcu.h | 15 ++++++
12 mt7996/vendor.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++
13 mt7996/vendor.h | 33 ++++++++++++
14 7 files changed, 282 insertions(+)
15
16diff --git a/mt7996/main.c b/mt7996/main.c
developer7e2761e2023-10-12 08:11:13 +080017index 9e3e4ed..d928564 100644
developerc2cfe0f2023-09-22 04:11:09 +080018--- a/mt7996/main.c
19+++ b/mt7996/main.c
20@@ -431,6 +431,9 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
21 int ret;
22
23 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
24+ ret = mt7996_mcu_edcca_enable(phy, true);
25+ if (ret)
26+ return ret;
27 ieee80211_stop_queues(hw);
28 ret = mt7996_set_channel(phy);
29 if (ret)
30diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer7e2761e2023-10-12 08:11:13 +080031index 989a2ff..bb876f3 100644
developerc2cfe0f2023-09-22 04:11:09 +080032--- a/mt7996/mcu.h
33+++ b/mt7996/mcu.h
developer7e2761e2023-10-12 08:11:13 +080034@@ -791,6 +791,8 @@ mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
developerc2cfe0f2023-09-22 04:11:09 +080035
36 enum {
37 UNI_BAND_CONFIG_RADIO_ENABLE,
38+ UNI_BAND_CONFIG_EDCCA_ENABLE = 0x05,
39+ UNI_BAND_CONFIG_EDCCA_THRESHOLD = 0x06,
40 UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
41 };
42
43diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer7e2761e2023-10-12 08:11:13 +080044index 9b110cf..8fd29d7 100644
developerc2cfe0f2023-09-22 04:11:09 +080045--- a/mt7996/mt7996.h
46+++ b/mt7996/mt7996.h
developer7e2761e2023-10-12 08:11:13 +080047@@ -750,6 +750,17 @@ int mt7996_vendor_amnt_sta_remove(struct mt7996_phy *phy,
developerc2cfe0f2023-09-22 04:11:09 +080048 struct ieee80211_sta *sta);
49 #endif
50
51+int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable);
52+int mt7996_mcu_edcca_threshold_ctrl(struct mt7996_phy *phy, u8 *value, bool set);
53+
54+enum edcca_bw_id {
55+ EDCCA_BW_20 = 0,
56+ EDCCA_BW_40,
57+ EDCCA_BW_80,
58+ EDCCA_BW_160,
59+ EDCCA_MAX_BW_NUM,
60+};
61+
62 #ifdef CONFIG_MTK_DEBUG
63 int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
64 #endif
65diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
developer7e2761e2023-10-12 08:11:13 +080066index f772243..048c534 100644
developerc2cfe0f2023-09-22 04:11:09 +080067--- a/mt7996/mtk_mcu.c
68+++ b/mt7996/mtk_mcu.c
69@@ -38,4 +38,90 @@ int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *even
70 return 0;
71 }
72
73+int mt7996_mcu_edcca_enable(struct mt7996_phy *phy, bool enable)
74+{
75+ struct mt7996_dev *dev = phy->dev;
76+ struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
77+ enum nl80211_band band = chandef->chan->band;
78+ struct {
79+ u8 band_idx;
80+ u8 _rsv[3];
81+
82+ __le16 tag;
83+ __le16 len;
84+ u8 enable;
85+ u8 std;
86+ u8 _rsv2[2];
87+ } __packed req = {
88+ .band_idx = phy->mt76->band_idx,
89+ .tag = cpu_to_le16(UNI_BAND_CONFIG_EDCCA_ENABLE),
90+ .len = cpu_to_le16(sizeof(req) - 4),
91+ .enable = enable,
92+ .std = EDCCA_DEFAULT,
93+ };
94+
95+ switch (dev->mt76.region) {
96+ case NL80211_DFS_JP:
97+ req.std = EDCCA_JAPAN;
98+ break;
99+ case NL80211_DFS_FCC:
100+ if (band == NL80211_BAND_6GHZ)
101+ req.std = EDCCA_FCC;
102+ break;
103+ case NL80211_DFS_ETSI:
104+ if (band == NL80211_BAND_6GHZ)
105+ req.std = EDCCA_ETSI;
106+ break;
107+ default:
108+ break;
109+ }
110+
111+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
112+ &req, sizeof(req), true);
113+}
114+
115+int mt7996_mcu_edcca_threshold_ctrl(struct mt7996_phy *phy, u8 *value, bool set)
116+{
117+ struct {
118+ u8 band_idx;
119+ u8 _rsv[3];
120+
121+ __le16 tag;
122+ __le16 len;
123+ u8 threshold[4];
124+ bool init;
125+ } __packed *res, req = {
126+ .band_idx = phy->mt76->band_idx,
127+ .tag = cpu_to_le16(UNI_BAND_CONFIG_EDCCA_THRESHOLD),
128+ .len = cpu_to_le16(sizeof(req) - 4),
129+ .init = false,
130+ };
131+ struct sk_buff *skb;
132+ int ret;
133+ int i;
134+
135+ for (i = 0; i < EDCCA_MAX_BW_NUM; i++)
136+ req.threshold[i] = value[i];
137+
138+ if (set)
139+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(BAND_CONFIG),
140+ &req, sizeof(req), true);
141+
142+ ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76,
143+ MCU_WM_UNI_CMD_QUERY(BAND_CONFIG),
144+ &req, sizeof(req), true, &skb);
145+
146+ if (ret)
147+ return ret;
148+
149+ res = (void *)skb->data;
150+
151+ for (i = 0; i < EDCCA_MAX_BW_NUM; i++)
152+ value[i] = res->threshold[i];
153+
154+ dev_kfree_skb(skb);
155+
156+ return 0;
157+}
158+
159 #endif
160diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
developer7e2761e2023-10-12 08:11:13 +0800161index beb1aba..9c0db87 100644
developerc2cfe0f2023-09-22 04:11:09 +0800162--- a/mt7996/mtk_mcu.h
163+++ b/mt7996/mtk_mcu.h
164@@ -89,6 +89,21 @@ enum txpower_event {
165 UNI_TXPOWER_PHY_RATE_INFO = 5,
166 };
167
168+enum {
169+ EDCCA_CTRL_SET_EN = 0,
170+ EDCCA_CTRL_SET_THRES,
171+ EDCCA_CTRL_GET_EN,
172+ EDCCA_CTRL_GET_THRES,
173+ EDCCA_CTRL_NUM,
174+};
175+
176+enum {
177+ EDCCA_DEFAULT = 0,
178+ EDCCA_FCC = 1,
179+ EDCCA_ETSI = 2,
180+ EDCCA_JAPAN = 3
181+};
182+
183 #endif
184
185 #endif
186diff --git a/mt7996/vendor.c b/mt7996/vendor.c
developer7e2761e2023-10-12 08:11:13 +0800187index 3910157..9f333d0 100644
developerc2cfe0f2023-09-22 04:11:09 +0800188--- a/mt7996/vendor.c
189+++ b/mt7996/vendor.c
190@@ -40,6 +40,26 @@ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL] = {
191 [MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
192 };
193
194+static const struct nla_policy
195+edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
196+ [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
197+ [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
198+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL] = { .type = NLA_U8 },
199+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] = { .type = NLA_U8 },
200+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] = { .type = NLA_U8 },
201+ [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_S8 },
202+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL] = { .type = NLA_U8 },
203+};
204+
205+static const struct nla_policy
206+edcca_dump_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP] = {
207+ [MTK_VENDOR_ATTR_EDCCA_DUMP_MODE] = { .type = NLA_U8 },
208+ [MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL] = { .type = NLA_U8 },
209+ [MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL] = { .type = NLA_U8 },
210+ [MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL] = { .type = NLA_U8 },
211+ [MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL] = { .type = NLA_U8 },
212+};
213+
214 struct mt7996_amnt_data {
215 u8 idx;
216 u8 addr[ETH_ALEN];
217@@ -436,6 +456,106 @@ mt7996_vendor_bss_color_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev
218 return len;
219 }
220
221+static int mt7996_vendor_edcca_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
222+ const void *data, int data_len)
223+{
224+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
225+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
226+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL];
227+ int err;
228+ u8 edcca_mode;
229+ u8 edcca_value[EDCCA_MAX_BW_NUM];
230+
231+ err = nla_parse(tb, MTK_VENDOR_ATTR_EDCCA_CTRL_MAX, data, data_len,
232+ edcca_ctrl_policy, NULL);
233+ if (err)
234+ return err;
235+
236+ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE])
237+ return -EINVAL;
238+
239+ edcca_mode = nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE]);
240+ if (edcca_mode == EDCCA_CTRL_SET_EN) {
241+ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL])
242+ return -EINVAL;
243+
244+ edcca_value[0] =
245+ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL]);
246+
247+ err = mt7996_mcu_edcca_enable(phy, !!edcca_value[0]);
248+ if (err)
249+ return err;
250+ } else if (edcca_mode == EDCCA_CTRL_SET_THRES) {
251+ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] ||
252+ !tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] ||
253+ !tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] ||
254+ !tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL]) {
255+ return -EINVAL;
256+ }
257+ edcca_value[EDCCA_BW_20] =
258+ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL]);
259+ edcca_value[EDCCA_BW_40] =
260+ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL]);
261+ edcca_value[EDCCA_BW_80] =
262+ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL]);
263+ edcca_value[EDCCA_BW_160] =
264+ nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL]);
265+
266+ err = mt7996_mcu_edcca_threshold_ctrl(phy, edcca_value, true);
267+
268+ if (err)
269+ return err;
270+ } else {
271+ return -EINVAL;
272+ }
273+
274+ return 0;
275+}
276+
277+
278+static int
279+mt7996_vendor_edcca_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
280+ struct sk_buff *skb, const void *data, int data_len,
281+ unsigned long *storage)
282+{
283+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
284+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
285+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL];
286+ int err;
287+ u8 edcca_mode;
288+ u8 value[EDCCA_MAX_BW_NUM];
289+
290+ if (*storage == 1)
291+ return -ENOENT;
292+ *storage = 1;
293+
294+ err = nla_parse(tb, MTK_VENDOR_ATTR_EDCCA_CTRL_MAX, data, data_len,
295+ edcca_ctrl_policy, NULL);
296+ if (err)
297+ return err;
298+
299+ if (!tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE])
300+ return -EINVAL;
301+
302+ edcca_mode = nla_get_u8(tb[MTK_VENDOR_ATTR_EDCCA_CTRL_MODE]);
303+
304+ if (edcca_mode != EDCCA_CTRL_GET_THRES)
305+ return -EINVAL;
306+
307+ err = mt7996_mcu_edcca_threshold_ctrl(phy, value, false);
308+
309+ if (err)
310+ return err;
311+
312+ if (nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL, value[EDCCA_BW_20]) ||
313+ nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL, value[EDCCA_BW_40]) ||
314+ nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL, value[EDCCA_BW_80]) ||
315+ nla_put_u8(skb, MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL, value[EDCCA_BW_160]))
316+ return -ENOMEM;
317+
318+ return EDCCA_MAX_BW_NUM;
319+}
320+
321 static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
322 {
323 .info = {
324@@ -472,6 +592,18 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
325 .policy = bss_color_ctrl_policy,
326 .maxattr = MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
327 },
328+ {
329+ .info = {
330+ .vendor_id = MTK_NL80211_VENDOR_ID,
331+ .subcmd = MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL,
332+ },
333+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
334+ WIPHY_VENDOR_CMD_NEED_RUNNING,
335+ .doit = mt7996_vendor_edcca_ctrl,
336+ .dumpit = mt7996_vendor_edcca_ctrl_dump,
337+ .policy = edcca_ctrl_policy,
338+ .maxattr = MTK_VENDOR_ATTR_EDCCA_CTRL_MAX,
339+ },
340 };
341
342 void mt7996_vendor_register(struct mt7996_phy *phy)
343diff --git a/mt7996/vendor.h b/mt7996/vendor.h
developer7e2761e2023-10-12 08:11:13 +0800344index eec9e74..4465bc9 100644
developerc2cfe0f2023-09-22 04:11:09 +0800345--- a/mt7996/vendor.h
346+++ b/mt7996/vendor.h
347@@ -6,9 +6,42 @@
348 enum mtk_nl80211_vendor_subcmds {
349 MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae,
350 MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
351+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
352 MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
353 };
354
355+enum mtk_vendor_attr_edcca_ctrl {
356+ MTK_VENDOR_ATTR_EDCCA_THRESHOLD_INVALID = 0,
357+
358+ MTK_VENDOR_ATTR_EDCCA_CTRL_MODE,
359+ MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL,
360+ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL,
361+ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL,
362+ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL,
363+ MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE,
364+ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL,
365+
366+ /* keep last */
367+ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL,
368+ MTK_VENDOR_ATTR_EDCCA_CTRL_MAX =
369+ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL - 1
370+};
371+
372+enum mtk_vendor_attr_edcca_dump {
373+ MTK_VENDOR_ATTR_EDCCA_DUMP_UNSPEC = 0,
374+
375+ MTK_VENDOR_ATTR_EDCCA_DUMP_MODE,
376+ MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL,
377+ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL,
378+ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL,
379+ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL,
380+
381+ /* keep last */
382+ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP,
383+ MTK_VENDOR_ATTR_EDCCA_DUMP_MAX =
384+ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP - 1
385+};
386+
387 enum mtk_vendor_attr_mu_ctrl {
388 MTK_VENDOR_ATTR_MU_CTRL_UNSPEC,
389
390--
developer7e2761e2023-10-12 08:11:13 +08003912.18.0
developerc2cfe0f2023-09-22 04:11:09 +0800392