]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Mar 2017 06:57:19 +0000 (07:57 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Mar 2017 06:57:19 +0000 (07:57 +0100)
added patches:
ath10k-fix-boot-failure-in-utf-mode-testmode.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
drivers-hv-vmbus-raise-retry-wait-limits-in-vmbus_post_msg.patch
pci-altera-fix-tlp_cfg_dw0-for-tlp-write.patch
pci-hotplug-pnv-php-disable-msi-and-pci-device-properly.patch
pci-hv-fix-wslot_to_devfn-to-fix-warnings-on-device-removal.patch

queue-4.9/ath10k-fix-boot-failure-in-utf-mode-testmode.patch [new file with mode: 0644]
queue-4.9/ath5k-drop-bogus-warning-on-drv_set_key-with-unsupported-cipher.patch [new file with mode: 0644]
queue-4.9/ath9k-fix-race-condition-in-enabling-disabling-irqs.patch [new file with mode: 0644]
queue-4.9/ath9k-use-correct-otp-register-offsets-for-the-ar9340-and-ar9550.patch [new file with mode: 0644]
queue-4.9/drivers-hv-vmbus-raise-retry-wait-limits-in-vmbus_post_msg.patch [new file with mode: 0644]
queue-4.9/pci-altera-fix-tlp_cfg_dw0-for-tlp-write.patch [new file with mode: 0644]
queue-4.9/pci-hotplug-pnv-php-disable-msi-and-pci-device-properly.patch [new file with mode: 0644]
queue-4.9/pci-hv-fix-wslot_to_devfn-to-fix-warnings-on-device-removal.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/ath10k-fix-boot-failure-in-utf-mode-testmode.patch b/queue-4.9/ath10k-fix-boot-failure-in-utf-mode-testmode.patch
new file mode 100644 (file)
index 0000000..309a761
--- /dev/null
@@ -0,0 +1,63 @@
+From cb4281528b62207918b1e95827cad7527aa4dbaa Mon Sep 17 00:00:00 2001
+From: Tamizh chelvam <c_traja@qti.qualcomm.com>
+Date: Thu, 2 Feb 2017 08:32:18 +0200
+Subject: ath10k: fix boot failure in UTF mode/testmode
+
+From: Tamizh chelvam <c_traja@qti.qualcomm.com>
+
+commit cb4281528b62207918b1e95827cad7527aa4dbaa upstream.
+
+Rx filter reset and the dynamic tx switch mode (EXT_RESOURCE_CFG)
+configuration are causing the following errors when UTF firmware
+is loaded to the target.
+
+Error message 1:
+[ 598.015629] ath10k_pci 0001:01:00.0: failed to ping firmware: -110
+[ 598.020828] ath10k_pci 0001:01:00.0: failed to reset rx filter: -110
+[ 598.141556] ath10k_pci 0001:01:00.0: failed to start core (testmode): -110
+
+Error message 2:
+[ 668.615839] ath10k_ahb a000000.wifi: failed to send ext resource cfg command : -95
+[ 668.618902] ath10k_ahb a000000.wifi: failed to start core (testmode): -95
+
+Avoiding these configurations while bringing the target in
+testmode is solving the problem.
+
+Signed-off-by: Tamizh chelvam <c_traja@qti.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/ath/ath10k/core.c |   14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -1901,7 +1901,8 @@ int ath10k_core_start(struct ath10k *ar,
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
+                  ar->hw->wiphy->fw_version);
+-      if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map)) {
++      if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map) &&
++          mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+               val = 0;
+               if (ath10k_peer_stats_enabled(ar))
+                       val = WMI_10_4_PEER_STATS;
+@@ -1954,10 +1955,13 @@ int ath10k_core_start(struct ath10k *ar,
+        * possible to implicitly make it correct by creating a dummy vdev and
+        * then deleting it.
+        */
+-      status = ath10k_core_reset_rx_filter(ar);
+-      if (status) {
+-              ath10k_err(ar, "failed to reset rx filter: %d\n", status);
+-              goto err_hif_stop;
++      if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
++              status = ath10k_core_reset_rx_filter(ar);
++              if (status) {
++                      ath10k_err(ar,
++                                 "failed to reset rx filter: %d\n", status);
++                      goto err_hif_stop;
++              }
+       }
+       /* If firmware indicates Full Rx Reorder support it must be used in a
diff --git a/queue-4.9/ath5k-drop-bogus-warning-on-drv_set_key-with-unsupported-cipher.patch b/queue-4.9/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.9/ath9k-fix-race-condition-in-enabling-disabling-irqs.patch b/queue-4.9/ath9k-fix-race-condition-in-enabling-disabling-irqs.patch
new file mode 100644 (file)
index 0000000..e360fa9
--- /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
+@@ -626,6 +626,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
+@@ -744,6 +744,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.9/ath9k-use-correct-otp-register-offsets-for-the-ar9340-and-ar9550.patch b/queue-4.9/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,
diff --git a/queue-4.9/drivers-hv-vmbus-raise-retry-wait-limits-in-vmbus_post_msg.patch b/queue-4.9/drivers-hv-vmbus-raise-retry-wait-limits-in-vmbus_post_msg.patch
new file mode 100644 (file)
index 0000000..81630c2
--- /dev/null
@@ -0,0 +1,187 @@
+From c0bb03924f1a80e7f65900e36c8e6b3dc167c5f8 Mon Sep 17 00:00:00 2001
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+Date: Wed, 7 Dec 2016 01:16:24 -0800
+Subject: Drivers: hv: vmbus: Raise retry/wait limits in vmbus_post_msg()
+
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+commit c0bb03924f1a80e7f65900e36c8e6b3dc167c5f8 upstream.
+
+DoS protection conditions were altered in WS2016 and now it's easy to get
+-EAGAIN returned from vmbus_post_msg() (e.g. when we try changing MTU on a
+netvsc device in a loop). All vmbus_post_msg() callers don't retry the
+operation and we usually end up with a non-functional device or crash.
+
+While host's DoS protection conditions are unknown to me my tests show that
+it can take up to 10 seconds before the message is sent so doing udelay()
+is not an option, we really need to sleep. Almost all vmbus_post_msg()
+callers are ready to sleep but there is one special case:
+vmbus_initiate_unload() which can be called from interrupt/NMI context and
+we can't sleep there. I'm also not sure about the lonely
+vmbus_send_tl_connect_request() which has no in-tree users but its external
+users are most likely waiting for the host to reply so sleeping there is
+also appropriate.
+
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/channel.c      |   17 +++++++++--------
+ drivers/hv/channel_mgmt.c |   10 ++++++----
+ drivers/hv/connection.c   |   17 ++++++++++++-----
+ drivers/hv/hyperv_vmbus.h |    2 +-
+ 4 files changed, 28 insertions(+), 18 deletions(-)
+
+--- a/drivers/hv/channel.c
++++ b/drivers/hv/channel.c
+@@ -181,7 +181,7 @@ int vmbus_open(struct vmbus_channel *new
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+       ret = vmbus_post_msg(open_msg,
+-                             sizeof(struct vmbus_channel_open_channel));
++                           sizeof(struct vmbus_channel_open_channel), true);
+       if (ret != 0) {
+               err = ret;
+@@ -233,7 +233,7 @@ int vmbus_send_tl_connect_request(const
+       conn_msg.guest_endpoint_id = *shv_guest_servie_id;
+       conn_msg.host_service_id = *shv_host_servie_id;
+-      return vmbus_post_msg(&conn_msg, sizeof(conn_msg));
++      return vmbus_post_msg(&conn_msg, sizeof(conn_msg), true);
+ }
+ EXPORT_SYMBOL_GPL(vmbus_send_tl_connect_request);
+@@ -419,7 +419,7 @@ int vmbus_establish_gpadl(struct vmbus_c
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+       ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
+-                             sizeof(*msginfo));
++                           sizeof(*msginfo), true);
+       if (ret != 0)
+               goto cleanup;
+@@ -433,8 +433,8 @@ int vmbus_establish_gpadl(struct vmbus_c
+               gpadl_body->gpadl = next_gpadl_handle;
+               ret = vmbus_post_msg(gpadl_body,
+-                                   submsginfo->msgsize -
+-                                   sizeof(*submsginfo));
++                                   submsginfo->msgsize - sizeof(*submsginfo),
++                                   true);
+               if (ret != 0)
+                       goto cleanup;
+@@ -485,8 +485,8 @@ int vmbus_teardown_gpadl(struct vmbus_ch
+       list_add_tail(&info->msglistentry,
+                     &vmbus_connection.chn_msg_list);
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+-      ret = vmbus_post_msg(msg,
+-                             sizeof(struct vmbus_channel_gpadl_teardown));
++      ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown),
++                           true);
+       if (ret)
+               goto post_msg_err;
+@@ -557,7 +557,8 @@ static int vmbus_close_internal(struct v
+       msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
+       msg->child_relid = channel->offermsg.child_relid;
+-      ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
++      ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel),
++                           true);
+       if (ret) {
+               pr_err("Close failed: close post msg return is %d\n", ret);
+--- a/drivers/hv/channel_mgmt.c
++++ b/drivers/hv/channel_mgmt.c
+@@ -321,7 +321,8 @@ static void vmbus_release_relid(u32 reli
+       memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
+       msg.child_relid = relid;
+       msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
+-      vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released));
++      vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released),
++                     true);
+ }
+ void hv_event_tasklet_disable(struct vmbus_channel *channel)
+@@ -728,7 +729,8 @@ void vmbus_initiate_unload(bool crash)
+       init_completion(&vmbus_connection.unload_event);
+       memset(&hdr, 0, sizeof(struct vmbus_channel_message_header));
+       hdr.msgtype = CHANNELMSG_UNLOAD;
+-      vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header));
++      vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header),
++                     !crash);
+       /*
+        * vmbus_initiate_unload() is also called on crash and the crash can be
+@@ -1116,8 +1118,8 @@ int vmbus_request_offers(void)
+       msg->msgtype = CHANNELMSG_REQUESTOFFERS;
+-      ret = vmbus_post_msg(msg,
+-                             sizeof(struct vmbus_channel_message_header));
++      ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_message_header),
++                           true);
+       if (ret != 0) {
+               pr_err("Unable to request offers - %d\n", ret);
+--- a/drivers/hv/connection.c
++++ b/drivers/hv/connection.c
+@@ -110,7 +110,8 @@ static int vmbus_negotiate_version(struc
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+       ret = vmbus_post_msg(msg,
+-                             sizeof(struct vmbus_channel_initiate_contact));
++                           sizeof(struct vmbus_channel_initiate_contact),
++                           true);
+       if (ret != 0) {
+               spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+               list_del(&msginfo->msglistentry);
+@@ -434,7 +435,7 @@ void vmbus_on_event(unsigned long data)
+ /*
+  * vmbus_post_msg - Send a msg on the vmbus's message connection
+  */
+-int vmbus_post_msg(void *buffer, size_t buflen)
++int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep)
+ {
+       union hv_connection_id conn_id;
+       int ret = 0;
+@@ -449,7 +450,7 @@ int vmbus_post_msg(void *buffer, size_t
+        * insufficient resources. Retry the operation a couple of
+        * times before giving up.
+        */
+-      while (retries < 20) {
++      while (retries < 100) {
+               ret = hv_post_message(conn_id, 1, buffer, buflen);
+               switch (ret) {
+@@ -472,8 +473,14 @@ int vmbus_post_msg(void *buffer, size_t
+               }
+               retries++;
+-              udelay(usec);
+-              if (usec < 2048)
++              if (can_sleep && usec > 1000)
++                      msleep(usec / 1000);
++              else if (usec < MAX_UDELAY_MS * 1000)
++                      udelay(usec);
++              else
++                      mdelay(usec / 1000);
++
++              if (usec < 256000)
+                       usec *= 2;
+       }
+       return ret;
+--- a/drivers/hv/hyperv_vmbus.h
++++ b/drivers/hv/hyperv_vmbus.h
+@@ -683,7 +683,7 @@ void vmbus_free_channels(void);
+ int vmbus_connect(void);
+ void vmbus_disconnect(void);
+-int vmbus_post_msg(void *buffer, size_t buflen);
++int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep);
+ void vmbus_on_event(unsigned long data);
+ void vmbus_on_msg_dpc(unsigned long data);
diff --git a/queue-4.9/pci-altera-fix-tlp_cfg_dw0-for-tlp-write.patch b/queue-4.9/pci-altera-fix-tlp_cfg_dw0-for-tlp-write.patch
new file mode 100644 (file)
index 0000000..7b671e3
--- /dev/null
@@ -0,0 +1,59 @@
+From 2a7275a3d867b228216886aae35e1f64291180b1 Mon Sep 17 00:00:00 2001
+From: Ley Foon Tan <ley.foon.tan@intel.com>
+Date: Tue, 28 Feb 2017 18:37:16 +0800
+Subject: PCI: altera: Fix TLP_CFG_DW0 for TLP write
+
+From: Ley Foon Tan <ley.foon.tan@intel.com>
+
+commit 2a7275a3d867b228216886aae35e1f64291180b1 upstream.
+
+eb5767122feb ("PCI: altera: Simplify TLB_CFG_DW0 usage") used
+TLP_FMTTYPE_CFGRD* (instead of TLP_FMTTYPE_CFGWR*) for TLP writes, which
+causes writing to configuration space to fail.  Fix it by using correct
+FMTTYPE for write operation.
+
+Fixes: eb5767122feb ("PCI: altera: Simplify TLB_CFG_DW0 usage")
+Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/host/pcie-altera.c |   10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/pci/host/pcie-altera.c
++++ b/drivers/pci/host/pcie-altera.c
+@@ -57,10 +57,14 @@
+ #define TLP_WRITE_TAG                 0x10
+ #define RP_DEVFN                      0
+ #define TLP_REQ_ID(bus, devfn)                (((bus) << 8) | (devfn))
+-#define TLP_CFG_DW0(pcie, bus)                                                \
++#define TLP_CFGRD_DW0(pcie, bus)                                      \
+     ((((bus == pcie->root_bus_nr) ? TLP_FMTTYPE_CFGRD0                        \
+                                   : TLP_FMTTYPE_CFGRD1) << 24) |      \
+      TLP_PAYLOAD_SIZE)
++#define TLP_CFGWR_DW0(pcie, bus)                                      \
++    ((((bus == pcie->root_bus_nr) ? TLP_FMTTYPE_CFGWR0                        \
++                                  : TLP_FMTTYPE_CFGWR1) << 24) |      \
++     TLP_PAYLOAD_SIZE)
+ #define TLP_CFG_DW1(pcie, tag, be)    \
+     (((TLP_REQ_ID(pcie->root_bus_nr,  RP_DEVFN)) << 16) | (tag << 8) | (be))
+ #define TLP_CFG_DW2(bus, devfn, offset)       \
+@@ -222,7 +226,7 @@ static int tlp_cfg_dword_read(struct alt
+ {
+       u32 headers[TLP_HDR_SIZE];
+-      headers[0] = TLP_CFG_DW0(pcie, bus);
++      headers[0] = TLP_CFGRD_DW0(pcie, bus);
+       headers[1] = TLP_CFG_DW1(pcie, TLP_READ_TAG, byte_en);
+       headers[2] = TLP_CFG_DW2(bus, devfn, where);
+@@ -237,7 +241,7 @@ static int tlp_cfg_dword_write(struct al
+       u32 headers[TLP_HDR_SIZE];
+       int ret;
+-      headers[0] = TLP_CFG_DW0(pcie, bus);
++      headers[0] = TLP_CFGWR_DW0(pcie, bus);
+       headers[1] = TLP_CFG_DW1(pcie, TLP_WRITE_TAG, byte_en);
+       headers[2] = TLP_CFG_DW2(bus, devfn, where);
diff --git a/queue-4.9/pci-hotplug-pnv-php-disable-msi-and-pci-device-properly.patch b/queue-4.9/pci-hotplug-pnv-php-disable-msi-and-pci-device-properly.patch
new file mode 100644 (file)
index 0000000..fa7f3a0
--- /dev/null
@@ -0,0 +1,90 @@
+From 49f4b08e61547a5ccd2db551d994c4503efe5666 Mon Sep 17 00:00:00 2001
+From: Gavin Shan <gwshan@linux.vnet.ibm.com>
+Date: Thu, 16 Feb 2017 10:22:34 +1100
+Subject: pci/hotplug/pnv-php: Disable MSI and PCI device properly
+
+From: Gavin Shan <gwshan@linux.vnet.ibm.com>
+
+commit 49f4b08e61547a5ccd2db551d994c4503efe5666 upstream.
+
+pnv_php_disable_irq() can be called in two paths: Bailing path in
+pnv_php_enable_irq() or releasing slot. The MSI (or MSIx) interrupts
+is disabled unconditionally in pnv_php_disable_irq(). It's wrong
+because that might be enabled by drivers other than pnv-php.
+
+This disables MSI (or MSIx) interrupts and the PCI device only if
+it was enabled by pnv-php. In the error path of pnv_php_enable_irq(),
+we rely on the newly added parameter @disable_device. In the path
+of releasing slot, @pnv_php->irq is checked.
+
+Fixes: 360aebd85a4c ("drivers/pci/hotplug: Support surprise hotplug in powernv driver")
+Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
+Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/hotplug/pnv_php.c |   22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+--- a/drivers/pci/hotplug/pnv_php.c
++++ b/drivers/pci/hotplug/pnv_php.c
+@@ -35,9 +35,11 @@ static void pnv_php_register(struct devi
+ static void pnv_php_unregister_one(struct device_node *dn);
+ static void pnv_php_unregister(struct device_node *dn);
+-static void pnv_php_disable_irq(struct pnv_php_slot *php_slot)
++static void pnv_php_disable_irq(struct pnv_php_slot *php_slot,
++                              bool disable_device)
+ {
+       struct pci_dev *pdev = php_slot->pdev;
++      int irq = php_slot->irq;
+       u16 ctrl;
+       if (php_slot->irq > 0) {
+@@ -56,10 +58,14 @@ static void pnv_php_disable_irq(struct p
+               php_slot->wq = NULL;
+       }
+-      if (pdev->msix_enabled)
+-              pci_disable_msix(pdev);
+-      else if (pdev->msi_enabled)
+-              pci_disable_msi(pdev);
++      if (disable_device || irq > 0) {
++              if (pdev->msix_enabled)
++                      pci_disable_msix(pdev);
++              else if (pdev->msi_enabled)
++                      pci_disable_msi(pdev);
++
++              pci_disable_device(pdev);
++      }
+ }
+ static void pnv_php_free_slot(struct kref *kref)
+@@ -68,7 +74,7 @@ static void pnv_php_free_slot(struct kre
+                                       struct pnv_php_slot, kref);
+       WARN_ON(!list_empty(&php_slot->children));
+-      pnv_php_disable_irq(php_slot);
++      pnv_php_disable_irq(php_slot, false);
+       kfree(php_slot->name);
+       kfree(php_slot);
+ }
+@@ -759,7 +765,7 @@ static void pnv_php_init_irq(struct pnv_
+       php_slot->wq = alloc_workqueue("pciehp-%s", 0, 0, php_slot->name);
+       if (!php_slot->wq) {
+               dev_warn(&pdev->dev, "Cannot alloc workqueue\n");
+-              pnv_php_disable_irq(php_slot);
++              pnv_php_disable_irq(php_slot, true);
+               return;
+       }
+@@ -772,7 +778,7 @@ static void pnv_php_init_irq(struct pnv_
+       ret = request_irq(irq, pnv_php_interrupt, IRQF_SHARED,
+                         php_slot->name, php_slot);
+       if (ret) {
+-              pnv_php_disable_irq(php_slot);
++              pnv_php_disable_irq(php_slot, true);
+               dev_warn(&pdev->dev, "Error %d enabling IRQ %d\n", ret, irq);
+               return;
+       }
diff --git a/queue-4.9/pci-hv-fix-wslot_to_devfn-to-fix-warnings-on-device-removal.patch b/queue-4.9/pci-hv-fix-wslot_to_devfn-to-fix-warnings-on-device-removal.patch
new file mode 100644 (file)
index 0000000..6be4b4b
--- /dev/null
@@ -0,0 +1,63 @@
+From 60e2e2fbafdd1285ae1b4ad39ded41603e0c74d0 Mon Sep 17 00:00:00 2001
+From: Dexuan Cui <decui@microsoft.com>
+Date: Fri, 10 Feb 2017 15:18:46 -0600
+Subject: PCI: hv: Fix wslot_to_devfn() to fix warnings on device removal
+
+From: Dexuan Cui <decui@microsoft.com>
+
+commit 60e2e2fbafdd1285ae1b4ad39ded41603e0c74d0 upstream.
+
+The devfn of 00:02.0 is 0x10.  devfn_to_wslot(0x10) == 0x2, and
+wslot_to_devfn(0x2) should be 0x10, while it's 0x2 in the current code.
+
+Due to this, hv_eject_device_work() -> pci_get_domain_bus_and_slot()
+returns NULL and pci_stop_and_remove_bus_device() is not called.
+
+Later when the real device driver's .remove() is invoked by
+hv_pci_remove() -> pci_stop_root_bus(), some warnings can be noticed
+because the VM has lost the access to the underlying device at that
+time.
+
+Signed-off-by: Jake Oshins <jakeo@microsoft.com>
+Signed-off-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+CC: K. Y. Srinivasan <kys@microsoft.com>
+CC: Stephen Hemminger <sthemmin@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/host/pci-hyperv.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/pci/host/pci-hyperv.c
++++ b/drivers/pci/host/pci-hyperv.c
+@@ -130,7 +130,8 @@ union pci_version {
+  */
+ union win_slot_encoding {
+       struct {
+-              u32     func:8;
++              u32     dev:5;
++              u32     func:3;
+               u32     reserved:24;
+       } bits;
+       u32 slot;
+@@ -483,7 +484,8 @@ static u32 devfn_to_wslot(int devfn)
+       union win_slot_encoding wslot;
+       wslot.slot = 0;
+-      wslot.bits.func = PCI_SLOT(devfn) | (PCI_FUNC(devfn) << 5);
++      wslot.bits.dev = PCI_SLOT(devfn);
++      wslot.bits.func = PCI_FUNC(devfn);
+       return wslot.slot;
+ }
+@@ -501,7 +503,7 @@ static int wslot_to_devfn(u32 wslot)
+       union win_slot_encoding slot_no;
+       slot_no.slot = wslot;
+-      return PCI_DEVFN(0, slot_no.bits.func);
++      return PCI_DEVFN(slot_no.bits.dev, slot_no.bits.func);
+ }
+ /*
index bb86a407c460456f5195d8ba41a9618fb88f0c55..9b626747dadf373aff4e853d0b6ef1c28eed75c5 100644 (file)
@@ -75,3 +75,11 @@ ext4-preserve-the-needs_recovery-flag-when-the-journal-is-aborted.patch
 ext4-return-erofs-if-device-is-r-o-and-journal-replay-is-needed.patch
 samples-seccomp-fix-64-bit-comparison-macros.patch
 mei-remove-support-for-broken-parallel-read.patch
+ath10k-fix-boot-failure-in-utf-mode-testmode.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
+pci-hv-fix-wslot_to_devfn-to-fix-warnings-on-device-removal.patch
+pci-hotplug-pnv-php-disable-msi-and-pci-device-properly.patch
+pci-altera-fix-tlp_cfg_dw0-for-tlp-write.patch
+drivers-hv-vmbus-raise-retry-wait-limits-in-vmbus_post_msg.patch