aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/dma.c
diff options
context:
space:
mode:
authorNick Kossifidis <mickflemm@gmail.com>2010-11-23 13:41:15 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-30 13:52:30 -0500
commitd41174fabdae348c6583cf05aeb329da232c342c (patch)
tree6f1979e64f748c8f6c060c28804424a79f49b0d6 /drivers/net/wireless/ath/ath5k/dma.c
parent9320b5c4a7260d9593102f378201d17e3f030739 (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.c52
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 */
180int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) 180int 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 */
749int 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}