diff options
author | Shanyu Zhao <shanyu.zhao@intel.com> | 2010-11-10 12:56:48 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-15 13:26:56 -0500 |
commit | 3031242b31dcd76e1c6b1c1718cfee872f55d5af (patch) | |
tree | 772f806acc6c855948573455b5c900e8eefb63ed | |
parent | b2769b84d86a2d29fa131a763d2b23b112834420 (diff) |
iwlwifi: seperate disconnected antenna function
Disconnected antenna algorithm is seperated into its own function from chain noise
calibration routine for better code management.
Signed-off-by: Shanyu Zhao <shanyu.zhao@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 231 |
1 files changed, 123 insertions, 108 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index e2019e756936..b4cfc3c16285 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -732,8 +732,128 @@ static inline u8 find_first_chain(u8 mask) | |||
732 | return CHAIN_C; | 732 | return CHAIN_C; |
733 | } | 733 | } |
734 | 734 | ||
735 | /** | ||
736 | * Run disconnected antenna algorithm to find out which antennas are | ||
737 | * disconnected. | ||
738 | */ | ||
739 | static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | ||
740 | struct iwl_chain_noise_data *data) | ||
741 | { | ||
742 | u32 active_chains = 0; | ||
743 | u32 max_average_sig; | ||
744 | u16 max_average_sig_antenna_i; | ||
745 | u8 num_tx_chains; | ||
746 | u8 first_chain; | ||
747 | u16 i = 0; | ||
748 | |||
749 | average_sig[0] = data->chain_signal_a / | ||
750 | priv->cfg->base_params->chain_noise_num_beacons; | ||
751 | average_sig[1] = data->chain_signal_b / | ||
752 | priv->cfg->base_params->chain_noise_num_beacons; | ||
753 | average_sig[2] = data->chain_signal_c / | ||
754 | priv->cfg->base_params->chain_noise_num_beacons; | ||
755 | |||
756 | if (average_sig[0] >= average_sig[1]) { | ||
757 | max_average_sig = average_sig[0]; | ||
758 | max_average_sig_antenna_i = 0; | ||
759 | active_chains = (1 << max_average_sig_antenna_i); | ||
760 | } else { | ||
761 | max_average_sig = average_sig[1]; | ||
762 | max_average_sig_antenna_i = 1; | ||
763 | active_chains = (1 << max_average_sig_antenna_i); | ||
764 | } | ||
765 | |||
766 | if (average_sig[2] >= max_average_sig) { | ||
767 | max_average_sig = average_sig[2]; | ||
768 | max_average_sig_antenna_i = 2; | ||
769 | active_chains = (1 << max_average_sig_antenna_i); | ||
770 | } | ||
771 | |||
772 | IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n", | ||
773 | average_sig[0], average_sig[1], average_sig[2]); | ||
774 | IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n", | ||
775 | max_average_sig, max_average_sig_antenna_i); | ||
776 | |||
777 | /* Compare signal strengths for all 3 receivers. */ | ||
778 | for (i = 0; i < NUM_RX_CHAINS; i++) { | ||
779 | if (i != max_average_sig_antenna_i) { | ||
780 | s32 rssi_delta = (max_average_sig - average_sig[i]); | ||
781 | |||
782 | /* If signal is very weak, compared with | ||
783 | * strongest, mark it as disconnected. */ | ||
784 | if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS) | ||
785 | data->disconn_array[i] = 1; | ||
786 | else | ||
787 | active_chains |= (1 << i); | ||
788 | IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " | ||
789 | "disconn_array[i] = %d\n", | ||
790 | i, rssi_delta, data->disconn_array[i]); | ||
791 | } | ||
792 | } | ||
793 | |||
794 | /* | ||
795 | * The above algorithm sometimes fails when the ucode | ||
796 | * reports 0 for all chains. It's not clear why that | ||
797 | * happens to start with, but it is then causing trouble | ||
798 | * because this can make us enable more chains than the | ||
799 | * hardware really has. | ||
800 | * | ||
801 | * To be safe, simply mask out any chains that we know | ||
802 | * are not on the device. | ||
803 | */ | ||
804 | if (priv->cfg->bt_params && | ||
805 | priv->cfg->bt_params->advanced_bt_coexist && | ||
806 | priv->bt_full_concurrent) { | ||
807 | /* operated as 1x1 in full concurrency mode */ | ||
808 | active_chains &= first_antenna(priv->hw_params.valid_rx_ant); | ||
809 | } else | ||
810 | active_chains &= priv->hw_params.valid_rx_ant; | ||
811 | |||
812 | num_tx_chains = 0; | ||
813 | for (i = 0; i < NUM_RX_CHAINS; i++) { | ||
814 | /* loops on all the bits of | ||
815 | * priv->hw_setting.valid_tx_ant */ | ||
816 | u8 ant_msk = (1 << i); | ||
817 | if (!(priv->hw_params.valid_tx_ant & ant_msk)) | ||
818 | continue; | ||
819 | |||
820 | num_tx_chains++; | ||
821 | if (data->disconn_array[i] == 0) | ||
822 | /* there is a Tx antenna connected */ | ||
823 | break; | ||
824 | if (num_tx_chains == priv->hw_params.tx_chains_num && | ||
825 | data->disconn_array[i]) { | ||
826 | /* | ||
827 | * If all chains are disconnected | ||
828 | * connect the first valid tx chain | ||
829 | */ | ||
830 | first_chain = | ||
831 | find_first_chain(priv->cfg->valid_tx_ant); | ||
832 | data->disconn_array[first_chain] = 0; | ||
833 | active_chains |= BIT(first_chain); | ||
834 | IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected \ | ||
835 | W/A - declare %d as connected\n", | ||
836 | first_chain); | ||
837 | break; | ||
838 | } | ||
839 | } | ||
840 | |||
841 | if (active_chains != priv->hw_params.valid_rx_ant && | ||
842 | active_chains != priv->chain_noise_data.active_chains) | ||
843 | IWL_DEBUG_CALIB(priv, | ||
844 | "Detected that not all antennas are connected! " | ||
845 | "Connected: %#x, valid: %#x.\n", | ||
846 | active_chains, priv->hw_params.valid_rx_ant); | ||
847 | |||
848 | /* Save for use within RXON, TX, SCAN commands, etc. */ | ||
849 | data->active_chains = active_chains; | ||
850 | IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", | ||
851 | active_chains); | ||
852 | } | ||
853 | |||
854 | |||
735 | /* | 855 | /* |
736 | * Accumulate 20 beacons of signal and noise statistics for each of | 856 | * Accumulate 16 beacons of signal and noise statistics for each of |
737 | * 3 receivers/antennas/rx-chains, then figure out: | 857 | * 3 receivers/antennas/rx-chains, then figure out: |
738 | * 1) Which antennas are connected. | 858 | * 1) Which antennas are connected. |
739 | * 2) Differential rx gain settings to balance the 3 receivers. | 859 | * 2) Differential rx gain settings to balance the 3 receivers. |
@@ -750,8 +870,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
750 | u32 chain_sig_c; | 870 | u32 chain_sig_c; |
751 | u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; | 871 | u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; |
752 | u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; | 872 | u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; |
753 | u32 max_average_sig; | ||
754 | u16 max_average_sig_antenna_i; | ||
755 | u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE; | 873 | u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE; |
756 | u16 min_average_noise_antenna_i = INITIALIZATION_VALUE; | 874 | u16 min_average_noise_antenna_i = INITIALIZATION_VALUE; |
757 | u16 i = 0; | 875 | u16 i = 0; |
@@ -759,11 +877,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
759 | u16 stat_chnum = INITIALIZATION_VALUE; | 877 | u16 stat_chnum = INITIALIZATION_VALUE; |
760 | u8 rxon_band24; | 878 | u8 rxon_band24; |
761 | u8 stat_band24; | 879 | u8 stat_band24; |
762 | u32 active_chains = 0; | ||
763 | u8 num_tx_chains; | ||
764 | unsigned long flags; | 880 | unsigned long flags; |
765 | struct statistics_rx_non_phy *rx_info; | 881 | struct statistics_rx_non_phy *rx_info; |
766 | u8 first_chain; | 882 | |
767 | /* | 883 | /* |
768 | * MULTI-FIXME: | 884 | * MULTI-FIXME: |
769 | * When we support multiple interfaces on different channels, | 885 | * When we support multiple interfaces on different channels, |
@@ -869,108 +985,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
869 | return; | 985 | return; |
870 | 986 | ||
871 | /* Analyze signal for disconnected antenna */ | 987 | /* Analyze signal for disconnected antenna */ |
872 | average_sig[0] = data->chain_signal_a / | 988 | iwl_find_disconn_antenna(priv, average_sig, data); |
873 | priv->cfg->base_params->chain_noise_num_beacons; | ||
874 | average_sig[1] = data->chain_signal_b / | ||
875 | priv->cfg->base_params->chain_noise_num_beacons; | ||
876 | average_sig[2] = data->chain_signal_c / | ||
877 | priv->cfg->base_params->chain_noise_num_beacons; | ||
878 | |||
879 | if (average_sig[0] >= average_sig[1]) { | ||
880 | max_average_sig = average_sig[0]; | ||
881 | max_average_sig_antenna_i = 0; | ||
882 | active_chains = (1 << max_average_sig_antenna_i); | ||
883 | } else { | ||
884 | max_average_sig = average_sig[1]; | ||
885 | max_average_sig_antenna_i = 1; | ||
886 | active_chains = (1 << max_average_sig_antenna_i); | ||
887 | } | ||
888 | |||
889 | if (average_sig[2] >= max_average_sig) { | ||
890 | max_average_sig = average_sig[2]; | ||
891 | max_average_sig_antenna_i = 2; | ||
892 | active_chains = (1 << max_average_sig_antenna_i); | ||
893 | } | ||
894 | |||
895 | IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n", | ||
896 | average_sig[0], average_sig[1], average_sig[2]); | ||
897 | IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n", | ||
898 | max_average_sig, max_average_sig_antenna_i); | ||
899 | |||
900 | /* Compare signal strengths for all 3 receivers. */ | ||
901 | for (i = 0; i < NUM_RX_CHAINS; i++) { | ||
902 | if (i != max_average_sig_antenna_i) { | ||
903 | s32 rssi_delta = (max_average_sig - average_sig[i]); | ||
904 | |||
905 | /* If signal is very weak, compared with | ||
906 | * strongest, mark it as disconnected. */ | ||
907 | if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS) | ||
908 | data->disconn_array[i] = 1; | ||
909 | else | ||
910 | active_chains |= (1 << i); | ||
911 | IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " | ||
912 | "disconn_array[i] = %d\n", | ||
913 | i, rssi_delta, data->disconn_array[i]); | ||
914 | } | ||
915 | } | ||
916 | |||
917 | /* | ||
918 | * The above algorithm sometimes fails when the ucode | ||
919 | * reports 0 for all chains. It's not clear why that | ||
920 | * happens to start with, but it is then causing trouble | ||
921 | * because this can make us enable more chains than the | ||
922 | * hardware really has. | ||
923 | * | ||
924 | * To be safe, simply mask out any chains that we know | ||
925 | * are not on the device. | ||
926 | */ | ||
927 | if (priv->cfg->bt_params && | ||
928 | priv->cfg->bt_params->advanced_bt_coexist && | ||
929 | priv->bt_full_concurrent) { | ||
930 | /* operated as 1x1 in full concurrency mode */ | ||
931 | active_chains &= first_antenna(priv->hw_params.valid_rx_ant); | ||
932 | } else | ||
933 | active_chains &= priv->hw_params.valid_rx_ant; | ||
934 | |||
935 | num_tx_chains = 0; | ||
936 | for (i = 0; i < NUM_RX_CHAINS; i++) { | ||
937 | /* loops on all the bits of | ||
938 | * priv->hw_setting.valid_tx_ant */ | ||
939 | u8 ant_msk = (1 << i); | ||
940 | if (!(priv->hw_params.valid_tx_ant & ant_msk)) | ||
941 | continue; | ||
942 | |||
943 | num_tx_chains++; | ||
944 | if (data->disconn_array[i] == 0) | ||
945 | /* there is a Tx antenna connected */ | ||
946 | break; | ||
947 | if (num_tx_chains == priv->hw_params.tx_chains_num && | ||
948 | data->disconn_array[i]) { | ||
949 | /* | ||
950 | * If all chains are disconnected | ||
951 | * connect the first valid tx chain | ||
952 | */ | ||
953 | first_chain = | ||
954 | find_first_chain(priv->cfg->valid_tx_ant); | ||
955 | data->disconn_array[first_chain] = 0; | ||
956 | active_chains |= BIT(first_chain); | ||
957 | IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n", | ||
958 | first_chain); | ||
959 | break; | ||
960 | } | ||
961 | } | ||
962 | |||
963 | if (active_chains != priv->hw_params.valid_rx_ant && | ||
964 | active_chains != priv->chain_noise_data.active_chains) | ||
965 | IWL_DEBUG_CALIB(priv, | ||
966 | "Detected that not all antennas are connected! " | ||
967 | "Connected: %#x, valid: %#x.\n", | ||
968 | active_chains, priv->hw_params.valid_rx_ant); | ||
969 | |||
970 | /* Save for use within RXON, TX, SCAN commands, etc. */ | ||
971 | priv->chain_noise_data.active_chains = active_chains; | ||
972 | IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", | ||
973 | active_chains); | ||
974 | 989 | ||
975 | /* Analyze noise for rx balance */ | 990 | /* Analyze noise for rx balance */ |
976 | average_noise[0] = data->chain_noise_a / | 991 | average_noise[0] = data->chain_noise_a / |