Skip to content

Commit

Permalink
ath9k: fix interrupt storms on queued hardware reset
Browse files Browse the repository at this point in the history
commit b74713d
"ath9k: Handle fatal interrupts properly" introduced a race condition, where
IRQs are being left enabled, however the irq handler returns IRQ_HANDLED
while the reset is still queued without addressing the IRQ cause.
This leads to an IRQ storm that prevents the system from even getting to
the reset code.

Fix this by disabling IRQs in the handler without touching intr_ref_cnt.

Cc: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
Cc: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Felix Fietkau authored and John W. Linville committed Aug 10, 2012
1 parent bbf2e65 commit f41a9b3
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 7 deletions.
18 changes: 12 additions & 6 deletions drivers/net/wireless/ath/ath9k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -773,15 +773,10 @@ bool ath9k_hw_intrpend(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_intrpend);

void ath9k_hw_disable_interrupts(struct ath_hw *ah)
void ath9k_hw_kill_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, INTERRUPT, "disable IER\n");
REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
(void) REG_READ(ah, AR_IER);
Expand All @@ -793,6 +788,17 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah)
(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
}
}
EXPORT_SYMBOL(ath9k_hw_kill_interrupts);

void ath9k_hw_disable_interrupts(struct ath_hw *ah)
{
if (!(ah->imask & ATH9K_INT_GLOBAL))
atomic_set(&ah->intr_ref_cnt, -1);
else
atomic_dec(&ah->intr_ref_cnt);

ath9k_hw_kill_interrupts(ah);
}
EXPORT_SYMBOL(ath9k_hw_disable_interrupts);

void ath9k_hw_enable_interrupts(struct ath_hw *ah)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath9k/mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ bool ath9k_hw_intrpend(struct ath_hw *ah);
void ath9k_hw_set_interrupts(struct ath_hw *ah);
void ath9k_hw_enable_interrupts(struct ath_hw *ah);
void ath9k_hw_disable_interrupts(struct ath_hw *ah);
void ath9k_hw_kill_interrupts(struct ath_hw *ah);

void ar9002_hw_attach_mac_ops(struct ath_hw *ah);

Expand Down
4 changes: 3 additions & 1 deletion drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,10 @@ irqreturn_t ath_isr(int irq, void *dev)
if (!ath9k_hw_intrpend(ah))
return IRQ_NONE;

if(test_bit(SC_OP_HW_RESET, &sc->sc_flags))
if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) {
ath9k_hw_kill_interrupts(ah);
return IRQ_HANDLED;
}

/*
* Figure out the reason(s) for the interrupt. Note
Expand Down

0 comments on commit f41a9b3

Please sign in to comment.