diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2009-02-16 02:53:20 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-27 14:52:37 -0500 |
commit | 0caa7b14f36e8c3c43dd9294a960ae55cafe07fb (patch) | |
tree | 13a878857346d4bb67e57b31f6ab25a03ed4c6d7 | |
parent | 70768496db9ee27d53d3d03d50c93fbf4c0198a0 (diff) |
ath9k: Fix HW wait timeout
RX and calibration have different timeout requirements.
This patch fixes it by changing the HW wait routine
to accept a timeout value.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath9k/calib.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/hw.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/hw.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/mac.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/pci.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/recv.c | 1 |
6 files changed, 41 insertions, 18 deletions
diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index e5abe6564ca7..93c6e1f72353 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c | |||
@@ -893,7 +893,8 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, | |||
893 | AR_PHY_AGC_CONTROL_CAL); | 893 | AR_PHY_AGC_CONTROL_CAL); |
894 | 894 | ||
895 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | 895 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, |
896 | AR_PHY_AGC_CONTROL_CAL, 0)) { | 896 | AR_PHY_AGC_CONTROL_CAL, 0, |
897 | AH_WAIT_TIMEOUT)) { | ||
897 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 898 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, |
898 | "offset calibration failed to complete in 1ms; " | 899 | "offset calibration failed to complete in 1ms; " |
899 | "noisy environment?\n"); | 900 | "noisy environment?\n"); |
@@ -910,7 +911,8 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, | |||
910 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | 911 | REG_READ(ah, AR_PHY_AGC_CONTROL) | |
911 | AR_PHY_AGC_CONTROL_CAL); | 912 | AR_PHY_AGC_CONTROL_CAL); |
912 | 913 | ||
913 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { | 914 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, |
915 | 0, AH_WAIT_TIMEOUT)) { | ||
914 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 916 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, |
915 | "offset calibration failed to complete in 1ms; " | 917 | "offset calibration failed to complete in 1ms; " |
916 | "noisy environment?\n"); | 918 | "noisy environment?\n"); |
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 1c02358b31f5..eeee5b808154 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -84,11 +84,13 @@ static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) | |||
84 | return ath9k_hw_mac_clks(ah, usecs); | 84 | return ath9k_hw_mac_clks(ah, usecs); |
85 | } | 85 | } |
86 | 86 | ||
87 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val) | 87 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) |
88 | { | 88 | { |
89 | int i; | 89 | int i; |
90 | 90 | ||
91 | for (i = 0; i < (AH_TIMEOUT / AH_TIME_QUANTUM); i++) { | 91 | BUG_ON(timeout < AH_TIME_QUANTUM); |
92 | |||
93 | for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) { | ||
92 | if ((REG_READ(ah, reg) & mask) == val) | 94 | if ((REG_READ(ah, reg) & mask) == val) |
93 | return true; | 95 | return true; |
94 | 96 | ||
@@ -96,8 +98,8 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val) | |||
96 | } | 98 | } |
97 | 99 | ||
98 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | 100 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, |
99 | "timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", | 101 | "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", |
100 | reg, REG_READ(ah, reg), mask, val); | 102 | timeout, reg, REG_READ(ah, reg), mask, val); |
101 | 103 | ||
102 | return false; | 104 | return false; |
103 | } | 105 | } |
@@ -1516,7 +1518,7 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
1516 | udelay(50); | 1518 | udelay(50); |
1517 | 1519 | ||
1518 | REG_WRITE(ah, AR_RTC_RC, 0); | 1520 | REG_WRITE(ah, AR_RTC_RC, 0); |
1519 | if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) { | 1521 | if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { |
1520 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | 1522 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, |
1521 | "RTC stuck in MAC reset\n"); | 1523 | "RTC stuck in MAC reset\n"); |
1522 | return false; | 1524 | return false; |
@@ -1545,7 +1547,8 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1545 | if (!ath9k_hw_wait(ah, | 1547 | if (!ath9k_hw_wait(ah, |
1546 | AR_RTC_STATUS, | 1548 | AR_RTC_STATUS, |
1547 | AR_RTC_STATUS_M, | 1549 | AR_RTC_STATUS_M, |
1548 | AR_RTC_STATUS_ON)) { | 1550 | AR_RTC_STATUS_ON, |
1551 | AH_WAIT_TIMEOUT)) { | ||
1549 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n"); | 1552 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n"); |
1550 | return false; | 1553 | return false; |
1551 | } | 1554 | } |
@@ -1640,7 +1643,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1640 | 1643 | ||
1641 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); | 1644 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); |
1642 | if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, | 1645 | if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, |
1643 | AR_PHY_RFBUS_GRANT_EN)) { | 1646 | AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { |
1644 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | 1647 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, |
1645 | "Could not kill baseband RX\n"); | 1648 | "Could not kill baseband RX\n"); |
1646 | return false; | 1649 | return false; |
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index 08469d9525bc..ddab3b7d07b2 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h | |||
@@ -93,7 +93,7 @@ | |||
93 | #define ATH9K_NUM_QUEUES 10 | 93 | #define ATH9K_NUM_QUEUES 10 |
94 | 94 | ||
95 | #define MAX_RATE_POWER 63 | 95 | #define MAX_RATE_POWER 63 |
96 | #define AH_TIMEOUT 100000 | 96 | #define AH_WAIT_TIMEOUT 100000 /* (us) */ |
97 | #define AH_TIME_QUANTUM 10 | 97 | #define AH_TIME_QUANTUM 10 |
98 | #define AR_KEYTABLE_SIZE 128 | 98 | #define AR_KEYTABLE_SIZE 128 |
99 | #define POWER_UP_TIME 200000 | 99 | #define POWER_UP_TIME 200000 |
@@ -612,7 +612,7 @@ bool ath9k_hw_setantennaswitch(struct ath_hw *ah, | |||
612 | u8 *antenna_cfgd); | 612 | u8 *antenna_cfgd); |
613 | 613 | ||
614 | /* General Operation */ | 614 | /* General Operation */ |
615 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val); | 615 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); |
616 | u32 ath9k_hw_reverse_bits(u32 val, u32 n); | 616 | u32 ath9k_hw_reverse_bits(u32 val, u32 n); |
617 | bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); | 617 | bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); |
618 | u16 ath9k_hw_computetxtime(struct ath_hw *ah, struct ath_rate_table *rates, | 618 | u16 ath9k_hw_computetxtime(struct ath_hw *ah, struct ath_rate_table *rates, |
diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c index f32c622db6e7..a6c204283ad5 100644 --- a/drivers/net/wireless/ath9k/mac.c +++ b/drivers/net/wireless/ath9k/mac.c | |||
@@ -886,7 +886,8 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) | |||
886 | REG_SET_BIT(ah, AR_DIAG_SW, | 886 | REG_SET_BIT(ah, AR_DIAG_SW, |
887 | (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | 887 | (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); |
888 | 888 | ||
889 | if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0)) { | 889 | if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, |
890 | 0, AH_WAIT_TIMEOUT)) { | ||
890 | REG_CLR_BIT(ah, AR_DIAG_SW, | 891 | REG_CLR_BIT(ah, AR_DIAG_SW, |
891 | (AR_DIAG_RX_DIS | | 892 | (AR_DIAG_RX_DIS | |
892 | AR_DIAG_RX_ABORT)); | 893 | AR_DIAG_RX_ABORT)); |
@@ -933,15 +934,32 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah) | |||
933 | 934 | ||
934 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah) | 935 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah) |
935 | { | 936 | { |
937 | #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ | ||
938 | #define AH_RX_TIME_QUANTUM 100 /* usec */ | ||
939 | |||
940 | int i; | ||
941 | |||
936 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | 942 | REG_WRITE(ah, AR_CR, AR_CR_RXD); |
937 | 943 | ||
938 | if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) { | 944 | /* Wait for rx enable bit to go low */ |
945 | for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) { | ||
946 | if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) | ||
947 | break; | ||
948 | udelay(AH_TIME_QUANTUM); | ||
949 | } | ||
950 | |||
951 | if (i == 0) { | ||
939 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | 952 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, |
940 | "dma failed to stop in 10ms\n" | 953 | "dma failed to stop in %d ms " |
941 | "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", | 954 | "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", |
942 | REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); | 955 | AH_RX_STOP_DMA_TIMEOUT / 1000, |
956 | REG_READ(ah, AR_CR), | ||
957 | REG_READ(ah, AR_DIAG_SW)); | ||
943 | return false; | 958 | return false; |
944 | } else { | 959 | } else { |
945 | return true; | 960 | return true; |
946 | } | 961 | } |
962 | |||
963 | #undef AH_RX_TIME_QUANTUM | ||
964 | #undef AH_RX_STOP_DMA_TIMEOUT | ||
947 | } | 965 | } |
diff --git a/drivers/net/wireless/ath9k/pci.c b/drivers/net/wireless/ath9k/pci.c index c28afe42b269..a70f954c9e75 100644 --- a/drivers/net/wireless/ath9k/pci.c +++ b/drivers/net/wireless/ath9k/pci.c | |||
@@ -63,7 +63,8 @@ static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) | |||
63 | if (!ath9k_hw_wait(ah, | 63 | if (!ath9k_hw_wait(ah, |
64 | AR_EEPROM_STATUS_DATA, | 64 | AR_EEPROM_STATUS_DATA, |
65 | AR_EEPROM_STATUS_DATA_BUSY | | 65 | AR_EEPROM_STATUS_DATA_BUSY | |
66 | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) { | 66 | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, |
67 | AH_WAIT_TIMEOUT)) { | ||
67 | return false; | 68 | return false; |
68 | } | 69 | } |
69 | 70 | ||
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 08f676af894f..28ad1d5af129 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c | |||
@@ -427,7 +427,6 @@ bool ath_stoprecv(struct ath_softc *sc) | |||
427 | ath9k_hw_stoppcurecv(ah); | 427 | ath9k_hw_stoppcurecv(ah); |
428 | ath9k_hw_setrxfilter(ah, 0); | 428 | ath9k_hw_setrxfilter(ah, 0); |
429 | stopped = ath9k_hw_stopdmarecv(ah); | 429 | stopped = ath9k_hw_stopdmarecv(ah); |
430 | mdelay(3); /* 3ms is long enough for 1 frame */ | ||
431 | sc->rx.rxlink = NULL; | 430 | sc->rx.rxlink = NULL; |
432 | 431 | ||
433 | return stopped; | 432 | return stopped; |