ath9k: Fix bug in TX DMA termination
authorSujith <Sujith.Manoharan@atheros.com>
Tue, 27 Jan 2009 09:36:38 +0000 (15:06 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 30 Jan 2009 18:38:27 +0000 (13:38 -0500)
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>
drivers/net/wireless/ath9k/mac.c

index af32d091dc38231b4d77ba321d56711e93297c7e..ef832a5ebbd8f2d6b86f9d473a8aa27df5e030ea 100644 (file)
@@ -107,14 +107,32 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel)
 
 bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
 {
+#define ATH9K_TX_STOP_DMA_TIMEOUT      4000    /* usec */
+#define ATH9K_TIME_QUANTUM             100     /* usec */
+
+       struct ath_hal_5416 *ahp = AH5416(ah);
+       struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+       struct ath9k_tx_queue_info *qi;
        u32 tsfLow, j, wait;
+       u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
+
+       if (q >= pCap->total_queues) {
+               DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
+               return false;
+       }
+
+       qi = &ahp->ah_txq[q];
+       if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+               DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
+               return false;
+       }
 
        REG_WRITE(ah, AR_Q_TXD, 1 << q);
 
-       for (wait = 1000; wait != 0; wait--) {
+       for (wait = wait_time; wait != 0; wait--) {
                if (ath9k_hw_numtxpending(ah, q) == 0)
                        break;
-               udelay(100);
+               udelay(ATH9K_TIME_QUANTUM);
        }
 
        if (ath9k_hw_numtxpending(ah, q)) {
@@ -144,8 +162,7 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
                udelay(200);
                REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
 
-               wait = 1000;
-
+               wait = wait_time;
                while (ath9k_hw_numtxpending(ah, q)) {
                        if ((--wait) == 0) {
                                DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
@@ -153,15 +170,17 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
                                        "msec after killing last frame\n");
                                break;
                        }
-                       udelay(100);
+                       udelay(ATH9K_TIME_QUANTUM);
                }
 
                REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
        }
 
        REG_WRITE(ah, AR_Q_TXD, 0);
-
        return wait != 0;
+
+#undef ATH9K_TX_STOP_DMA_TIMEOUT
+#undef ATH9K_TIME_QUANTUM
 }
 
 bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,