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