From 5a05cb40ce04154772ab333bc1587beaad68717d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 13 Nov 2014 17:38:22 +0000 Subject: ath9k: fix crashes when using shared IRQs Signed-off-by: Felix Fietkau SVN-Revision: 43239 --- ...-not-access-hardware-on-IRQs-during-reset.patch | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 package/kernel/mac80211/patches/311-ath9k-do-not-access-hardware-on-IRQs-during-reset.patch (limited to 'package/kernel/mac80211/patches/311-ath9k-do-not-access-hardware-on-IRQs-during-reset.patch') diff --git a/package/kernel/mac80211/patches/311-ath9k-do-not-access-hardware-on-IRQs-during-reset.patch b/package/kernel/mac80211/patches/311-ath9k-do-not-access-hardware-on-IRQs-during-reset.patch new file mode 100644 index 0000000000..7996725025 --- /dev/null +++ b/package/kernel/mac80211/patches/311-ath9k-do-not-access-hardware-on-IRQs-during-reset.patch @@ -0,0 +1,51 @@ +From: Felix Fietkau +Date: Thu, 13 Nov 2014 18:29:26 +0100 +Subject: [PATCH] ath9k: do not access hardware on IRQs during reset + +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. + +Cc: stable@vger.kernel.org +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -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 (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 +@@ -613,6 +610,7 @@ int ath_reset(struct ath_softc *sc, stru + 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); +@@ -633,6 +631,7 @@ void ath9k_queue_reset(struct ath_softc + #ifdef CPTCFG_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); + } -- cgit v1.2.3