ath9k: improve reliability of beacon transmission and stuck beacon handling
[cascardo/linux.git] / drivers / net / wireless / ath / ath9k / mac.c
index 58aaf9a..cb5d814 100644 (file)
@@ -171,84 +171,31 @@ void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
 
-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
+bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
 {
-#define ATH9K_TX_STOP_DMA_TIMEOUT      4000    /* usec */
+#define ATH9K_TX_STOP_DMA_TIMEOUT      1000    /* usec */
 #define ATH9K_TIME_QUANTUM             100     /* usec */
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ath9k_hw_capabilities *pCap = &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) {
-               ath_dbg(common, ATH_DBG_QUEUE,
-                       "Stopping TX DMA, invalid queue: %u\n", q);
-               return false;
-       }
-
-       qi = &ah->txq[q];
-       if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-               ath_dbg(common, ATH_DBG_QUEUE,
-                       "Stopping TX DMA, inactive queue: %u\n", q);
-               return false;
-       }
+       int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
+       int wait;
 
        REG_WRITE(ah, AR_Q_TXD, 1 << q);
 
        for (wait = wait_time; wait != 0; wait--) {
-               if (ath9k_hw_numtxpending(ah, q) == 0)
-                       break;
-               udelay(ATH9K_TIME_QUANTUM);
-       }
-
-       if (ath9k_hw_numtxpending(ah, q)) {
-               ath_dbg(common, ATH_DBG_QUEUE,
-                       "%s: Num of pending TX Frames %d on Q %d\n",
-                       __func__, ath9k_hw_numtxpending(ah, q), q);
-
-               for (j = 0; j < 2; j++) {
-                       tsfLow = REG_READ(ah, AR_TSF_L32);
-                       REG_WRITE(ah, AR_QUIET2,
-                                 SM(10, AR_QUIET2_QUIET_DUR));
-                       REG_WRITE(ah, AR_QUIET_PERIOD, 100);
-                       REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
-                       REG_SET_BIT(ah, AR_TIMER_MODE,
-                                      AR_QUIET_TIMER_EN);
-
-                       if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
-                               break;
-
-                       ath_dbg(common, ATH_DBG_QUEUE,
-                               "TSF has moved while trying to set quiet time TSF: 0x%08x\n",
-                               tsfLow);
-               }
-
-               REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
-
-               udelay(200);
-               REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
-
-               wait = wait_time;
-               while (ath9k_hw_numtxpending(ah, q)) {
-                       if ((--wait) == 0) {
-                               ath_err(common,
-                                       "Failed to stop TX DMA in 100 msec after killing last frame\n");
-                               break;
-                       }
+               if (wait != wait_time)
                        udelay(ATH9K_TIME_QUANTUM);
-               }
 
-               REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+               if (ath9k_hw_numtxpending(ah, q) == 0)
+                       break;
        }
 
        REG_WRITE(ah, AR_Q_TXD, 0);
+
        return wait != 0;
 
 #undef ATH9K_TX_STOP_DMA_TIMEOUT
 #undef ATH9K_TIME_QUANTUM
 }
-EXPORT_SYMBOL(ath9k_hw_stoptxdma);
+EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
 
 void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
 {