summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMukesh Sisodiya <mukesh.sisodiya@intel.com>2024-01-24 06:02:09 +0200
committeriwlwifi publisher <>2024-04-17 12:46:04 +0000
commitebec655ebe4ca87f67cf2f1b5a12dee7069d92d8 (patch)
treee6522ad604b3eb724b5dfa15b6bfb3e16ebecdcb
parent764f16c658c08614d300c763c817c2ca57627e26 (diff)
downloadbackport-iwlwifi-ebec655ebe4ca87f67cf2f1b5a12dee7069d92d8.tar.gz
wifi: mac80211: Refactor TPE element parsing and handling
TPE element is stored in one dimensional array and overwrite once more then eight elements are received. Refactor the TPE parsing and handling code based on the interpretation and category to modify the correct index once received Add the TPE elements validity check before parsing the data sent from AP type=feature ticket=jira:WIFI-309924 Signed-off-by: Mukesh Sisodiya <mukesh.sisodiya@intel.com> Change-Id: I5361ed88160f02e453829695caf20da63b96d037 Reviewed-on: https://gerritwcs.ir.intel.com/c/iwlwifi-stack-dev/+/91140 tested: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM> Tested-by: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com> x-iwlwifi-stack-dev: 359018c1e16b1f71890d112924e4f8e688eeff8c
-rw-r--r--include/linux/ieee80211.h58
-rw-r--r--include/net/mac80211.h8
-rw-r--r--net/mac80211/ieee80211_i.h7
-rw-r--r--net/mac80211/mlme.c26
-rw-r--r--net/mac80211/parse.c27
-rw-r--r--versions2
6 files changed, 101 insertions, 27 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 4b072dcf44..ee8597ce9b 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2802,6 +2802,10 @@ struct ieee80211_he_6ghz_oper {
#define IEEE80211_MAX_NUM_PWR_LEVEL 8
#define IEEE80211_TPE_MAX_POWER_COUNT 8
+#define IEEE80211_TPE_MAX_EIRP_COUNT 3
+#define IEEE80211_TPE_MAX_EIRP_PSD_COUNT 4
+#define IEEE80211_TPE_MAX_INTER_COUNT 4
+#define IEEE80211_TPE_MAX_CAT_COUNT 2
/* transmit power interpretation type of transmit power envelope element */
enum ieee80211_tx_power_intrpt_type {
@@ -2811,6 +2815,12 @@ enum ieee80211_tx_power_intrpt_type {
IEEE80211_TPE_REG_CLIENT_EIRP_PSD,
};
+/* category type of transmit power envelope element */
+enum ieee80211_tx_power_category {
+ IEEE80211_TPE_CAT_DEFAULT,
+ IEEE80211_TPE_CAT_SUB_DEV,
+};
+
/**
* struct ieee80211_tx_pwr_env - Transmit Power Envelope
* @tx_power_info: Transmit Power Information field
@@ -2829,6 +2839,54 @@ struct ieee80211_tx_pwr_env {
#define IEEE80211_TX_PWR_ENV_INFO_INTERPRET 0x38
#define IEEE80211_TX_PWR_ENV_INFO_CATEGORY 0xC0
+/**
+ * ieee80211_tx_pwr_env_ok - validate the TPE element
+ * @pos: TPE element contents
+ * @elen: length of TPE element
+ * return: true if elen and parameter is in valid range
+ */
+static inline bool
+ieee80211_tx_pwr_env_ok(const u8 *pos, u8 elen)
+{
+ u8 count;
+ u8 interpret;
+ u8 category;
+ const struct ieee80211_tx_pwr_env *tx_pwr_env = (const void *)pos;
+ u8 info_len = offsetofend(typeof(*tx_pwr_env), tx_power_info);
+
+ if (elen < info_len)
+ return false;
+
+ count = u8_get_bits(tx_pwr_env->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_COUNT);
+ interpret = u8_get_bits(tx_pwr_env->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
+ category = u8_get_bits(tx_pwr_env->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_CATEGORY);
+
+ if (category > IEEE80211_TPE_CAT_SUB_DEV)
+ return false;
+
+ switch (interpret) {
+ case IEEE80211_TPE_LOCAL_EIRP:
+ case IEEE80211_TPE_REG_CLIENT_EIRP:
+ if (count > IEEE80211_TPE_MAX_EIRP_COUNT)
+ return false;
+ info_len += count + 1;
+ break;
+ case IEEE80211_TPE_LOCAL_EIRP_PSD:
+ case IEEE80211_TPE_REG_CLIENT_EIRP_PSD:
+ if (count > IEEE80211_TPE_MAX_EIRP_PSD_COUNT)
+ return false;
+ info_len += (count == 0 ? 1 : 1 << (count - 1));
+ break;
+ default:
+ return false;
+ }
+
+ return elen >= info_len;
+}
+
/*
* ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size
* @he_oper_ie: byte data of the He Operations IE, stating from the byte
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d485ae6cf1..2cf92034e2 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -661,7 +661,7 @@ struct ieee80211_fils_discovery {
* to driver when rate control is offloaded to firmware.
* @power_type: power type of BSS for 6 GHz
* @tx_pwr_env: transmit power envelope array of BSS.
- * @tx_pwr_env_num: number of @tx_pwr_env.
+ * @tx_pwr_env_len: length of @tx_pwr_env.
* @pwr_reduction: power constraint of BSS.
* @eht_support: does this BSS support EHT
* @csa_active: marks whether a channel switch is going on.
@@ -769,8 +769,10 @@ struct ieee80211_bss_conf {
u32 unsol_bcast_probe_resp_interval;
struct cfg80211_bitrate_mask beacon_tx_rate;
enum ieee80211_ap_reg_power power_type;
- struct ieee80211_tx_pwr_env tx_pwr_env[IEEE80211_TPE_MAX_IE_COUNT];
- u8 tx_pwr_env_num;
+ struct ieee80211_tx_pwr_env tx_pwr_env[IEEE80211_TPE_MAX_INTER_COUNT]
+ [IEEE80211_TPE_MAX_CAT_COUNT];
+ u8 tx_pwr_env_len[IEEE80211_TPE_MAX_INTER_COUNT]
+ [IEEE80211_TPE_MAX_CAT_COUNT];
u8 pwr_reduction;
bool eht_support;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 1374e5300e..8b1f235d03 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1710,7 +1710,8 @@ struct ieee802_11_elems {
const struct ieee80211_he_spr *he_spr;
const struct ieee80211_mu_edca_param_set *mu_edca_param_set;
const struct ieee80211_he_6ghz_capa *he_6ghz_capa;
- const struct ieee80211_tx_pwr_env *tx_pwr_env[IEEE80211_TPE_MAX_IE_COUNT];
+ const struct ieee80211_tx_pwr_env *tx_pwr_env[IEEE80211_TPE_MAX_INTER_COUNT]
+ [IEEE80211_TPE_MAX_CAT_COUNT];
const u8 *uora_element;
const u8 *mesh_id;
const u8 *peering;
@@ -1767,8 +1768,8 @@ struct ieee802_11_elems {
u8 perr_len;
u8 country_elem_len;
u8 bssid_index_len;
- u8 tx_pwr_env_len[IEEE80211_TPE_MAX_IE_COUNT];
- u8 tx_pwr_env_num;
+ u8 tx_pwr_env_len[IEEE80211_TPE_MAX_INTER_COUNT]
+ [IEEE80211_TPE_MAX_CAT_COUNT];
u8 eht_cap_len;
/* mult-link element can be de-fragmented and thus u8 is not sufficient */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b630c901a1..a797c3db15 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3243,7 +3243,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.power_type = IEEE80211_REG_UNSET_AP;
sdata->vif.bss_conf.pwr_reduction = 0;
- sdata->vif.bss_conf.tx_pwr_env_num = 0;
+ memset(sdata->vif.bss_conf.tx_pwr_env_len, 0,
+ sizeof(sdata->vif.bss_conf.tx_pwr_env_len));
memset(sdata->vif.bss_conf.tx_pwr_env, 0,
sizeof(sdata->vif.bss_conf.tx_pwr_env));
@@ -5002,7 +5003,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
if (link && is_6ghz && conn->mode >= IEEE80211_CONN_MODE_HE) {
struct ieee80211_bss_conf *bss_conf;
- u8 j = 0;
+ u8 j;
bss_conf = link->conf;
@@ -5012,14 +5013,19 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
BUILD_BUG_ON(ARRAY_SIZE(bss_conf->tx_pwr_env) !=
ARRAY_SIZE(elems->tx_pwr_env));
- for (i = 0; i < elems->tx_pwr_env_num; i++) {
- if (elems->tx_pwr_env_len[i] > sizeof(bss_conf->tx_pwr_env[j]))
- continue;
-
- bss_conf->tx_pwr_env_num++;
- memcpy(&bss_conf->tx_pwr_env[j], elems->tx_pwr_env[i],
- elems->tx_pwr_env_len[i]);
- j++;
+ for (i = 0; i < IEEE80211_TPE_MAX_INTER_COUNT; i++) {
+ for (j = 0; j < IEEE80211_TPE_MAX_CAT_COUNT; j++) {
+ if (!elems->tx_pwr_env[i][j]) {
+ bss_conf->tx_pwr_env_len[i][j] = 0;
+ continue;
+ }
+ bss_conf->tx_pwr_env_len[i][j] =
+ min_t(u8, elems->tx_pwr_env_len[i][j],
+ sizeof(bss_conf->tx_pwr_env_len[i][j]));
+ memcpy(&bss_conf->tx_pwr_env[i][j],
+ elems->tx_pwr_env[i][j],
+ bss_conf->tx_pwr_env_len[i][j]);
+ }
}
}
rcu_read_unlock();
diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c
index bb81c9bd52..3b50ec8438 100644
--- a/net/mac80211/parse.c
+++ b/net/mac80211/parse.c
@@ -171,6 +171,22 @@ ieee80211_parse_extension_element(u32 *crc,
*crc = crc32_be(*crc, (void *)elem, elem->datalen + 2);
}
+static void
+ieee80211_parse_tpe_element(struct ieee802_11_elems *elems,
+ const u8 *pos, u8 elen)
+{
+ if (ieee80211_tx_pwr_env_ok(pos, elen)) {
+ const struct ieee80211_tx_pwr_env *tx_pwr_env = (const void *)pos;
+ u8 inte = u8_get_bits(tx_pwr_env->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_INTERPRET);
+ u8 cat = u8_get_bits(tx_pwr_env->tx_power_info,
+ IEEE80211_TX_PWR_ENV_INFO_CATEGORY);
+
+ elems->tx_pwr_env[inte][cat] = tx_pwr_env;
+ elems->tx_pwr_env_len[inte][cat] = elen;
+ }
+}
+
static u32
_ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
struct ieee802_11_elems *elems,
@@ -588,16 +604,7 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
elems->rsnx_len = elen;
break;
case WLAN_EID_TX_POWER_ENVELOPE:
- if (elen < 1 ||
- elen > sizeof(struct ieee80211_tx_pwr_env))
- break;
-
- if (elems->tx_pwr_env_num >= ARRAY_SIZE(elems->tx_pwr_env))
- break;
-
- elems->tx_pwr_env[elems->tx_pwr_env_num] = (void *)pos;
- elems->tx_pwr_env_len[elems->tx_pwr_env_num] = elen;
- elems->tx_pwr_env_num++;
+ ieee80211_parse_tpe_element(elems, pos, elen);
break;
case WLAN_EID_EXTENSION:
ieee80211_parse_extension_element(calc_crc ?
diff --git a/versions b/versions
index 7078c4cdb1..5d0535c0cc 100644
--- a/versions
+++ b/versions
@@ -2,4 +2,4 @@ BACKPORTS_VERSION="(see git)"
BACKPORTED_KERNEL_VERSION="(see git)"
BACKPORTED_KERNEL_NAME="iwlwifi"
BACKPORTS_BUILD_TSTAMP=__DATE__ \" \" __TIME__
-BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:master:11882:30a8461e"
+BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:master:11883:359018c1"