ath9k: never read from the AR_IMR_S2 register
The AR_IMR_S2 register sometimes cannot be read correctly. Instead of a valid value, 0xdeadbeef is returned. The driver has been observed writing that value back to AR_IMR_S2 after changing a few bits. Cache the register value in ah->imrs2_reg and always write chached value to the register. Signed-off-by: Pavel Roskin <proski@gnu.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
b4d59a9317
commit
74bad5cb49
@ -1151,7 +1151,8 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
|
||||
ah->mask_reg |= AR_IMR_MIB;
|
||||
|
||||
REG_WRITE(ah, AR_IMR, ah->mask_reg);
|
||||
REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
|
||||
ah->imrs2_reg |= AR_IMR_S2_GTT;
|
||||
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
|
||||
|
||||
if (!AR_SREV_9100(ah)) {
|
||||
REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
|
||||
@ -2920,14 +2921,11 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
|
||||
|
||||
ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
|
||||
REG_WRITE(ah, AR_IMR, mask);
|
||||
mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
|
||||
AR_IMR_S2_DTIM |
|
||||
AR_IMR_S2_DTIMSYNC |
|
||||
AR_IMR_S2_CABEND |
|
||||
AR_IMR_S2_CABTO |
|
||||
AR_IMR_S2_TSFOOR |
|
||||
AR_IMR_S2_GTT | AR_IMR_S2_CST);
|
||||
REG_WRITE(ah, AR_IMR_S2, mask | mask2);
|
||||
ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
|
||||
AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
|
||||
AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
|
||||
ah->imrs2_reg |= mask2;
|
||||
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
|
||||
ah->mask_reg = ints;
|
||||
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
|
||||
|
@ -479,6 +479,7 @@ struct ath_hw {
|
||||
|
||||
int16_t curchan_rad_index;
|
||||
u32 mask_reg;
|
||||
u32 imrs2_reg;
|
||||
u32 txok_interrupt_mask;
|
||||
u32 txerr_interrupt_mask;
|
||||
u32 txdesc_interrupt_mask;
|
||||
|
@ -31,8 +31,10 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
|
||||
REG_WRITE(ah, AR_IMR_S1,
|
||||
SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
|
||||
| SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
|
||||
REG_RMW_FIELD(ah, AR_IMR_S2,
|
||||
AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask);
|
||||
|
||||
ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
|
||||
ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
|
||||
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
|
||||
}
|
||||
|
||||
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
|
||||
|
Loading…
Reference in New Issue
Block a user