diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/mac.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 562257ac52cf..edc1cbbfecaf 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -751,28 +751,47 @@ void ath9k_hw_abortpcurecv(struct ath_hw *ah) | |||
751 | } | 751 | } |
752 | EXPORT_SYMBOL(ath9k_hw_abortpcurecv); | 752 | EXPORT_SYMBOL(ath9k_hw_abortpcurecv); |
753 | 753 | ||
754 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah) | 754 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset) |
755 | { | 755 | { |
756 | #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ | 756 | #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ |
757 | #define AH_RX_TIME_QUANTUM 100 /* usec */ | 757 | #define AH_RX_TIME_QUANTUM 100 /* usec */ |
758 | struct ath_common *common = ath9k_hw_common(ah); | 758 | struct ath_common *common = ath9k_hw_common(ah); |
759 | u32 mac_status, last_mac_status = 0; | ||
759 | int i; | 760 | int i; |
760 | 761 | ||
762 | /* Enable access to the DMA observation bus */ | ||
763 | REG_WRITE(ah, AR_MACMISC, | ||
764 | ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | | ||
765 | (AR_MACMISC_MISC_OBS_BUS_1 << | ||
766 | AR_MACMISC_MISC_OBS_BUS_MSB_S))); | ||
767 | |||
761 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | 768 | REG_WRITE(ah, AR_CR, AR_CR_RXD); |
762 | 769 | ||
763 | /* Wait for rx enable bit to go low */ | 770 | /* Wait for rx enable bit to go low */ |
764 | for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) { | 771 | for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) { |
765 | if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) | 772 | if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) |
766 | break; | 773 | break; |
774 | |||
775 | if (!AR_SREV_9300_20_OR_LATER(ah)) { | ||
776 | mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0; | ||
777 | if (mac_status == 0x1c0 && mac_status == last_mac_status) { | ||
778 | *reset = true; | ||
779 | break; | ||
780 | } | ||
781 | |||
782 | last_mac_status = mac_status; | ||
783 | } | ||
784 | |||
767 | udelay(AH_TIME_QUANTUM); | 785 | udelay(AH_TIME_QUANTUM); |
768 | } | 786 | } |
769 | 787 | ||
770 | if (i == 0) { | 788 | if (i == 0) { |
771 | ath_err(common, | 789 | ath_err(common, |
772 | "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", | 790 | "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n", |
773 | AH_RX_STOP_DMA_TIMEOUT / 1000, | 791 | AH_RX_STOP_DMA_TIMEOUT / 1000, |
774 | REG_READ(ah, AR_CR), | 792 | REG_READ(ah, AR_CR), |
775 | REG_READ(ah, AR_DIAG_SW)); | 793 | REG_READ(ah, AR_DIAG_SW), |
794 | REG_READ(ah, AR_DMADBG_7)); | ||
776 | return false; | 795 | return false; |
777 | } else { | 796 | } else { |
778 | return true; | 797 | return true; |