diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_hw.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_hw.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index f1d3c4aa2396..75a6d85d6ee9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -892,6 +892,77 @@ static void ar9003_hw_init_hang_checks(struct ath_hw *ah) | |||
892 | ah->bb_watchdog_timeout_ms = 25; | 892 | ah->bb_watchdog_timeout_ms = 25; |
893 | } | 893 | } |
894 | 894 | ||
895 | static bool ath9k_hw_check_dcs(u32 dma_dbg, u32 num_dcu_states, | ||
896 | int *hang_state, int *hang_pos) | ||
897 | { | ||
898 | static u32 dcu_chain_state[] = {5, 6, 9}; /* DCU chain stuck states */ | ||
899 | u32 chain_state, dcs_pos, i; | ||
900 | |||
901 | for (dcs_pos = 0; dcs_pos < num_dcu_states; dcs_pos++) { | ||
902 | chain_state = (dma_dbg >> (5 * dcs_pos)) & 0x1f; | ||
903 | for (i = 0; i < 3; i++) { | ||
904 | if (chain_state == dcu_chain_state[i]) { | ||
905 | *hang_state = chain_state; | ||
906 | *hang_pos = dcs_pos; | ||
907 | return true; | ||
908 | } | ||
909 | } | ||
910 | } | ||
911 | return false; | ||
912 | } | ||
913 | |||
914 | #define DCU_COMPLETE_STATE 1 | ||
915 | #define DCU_COMPLETE_STATE_MASK 0x3 | ||
916 | #define NUM_STATUS_READS 50 | ||
917 | |||
918 | static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah) | ||
919 | { | ||
920 | u32 chain_state, comp_state, dcs_reg = AR_DMADBG_4; | ||
921 | u32 i, hang_pos, hang_state, num_state = 6; | ||
922 | |||
923 | comp_state = REG_READ(ah, AR_DMADBG_6); | ||
924 | |||
925 | if ((comp_state & DCU_COMPLETE_STATE_MASK) != DCU_COMPLETE_STATE) { | ||
926 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
927 | "MAC Hang signature not found at DCU complete\n"); | ||
928 | return false; | ||
929 | } | ||
930 | |||
931 | chain_state = REG_READ(ah, dcs_reg); | ||
932 | if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos)) | ||
933 | goto hang_check_iter; | ||
934 | |||
935 | dcs_reg = AR_DMADBG_5; | ||
936 | num_state = 4; | ||
937 | chain_state = REG_READ(ah, dcs_reg); | ||
938 | if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos)) | ||
939 | goto hang_check_iter; | ||
940 | |||
941 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
942 | "MAC Hang signature 1 not found\n"); | ||
943 | return false; | ||
944 | |||
945 | hang_check_iter: | ||
946 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
947 | "DCU registers: chain %08x complete %08x Hang: state %d pos %d\n", | ||
948 | chain_state, comp_state, hang_state, hang_pos); | ||
949 | |||
950 | for (i = 0; i < NUM_STATUS_READS; i++) { | ||
951 | chain_state = REG_READ(ah, dcs_reg); | ||
952 | chain_state = (chain_state >> (5 * hang_pos)) & 0x1f; | ||
953 | comp_state = REG_READ(ah, AR_DMADBG_6); | ||
954 | |||
955 | if (((comp_state & DCU_COMPLETE_STATE_MASK) != | ||
956 | DCU_COMPLETE_STATE) || | ||
957 | (chain_state != hang_state)) | ||
958 | return false; | ||
959 | } | ||
960 | |||
961 | ath_dbg(ath9k_hw_common(ah), RESET, "MAC Hang signature 1 found\n"); | ||
962 | |||
963 | return true; | ||
964 | } | ||
965 | |||
895 | /* Sets up the AR9003 hardware familiy callbacks */ | 966 | /* Sets up the AR9003 hardware familiy callbacks */ |
896 | void ar9003_hw_attach_ops(struct ath_hw *ah) | 967 | void ar9003_hw_attach_ops(struct ath_hw *ah) |
897 | { | 968 | { |
@@ -901,6 +972,7 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) | |||
901 | ar9003_hw_init_mode_regs(ah); | 972 | ar9003_hw_init_mode_regs(ah); |
902 | priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; | 973 | priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; |
903 | priv_ops->init_hang_checks = ar9003_hw_init_hang_checks; | 974 | priv_ops->init_hang_checks = ar9003_hw_init_hang_checks; |
975 | priv_ops->detect_mac_hang = ar9003_hw_detect_mac_hang; | ||
904 | 976 | ||
905 | ops->config_pci_powersave = ar9003_hw_configpcipowersave; | 977 | ops->config_pci_powersave = ar9003_hw_configpcipowersave; |
906 | 978 | ||