aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-02-25 06:24:11 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-25 15:33:39 -0500
commit850bedcc10377629ea88c96c07f8e1d0a99cf4ca (patch)
tree102aa7e024d291a71fc250c2b680e83f4f77e2ad /drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
parent90b4ca9dba87bef9a3352c3d5bcab998be70fc4f (diff)
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: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rxon.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c58
1 files changed, 41 insertions, 17 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 6c2adc58d65..dfdbea6e8f9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -471,6 +471,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
471 struct iwl_rxon_context *tmp; 471 struct iwl_rxon_context *tmp;
472 struct ieee80211_sta *sta; 472 struct ieee80211_sta *sta;
473 struct iwl_ht_config *ht_conf = &priv->current_ht_config; 473 struct iwl_ht_config *ht_conf = &priv->current_ht_config;
474 struct ieee80211_sta_ht_cap *ht_cap;
474 bool need_multiple; 475 bool need_multiple;
475 476
476 lockdep_assert_held(&priv->mutex); 477 lockdep_assert_held(&priv->mutex);
@@ -479,23 +480,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
479 case NL80211_IFTYPE_STATION: 480 case NL80211_IFTYPE_STATION:
480 rcu_read_lock(); 481 rcu_read_lock();
481 sta = ieee80211_find_sta(vif, bss_conf->bssid); 482 sta = ieee80211_find_sta(vif, bss_conf->bssid);
482 if (sta) { 483 if (!sta) {
483 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
484 int maxstreams;
485
486 maxstreams = (ht_cap->mcs.tx_params &
487 IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
488 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
489 maxstreams += 1;
490
491 need_multiple = true;
492
493 if ((ht_cap->mcs.rx_mask[1] == 0) &&
494 (ht_cap->mcs.rx_mask[2] == 0))
495 need_multiple = false;
496 if (maxstreams <= 1)
497 need_multiple = false;
498 } else {
499 /* 484 /*
500 * If at all, this can only happen through a race 485 * If at all, this can only happen through a race
501 * when the AP disconnects us while we're still 486 * when the AP disconnects us while we're still
@@ -503,7 +488,46 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
503 * will soon tell us about that. 488 * will soon tell us about that.
504 */ 489 */
505 need_multiple = false; 490 need_multiple = false;
491 rcu_read_unlock();
492 break;
493 }
494
495 ht_cap = &sta->ht_cap;
496
497 need_multiple = true;
498
499 /*
500 * If the peer advertises no support for receiving 2 and 3
501 * stream MCS rates, it can't be transmitting them either.
502 */
503 if (ht_cap->mcs.rx_mask[1] == 0 &&
504 ht_cap->mcs.rx_mask[2] == 0) {
505 need_multiple = false;
506 } else if (!(ht_cap->mcs.tx_params &
507 IEEE80211_HT_MCS_TX_DEFINED)) {
508 /* If it can't TX MCS at all ... */
509 need_multiple = false;
510 } else if (ht_cap->mcs.tx_params &
511 IEEE80211_HT_MCS_TX_RX_DIFF) {
512 int maxstreams;
513
514 /*
515 * But if it can receive them, it might still not
516 * be able to transmit them, which is what we need
517 * to check here -- so check the number of streams
518 * it advertises for TX (if different from RX).
519 */
520
521 maxstreams = (ht_cap->mcs.tx_params &
522 IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK);
523 maxstreams >>=
524 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
525 maxstreams += 1;
526
527 if (maxstreams <= 1)
528 need_multiple = false;
506 } 529 }
530
507 rcu_read_unlock(); 531 rcu_read_unlock();
508 break; 532 break;
509 case NL80211_IFTYPE_ADHOC: 533 case NL80211_IFTYPE_ADHOC: