blob: 757c28bc063a8c0799b877baf1ee3e5a192893a9 [file] [log] [blame]
developer66e89bc2024-04-23 14:50:01 +08001From e64468ed944634f41f7f305e7460b6a696b00127 Mon Sep 17 00:00:00 2001
2From: Howard Hsu <howard-yh.hsu@mediatek.com>
3Date: Sat, 3 Jun 2023 17:12:15 +0800
4Subject: [PATCH 052/104] mtk: hostapd: add connac3 PHY MURU manual mode config
5 support
6
7This commit supports read the following two formats to set MU/RU manual
8mode:
91. hostapd_cli -i <intf> raw set_muru_manual_config=<field>:<value>
102. hostapd_cli -i <intf> set_mu <field> <value>
11
12For the <field>, we support the following field:
131. ul_comm_user_cnt/dl_comm_user_cnt: set the number of user
142. ul_comm_bw/dl_comm_bw: set the bandwith
153. ul_user_ru_alloc/dl_user_ru_alloc: set the RU band idx and RU
16allocate idx
174. ul_user_mcs/dl_user_mcs: set the mcs for each user
185. ul_user_ssAlloc_raru: set the number of ss for each user
196. ul_comm_gi_ltf: set the combinations of gi and ltf for UL only.
207. dl_comm_toneplan: fix ru toneplan allocation
218. dl_comm_ack_policy: fix station ack policy
229. update : trigger driver to send mcu command to set muru manual mode.
23
24For the value of each field, please check wiki to learn the details:
25https://wiki.mediatek.inc/display/GWKB/muru_mancfg_user_guide
26
27For the fields that mt76 support to use, we will update in this wiki:
28https://wiki.mediatek.inc/pages/viewpage.action?pageId=1271741116
29
30Please noted that this commit is only for connac 3 gen chips. If this
31feature is to be used in other generations, the following actions must
32be taken:
331. Different data structue needs to be defined for different
34generations, e.g. connac4_muru_comm, connac4_muru_dl.
352. hostapd_ctrl_iface_set_mu() shall be modified.
363. A new code level configuration shall be defined to differentiate the
37code flow that different generations will go through.
38---
39 hostapd/ctrl_iface.c | 237 +++++++++++++++++++++++++++++++----
40 src/ap/ap_config.h | 1 +
41 src/ap/ap_drv_ops.c | 4 +-
42 src/ap/ap_drv_ops.h | 2 +-
43 src/ap/hostapd.c | 2 +-
44 src/common/mtk_vendor.h | 166 +++++++++++++++++++++++-
45 src/drivers/driver.h | 2 +-
46 src/drivers/driver_nl80211.c | 21 ++--
47 8 files changed, 391 insertions(+), 44 deletions(-)
48
49diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
50index 88475b321..ed383df7d 100644
51--- a/hostapd/ctrl_iface.c
52+++ b/hostapd/ctrl_iface.c
53@@ -3775,7 +3775,6 @@ hostapd_ctrl_iface_get_edcca(struct hostapd_data *hapd, char *cmd, char *buf,
54 }
55 }
56
57-
58 #ifdef CONFIG_NAN_USD
59
60 static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
61@@ -4062,21 +4061,61 @@ fail:
62 #endif /* CONFIG_NAN_USD */
63
64
65+static int
66+hostapd_parse_argument_helper(char *value, u16 **ptr_input)
67+{
68+#define MAX_MU_CTRL_NUM 17
69+ u16 *input;
70+ char *endptr;
71+ int cnt = 0;
72+
73+ input = os_zalloc(MAX_MU_CTRL_NUM * sizeof(u16));
74+ if (input == NULL) {
75+ wpa_printf(MSG_ERROR, "Failed to allocate memory.\n");
76+ return -1;
77+ }
78+ while (value) {
79+ u8 val = strtol(value, &endptr, 10);
80+
81+ if (value != endptr) {
82+ input[cnt++] = val;
83+ value = os_strchr(endptr, ':');
84+ if (value)
85+ value++;
86+ } else {
87+ break;
88+ }
89+ }
90+
91+ *ptr_input = input;
92+ return cnt;
93+}
94+
95+#define MURU_CFG_DEPENDENCE_CHECK(_val, _mask) do { \
96+ if ((le_to_host32(_val) & (_mask)) != _mask) { \
97+ wpa_printf(MSG_ERROR, "Set %s first\n", #_mask); \
98+ goto fail; \
99+ } \
100+ } while(0)
101+
102 static int
103 hostapd_ctrl_iface_set_mu(struct hostapd_data *hapd, char *cmd,
104- char *buf, size_t buflen)
105+ char *buf, size_t buflen)
106 {
107 char *pos, *config, *value;
108- u8 mode;
109+ u8 i;
110+ int cnt = 0, ret;
111+ u16 *val;
112+ struct connac3_muru *muru;
113+ struct connac3_muru_dl *dl;
114+ struct connac3_muru_ul *ul;
115+ struct connac3_muru_comm *comm;
116
117 config = cmd;
118 pos = os_strchr(config, ' ');
119- if (pos == NULL)
120- return -1;
121- *pos++ = '\0';
122+ if (pos != NULL)
123+ *pos++ = '\0';
124
125- if(pos == NULL)
126- return -1;
127 value = pos;
128
129 if (os_strcmp(config, "onoff") == 0) {
130@@ -4086,24 +4125,167 @@ hostapd_ctrl_iface_set_mu(struct hostapd_data *hapd, char *cmd,
131 return -1;
132 }
133 hapd->iconf->mu_onoff = (u8) mu;
134- mode = MU_CTRL_ONOFF;
135- } else if (os_strcmp(config, "ul_user_cnt") == 0) {
136- mode = MU_CTRL_UL_USER_CNT;
137- wpa_printf(MSG_ERROR, "ul_user_cnt:%d\n", (u8)atoi(value));
138- } else if (os_strcmp(config, "dl_user_cnt") == 0) {
139- mode = MU_CTRL_DL_USER_CNT;
140- wpa_printf(MSG_ERROR, "dl_user_cnt:%d\n", (u8)atoi(value));
141- } else {
142- wpa_printf(MSG_ERROR,
143- "Unsupported parameter %s for SET_MU", config);
144- return -1;
145+
146+ if (hostapd_drv_mu_ctrl(hapd, MU_CTRL_ONOFF) == 0)
147+ return os_snprintf(buf, buflen, "OK\n");
148+ else
149+ goto fail;
150 }
151
152- if(hostapd_drv_mu_ctrl(hapd, mode, (u8)atoi(value)) == 0) {
153- return os_snprintf(buf, buflen, "OK\n");
154+ if (hapd->iconf->muru_config == NULL)
155+ hapd->iconf->muru_config = os_zalloc(sizeof(struct connac3_muru));
156+
157+ muru = hapd->iconf->muru_config;
158+ dl = &muru->dl;
159+ ul = &muru->ul;
160+ comm = &muru->comm;
161+
162+ if (os_strncmp(config, "update", 6) == 0) {
163+ ret = hostapd_drv_mu_ctrl(hapd, MU_CTRL_UPDATE);
164+
165+ os_free(hapd->iconf->muru_config);
166+ hapd->iconf->muru_config = NULL;
167+
168+ if (ret)
169+ goto fail;
170+ } else if (os_strcmp(config, "ul_comm_user_cnt") == 0) {
171+ ul->user_num = (u8)atoi(value);
172+ comm->ppdu_format |= MURU_PPDU_HE_TRIG;
173+ comm->sch_type |= MURU_OFDMA_SCH_TYPE_UL;
174+ muru->cfg_comm |= host_to_le32(MURU_COMM_SET);
175+ muru->cfg_ul |= host_to_le32(MURU_FIXED_UL_TOTAL_USER_CNT);
176+ } else if (os_strcmp(config, "dl_comm_user_cnt") == 0) {
177+ dl->user_num = (u8)atoi(value);
178+ comm->ppdu_format |= MURU_PPDU_HE_MU;
179+ comm->sch_type |= MURU_OFDMA_SCH_TYPE_DL;
180+ muru->cfg_comm |= host_to_le32(MURU_COMM_SET);
181+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_TOTAL_USER_CNT);
182+ } else if (os_strcmp(config, "dl_comm_bw") == 0) {
183+ dl->bw = (u8)atoi(value);
184+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_BW);
185+ } else if (os_strcmp(config, "ul_comm_bw") == 0) {
186+ ul->bw = (u8)atoi(value);
187+ muru->cfg_ul |= host_to_le32(MURU_FIXED_UL_BW);
188+ } else if (os_strcmp(config, "dl_user_ru_alloc") == 0) {
189+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_dl, MURU_FIXED_DL_TOTAL_USER_CNT);
190+ cnt = hostapd_parse_argument_helper(value, &val);
191+ if (cnt == -1)
192+ goto fail;
193+ if (cnt != (dl->user_num * 2))
194+ goto para_fail;
195+ for (i = 0; i < dl->user_num; i++) {
196+ dl->usr[i].ru_alloc_seg = (val[2 * i] & 0x1);
197+ dl->usr[i].ru_allo_ps160 = ((val[2 * i] & 0x2) >> 1);
198+ dl->usr[i].ru_idx = val[(2 * i) + 1];
199+ }
200+ os_free(val);
201+ muru->cfg_dl |= host_to_le32(MURU_FIXED_USER_DL_RU_ALLOC);
202+ } else if (os_strcmp(config, "ul_user_ru_alloc") == 0) {
203+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_ul, MURU_FIXED_UL_TOTAL_USER_CNT);
204+ cnt = hostapd_parse_argument_helper(value, &val);
205+ if (cnt == -1)
206+ goto fail;
207+ if (cnt != (ul->user_num * 2))
208+ goto para_fail;
209+ for (i = 0; i < ul->user_num; i++) {
210+ ul->usr[i].ru_alloc_seg = (val[2 * i] & 0x1);
211+ ul->usr[i].ru_allo_ps160 = ((val[2 * i] & 0x2) >> 1);
212+ ul->usr[i].ru_idx = val[(2 * i) + 1];
213+ }
214+ os_free(val);
215+ muru->cfg_ul |= host_to_le32(MURU_FIXED_USER_UL_RU_ALLOC);
216+ } else if (os_strcmp(config, "dl_user_mcs") == 0) {
217+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_dl, MURU_FIXED_DL_TOTAL_USER_CNT);
218+ cnt = hostapd_parse_argument_helper(value, &val);
219+ if (cnt == -1)
220+ goto fail;
221+ if (cnt != dl->user_num)
222+ goto para_fail;
223+ for (i = 0; i < cnt; i++)
224+ dl->usr[i].mcs = (u8) val[i];
225+ os_free(val);
226+ muru->cfg_dl |= host_to_le32(MURU_FIXED_USER_DL_MCS);
227+ } else if (os_strcmp(config, "ul_user_mcs") == 0) {
228+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_ul, MURU_FIXED_UL_TOTAL_USER_CNT);
229+ cnt = hostapd_parse_argument_helper(value, &val);
230+ if (cnt == -1)
231+ goto fail;
232+ if (cnt != ul->user_num)
233+ goto para_fail;
234+ for (i = 0; i < cnt; i++)
235+ ul->usr[i].mcs = (u8) val[i];
236+ os_free(val);
237+ muru->cfg_ul |= host_to_le32(MURU_FIXED_USER_UL_MCS);
238+ } else if (os_strcmp(config, "dl_user_cod") == 0) {
239+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_dl, MURU_FIXED_DL_TOTAL_USER_CNT);
240+ cnt = hostapd_parse_argument_helper(value, &val);
241+ if (cnt == -1)
242+ goto fail;
243+ if (cnt != dl->user_num)
244+ goto para_fail;
245+ for (i = 0; i < cnt; i++)
246+ dl->usr[i].ldpc = (u8) val[i];
247+ os_free(val);
248+ muru->cfg_dl |= host_to_le32(MURU_FIXED_USER_DL_COD);
249+ } else if (os_strcmp(config, "ul_user_cod") == 0) {
250+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_ul, MURU_FIXED_UL_TOTAL_USER_CNT);
251+ cnt = hostapd_parse_argument_helper(value, &val);
252+ if (cnt == -1)
253+ goto fail;
254+ if (cnt != ul->user_num)
255+ goto para_fail;
256+ for (i = 0; i < cnt; i++)
257+ ul->usr[i].ldpc = (u8) val[i];
258+ os_free(val);
259+ muru->cfg_ul |= host_to_le32(MURU_FIXED_USER_UL_COD);
260+ } else if (os_strcmp(config, "ul_user_ssAlloc_raru") == 0) {
261+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_ul, MURU_FIXED_UL_TOTAL_USER_CNT);
262+ cnt = hostapd_parse_argument_helper(value, &val);
263+ if (cnt == -1)
264+ goto fail;
265+ if (cnt != ul->user_num)
266+ goto para_fail;
267+ for (i = 0; i < cnt; i++)
268+ ul->usr[i].nss = (u8) val[i];
269+ os_free(val);
270+ muru->cfg_ul |= host_to_le32(MURU_FIXED_USER_UL_NSS);
271+ } else if (os_strcmp(config, "dl_comm_gi") == 0) {
272+ dl->gi = (u8)atoi(value);
273+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_GI);
274+ } else if (os_strcmp(config, "dl_comm_ltf") == 0) {
275+ dl->ltf = (u8)atoi(value);
276+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_LTF);
277+ } else if (os_strcmp(config, "ul_comm_gi_ltf") == 0) {
278+ ul->gi_ltf = (u8)atoi(value);
279+ muru->cfg_ul |= host_to_le32(MURU_FIXED_UL_GILTF);
280+ } else if (os_strcmp(config, "dl_comm_ack_policy") == 0) {
281+ dl->ack_policy = (u8)atoi(value);
282+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_ACK_PLY);
283+ } else if (os_strcmp(config, "dl_comm_toneplan") == 0) {
284+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_dl, MURU_FIXED_DL_BW);
285+ cnt = hostapd_parse_argument_helper(value, &val);
286+ if (cnt == -1)
287+ goto fail;
288+ i = pow(2, dl->bw);
289+ if (cnt != i)
290+ goto para_fail;
291+ for (i = 0; i < cnt; i++)
292+ dl->ru[i] = host_to_le16(val[i]);
293+ os_free(val);
294+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_TONE_PLAN);
295 } else {
296- return -1;
297+ wpa_printf(MSG_ERROR,
298+ "Unsupported parameter %s for SET_MU", config);
299+ goto fail;
300 }
301+
302+ return os_snprintf(buf, buflen, "OK\n");
303+
304+para_fail:
305+ os_free(val);
306+ wpa_printf(MSG_ERROR, "Incorrect input number\n");
307+fail:
308+ return os_snprintf(buf, buflen, "FAIL\n");
309 }
310
311
312@@ -5148,8 +5330,7 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
313 reply_len = hostapd_ctrl_iface_get_edcca(hapd, buf+10, reply,
314 reply_size);
315 } else if (os_strncmp(buf, "SET_MU ", 7) == 0) {
316- reply_len = hostapd_ctrl_iface_set_mu(hapd, buf + 7, reply,
317- reply_size);
318+ reply_len = hostapd_ctrl_iface_set_mu(hapd, buf + 7, reply, reply_size);
319 } else if (os_strncmp(buf, "GET_MU", 6) == 0) {
320 reply_len = hostapd_ctrl_iface_get_mu(hapd, reply, reply_size);
321 } else if (os_strncmp(buf, "GET_IBF", 7) == 0) {
322@@ -5175,6 +5356,14 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
323 } else if (os_strncmp(buf, "DUMP_AMNT", 9) == 0) {
324 reply_len = hostapd_ctrl_iface_dump_amnt(hapd, buf+10,
325 reply, reply_size);
326+ } else if (os_strncmp(buf, "set_muru_manual_config=", 23) == 0) {
327+ // Replace first ':' with a single space ' '
328+ char *pos = buf + 23;
329+
330+ pos = os_strchr(pos, ':');
331+ if (pos)
332+ *pos = ' ';
333+ reply_len = hostapd_ctrl_iface_set_mu(hapd, buf + 23, reply, reply_size);
334 } else {
335 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
336 reply_len = 16;
337diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
338index d995b8d9c..3827a8fc8 100644
339--- a/src/ap/ap_config.h
340+++ b/src/ap/ap_config.h
341@@ -1291,6 +1291,7 @@ struct hostapd_config {
342 u8 ibf_enable;
343 u8 dfs_detect_mode;
344 u8 amsdu;
345+ void *muru_config;
346 };
347
348 enum three_wire_mode {
349diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
350index 8878db380..116bc4ceb 100644
351--- a/src/ap/ap_drv_ops.c
352+++ b/src/ap/ap_drv_ops.c
353@@ -1270,11 +1270,11 @@ int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value)
354 return hapd->driver->get_edcca(hapd->drv_priv, mode, value);
355 }
356
357-int hostapd_drv_mu_ctrl(struct hostapd_data *hapd, u8 mode, u8 val)
358+int hostapd_drv_mu_ctrl(struct hostapd_data *hapd, u8 mode)
359 {
360 if (!hapd->driver || !hapd->driver->mu_ctrl)
361 return 0;
362- return hapd->driver->mu_ctrl(hapd->drv_priv, mode, val);
363+ return hapd->driver->mu_ctrl(hapd->drv_priv, mode, hapd->iconf);
364 }
365
366 int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff)
367diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
368index f77d07da0..84b41881a 100644
369--- a/src/ap/ap_drv_ops.h
370+++ b/src/ap/ap_drv_ops.h
371@@ -153,7 +153,7 @@ int hostapd_drv_configure_edcca_enable(struct hostapd_data *hapd);
372 int hostapd_drv_configure_edcca_threshold(struct hostapd_data *hapd,
373 const int *threshold);
374 int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value);
375-int hostapd_drv_mu_ctrl(struct hostapd_data *hapd, u8 mode, u8 val);
376+int hostapd_drv_mu_ctrl(struct hostapd_data *hapd, u8 mode);
377 int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
378 int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd);
379 int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
380diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
381index 5fd46d53d..d1ee0764b 100644
382--- a/src/ap/hostapd.c
383+++ b/src/ap/hostapd.c
384@@ -2700,7 +2700,7 @@ dfs_offload:
385 if (hostapd_drv_configure_edcca_threshold(hapd,
386 hapd->iconf->edcca_threshold) < 0)
387 goto fail;
388- if (hostapd_drv_mu_ctrl(hapd, MU_CTRL_ONOFF, hapd->iconf->mu_onoff) < 0)
389+ if (hostapd_drv_mu_ctrl(hapd, MU_CTRL_ONOFF) < 0)
390 goto fail;
391 if (hostapd_drv_three_wire_ctrl(hapd) < 0)
392 goto fail;
393diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
394index 99371bf73..e140de60b 100644
395--- a/src/common/mtk_vendor.h
396+++ b/src/common/mtk_vendor.h
397@@ -199,8 +199,11 @@ enum mtk_vendor_attr_mu_ctrl {
398
399 MTK_VENDOR_ATTR_MU_CTRL_ONOFF,
400 MTK_VENDOR_ATTR_MU_CTRL_DUMP,
401- MTK_VENDOR_ATTR_MU_CTRL_OFDMA_MODE,
402- MTK_VENDOR_ATTR_MU_CTRL_OFDMA_VAL,
403+ /**
404+ * The above attrs are also used by connac 2. It is best not to modify the
405+ * above data structure.
406+ */
407+ MTK_VENDOR_ATTR_MU_CTRL_STRUCT,
408
409 /* keep last */
410 NUM_MTK_VENDOR_ATTRS_MU_CTRL,
411@@ -275,8 +278,163 @@ struct amnt_resp_data {
412 };
413
414 enum {
415+ MU_CTRL_UPDATE,
416 MU_CTRL_ONOFF,
417- MU_CTRL_DL_USER_CNT,
418- MU_CTRL_UL_USER_CNT,
419 };
420+
421+struct connac3_muru_comm {
422+ u8 pda_pol;
423+ u8 band;
424+ u8 spe_idx;
425+ u8 proc_type;
426+
427+ le16 mlo_ctrl;
428+ u8 sch_type;
429+ u8 ppdu_format;
430+ u8 ac;
431+ u8 _rsv[3];
432+};
433+
434+struct connac3_muru_dl {
435+ u8 user_num;
436+ u8 tx_mode;
437+ u8 bw;
438+ u8 gi;
439+
440+ u8 ltf;
441+ u8 mcs;
442+ u8 dcm;
443+ u8 cmprs;
444+
445+ le16 ru[16];
446+
447+ u8 c26[2];
448+ u8 ack_policy;
449+ u8 tx_power;
450+
451+ le16 mu_ppdu_duration;
452+ u8 agc_disp_order;
453+ u8 _rsv1;
454+
455+ u8 agc_disp_pol;
456+ u8 agc_disp_ratio;
457+ le16 agc_disp_linkMFG;
458+
459+ le16 prmbl_punc_bmp;
460+ u8 _rsv2[2];
461+
462+ struct {
463+ le16 wlan_idx;
464+ u8 ru_alloc_seg;
465+ u8 ru_idx;
466+ u8 ldpc;
467+ u8 nss;
468+ u8 mcs;
469+ u8 mu_group_idx;
470+ u8 vht_groud_id;
471+ u8 vht_up;
472+ u8 he_start_stream;
473+ u8 he_mu_spatial;
474+ le16 tx_power_alpha;
475+ u8 ack_policy;
476+ u8 ru_allo_ps160;
477+ } usr[16];
478+};
479+
480+struct connac3_muru_ul {
481+ u8 user_num;
482+ u8 tx_mode;
483+
484+ u8 ba_type;
485+ u8 _rsv;
486+
487+ u8 bw;
488+ u8 gi_ltf;
489+ le16 ul_len;
490+
491+ le16 trig_cnt;
492+ u8 pad;
493+ u8 trig_type;
494+
495+ le16 trig_intv;
496+ u8 trig_ta[ETH_ALEN];
497+ le16 ul_ru[16];
498+
499+ u8 c26[2];
500+ le16 agc_disp_linkMFG;
501+
502+ u8 agc_disp_mu_len;
503+ u8 agc_disp_pol;
504+ u8 agc_disp_ratio;
505+ u8 agc_disp_pu_idx;
506+
507+ struct {
508+ le16 wlan_idx;
509+ u8 ru_alloc_seg;
510+ u8 ru_idx;
511+ u8 ldpc;
512+ u8 nss;
513+ u8 mcs;
514+ u8 target_rssi;
515+ le32 trig_pkt_size;
516+ u8 ru_allo_ps160;
517+ u8 _rsv2[3];
518+ } usr[16];
519+};
520+
521+struct connac3_muru_dbg {
522+ /* HE TB RX Debug */
523+ le32 rx_hetb_nonsf_en_bitmap;
524+ le32 rx_hetb_cfg[2];
525+};
526+
527+struct connac3_muru {
528+ le32 cfg_comm;
529+ le32 cfg_dl;
530+ le32 cfg_ul;
531+ le32 cfg_dbg;
532+
533+ struct connac3_muru_comm comm;
534+ struct connac3_muru_dl dl;
535+ struct connac3_muru_ul ul;
536+ struct connac3_muru_dbg dbg;
537+};
538+
539+#define MURU_OFDMA_SCH_TYPE_DL BIT(0)
540+#define MURU_OFDMA_SCH_TYPE_UL BIT(1)
541+#define MURU_PPDU_HE_TRIG BIT(2)
542+#define MURU_PPDU_HE_MU BIT(3)
543+
544+/* Common Config */
545+#define MURU_COMM_PPDU_FMT BIT(0)
546+#define MURU_COMM_BAND BIT(2)
547+#define MURU_COMM_WMM BIT(3)
548+#define MURU_COMM_SPE_IDX BIT(4)
549+#define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_BAND | \
550+ MURU_COMM_WMM | MURU_COMM_SPE_IDX)
551+
552+/* DL Common config */
553+#define MURU_FIXED_DL_BW BIT(0)
554+#define MURU_FIXED_DL_GI BIT(1)
555+#define MURU_FIXED_DL_TONE_PLAN BIT(3)
556+#define MURU_FIXED_DL_TOTAL_USER_CNT BIT(4)
557+#define MURU_FIXED_DL_LTF BIT(5)
558+#define MURU_FIXED_DL_ACK_PLY BIT(9)
559+
560+/* DL Per User Config */
561+#define MURU_FIXED_USER_DL_COD BIT(17)
562+#define MURU_FIXED_USER_DL_MCS BIT(18)
563+#define MURU_FIXED_USER_DL_RU_ALLOC BIT(20)
564+
565+/* UL Common Config */
566+#define MURU_FIXED_UL_TOTAL_USER_CNT BIT(4)
567+#define MURU_FIXED_UL_BW BIT(5)
568+#define MURU_FIXED_UL_GILTF BIT(6)
569+
570+/* UL Per User Config */
571+#define MURU_FIXED_USER_UL_COD BIT(18)
572+#define MURU_FIXED_USER_UL_MCS BIT(19)
573+#define MURU_FIXED_USER_UL_NSS BIT(20)
574+#define MURU_FIXED_USER_UL_RU_ALLOC BIT(21)
575+
576 #endif /* MTK_VENDOR_H */
577diff --git a/src/drivers/driver.h b/src/drivers/driver.h
578index 3be4562e7..1c0c38e24 100644
579--- a/src/drivers/driver.h
580+++ b/src/drivers/driver.h
581@@ -5240,7 +5240,7 @@ struct wpa_driver_ops {
582 * @priv: Private driver interface data
583 *
584 */
585- int (*mu_ctrl)(void *priv, u8 mode, u8 val);
586+ int (*mu_ctrl)(void *priv, u8 mode, void *config);
587 int (*mu_dump)(void *priv, u8 *mu_onoff);
588
589 /**
590diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
591index 035a477e2..aeb755b11 100644
592--- a/src/drivers/driver_nl80211.c
593+++ b/src/drivers/driver_nl80211.c
594@@ -13982,12 +13982,13 @@ fail:
595
596
597 #ifdef CONFIG_IEEE80211AX
598-static int nl80211_mu_ctrl(void *priv, u8 mode, u8 val)
599+static int nl80211_mu_ctrl(void *priv, u8 mode, void *config)
600 {
601 struct i802_bss *bss = priv;
602 struct wpa_driver_nl80211_data *drv = bss->drv;
603 struct nl_msg *msg;
604 struct nlattr *data;
605+ struct hostapd_config *cfg = config;
606 int ret = -ENOBUFS;
607
608 if (!drv->mtk_mu_vendor_cmd_avail) {
609@@ -14004,17 +14005,16 @@ static int nl80211_mu_ctrl(void *priv, u8 mode, u8 val)
610
611 switch (mode) {
612 case MU_CTRL_ONOFF:
613- if (nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_ONOFF, val))
614- goto fail;
615+ if (nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_ONOFF, cfg->mu_onoff))
616+ goto fail;
617 break;
618- case MU_CTRL_UL_USER_CNT:
619- case MU_CTRL_DL_USER_CNT:
620- if (nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_OFDMA_MODE, mode) ||
621- nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_OFDMA_VAL, val))
622- goto fail;
623+ case MU_CTRL_UPDATE:
624+ if (nla_put(msg, MTK_VENDOR_ATTR_MU_CTRL_STRUCT,
625+ sizeof(struct connac3_muru), cfg->muru_config))
626+ goto fail;
627 break;
628 default:
629- wpa_printf(MSG_ERROR, "nl80211: Wrong mu mode !");
630+ wpa_printf(MSG_ERROR, "nl80211: Wrong mu mode %u!", mode);
631 ret = -EINVAL;
632 goto fail;
633 }
634@@ -14022,9 +14022,8 @@ static int nl80211_mu_ctrl(void *priv, u8 mode, u8 val)
635 nla_nest_end(msg, data);
636
637 ret = send_and_recv_cmd(drv, msg);
638- if(ret){
639+ if (ret)
640 wpa_printf(MSG_ERROR, "Failed to set mu_ctrl. ret=%d (%s)", ret, strerror(-ret));
641- }
642 return ret;
643
644 fail:
645--
6462.39.2
647