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

Commit 063d8be3 authored by Sujith's avatar Sujith Committed by John W. Linville
Browse files

ath9k: Clean Interrupt handling routine



This patch cleans up the ISR, removing a unnecessary do..while
loop, and waking up the chip before getting the pending
interrupts.

Signed-off-by: default avatarSujith <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 87792efc
Loading
Loading
Loading
Loading
+95 −102
Original line number Original line Diff line number Diff line
@@ -456,21 +456,18 @@ static void ath9k_tasklet(unsigned long data)
	u32 status = sc->intrstatus;
	u32 status = sc->intrstatus;


	if (status & ATH9K_INT_FATAL) {
	if (status & ATH9K_INT_FATAL) {
		/* need a chip reset */
		ath_reset(sc, false);
		ath_reset(sc, false);
		return;
		return;
	} else {
	}


		if (status &
	if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
		    (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
		spin_lock_bh(&sc->rx.rxflushlock);
		spin_lock_bh(&sc->rx.rxflushlock);
		ath_rx_tasklet(sc, 0);
		ath_rx_tasklet(sc, 0);
		spin_unlock_bh(&sc->rx.rxflushlock);
		spin_unlock_bh(&sc->rx.rxflushlock);
	}
	}
		/* XXX: optimize this */

	if (status & ATH9K_INT_TX)
	if (status & ATH9K_INT_TX)
		ath_tx_tasklet(sc);
		ath_tx_tasklet(sc);
	}


	/* re-enable hardware interrupt */
	/* re-enable hardware interrupt */
	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
@@ -478,21 +475,35 @@ static void ath9k_tasklet(unsigned long data)


irqreturn_t ath_isr(int irq, void *dev)
irqreturn_t ath_isr(int irq, void *dev)
{
{
#define SCHED_INTR (				\
		ATH9K_INT_FATAL |		\
		ATH9K_INT_RXORN |		\
		ATH9K_INT_RXEOL |		\
		ATH9K_INT_RX |			\
		ATH9K_INT_TX |			\
		ATH9K_INT_BMISS |		\
		ATH9K_INT_CST |			\
		ATH9K_INT_TSFOOR)

	struct ath_softc *sc = dev;
	struct ath_softc *sc = dev;
	struct ath_hw *ah = sc->sc_ah;
	struct ath_hw *ah = sc->sc_ah;
	enum ath9k_int status;
	enum ath9k_int status;
	bool sched = false;
	bool sched = false;


	do {
		if (sc->sc_flags & SC_OP_INVALID) {
	/*
	/*
	 * The hardware is not ready/present, don't
	 * The hardware is not ready/present, don't
	 * touch anything. Note this can happen early
	 * touch anything. Note this can happen early
	 * on if the IRQ is shared.
	 * on if the IRQ is shared.
	 */
	 */
	if (sc->sc_flags & SC_OP_INVALID)
		return IRQ_NONE;
		return IRQ_NONE;
		}

		if (!ath9k_hw_intrpend(ah)) {	/* shared irq, not for us */
	ath9k_ps_wakeup(sc);

	/* shared irq, not for us */

	if (!ath9k_hw_intrpend(ah)) {
		ath9k_ps_restore(sc);
		return IRQ_NONE;
		return IRQ_NONE;
	}
	}


@@ -503,52 +514,36 @@ irqreturn_t ath_isr(int irq, void *dev)
	 * value to insure we only process bits we requested.
	 * value to insure we only process bits we requested.
	 */
	 */
	ath9k_hw_getisr(ah, &status);	/* NB: clears ISR too */
	ath9k_hw_getisr(ah, &status);	/* NB: clears ISR too */

	status &= sc->imask;	/* discard unasked-for bits */
	status &= sc->imask;	/* discard unasked-for bits */


	/*
	/*
	 * If there are no status bits set, then this interrupt was not
	 * If there are no status bits set, then this interrupt was not
	 * for me (should have been caught above).
	 * for me (should have been caught above).
	 */
	 */
		if (!status)
	if (!status) {
		ath9k_ps_restore(sc);
		return IRQ_NONE;
		return IRQ_NONE;
	}


	/* Cache the status */
	sc->intrstatus = status;
	sc->intrstatus = status;
		ath9k_ps_wakeup(sc);


		if (status & ATH9K_INT_FATAL) {
	if (status & SCHED_INTR)
			/* need a chip reset */
			sched = true;
		} else if (status & ATH9K_INT_RXORN) {
			/* need a chip reset */
		sched = true;
		sched = true;
		} else {

			if (status & ATH9K_INT_SWBA) {
				/* schedule a tasklet for beacon handling */
				tasklet_schedule(&sc->bcon_tasklet);
			}
			if (status & ATH9K_INT_RXEOL) {
	/*
	/*
				 * NB: the hardware should re-read the link when
	 * If a FATAL or RXORN interrupt is received, we have to reset the
				 *     RXE bit is written, but it doesn't work
	 * chip immediately.
				 *     at least on older hardware revs.
	 */
	 */
				sched = true;
	if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN))
			}
		goto chip_reset;

	if (status & ATH9K_INT_SWBA)
		tasklet_schedule(&sc->bcon_tasklet);


	if (status & ATH9K_INT_TXURN)
	if (status & ATH9K_INT_TXURN)
				/* bump tx trigger level */
		ath9k_hw_updatetxtriglevel(ah, true);
		ath9k_hw_updatetxtriglevel(ah, true);
			/* XXX: optimize this */

			if (status & ATH9K_INT_RX)
				sched = true;
			if (status & ATH9K_INT_TX)
				sched = true;
			if (status & ATH9K_INT_BMISS)
				sched = true;
			/* carrier sense timeout */
			if (status & ATH9K_INT_CST)
				sched = true;
	if (status & ATH9K_INT_MIB) {
	if (status & ATH9K_INT_MIB) {
		/*
		/*
		 * Disable interrupts until we service the MIB
		 * Disable interrupts until we service the MIB
@@ -564,9 +559,9 @@ irqreturn_t ath_isr(int irq, void *dev)
		ath9k_hw_procmibevent(ah, &sc->nodestats);
		ath9k_hw_procmibevent(ah, &sc->nodestats);
		ath9k_hw_set_interrupts(ah, sc->imask);
		ath9k_hw_set_interrupts(ah, sc->imask);
	}
	}

	if (status & ATH9K_INT_TIM_TIMER) {
	if (status & ATH9K_INT_TIM_TIMER) {
				if (!(ah->caps.hw_caps &
		if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
				      ATH9K_HW_CAP_AUTOSLEEP)) {
			/* Clear RxAbort bit so that we can
			/* Clear RxAbort bit so that we can
			 * receive frames */
			 * receive frames */
			ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
			ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
@@ -575,14 +570,10 @@ irqreturn_t ath_isr(int irq, void *dev)
			sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
			sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
		}
		}
	}
	}
			if (status & ATH9K_INT_TSFOOR) {
				/* FIXME: Handle this interrupt for power save */
				sched = true;
			}
		}
		ath9k_ps_restore(sc);
	} while (0);


chip_reset:

	ath9k_ps_restore(sc);
	ath_debug_stat_interrupt(sc, status);
	ath_debug_stat_interrupt(sc, status);


	if (sched) {
	if (sched) {
@@ -592,6 +583,8 @@ irqreturn_t ath_isr(int irq, void *dev)
	}
	}


	return IRQ_HANDLED;
	return IRQ_HANDLED;

#undef SCHED_INTR
}
}


static u32 ath_get_extchanmode(struct ath_softc *sc,
static u32 ath_get_extchanmode(struct ath_softc *sc,