wifi: ieee80211: fix erroneous NSTR bitmap size checks
[carl9170fw.git] / include / linux / ieee80211.h
index 5fb8142cf08e6dd14d94281ceec790d81b9e7a7d..ca76f88b4c4c2f69baad49b70e8f00264a9a5490 100644 (file)
@@ -2014,12 +2014,18 @@ struct ieee80211_mu_edca_param_set {
  * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams
  *     supported for reception and the maximum number of spatial streams
  *     supported for transmission for MCS 12 - 13.
+ * @rx_tx_max_nss: array of the previous fields for easier loop access
  */
 struct ieee80211_eht_mcs_nss_supp_20mhz_only {
-       u8 rx_tx_mcs7_max_nss;
-       u8 rx_tx_mcs9_max_nss;
-       u8 rx_tx_mcs11_max_nss;
-       u8 rx_tx_mcs13_max_nss;
+       union {
+               struct {
+                       u8 rx_tx_mcs7_max_nss;
+                       u8 rx_tx_mcs9_max_nss;
+                       u8 rx_tx_mcs11_max_nss;
+                       u8 rx_tx_mcs13_max_nss;
+               };
+               u8 rx_tx_max_nss[4];
+       };
 };
 
 /**
@@ -2039,11 +2045,17 @@ struct ieee80211_eht_mcs_nss_supp_20mhz_only {
  * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams
  *     supported for reception and the maximum number of spatial streams
  *     supported for transmission for MCS 12 - 13.
+ * @rx_tx_max_nss: array of the previous fields for easier loop access
  */
 struct ieee80211_eht_mcs_nss_supp_bw {
-       u8 rx_tx_mcs9_max_nss;
-       u8 rx_tx_mcs11_max_nss;
-       u8 rx_tx_mcs13_max_nss;
+       union {
+               struct {
+                       u8 rx_tx_mcs9_max_nss;
+                       u8 rx_tx_mcs11_max_nss;
+                       u8 rx_tx_mcs13_max_nss;
+               };
+               u8 rx_tx_max_nss[3];
+       };
 };
 
 /**
@@ -2096,7 +2108,7 @@ struct ieee80211_eht_cap_elem {
  */
 struct ieee80211_eht_operation {
        u8 params;
-       __le32 basic_mcs_nss;
+       struct ieee80211_eht_mcs_nss_supp_20mhz_only basic_mcs_nss;
        u8 optional[];
 } __packed;
 
@@ -4421,6 +4433,9 @@ static inline bool for_each_element_completed(const struct element *element,
 #define IEEE80211_RNR_TBTT_PARAMS_PROBE_ACTIVE                 0x20
 #define IEEE80211_RNR_TBTT_PARAMS_COLOC_AP                     0x40
 
+#define IEEE80211_RNR_TBTT_PARAMS_PSD_NO_LIMIT                 127
+#define IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED                 -128
+
 struct ieee80211_neighbor_ap_info {
        u8 tbtt_info_hdr;
        u8 tbtt_info_len;
@@ -4456,7 +4471,7 @@ struct ieee80211_tbtt_info_7_8_9 {
 
        /* The following element is optional, structure may not grow */
        u8 bss_params;
-       u8 psd_20;
+       s8 psd_20;
 } __packed;
 
 /* Format of the TBTT information element if it has >= 11 bytes */
@@ -4467,7 +4482,7 @@ struct ieee80211_tbtt_info_ge_11 {
 
        /* The following elements are optional, structure may grow */
        u8 bss_params;
-       u8 psd_20;
+       s8 psd_20;
        struct ieee80211_rnr_mld_params mld_params;
 } __packed;
 
@@ -4605,6 +4620,34 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)
        return sizeof(*mle) + common + mle->variable[0];
 }
 
+/**
+ * ieee80211_mle_get_bss_param_ch_cnt - returns the BSS parameter change count
+ * @mle: the basic multi link element
+ *
+ * The element is assumed to be of the correct type (BASIC) and big enough,
+ * this must be checked using ieee80211_mle_type_ok().
+ *
+ * If the BSS parameter change count value can't be found (the presence bit
+ * for it is clear), 0 will be returned.
+ */
+static inline u8
+ieee80211_mle_get_bss_param_ch_cnt(const struct ieee80211_multi_link_elem *mle)
+{
+       u16 control = le16_to_cpu(mle->control);
+       const u8 *common = mle->variable;
+
+       /* common points now at the beginning of ieee80211_mle_basic_common_info */
+       common += sizeof(struct ieee80211_mle_basic_common_info);
+
+       if (!(control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT))
+               return 0;
+
+       if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
+               common += 1;
+
+       return *common;
+}
+
 /**
  * ieee80211_mle_get_eml_sync_delay - returns the medium sync delay
  * @data: pointer to the multi link EHT IE
@@ -4805,7 +4848,7 @@ static inline bool ieee80211_mle_basic_sta_prof_size_ok(const u8 *data,
        if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT)
                info_len += 2;
        if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE &&
-           control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) {
+           control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) {
                if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE)
                        info_len += 2;
                else
@@ -4818,6 +4861,42 @@ static inline bool ieee80211_mle_basic_sta_prof_size_ok(const u8 *data,
               fixed + prof->sta_info_len <= len;
 }
 
+/**
+ * ieee80211_mle_basic_sta_prof_bss_param_ch_cnt - get per-STA profile BSS
+ *     parameter change count
+ * @prof: the per-STA profile, having been checked with
+ *     ieee80211_mle_basic_sta_prof_size_ok() for the correct length
+ *
+ * Return: The BSS parameter change count value if present, 0 otherwise.
+ */
+static inline u8
+ieee80211_mle_basic_sta_prof_bss_param_ch_cnt(const struct ieee80211_mle_per_sta_profile *prof)
+{
+       u16 control = le16_to_cpu(prof->control);
+       const u8 *pos = prof->variable;
+
+       if (!(control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT))
+               return 0;
+
+       if (control & IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT)
+               pos += 6;
+       if (control & IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT)
+               pos += 2;
+       if (control & IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT)
+               pos += 8;
+       if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT)
+               pos += 2;
+       if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE &&
+           control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) {
+               if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE)
+                       pos += 2;
+               else
+                       pos += 1;
+       }
+
+       return *pos;
+}
+
 #define IEEE80211_MLE_STA_RECONF_CONTROL_LINK_ID                       0x000f
 #define IEEE80211_MLE_STA_RECONF_CONTROL_COMPLETE_PROFILE              0x0010
 #define IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT          0x0020