From 15a474ce374e1ccb9db8cea7e907db6c97a059dd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 9 Mar 2017 07:57:19 +0100 Subject: [PATCH] 4.9-stable patches 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 --- ...ix-boot-failure-in-utf-mode-testmode.patch | 63 ++++++ ...-drv_set_key-with-unsupported-cipher.patch | 31 +++ ...condition-in-enabling-disabling-irqs.patch | 210 ++++++++++++++++++ ...er-offsets-for-the-ar9340-and-ar9550.patch | 53 +++++ ...-retry-wait-limits-in-vmbus_post_msg.patch | 187 ++++++++++++++++ ...altera-fix-tlp_cfg_dw0-for-tlp-write.patch | 59 +++++ ...-disable-msi-and-pci-device-properly.patch | 90 ++++++++ ...fn-to-fix-warnings-on-device-removal.patch | 63 ++++++ queue-4.9/series | 8 + 9 files changed, 764 insertions(+) create mode 100644 queue-4.9/ath10k-fix-boot-failure-in-utf-mode-testmode.patch create mode 100644 queue-4.9/ath5k-drop-bogus-warning-on-drv_set_key-with-unsupported-cipher.patch create mode 100644 queue-4.9/ath9k-fix-race-condition-in-enabling-disabling-irqs.patch create mode 100644 queue-4.9/ath9k-use-correct-otp-register-offsets-for-the-ar9340-and-ar9550.patch create mode 100644 queue-4.9/drivers-hv-vmbus-raise-retry-wait-limits-in-vmbus_post_msg.patch create mode 100644 queue-4.9/pci-altera-fix-tlp_cfg_dw0-for-tlp-write.patch create mode 100644 queue-4.9/pci-hotplug-pnv-php-disable-msi-and-pci-device-properly.patch create mode 100644 queue-4.9/pci-hv-fix-wslot_to_devfn-to-fix-warnings-on-device-removal.patch 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 index 00000000000..309a7616012 --- /dev/null +++ b/queue-4.9/ath10k-fix-boot-failure-in-utf-mode-testmode.patch @@ -0,0 +1,63 @@ +From cb4281528b62207918b1e95827cad7527aa4dbaa Mon Sep 17 00:00:00 2001 +From: Tamizh chelvam +Date: Thu, 2 Feb 2017 08:32:18 +0200 +Subject: ath10k: fix boot failure in UTF mode/testmode + +From: Tamizh chelvam + +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 +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..bb3d8e46968 --- /dev/null +++ b/queue-4.9/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.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 index 00000000000..e360fa9fce7 --- /dev/null +++ b/queue-4.9/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 +@@ -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 index 00000000000..a60ad928b69 --- /dev/null +++ b/queue-4.9/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.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 index 00000000000..81630c200a0 --- /dev/null +++ b/queue-4.9/drivers-hv-vmbus-raise-retry-wait-limits-in-vmbus_post_msg.patch @@ -0,0 +1,187 @@ +From c0bb03924f1a80e7f65900e36c8e6b3dc167c5f8 Mon Sep 17 00:00:00 2001 +From: Vitaly Kuznetsov +Date: Wed, 7 Dec 2016 01:16:24 -0800 +Subject: Drivers: hv: vmbus: Raise retry/wait limits in vmbus_post_msg() + +From: Vitaly Kuznetsov + +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 +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..7b671e3a03b --- /dev/null +++ b/queue-4.9/pci-altera-fix-tlp_cfg_dw0-for-tlp-write.patch @@ -0,0 +1,59 @@ +From 2a7275a3d867b228216886aae35e1f64291180b1 Mon Sep 17 00:00:00 2001 +From: Ley Foon Tan +Date: Tue, 28 Feb 2017 18:37:16 +0800 +Subject: PCI: altera: Fix TLP_CFG_DW0 for TLP write + +From: Ley Foon Tan + +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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..fa7f3a0bf94 --- /dev/null +++ b/queue-4.9/pci-hotplug-pnv-php-disable-msi-and-pci-device-properly.patch @@ -0,0 +1,90 @@ +From 49f4b08e61547a5ccd2db551d994c4503efe5666 Mon Sep 17 00:00:00 2001 +From: Gavin Shan +Date: Thu, 16 Feb 2017 10:22:34 +1100 +Subject: pci/hotplug/pnv-php: Disable MSI and PCI device properly + +From: Gavin Shan + +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 +Reviewed-by: Andrew Donnellan +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..6be4b4bd595 --- /dev/null +++ b/queue-4.9/pci-hv-fix-wslot_to_devfn-to-fix-warnings-on-device-removal.patch @@ -0,0 +1,63 @@ +From 60e2e2fbafdd1285ae1b4ad39ded41603e0c74d0 Mon Sep 17 00:00:00 2001 +From: Dexuan Cui +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 + +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 +Signed-off-by: Dexuan Cui +Signed-off-by: Bjorn Helgaas +Acked-by: Haiyang Zhang +CC: K. Y. Srinivasan +CC: Stephen Hemminger +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } + + /* diff --git a/queue-4.9/series b/queue-4.9/series index bb86a407c46..9b626747dad 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -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 -- 2.47.3