Commit 850bedcc authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

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
...@@ -471,6 +471,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv, ...@@ -471,6 +471,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
struct iwl_rxon_context *tmp; struct iwl_rxon_context *tmp;
struct ieee80211_sta *sta; struct ieee80211_sta *sta;
struct iwl_ht_config *ht_conf = &priv->current_ht_config; struct iwl_ht_config *ht_conf = &priv->current_ht_config;
struct ieee80211_sta_ht_cap *ht_cap;
bool need_multiple; bool need_multiple;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->mutex);
...@@ -479,31 +480,54 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv, ...@@ -479,31 +480,54 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
rcu_read_lock(); rcu_read_lock();
sta = ieee80211_find_sta(vif, bss_conf->bssid); sta = ieee80211_find_sta(vif, bss_conf->bssid);
if (sta) { if (!sta) {
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; /*
int maxstreams; * If at all, this can only happen through a race
* when the AP disconnects us while we're still
* setting up the connection, in that case mac80211
* will soon tell us about that.
*/
need_multiple = false;
rcu_read_unlock();
break;
}
maxstreams = (ht_cap->mcs.tx_params & ht_cap = &sta->ht_cap;
IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
maxstreams += 1;
need_multiple = true; need_multiple = true;
if ((ht_cap->mcs.rx_mask[1] == 0) && /*
(ht_cap->mcs.rx_mask[2] == 0)) * 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; need_multiple = false;
if (maxstreams <= 1) } else if (!(ht_cap->mcs.tx_params &
IEEE80211_HT_MCS_TX_DEFINED)) {
/* If it can't TX MCS at all ... */
need_multiple = false; need_multiple = false;
} else { } else if (ht_cap->mcs.tx_params &
IEEE80211_HT_MCS_TX_RX_DIFF) {
int maxstreams;
/* /*
* If at all, this can only happen through a race * But if it can receive them, it might still not
* when the AP disconnects us while we're still * be able to transmit them, which is what we need
* setting up the connection, in that case mac80211 * to check here -- so check the number of streams
* will soon tell us about that. * 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; need_multiple = false;
} }
rcu_read_unlock(); rcu_read_unlock();
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
......
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