From bd7f9e8c379e7b9e43dec62d1b48699347469c7b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 9 Mar 2017 07:56:53 +0100 Subject: [PATCH] 4.4-stable patches added patches: ath5k-drop-bogus-warning-on-drv_set_key-with-unsupported-cipher.patch ath9k-fix-race-condition-in-enabling-disabling-irqs.patch ath9k-use-correct-otp-register-offsets-for-the-ar9340-and-ar9550.patch --- ...-drv_set_key-with-unsupported-cipher.patch | 31 +++ ...condition-in-enabling-disabling-irqs.patch | 210 ++++++++++++++++++ ...er-offsets-for-the-ar9340-and-ar9550.patch | 53 +++++ queue-4.4/series | 3 + 4 files changed, 297 insertions(+) create mode 100644 queue-4.4/ath5k-drop-bogus-warning-on-drv_set_key-with-unsupported-cipher.patch create mode 100644 queue-4.4/ath9k-fix-race-condition-in-enabling-disabling-irqs.patch create mode 100644 queue-4.4/ath9k-use-correct-otp-register-offsets-for-the-ar9340-and-ar9550.patch diff --git a/queue-4.4/ath5k-drop-bogus-warning-on-drv_set_key-with-unsupported-cipher.patch b/queue-4.4/ath5k-drop-bogus-warning-on-drv_set_key-with-unsupported-cipher.patch new file mode 100644 index 00000000000..bb3d8e46968 --- /dev/null +++ b/queue-4.4/ath5k-drop-bogus-warning-on-drv_set_key-with-unsupported-cipher.patch @@ -0,0 +1,31 @@ +From a70e1d6fd6b5e1a81fa6171600942bee34f5128f Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Wed, 11 Jan 2017 16:32:13 +0200 +Subject: ath5k: drop bogus warning on drv_set_key with unsupported cipher + +From: Felix Fietkau + +commit a70e1d6fd6b5e1a81fa6171600942bee34f5128f upstream. + +Simply return -EOPNOTSUPP instead. + +Signed-off-by: Felix Fietkau +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath5k/mac80211-ops.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c ++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +@@ -502,8 +502,7 @@ ath5k_set_key(struct ieee80211_hw *hw, e + break; + return -EOPNOTSUPP; + default: +- WARN_ON(1); +- return -EINVAL; ++ return -EOPNOTSUPP; + } + + mutex_lock(&ah->lock); diff --git a/queue-4.4/ath9k-fix-race-condition-in-enabling-disabling-irqs.patch b/queue-4.4/ath9k-fix-race-condition-in-enabling-disabling-irqs.patch new file mode 100644 index 00000000000..d913779172c --- /dev/null +++ b/queue-4.4/ath9k-fix-race-condition-in-enabling-disabling-irqs.patch @@ -0,0 +1,210 @@ +From 3a5e969bb2f6692a256352649355d56d018d6b88 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 2 Feb 2017 10:14:52 +0100 +Subject: ath9k: fix race condition in enabling/disabling IRQs + +From: Felix Fietkau + +commit 3a5e969bb2f6692a256352649355d56d018d6b88 upstream. + +The code currently relies on refcounting to disable IRQs from within the +IRQ handler and re-enabling them again after the tasklet has run. + +However, due to race conditions sometimes the IRQ handler might be +called twice, or the tasklet may not run at all (if interrupted in the +middle of a reset). + +This can cause nasty imbalances in the irq-disable refcount which will +get the driver permanently stuck until the entire radio has been stopped +and started again (ath_reset will not recover from this). + +Instead of using this fragile logic, change the code to ensure that +running the irq handler during tasklet processing is safe, and leave the +refcount untouched. + +Signed-off-by: Felix Fietkau +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 1 + drivers/net/wireless/ath/ath9k/mac.c | 44 +++++++++++++++++++++++++-------- + drivers/net/wireless/ath/ath9k/mac.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 27 ++++++++------------ + 5 files changed, 48 insertions(+), 26 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -959,6 +959,7 @@ struct ath_softc { + struct survey_info *cur_survey; + struct survey_info survey[ATH9K_NUM_CHANNELS]; + ++ spinlock_t intr_lock; + struct tasklet_struct intr_tq; + struct tasklet_struct bcon_tasklet; + struct ath_hw *sc_ah; +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -619,6 +619,7 @@ static int ath9k_init_softc(u16 devid, s + common->bt_ant_diversity = 1; + + spin_lock_init(&common->cc_lock); ++ spin_lock_init(&sc->intr_lock); + spin_lock_init(&sc->sc_serial_rw); + spin_lock_init(&sc->sc_pm_lock); + spin_lock_init(&sc->chan_lock); +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -805,21 +805,12 @@ void ath9k_hw_disable_interrupts(struct + } + EXPORT_SYMBOL(ath9k_hw_disable_interrupts); + +-void ath9k_hw_enable_interrupts(struct ath_hw *ah) ++static void __ath9k_hw_enable_interrupts(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); + u32 sync_default = AR_INTR_SYNC_DEFAULT; + u32 async_mask; + +- if (!(ah->imask & ATH9K_INT_GLOBAL)) +- return; +- +- if (!atomic_inc_and_test(&ah->intr_ref_cnt)) { +- ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", +- atomic_read(&ah->intr_ref_cnt)); +- return; +- } +- + if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || + AR_SREV_9561(ah)) + sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; +@@ -841,6 +832,39 @@ void ath9k_hw_enable_interrupts(struct a + ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", + REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); + } ++ ++void ath9k_hw_resume_interrupts(struct ath_hw *ah) ++{ ++ struct ath_common *common = ath9k_hw_common(ah); ++ ++ if (!(ah->imask & ATH9K_INT_GLOBAL)) ++ return; ++ ++ if (atomic_read(&ah->intr_ref_cnt) != 0) { ++ ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", ++ atomic_read(&ah->intr_ref_cnt)); ++ return; ++ } ++ ++ __ath9k_hw_enable_interrupts(ah); ++} ++EXPORT_SYMBOL(ath9k_hw_resume_interrupts); ++ ++void ath9k_hw_enable_interrupts(struct ath_hw *ah) ++{ ++ struct ath_common *common = ath9k_hw_common(ah); ++ ++ if (!(ah->imask & ATH9K_INT_GLOBAL)) ++ return; ++ ++ if (!atomic_inc_and_test(&ah->intr_ref_cnt)) { ++ ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", ++ atomic_read(&ah->intr_ref_cnt)); ++ return; ++ } ++ ++ __ath9k_hw_enable_interrupts(ah); ++} + EXPORT_SYMBOL(ath9k_hw_enable_interrupts); + + void ath9k_hw_set_interrupts(struct ath_hw *ah) +--- a/drivers/net/wireless/ath/ath9k/mac.h ++++ b/drivers/net/wireless/ath/ath9k/mac.h +@@ -748,6 +748,7 @@ void ath9k_hw_set_interrupts(struct ath_ + 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 ath9k_hw_resume_interrupts(struct ath_hw *ah); + + void ar9002_hw_attach_mac_ops(struct ath_hw *ah); + +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -373,21 +373,20 @@ void ath9k_tasklet(unsigned long data) + struct ath_common *common = ath9k_hw_common(ah); + enum ath_reset_type type; + unsigned long flags; +- u32 status = sc->intrstatus; ++ u32 status; + u32 rxmask; + ++ spin_lock_irqsave(&sc->intr_lock, flags); ++ status = sc->intrstatus; ++ sc->intrstatus = 0; ++ spin_unlock_irqrestore(&sc->intr_lock, flags); ++ + ath9k_ps_wakeup(sc); + spin_lock(&sc->sc_pcu_lock); + + if (status & ATH9K_INT_FATAL) { + type = RESET_TYPE_FATAL_INT; + ath9k_queue_reset(sc, type); +- +- /* +- * Increment the ref. counter here so that +- * interrupts are enabled in the reset routine. +- */ +- atomic_inc(&ah->intr_ref_cnt); + ath_dbg(common, RESET, "FATAL: Skipping interrupts\n"); + goto out; + } +@@ -403,11 +402,6 @@ void ath9k_tasklet(unsigned long data) + type = RESET_TYPE_BB_WATCHDOG; + ath9k_queue_reset(sc, type); + +- /* +- * Increment the ref. counter here so that +- * interrupts are enabled in the reset routine. +- */ +- atomic_inc(&ah->intr_ref_cnt); + ath_dbg(common, RESET, + "BB_WATCHDOG: Skipping interrupts\n"); + goto out; +@@ -420,7 +414,6 @@ void ath9k_tasklet(unsigned long data) + if ((sc->gtt_cnt >= MAX_GTT_CNT) && !ath9k_hw_check_alive(ah)) { + type = RESET_TYPE_TX_GTT; + ath9k_queue_reset(sc, type); +- atomic_inc(&ah->intr_ref_cnt); + ath_dbg(common, RESET, + "GTT: Skipping interrupts\n"); + goto out; +@@ -477,7 +470,7 @@ void ath9k_tasklet(unsigned long data) + ath9k_btcoex_handle_interrupt(sc, status); + + /* re-enable hardware interrupt */ +- ath9k_hw_enable_interrupts(ah); ++ ath9k_hw_resume_interrupts(ah); + out: + spin_unlock(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); +@@ -541,7 +534,9 @@ irqreturn_t ath_isr(int irq, void *dev) + return IRQ_NONE; + + /* Cache the status */ +- sc->intrstatus = status; ++ spin_lock(&sc->intr_lock); ++ sc->intrstatus |= status; ++ spin_unlock(&sc->intr_lock); + + if (status & SCHED_INTR) + sched = true; +@@ -587,7 +582,7 @@ chip_reset: + + if (sched) { + /* turn off every interrupt */ +- ath9k_hw_disable_interrupts(ah); ++ ath9k_hw_kill_interrupts(ah); + tasklet_schedule(&sc->intr_tq); + } + diff --git a/queue-4.4/ath9k-use-correct-otp-register-offsets-for-the-ar9340-and-ar9550.patch b/queue-4.4/ath9k-use-correct-otp-register-offsets-for-the-ar9340-and-ar9550.patch new file mode 100644 index 00000000000..a60ad928b69 --- /dev/null +++ b/queue-4.4/ath9k-use-correct-otp-register-offsets-for-the-ar9340-and-ar9550.patch @@ -0,0 +1,53 @@ +From c9f1e32600816d695f817477d56490bfc2ba43c6 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Tue, 14 Feb 2017 20:10:30 +0100 +Subject: ath9k: use correct OTP register offsets for the AR9340 and AR9550 + +From: Christian Lamparter + +commit c9f1e32600816d695f817477d56490bfc2ba43c6 upstream. + +This patch fixes the OTP register definitions for the AR934x and AR9550 +WMAC SoC. + +Previously, the ath9k driver was unable to initialize the integrated +WMAC on an Aerohive AP121: + +| ath: phy0: timeout (1000 us) on reg 0x30018: 0xbadc0ffe & 0x00000007 != 0x00000004 +| ath: phy0: timeout (1000 us) on reg 0x30018: 0xbadc0ffe & 0x00000007 != 0x00000004 +| ath: phy0: Unable to initialize hardware; initialization status: -5 +| ath9k ar934x_wmac: failed to initialize device +| ath9k: probe of ar934x_wmac failed with error -5 + +It turns out that the AR9300_OTP_STATUS and AR9300_OTP_DATA +definitions contain a typo. + +Cc: Gabor Juhos +Fixes: add295a4afbdf5852d0 "ath9k: use correct OTP register offsets for AR9550" +Signed-off-by: Christian Lamparter +Signed-off-by: Chris Blake +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +@@ -73,13 +73,13 @@ + #define AR9300_OTP_BASE \ + ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000) + #define AR9300_OTP_STATUS \ +- ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30018 : 0x15f18) ++ ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x31018 : 0x15f18) + #define AR9300_OTP_STATUS_TYPE 0x7 + #define AR9300_OTP_STATUS_VALID 0x4 + #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 + #define AR9300_OTP_STATUS_SM_BUSY 0x1 + #define AR9300_OTP_READ_DATA \ +- ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3001c : 0x15f1c) ++ ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3101c : 0x15f1c) + + enum targetPowerHTRates { + HT_TARGET_RATE_0_8_16, diff --git a/queue-4.4/series b/queue-4.4/series index 659099c7b29..73cf50d3d2b 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -51,3 +51,6 @@ ext4-return-erofs-if-device-is-r-o-and-journal-replay-is-needed.patch samples-seccomp-fix-64-bit-comparison-macros.patch target-obtain-se_node_acl-acl_kref-during-get_initiator_node_acl.patch target-fix-multi-session-dynamic-se_node_acl-double-free-oops.patch +ath5k-drop-bogus-warning-on-drv_set_key-with-unsupported-cipher.patch +ath9k-fix-race-condition-in-enabling-disabling-irqs.patch +ath9k-use-correct-otp-register-offsets-for-the-ar9340-and-ar9550.patch -- 2.47.3