Skip to content

Commit 39dc8b8

Browse files
committed
wifi: mac80211: pass parsed TPE data to drivers
Instead of passing the full TPE elements, in all their glory and mixed up data formats for HE backward compatibility, parse them fully into the right values, and pass that to the drivers. Also introduce proper validation already in mac80211, so that drivers don't need to do it, and parse the EHT portions. The code now passes the values in the right order according to the channel used by an interface, which could also be a subset of the data advertised by the AP, if we couldn't connect with the full bandwidth (for whatever reason.) Also add kunit tests for the more complicated bits of it. Reviewed-by: Miriam Rachel Korenblit <[email protected]> Acked-by: Kalle Valo <[email protected]> Link: https://msgid.link/20240506214536.2aa839969b60.I265b28209e0b29772b2f125f7f83de44a4da877b@changeid Signed-off-by: Johannes Berg <[email protected]>
1 parent caa12b3 commit 39dc8b8

File tree

9 files changed

+761
-171
lines changed

9 files changed

+761
-171
lines changed

drivers/net/wireless/ath/ath11k/mac.c

Lines changed: 34 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -7507,32 +7507,6 @@ static int ath11k_mac_stop_vdev_early(struct ieee80211_hw *hw,
75077507
return 0;
75087508
}
75097509

7510-
static u8 ath11k_mac_get_tpe_count(u8 txpwr_intrprt, u8 txpwr_cnt)
7511-
{
7512-
switch (txpwr_intrprt) {
7513-
/* Refer "Table 9-276-Meaning of Maximum Transmit Power Count subfield
7514-
* if the Maximum Transmit Power Interpretation subfield is 0 or 2" of
7515-
* "IEEE Std 802.11ax 2021".
7516-
*/
7517-
case IEEE80211_TPE_LOCAL_EIRP:
7518-
case IEEE80211_TPE_REG_CLIENT_EIRP:
7519-
txpwr_cnt = txpwr_cnt <= 3 ? txpwr_cnt : 3;
7520-
txpwr_cnt = txpwr_cnt + 1;
7521-
break;
7522-
/* Refer "Table 9-277-Meaning of Maximum Transmit Power Count subfield
7523-
* if Maximum Transmit Power Interpretation subfield is 1 or 3" of
7524-
* "IEEE Std 802.11ax 2021".
7525-
*/
7526-
case IEEE80211_TPE_LOCAL_EIRP_PSD:
7527-
case IEEE80211_TPE_REG_CLIENT_EIRP_PSD:
7528-
txpwr_cnt = txpwr_cnt <= 4 ? txpwr_cnt : 4;
7529-
txpwr_cnt = txpwr_cnt ? (BIT(txpwr_cnt - 1)) : 1;
7530-
break;
7531-
}
7532-
7533-
return txpwr_cnt;
7534-
}
7535-
75367510
static u8 ath11k_mac_get_num_pwr_levels(struct cfg80211_chan_def *chan_def)
75377511
{
75387512
if (chan_def->chan->flags & IEEE80211_CHAN_PSD) {
@@ -7859,33 +7833,23 @@ static void ath11k_mac_parse_tx_pwr_env(struct ath11k *ar,
78597833
struct ath11k_base *ab = ar->ab;
78607834
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
78617835
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
7862-
struct ieee80211_tx_pwr_env *single_tpe;
7836+
struct ieee80211_parsed_tpe_eirp *non_psd = NULL;
7837+
struct ieee80211_parsed_tpe_psd *psd = NULL;
78637838
enum wmi_reg_6ghz_client_type client_type;
78647839
struct cur_regulatory_info *reg_info;
7840+
u8 local_tpe_count, reg_tpe_count;
7841+
bool use_local_tpe;
78657842
int i;
7866-
u8 pwr_count, pwr_interpret, pwr_category;
7867-
u8 psd_index = 0, non_psd_index = 0, local_tpe_count = 0, reg_tpe_count = 0;
7868-
bool use_local_tpe, non_psd_set = false, psd_set = false;
78697843

78707844
reg_info = &ab->reg_info_store[ar->pdev_idx];
78717845
client_type = reg_info->client_type;
78727846

7873-
for (i = 0; i < bss_conf->tx_pwr_env_num; i++) {
7874-
single_tpe = &bss_conf->tx_pwr_env[i];
7875-
pwr_category = u8_get_bits(single_tpe->tx_power_info,
7876-
IEEE80211_TX_PWR_ENV_INFO_CATEGORY);
7877-
pwr_interpret = u8_get_bits(single_tpe->tx_power_info,
7878-
IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
7879-
7880-
if (pwr_category == client_type) {
7881-
if (pwr_interpret == IEEE80211_TPE_LOCAL_EIRP ||
7882-
pwr_interpret == IEEE80211_TPE_LOCAL_EIRP_PSD)
7883-
local_tpe_count++;
7884-
else if (pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP ||
7885-
pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP_PSD)
7886-
reg_tpe_count++;
7887-
}
7888-
}
7847+
local_tpe_count =
7848+
bss_conf->tpe.max_local[client_type].valid +
7849+
bss_conf->tpe.psd_local[client_type].valid;
7850+
reg_tpe_count =
7851+
bss_conf->tpe.max_reg_client[client_type].valid +
7852+
bss_conf->tpe.psd_reg_client[client_type].valid;
78897853

78907854
if (!reg_tpe_count && !local_tpe_count) {
78917855
ath11k_warn(ab,
@@ -7898,83 +7862,44 @@ static void ath11k_mac_parse_tx_pwr_env(struct ath11k *ar,
78987862
use_local_tpe = false;
78997863
}
79007864

7901-
for (i = 0; i < bss_conf->tx_pwr_env_num; i++) {
7902-
single_tpe = &bss_conf->tx_pwr_env[i];
7903-
pwr_category = u8_get_bits(single_tpe->tx_power_info,
7904-
IEEE80211_TX_PWR_ENV_INFO_CATEGORY);
7905-
pwr_interpret = u8_get_bits(single_tpe->tx_power_info,
7906-
IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
7907-
7908-
if (pwr_category != client_type)
7909-
continue;
7910-
7911-
/* get local transmit power envelope */
7912-
if (use_local_tpe) {
7913-
if (pwr_interpret == IEEE80211_TPE_LOCAL_EIRP) {
7914-
non_psd_index = i;
7915-
non_psd_set = true;
7916-
} else if (pwr_interpret == IEEE80211_TPE_LOCAL_EIRP_PSD) {
7917-
psd_index = i;
7918-
psd_set = true;
7919-
}
7920-
/* get regulatory transmit power envelope */
7921-
} else {
7922-
if (pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP) {
7923-
non_psd_index = i;
7924-
non_psd_set = true;
7925-
} else if (pwr_interpret == IEEE80211_TPE_REG_CLIENT_EIRP_PSD) {
7926-
psd_index = i;
7927-
psd_set = true;
7928-
}
7929-
}
7865+
if (use_local_tpe) {
7866+
psd = &bss_conf->tpe.psd_local[client_type];
7867+
if (!psd->valid)
7868+
psd = NULL;
7869+
non_psd = &bss_conf->tpe.max_local[client_type];
7870+
if (!non_psd->valid)
7871+
non_psd = NULL;
7872+
} else {
7873+
psd = &bss_conf->tpe.psd_reg_client[client_type];
7874+
if (!psd->valid)
7875+
psd = NULL;
7876+
non_psd = &bss_conf->tpe.max_reg_client[client_type];
7877+
if (!non_psd->valid)
7878+
non_psd = NULL;
79307879
}
79317880

7932-
if (non_psd_set && !psd_set) {
7933-
single_tpe = &bss_conf->tx_pwr_env[non_psd_index];
7934-
pwr_count = u8_get_bits(single_tpe->tx_power_info,
7935-
IEEE80211_TX_PWR_ENV_INFO_COUNT);
7936-
pwr_interpret = u8_get_bits(single_tpe->tx_power_info,
7937-
IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
7881+
if (non_psd && !psd) {
79387882
arvif->reg_tpc_info.is_psd_power = false;
79397883
arvif->reg_tpc_info.eirp_power = 0;
79407884

7941-
arvif->reg_tpc_info.num_pwr_levels =
7942-
ath11k_mac_get_tpe_count(pwr_interpret, pwr_count);
7885+
arvif->reg_tpc_info.num_pwr_levels = non_psd->count;
79437886

79447887
for (i = 0; i < arvif->reg_tpc_info.num_pwr_levels; i++) {
79457888
ath11k_dbg(ab, ATH11K_DBG_MAC,
79467889
"non PSD power[%d] : %d\n",
7947-
i, single_tpe->tx_power[i]);
7948-
arvif->reg_tpc_info.tpe[i] = single_tpe->tx_power[i] / 2;
7890+
i, non_psd->power[i]);
7891+
arvif->reg_tpc_info.tpe[i] = non_psd->power[i] / 2;
79497892
}
79507893
}
79517894

7952-
if (psd_set) {
7953-
single_tpe = &bss_conf->tx_pwr_env[psd_index];
7954-
pwr_count = u8_get_bits(single_tpe->tx_power_info,
7955-
IEEE80211_TX_PWR_ENV_INFO_COUNT);
7956-
pwr_interpret = u8_get_bits(single_tpe->tx_power_info,
7957-
IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
7958-
arvif->reg_tpc_info.is_psd_power = true;
7895+
if (psd) {
7896+
arvif->reg_tpc_info.num_pwr_levels = psd->count;
79597897

7960-
if (pwr_count == 0) {
7898+
for (i = 0; i < arvif->reg_tpc_info.num_pwr_levels; i++) {
79617899
ath11k_dbg(ab, ATH11K_DBG_MAC,
7962-
"TPE PSD power : %d\n", single_tpe->tx_power[0]);
7963-
arvif->reg_tpc_info.num_pwr_levels =
7964-
ath11k_mac_get_num_pwr_levels(&ctx->def);
7965-
7966-
for (i = 0; i < arvif->reg_tpc_info.num_pwr_levels; i++)
7967-
arvif->reg_tpc_info.tpe[i] = single_tpe->tx_power[0] / 2;
7968-
} else {
7969-
arvif->reg_tpc_info.num_pwr_levels =
7970-
ath11k_mac_get_tpe_count(pwr_interpret, pwr_count);
7971-
7972-
for (i = 0; i < arvif->reg_tpc_info.num_pwr_levels; i++) {
7973-
ath11k_dbg(ab, ATH11K_DBG_MAC,
7974-
"TPE PSD power[%d] : %d\n",
7975-
i, single_tpe->tx_power[i]);
7976-
arvif->reg_tpc_info.tpe[i] = single_tpe->tx_power[i] / 2;
7977-
}
7900+
"TPE PSD power[%d] : %d\n",
7901+
i, psd->power[i]);
7902+
arvif->reg_tpc_info.tpe[i] = psd->power[i] / 2;
79787903
}
79797904
}
79807905
}

include/linux/ieee80211.h

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2825,17 +2825,6 @@ struct ieee80211_he_6ghz_oper {
28252825
u8 minrate;
28262826
} __packed;
28272827

2828-
/*
2829-
* In "9.4.2.161 Transmit Power Envelope element" of "IEEE Std 802.11ax-2021",
2830-
* it show four types in "Table 9-275a-Maximum Transmit Power Interpretation
2831-
* subfield encoding", and two category for each type in "Table E-12-Regulatory
2832-
* Info subfield encoding in the United States".
2833-
* So it it totally max 8 Transmit Power Envelope element.
2834-
*/
2835-
#define IEEE80211_TPE_MAX_IE_COUNT 8
2836-
2837-
#define IEEE80211_TPE_MAX_POWER_COUNT 8
2838-
28392828
/* transmit power interpretation type of transmit power envelope element */
28402829
enum ieee80211_tx_power_intrpt_type {
28412830
IEEE80211_TPE_LOCAL_EIRP,
@@ -2844,24 +2833,107 @@ enum ieee80211_tx_power_intrpt_type {
28442833
IEEE80211_TPE_REG_CLIENT_EIRP_PSD,
28452834
};
28462835

2836+
/* category type of transmit power envelope element */
2837+
enum ieee80211_tx_power_category_6ghz {
2838+
IEEE80211_TPE_CAT_6GHZ_DEFAULT = 0,
2839+
IEEE80211_TPE_CAT_6GHZ_SUBORDINATE = 1,
2840+
};
2841+
2842+
/*
2843+
* For IEEE80211_TPE_LOCAL_EIRP / IEEE80211_TPE_REG_CLIENT_EIRP,
2844+
* setting to 63.5 dBm means no constraint.
2845+
*/
2846+
#define IEEE80211_TPE_MAX_TX_PWR_NO_CONSTRAINT 127
2847+
2848+
/*
2849+
* For IEEE80211_TPE_LOCAL_EIRP_PSD / IEEE80211_TPE_REG_CLIENT_EIRP_PSD,
2850+
* setting to 127 indicates no PSD limit for the 20 MHz channel.
2851+
*/
2852+
#define IEEE80211_TPE_PSD_NO_LIMIT 127
2853+
28472854
/**
28482855
* struct ieee80211_tx_pwr_env - Transmit Power Envelope
2849-
* @tx_power_info: Transmit Power Information field
2850-
* @tx_power: Maximum Transmit Power field
2856+
* @info: Transmit Power Information field
2857+
* @variable: Maximum Transmit Power field
28512858
*
28522859
* This structure represents the payload of the "Transmit Power
28532860
* Envelope element" as described in IEEE Std 802.11ax-2021 section
28542861
* 9.4.2.161
28552862
*/
28562863
struct ieee80211_tx_pwr_env {
2857-
u8 tx_power_info;
2858-
s8 tx_power[IEEE80211_TPE_MAX_POWER_COUNT];
2864+
u8 info;
2865+
u8 variable[];
28592866
} __packed;
28602867

28612868
#define IEEE80211_TX_PWR_ENV_INFO_COUNT 0x7
28622869
#define IEEE80211_TX_PWR_ENV_INFO_INTERPRET 0x38
28632870
#define IEEE80211_TX_PWR_ENV_INFO_CATEGORY 0xC0
28642871

2872+
#define IEEE80211_TX_PWR_ENV_EXT_COUNT 0xF
2873+
2874+
static inline bool ieee80211_valid_tpe_element(const u8 *data, u8 len)
2875+
{
2876+
const struct ieee80211_tx_pwr_env *env = (const void *)data;
2877+
u8 count, interpret, category;
2878+
u8 needed = sizeof(*env);
2879+
u8 N; /* also called N in the spec */
2880+
2881+
if (len < needed)
2882+
return false;
2883+
2884+
count = u8_get_bits(env->info, IEEE80211_TX_PWR_ENV_INFO_COUNT);
2885+
interpret = u8_get_bits(env->info, IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
2886+
category = u8_get_bits(env->info, IEEE80211_TX_PWR_ENV_INFO_CATEGORY);
2887+
2888+
switch (category) {
2889+
case IEEE80211_TPE_CAT_6GHZ_DEFAULT:
2890+
case IEEE80211_TPE_CAT_6GHZ_SUBORDINATE:
2891+
break;
2892+
default:
2893+
return false;
2894+
}
2895+
2896+
switch (interpret) {
2897+
case IEEE80211_TPE_LOCAL_EIRP:
2898+
case IEEE80211_TPE_REG_CLIENT_EIRP:
2899+
if (count > 3)
2900+
return false;
2901+
2902+
/* count == 0 encodes 1 value for 20 MHz, etc. */
2903+
needed += count + 1;
2904+
2905+
if (len < needed)
2906+
return false;
2907+
2908+
/* there can be extension fields not accounted for in 'count' */
2909+
2910+
return true;
2911+
case IEEE80211_TPE_LOCAL_EIRP_PSD:
2912+
case IEEE80211_TPE_REG_CLIENT_EIRP_PSD:
2913+
if (count > 4)
2914+
return false;
2915+
2916+
N = count ? 1 << (count - 1) : 1;
2917+
needed += N;
2918+
2919+
if (len < needed)
2920+
return false;
2921+
2922+
if (len > needed) {
2923+
u8 K = u8_get_bits(env->variable[N],
2924+
IEEE80211_TX_PWR_ENV_EXT_COUNT);
2925+
2926+
needed += 1 + K;
2927+
if (len < needed)
2928+
return false;
2929+
}
2930+
2931+
return true;
2932+
}
2933+
2934+
return false;
2935+
}
2936+
28652937
/*
28662938
* ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size
28672939
* @he_oper_ie: byte data of the He Operations IE, stating from the byte

include/net/mac80211.h

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,39 @@ struct ieee80211_fils_discovery {
550550
u32 max_interval;
551551
};
552552

553+
#define IEEE80211_TPE_EIRP_ENTRIES_320MHZ 5
554+
struct ieee80211_parsed_tpe_eirp {
555+
bool valid;
556+
s8 power[IEEE80211_TPE_EIRP_ENTRIES_320MHZ];
557+
u8 count;
558+
};
559+
560+
#define IEEE80211_TPE_PSD_ENTRIES_320MHZ 16
561+
struct ieee80211_parsed_tpe_psd {
562+
bool valid;
563+
s8 power[IEEE80211_TPE_PSD_ENTRIES_320MHZ];
564+
u8 count, n;
565+
};
566+
567+
/**
568+
* struct ieee80211_parsed_tpe - parsed transmit power envelope information
569+
* @max_local: maximum local EIRP, one value for 20, 40, 80, 160, 320 MHz each
570+
* (indexed by TX power category)
571+
* @max_reg_client: maximum regulatory client EIRP, one value for 20, 40, 80,
572+
* 160, 320 MHz each
573+
* (indexed by TX power category)
574+
* @psd_local: maximum local power spectral density, one value for each 20 MHz
575+
* subchannel per bss_conf's chanreq.oper
576+
* (indexed by TX power category)
577+
* @psd_reg_client: maximum regulatory power spectral density, one value for
578+
* each 20 MHz subchannel per bss_conf's chanreq.oper
579+
* (indexed by TX power category)
580+
*/
581+
struct ieee80211_parsed_tpe {
582+
struct ieee80211_parsed_tpe_eirp max_local[2], max_reg_client[2];
583+
struct ieee80211_parsed_tpe_psd psd_local[2], psd_reg_client[2];
584+
};
585+
553586
/**
554587
* struct ieee80211_bss_conf - holds the BSS's changing parameters
555588
*
@@ -662,8 +695,7 @@ struct ieee80211_fils_discovery {
662695
* @beacon_tx_rate: The configured beacon transmit rate that needs to be passed
663696
* to driver when rate control is offloaded to firmware.
664697
* @power_type: power type of BSS for 6 GHz
665-
* @tx_pwr_env: transmit power envelope array of BSS.
666-
* @tx_pwr_env_num: number of @tx_pwr_env.
698+
* @tpe: transmit power envelope information
667699
* @pwr_reduction: power constraint of BSS.
668700
* @eht_support: does this BSS support EHT
669701
* @csa_active: marks whether a channel switch is going on.
@@ -766,8 +798,9 @@ struct ieee80211_bss_conf {
766798
u32 unsol_bcast_probe_resp_interval;
767799
struct cfg80211_bitrate_mask beacon_tx_rate;
768800
enum ieee80211_ap_reg_power power_type;
769-
struct ieee80211_tx_pwr_env tx_pwr_env[IEEE80211_TPE_MAX_IE_COUNT];
770-
u8 tx_pwr_env_num;
801+
802+
struct ieee80211_parsed_tpe tpe;
803+
771804
u8 pwr_reduction;
772805
bool eht_support;
773806

0 commit comments

Comments
 (0)