Commit afe0d181 authored by Johannes Berg's avatar Johannes Berg

wifi: mac80211: add link_id to vht.c code for MLO

Update the code in vht.c and add the link_id parameter where
necessary.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 4b41b2ef
...@@ -1776,7 +1776,7 @@ static void iwl_mvm_mu_mimo_iface_iterator(void *_data, u8 *mac, ...@@ -1776,7 +1776,7 @@ static void iwl_mvm_mu_mimo_iface_iterator(void *_data, u8 *mac,
* the data received from firmware as if it came from the * the data received from firmware as if it came from the
* action frame, so no conversion is needed. * action frame, so no conversion is needed.
*/ */
ieee80211_update_mu_groups(vif, ieee80211_update_mu_groups(vif, 0,
(u8 *)&notif->membership_status, (u8 *)&notif->membership_status,
(u8 *)&notif->user_position); (u8 *)&notif->user_position);
} }
......
...@@ -6548,6 +6548,7 @@ ieee80211_vif_type_p2p(struct ieee80211_vif *vif) ...@@ -6548,6 +6548,7 @@ ieee80211_vif_type_p2p(struct ieee80211_vif *vif)
* ieee80211_update_mu_groups - set the VHT MU-MIMO groud data * ieee80211_update_mu_groups - set the VHT MU-MIMO groud data
* *
* @vif: the specified virtual interface * @vif: the specified virtual interface
* @link_id: the link ID for MLO, otherwise 0
* @membership: 64 bits array - a bit is set if station is member of the group * @membership: 64 bits array - a bit is set if station is member of the group
* @position: 2 bits per group id indicating the position in the group * @position: 2 bits per group id indicating the position in the group
* *
...@@ -6556,7 +6557,7 @@ ieee80211_vif_type_p2p(struct ieee80211_vif *vif) ...@@ -6556,7 +6557,7 @@ ieee80211_vif_type_p2p(struct ieee80211_vif *vif)
* matching GroupId management frame. * matching GroupId management frame.
* Calls to this function need to be serialized with RX path. * Calls to this function need to be serialized with RX path.
*/ */
void ieee80211_update_mu_groups(struct ieee80211_vif *vif, void ieee80211_update_mu_groups(struct ieee80211_vif *vif, unsigned int link_id,
const u8 *membership, const u8 *position); const u8 *membership, const u8 *position);
void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
......
...@@ -1763,7 +1763,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, ...@@ -1763,7 +1763,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
/* VHT can override some HT caps such as the A-MSDU max length */ /* VHT can override some HT caps such as the A-MSDU max length */
if (params->vht_capa) if (params->vht_capa)
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
params->vht_capa, sta); params->vht_capa, sta, 0);
if (params->he_capa) if (params->he_capa)
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
...@@ -1784,7 +1784,8 @@ static int sta_apply_parameters(struct ieee80211_local *local, ...@@ -1784,7 +1784,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
/* returned value is only needed for rc update, but the /* returned value is only needed for rc update, but the
* rc isn't initialized here yet, so ignore it * rc isn't initialized here yet, so ignore it
*/ */
__ieee80211_vht_handle_opmode(sdata, sta, params->opmode_notif, __ieee80211_vht_handle_opmode(sdata, sta, 0,
params->opmode_notif,
sband->band); sband->band);
} }
......
...@@ -1068,7 +1068,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, ...@@ -1068,7 +1068,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
&chandef); &chandef);
memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
&cap_ie, sta); &cap_ie, sta, 0);
if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap))) if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap)))
rates_updated |= true; rates_updated |= true;
} }
......
...@@ -2121,29 +2121,31 @@ void ...@@ -2121,29 +2121,31 @@ void
ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband, struct ieee80211_supported_band *sband,
const struct ieee80211_vht_cap *vht_cap_ie, const struct ieee80211_vht_cap *vht_cap_ie,
struct sta_info *sta); struct sta_info *sta, unsigned int link_id);
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta, enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta,
unsigned int link_id); unsigned int link_id);
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta, enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta,
unsigned int link_id); unsigned int link_id);
void ieee80211_sta_set_rx_nss(struct sta_info *sta); void ieee80211_sta_set_rx_nss(struct sta_info *sta, unsigned int link_id);
enum ieee80211_sta_rx_bandwidth enum ieee80211_sta_rx_bandwidth
ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width); ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width);
enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta); enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta,
unsigned int link_id);
void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata, void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
unsigned int link_id,
struct ieee80211_mgmt *mgmt); struct ieee80211_mgmt *mgmt);
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, u8 opmode, struct sta_info *sta, unsigned int link_id,
enum nl80211_band band); u8 opmode, enum nl80211_band band);
void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, u8 opmode, struct sta_info *sta, unsigned int link_id,
enum nl80211_band band); u8 opmode, enum nl80211_band band);
void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta_vht_cap *vht_cap); struct ieee80211_sta_vht_cap *vht_cap);
void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
u16 vht_mask[NL80211_VHT_NSS_MAX]); u16 vht_mask[NL80211_VHT_NSS_MAX]);
enum nl80211_chan_width enum nl80211_chan_width
ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta); ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta, unsigned int link_id);
/* HE */ /* HE */
void void
......
...@@ -1496,14 +1496,14 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local, ...@@ -1496,14 +1496,14 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
sta = sta_info_get_bss(sdata, mgmt->sa); sta = sta_info_get_bss(sdata, mgmt->sa);
if (sta) if (sta)
ieee80211_vht_handle_opmode(sdata, sta, opmode, ieee80211_vht_handle_opmode(sdata, sta, 0,
band); opmode, band);
mutex_unlock(&local->sta_mtx); mutex_unlock(&local->sta_mtx);
break; break;
} }
case WLAN_VHT_ACTION_GROUPID_MGMT: case WLAN_VHT_ACTION_GROUPID_MGMT:
ieee80211_process_mu_groups(sdata, mgmt); ieee80211_process_mu_groups(sdata, 0, mgmt);
break; break;
default: default:
WARN_ON(1); WARN_ON(1);
......
...@@ -442,7 +442,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, ...@@ -442,7 +442,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
changed |= IEEE80211_RC_BW_CHANGED; changed |= IEEE80211_RC_BW_CHANGED;
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
elems->vht_cap_elem, sta); elems->vht_cap_elem, sta, 0);
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap, ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap,
elems->he_cap_len, elems->he_cap_len,
......
...@@ -3570,7 +3570,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ...@@ -3570,7 +3570,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
if (elems->vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) if (elems->vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
elems->vht_cap_elem, sta); elems->vht_cap_elem,
sta, 0);
if (elems->he_operation && !(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && if (elems->he_operation && !(ifmgd->flags & IEEE80211_STA_DISABLE_HE) &&
elems->he_cap) { elems->he_cap) {
...@@ -4377,7 +4378,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ...@@ -4377,7 +4378,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
} }
if (sta && elems->opmode_notif) if (sta && elems->opmode_notif)
ieee80211_vht_handle_opmode(sdata, sta, *elems->opmode_notif, ieee80211_vht_handle_opmode(sdata, sta, 0,
*elems->opmode_notif,
rx_status->band); rx_status->band);
mutex_unlock(&local->sta_mtx); mutex_unlock(&local->sta_mtx);
......
...@@ -37,7 +37,7 @@ void rate_control_rate_init(struct sta_info *sta) ...@@ -37,7 +37,7 @@ void rate_control_rate_init(struct sta_info *sta)
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx_conf *chanctx_conf;
ieee80211_sta_set_rx_nss(sta); ieee80211_sta_set_rx_nss(sta, 0);
if (!ref) if (!ref)
return; return;
......
...@@ -3403,7 +3403,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) ...@@ -3403,7 +3403,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
rx->sta->sta.deflink.bandwidth = new_bw; rx->sta->sta.deflink.bandwidth = new_bw;
sband = rx->local->hw.wiphy->bands[status->band]; sband = rx->local->hw.wiphy->bands[status->band];
sta_opmode.bw = sta_opmode.bw =
ieee80211_sta_rx_bw_to_chan_width(rx->sta); ieee80211_sta_rx_bw_to_chan_width(rx->sta, 0);
sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED;
rate_control_rate_update(local, sband, rx->sta, 0, rate_control_rate_update(local, sband, rx->sta, 0,
......
...@@ -308,7 +308,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata, ...@@ -308,7 +308,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata,
/* IEEE802.11ac-2013 Table E-4 */ /* IEEE802.11ac-2013 Table E-4 */
u16 centers_80mhz[] = { 5210, 5290, 5530, 5610, 5690, 5775 }; u16 centers_80mhz[] = { 5210, 5290, 5530, 5610, 5690, 5775 };
struct cfg80211_chan_def uc = sta->tdls_chandef; struct cfg80211_chan_def uc = sta->tdls_chandef;
enum nl80211_chan_width max_width = ieee80211_sta_cap_chan_bw(sta); enum nl80211_chan_width max_width = ieee80211_sta_cap_chan_bw(sta, 0);
int i; int i;
/* only support upgrading non-narrow channels up to 80Mhz */ /* only support upgrading non-narrow channels up to 80Mhz */
......
...@@ -116,16 +116,16 @@ void ...@@ -116,16 +116,16 @@ void
ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband, struct ieee80211_supported_band *sband,
const struct ieee80211_vht_cap *vht_cap_ie, const struct ieee80211_vht_cap *vht_cap_ie,
struct sta_info *sta) struct sta_info *sta, unsigned int link_id)
{ {
struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.deflink.vht_cap; struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.link[link_id]->vht_cap;
struct ieee80211_sta_vht_cap own_cap; struct ieee80211_sta_vht_cap own_cap;
u32 cap_info, i; u32 cap_info, i;
bool have_80mhz; bool have_80mhz;
memset(vht_cap, 0, sizeof(*vht_cap)); memset(vht_cap, 0, sizeof(*vht_cap));
if (!sta->sta.deflink.ht_cap.ht_supported) if (!sta->sta.link[link_id]->ht_cap.ht_supported)
return; return;
if (!vht_cap_ie || !sband->vht_cap.vht_supported) if (!vht_cap_ie || !sband->vht_cap.vht_supported)
...@@ -295,10 +295,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, ...@@ -295,10 +295,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_160; sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
break; break;
default: default:
sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_80; sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
if (!(vht_cap->vht_mcs.tx_highest & if (!(vht_cap->vht_mcs.tx_highest &
cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE))) cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE)))
...@@ -310,10 +310,11 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, ...@@ -310,10 +310,11 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
* above) between 160 and 80+80 yet. * above) between 160 and 80+80 yet.
*/ */
if (cap_info & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) if (cap_info & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)
sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_160; sta->link[link_id]->cur_max_bandwidth =
IEEE80211_STA_RX_BW_160;
} }
sta->sta.deflink.bandwidth = ieee80211_sta_cur_vht_bw(sta, 0); sta->sta.link[link_id]->bandwidth = ieee80211_sta_cur_vht_bw(sta, link_id);
switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) { switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
...@@ -391,16 +392,17 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta, ...@@ -391,16 +392,17 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta,
return IEEE80211_STA_RX_BW_80; return IEEE80211_STA_RX_BW_80;
} }
enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta) enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta,
unsigned int link_id)
{ {
struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.deflink.vht_cap; struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.link[link_id]->vht_cap;
u32 cap_width; u32 cap_width;
if (!vht_cap->vht_supported) { if (!vht_cap->vht_supported) {
if (!sta->sta.deflink.ht_cap.ht_supported) if (!sta->sta.link[link_id]->ht_cap.ht_supported)
return NL80211_CHAN_WIDTH_20_NOHT; return NL80211_CHAN_WIDTH_20_NOHT;
return sta->sta.deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? return sta->sta.link[link_id]->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
NL80211_CHAN_WIDTH_40 : NL80211_CHAN_WIDTH_20; NL80211_CHAN_WIDTH_40 : NL80211_CHAN_WIDTH_20;
} }
...@@ -415,15 +417,17 @@ enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta) ...@@ -415,15 +417,17 @@ enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta)
} }
enum nl80211_chan_width enum nl80211_chan_width
ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta) ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta, unsigned int link_id)
{ {
enum ieee80211_sta_rx_bandwidth cur_bw = sta->sta.deflink.bandwidth; enum ieee80211_sta_rx_bandwidth cur_bw =
struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.deflink.vht_cap; sta->sta.link[link_id]->bandwidth;
struct ieee80211_sta_vht_cap *vht_cap =
&sta->sta.link[link_id]->vht_cap;
u32 cap_width; u32 cap_width;
switch (cur_bw) { switch (cur_bw) {
case IEEE80211_STA_RX_BW_20: case IEEE80211_STA_RX_BW_20:
if (!sta->sta.deflink.ht_cap.ht_supported) if (!sta->sta.link[link_id]->ht_cap.ht_supported)
return NL80211_CHAN_WIDTH_20_NOHT; return NL80211_CHAN_WIDTH_20_NOHT;
else else
return NL80211_CHAN_WIDTH_20; return NL80211_CHAN_WIDTH_20;
...@@ -497,18 +501,18 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta, ...@@ -497,18 +501,18 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta,
return bw; return bw;
} }
void ieee80211_sta_set_rx_nss(struct sta_info *sta) void ieee80211_sta_set_rx_nss(struct sta_info *sta, unsigned int link_id)
{ {
u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, eht_rx_nss = 0, rx_nss; u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, eht_rx_nss = 0, rx_nss;
bool support_160; bool support_160;
/* if we received a notification already don't overwrite it */ /* if we received a notification already don't overwrite it */
if (sta->sta.deflink.rx_nss) if (sta->sta.link[link_id]->rx_nss)
return; return;
if (sta->sta.deflink.eht_cap.has_eht) { if (sta->sta.link[link_id]->eht_cap.has_eht) {
int i; int i;
const u8 *rx_nss_mcs = (void *)&sta->sta.deflink.eht_cap.eht_mcs_nss_supp; const u8 *rx_nss_mcs = (void *)&sta->sta.link[link_id]->eht_cap.eht_mcs_nss_supp;
/* get the max nss for EHT over all possible bandwidths and mcs */ /* get the max nss for EHT over all possible bandwidths and mcs */
for (i = 0; i < sizeof(struct ieee80211_eht_mcs_nss_supp); i++) for (i = 0; i < sizeof(struct ieee80211_eht_mcs_nss_supp); i++)
...@@ -517,10 +521,10 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) ...@@ -517,10 +521,10 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
IEEE80211_EHT_MCS_NSS_RX)); IEEE80211_EHT_MCS_NSS_RX));
} }
if (sta->sta.deflink.he_cap.has_he) { if (sta->sta.link[link_id]->he_cap.has_he) {
int i; int i;
u8 rx_mcs_80 = 0, rx_mcs_160 = 0; u8 rx_mcs_80 = 0, rx_mcs_160 = 0;
const struct ieee80211_sta_he_cap *he_cap = &sta->sta.deflink.he_cap; const struct ieee80211_sta_he_cap *he_cap = &sta->sta.link[link_id]->he_cap;
u16 mcs_160_map = u16 mcs_160_map =
le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
u16 mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80); u16 mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
...@@ -551,23 +555,23 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) ...@@ -551,23 +555,23 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
he_rx_nss = rx_mcs_80; he_rx_nss = rx_mcs_80;
} }
if (sta->sta.deflink.ht_cap.ht_supported) { if (sta->sta.link[link_id]->ht_cap.ht_supported) {
if (sta->sta.deflink.ht_cap.mcs.rx_mask[0]) if (sta->sta.link[link_id]->ht_cap.mcs.rx_mask[0])
ht_rx_nss++; ht_rx_nss++;
if (sta->sta.deflink.ht_cap.mcs.rx_mask[1]) if (sta->sta.link[link_id]->ht_cap.mcs.rx_mask[1])
ht_rx_nss++; ht_rx_nss++;
if (sta->sta.deflink.ht_cap.mcs.rx_mask[2]) if (sta->sta.link[link_id]->ht_cap.mcs.rx_mask[2])
ht_rx_nss++; ht_rx_nss++;
if (sta->sta.deflink.ht_cap.mcs.rx_mask[3]) if (sta->sta.link[link_id]->ht_cap.mcs.rx_mask[3])
ht_rx_nss++; ht_rx_nss++;
/* FIXME: consider rx_highest? */ /* FIXME: consider rx_highest? */
} }
if (sta->sta.deflink.vht_cap.vht_supported) { if (sta->sta.link[link_id]->vht_cap.vht_supported) {
int i; int i;
u16 rx_mcs_map; u16 rx_mcs_map;
rx_mcs_map = le16_to_cpu(sta->sta.deflink.vht_cap.vht_mcs.rx_mcs_map); rx_mcs_map = le16_to_cpu(sta->sta.link[link_id]->vht_cap.vht_mcs.rx_mcs_map);
for (i = 7; i >= 0; i--) { for (i = 7; i >= 0; i--) {
u8 mcs = (rx_mcs_map >> (2 * i)) & 3; u8 mcs = (rx_mcs_map >> (2 * i)) & 3;
...@@ -583,12 +587,12 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) ...@@ -583,12 +587,12 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
rx_nss = max(vht_rx_nss, ht_rx_nss); rx_nss = max(vht_rx_nss, ht_rx_nss);
rx_nss = max(he_rx_nss, rx_nss); rx_nss = max(he_rx_nss, rx_nss);
rx_nss = max(eht_rx_nss, rx_nss); rx_nss = max(eht_rx_nss, rx_nss);
sta->sta.deflink.rx_nss = max_t(u8, 1, rx_nss); sta->sta.link[link_id]->rx_nss = max_t(u8, 1, rx_nss);
} }
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, u8 opmode, struct sta_info *sta, unsigned int link_id,
enum nl80211_band band) u8 opmode, enum nl80211_band band)
{ {
enum ieee80211_sta_rx_bandwidth new_bw; enum ieee80211_sta_rx_bandwidth new_bw;
struct sta_opmode_info sta_opmode = {}; struct sta_opmode_info sta_opmode = {};
...@@ -603,8 +607,8 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, ...@@ -603,8 +607,8 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT;
nss += 1; nss += 1;
if (sta->sta.deflink.rx_nss != nss) { if (sta->sta.link[link_id]->rx_nss != nss) {
sta->sta.deflink.rx_nss = nss; sta->sta.link[link_id]->rx_nss = nss;
sta_opmode.rx_nss = nss; sta_opmode.rx_nss = nss;
changed |= IEEE80211_RC_NSS_CHANGED; changed |= IEEE80211_RC_NSS_CHANGED;
sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED;
...@@ -613,28 +617,28 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, ...@@ -613,28 +617,28 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
/* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */ /* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_20; sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
break; break;
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ: case IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ:
/* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */ /* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_40; sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_40;
break; break;
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ: case IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ:
if (opmode & IEEE80211_OPMODE_NOTIF_BW_160_80P80) if (opmode & IEEE80211_OPMODE_NOTIF_BW_160_80P80)
sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_160; sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
else else
sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_80; sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
break; break;
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ: case IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ:
/* legacy only, no longer used by newer spec */ /* legacy only, no longer used by newer spec */
sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_160; sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
break; break;
} }
new_bw = ieee80211_sta_cur_vht_bw(sta, 0); new_bw = ieee80211_sta_cur_vht_bw(sta, link_id);
if (new_bw != sta->sta.deflink.bandwidth) { if (new_bw != sta->sta.link[link_id]->bandwidth) {
sta->sta.deflink.bandwidth = new_bw; sta->sta.link[link_id]->bandwidth = new_bw;
sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(sta); sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(sta, link_id);
changed |= IEEE80211_RC_BW_CHANGED; changed |= IEEE80211_RC_BW_CHANGED;
sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED; sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED;
} }
...@@ -647,54 +651,56 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, ...@@ -647,54 +651,56 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
} }
void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata, void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
unsigned int link_id,
struct ieee80211_mgmt *mgmt) struct ieee80211_mgmt *mgmt)
{ {
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
if (!sdata->vif.bss_conf.mu_mimo_owner) if (!link_conf->mu_mimo_owner)
return; return;
if (!memcmp(mgmt->u.action.u.vht_group_notif.position, if (!memcmp(mgmt->u.action.u.vht_group_notif.position,
bss_conf->mu_group.position, WLAN_USER_POSITION_LEN) && link_conf->mu_group.position, WLAN_USER_POSITION_LEN) &&
!memcmp(mgmt->u.action.u.vht_group_notif.membership, !memcmp(mgmt->u.action.u.vht_group_notif.membership,
bss_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN)) link_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN))
return; return;
memcpy(bss_conf->mu_group.membership, memcpy(link_conf->mu_group.membership,
mgmt->u.action.u.vht_group_notif.membership, mgmt->u.action.u.vht_group_notif.membership,
WLAN_MEMBERSHIP_LEN); WLAN_MEMBERSHIP_LEN);
memcpy(bss_conf->mu_group.position, memcpy(link_conf->mu_group.position,
mgmt->u.action.u.vht_group_notif.position, mgmt->u.action.u.vht_group_notif.position,
WLAN_USER_POSITION_LEN); WLAN_USER_POSITION_LEN);
ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_MU_GROUPS); ieee80211_link_info_change_notify(sdata, link_id, BSS_CHANGED_MU_GROUPS);
} }
void ieee80211_update_mu_groups(struct ieee80211_vif *vif, void ieee80211_update_mu_groups(struct ieee80211_vif *vif, unsigned int link_id,
const u8 *membership, const u8 *position) const u8 *membership, const u8 *position)
{ {
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; struct ieee80211_bss_conf *link_conf = vif->link_conf[link_id];
if (WARN_ON_ONCE(!vif->bss_conf.mu_mimo_owner)) if (WARN_ON_ONCE(!link_conf->mu_mimo_owner))
return; return;
memcpy(bss_conf->mu_group.membership, membership, WLAN_MEMBERSHIP_LEN); memcpy(link_conf->mu_group.membership, membership, WLAN_MEMBERSHIP_LEN);
memcpy(bss_conf->mu_group.position, position, WLAN_USER_POSITION_LEN); memcpy(link_conf->mu_group.position, position, WLAN_USER_POSITION_LEN);
} }
EXPORT_SYMBOL_GPL(ieee80211_update_mu_groups); EXPORT_SYMBOL_GPL(ieee80211_update_mu_groups);
void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, u8 opmode, struct sta_info *sta, unsigned int link_id,
enum nl80211_band band) u8 opmode, enum nl80211_band band)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band); u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, link_id,
opmode, band);
if (changed > 0) { if (changed > 0) {
ieee80211_recalc_min_chandef(sdata); ieee80211_recalc_min_chandef(sdata);
rate_control_rate_update(local, sband, sta, 0, changed); rate_control_rate_update(local, sband, sta, link_id, changed);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment