Update Transmit Power Envelope (TPE) IE according to the reply from AFC coordinator on UNII-5 or UNII-7 6GHz bands. Tested-by: Felix Fietkau <nbd@xxxxxxxx> Tested-by: Allen Ye <allen.ye@xxxxxxxxxxxx> Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> --- src/ap/afc.c | 37 +++++++++++++++++++++++++++++++++++ src/ap/hostapd.h | 9 +++++++++ src/ap/ieee802_11.c | 47 ++++++++++++++++++++++++++++----------------- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/src/ap/afc.c b/src/ap/afc.c index 21e1e17cb..053c8d267 100644 --- a/src/ap/afc.c +++ b/src/ap/afc.c @@ -994,3 +994,40 @@ void hostap_afc_disable_channels(struct hostapd_iface *iface) chan->freq); } } + + +int hostap_afc_get_chan_max_eirp_power(struct hostapd_iface *iface, bool psd, + int *power) +{ + int i; + + if (!he_reg_is_sp(iface->conf->he_6ghz_reg_pwr_type)) + return -EINVAL; + + if (!iface->afc.data_valid) + return -EINVAL; + + if (psd) { + for (i = 0; i < iface->afc.num_freq_range; i++) { + struct afc_freq_range_elem *f; + + f = &iface->afc.freq_range[i]; + if (iface->freq >= f->low_freq && + iface->freq <= f->high_freq) { + *power = 2 * f->max_psd; + return 0; + } + } + } else { + for (i = 0; i < iface->afc.num_chan_info; i++) { + struct afc_chan_info_elem *c; + + c = &iface->afc.chan_info_list[i]; + if (c->chan == iface->conf->channel) { + *power = 2 * c->power; + return 0; + } + } + } + return -EINVAL; +} diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 88d111022..5e8e10449 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -740,10 +740,19 @@ struct hostapd_iface { /* hostapd.c */ #ifdef CONFIG_AFC +int hostap_afc_get_chan_max_eirp_power(struct hostapd_iface *iface, bool psd, + int *power); int hostapd_afc_handle_request(struct hostapd_iface *iface); void hostapd_afc_stop(struct hostapd_iface *iface); void hostap_afc_disable_channels(struct hostapd_iface *iface); #else +static inline int +hostap_afc_get_chan_max_eirp_power(struct hostapd_iface *iface, bool psd, + int *power) +{ + return -EINVAL; +} + static inline int hostapd_afc_handle_request(struct hostapd_iface *iface) { return 1; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 85a39d5ff..df07405ed 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -7104,42 +7104,53 @@ u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid) */ if (is_6ghz_op_class(iconf->op_class)) { enum max_tx_pwr_interpretation tx_pwr_intrpn; + int err, max_eirp_psd, max_eirp_power; /* Same Maximum Transmit Power for all 20 MHz bands */ tx_pwr_count = 0; tx_pwr_intrpn = REGULATORY_CLIENT_EIRP_PSD; /* Default Transmit Power Envelope for Global Operating Class */ - if (hapd->iconf->reg_def_cli_eirp_psd != -1) - tx_pwr = hapd->iconf->reg_def_cli_eirp_psd; - else - tx_pwr = REG_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT * 2; + err = hostap_afc_get_chan_max_eirp_power(iface, true, + &max_eirp_psd); + if (err < 0) { + if (hapd->iconf->reg_def_cli_eirp_psd != -1) + max_eirp_psd = hapd->iconf->reg_def_cli_eirp_psd; + else + max_eirp_psd = REG_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT * 2; + } eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn, - REG_DEFAULT_CLIENT, tx_pwr); + REG_DEFAULT_CLIENT, max_eirp_psd); /* Indoor Access Point must include an additional TPE for * subordinate devices */ if (he_reg_is_indoor(iconf->he_6ghz_reg_pwr_type)) { - /* TODO: Extract PSD limits from channel data */ - if (hapd->iconf->reg_sub_cli_eirp_psd != -1) - tx_pwr = hapd->iconf->reg_sub_cli_eirp_psd; - else - tx_pwr = REG_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT * 2; + if (err < 0) { + /* non-AFC connection */ + if (hapd->iconf->reg_sub_cli_eirp_psd != -1) + max_eirp_psd = hapd->iconf->reg_sub_cli_eirp_psd; + else + max_eirp_psd = REG_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT * 2; + } eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn, REG_SUBORDINATE_CLIENT, - tx_pwr); + max_eirp_psd); } - if (iconf->reg_def_cli_eirp != -1 && - he_reg_is_sp(iconf->he_6ghz_reg_pwr_type)) - eid = hostapd_add_tpe_info( - eid, tx_pwr_count, REGULATORY_CLIENT_EIRP, - REG_DEFAULT_CLIENT, - hapd->iconf->reg_def_cli_eirp); + if (hostap_afc_get_chan_max_eirp_power(iface, false, + &max_eirp_power)) { + max_eirp_power = iconf->reg_def_cli_eirp; + if (max_eirp_power == -1 || + !he_reg_is_sp(iconf->he_6ghz_reg_pwr_type)) + return eid; + } - return eid; + return hostapd_add_tpe_info(eid, tx_pwr_count, + REGULATORY_CLIENT_EIRP, + REG_DEFAULT_CLIENT, + max_eirp_power); } #endif /* CONFIG_IEEE80211AX */ -- 2.44.0 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap