aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
diff options
context:
space:
mode:
authorShanyu Zhao <shanyu.zhao@intel.com>2010-11-10 12:56:48 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:26:56 -0500
commit3031242b31dcd76e1c6b1c1718cfee872f55d5af (patch)
tree772f806acc6c855948573455b5c900e8eefb63ed /drivers/net/wireless/iwlwifi/iwl-agn-calib.c
parentb2769b84d86a2d29fa131a763d2b23b112834420 (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>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-calib.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c231
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 */
739static 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 /