diff options
Diffstat (limited to 'package/kernel/mac80211/patches/307-ath9k-Set-ATH_OP_HW_RESET-before-HW-reset.patch')
-rw-r--r-- | package/kernel/mac80211/patches/307-ath9k-Set-ATH_OP_HW_RESET-before-HW-reset.patch | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/307-ath9k-Set-ATH_OP_HW_RESET-before-HW-reset.patch b/package/kernel/mac80211/patches/307-ath9k-Set-ATH_OP_HW_RESET-before-HW-reset.patch new file mode 100644 index 0000000..75a2ab5 --- /dev/null +++ b/package/kernel/mac80211/patches/307-ath9k-Set-ATH_OP_HW_RESET-before-HW-reset.patch @@ -0,0 +1,55 @@ +From: Sujith Manoharan <c_manoha@qca.qualcomm.com> +Date: Fri, 17 Oct 2014 07:40:12 +0530 +Subject: [PATCH] ath9k: Set ATH_OP_HW_RESET before HW reset + +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_manoha@qca.qualcomm.com> +--- + +--- 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, stru + 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); |