From: Sujith Manoharan <c_man...@qca.qualcomm.com>

When a HW reset is done, the interrupt tasklet is
disabled before ISRs are disabled in the HW. This
allows a small window where the HW can still generate
interrupts. Since the tasklet is disabled and not killed,
it is not scheduled but deferred for execution at a later
time.

This happens because ATH_OP_HW_RESET is not set when ath_reset()
is called. When the hw_reset_work workqueue is used, this
problem doesn't arise because ATH_OP_HW_RESET is set
and the ISR bails out.

Set ATH_OP_HW_RESET properly in ath_reset() to avoid
this race - all the ath_reset_internal() callers have
been converted to use ath_reset() in the previous patch.

Signed-off-by: Sujith Manoharan <c_man...@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/main.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/main.c 
b/drivers/net/wireless/ath/ath9k/main.c
index eb6ba9f..dda09ba 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -598,10 +598,17 @@ chip_reset:
 #undef SCHED_INTR
 }
 
+/*
+ * This function is called when a HW reset cannot be deferred
+ * and has to be immediate.
+ */
 int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan)
 {
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        int r;
 
+       set_bit(ATH_OP_HW_RESET, &common->op_flags);
+
        ath9k_ps_wakeup(sc);
        r = ath_reset_internal(sc, hchan);
        ath9k_ps_restore(sc);
@@ -609,6 +616,11 @@ int ath_reset(struct ath_softc *sc, struct ath9k_channel 
*hchan)
        return r;
 }
 
+/*
+ * When a HW reset can be deferred, it is added to the
+ * hw_reset_work workqueue, but we set ATH_OP_HW_RESET before
+ * queueing.
+ */
 void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-- 
2.1.2

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to