diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-calib.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 316 |
1 files changed, 163 insertions, 153 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index c4c5691032a6..c9255def1080 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of version 2 of the GNU General Public License as | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -65,7 +65,7 @@ | |||
65 | 65 | ||
66 | #include "iwl-dev.h" | 66 | #include "iwl-dev.h" |
67 | #include "iwl-core.h" | 67 | #include "iwl-core.h" |
68 | #include "iwl-calib.h" | 68 | #include "iwl-agn-calib.h" |
69 | 69 | ||
70 | /***************************************************************************** | 70 | /***************************************************************************** |
71 | * INIT calibrations framework | 71 | * INIT calibrations framework |
@@ -87,14 +87,14 @@ int iwl_send_calib_results(struct iwl_priv *priv) | |||
87 | 87 | ||
88 | struct iwl_host_cmd hcmd = { | 88 | struct iwl_host_cmd hcmd = { |
89 | .id = REPLY_PHY_CALIBRATION_CMD, | 89 | .id = REPLY_PHY_CALIBRATION_CMD, |
90 | .flags = CMD_SIZE_HUGE, | ||
91 | }; | 90 | }; |
92 | 91 | ||
93 | for (i = 0; i < IWL_CALIB_MAX; i++) { | 92 | for (i = 0; i < IWL_CALIB_MAX; i++) { |
94 | if ((BIT(i) & priv->hw_params.calib_init_cfg) && | 93 | if ((BIT(i) & priv->hw_params.calib_init_cfg) && |
95 | priv->calib_results[i].buf) { | 94 | priv->calib_results[i].buf) { |
96 | hcmd.len = priv->calib_results[i].buf_len; | 95 | hcmd.len[0] = priv->calib_results[i].buf_len; |
97 | hcmd.data = priv->calib_results[i].buf; | 96 | hcmd.data[0] = priv->calib_results[i].buf; |
97 | hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
98 | ret = iwl_send_cmd_sync(priv, &hcmd); | 98 | ret = iwl_send_cmd_sync(priv, &hcmd); |
99 | if (ret) { | 99 | if (ret) { |
100 | IWL_ERR(priv, "Error %d iteration %d\n", | 100 | IWL_ERR(priv, "Error %d iteration %d\n", |
@@ -456,9 +456,9 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) | |||
456 | struct iwl_sensitivity_data *data = NULL; | 456 | struct iwl_sensitivity_data *data = NULL; |
457 | struct iwl_host_cmd cmd_out = { | 457 | struct iwl_host_cmd cmd_out = { |
458 | .id = SENSITIVITY_CMD, | 458 | .id = SENSITIVITY_CMD, |
459 | .len = sizeof(struct iwl_sensitivity_cmd), | 459 | .len = { sizeof(struct iwl_sensitivity_cmd), }, |
460 | .flags = CMD_ASYNC, | 460 | .flags = CMD_ASYNC, |
461 | .data = &cmd, | 461 | .data = { &cmd, }, |
462 | }; | 462 | }; |
463 | 463 | ||
464 | data = &(priv->sensitivity_data); | 464 | data = &(priv->sensitivity_data); |
@@ -491,9 +491,9 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) | |||
491 | struct iwl_sensitivity_data *data = NULL; | 491 | struct iwl_sensitivity_data *data = NULL; |
492 | struct iwl_host_cmd cmd_out = { | 492 | struct iwl_host_cmd cmd_out = { |
493 | .id = SENSITIVITY_CMD, | 493 | .id = SENSITIVITY_CMD, |
494 | .len = sizeof(struct iwl_enhance_sensitivity_cmd), | 494 | .len = { sizeof(struct iwl_enhance_sensitivity_cmd), }, |
495 | .flags = CMD_ASYNC, | 495 | .flags = CMD_ASYNC, |
496 | .data = &cmd, | 496 | .data = { &cmd, }, |
497 | }; | 497 | }; |
498 | 498 | ||
499 | data = &(priv->sensitivity_data); | 499 | data = &(priv->sensitivity_data); |
@@ -605,7 +605,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) | |||
605 | IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret); | 605 | IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret); |
606 | } | 606 | } |
607 | 607 | ||
608 | void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp) | 608 | void iwl_sensitivity_calibration(struct iwl_priv *priv) |
609 | { | 609 | { |
610 | u32 rx_enable_time; | 610 | u32 rx_enable_time; |
611 | u32 fa_cck; | 611 | u32 fa_cck; |
@@ -625,22 +625,15 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp) | |||
625 | 625 | ||
626 | data = &(priv->sensitivity_data); | 626 | data = &(priv->sensitivity_data); |
627 | 627 | ||
628 | if (!iwl_is_associated(priv)) { | 628 | if (!iwl_is_any_associated(priv)) { |
629 | IWL_DEBUG_CALIB(priv, "<< - not associated\n"); | 629 | IWL_DEBUG_CALIB(priv, "<< - not associated\n"); |
630 | return; | 630 | return; |
631 | } | 631 | } |
632 | 632 | ||
633 | spin_lock_irqsave(&priv->lock, flags); | 633 | spin_lock_irqsave(&priv->lock, flags); |
634 | if (priv->cfg->bt_statistics) { | 634 | rx_info = &priv->statistics.rx_non_phy; |
635 | rx_info = &(((struct iwl_bt_notif_statistics *)resp)-> | 635 | ofdm = &priv->statistics.rx_ofdm; |
636 | rx.general.common); | 636 | cck = &priv->statistics.rx_cck; |
637 | ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm); | ||
638 | cck = &(((struct iwl_bt_notif_statistics *)resp)->rx.cck); | ||
639 | } else { | ||
640 | rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general); | ||
641 | ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm); | ||
642 | cck = &(((struct iwl_notif_statistics *)resp)->rx.cck); | ||
643 | } | ||
644 | if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { | 637 | if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { |
645 | IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); | 638 | IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); |
646 | spin_unlock_irqrestore(&priv->lock, flags); | 639 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -731,13 +724,127 @@ static inline u8 find_first_chain(u8 mask) | |||
731 | return CHAIN_C; | 724 | return CHAIN_C; |
732 | } | 725 | } |
733 | 726 | ||
727 | /** | ||
728 | * Run disconnected antenna algorithm to find out which antennas are | ||
729 | * disconnected. | ||
730 | */ | ||
731 | static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | ||
732 | struct iwl_chain_noise_data *data) | ||
733 | { | ||
734 | u32 active_chains = 0; | ||
735 | u32 max_average_sig; | ||
736 | u16 max_average_sig_antenna_i; | ||
737 | u8 num_tx_chains; | ||
738 | u8 first_chain; | ||
739 | u16 i = 0; | ||
740 | |||
741 | average_sig[0] = data->chain_signal_a / | ||
742 | priv->cfg->base_params->chain_noise_num_beacons; | ||
743 | average_sig[1] = data->chain_signal_b / | ||
744 | priv->cfg->base_params->chain_noise_num_beacons; | ||
745 | average_sig[2] = data->chain_signal_c / | ||
746 | priv->cfg->base_params->chain_noise_num_beacons; | ||
747 | |||
748 | if (average_sig[0] >= average_sig[1]) { | ||
749 | max_average_sig = average_sig[0]; | ||
750 | max_average_sig_antenna_i = 0; | ||
751 | active_chains = (1 << max_average_sig_antenna_i); | ||
752 | } else { | ||
753 | max_average_sig = average_sig[1]; | ||
754 | max_average_sig_antenna_i = 1; | ||
755 | active_chains = (1 << max_average_sig_antenna_i); | ||
756 | } | ||
757 | |||
758 | if (average_sig[2] >= max_average_sig) { | ||
759 | max_average_sig = average_sig[2]; | ||
760 | max_average_sig_antenna_i = 2; | ||
761 | active_chains = (1 << max_average_sig_antenna_i); | ||
762 | } | ||
763 | |||
764 | IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n", | ||
765 | average_sig[0], average_sig[1], average_sig[2]); | ||
766 | IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n", | ||
767 | max_average_sig, max_average_sig_antenna_i); | ||
768 | |||
769 | /* Compare signal strengths for all 3 receivers. */ | ||
770 | for (i = 0; i < NUM_RX_CHAINS; i++) { | ||
771 | if (i != max_average_sig_antenna_i) { | ||
772 | s32 rssi_delta = (max_average_sig - average_sig[i]); | ||
773 | |||
774 | /* If signal is very weak, compared with | ||
775 | * strongest, mark it as disconnected. */ | ||
776 | if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS) | ||
777 | data->disconn_array[i] = 1; | ||
778 | else | ||
779 | active_chains |= (1 << i); | ||
780 | IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " | ||
781 | "disconn_array[i] = %d\n", | ||
782 | i, rssi_delta, data->disconn_array[i]); | ||
783 | } | ||
784 | } | ||
785 | |||
786 | /* | ||
787 | * The above algorithm sometimes fails when the ucode | ||
788 | * reports 0 for all chains. It's not clear why that | ||
789 | * happens to start with, but it is then causing trouble | ||
790 | * because this can make us enable more chains than the | ||
791 | * hardware really has. | ||
792 | * | ||
793 | * To be safe, simply mask out any chains that we know | ||
794 | * are not on the device. | ||
795 | */ | ||
796 | active_chains &= priv->hw_params.valid_rx_ant; | ||
797 | |||
798 | num_tx_chains = 0; | ||
799 | for (i = 0; i < NUM_RX_CHAINS; i++) { | ||
800 | /* loops on all the bits of | ||
801 | * priv->hw_setting.valid_tx_ant */ | ||
802 | u8 ant_msk = (1 << i); | ||
803 | if (!(priv->hw_params.valid_tx_ant & ant_msk)) | ||
804 | continue; | ||
805 | |||
806 | num_tx_chains++; | ||
807 | if (data->disconn_array[i] == 0) | ||
808 | /* there is a Tx antenna connected */ | ||
809 | break; | ||
810 | if (num_tx_chains == priv->hw_params.tx_chains_num && | ||
811 | data->disconn_array[i]) { | ||
812 | /* | ||
813 | * If all chains are disconnected | ||
814 | * connect the first valid tx chain | ||
815 | */ | ||
816 | first_chain = | ||
817 | find_first_chain(priv->cfg->valid_tx_ant); | ||
818 | data->disconn_array[first_chain] = 0; | ||
819 | active_chains |= BIT(first_chain); | ||
820 | IWL_DEBUG_CALIB(priv, | ||
821 | "All Tx chains are disconnected W/A - declare %d as connected\n", | ||
822 | first_chain); | ||
823 | break; | ||
824 | } | ||
825 | } | ||
826 | |||
827 | if (active_chains != priv->hw_params.valid_rx_ant && | ||
828 | active_chains != priv->chain_noise_data.active_chains) | ||
829 | IWL_DEBUG_CALIB(priv, | ||
830 | "Detected that not all antennas are connected! " | ||
831 | "Connected: %#x, valid: %#x.\n", | ||
832 | active_chains, priv->hw_params.valid_rx_ant); | ||
833 | |||
834 | /* Save for use within RXON, TX, SCAN commands, etc. */ | ||
835 | data->active_chains = active_chains; | ||
836 | IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", | ||
837 | active_chains); | ||
838 | } | ||
839 | |||
840 | |||
734 | /* | 841 | /* |
735 | * Accumulate 20 beacons of signal and noise statistics for each of | 842 | * Accumulate 16 beacons of signal and noise statistics for each of |
736 | * 3 receivers/antennas/rx-chains, then figure out: | 843 | * 3 receivers/antennas/rx-chains, then figure out: |
737 | * 1) Which antennas are connected. | 844 | * 1) Which antennas are connected. |
738 | * 2) Differential rx gain settings to balance the 3 receivers. | 845 | * 2) Differential rx gain settings to balance the 3 receivers. |
739 | */ | 846 | */ |
740 | void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | 847 | void iwl_chain_noise_calibration(struct iwl_priv *priv) |
741 | { | 848 | { |
742 | struct iwl_chain_noise_data *data = NULL; | 849 | struct iwl_chain_noise_data *data = NULL; |
743 | 850 | ||
@@ -749,8 +856,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
749 | u32 chain_sig_c; | 856 | u32 chain_sig_c; |
750 | u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; | 857 | u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; |
751 | u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; | 858 | u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; |
752 | u32 max_average_sig; | ||
753 | u16 max_average_sig_antenna_i; | ||
754 | u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE; | 859 | u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE; |
755 | u16 min_average_noise_antenna_i = INITIALIZATION_VALUE; | 860 | u16 min_average_noise_antenna_i = INITIALIZATION_VALUE; |
756 | u16 i = 0; | 861 | u16 i = 0; |
@@ -758,11 +863,15 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
758 | u16 stat_chnum = INITIALIZATION_VALUE; | 863 | u16 stat_chnum = INITIALIZATION_VALUE; |
759 | u8 rxon_band24; | 864 | u8 rxon_band24; |
760 | u8 stat_band24; | 865 | u8 stat_band24; |
761 | u32 active_chains = 0; | ||
762 | u8 num_tx_chains; | ||
763 | unsigned long flags; | 866 | unsigned long flags; |
764 | struct statistics_rx_non_phy *rx_info; | 867 | struct statistics_rx_non_phy *rx_info; |
765 | u8 first_chain; | 868 | |
869 | /* | ||
870 | * MULTI-FIXME: | ||
871 | * When we support multiple interfaces on different channels, | ||
872 | * this must be modified/fixed. | ||
873 | */ | ||
874 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
766 | 875 | ||
767 | if (priv->disable_chain_noise_cal) | 876 | if (priv->disable_chain_noise_cal) |
768 | return; | 877 | return; |
@@ -780,34 +889,20 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
780 | } | 889 | } |
781 | 890 | ||
782 | spin_lock_irqsave(&priv->lock, flags); | 891 | spin_lock_irqsave(&priv->lock, flags); |
783 | if (priv->cfg->bt_statistics) { | 892 | |
784 | rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)-> | 893 | rx_info = &priv->statistics.rx_non_phy; |
785 | rx.general.common); | 894 | |
786 | } else { | ||
787 | rx_info = &(((struct iwl_notif_statistics *)stat_resp)-> | ||
788 | rx.general); | ||
789 | } | ||
790 | if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { | 895 | if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { |
791 | IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); | 896 | IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); |
792 | spin_unlock_irqrestore(&priv->lock, flags); | 897 | spin_unlock_irqrestore(&priv->lock, flags); |
793 | return; | 898 | return; |
794 | } | 899 | } |
795 | 900 | ||
796 | rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK); | 901 | rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK); |
797 | rxon_chnum = le16_to_cpu(priv->staging_rxon.channel); | 902 | rxon_chnum = le16_to_cpu(ctx->staging.channel); |
798 | if (priv->cfg->bt_statistics) { | 903 | stat_band24 = |
799 | stat_band24 = !!(((struct iwl_bt_notif_statistics *) | 904 | !!(priv->statistics.flag & STATISTICS_REPLY_FLG_BAND_24G_MSK); |
800 | stat_resp)->flag & | 905 | stat_chnum = le32_to_cpu(priv->statistics.flag) >> 16; |
801 | STATISTICS_REPLY_FLG_BAND_24G_MSK); | ||
802 | stat_chnum = le32_to_cpu(((struct iwl_bt_notif_statistics *) | ||
803 | stat_resp)->flag) >> 16; | ||
804 | } else { | ||
805 | stat_band24 = !!(((struct iwl_notif_statistics *) | ||
806 | stat_resp)->flag & | ||
807 | STATISTICS_REPLY_FLG_BAND_24G_MSK); | ||
808 | stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *) | ||
809 | stat_resp)->flag) >> 16; | ||
810 | } | ||
811 | 906 | ||
812 | /* Make sure we accumulate data for just the associated channel | 907 | /* Make sure we accumulate data for just the associated channel |
813 | * (even if scanning). */ | 908 | * (even if scanning). */ |
@@ -855,114 +950,29 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
855 | /* If this is the "chain_noise_num_beacons", determine: | 950 | /* If this is the "chain_noise_num_beacons", determine: |
856 | * 1) Disconnected antennas (using signal strengths) | 951 | * 1) Disconnected antennas (using signal strengths) |
857 | * 2) Differential gain (using silence noise) to balance receivers */ | 952 | * 2) Differential gain (using silence noise) to balance receivers */ |
858 | if (data->beacon_count != priv->cfg->chain_noise_num_beacons) | 953 | if (data->beacon_count != |
954 | priv->cfg->base_params->chain_noise_num_beacons) | ||
859 | return; | 955 | return; |
860 | 956 | ||
861 | /* Analyze signal for disconnected antenna */ | 957 | /* Analyze signal for disconnected antenna */ |
862 | average_sig[0] = | 958 | if (priv->cfg->bt_params && |
863 | (data->chain_signal_a) / priv->cfg->chain_noise_num_beacons; | 959 | priv->cfg->bt_params->advanced_bt_coexist) { |
864 | average_sig[1] = | 960 | /* Disable disconnected antenna algorithm for advanced |
865 | (data->chain_signal_b) / priv->cfg->chain_noise_num_beacons; | 961 | bt coex, assuming valid antennas are connected */ |
866 | average_sig[2] = | 962 | data->active_chains = priv->hw_params.valid_rx_ant; |
867 | (data->chain_signal_c) / priv->cfg->chain_noise_num_beacons; | 963 | for (i = 0; i < NUM_RX_CHAINS; i++) |
868 | 964 | if (!(data->active_chains & (1<<i))) | |
869 | if (average_sig[0] >= average_sig[1]) { | ||
870 | max_average_sig = average_sig[0]; | ||
871 | max_average_sig_antenna_i = 0; | ||
872 | active_chains = (1 << max_average_sig_antenna_i); | ||
873 | } else { | ||
874 | max_average_sig = average_sig[1]; | ||
875 | max_average_sig_antenna_i = 1; | ||
876 | active_chains = (1 << max_average_sig_antenna_i); | ||
877 | } | ||
878 | |||
879 | if (average_sig[2] >= max_average_sig) { | ||
880 | max_average_sig = average_sig[2]; | ||
881 | max_average_sig_antenna_i = 2; | ||
882 | active_chains = (1 << max_average_sig_antenna_i); | ||
883 | } | ||
884 | |||
885 | IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n", | ||
886 | average_sig[0], average_sig[1], average_sig[2]); | ||
887 | IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n", | ||
888 | max_average_sig, max_average_sig_antenna_i); | ||
889 | |||
890 | /* Compare signal strengths for all 3 receivers. */ | ||
891 | for (i = 0; i < NUM_RX_CHAINS; i++) { | ||
892 | if (i != max_average_sig_antenna_i) { | ||
893 | s32 rssi_delta = (max_average_sig - average_sig[i]); | ||
894 | |||
895 | /* If signal is very weak, compared with | ||
896 | * strongest, mark it as disconnected. */ | ||
897 | if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS) | ||
898 | data->disconn_array[i] = 1; | 965 | data->disconn_array[i] = 1; |
899 | else | 966 | } else |
900 | active_chains |= (1 << i); | 967 | iwl_find_disconn_antenna(priv, average_sig, data); |
901 | IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " | ||
902 | "disconn_array[i] = %d\n", | ||
903 | i, rssi_delta, data->disconn_array[i]); | ||
904 | } | ||
905 | } | ||
906 | |||
907 | /* | ||
908 | * The above algorithm sometimes fails when the ucode | ||
909 | * reports 0 for all chains. It's not clear why that | ||
910 | * happens to start with, but it is then causing trouble | ||
911 | * because this can make us enable more chains than the | ||
912 | * hardware really has. | ||
913 | * | ||
914 | * To be safe, simply mask out any chains that we know | ||
915 | * are not on the device. | ||
916 | */ | ||
917 | active_chains &= priv->hw_params.valid_rx_ant; | ||
918 | |||
919 | num_tx_chains = 0; | ||
920 | for (i = 0; i < NUM_RX_CHAINS; i++) { | ||
921 | /* loops on all the bits of | ||
922 | * priv->hw_setting.valid_tx_ant */ | ||
923 | u8 ant_msk = (1 << i); | ||
924 | if (!(priv->hw_params.valid_tx_ant & ant_msk)) | ||
925 | continue; | ||
926 | |||
927 | num_tx_chains++; | ||
928 | if (data->disconn_array[i] == 0) | ||
929 | /* there is a Tx antenna connected */ | ||
930 | break; | ||
931 | if (num_tx_chains == priv->hw_params.tx_chains_num && | ||
932 | data->disconn_array[i]) { | ||
933 | /* | ||
934 | * If all chains are disconnected | ||
935 | * connect the first valid tx chain | ||
936 | */ | ||
937 | first_chain = | ||
938 | find_first_chain(priv->cfg->valid_tx_ant); | ||
939 | data->disconn_array[first_chain] = 0; | ||
940 | active_chains |= BIT(first_chain); | ||
941 | IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n", | ||
942 | first_chain); | ||
943 | break; | ||
944 | } | ||
945 | } | ||
946 | |||
947 | if (active_chains != priv->hw_params.valid_rx_ant && | ||
948 | active_chains != priv->chain_noise_data.active_chains) | ||
949 | IWL_DEBUG_CALIB(priv, | ||
950 | "Detected that not all antennas are connected! " | ||
951 | "Connected: %#x, valid: %#x.\n", | ||
952 | active_chains, priv->hw_params.valid_rx_ant); | ||
953 | |||
954 | /* Save for use within RXON, TX, SCAN commands, etc. */ | ||
955 | priv->chain_noise_data.active_chains = active_chains; | ||
956 | IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", | ||
957 | active_chains); | ||
958 | 968 | ||
959 | /* Analyze noise for rx balance */ | 969 | /* Analyze noise for rx balance */ |
960 | average_noise[0] = | 970 | average_noise[0] = data->chain_noise_a / |
961 | ((data->chain_noise_a) / priv->cfg->chain_noise_num_beacons); | 971 | priv->cfg->base_params->chain_noise_num_beacons; |
962 | average_noise[1] = | 972 | average_noise[1] = data->chain_noise_b / |
963 | ((data->chain_noise_b) / priv->cfg->chain_noise_num_beacons); | 973 | priv->cfg->base_params->chain_noise_num_beacons; |
964 | average_noise[2] = | 974 | average_noise[2] = data->chain_noise_c / |
965 | ((data->chain_noise_c) / priv->cfg->chain_noise_num_beacons); | 975 | priv->cfg->base_params->chain_noise_num_beacons; |
966 | 976 | ||
967 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 977 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
968 | if (!(data->disconn_array[i]) && | 978 | if (!(data->disconn_array[i]) && |