.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * HE handling |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright(c) 2017 Intel Deutschland GmbH |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License version 2 as |
---|
8 | | - * published by the Free Software Foundation. |
---|
| 6 | + * Copyright(c) 2019 - 2020 Intel Corporation |
---|
9 | 7 | */ |
---|
10 | 8 | |
---|
11 | 9 | #include "ieee80211_i.h" |
---|
| 10 | + |
---|
| 11 | +static void |
---|
| 12 | +ieee80211_update_from_he_6ghz_capa(const struct ieee80211_he_6ghz_capa *he_6ghz_capa, |
---|
| 13 | + struct sta_info *sta) |
---|
| 14 | +{ |
---|
| 15 | + enum ieee80211_smps_mode smps_mode; |
---|
| 16 | + |
---|
| 17 | + if (sta->sdata->vif.type == NL80211_IFTYPE_AP || |
---|
| 18 | + sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { |
---|
| 19 | + switch (le16_get_bits(he_6ghz_capa->capa, |
---|
| 20 | + IEEE80211_HE_6GHZ_CAP_SM_PS)) { |
---|
| 21 | + case WLAN_HT_CAP_SM_PS_INVALID: |
---|
| 22 | + case WLAN_HT_CAP_SM_PS_STATIC: |
---|
| 23 | + smps_mode = IEEE80211_SMPS_STATIC; |
---|
| 24 | + break; |
---|
| 25 | + case WLAN_HT_CAP_SM_PS_DYNAMIC: |
---|
| 26 | + smps_mode = IEEE80211_SMPS_DYNAMIC; |
---|
| 27 | + break; |
---|
| 28 | + case WLAN_HT_CAP_SM_PS_DISABLED: |
---|
| 29 | + smps_mode = IEEE80211_SMPS_OFF; |
---|
| 30 | + break; |
---|
| 31 | + } |
---|
| 32 | + |
---|
| 33 | + sta->sta.smps_mode = smps_mode; |
---|
| 34 | + } else { |
---|
| 35 | + sta->sta.smps_mode = IEEE80211_SMPS_OFF; |
---|
| 36 | + } |
---|
| 37 | + |
---|
| 38 | + switch (le16_get_bits(he_6ghz_capa->capa, |
---|
| 39 | + IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN)) { |
---|
| 40 | + case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: |
---|
| 41 | + sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454; |
---|
| 42 | + break; |
---|
| 43 | + case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991: |
---|
| 44 | + sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991; |
---|
| 45 | + break; |
---|
| 46 | + case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895: |
---|
| 47 | + default: |
---|
| 48 | + sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895; |
---|
| 49 | + break; |
---|
| 50 | + } |
---|
| 51 | + |
---|
| 52 | + sta->sta.he_6ghz_capa = *he_6ghz_capa; |
---|
| 53 | +} |
---|
12 | 54 | |
---|
13 | 55 | void |
---|
14 | 56 | ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, |
---|
15 | 57 | struct ieee80211_supported_band *sband, |
---|
16 | 58 | const u8 *he_cap_ie, u8 he_cap_len, |
---|
| 59 | + const struct ieee80211_he_6ghz_capa *he_6ghz_capa, |
---|
17 | 60 | struct sta_info *sta) |
---|
18 | 61 | { |
---|
19 | 62 | struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap; |
---|
.. | .. |
---|
52 | 95 | he_ppe_size); |
---|
53 | 96 | |
---|
54 | 97 | he_cap->has_he = true; |
---|
| 98 | + |
---|
| 99 | + sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta); |
---|
| 100 | + sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta); |
---|
| 101 | + |
---|
| 102 | + if (sband->band == NL80211_BAND_6GHZ && he_6ghz_capa) |
---|
| 103 | + ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, sta); |
---|
| 104 | +} |
---|
| 105 | + |
---|
| 106 | +void |
---|
| 107 | +ieee80211_he_op_ie_to_bss_conf(struct ieee80211_vif *vif, |
---|
| 108 | + const struct ieee80211_he_operation *he_op_ie) |
---|
| 109 | +{ |
---|
| 110 | + memset(&vif->bss_conf.he_oper, 0, sizeof(vif->bss_conf.he_oper)); |
---|
| 111 | + if (!he_op_ie) |
---|
| 112 | + return; |
---|
| 113 | + |
---|
| 114 | + vif->bss_conf.he_oper.params = __le32_to_cpu(he_op_ie->he_oper_params); |
---|
| 115 | + vif->bss_conf.he_oper.nss_set = __le16_to_cpu(he_op_ie->he_mcs_nss_set); |
---|
| 116 | +} |
---|
| 117 | + |
---|
| 118 | +void |
---|
| 119 | +ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif, |
---|
| 120 | + const struct ieee80211_he_spr *he_spr_ie_elem) |
---|
| 121 | +{ |
---|
| 122 | + struct ieee80211_he_obss_pd *he_obss_pd = |
---|
| 123 | + &vif->bss_conf.he_obss_pd; |
---|
| 124 | + const u8 *data; |
---|
| 125 | + |
---|
| 126 | + memset(he_obss_pd, 0, sizeof(*he_obss_pd)); |
---|
| 127 | + |
---|
| 128 | + if (!he_spr_ie_elem) |
---|
| 129 | + return; |
---|
| 130 | + data = he_spr_ie_elem->optional; |
---|
| 131 | + |
---|
| 132 | + if (he_spr_ie_elem->he_sr_control & |
---|
| 133 | + IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) |
---|
| 134 | + data++; |
---|
| 135 | + if (he_spr_ie_elem->he_sr_control & |
---|
| 136 | + IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) { |
---|
| 137 | + he_obss_pd->max_offset = *data++; |
---|
| 138 | + he_obss_pd->min_offset = *data++; |
---|
| 139 | + he_obss_pd->enable = true; |
---|
| 140 | + } |
---|
55 | 141 | } |
---|