Skip to content
Snippets Groups Projects
Commit 850bedcc authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

iwlagn: fix iwlagn_check_needed_chains


This function was intended to calculate the
number of RX chains needed, but could only
work where the AP's streams were asymmetric,
i.e. 2 TX and 3 RX or similar. In the case
where IEEE80211_HT_MCS_TX_RX_DIFF was not
set, this function would calculate the wrong
information.

Additionally, mac80211 didn't pass through
the required values at all, so it couldn't
work anyway.

Rewrite the logic in this function and add
appropriate comments to make it readable.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 90b4ca9d
No related branches found
No related tags found
No related merge requests found
......@@ -471,6 +471,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
struct iwl_rxon_context *tmp;
struct ieee80211_sta *sta;
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
struct ieee80211_sta_ht_cap *ht_cap;
bool need_multiple;
lockdep_assert_held(&priv->mutex);
......@@ -479,23 +480,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
case NL80211_IFTYPE_STATION:
rcu_read_lock();
sta = ieee80211_find_sta(vif, bss_conf->bssid);
if (sta) {
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
int maxstreams;
maxstreams = (ht_cap->mcs.tx_params &
IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
maxstreams += 1;
need_multiple = true;
if ((ht_cap->mcs.rx_mask[1] == 0) &&
(ht_cap->mcs.rx_mask[2] == 0))
need_multiple = false;
if (maxstreams <= 1)
need_multiple = false;
} else {
if (!sta) {
/*
* If at all, this can only happen through a race
* when the AP disconnects us while we're still
......@@ -503,7 +488,46 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
* will soon tell us about that.
*/
need_multiple = false;
rcu_read_unlock();
break;
}
ht_cap = &sta->ht_cap;
need_multiple = true;
/*
* If the peer advertises no support for receiving 2 and 3
* stream MCS rates, it can't be transmitting them either.
*/
if (ht_cap->mcs.rx_mask[1] == 0 &&
ht_cap->mcs.rx_mask[2] == 0) {
need_multiple = false;
} else if (!(ht_cap->mcs.tx_params &
IEEE80211_HT_MCS_TX_DEFINED)) {
/* If it can't TX MCS at all ... */
need_multiple = false;
} else if (ht_cap->mcs.tx_params &
IEEE80211_HT_MCS_TX_RX_DIFF) {
int maxstreams;
/*
* But if it can receive them, it might still not
* be able to transmit them, which is what we need
* to check here -- so check the number of streams
* it advertises for TX (if different from RX).
*/
maxstreams = (ht_cap->mcs.tx_params &
IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK);
maxstreams >>=
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
maxstreams += 1;
if (maxstreams <= 1)
need_multiple = false;
}
rcu_read_unlock();
break;
case NL80211_IFTYPE_ADHOC:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment