mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 02:19:51 +00:00
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>
This commit is contained in:
parent
9320b5c4a7
commit
d41174fabd
3 changed files with 59 additions and 9 deletions
|
@ -1180,8 +1180,9 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
|
|||
int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
|
||||
enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask);
|
||||
void ath5k_hw_update_mib_counters(struct ath5k_hw *ah);
|
||||
/* Init function */
|
||||
/* Init/Stop functions */
|
||||
void ath5k_hw_dma_init(struct ath5k_hw *ah);
|
||||
int ath5k_hw_dma_stop(struct ath5k_hw *ah);
|
||||
|
||||
/* EEPROM access functions */
|
||||
int ath5k_eeprom_init(struct ath5k_hw *ah);
|
||||
|
|
|
@ -126,7 +126,7 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
|
|||
|
||||
/* Return if queue is declared inactive */
|
||||
if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
|
||||
return -EIO;
|
||||
return -EINVAL;
|
||||
|
||||
if (ah->ah_version == AR5K_AR5210) {
|
||||
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)
|
|||
*
|
||||
* Stop DMA transmit on a specific hw queue and drain queue so we don't
|
||||
* have any pending frames. Returns -EBUSY if we still have pending frames,
|
||||
* -EINVAL if queue number is out of range.
|
||||
* -EINVAL if queue number is out of range or inactive.
|
||||
*
|
||||
*/
|
||||
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)
|
|||
|
||||
/* Return if queue is declared inactive */
|
||||
if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
|
||||
return -EIO;
|
||||
return -EINVAL;
|
||||
|
||||
if (ah->ah_version == AR5K_AR5210) {
|
||||
tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
|
||||
|
@ -733,3 +733,49 @@ void ath5k_hw_dma_init(struct ath5k_hw *ah)
|
|||
ath5k_hw_set_imr(ah, ah->ah_imr);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_dma_stop - stop DMA unit
|
||||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
*
|
||||
* Stop tx/rx DMA and interrupts. Returns
|
||||
* -EBUSY if tx or rx dma failed to stop.
|
||||
*
|
||||
* XXX: Sometimes DMA unit hangs and we have
|
||||
* stuck frames on tx queues, only a reset
|
||||
* can fix that.
|
||||
*/
|
||||
int ath5k_hw_dma_stop(struct ath5k_hw *ah)
|
||||
{
|
||||
int i, qmax, err;
|
||||
err = 0;
|
||||
|
||||
/* Disable interrupts */
|
||||
ath5k_hw_set_imr(ah, 0);
|
||||
|
||||
/* Stop rx dma */
|
||||
err = ath5k_hw_stop_rx_dma(ah);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Clear any pending interrupts
|
||||
* and disable tx dma */
|
||||
if (ah->ah_version != AR5K_AR5210) {
|
||||
ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
|
||||
qmax = AR5K_NUM_TX_QUEUES;
|
||||
} else {
|
||||
/* PISR/SISR Not available on 5210 */
|
||||
ath5k_hw_reg_read(ah, AR5K_ISR);
|
||||
qmax = AR5K_NUM_TX_QUEUES_NOQCU;
|
||||
}
|
||||
|
||||
for (i = 0; i < qmax; i++) {
|
||||
err = ath5k_hw_stop_tx_dma(ah, i);
|
||||
/* -EINVAL -> queue inactive */
|
||||
if (err != -EINVAL)
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -822,6 +822,14 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
freq = 0;
|
||||
mode = 0;
|
||||
|
||||
/*
|
||||
* Stop DMA
|
||||
*
|
||||
* Note: If DMA didn't stop continue
|
||||
* since only a reset will fix it.
|
||||
*/
|
||||
ath5k_hw_dma_stop(ah);
|
||||
|
||||
/*
|
||||
* Save some registers before a reset
|
||||
*/
|
||||
|
@ -1015,11 +1023,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
*/
|
||||
ath5k_hw_pcu_init(ah, op_mode, mode);
|
||||
|
||||
/* Clear any pending interrupts
|
||||
* PISR/SISR Not available on 5210 */
|
||||
if (ah->ah_version != AR5K_AR5210)
|
||||
ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
|
||||
|
||||
/*
|
||||
* Initialize PHY
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue