aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
diff options
context:
space:
mode:
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: