]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Mar 2017 06:56:53 +0000 (07:56 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Mar 2017 06:56:53 +0000 (07:56 +0100)
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

queue-4.4/ath5k-drop-bogus-warning-on-drv_set_key-with-unsupported-cipher.patch [new file with mode: 0644]
queue-4.4/ath9k-fix-race-condition-in-enabling-disabling-irqs.patch [new file with mode: 0644]
queue-4.4/ath9k-use-correct-otp-register-offsets-for-the-ar9340-and-ar9550.patch [new file with mode: 0644]
queue-4.4/series

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 (file)
index 0000000..bb3d8e4
--- /dev/null
@@ -0,0 +1,31 @@
+From a70e1d6fd6b5e1a81fa6171600942bee34f5128f Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@nbd.name>
+Date: Wed, 11 Jan 2017 16:32:13 +0200
+Subject: ath5k: drop bogus warning on drv_set_key with unsupported cipher
+
+From: Felix Fietkau <nbd@nbd.name>
+
+commit a70e1d6fd6b5e1a81fa6171600942bee34f5128f upstream.
+
+Simply return -EOPNOTSUPP instead.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..d913779
--- /dev/null
@@ -0,0 +1,210 @@
+From 3a5e969bb2f6692a256352649355d56d018d6b88 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 2 Feb 2017 10:14:52 +0100
+Subject: ath9k: fix race condition in enabling/disabling IRQs
+
+From: Felix Fietkau <nbd@nbd.name>
+
+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 <nbd@nbd.name>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..a60ad92
--- /dev/null
@@ -0,0 +1,53 @@
+From c9f1e32600816d695f817477d56490bfc2ba43c6 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Tue, 14 Feb 2017 20:10:30 +0100
+Subject: ath9k: use correct OTP register offsets for the AR9340 and AR9550
+
+From: Christian Lamparter <chunkeey@googlemail.com>
+
+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 <juhosg@openwrt.org>
+Fixes: add295a4afbdf5852d0 "ath9k: use correct OTP register offsets for AR9550"
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Chris Blake <chrisrblake93@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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,
index 659099c7b2933288fe45a20ac1d38fd1c892eabc..73cf50d3d2ba17793ac2840d7de66b6a17543607 100644 (file)
@@ -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