diff options
author | Nick Kossifidis <mickflemm@gmail.com> | 2010-11-23 13:41:15 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-30 13:52:30 -0500 |
commit | d41174fabdae348c6583cf05aeb329da232c342c (patch) | |
tree | 6f1979e64f748c8f6c060c28804424a79f49b0d6 /drivers/net/wireless/ath/ath5k/dma.c | |
parent | 9320b5c4a7260d9593102f378201d17e3f030739 (diff) |
ath5k: Add new function to stop rx/tx DMA
* Add a new function to stop rx/tx dma and use in when reset starts
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/dma.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/dma.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index b991b058509..ca0467e21e5 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c | |||
@@ -126,7 +126,7 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
126 | 126 | ||
127 | /* Return if queue is declared inactive */ | 127 | /* Return if queue is declared inactive */ |
128 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | 128 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) |
129 | return -EIO; | 129 | return -EINVAL; |
130 | 130 | ||
131 | if (ah->ah_version == AR5K_AR5210) { | 131 | if (ah->ah_version == AR5K_AR5210) { |
132 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); | 132 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); |
@@ -174,7 +174,7 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
174 | * | 174 | * |
175 | * Stop DMA transmit on a specific hw queue and drain queue so we don't | 175 | * Stop DMA transmit on a specific hw queue and drain queue so we don't |
176 | * have any pending frames. Returns -EBUSY if we still have pending frames, | 176 | * have any pending frames. Returns -EBUSY if we still have pending frames, |
177 | * -EINVAL if queue number is out of range. | 177 | * -EINVAL if queue number is out of range or inactive. |
178 | * | 178 | * |
179 | */ | 179 | */ |
180 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | 180 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) |
@@ -186,7 +186,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
186 | 186 | ||
187 | /* Return if queue is declared inactive */ | 187 | /* Return if queue is declared inactive */ |
188 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | 188 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) |
189 | return -EIO; | 189 | return -EINVAL; |
190 | 190 | ||
191 | if (ah->ah_version == AR5K_AR5210) { | 191 | if (ah->ah_version == AR5K_AR5210) { |
192 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); | 192 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); |
@@ -733,3 +733,49 @@ void ath5k_hw_dma_init(struct ath5k_hw *ah) | |||
733 | ath5k_hw_set_imr(ah, ah->ah_imr); | 733 | ath5k_hw_set_imr(ah, ah->ah_imr); |
734 | 734 | ||
735 | } | 735 | } |
736 | |||
737 | /** | ||
738 | * ath5k_hw_dma_stop - stop DMA unit | ||
739 | * | ||
740 | * @ah: The &struct ath5k_hw | ||
741 | * | ||
742 | * Stop tx/rx DMA and interrupts. Returns | ||
743 | * -EBUSY if tx or rx dma failed to stop. | ||
744 | * | ||
745 | * XXX: Sometimes DMA unit hangs and we have | ||
746 | * stuck frames on tx queues, only a reset | ||
747 | * can fix that. | ||
748 | */ | ||
749 | int ath5k_hw_dma_stop(struct ath5k_hw *ah) | ||
750 | { | ||
751 | int i, qmax, err; | ||
752 | err = 0; | ||
753 | |||
754 | /* Disable interrupts */ | ||
755 | ath5k_hw_set_imr(ah, 0); | ||
756 | |||
757 | /* Stop rx dma */ | ||
758 | err = ath5k_hw_stop_rx_dma(ah); | ||
759 | if (err) | ||
760 | return err; | ||
761 | |||
762 | /* Clear any pending interrupts | ||
763 | * and disable tx dma */ | ||
764 | if (ah->ah_version != AR5K_AR5210) { | ||
765 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); | ||
766 | qmax = AR5K_NUM_TX_QUEUES; | ||
767 | } else { | ||
768 | /* PISR/SISR Not available on 5210 */ | ||
769 | ath5k_hw_reg_read(ah, AR5K_ISR); | ||
770 | qmax = AR5K_NUM_TX_QUEUES_NOQCU; | ||
771 | } | ||
772 | |||
773 | for (i = 0; i < qmax; i++) { | ||
774 | err = ath5k_hw_stop_tx_dma(ah, i); | ||
775 | /* -EINVAL -> queue inactive */ | ||
776 | if (err != -EINVAL) | ||
777 | return err; | ||
778 | } | ||
779 | |||
780 | return err; | ||
781 | } | ||