* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2019 Intel Corporation
+ * Copyright (C) 2018 - 2020 Intel Corporation
  */
 
 #ifndef MAC80211_H
  * @ht_cap: HT capabilities of this STA; restricted to our own capabilities
  * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities
  * @he_cap: HE capabilities of this STA
+ * @he_6ghz_capa: on 6 GHz, holds the HE 6 GHz band capabilities
  * @max_rx_aggregation_subframes: maximal amount of frames in a single AMPDU
  *     that this station is allowed to transmit to us.
  *     Can be modified by driver.
        struct ieee80211_sta_ht_cap ht_cap;
        struct ieee80211_sta_vht_cap vht_cap;
        struct ieee80211_sta_he_cap he_cap;
+       struct ieee80211_he_6ghz_capa he_6ghz_capa;
        u16 max_rx_aggregation_subframes;
        bool wme;
        u8 uapsd_queues;
 
        if (params->he_capa)
                ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
                                                  (void *)params->he_capa,
-                                                 params->he_capa_len, sta);
+                                                 params->he_capa_len,
+                                                 (void *)params->he_6ghz_capa,
+                                                 sta);
 
        if (params->opmode_notif_used) {
                /* returned value is only needed for rc update, but the
 
 
 #include "ieee80211_i.h"
 
+static void
+ieee80211_update_from_he_6ghz_capa(const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
+                                  struct sta_info *sta)
+{
+       enum ieee80211_smps_mode smps_mode;
+
+       if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+           sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+               switch (le16_get_bits(he_6ghz_capa->capa,
+                                     IEEE80211_HE_6GHZ_CAP_SM_PS)) {
+               case WLAN_HT_CAP_SM_PS_INVALID:
+               case WLAN_HT_CAP_SM_PS_STATIC:
+                       smps_mode = IEEE80211_SMPS_STATIC;
+                       break;
+               case WLAN_HT_CAP_SM_PS_DYNAMIC:
+                       smps_mode = IEEE80211_SMPS_DYNAMIC;
+                       break;
+               case WLAN_HT_CAP_SM_PS_DISABLED:
+                       smps_mode = IEEE80211_SMPS_OFF;
+                       break;
+               }
+
+               sta->sta.smps_mode = smps_mode;
+       } else {
+               sta->sta.smps_mode = IEEE80211_SMPS_OFF;
+       }
+
+       switch (le16_get_bits(he_6ghz_capa->capa,
+                             IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN)) {
+       case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
+               sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
+               break;
+       case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
+               sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991;
+               break;
+       case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
+       default:
+               sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
+               break;
+       }
+
+       sta->sta.he_6ghz_capa = *he_6ghz_capa;
+}
+
 void
 ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
                                  struct ieee80211_supported_band *sband,
                                  const u8 *he_cap_ie, u8 he_cap_len,
+                                 const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
                                  struct sta_info *sta)
 {
        struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap;
 
        sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta);
        sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
+
+       if (sband->band == NL80211_BAND_6GHZ && he_6ghz_capa)
+               ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, sta);
 }
 
 void
 
 ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
                                  struct ieee80211_supported_band *sband,
                                  const u8 *he_cap_ie, u8 he_cap_len,
+                                 const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
                                  struct sta_info *sta);
 void
 ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif,
 
                                            elems->vht_cap_elem, sta);
 
        ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap,
-                                         elems->he_cap_len, sta);
+                                         elems->he_cap_len,
+                                         elems->he_6ghz_capa,
+                                         sta);
 
        if (bw != sta->sta.bandwidth)
                changed |= IEEE80211_RC_BW_CHANGED;
 
                ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
                                                  elems->he_cap,
                                                  elems->he_cap_len,
+                                                 elems->he_6ghz_capa,
                                                  sta);
 
                bss_conf->he_support = sta->sta.he_cap.has_he;