aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2009-02-16 02:53:20 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-02-27 14:52:37 -0500
commit0caa7b14f36e8c3c43dd9294a960ae55cafe07fb (patch)
tree13a878857346d4bb67e57b31f6ab25a03ed4c6d7
parent70768496db9ee27d53d3d03d50c93fbf4c0198a0 (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.c6
-rw-r--r--drivers/net/wireless/ath9k/hw.c17
-rw-r--r--drivers/net/wireless/ath9k/hw.h4
-rw-r--r--drivers/net/wireless/ath9k/mac.c28
-rw-r--r--drivers/net/wireless/ath9k/pci.c3
-rw-r--r--drivers/net/wireless/ath9k/recv.c1
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
87bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val) 87bool 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 */
615bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val); 615bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
616u32 ath9k_hw_reverse_bits(u32 val, u32 n); 616u32 ath9k_hw_reverse_bits(u32 val, u32 n);
617bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); 617bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high);
618u16 ath9k_hw_computetxtime(struct ath_hw *ah, struct ath_rate_table *rates, 618u16 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
934bool ath9k_hw_stopdmarecv(struct ath_hw *ah) 935bool 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;