| 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 |
| |