diff options
author | Sujith Manoharan <c_manoha@qca.qualcomm.com> | 2013-12-24 00:14:19 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-01-03 15:36:57 -0500 |
commit | 990de2b2e48ac377fb40842a9b04fd940ba78e1b (patch) | |
tree | 61c8d466c704157aaa1d082c7bacac7b1409a6fa /drivers/net | |
parent | 4598702d1b3e0b6aa6694f4c786313a999afbdc9 (diff) |
ath9k: Add HW callbacks for MAC/BB hang checks
This is required for adding separate hang check
routines for AR9002 and AR9003.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_hw.c | 72 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw-ops.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 70 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 3 |
4 files changed, 85 insertions, 70 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 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index bd95eae37d90..0b2550a91c7c 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -112,6 +112,16 @@ static inline void ath9k_hw_init_hang_checks(struct ath_hw *ah) | |||
112 | ath9k_hw_private_ops(ah)->init_hang_checks(ah); | 112 | ath9k_hw_private_ops(ah)->init_hang_checks(ah); |
113 | } | 113 | } |
114 | 114 | ||
115 | static inline bool ath9k_hw_detect_mac_hang(struct ath_hw *ah) | ||
116 | { | ||
117 | return ath9k_hw_private_ops(ah)->detect_mac_hang(ah); | ||
118 | } | ||
119 | |||
120 | static inline bool ath9k_hw_detect_bb_hang(struct ath_hw *ah) | ||
121 | { | ||
122 | return ath9k_hw_private_ops(ah)->detect_bb_hang(ah); | ||
123 | } | ||
124 | |||
115 | /* PHY ops */ | 125 | /* PHY ops */ |
116 | 126 | ||
117 | static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah, | 127 | static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 51c4edd07659..708388063a6b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1529,76 +1529,6 @@ static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) | |||
1529 | } | 1529 | } |
1530 | } | 1530 | } |
1531 | 1531 | ||
1532 | static bool ath9k_hw_check_dcs(u32 dma_dbg, u32 num_dcu_states, | ||
1533 | int *hang_state, int *hang_pos) | ||
1534 | { | ||
1535 | static u32 dcu_chain_state[] = {5, 6, 9}; /* DCU chain stuck states */ | ||
1536 | u32 chain_state, dcs_pos, i; | ||
1537 | |||
1538 | for (dcs_pos = 0; dcs_pos < num_dcu_states; dcs_pos++) { | ||
1539 | chain_state = (dma_dbg >> (5 * dcs_pos)) & 0x1f; | ||
1540 | for (i = 0; i < 3; i++) { | ||
1541 | if (chain_state == dcu_chain_state[i]) { | ||
1542 | *hang_state = chain_state; | ||
1543 | *hang_pos = dcs_pos; | ||
1544 | return true; | ||
1545 | } | ||
1546 | } | ||
1547 | } | ||
1548 | return false; | ||
1549 | } | ||
1550 | |||
1551 | #define DCU_COMPLETE_STATE 1 | ||
1552 | #define DCU_COMPLETE_STATE_MASK 0x3 | ||
1553 | #define NUM_STATUS_READS 50 | ||
1554 | static bool ath9k_hw_detect_mac_hang(struct ath_hw *ah) | ||
1555 | { | ||
1556 | u32 chain_state, comp_state, dcs_reg = AR_DMADBG_4; | ||
1557 | u32 i, hang_pos, hang_state, num_state = 6; | ||
1558 | |||
1559 | comp_state = REG_READ(ah, AR_DMADBG_6); | ||
1560 | |||
1561 | if ((comp_state & DCU_COMPLETE_STATE_MASK) != DCU_COMPLETE_STATE) { | ||
1562 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
1563 | "MAC Hang signature not found at DCU complete\n"); | ||
1564 | return false; | ||
1565 | } | ||
1566 | |||
1567 | chain_state = REG_READ(ah, dcs_reg); | ||
1568 | if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos)) | ||
1569 | goto hang_check_iter; | ||
1570 | |||
1571 | dcs_reg = AR_DMADBG_5; | ||
1572 | num_state = 4; | ||
1573 | chain_state = REG_READ(ah, dcs_reg); | ||
1574 | if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos)) | ||
1575 | goto hang_check_iter; | ||
1576 | |||
1577 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
1578 | "MAC Hang signature 1 not found\n"); | ||
1579 | return false; | ||
1580 | |||
1581 | hang_check_iter: | ||
1582 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
1583 | "DCU registers: chain %08x complete %08x Hang: state %d pos %d\n", | ||
1584 | chain_state, comp_state, hang_state, hang_pos); | ||
1585 | |||
1586 | for (i = 0; i < NUM_STATUS_READS; i++) { | ||
1587 | chain_state = REG_READ(ah, dcs_reg); | ||
1588 | chain_state = (chain_state >> (5 * hang_pos)) & 0x1f; | ||
1589 | comp_state = REG_READ(ah, AR_DMADBG_6); | ||
1590 | |||
1591 | if (((comp_state & DCU_COMPLETE_STATE_MASK) != | ||
1592 | DCU_COMPLETE_STATE) || | ||
1593 | (chain_state != hang_state)) | ||
1594 | return false; | ||
1595 | } | ||
1596 | |||
1597 | ath_dbg(ath9k_hw_common(ah), RESET, "MAC Hang signature 1 found\n"); | ||
1598 | |||
1599 | return true; | ||
1600 | } | ||
1601 | |||
1602 | void ath9k_hw_check_nav(struct ath_hw *ah) | 1532 | void ath9k_hw_check_nav(struct ath_hw *ah) |
1603 | { | 1533 | { |
1604 | struct ath_common *common = ath9k_hw_common(ah); | 1534 | struct ath_common *common = ath9k_hw_common(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 0a3cfc537859..cb930d680392 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -585,6 +585,9 @@ struct ath_hw_radar_conf { | |||
585 | */ | 585 | */ |
586 | struct ath_hw_private_ops { | 586 | struct ath_hw_private_ops { |
587 | void (*init_hang_checks)(struct ath_hw *ah); | 587 | void (*init_hang_checks)(struct ath_hw *ah); |
588 | bool (*detect_mac_hang)(struct ath_hw *ah); | ||
589 | bool (*detect_bb_hang)(struct ath_hw *ah); | ||
590 | |||
588 | /* Calibration ops */ | 591 | /* Calibration ops */ |
589 | void (*init_cal_settings)(struct ath_hw *ah); | 592 | void (*init_cal_settings)(struct ath_hw *ah); |
590 | bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan); | 593 | bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan); |