Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[pandora-kernel.git] / drivers / net / wireless / ath / ath9k / mac.c
index 562257a..edc1cbb 100644 (file)
@@ -751,28 +751,47 @@ void ath9k_hw_abortpcurecv(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_abortpcurecv);
 
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset)
 {
 #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
 #define AH_RX_TIME_QUANTUM     100     /* usec */
        struct ath_common *common = ath9k_hw_common(ah);
+       u32 mac_status, last_mac_status = 0;
        int i;
 
+       /* Enable access to the DMA observation bus */
+       REG_WRITE(ah, AR_MACMISC,
+                 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+                  (AR_MACMISC_MISC_OBS_BUS_1 <<
+                   AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
        REG_WRITE(ah, AR_CR, AR_CR_RXD);
 
        /* Wait for rx enable bit to go low */
        for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
                if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
                        break;
+
+               if (!AR_SREV_9300_20_OR_LATER(ah)) {
+                       mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
+                       if (mac_status == 0x1c0 && mac_status == last_mac_status) {
+                               *reset = true;
+                               break;
+                       }
+
+                       last_mac_status = mac_status;
+               }
+
                udelay(AH_TIME_QUANTUM);
        }
 
        if (i == 0) {
                ath_err(common,
-                       "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
+                       "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
                        AH_RX_STOP_DMA_TIMEOUT / 1000,
                        REG_READ(ah, AR_CR),
-                       REG_READ(ah, AR_DIAG_SW));
+                       REG_READ(ah, AR_DIAG_SW),
+                       REG_READ(ah, AR_DMADBG_7));
                return false;
        } else {
                return true;