wlan-ap-Telecominfraproject/feeds/qca/hostapd/patches/n00-001-hostapd-add-support-for-6GHz-operation.patch
John Crispin 008ca9618d
Some checks failed
Build OpenWrt/uCentral images / build (cig_wf186h) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf186w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf188n) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf189) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf196) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cybertan_eww631-a1) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cybertan_eww631-b1) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap101) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap102) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap104) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap105) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap111) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap112) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101-6e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101e-6e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_3) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xe) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xi) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xi_w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (indio_um-305ax) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sercomm_ap72tip) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630c-311g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630w-211g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630w-311g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (udaya_a6-id2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (udaya_a6-od2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr5018) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr6018) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr6018-v4) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_ax820) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_ax840) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap640) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap650) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap655) (push) Has been cancelled
Build OpenWrt/uCentral images / trigger-testing (push) Has been cancelled
Build OpenWrt/uCentral images / create-x64_vm-ami (push) Has been cancelled
ipq95xx: import ath12.4-cs kernel and drivers
Signed-off-by: John Crispin <john@phrozen.org>
2024-10-20 09:25:13 +02:00

566 lines
19 KiB
Diff

From 404211da041eef5ddfc52515048b04c70ef8579c Mon Sep 17 00:00:00 2001
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Thu, 21 Oct 2021 12:51:38 +0530
Subject: [PATCH] hostapd: add support for 6GHz operation
6 GHz gives users ability to select the AP mode from LPI, SP and
VLP modes. This mode needs to be passed on to the cfg80211
for further processing during AP bring up. Also, the regulatory
rules received by hostapd contains psd values for 6G rules.
Hostapd needs to store these values in order to later advertise
it in the tx power element in the beacon.
This patch adds the support to send the user configured 6g power
type during set_channel command and as well to get and store the
psd values from reg rules which will be later on used in tpe
advertisement during beacon formation.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
---
src/ap/ap_drv_ops.c | 9 ++++++---
src/ap/beacon.c | 9 +++++++--
src/ap/dfs.c | 6 ++++--
src/ap/hostapd.c | 2 +-
src/ap/ieee802_11.c | 13 ++++++++++++-
src/ap/ieee802_11_he.c | 10 ++++++++--
src/common/hw_features_common.c | 4 +++-
src/common/hw_features_common.h | 2 +-
src/common/ieee802_11_defs.h | 14 ++++++++++++++
src/drivers/driver.h | 20 +++++++++++++++++++-
src/drivers/driver_hostap.c | 3 ++-
src/drivers/driver_nl80211.c | 15 ++++++++++++++-
src/drivers/driver_nl80211.h | 2 +-
src/drivers/driver_nl80211_capa.c | 28 +++++++++++++++++++++++-----
src/drivers/driver_nl80211_event.c | 2 +-
src/drivers/nl80211_copy.h | 19 +++++++++++++++++++
wpa_supplicant/driver_i.h | 2 +-
wpa_supplicant/mesh.c | 2 +-
wpa_supplicant/wpa_supplicant.c | 2 +-
19 files changed, 138 insertions(+), 26 deletions(-)
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3580,6 +3580,15 @@ static int hostapd_config_fill(struct ho
}
} else if (os_strcmp(buf, "he_6ghz_reg_pwr_type") == 0) {
conf->he_6ghz_reg_pwr_type = atoi(pos);
+ if (conf->he_6ghz_reg_pwr_type > HE_6GHZ_VERY_LOW_POWER_AP ||
+ conf->he_6ghz_reg_pwr_type < HE_6GHZ_INDOOR_AP) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid 6ghz regulatory power type('%s') "
+ "[min: %d and max: %d]",
+ line, pos, HE_6GHZ_INDOOR_AP,
+ HE_6GHZ_VERY_LOW_POWER_AP);
+ return 1;
+ }
} else if (os_strcmp(buf, "he_oper_chwidth") == 0) {
conf->he_oper_chwidth = atoi(pos);
} else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) {
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -588,7 +588,8 @@ int hostapd_set_freq(struct hostapd_data
&cmode->he_capab[IEEE80211_MODE_AP] : NULL,
cmode ?
&cmode->eht_capab[IEEE80211_MODE_AP] :
- NULL))
+ NULL,
+ hapd->iconf->he_6ghz_reg_pwr_type))
return -1;
if (hapd->driver == NULL)
@@ -681,7 +682,8 @@ hostapd_get_hw_feature_data(struct hosta
!hapd->drv_priv)
return NULL;
return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
- flags, dfs_domain);
+ flags, dfs_domain,
+ hapd->iconf->he_6ghz_reg_pwr_type);
}
@@ -905,7 +907,8 @@ int hostapd_start_dfs_cac(struct hostapd
center_segment1,
cmode->vht_capab,
&cmode->he_capab[IEEE80211_MODE_AP],
- &cmode->eht_capab[IEEE80211_MODE_AP])) {
+ &cmode->eht_capab[IEEE80211_MODE_AP],
+ hapd->iconf->he_6ghz_reg_pwr_type)) {
wpa_printf(MSG_ERROR, "Can't set freq params");
return -1;
}
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -2183,7 +2183,8 @@ static int __ieee802_11_set_beacon(struc
hostapd_get_oper_centr_freq_seg1_idx(iconf),
cmode->vht_capab,
&cmode->he_capab[IEEE80211_MODE_AP],
- &cmode->eht_capab[IEEE80211_MODE_AP]) == 0)
+ &cmode->eht_capab[IEEE80211_MODE_AP],
+ iconf->he_6ghz_reg_pwr_type) == 0)
params.freq = &freq;
for (i = 0; i < hapd->iface->num_hw_features; i++) {
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1081,7 +1081,8 @@ static int hostapd_dfs_request_channel_s
oper_centr_freq_seg1_idx,
cmode->vht_capab,
&cmode->he_capab[ieee80211_mode],
- &cmode->eht_capab[ieee80211_mode]);
+ &cmode->eht_capab[ieee80211_mode],
+ iface->conf->he_6ghz_reg_pwr_type);
if (err) {
wpa_printf(MSG_ERROR,
@@ -1226,7 +1227,8 @@ static int hostapd_dfs_testmode_set_beac
vht_oper_centr_freq_seg1_idx,
iface->current_mode->vht_capab,
&iface->current_mode->he_capab[IEEE80211_MODE_AP],
- &iface->current_mode->eht_capab[IEEE80211_MODE_AP]);
+ &iface->current_mode->eht_capab[IEEE80211_MODE_AP],
+ iface->conf->he_6ghz_reg_pwr_type);
if (err) {
wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -3889,7 +3889,8 @@ static int hostapd_change_config_freq(st
mode ? &mode->he_capab[IEEE80211_MODE_AP] :
NULL,
mode ? &mode->eht_capab[IEEE80211_MODE_AP] :
- NULL))
+ NULL,
+ hapd->iconf->he_6ghz_reg_pwr_type))
return -1;
switch (params->bandwidth) {
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -6909,6 +6909,7 @@ void ieee802_11_rx_from_unknown(struct h
#define REG_APL1_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_LPI 2 /* dBm/MHz */
#define REG_APL1_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_VLP 1 /* dBm/MHz */
+#ifndef REG_DOM_SUPPORT_TX_POWER
static u8 hostapd_get_6g_tx_power(struct hostapd_data *hapd, u8 ap_type, u8 tx_pwr_cat)
{
char country[3];
@@ -6949,6 +6950,7 @@ static u8 hostapd_get_6g_tx_power(struct
ap_type, country);
return 0;
}
+#endif
static u8 * hostapd_add_tpe_info(u8 *eid, u8 tx_pwr_count,
enum max_tx_pwr_interpretation tx_pwr_intrpn,
@@ -6984,6 +6986,7 @@ u8 * hostapd_eid_txpower_envelope(struct
u8 channel, tx_pwr_count, local_pwr_constraint;
int max_tx_power;
u8 tx_pwr;
+ s8 psd;
if (!mode)
return eid;
@@ -7015,20 +7018,30 @@ u8 * hostapd_eid_txpower_envelope(struct
tx_pwr_count = 0;
tx_pwr_intrpn = REGULATORY_CLIENT_EIRP_PSD;
- /* Default Transmit Power Envelope for Global Operating Class */
- tx_pwr = (hostapd_get_6g_tx_power(hapd,
- iconf->he_6ghz_reg_pwr_type,
- REG_DEFAULT_CLIENT) * 2);
+ psd = mode->psd_values[NL80211_REG_REGULAR_CLIENT_LPI +
+ iconf->he_6ghz_reg_pwr_type];
+#ifdef REG_DOM_SUPPORT_TX_POWER
+ tx_pwr = psd * 2;
+#else
+ tx_pwr = (hostapd_get_6g_tx_power(hapd,
+ iconf->he_6ghz_reg_pwr_type,
+ REG_DEFAULT_CLIENT) * 2);
+#endif /* REG_DOM_SUPPORT_TX_POWER */
eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn,
REG_DEFAULT_CLIENT, tx_pwr);
/* Indoor Access Point must include an additional TPE for
* subordinate devices */
if (iconf->he_6ghz_reg_pwr_type == HE_6GHZ_INDOOR_AP) {
- /* TODO: Extract PSD limits from channel data */
- tx_pwr = (hostapd_get_6g_tx_power(hapd,
- iconf->he_6ghz_reg_pwr_type,
- REG_SUBORDINATE_CLIENT) * 2);
+ psd = mode->psd_values[NL80211_REG_SUBORDINATE_CLIENT_LPI +
+ iconf->he_6ghz_reg_pwr_type];
+#ifdef REG_DOM_SUPPORT_TX_POWER
+ tx_pwr = psd * 2;
+#else
+ tx_pwr = (hostapd_get_6g_tx_power(hapd,
+ iconf->he_6ghz_reg_pwr_type,
+ REG_SUBORDINATE_CLIENT) * 2);
+#endif /* REG_DOM_SUPPORT_TX_POWER */
eid = hostapd_add_tpe_info(eid, tx_pwr_count,
tx_pwr_intrpn,
REG_SUBORDINATE_CLIENT,
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -255,7 +255,10 @@ u8 * hostapd_eid_he_operation(struct hos
control = 3;
else
control = center_idx_to_bw_6ghz(seg0);
- if (hapd->iconf->he_6ghz_reg_pwr_type == 1)
+ if (hapd->iconf->he_6ghz_reg_pwr_type == 2)
+ control |= HE_6GHZ_VERY_LOW_POWER_AP <<
+ HE_6GHZ_OPER_INFO_CTRL_REG_INFO_SHIFT;
+ else if (hapd->iconf->he_6ghz_reg_pwr_type == 1)
control |= HE_6GHZ_STANDARD_POWER_AP <<
HE_6GHZ_OPER_INFO_CTRL_REG_INFO_SHIFT;
else
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -388,7 +388,8 @@ int hostapd_set_freq_params(struct hosta
int center_segment0,
int center_segment1, u32 vht_caps,
struct he_capabilities *he_cap,
- struct eht_capabilities *eht_cap)
+ struct eht_capabilities *eht_cap,
+ u8 reg_6g_pwr_mode)
{
if (!he_cap || !he_cap->he_supported)
he_enabled = 0;
@@ -484,6 +485,8 @@ int hostapd_set_freq_params(struct hosta
data->ht_enabled = 0;
data->vht_enabled = 0;
+ /* Append 6G reg power info */
+ data->he_6ghz_reg_pwr_type = reg_6g_pwr_mode;
return 0;
}
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -45,7 +45,8 @@ int hostapd_set_freq_params(struct hosta
int center_segment0,
int center_segment1, u32 vht_caps,
struct he_capabilities *he_caps,
- struct eht_capabilities *eht_cap);
+ struct eht_capabilities *eht_cap,
+ u8 reg_6g_pwr_mode);
void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps,
int disabled);
int ieee80211ac_cap_check(u32 hw, u32 conf);
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2009,6 +2009,16 @@ struct tpc_report {
} STRUCT_PACKED;
/*
+ * REG_DOM_SUPPORT_TX_POWER - regulatory domain
+ * supports tx power values or not.
+ *
+ * If this macro is undefined, tx-power macros will be used to
+ * get the tx-power, otherwise psd values from regulatory domain
+ * will be taken
+ */
+#define REG_DOM_SUPPORT_TX_POWER 1
+
+/*
* IEEE Std 802.11ax-2021, Table 9-275a - Maximum Transmit Power
* Interpretation subfield encoding
*/
@@ -2408,6 +2418,9 @@ enum he_6ghz_ap_type {
HE_6GHZ_VERY_LOW_POWER_AP = 2,
};
+#define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO 0x38
+#define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO_LSB 3
+
/* Spatial Reuse defines */
#define SPATIAL_REUSE_SRP_DISALLOWED BIT(0)
#define SPATIAL_REUSE_NON_SRG_OBSS_PD_SR_DISALLOWED BIT(1)
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -309,6 +309,12 @@ struct hostapd_hw_modes {
* eht_capab - EHT (IEEE 802.11be) capabilities
*/
struct eht_capabilities eht_capab[IEEE80211_MODE_NUM];
+
+ /**
+ * This array is used to store the psd value of each power mode
+ * supported in 6G band.
+ */
+ s8 psd_values[NL80211_REG_NUM_POWER_MODES];
};
@@ -844,6 +850,17 @@ struct hostapd_freq_params {
bool eht_enabled;
/**
+ * he_6ghz_reg_pwr_type - 6G regulatory power mode
+ * Since many operation related to channel for 6G depends on the
+ * power mode, this parameter is added here.
+ *
+ * 0 - LPI_AP
+ * 1 - SP_AP
+ * 2 - VLP_AP
+ */
+ u8 he_6ghz_reg_pwr_type;
+
+ /**
* link_id: If >=0 indicates the link of the AP MLD to configure
*/
int link_id;
@@ -3280,12 +3297,13 @@ struct wpa_driver_ops {
* @num_modes: Variable for returning the number of returned modes
* flags: Variable for returning hardware feature flags
* @dfs: Variable for returning DFS region (HOSTAPD_DFS_REGION_*)
+ * @pwr_mode: Variable required for processing the support data for 6G
* Returns: Pointer to allocated hardware data on success or %NULL on
* failure. Caller is responsible for freeing this.
*/
struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv,
u16 *num_modes,
- u16 *flags, u8 *dfs);
+ u16 *flags, u8 *dfs, u8 pwr_mode);
/**
* send_mlme - Send management frame from MLME
--- a/src/drivers/driver_hostap.c
+++ b/src/drivers/driver_hostap.c
@@ -1100,7 +1100,8 @@ static int hostap_sta_disassoc(void *pri
static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv,
u16 *num_modes,
- u16 *flags, u8 *dfs)
+ u16 *flags, u8 *dfs,
+ u8 pwr_mode)
{
struct hostapd_hw_modes *mode;
int i, clen, rlen;
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5420,6 +5420,20 @@ static int nl80211_set_channel(struct i8
return -1;
}
+#ifdef CONFIG_IEEE80211AX
+ if (freq->freq && is_6ghz_freq(freq->freq)) {
+ wpa_printf(MSG_DEBUG, "%s: 6g_reg_pwr_mode=%d",
+ __func__, freq->he_6ghz_reg_pwr_type);
+ if (nla_put_u8(msg, NL80211_ATTR_6G_REG_POWER_MODE,
+ freq->he_6ghz_reg_pwr_type)) {
+ wpa_printf(MSG_ERROR,
+ "%s: Failed to put 6g_reg_pwr_mode", __func__);
+ nlmsg_free(msg);
+ return -1;
+ }
+ }
+#endif /* CONFIG_IEEE80211AX */
+
if (nl80211_link_valid(bss, freq->link_id)) {
wpa_printf(MSG_DEBUG, "nl80211: Set link_id=%u for freq",
freq->link_id);
@@ -9059,7 +9073,7 @@ static int wpa_driver_nl80211_send_actio
int i;
modes = nl80211_get_hw_feature_data(bss, &num_modes,
- &flags, &dfs_domain);
+ &flags, &dfs_domain, 0);
if (dfs_domain != HOSTAPD_DFS_REGION_ETSI &&
ieee80211_is_dfs(bss->flink->freq, modes, num_modes))
offchanok = 0;
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -317,7 +317,7 @@ int nl80211_send_monitor(struct wpa_driv
int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv);
struct hostapd_hw_modes *
nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags,
- u8 *dfs_domain);
+ u8 *dfs_domain, u8 pwr_mode);
int process_global_event(struct nl_msg *msg, void *arg);
int process_bss_event(struct nl_msg *msg, void *arg);
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1574,6 +1574,7 @@ struct phy_info_arg {
int last_mode, last_chan_idx;
int failed;
u8 dfs_domain;
+ u8 pwr_mode;
};
static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
@@ -2266,7 +2267,9 @@ static void nl80211_set_ht40_mode_sec(st
static void nl80211_reg_rule_max_eirp(u32 start, u32 end, u32 max_eirp,
- struct phy_info_arg *results)
+ struct phy_info_arg *results,
+ u8 config_pwr_mode, u8 pwr_mode,
+ s8 psd)
{
u16 m;
@@ -2276,10 +2279,16 @@ static void nl80211_reg_rule_max_eirp(u3
for (c = 0; c < mode->num_channels; c++) {
struct hostapd_channel_data *chan = &mode->channels[c];
+
+ if (is_6ghz_freq(chan->freq) && config_pwr_mode != pwr_mode)
+ continue;
+
if ((u32) chan->freq - 10 >= start &&
(u32) chan->freq + 10 <= end)
chan->max_tx_power = max_eirp;
}
+ /* Update the psd rules */
+ mode->psd_values[pwr_mode] = psd;
}
}
@@ -2424,6 +2433,7 @@ static int nl80211_get_reg(struct nl_msg
[NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
};
+ u8 config_pwr_mode = results->pwr_mode;
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
if (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||
@@ -2448,6 +2458,8 @@ static int nl80211_get_reg(struct nl_msg
nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
{
u32 start, end, max_eirp = 0, max_bw = 0, flags = 0;
+ u8 pwr_mode = 0;
+ s8 psd = 0;
nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
nla_data(nl_rule), nla_len(nl_rule), reg_policy);
if (tb_rule[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
@@ -2461,9 +2473,13 @@ static int nl80211_get_reg(struct nl_msg
max_bw = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
if (tb_rule[NL80211_ATTR_REG_RULE_FLAGS])
flags = nla_get_u32(tb_rule[NL80211_ATTR_REG_RULE_FLAGS]);
+ if (tb_rule[NL80211_ATTR_REG_POWER_MODE])
+ pwr_mode = nla_get_u8(tb_rule[NL80211_ATTR_REG_POWER_MODE]);
+ if (tb_rule[NL80211_ATTR_POWER_RULE_PSD])
+ psd = (s8) nla_get_u8(tb_rule[NL80211_ATTR_POWER_RULE_PSD]);
- wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm%s%s%s%s%s%s%s%s",
- start, end, max_bw, max_eirp,
+ wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm pwr_mode: %u psd: %d%s%s%s%s%s%s%s%s",
+ start, end, max_bw, max_eirp, pwr_mode, psd,
flags & NL80211_RRF_NO_OFDM ? " (no OFDM)" : "",
flags & NL80211_RRF_NO_CCK ? " (no CCK)" : "",
flags & NL80211_RRF_NO_INDOOR ? " (no indoor)" : "",
@@ -2477,7 +2493,8 @@ static int nl80211_get_reg(struct nl_msg
nl80211_reg_rule_ht40(start, end, results);
if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
nl80211_reg_rule_max_eirp(start, end, max_eirp,
- results);
+ results, config_pwr_mode,
+ pwr_mode, psd);
}
nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
@@ -2581,7 +2598,7 @@ static void nl80211_dump_chan_list(struc
struct hostapd_hw_modes *
nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags,
- u8 *dfs_domain)
+ u8 *dfs_domain, u8 pwr_mode)
{
u32 feat;
struct i802_bss *bss = priv;
@@ -2594,6 +2611,7 @@ nl80211_get_hw_feature_data(void *priv,
.last_mode = -1,
.failed = 0,
.dfs_domain = 0,
+ .pwr_mode = pwr_mode
};
*num_modes = 0;
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -2580,7 +2580,7 @@ static unsigned int chan_to_freq(struct
int i;
modes = nl80211_get_hw_feature_data(drv->first_bss, &num_modes,
- &flags, &dfs_domain);
+ &flags, &dfs_domain, 0);
if (!modes) {
wpa_printf(MSG_DEBUG,
"nl80211: Fetching hardware mode failed");
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -3373,6 +3373,8 @@ enum nl80211_attrs {
NL80211_ATTR_AWGN_INTERFERENCE_BITMAP,
+ NL80211_ATTR_6G_REG_POWER_MODE,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -4127,6 +4129,20 @@ enum nl80211_band_attr {
#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
+enum nl80211_regulatory_power_modes {
+ NL80211_REG_AP_LPI,
+ NL80211_REG_AP_SP,
+ NL80211_REG_AP_VLP,
+ NL80211_REG_REGULAR_CLIENT_LPI,
+ NL80211_REG_REGULAR_CLIENT_SP,
+ NL80211_REG_REGULAR_CLIENT_VLP,
+ NL80211_REG_SUBORDINATE_CLIENT_LPI,
+ NL80211_REG_SUBORDINATE_CLIENT_SP,
+ NL80211_REG_SUBORDINATE_CLIENT_VLP,
+
+ NL80211_REG_NUM_POWER_MODES,
+};
+
/**
* enum nl80211_wmm_rule - regulatory wmm rule
*
@@ -4357,6 +4373,9 @@ enum nl80211_reg_type {
* a given frequency range. The value is in mBm (100 * dBm).
* @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
* If not present or 0 default CAC time will be used.
+ * @NL80211_ATTR_POWER_RULE_PSD: power spectral density (in dBm).
+ * This could be negative.
+ * @NL80211_ATTR_REG_POWER_MODE: the regulatory power mode for 6G rules
* @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
* currently defined
* @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
@@ -4374,6 +4393,10 @@ enum nl80211_reg_rule_attr {
NL80211_ATTR_DFS_CAC_TIME,
+ NL80211_ATTR_POWER_RULE_PSD,
+
+ NL80211_ATTR_REG_POWER_MODE,
+
/* keep last */
__NL80211_REG_RULE_ATTR_AFTER_LAST,
NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -309,7 +309,7 @@ wpa_drv_get_hw_feature_data(struct wpa_s
if (wpa_s->driver->get_hw_feature_data)
return wpa_s->driver->get_hw_feature_data(wpa_s->drv_priv,
num_modes, flags,
- dfs_domain);
+ dfs_domain, 0);
return NULL;
}
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -232,7 +232,8 @@ static int wpas_mesh_update_freq_params(
hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
ifmsh->conf->vht_capab,
- he_capab, NULL)) {
+ he_capab, NULL,
+ ifmsh->conf->he_6ghz_reg_pwr_type)) {
wpa_printf(MSG_ERROR, "Error updating mesh frequency params");
wpa_supplicant_mesh_deinit(wpa_s, true);
return -1;