aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2009-01-27 04:36:38 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-30 13:38:27 -0500
commit94ff91d4afd8ae14e8bb7012ba17cf6984130e44 (patch)
tree742360ef9a99a31279dc4ebee525b12bafa72d9c
parentf46730d13f23b4578dca1c0f7663ea3093ff4f0e (diff)
ath9k: Fix bug in TX DMA termination
Removing the module was slow because ath9k_hw_stopdma() was looping for a long time quantum. Use reasonable values now to fix this issue. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath9k/mac.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c
index af32d091dc38..ef832a5ebbd8 100644
--- a/drivers/net/wireless/ath9k/mac.c
+++ b/drivers/net/wireless/ath9k/mac.c
@@ -107,14 +107,32 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel)
107 107
108bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) 108bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
109{ 109{
110#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */
111#define ATH9K_TIME_QUANTUM 100 /* usec */
112
113 struct ath_hal_5416 *ahp = AH5416(ah);
114 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
115 struct ath9k_tx_queue_info *qi;
110 u32 tsfLow, j, wait; 116 u32 tsfLow, j, wait;
117 u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
118
119 if (q >= pCap->total_queues) {
120 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
121 return false;
122 }
123
124 qi = &ahp->ah_txq[q];
125 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
126 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
127 return false;
128 }
111 129
112 REG_WRITE(ah, AR_Q_TXD, 1 << q); 130 REG_WRITE(ah, AR_Q_TXD, 1 << q);
113 131
114 for (wait = 1000; wait != 0; wait--) { 132 for (wait = wait_time; wait != 0; wait--) {
115 if (ath9k_hw_numtxpending(ah, q) == 0) 133 if (ath9k_hw_numtxpending(ah, q) == 0)
116 break; 134 break;
117 udelay(100); 135 udelay(ATH9K_TIME_QUANTUM);
118 } 136 }
119 137
120 if (ath9k_hw_numtxpending(ah, q)) { 138 if (ath9k_hw_numtxpending(ah, q)) {
@@ -144,8 +162,7 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
144 udelay(200); 162 udelay(200);
145 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); 163 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
146 164
147 wait = 1000; 165 wait = wait_time;
148
149 while (ath9k_hw_numtxpending(ah, q)) { 166 while (ath9k_hw_numtxpending(ah, q)) {
150 if ((--wait) == 0) { 167 if ((--wait) == 0) {
151 DPRINTF(ah->ah_sc, ATH_DBG_XMIT, 168 DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
@@ -153,15 +170,17 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
153 "msec after killing last frame\n"); 170 "msec after killing last frame\n");
154 break; 171 break;
155 } 172 }
156 udelay(100); 173 udelay(ATH9K_TIME_QUANTUM);
157 } 174 }
158 175
159 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); 176 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
160 } 177 }
161 178
162 REG_WRITE(ah, AR_Q_TXD, 0); 179 REG_WRITE(ah, AR_Q_TXD, 0);
163
164 return wait != 0; 180 return wait != 0;
181
182#undef ATH9K_TX_STOP_DMA_TIMEOUT
183#undef ATH9K_TIME_QUANTUM
165} 184}
166 185
167bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds, 186bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,