mac80211: Revision r36939 breaks support for RT5370 (rt2800usb)
[oweals/openwrt.git] / package / kernel / mac80211 / patches / 329-ath9k-fix-race-condition-in-irq-processing-during-ha.patch
1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Wed, 14 Jan 2015 14:13:15 +0100
3 Subject: [PATCH] ath9k: fix race condition in irq processing during hardware
4  reset
5
6 To fix invalid hardware accesses, the commit
7 "ath9k: do not access hardware on IRQs during reset" made the irq
8 handler ignore interrupts emitted after queueing a hardware reset (which
9 disables the IRQ). This left a small time window for the IRQ to get
10 re-enabled by the tasklet, which caused IRQ storms.
11 Instead of returning IRQ_NONE when ATH_OP_HW_RESET is set, disable the
12 IRQ entirely for the duration of the reset.
13
14 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
15 ---
16
17 --- a/drivers/net/wireless/ath/ath9k/main.c
18 +++ b/drivers/net/wireless/ath/ath9k/main.c
19 @@ -285,6 +285,7 @@ static int ath_reset_internal(struct ath
20  
21         __ath_cancel_work(sc);
22  
23 +       disable_irq(sc->irq);
24         tasklet_disable(&sc->intr_tq);
25         tasklet_disable(&sc->bcon_tasklet);
26         spin_lock_bh(&sc->sc_pcu_lock);
27 @@ -331,6 +332,7 @@ static int ath_reset_internal(struct ath
28                 r = -EIO;
29  
30  out:
31 +       enable_irq(sc->irq);
32         spin_unlock_bh(&sc->sc_pcu_lock);
33         tasklet_enable(&sc->bcon_tasklet);
34         tasklet_enable(&sc->intr_tq);
35 @@ -512,9 +514,6 @@ irqreturn_t ath_isr(int irq, void *dev)
36         if (!ah || test_bit(ATH_OP_INVALID, &common->op_flags))
37                 return IRQ_NONE;
38  
39 -       if (!AR_SREV_9100(ah) && test_bit(ATH_OP_HW_RESET, &common->op_flags))
40 -               return IRQ_NONE;
41 -
42         /* shared irq, not for us */
43         if (!ath9k_hw_intrpend(ah))
44                 return IRQ_NONE;
45 @@ -529,7 +528,7 @@ irqreturn_t ath_isr(int irq, void *dev)
46         ath9k_debug_sync_cause(sc, sync_cause);
47         status &= ah->imask;    /* discard unasked-for bits */
48  
49 -       if (AR_SREV_9100(ah) && test_bit(ATH_OP_HW_RESET, &common->op_flags))
50 +       if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
51                 return IRQ_HANDLED;
52  
53         /*