diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rxon.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 58 |
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 6c2adc58d654..dfdbea6e8f99 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: |