blob: db8ae73ecb4eab8b9e47f3259f69929e7f7f7177 [file] [log] [blame]
From 738370924d0153163300f44c87a68e19a5220272 Mon Sep 17 00:00:00 2001
From: Howard Hsu <howard-yh.hsu@mediatek.com>
Date: Sat, 3 Jun 2023 17:12:15 +0800
Subject: [PATCH 25/54] mtk: hostapd: add connac3 PHY MURU manual mode config
support
This commit supports read the following two formats to set MU/RU manual
mode:
1. hostapd_cli -i <intf> raw set_muru_manual_config=<field>:<value>
2. hostapd_cli -i <intf> set_mu <field> <value>
For the <field>, we support the following field:
1. ul_comm_user_cnt/dl_comm_user_cnt: set the number of user
2. ul_comm_bw/dl_comm_bw: set the bandwith
3. ul_user_ru_alloc/dl_user_ru_alloc: set the RU band idx and RU
allocate idx
4. ul_user_mcs/dl_user_mcs: set the mcs for each user
5. ul_user_ssAlloc_raru: set the number of ss for each user
6. ul_comm_gi_ltf: set the combinations of gi and ltf for UL only.
7. dl_comm_toneplan: fix ru toneplan allocation
8. dl_comm_ack_policy: fix station ack policy
9. update : trigger driver to send mcu command to set muru manual mode.
For the value of each field, please check wiki to learn the details:
https://wiki.mediatek.inc/display/GWKB/muru_mancfg_user_guide
For the fields that mt76 support to use, we will update in this wiki:
https://wiki.mediatek.inc/pages/viewpage.action?pageId=1271741116
Please noted that this commit is only for connac 3 gen chips. If this
feature is to be used in other generations, the following actions must
be taken:
1. Different data structue needs to be defined for different
generations, e.g. connac4_muru_comm, connac4_muru_dl.
2. hostapd_ctrl_iface_set_mu() shall be modified.
3. A new code level configuration shall be defined to differentiate the
code flow that different generations will go through.
---
hostapd/ctrl_iface.c | 235 +++++++++++++++++++++++++++++++----
src/ap/ap_config.h | 1 +
src/ap/ap_drv_ops.c | 4 +-
src/ap/ap_drv_ops.h | 2 +-
src/ap/hostapd.c | 2 +-
src/common/mtk_vendor.h | 166 ++++++++++++++++++++++++-
src/drivers/driver.h | 2 +-
src/drivers/driver_nl80211.c | 21 ++--
8 files changed, 390 insertions(+), 43 deletions(-)
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 4515583cf..ae61cf625 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -3500,22 +3500,61 @@ hostapd_ctrl_iface_get_edcca(struct hostapd_data *hapd, char *cmd, char *buf,
}
}
+static int
+hostapd_parse_argument_helper(char *value, u16 **ptr_input)
+{
+#define MAX_MU_CTRL_NUM 17
+
+ u16 *input;
+ char *endptr;
+ int cnt = 0;
+
+ input = os_zalloc(MAX_MU_CTRL_NUM * sizeof(u16));
+ if (input == NULL) {
+ wpa_printf(MSG_ERROR, "Failed to allocate memory.\n");
+ return -1;
+ }
+ while (value) {
+ u8 val = strtol(value, &endptr, 10);
+
+ if (value != endptr) {
+ input[cnt++] = val;
+ value = os_strchr(endptr, ':');
+ if (value)
+ value++;
+ } else {
+ break;
+ }
+ }
+ *ptr_input = input;
+ return cnt;
+}
+
+#define MURU_CFG_DEPENDENCE_CHECK(_val, _mask) do { \
+ if ((le_to_host32(_val) & (_mask)) != _mask) { \
+ wpa_printf(MSG_ERROR, "Set %s first\n", #_mask); \
+ goto fail; \
+ } \
+ } while(0)
static int
hostapd_ctrl_iface_set_mu(struct hostapd_data *hapd, char *cmd,
- char *buf, size_t buflen)
+ char *buf, size_t buflen)
{
char *pos, *config, *value;
- u8 mode;
+ u8 i;
+ int cnt = 0, ret;
+ u16 *val;
+ struct connac3_muru *muru;
+ struct connac3_muru_dl *dl;
+ struct connac3_muru_ul *ul;
+ struct connac3_muru_comm *comm;
config = cmd;
pos = os_strchr(config, ' ');
- if (pos == NULL)
- return -1;
- *pos++ = '\0';
+ if (pos != NULL)
+ *pos++ = '\0';
- if(pos == NULL)
- return -1;
value = pos;
if (os_strcmp(config, "onoff") == 0) {
@@ -3525,24 +3564,167 @@ hostapd_ctrl_iface_set_mu(struct hostapd_data *hapd, char *cmd,
return -1;
}
hapd->iconf->mu_onoff = (u8) mu;
- mode = MU_CTRL_ONOFF;
- } else if (os_strcmp(config, "ul_user_cnt") == 0) {
- mode = MU_CTRL_UL_USER_CNT;
- wpa_printf(MSG_ERROR, "ul_user_cnt:%d\n", (u8)atoi(value));
- } else if (os_strcmp(config, "dl_user_cnt") == 0) {
- mode = MU_CTRL_DL_USER_CNT;
- wpa_printf(MSG_ERROR, "dl_user_cnt:%d\n", (u8)atoi(value));
- } else {
- wpa_printf(MSG_ERROR,
- "Unsupported parameter %s for SET_MU", config);
- return -1;
+
+ if (hostapd_drv_mu_ctrl(hapd, MU_CTRL_ONOFF) == 0)
+ return os_snprintf(buf, buflen, "OK\n");
+ else
+ goto fail;
}
- if(hostapd_drv_mu_ctrl(hapd, mode, (u8)atoi(value)) == 0) {
- return os_snprintf(buf, buflen, "OK\n");
+ if (hapd->iconf->muru_config == NULL)
+ hapd->iconf->muru_config = os_zalloc(sizeof(struct connac3_muru));
+
+ muru = hapd->iconf->muru_config;
+ dl = &muru->dl;
+ ul = &muru->ul;
+ comm = &muru->comm;
+
+ if (os_strncmp(config, "update", 6) == 0) {
+ ret = hostapd_drv_mu_ctrl(hapd, MU_CTRL_UPDATE);
+
+ os_free(hapd->iconf->muru_config);
+ hapd->iconf->muru_config = NULL;
+
+ if (ret)
+ goto fail;
+ } else if (os_strcmp(config, "ul_comm_user_cnt") == 0) {
+ ul->user_num = (u8)atoi(value);
+ comm->ppdu_format |= MURU_PPDU_HE_TRIG;
+ comm->sch_type |= MURU_OFDMA_SCH_TYPE_UL;
+ muru->cfg_comm |= host_to_le32(MURU_COMM_SET);
+ muru->cfg_ul |= host_to_le32(MURU_FIXED_UL_TOTAL_USER_CNT);
+ } else if (os_strcmp(config, "dl_comm_user_cnt") == 0) {
+ dl->user_num = (u8)atoi(value);
+ comm->ppdu_format |= MURU_PPDU_HE_MU;
+ comm->sch_type |= MURU_OFDMA_SCH_TYPE_DL;
+ muru->cfg_comm |= host_to_le32(MURU_COMM_SET);
+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_TOTAL_USER_CNT);
+ } else if (os_strcmp(config, "dl_comm_bw") == 0) {
+ dl->bw = (u8)atoi(value);
+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_BW);
+ } else if (os_strcmp(config, "ul_comm_bw") == 0) {
+ ul->bw = (u8)atoi(value);
+ muru->cfg_ul |= host_to_le32(MURU_FIXED_UL_BW);
+ } else if (os_strcmp(config, "dl_user_ru_alloc") == 0) {
+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_dl, MURU_FIXED_DL_TOTAL_USER_CNT);
+ cnt = hostapd_parse_argument_helper(value, &val);
+ if (cnt == -1)
+ goto fail;
+ if (cnt != (dl->user_num * 2))
+ goto para_fail;
+ for (i = 0; i < dl->user_num; i++) {
+ dl->usr[i].ru_alloc_seg = (val[2 * i] & 0x1);
+ dl->usr[i].ru_allo_ps160 = ((val[2 * i] & 0x2) >> 1);
+ dl->usr[i].ru_idx = val[(2 * i) + 1];
+ }
+ os_free(val);
+ muru->cfg_dl |= host_to_le32(MURU_FIXED_USER_DL_RU_ALLOC);
+ } else if (os_strcmp(config, "ul_user_ru_alloc") == 0) {
+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_ul, MURU_FIXED_UL_TOTAL_USER_CNT);
+ cnt = hostapd_parse_argument_helper(value, &val);
+ if (cnt == -1)
+ goto fail;
+ if (cnt != (ul->user_num * 2))
+ goto para_fail;
+ for (i = 0; i < ul->user_num; i++) {
+ ul->usr[i].ru_alloc_seg = (val[2 * i] & 0x1);
+ ul->usr[i].ru_allo_ps160 = ((val[2 * i] & 0x2) >> 1);
+ ul->usr[i].ru_idx = val[(2 * i) + 1];
+ }
+ os_free(val);
+ muru->cfg_ul |= host_to_le32(MURU_FIXED_USER_UL_RU_ALLOC);
+ } else if (os_strcmp(config, "dl_user_mcs") == 0) {
+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_dl, MURU_FIXED_DL_TOTAL_USER_CNT);
+ cnt = hostapd_parse_argument_helper(value, &val);
+ if (cnt == -1)
+ goto fail;
+ if (cnt != dl->user_num)
+ goto para_fail;
+ for (i = 0; i < cnt; i++)
+ dl->usr[i].mcs = (u8) val[i];
+ os_free(val);
+ muru->cfg_dl |= host_to_le32(MURU_FIXED_USER_DL_MCS);
+ } else if (os_strcmp(config, "ul_user_mcs") == 0) {
+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_ul, MURU_FIXED_UL_TOTAL_USER_CNT);
+ cnt = hostapd_parse_argument_helper(value, &val);
+ if (cnt == -1)
+ goto fail;
+ if (cnt != ul->user_num)
+ goto para_fail;
+ for (i = 0; i < cnt; i++)
+ ul->usr[i].mcs = (u8) val[i];
+ os_free(val);
+ muru->cfg_ul |= host_to_le32(MURU_FIXED_USER_UL_MCS);
+ } else if (os_strcmp(config, "dl_user_cod") == 0) {
+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_dl, MURU_FIXED_DL_TOTAL_USER_CNT);
+ cnt = hostapd_parse_argument_helper(value, &val);
+ if (cnt == -1)
+ goto fail;
+ if (cnt != dl->user_num)
+ goto para_fail;
+ for (i = 0; i < cnt; i++)
+ dl->usr[i].ldpc = (u8) val[i];
+ os_free(val);
+ muru->cfg_dl |= host_to_le32(MURU_FIXED_USER_DL_COD);
+ } else if (os_strcmp(config, "ul_user_cod") == 0) {
+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_ul, MURU_FIXED_UL_TOTAL_USER_CNT);
+ cnt = hostapd_parse_argument_helper(value, &val);
+ if (cnt == -1)
+ goto fail;
+ if (cnt != ul->user_num)
+ goto para_fail;
+ for (i = 0; i < cnt; i++)
+ ul->usr[i].ldpc = (u8) val[i];
+ os_free(val);
+ muru->cfg_ul |= host_to_le32(MURU_FIXED_USER_UL_COD);
+ } else if (os_strcmp(config, "ul_user_ssAlloc_raru") == 0) {
+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_ul, MURU_FIXED_UL_TOTAL_USER_CNT);
+ cnt = hostapd_parse_argument_helper(value, &val);
+ if (cnt == -1)
+ goto fail;
+ if (cnt != ul->user_num)
+ goto para_fail;
+ for (i = 0; i < cnt; i++)
+ ul->usr[i].nss = (u8) val[i];
+ os_free(val);
+ muru->cfg_ul |= host_to_le32(MURU_FIXED_USER_UL_NSS);
+ } else if (os_strcmp(config, "dl_comm_gi") == 0) {
+ dl->gi = (u8)atoi(value);
+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_GI);
+ } else if (os_strcmp(config, "dl_comm_ltf") == 0) {
+ dl->ltf = (u8)atoi(value);
+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_LTF);
+ } else if (os_strcmp(config, "ul_comm_gi_ltf") == 0) {
+ ul->gi_ltf = (u8)atoi(value);
+ muru->cfg_ul |= host_to_le32(MURU_FIXED_UL_GILTF);
+ } else if (os_strcmp(config, "dl_comm_ack_policy") == 0) {
+ dl->ack_policy = (u8)atoi(value);
+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_ACK_PLY);
+ } else if (os_strcmp(config, "dl_comm_toneplan") == 0) {
+ MURU_CFG_DEPENDENCE_CHECK(muru->cfg_dl, MURU_FIXED_DL_BW);
+ cnt = hostapd_parse_argument_helper(value, &val);
+ if (cnt == -1)
+ goto fail;
+ i = pow(2, dl->bw);
+ if (cnt != i)
+ goto para_fail;
+ for (i = 0; i < cnt; i++)
+ dl->ru[i] = host_to_le16(val[i]);
+ os_free(val);
+ muru->cfg_dl |= host_to_le32(MURU_FIXED_DL_TONE_PLAN);
} else {
- return -1;
+ wpa_printf(MSG_ERROR,
+ "Unsupported parameter %s for SET_MU", config);
+ goto fail;
}
+
+ return os_snprintf(buf, buflen, "OK\n");
+
+para_fail:
+ os_free(val);
+ wpa_printf(MSG_ERROR, "Incorrect input number\n");
+fail:
+ return os_snprintf(buf, buflen, "FAIL\n");
}
@@ -4540,8 +4722,7 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
reply_len = hostapd_ctrl_iface_get_edcca(hapd, buf+10, reply,
reply_size);
} else if (os_strncmp(buf, "SET_MU ", 7) == 0) {
- reply_len = hostapd_ctrl_iface_set_mu(hapd, buf + 7, reply,
- reply_size);
+ reply_len = hostapd_ctrl_iface_set_mu(hapd, buf + 7, reply, reply_size);
} else if (os_strncmp(buf, "GET_MU", 6) == 0) {
reply_len = hostapd_ctrl_iface_get_mu(hapd, reply, reply_size);
} else if (os_strncmp(buf, "GET_IBF", 7) == 0) {
@@ -4567,6 +4748,14 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "DUMP_AMNT", 9) == 0) {
reply_len = hostapd_ctrl_iface_dump_amnt(hapd, buf+10,
reply, reply_size);
+ } else if (os_strncmp(buf, "set_muru_manual_config=", 23) == 0) {
+ // Replace first ':' with a single space ' '
+ char *pos = buf + 23;
+
+ pos = os_strchr(pos, ':');
+ if (pos)
+ *pos = ' ';
+ reply_len = hostapd_ctrl_iface_set_mu(hapd, buf + 23, reply, reply_size);
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index f03a957b7..7c0d12a3b 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1203,6 +1203,7 @@ struct hostapd_config {
u8 ibf_enable;
u8 dfs_detect_mode;
u8 amsdu;
+ void *muru_config;
};
enum three_wire_mode {
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 0aec9e925..721bfa053 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -1162,11 +1162,11 @@ int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value)
return hapd->driver->get_edcca(hapd->drv_priv, mode, value);
}
-int hostapd_drv_mu_ctrl(struct hostapd_data *hapd, u8 mode, u8 val)
+int hostapd_drv_mu_ctrl(struct hostapd_data *hapd, u8 mode)
{
if (!hapd->driver || !hapd->driver->mu_ctrl)
return 0;
- return hapd->driver->mu_ctrl(hapd->drv_priv, mode, val);
+ return hapd->driver->mu_ctrl(hapd->drv_priv, mode, hapd->iconf);
}
int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff)
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 464efbae1..1e7ae7a8d 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -148,7 +148,7 @@ int hostapd_drv_configure_edcca_enable(struct hostapd_data *hapd);
int hostapd_drv_configure_edcca_threshold(struct hostapd_data *hapd,
const int *threshold);
int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value);
-int hostapd_drv_mu_ctrl(struct hostapd_data *hapd, u8 mode, u8 val);
+int hostapd_drv_mu_ctrl(struct hostapd_data *hapd, u8 mode);
int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd);
int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 2d7fb6d39..a28466405 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -2518,7 +2518,7 @@ dfs_offload:
if (hostapd_drv_configure_edcca_threshold(hapd,
hapd->iconf->edcca_threshold) < 0)
goto fail;
- if (hostapd_drv_mu_ctrl(hapd, MU_CTRL_ONOFF, hapd->iconf->mu_onoff) < 0)
+ if (hostapd_drv_mu_ctrl(hapd, MU_CTRL_ONOFF) < 0)
goto fail;
if (hostapd_drv_three_wire_ctrl(hapd) < 0)
goto fail;
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
index 99371bf73..e140de60b 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -199,8 +199,11 @@ enum mtk_vendor_attr_mu_ctrl {
MTK_VENDOR_ATTR_MU_CTRL_ONOFF,
MTK_VENDOR_ATTR_MU_CTRL_DUMP,
- MTK_VENDOR_ATTR_MU_CTRL_OFDMA_MODE,
- MTK_VENDOR_ATTR_MU_CTRL_OFDMA_VAL,
+ /**
+ * The above attrs are also used by connac 2. It is best not to modify the
+ * above data structure.
+ */
+ MTK_VENDOR_ATTR_MU_CTRL_STRUCT,
/* keep last */
NUM_MTK_VENDOR_ATTRS_MU_CTRL,
@@ -275,8 +278,163 @@ struct amnt_resp_data {
};
enum {
+ MU_CTRL_UPDATE,
MU_CTRL_ONOFF,
- MU_CTRL_DL_USER_CNT,
- MU_CTRL_UL_USER_CNT,
};
+
+struct connac3_muru_comm {
+ u8 pda_pol;
+ u8 band;
+ u8 spe_idx;
+ u8 proc_type;
+
+ le16 mlo_ctrl;
+ u8 sch_type;
+ u8 ppdu_format;
+ u8 ac;
+ u8 _rsv[3];
+};
+
+struct connac3_muru_dl {
+ u8 user_num;
+ u8 tx_mode;
+ u8 bw;
+ u8 gi;
+
+ u8 ltf;
+ u8 mcs;
+ u8 dcm;
+ u8 cmprs;
+
+ le16 ru[16];
+
+ u8 c26[2];
+ u8 ack_policy;
+ u8 tx_power;
+
+ le16 mu_ppdu_duration;
+ u8 agc_disp_order;
+ u8 _rsv1;
+
+ u8 agc_disp_pol;
+ u8 agc_disp_ratio;
+ le16 agc_disp_linkMFG;
+
+ le16 prmbl_punc_bmp;
+ u8 _rsv2[2];
+
+ struct {
+ le16 wlan_idx;
+ u8 ru_alloc_seg;
+ u8 ru_idx;
+ u8 ldpc;
+ u8 nss;
+ u8 mcs;
+ u8 mu_group_idx;
+ u8 vht_groud_id;
+ u8 vht_up;
+ u8 he_start_stream;
+ u8 he_mu_spatial;
+ le16 tx_power_alpha;
+ u8 ack_policy;
+ u8 ru_allo_ps160;
+ } usr[16];
+};
+
+struct connac3_muru_ul {
+ u8 user_num;
+ u8 tx_mode;
+
+ u8 ba_type;
+ u8 _rsv;
+
+ u8 bw;
+ u8 gi_ltf;
+ le16 ul_len;
+
+ le16 trig_cnt;
+ u8 pad;
+ u8 trig_type;
+
+ le16 trig_intv;
+ u8 trig_ta[ETH_ALEN];
+ le16 ul_ru[16];
+
+ u8 c26[2];
+ le16 agc_disp_linkMFG;
+
+ u8 agc_disp_mu_len;
+ u8 agc_disp_pol;
+ u8 agc_disp_ratio;
+ u8 agc_disp_pu_idx;
+
+ struct {
+ le16 wlan_idx;
+ u8 ru_alloc_seg;
+ u8 ru_idx;
+ u8 ldpc;
+ u8 nss;
+ u8 mcs;
+ u8 target_rssi;
+ le32 trig_pkt_size;
+ u8 ru_allo_ps160;
+ u8 _rsv2[3];
+ } usr[16];
+};
+
+struct connac3_muru_dbg {
+ /* HE TB RX Debug */
+ le32 rx_hetb_nonsf_en_bitmap;
+ le32 rx_hetb_cfg[2];
+};
+
+struct connac3_muru {
+ le32 cfg_comm;
+ le32 cfg_dl;
+ le32 cfg_ul;
+ le32 cfg_dbg;
+
+ struct connac3_muru_comm comm;
+ struct connac3_muru_dl dl;
+ struct connac3_muru_ul ul;
+ struct connac3_muru_dbg dbg;
+};
+
+#define MURU_OFDMA_SCH_TYPE_DL BIT(0)
+#define MURU_OFDMA_SCH_TYPE_UL BIT(1)
+#define MURU_PPDU_HE_TRIG BIT(2)
+#define MURU_PPDU_HE_MU BIT(3)
+
+/* Common Config */
+#define MURU_COMM_PPDU_FMT BIT(0)
+#define MURU_COMM_BAND BIT(2)
+#define MURU_COMM_WMM BIT(3)
+#define MURU_COMM_SPE_IDX BIT(4)
+#define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_BAND | \
+ MURU_COMM_WMM | MURU_COMM_SPE_IDX)
+
+/* DL Common config */
+#define MURU_FIXED_DL_BW BIT(0)
+#define MURU_FIXED_DL_GI BIT(1)
+#define MURU_FIXED_DL_TONE_PLAN BIT(3)
+#define MURU_FIXED_DL_TOTAL_USER_CNT BIT(4)
+#define MURU_FIXED_DL_LTF BIT(5)
+#define MURU_FIXED_DL_ACK_PLY BIT(9)
+
+/* DL Per User Config */
+#define MURU_FIXED_USER_DL_COD BIT(17)
+#define MURU_FIXED_USER_DL_MCS BIT(18)
+#define MURU_FIXED_USER_DL_RU_ALLOC BIT(20)
+
+/* UL Common Config */
+#define MURU_FIXED_UL_TOTAL_USER_CNT BIT(4)
+#define MURU_FIXED_UL_BW BIT(5)
+#define MURU_FIXED_UL_GILTF BIT(6)
+
+/* UL Per User Config */
+#define MURU_FIXED_USER_UL_COD BIT(18)
+#define MURU_FIXED_USER_UL_MCS BIT(19)
+#define MURU_FIXED_USER_UL_NSS BIT(20)
+#define MURU_FIXED_USER_UL_RU_ALLOC BIT(21)
+
#endif /* MTK_VENDOR_H */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 83d347338..8da93e025 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -5125,7 +5125,7 @@ struct wpa_driver_ops {
* @priv: Private driver interface data
*
*/
- int (*mu_ctrl)(void *priv, u8 mode, u8 val);
+ int (*mu_ctrl)(void *priv, u8 mode, void *config);
int (*mu_dump)(void *priv, u8 *mu_onoff);
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 8226bebc4..b3897e61d 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -13698,12 +13698,13 @@ fail:
#ifdef CONFIG_IEEE80211AX
-static int nl80211_mu_ctrl(void *priv, u8 mode, u8 val)
+static int nl80211_mu_ctrl(void *priv, u8 mode, void *config)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
struct nlattr *data;
+ struct hostapd_config *cfg = config;
int ret = -ENOBUFS;
if (!drv->mtk_mu_vendor_cmd_avail) {
@@ -13720,17 +13721,16 @@ static int nl80211_mu_ctrl(void *priv, u8 mode, u8 val)
switch (mode) {
case MU_CTRL_ONOFF:
- if (nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_ONOFF, val))
- goto fail;
+ if (nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_ONOFF, cfg->mu_onoff))
+ goto fail;
break;
- case MU_CTRL_UL_USER_CNT:
- case MU_CTRL_DL_USER_CNT:
- if (nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_OFDMA_MODE, mode) ||
- nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_OFDMA_VAL, val))
- goto fail;
+ case MU_CTRL_UPDATE:
+ if (nla_put(msg, MTK_VENDOR_ATTR_MU_CTRL_STRUCT,
+ sizeof(struct connac3_muru), cfg->muru_config))
+ goto fail;
break;
default:
- wpa_printf(MSG_ERROR, "nl80211: Wrong mu mode !");
+ wpa_printf(MSG_ERROR, "nl80211: Wrong mu mode %u!", mode);
ret = -EINVAL;
goto fail;
}
@@ -13738,9 +13738,8 @@ static int nl80211_mu_ctrl(void *priv, u8 mode, u8 val)
nla_nest_end(msg, data);
ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
- if(ret){
+ if (ret)
wpa_printf(MSG_ERROR, "Failed to set mu_ctrl. ret=%d (%s)", ret, strerror(-ret));
- }
return ret;
fail:
--
2.18.0