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

Commit e8fe7336 authored by Rajkumar Manoharan's avatar Rajkumar Manoharan Committed by John W. Linville
Browse files

ath9k: Use atomic reference count for interrupt ops



Let us enable/disable interrupts based on reference count.
By doing this we can ensure that interrupts are never be
enabled in the middle of tasklet processing. Instead of
addressing corner cases like "ath9k: avoid enabling interrupts
while processing rx", this approach handles it in generic manner.

Signed-off-by: default avatarRajkumar Manoharan <rmanohar@qca.qualcomm.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a844adfd
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -567,7 +567,6 @@ struct ath_ant_comb {
#define PS_WAIT_FOR_PSPOLL_DATA   BIT(2)
#define PS_WAIT_FOR_TX_ACK        BIT(3)
#define PS_BEACON_SYNC            BIT(4)
#define PS_TSFOOR_SYNC            BIT(5)

struct ath_rate_table;

+5 −16
Original line number Diff line number Diff line
@@ -649,15 +649,9 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
	ath9k_hw_set_sta_beacon_timers(ah, &bs);
	ah->imask |= ATH9K_INT_BMISS;

	/*
	 * If the beacon config is called beacause of TSFOOR,
	 * Interrupts will be enabled back at the end of ath9k_tasklet
	 */
	if (!(sc->ps_flags & PS_TSFOOR_SYNC)) {
	ath9k_hw_set_interrupts(ah, ah->imask);
	ath9k_hw_enable_interrupts(ah);
}
}

static void ath_beacon_config_adhoc(struct ath_softc *sc,
				    struct ath_beacon_config *conf)
@@ -690,15 +684,10 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
	ath9k_hw_disable_interrupts(ah);
	ath9k_beacon_init(sc, nexttbtt, intval);
	sc->beacon.bmisscnt = 0;
	/*
	 * If the beacon config is called beacause of TSFOOR,
	 * Interrupts will be enabled back at the end of ath9k_tasklet
	 */
	if (!(sc->ps_flags & PS_TSFOOR_SYNC)) {

	ath9k_hw_set_interrupts(ah, ah->imask);
	ath9k_hw_enable_interrupts(ah);
}
}

static bool ath9k_allow_beacon_config(struct ath_softc *sc,
				      struct ieee80211_vif *vif)
+1 −0
Original line number Diff line number Diff line
@@ -709,6 +709,7 @@ struct ath_hw {
	u32 txdesc_interrupt_mask;
	u32 txeol_interrupt_mask;
	u32 txurn_interrupt_mask;
	atomic_t intr_ref_cnt;
	bool chip_fullsleep;
	u32 atim_window;

+1 −0
Original line number Diff line number Diff line
@@ -566,6 +566,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
	ah->reg_ops.read = ath9k_ioread32;
	ah->reg_ops.write = ath9k_iowrite32;
	ah->reg_ops.rmw = ath9k_reg_rmw;
	atomic_set(&ah->intr_ref_cnt, -1);
	sc->sc_ah = ah;

	if (!pdata) {
+12 −1
Original line number Diff line number Diff line
@@ -800,6 +800,11 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah)
{
	struct ath_common *common = ath9k_hw_common(ah);

	if (!(ah->imask & ATH9K_INT_GLOBAL))
		atomic_set(&ah->intr_ref_cnt, -1);
	else
		atomic_dec(&ah->intr_ref_cnt);

	ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n");
	REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
	(void) REG_READ(ah, AR_IER);
@@ -821,6 +826,13 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
	if (!(ah->imask & ATH9K_INT_GLOBAL))
		return;

	if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
		ath_dbg(common, ATH_DBG_INTERRUPT,
			"Do not enable IER ref count %d\n",
			atomic_read(&ah->intr_ref_cnt));
		return;
	}

	if (AR_SREV_9340(ah))
		sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;

@@ -852,7 +864,6 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)

	ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);

	/* TODO: global int Ref count */
	mask = ints & ATH9K_INT_COMMON;
	mask2 = 0;

Loading