[PATCH v8 5/5] hostapd: Update TPE IE according to AFC
Lorenzo Bianconi
lorenzo at kernel.org
Thu Nov 28 00:08:35 PST 2024
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 at nbd.name>
Tested-by: Allen Ye <allen.ye at mediatek.com>
Tested-by: Krishna Chaitanya <chaitanya.mgit at gmail.com>
Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
---
src/ap/afc.c | 41 +++++++++++++++++++++++++++++++++++++++
src/ap/hostapd.h | 9 +++++++++
src/ap/ieee802_11.c | 47 ++++++++++++++++++++++++++++-----------------
3 files changed, 79 insertions(+), 18 deletions(-)
diff --git a/src/ap/afc.c b/src/ap/afc.c
index 7dfd01346..27c2a8061 100644
--- a/src/ap/afc.c
+++ b/src/ap/afc.c
@@ -1107,3 +1107,44 @@ 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) {
+ int j;
+
+ *power = 0;
+ for (j = 0; j < ARRAY_SIZE(c->power); j++)
+ *power = MAX(*power, 2 * c->power[j]);
+ return 0;
+ }
+ }
+ }
+ return -EINVAL;
+}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index ff6dd40af..e47abf922 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -774,10 +774,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 c0da03f4c..f9fe3e355 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -7242,42 +7242,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.47.0
More information about the Hostap
mailing list