aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c78
1 files changed, 46 insertions, 32 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 9bd61809129f..80f2f84defa8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -28,7 +28,6 @@
28 28
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/version.h>
32#include <net/mac80211.h> 31#include <net/mac80211.h>
33 32
34struct iwl_priv; /* FIXME: remove */ 33struct iwl_priv; /* FIXME: remove */
@@ -593,12 +592,11 @@ static void iwlcore_free_geos(struct iwl_priv *priv)
593 clear_bit(STATUS_GEO_CONFIGURED, &priv->status); 592 clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
594} 593}
595 594
596static u8 is_single_rx_stream(struct iwl_priv *priv) 595static bool is_single_rx_stream(struct iwl_priv *priv)
597{ 596{
598 return !priv->current_ht_config.is_ht || 597 return !priv->current_ht_config.is_ht ||
599 ((priv->current_ht_config.supp_mcs_set[1] == 0) && 598 ((priv->current_ht_config.supp_mcs_set[1] == 0) &&
600 (priv->current_ht_config.supp_mcs_set[2] == 0)) || 599 (priv->current_ht_config.supp_mcs_set[2] == 0));
601 priv->ps_mode == IWL_MIMO_PS_STATIC;
602} 600}
603 601
604static u8 iwl_is_channel_extension(struct iwl_priv *priv, 602static u8 iwl_is_channel_extension(struct iwl_priv *priv,
@@ -705,33 +703,39 @@ EXPORT_SYMBOL(iwl_set_rxon_ht);
705 * MIMO (dual stream) requires at least 2, but works better with 3. 703 * MIMO (dual stream) requires at least 2, but works better with 3.
706 * This does not determine *which* chains to use, just how many. 704 * This does not determine *which* chains to use, just how many.
707 */ 705 */
708static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv, 706static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
709 u8 *idle_state, u8 *rx_state)
710{ 707{
711 u8 is_single = is_single_rx_stream(priv); 708 bool is_single = is_single_rx_stream(priv);
712 u8 is_cam = test_bit(STATUS_POWER_PMI, &priv->status) ? 0 : 1; 709 bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
713 710
714 /* # of Rx chains to use when expecting MIMO. */ 711 /* # of Rx chains to use when expecting MIMO. */
715 if (is_single || (!is_cam && (priv->ps_mode == IWL_MIMO_PS_STATIC))) 712 if (is_single || (!is_cam && (priv->ps_mode == IWL_MIMO_PS_STATIC)))
716 *rx_state = 2; 713 return 2;
717 else 714 else
718 *rx_state = 3; 715 return 3;
716}
719 717
718static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
719{
720 int idle_cnt;
721 bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
720 /* # Rx chains when idling and maybe trying to save power */ 722 /* # Rx chains when idling and maybe trying to save power */
721 switch (priv->ps_mode) { 723 switch (priv->ps_mode) {
722 case IWL_MIMO_PS_STATIC: 724 case IWL_MIMO_PS_STATIC:
723 case IWL_MIMO_PS_DYNAMIC: 725 case IWL_MIMO_PS_DYNAMIC:
724 *idle_state = (is_cam) ? 2 : 1; 726 idle_cnt = (is_cam) ? 2 : 1;
725 break; 727 break;
726 case IWL_MIMO_PS_NONE: 728 case IWL_MIMO_PS_NONE:
727 *idle_state = (is_cam) ? *rx_state : 1; 729 idle_cnt = (is_cam) ? active_cnt : 1;
728 break; 730 break;
731 case IWL_MIMO_PS_INVALID:
729 default: 732 default:
730 *idle_state = 1; 733 IWL_ERROR("invalide mimo ps mode %d\n", priv->ps_mode);
734 WARN_ON(1);
735 idle_cnt = -1;
731 break; 736 break;
732 } 737 }
733 738 return idle_cnt;
734 return 0;
735} 739}
736 740
737/** 741/**
@@ -742,34 +746,44 @@ static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv,
742 */ 746 */
743void iwl_set_rxon_chain(struct iwl_priv *priv) 747void iwl_set_rxon_chain(struct iwl_priv *priv)
744{ 748{
745 u8 is_single = is_single_rx_stream(priv); 749 bool is_single = is_single_rx_stream(priv);
746 u8 idle_state, rx_state; 750 bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
747 751 u8 idle_rx_cnt, active_rx_cnt;
748 priv->staging_rxon.rx_chain = 0; 752 u16 rx_chain;
749 rx_state = idle_state = 3;
750 753
751 /* Tell uCode which antennas are actually connected. 754 /* Tell uCode which antennas are actually connected.
752 * Before first association, we assume all antennas are connected. 755 * Before first association, we assume all antennas are connected.
753 * Just after first association, iwl_chain_noise_calibration() 756 * Just after first association, iwl_chain_noise_calibration()
754 * checks which antennas actually *are* connected. */ 757 * checks which antennas actually *are* connected. */
755 priv->staging_rxon.rx_chain |= 758 rx_chain = priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
756 cpu_to_le16(priv->hw_params.valid_rx_ant <<
757 RXON_RX_CHAIN_VALID_POS);
758 759
759 /* How many receivers should we use? */ 760 /* How many receivers should we use? */
760 iwlcore_get_rx_chain_counter(priv, &idle_state, &rx_state); 761 active_rx_cnt = iwl_get_active_rx_chain_count(priv);
761 priv->staging_rxon.rx_chain |= 762 idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
762 cpu_to_le16(rx_state << RXON_RX_CHAIN_MIMO_CNT_POS); 763
763 priv->staging_rxon.rx_chain |= 764 /* correct rx chain count accoridng hw settings */
764 cpu_to_le16(idle_state << RXON_RX_CHAIN_CNT_POS); 765 if (priv->hw_params.rx_chains_num < active_rx_cnt)
765 766 active_rx_cnt = priv->hw_params.rx_chains_num;
766 if (!is_single && (rx_state >= 2) && 767
767 !test_bit(STATUS_POWER_PMI, &priv->status)) 768 if (priv->hw_params.rx_chains_num < idle_rx_cnt)
769 idle_rx_cnt = priv->hw_params.rx_chains_num;
770
771 rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
772 rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
773
774 priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
775
776 if (!is_single && (active_rx_cnt >= 2) && is_cam)
768 priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; 777 priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
769 else 778 else
770 priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; 779 priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
771 780
772 IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain); 781 IWL_DEBUG_ASSOC("rx_chain=0x%Xi active=%d idle=%d\n",
782 priv->staging_rxon.rx_chain,
783 active_rx_cnt, idle_rx_cnt);
784
785 WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
786 active_rx_cnt < idle_rx_cnt);
773} 787}
774EXPORT_SYMBOL(iwl_set_rxon_chain); 788EXPORT_SYMBOL(iwl_set_rxon_chain);
775 789