@@ -332,15 +332,23 @@ struct ieee80211_sta_vht_cap {
* to describe 802.11ax HE capabilities for a STA.
*
* @has_he: true iff HE data is valid.
+ * @has_he_6ghz: true iff HE 6 GHz data is valid.
* @he_cap_elem: Fixed portion of the HE capabilities element.
* @he_mcs_nss_supp: The supported NSS/MCS combinations.
* @ppe_thres: Holds the PPE Thresholds data.
+ * @ampdu_factor: Maximum A-MPDU length factor used in 6 GHz.
+ * @ampdu_density: Minimum A-MPDU spacing used in 6 GHz.
+ * @he_6gz_cap: HE 6 GHz Band capability.
*/
struct ieee80211_sta_he_cap {
bool has_he;
+ bool has_he_6ghz;
struct ieee80211_he_cap_elem he_cap_elem;
struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp;
u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN];
+ u8 ampdu_factor;
+ u8 ampdu_density;
+ u16 he_6ghz_cap;
};
/**
@@ -1272,7 +1280,7 @@ struct station_parameters {
u8 he_capa_len;
u16 airtime_weight;
struct sta_txpwr txpwr;
- const struct ieee80211_he_6ghz_band_cap *he_6ghz_capa;
+ const u8 *he_6ghz_capa;
};
/**
@@ -1508,7 +1508,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
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,
+ params->he_6ghz_capa, sta);
if (params->opmode_notif_used) {
/* returned value is only needed for rc update, but the
@@ -12,10 +12,14 @@ 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 u8 *he_6ghz_cap_ie,
struct sta_info *sta)
{
struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap;
struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie;
+ struct ieee80211_he_6ghz_band_cap *he_6ghz_cap_elem;
+ enum ieee80211_smps_mode smps_mode;
+ u16 cap;
u8 he_ppe_size;
u8 mcs_nss_size;
u8 he_total_size;
@@ -53,6 +57,54 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta);
sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
+
+ if (!he_6ghz_cap_ie)
+ return;
+
+ he_6ghz_cap_elem = (struct ieee80211_he_6ghz_band_cap *)he_6ghz_cap_ie;
+ cap = __le16_to_cpu(he_6ghz_cap_elem->capab);
+
+ he_cap->ampdu_density =
+ FIELD_GET(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START_SPACE_MASK,
+ cap);
+ he_cap->ampdu_factor =
+ FIELD_GET(IEEE80211_HE_6GHZ_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
+ cap);
+
+ switch (FIELD_GET(IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LENGTH_MASK, cap)) {
+ 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;
+ }
+
+ switch (FIELD_GET(IEEE80211_HE_6GHZ_CAP_SMPS_MASK, cap)) {
+ 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;
+ }
+
+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+ sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ sta->sta.smps_mode = smps_mode;
+ else
+ sta->sta.smps_mode = IEEE80211_SMPS_OFF;
+
+ he_cap->he_6ghz_cap = cap;
+ he_cap->has_he_6ghz = true;
}
void
@@ -1892,6 +1892,7 @@ 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 u8 *he_6ghz_cap_ie,
struct sta_info *sta);
void
ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif,
@@ -441,7 +441,9 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
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_cap_elem,
+ sta);
if (bw != sta->sta.bandwidth)
changed |= IEEE80211_RC_BW_CHANGED;
@@ -3381,6 +3381,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
elems->he_cap,
elems->he_cap_len,
+ elems->he_6ghz_cap_elem,
sta);
bss_conf->he_support = sta->sta.he_cap.has_he;
During association or mesh peering of HE STA in 6 GHz band, required HT/VHT information has to be processed from 6 GHz band capabilities as HT/VHT IEs are not allowed in 6 GHz. Signed-off-by: Rajkumar Manoharan <rmanohar@codeaurora.org> --- include/net/cfg80211.h | 10 ++++++++- net/mac80211/cfg.c | 3 ++- net/mac80211/he.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/mesh_plink.c | 4 +++- net/mac80211/mlme.c | 1 + 6 files changed, 68 insertions(+), 3 deletions(-)