Skip to content

Commit

Permalink
ath9k: do not access hardware on IRQs during reset
Browse files Browse the repository at this point in the history
Instead of killing interrupts during reset when the first one happens,
kill them before issuing the reset.
This fixes an easy to reproduce crash with multiple cards sharing the
same IRQ.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Felix Fietkau authored and linvjw committed Dec 1, 2014
1 parent ef739ab commit 872b5d8
Showing 1 changed file with 8 additions and 6 deletions.
14 changes: 8 additions & 6 deletions drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,16 +512,13 @@ irqreturn_t ath_isr(int irq, void *dev)
if (!ah || test_bit(ATH_OP_INVALID, &common->op_flags))
return IRQ_NONE;

/* shared irq, not for us */
if (!AR_SREV_9100(ah) && test_bit(ATH_OP_HW_RESET, &common->op_flags))
return IRQ_NONE;

/* shared irq, not for us */
if (!ath9k_hw_intrpend(ah))
return IRQ_NONE;

if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) {
ath9k_hw_kill_interrupts(ah);
return IRQ_HANDLED;
}

/*
* Figure out the reason(s) for the interrupt. Note
* that the hal returns a pseudo-ISR that may include
Expand All @@ -532,6 +529,9 @@ irqreturn_t ath_isr(int irq, void *dev)
ath9k_debug_sync_cause(sc, sync_cause);
status &= ah->imask; /* discard unasked-for bits */

if (AR_SREV_9100(ah) && test_bit(ATH_OP_HW_RESET, &common->op_flags))
return IRQ_HANDLED;

/*
* If there are no status bits set, then this interrupt was not
* for me (should have been caught above).
Expand Down Expand Up @@ -613,6 +613,7 @@ int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan)
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int r;

ath9k_hw_kill_interrupts(sc->sc_ah);
set_bit(ATH_OP_HW_RESET, &common->op_flags);

ath9k_ps_wakeup(sc);
Expand All @@ -633,6 +634,7 @@ void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type)
#ifdef CONFIG_ATH9K_DEBUGFS
RESET_STAT_INC(sc, type);
#endif
ath9k_hw_kill_interrupts(sc->sc_ah);
set_bit(ATH_OP_HW_RESET, &common->op_flags);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
Expand Down

0 comments on commit 872b5d8

Please sign in to comment.