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