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

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
...@@ -456,133 +456,124 @@ static void ath9k_tasklet(unsigned long data) ...@@ -456,133 +456,124 @@ 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)
ath_tx_tasklet(sc);
} }
if (status & ATH9K_INT_TX)
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);
} }
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
/* * touch anything. Note this can happen early
* The hardware is not ready/present, don't * on if the IRQ is shared.
* touch anything. Note this can happen early */
* 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 */
return IRQ_NONE;
}
/* ath9k_ps_wakeup(sc);
* Figure out the reason(s) for the interrupt. Note
* that the hal returns a pseudo-ISR that may include
* bits we haven't explicitly enabled so we mask the
* value to insure we only process bits we requested.
*/
ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
status &= sc->imask; /* discard unasked-for bits */ /* shared irq, not for us */
if (!ath9k_hw_intrpend(ah)) {
ath9k_ps_restore(sc);
return IRQ_NONE;
}
/*
* Figure out the reason(s) for the interrupt. Note
* that the hal returns a pseudo-ISR that may include
* bits we haven't explicitly enabled so we mask the
* value to insure we only process bits we requested.
*/
ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
status &= sc->imask; /* discard unasked-for bits */
/*
* If there are no status bits set, then this interrupt was not
* for me (should have been caught above).
*/
if (!status) {
ath9k_ps_restore(sc);
return IRQ_NONE;
}
/* Cache the status */
sc->intrstatus = status;
if (status & SCHED_INTR)
sched = true;
/*
* If a FATAL or RXORN interrupt is received, we have to reset the
* chip immediately.
*/
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)
ath9k_hw_updatetxtriglevel(ah, true);
if (status & ATH9K_INT_MIB) {
/* /*
* If there are no status bits set, then this interrupt was not * Disable interrupts until we service the MIB
* for me (should have been caught above). * interrupt; otherwise it will continue to
* fire.
*/ */
if (!status) ath9k_hw_set_interrupts(ah, 0);
return IRQ_NONE; /*
* Let the hal handle the event. We assume
sc->intrstatus = status; * it will clear whatever condition caused
ath9k_ps_wakeup(sc); * the interrupt.
*/
ath9k_hw_procmibevent(ah, &sc->nodestats);
ath9k_hw_set_interrupts(ah, sc->imask);
}
if (status & ATH9K_INT_FATAL) { if (status & ATH9K_INT_TIM_TIMER) {
/* need a chip reset */ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
sched = true; /* Clear RxAbort bit so that we can
} else if (status & ATH9K_INT_RXORN) { * receive frames */
/* need a chip reset */ ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
ath9k_hw_setrxabort(ah, 0);
sched = true; sched = true;
} else { sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
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
* RXE bit is written, but it doesn't work
* at least on older hardware revs.
*/
sched = true;
}
if (status & ATH9K_INT_TXURN)
/* bump tx trigger level */
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) {
/*
* Disable interrupts until we service the MIB
* interrupt; otherwise it will continue to
* fire.
*/
ath9k_hw_set_interrupts(ah, 0);
/*
* Let the hal handle the event. We assume
* it will clear whatever condition caused
* the interrupt.
*/
ath9k_hw_procmibevent(ah, &sc->nodestats);
ath9k_hw_set_interrupts(ah, sc->imask);
}
if (status & ATH9K_INT_TIM_TIMER) {
if (!(ah->caps.hw_caps &
ATH9K_HW_CAP_AUTOSLEEP)) {
/* Clear RxAbort bit so that we can
* receive frames */
ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
ath9k_hw_setrxabort(ah, 0);
sched = true;
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) ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment