blob: 0f8af3e141defb244d64c83fbe91fb15bb7cfc35 [file] [log] [blame]
From d45a052e2c7efe295705ad2185f36b38058ede83 Mon Sep 17 00:00:00 2001
From: Allen Ye <allen.ye@mediatek.com>
Date: Tue, 28 May 2024 17:46:26 +0800
Subject: [PATCH 112/126] mtk: hostapd: support enable/disable preamble
puncture from mtk vendor command
Add mtk vendor event to update punct bitmap and trigger channel switch.
Change to pp user mode when use hostapd_cli to channel switch.
Change pp vendor cmd use link_id instead of band_idx.
Remove band_ind in hostapd_cli get/set pp cmd.
Change pp default enable firmware mode.
Signed-off-by: Allen Ye <allen.ye@mediatek.com>
---
hostapd/config_file.c | 1 -
hostapd/ctrl_iface.c | 45 ++++++++--------
hostapd/hostapd_cli.c | 4 +-
src/ap/ap_config.c | 2 +-
src/ap/ap_drv_ops.c | 10 +++-
src/ap/drv_callbacks.c | 82 ++++++++++++++++++++++++++++++
src/common/mtk_vendor.h | 8 ++-
src/drivers/driver.h | 11 +++-
src/drivers/driver_nl80211.c | 10 ++--
src/drivers/driver_nl80211_event.c | 48 +++++++++++++++++
10 files changed, 185 insertions(+), 36 deletions(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 38273a4f2..f7bfc357a 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -5452,7 +5452,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
if (get_u16(pos, line, &conf->punct_bitmap))
return 1;
conf->punct_bitmap = atoi(pos);
- conf->pp_mode = PP_USR_MODE;
} else if (os_strcmp(buf, "punct_acs_threshold") == 0) {
int val = atoi(pos);
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 988bc90de..337261f8f 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -2818,6 +2818,7 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
#ifdef NEED_AP_MLME
struct hostapd_hw_modes *mode = iface->current_mode;
struct csa_settings settings, background_settings;
+ struct hostapd_data *hapd;
int ret;
int freq, state;
int bandwidth, oper_chwidth;
@@ -2914,6 +2915,17 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
break;
}
+#ifdef CONFIG_IEEE80211BE
+ hapd = iface->bss[0];
+ if (hapd->iconf->punct_bitmap != settings.punct_bitmap &&
+ hapd->iconf->pp_mode != PP_USR_MODE) {
+ hapd->iconf->pp_mode = PP_USR_MODE;
+ ret = hostapd_drv_pp_mode_set(hapd);
+ if (ret)
+ return ret;
+ }
+#endif /* CONFIG_IEEE80211BE */
+
for (i = 0; i < iface->num_bss; i++) {
/* Save CHAN_SWITCH VHT, HE, and EHT config */
@@ -5172,8 +5184,7 @@ static int
hostapd_ctrl_iface_set_pp(struct hostapd_data *hapd, char *cmd, char *buf,
size_t buflen)
{
- char *band, *config, *value;
- u8 band_idx;
+ char *config, *value;
config = cmd;
@@ -5182,31 +5193,26 @@ hostapd_ctrl_iface_set_pp(struct hostapd_data *hapd, char *cmd, char *buf,
return -1;
*value++ = '\0';
- band = os_strchr(value, ' ');
- if (band == NULL)
- return -1;
- *band++ = '\0';
- band_idx = strtol(band, NULL, 10);
-
- hapd = hostapd_get_hapd_by_band_idx(hapd, band_idx);
-
- if (!hapd)
- return -1;
-
if (os_strcmp(config, "mode") == 0) {
int val = strtol(value, NULL, 10);
- if (val < PP_DISABLE || val > PP_FW_MODE) {
+ switch(val) {
+ case PP_DISABLE:
+ case PP_FW_MODE:
+ break;
+ case PP_USR_MODE:
+ default:
wpa_printf(MSG_ERROR, "Invalid value for SET_PP");
return -1;
}
hapd->iconf->pp_mode = (u8) val;
+ hapd->iconf->punct_bitmap = 0;
if (hostapd_drv_pp_mode_set(hapd) != 0)
return -1;
} else {
wpa_printf(MSG_ERROR,
"Unsupported parameter %s for SET_PP"
- "Usage: set_pp mode <value> <band_idx>", config);
+ "Usage: set_pp mode <value>", config);
return -1;
}
return os_snprintf(buf, buflen, "OK\n");
@@ -5216,15 +5222,6 @@ static int
hostapd_ctrl_iface_get_pp(struct hostapd_data *hapd, char *cmd, char *buf,
size_t buflen)
{
- u8 band_idx;
-
- band_idx = strtol(cmd, NULL, 10);
-
- hapd = hostapd_get_hapd_by_band_idx(hapd, band_idx);
-
- if (!hapd)
- return -1;
-
return os_snprintf(buf, buflen, "pp_mode: %d, punct_bitmap: 0x%04x\n",
hapd->iconf->pp_mode, hapd->iconf->punct_bitmap);
}
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index bfa912dff..12ee0a18f 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1764,13 +1764,13 @@ static int hostapd_cli_cmd_dump_csi(struct wpa_ctrl *ctrl, int argc,
static int hostapd_cli_cmd_set_pp(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- return hostapd_cli_cmd(ctrl, "set_pp", 3, argc, argv);
+ return hostapd_cli_cmd(ctrl, "set_pp", 2, argc, argv);
}
static int hostapd_cli_cmd_get_pp(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- return hostapd_cli_cmd(ctrl, "get_pp", 1, argc, argv);
+ return hostapd_cli_cmd(ctrl, "get_pp", 0, argc, argv);
}
static int hostapd_cli_cmd_wmm(struct wpa_ctrl *ctrl, int argc,
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 95100b25c..4528df823 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -312,7 +312,7 @@ struct hostapd_config * hostapd_config_defaults(void)
conf->three_wire_enable = THREE_WIRE_MODE_DISABLE;
conf->ibf_enable = IBF_DEFAULT_ENABLE;
conf->amsdu = 1;
- conf->pp_mode = PP_DISABLE;
+ conf->pp_mode = PP_FW_MODE;
conf->band_idx = 255;
hostapd_set_and_check_bw320_offset(conf, 0);
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 8631bf960..f9ec9a689 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -1447,14 +1447,20 @@ int hostapd_drv_background_radar_mode(struct hostapd_data *hapd)
int hostapd_drv_pp_mode_set(struct hostapd_data *hapd)
{
+ s8 link_id = -1;
+
if (!hapd->driver || !hapd->driver->pp_mode_set ||
- hapd->iconf->pp_mode >= PP_USR_MODE ||
+ hapd->iconf->pp_mode > PP_USR_MODE ||
hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
return 0;
+ if (hapd->conf->mld_ap)
+ link_id = hapd->mld_link_id;
+
return hapd->driver->pp_mode_set(hapd->drv_priv,
hapd->iconf->pp_mode,
- hapd->iconf->band_idx);
+ link_id,
+ hapd->iconf->punct_bitmap);
}
int hostapd_drv_beacon_ctrl(struct hostapd_data *hapd, u8 beacon_mode)
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 0e7cfd285..420d156c8 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -43,6 +43,7 @@
#include "fils_hlp.h"
#include "neighbor_db.h"
#include "nan_usd_ap.h"
+#include "ap/beacon.h"
#ifdef CONFIG_FILS
@@ -2456,6 +2457,81 @@ static void hostapd_event_color_change(struct hostapd_data *hapd, bool success)
#endif /* CONFIG_IEEE80211AX */
+static void hostapd_event_pp_bitmap_update(struct hostapd_data *hapd,
+ struct ch_switch *ch_switch)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ struct hostapd_hw_modes *cmode = iface->current_mode;
+ int err, freq;
+ struct csa_settings csa_settings;
+ unsigned int i;
+
+ /* Check if CSA in progress */
+ if (hostapd_csa_in_progress(iface))
+ return;
+
+ if (!hw_get_channel_chan(cmode, iface->conf->channel, &freq))
+ return;
+
+ if (iface->conf->punct_bitmap == ch_switch->punct_bitmap ||
+ freq != ch_switch->freq)
+ return;
+
+ /* Setup CSA request */
+ os_memset(&csa_settings, 0, sizeof(csa_settings));
+ csa_settings.cs_count = 5;
+ csa_settings.block_tx = 0;
+ csa_settings.punct_bitmap = ch_switch->punct_bitmap;
+ csa_settings.link_id = ch_switch->link_id;
+
+ err = hostapd_set_freq_params(&csa_settings.freq_params,
+ iface->conf->hw_mode,
+ freq,
+ iface->conf->channel,
+ iface->conf->enable_edmg,
+ iface->conf->edmg_channel,
+ iface->conf->ieee80211n,
+ iface->conf->ieee80211ac,
+ iface->conf->ieee80211ax,
+ iface->conf->ieee80211be,
+ iface->conf->secondary_channel,
+ hostapd_get_oper_chwidth(iface->conf),
+ hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
+ hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
+ cmode->vht_capab,
+ &cmode->he_capab[IEEE80211_MODE_AP],
+ &cmode->eht_capab[IEEE80211_MODE_AP],
+ ch_switch->punct_bitmap);
+
+ if (err) {
+ wpa_printf(MSG_ERROR,
+ "Failed to calculate CSA freq params");
+ hostapd_disable_iface(iface);
+ return;
+ }
+
+ for (i = 0; i < iface->num_bss; i++) {
+ ieee802_11_set_bss_critical_update(iface->bss[i],
+ BSS_CRIT_UPDATE_EVENT_CSA);
+
+ err = hostapd_switch_channel(iface->bss[i], &csa_settings);
+ if (err)
+ break;
+
+#ifdef CONFIG_IEEE80211BE
+ if (iface->bss[i]->conf->mld_ap)
+ hostapd_update_aff_link_beacon(iface->bss[i],
+ csa_settings.cs_count);
+
+ /* FIXME:
+ * CU flag should be cleared when receiving DTIM event from FW
+ */
+ iface->bss[i]->eht_mld_bss_critical_update = 0;
+#endif /* CONFIG_IEEE80211BE */
+ }
+}
+
+
void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
@@ -2759,6 +2835,12 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
hostapd_event_dfs_cac_started(hapd, &data->dfs_event);
break;
#endif /* NEED_AP_MLME */
+ case EVENT_PP_BITMAP_UPDATE:
+ if (!data)
+ break;
+ hapd = switch_link_hapd(hapd, data->ch_switch.link_id);
+ hostapd_event_pp_bitmap_update(hapd, &data->ch_switch);
+ break;
case EVENT_INTERFACE_ENABLED:
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
if (hapd->disabled && hapd->started) {
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
index 937b968d5..933f0099d 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -22,6 +22,10 @@ enum mtk_nl80211_vendor_subcmds {
MTK_NL80211_VENDOR_SUBCMD_EML_CTRL = 0xd3,
};
+enum mtk_nl80211_vendor_subevents {
+ MTK_NL80211_VENDOR_EVENT_PP_BMP_UPDATE = 0x5,
+};
+
enum mtk_vendor_attr_edcca_ctrl {
MTK_VENDOR_ATTR_EDCCA_THRESHOLD_INVALID = 0,
@@ -271,7 +275,9 @@ enum mtk_vendor_attr_pp_ctrl {
MTK_VENDOR_ATTR_PP_CTRL_UNSPEC,
MTK_VENDOR_ATTR_PP_MODE,
- MTK_VENDOR_ATTR_PP_BAND_IDX,
+ MTK_VENDOR_ATTR_PP_LINK_ID,
+ MTK_VENDOR_ATTR_PP_BITMAP,
+ MTK_VENDOR_ATTR_PP_CURR_FREQ,
/* keep last */
NUM_MTK_VENDOR_ATTRS_PP_CTRL,
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index dacf0a98d..5e65d9e0b 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -5381,9 +5381,10 @@ struct wpa_driver_ops {
* pp_mode_set - Set preamble puncture operation mode
* @priv: Private driver interface data
* @pp_mode: Value is defined in enum pp_mode
- * @band_idx: chip band index
+ * @link_id: MLD link id. -1 if this is an non-MLD AP
+ * @punct_bitmap: current puncture bitmap
*/
- int (*pp_mode_set)(void *priv, const u8 pp_mode, u8 band_idx);
+ int (*pp_mode_set)(void *priv, const u8 pp_mode, s8 link_id, u16 punct_bitmap);
#ifdef CONFIG_IEEE80211BE
int (*get_mld_addr)(void *priv, u8 *addr);
#endif
@@ -6058,6 +6059,12 @@ enum wpa_event_type {
* channel has been updated and operating channel should expand its width.
*/
EVENT_DFS_BACKGROUND_CHAN_EXPAND,
+
+ /**
+ * EVENT_PP_BITMAP_UPDATE - Notification that the new puncture bitmap
+ * has been applied and a channel switch should be triggered.
+ */
+ EVENT_PP_BITMAP_UPDATE,
};
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 80fe2e591..5d97317f7 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -160,7 +160,9 @@ amnt_dump_policy[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP] = {
static struct nla_policy
pp_ctrl_policy[NUM_MTK_VENDOR_ATTRS_PP_CTRL] = {
[MTK_VENDOR_ATTR_PP_MODE] = { .type = NLA_U8 },
- [MTK_VENDOR_ATTR_PP_BAND_IDX] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_PP_LINK_ID] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_PP_BITMAP] = { .type = NLA_U16 },
+ [MTK_VENDOR_ATTR_PP_CURR_FREQ] = { .type = NLA_U32 },
};
static struct nla_policy csi_ctrl_policy[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = {
@@ -15248,7 +15250,7 @@ static int nl80211_background_radar_mode(void *priv, const u8 background_radar_m
return ret;
}
-static int nl80211_pp_mode_set(void *priv, const u8 pp_mode, u8 band_idx)
+static int nl80211_pp_mode_set(void *priv, const u8 pp_mode, s8 link_id, u16 punct_bitmap)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -15275,8 +15277,10 @@ static int nl80211_pp_mode_set(void *priv, const u8 pp_mode, u8 band_idx)
if (!data)
goto fail;
- nla_put_u8(msg, MTK_VENDOR_ATTR_PP_BAND_IDX, band_idx);
+ if (link_id > -1)
+ nla_put_u8(msg, MTK_VENDOR_ATTR_PP_LINK_ID, link_id);
nla_put_u8(msg, MTK_VENDOR_ATTR_PP_MODE, pp_mode);
+ nla_put_u16(msg, MTK_VENDOR_ATTR_PP_BITMAP, punct_bitmap);
nla_nest_end(msg, data);
ret = send_and_recv_cmd(drv, msg);
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index e95593a5b..efdb8ef7f 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -19,6 +19,7 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "driver_nl80211.h"
+#include "common/mtk_vendor.h"
static void
@@ -3332,6 +3333,50 @@ static void nl80211_vendor_event_brcm(struct wpa_driver_nl80211_data *drv,
#endif /* CONFIG_DRIVER_NL80211_BRCM */
+static void mtk_nl80211_pp_bitmap_update(struct wpa_driver_nl80211_data *drv,
+ const u8 *data, size_t len)
+{
+ struct nlattr *tb[MTK_VENDOR_ATTR_PP_CTRL_MAX + 1];
+ union wpa_event_data event;
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: MTK pp bitmap update vendor event received");
+
+ if (nla_parse(tb, MTK_VENDOR_ATTR_PP_CTRL_MAX,
+ (struct nlattr *) data, len, NULL) ||
+ !tb[MTK_VENDOR_ATTR_PP_CURR_FREQ] ||
+ !tb[MTK_VENDOR_ATTR_PP_BITMAP])
+ return;
+
+ os_memset(&event, 0, sizeof(event));
+ event.ch_switch.freq = nla_get_u32(tb[MTK_VENDOR_ATTR_PP_CURR_FREQ]);
+
+ event.ch_switch.link_id =
+ nl80211_get_link_id_by_freq(drv->first_bss, event.ch_switch.freq);
+ event.ch_switch.punct_bitmap =
+ nla_get_u16(tb[MTK_VENDOR_ATTR_PP_BITMAP]);
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: puncture bitmap: 0x%04x, link_id: %d",
+ event.ch_switch.punct_bitmap, event.ch_switch.link_id);
+ wpa_supplicant_event(drv->ctx, EVENT_PP_BITMAP_UPDATE, &event);
+}
+
+static void nl80211_vendor_event_mtk(struct wpa_driver_nl80211_data *drv,
+ u32 subcmd, u8 *data, size_t len)
+{
+ wpa_printf(MSG_DEBUG, "nl80211: Got MTK vendor event %u", subcmd);
+ switch (subcmd) {
+ case MTK_NL80211_VENDOR_EVENT_PP_BMP_UPDATE:
+ mtk_nl80211_pp_bitmap_update(drv, data, len);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG,
+ "%s: Ignore unsupported MTK vendor event %u",
+ __func__, subcmd);
+ break;
+ }
+}
static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
struct nlattr **tb)
@@ -3388,6 +3433,9 @@ static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
nl80211_vendor_event_brcm(drv, subcmd, data, len);
break;
#endif /* CONFIG_DRIVER_NL80211_BRCM */
+ case OUI_MTK:
+ nl80211_vendor_event_mtk(drv, subcmd, data, len);
+ break;
default:
wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event");
break;
--
2.18.0