wifi: mac80211: provide a helper to fetch the medium synchronization delay
[carl9170fw.git] / include / linux / ieee80211.h
index 5c88243c7898ce53e8747bca37dc1441f0839a07..4891d1c4a58e79fa22d8d692318c01919b3b6162 100644 (file)
@@ -786,20 +786,6 @@ static inline bool ieee80211_is_any_nullfunc(__le16 fc)
        return (ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc));
 }
 
-/**
- * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
- * @fc: frame control field in little-endian byteorder
- */
-static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
-{
-       /* IEEE 802.11-2012, definition of "bufferable management frame";
-        * note that this ignores the IBSS special case. */
-       return ieee80211_is_mgmt(fc) &&
-              (ieee80211_is_action(fc) ||
-               ieee80211_is_disassoc(fc) ||
-               ieee80211_is_deauth(fc));
-}
-
 /**
  * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
  * @seq_ctrl: frame sequence control bytes in little-endian byteorder
@@ -1364,8 +1350,11 @@ struct ieee80211_mgmt {
 /* Supported rates membership selectors */
 #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
 #define BSS_MEMBERSHIP_SELECTOR_VHT_PHY        126
-#define BSS_MEMBERSHIP_SELECTOR_HE_PHY 122
+#define BSS_MEMBERSHIP_SELECTOR_GLK    125
+#define BSS_MEMBERSHIP_SELECTOR_EPS    124
 #define BSS_MEMBERSHIP_SELECTOR_SAE_H2E 123
+#define BSS_MEMBERSHIP_SELECTOR_HE_PHY 122
+#define BSS_MEMBERSHIP_SELECTOR_EHT_PHY        121
 
 /* mgmt header + 1 byte category code */
 #define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
@@ -4132,6 +4121,44 @@ static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr)
        return hdr->addr2;
 }
 
+/**
+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
+ * @skb: the skb to check, starting with the 802.11 header
+ */
+static inline bool ieee80211_is_bufferable_mmpdu(struct ieee80211_hdr *hdr, size_t len)
+{
+       struct ieee80211_mgmt *mgmt = (void *)hdr;
+       __le16 fc = mgmt->frame_control;
+
+       /*
+        * IEEE 802.11 REVme D2.0 definition of bufferable MMPDU;
+        * note that this ignores the IBSS special case.
+        */
+       if (!ieee80211_is_mgmt(fc))
+               return false;
+
+       if (ieee80211_is_disassoc(fc) || ieee80211_is_deauth(fc))
+               return true;
+
+       if (!ieee80211_is_action(fc))
+               return false;
+
+       if (len < offsetofend(typeof(*mgmt), u.action.u.ftm.action_code))
+               return true;
+
+       /* action frame - additionally check for non-bufferable FTM */
+
+       if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC &&
+           mgmt->u.action.category != WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION)
+               return true;
+
+       if (mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_REQUEST ||
+           mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_RESPONSE)
+               return false;
+
+       return true;
+}
+
 /**
  * ieee80211_get_DA - get pointer to DA
  * @hdr: the frame
@@ -4536,6 +4563,76 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)
        return sizeof(*mle) + common + mle->variable[0];
 }
 
+/**
+ * ieee80211_mle_get_eml_sync_delay - returns the medium sync delay
+ * @data: pointer to the multi link EHT IE
+ *
+ * The element is assumed to be big enough. This must be checked by
+ * ieee80211_mle_size_ok().
+ * If the medium synchronization can't be found (the type is not basic, or
+ * the medium sync presence bit is clear), 0 will be returned.
+ */
+static inline u16 ieee80211_mle_get_eml_med_sync_delay(const u8 *data)
+{
+       const struct ieee80211_multi_link_elem *mle = (const void *)data;
+       u16 control = le16_to_cpu(mle->control);
+       const u8 *common = mle->variable;
+
+       if (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE) !=
+           IEEE80211_ML_CONTROL_TYPE_BASIC)
+               return 0;
+
+       /* 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_MED_SYNC_DELAY))
+               return 0;
+
+       if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
+               common += 1;
+       if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT)
+               common += 1;
+
+       return get_unaligned_le16(common);
+}
+
+/**
+ * ieee80211_mle_get_eml_cap - returns the EML capability
+ * @data: pointer to the multi link EHT IE
+ *
+ * The element is assumed to be big enough. This must be checked by
+ * ieee80211_mle_size_ok().
+ * If the EML capability can't be found (the type is not basic, or
+ * the EML capability presence bit is clear), 0 will be returned.
+ */
+static inline u16 ieee80211_mle_get_eml_cap(const u8 *data)
+{
+       const struct ieee80211_multi_link_elem *mle = (const void *)data;
+       u16 control = le16_to_cpu(mle->control);
+       const u8 *common = mle->variable;
+
+       if (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE) !=
+           IEEE80211_ML_CONTROL_TYPE_BASIC)
+               return 0;
+
+       /* 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_EML_CAPA))
+               return 0;
+
+       if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
+               common += 1;
+       if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT)
+               common += 1;
+       if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY)
+               common += 2;
+
+       return get_unaligned_le16(common);
+}
+
 /**
  * ieee80211_mle_size_ok - validate multi-link element size
  * @data: pointer to the element data