Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74bad5cb authored by Pavel Roskin's avatar Pavel Roskin Committed by John W. Linville
Browse files

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: default avatarPavel Roskin <proski@gnu.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b4d59a93
Loading
Loading
Loading
Loading
+7 −9
Original line number Diff line number Diff line
@@ -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)) {
+1 −0
Original line number Diff line number Diff line
@@ -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;
+4 −2
Original line number Diff line number Diff line
@@ -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)