diff options
author | David S. Miller <davem@davemloft.net> | 2008-09-03 17:32:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-03 17:32:33 -0400 |
commit | 56e9c0a6eb4918ae010aa4689e4481ab67986a0c (patch) | |
tree | ae92769a6f62c01be0e5d0d73a5aa6ddd81dde76 /drivers/net/wireless/iwlwifi/iwl-core.c | |
parent | 6c00055a819ce8a6e2c3af2f65d4ea1a8559c491 (diff) | |
parent | 9aab3e3ee6f256a1eaabc275e0748132966f963d (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 77 |
1 files changed, 46 insertions, 31 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c72f72579bea..80f2f84defa8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -592,12 +592,11 @@ static void iwlcore_free_geos(struct iwl_priv *priv) | |||
592 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); | 592 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); |
593 | } | 593 | } |
594 | 594 | ||
595 | static u8 is_single_rx_stream(struct iwl_priv *priv) | 595 | static bool is_single_rx_stream(struct iwl_priv *priv) |
596 | { | 596 | { |
597 | return !priv->current_ht_config.is_ht || | 597 | return !priv->current_ht_config.is_ht || |
598 | ((priv->current_ht_config.supp_mcs_set[1] == 0) && | 598 | ((priv->current_ht_config.supp_mcs_set[1] == 0) && |
599 | (priv->current_ht_config.supp_mcs_set[2] == 0)) || | 599 | (priv->current_ht_config.supp_mcs_set[2] == 0)); |
600 | priv->ps_mode == IWL_MIMO_PS_STATIC; | ||
601 | } | 600 | } |
602 | 601 | ||
603 | static u8 iwl_is_channel_extension(struct iwl_priv *priv, | 602 | static u8 iwl_is_channel_extension(struct iwl_priv *priv, |
@@ -704,33 +703,39 @@ EXPORT_SYMBOL(iwl_set_rxon_ht); | |||
704 | * 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. |
705 | * This does not determine *which* chains to use, just how many. | 704 | * This does not determine *which* chains to use, just how many. |
706 | */ | 705 | */ |
707 | static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv, | 706 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) |
708 | u8 *idle_state, u8 *rx_state) | ||
709 | { | 707 | { |
710 | u8 is_single = is_single_rx_stream(priv); | 708 | bool is_single = is_single_rx_stream(priv); |
711 | u8 is_cam = test_bit(STATUS_POWER_PMI, &priv->status) ? 0 : 1; | 709 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); |
712 | 710 | ||
713 | /* # of Rx chains to use when expecting MIMO. */ | 711 | /* # of Rx chains to use when expecting MIMO. */ |
714 | 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))) |
715 | *rx_state = 2; | 713 | return 2; |
716 | else | 714 | else |
717 | *rx_state = 3; | 715 | return 3; |
716 | } | ||
718 | 717 | ||
718 | static 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); | ||
719 | /* # Rx chains when idling and maybe trying to save power */ | 722 | /* # Rx chains when idling and maybe trying to save power */ |
720 | switch (priv->ps_mode) { | 723 | switch (priv->ps_mode) { |
721 | case IWL_MIMO_PS_STATIC: | 724 | case IWL_MIMO_PS_STATIC: |
722 | case IWL_MIMO_PS_DYNAMIC: | 725 | case IWL_MIMO_PS_DYNAMIC: |
723 | *idle_state = (is_cam) ? 2 : 1; | 726 | idle_cnt = (is_cam) ? 2 : 1; |
724 | break; | 727 | break; |
725 | case IWL_MIMO_PS_NONE: | 728 | case IWL_MIMO_PS_NONE: |
726 | *idle_state = (is_cam) ? *rx_state : 1; | 729 | idle_cnt = (is_cam) ? active_cnt : 1; |
727 | break; | 730 | break; |
731 | case IWL_MIMO_PS_INVALID: | ||
728 | default: | 732 | default: |
729 | *idle_state = 1; | 733 | IWL_ERROR("invalide mimo ps mode %d\n", priv->ps_mode); |
734 | WARN_ON(1); | ||
735 | idle_cnt = -1; | ||
730 | break; | 736 | break; |
731 | } | 737 | } |
732 | 738 | return idle_cnt; | |
733 | return 0; | ||
734 | } | 739 | } |
735 | 740 | ||
736 | /** | 741 | /** |
@@ -741,34 +746,44 @@ static int iwlcore_get_rx_chain_counter(struct iwl_priv *priv, | |||
741 | */ | 746 | */ |
742 | void iwl_set_rxon_chain(struct iwl_priv *priv) | 747 | void iwl_set_rxon_chain(struct iwl_priv *priv) |
743 | { | 748 | { |
744 | u8 is_single = is_single_rx_stream(priv); | 749 | bool is_single = is_single_rx_stream(priv); |
745 | u8 idle_state, rx_state; | 750 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); |
746 | 751 | u8 idle_rx_cnt, active_rx_cnt; | |
747 | priv->staging_rxon.rx_chain = 0; | 752 | u16 rx_chain; |
748 | rx_state = idle_state = 3; | ||
749 | 753 | ||
750 | /* Tell uCode which antennas are actually connected. | 754 | /* Tell uCode which antennas are actually connected. |
751 | * Before first association, we assume all antennas are connected. | 755 | * Before first association, we assume all antennas are connected. |
752 | * Just after first association, iwl_chain_noise_calibration() | 756 | * Just after first association, iwl_chain_noise_calibration() |
753 | * checks which antennas actually *are* connected. */ | 757 | * checks which antennas actually *are* connected. */ |
754 | priv->staging_rxon.rx_chain |= | 758 | rx_chain = priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; |
755 | cpu_to_le16(priv->hw_params.valid_rx_ant << | ||
756 | RXON_RX_CHAIN_VALID_POS); | ||
757 | 759 | ||
758 | /* How many receivers should we use? */ | 760 | /* How many receivers should we use? */ |
759 | iwlcore_get_rx_chain_counter(priv, &idle_state, &rx_state); | 761 | active_rx_cnt = iwl_get_active_rx_chain_count(priv); |
760 | priv->staging_rxon.rx_chain |= | 762 | idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt); |
761 | cpu_to_le16(rx_state << RXON_RX_CHAIN_MIMO_CNT_POS); | 763 | |
762 | priv->staging_rxon.rx_chain |= | 764 | /* correct rx chain count accoridng hw settings */ |
763 | cpu_to_le16(idle_state << RXON_RX_CHAIN_CNT_POS); | 765 | if (priv->hw_params.rx_chains_num < active_rx_cnt) |
764 | 766 | active_rx_cnt = priv->hw_params.rx_chains_num; | |
765 | if (!is_single && (rx_state >= 2) && | 767 | |
766 | !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) | ||
767 | priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; | 777 | priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; |
768 | else | 778 | else |
769 | priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; | 779 | priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; |
770 | 780 | ||
771 | 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); | ||
772 | } | 787 | } |
773 | EXPORT_SYMBOL(iwl_set_rxon_chain); | 788 | EXPORT_SYMBOL(iwl_set_rxon_chain); |
774 | 789 | ||