--- /dev/null
+From a477b9cd37aa81a490dfa3265b7ff4f2c5a92463 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier@arm.com>
+Date: Tue, 1 Aug 2017 20:11:02 -0500
+Subject: PCI: Add pci_reset_function_locked()
+
+From: Marc Zyngier <marc.zyngier@arm.com>
+
+commit a477b9cd37aa81a490dfa3265b7ff4f2c5a92463 upstream.
+
+The implementation of PCI workarounds may require that the device is reset
+from its probe function. This implies that the PCI device lock is already
+held, and makes calling pci_reset_function() impossible (since it will
+itself try to take that lock).
+
+Add pci_reset_function_locked(), which is the equivalent of
+pci_reset_function(), except that it requires the PCI device lock to be
+already held by the caller.
+
+Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
+[bhelgaas: folded in fix for conflict with 52354b9d1f46 ("PCI: Remove
+__pci_dev_reset() and pci_dev_reset()")]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pci.c | 35 +++++++++++++++++++++++++++++++++++
+ include/linux/pci.h | 1 +
+ 2 files changed, 36 insertions(+)
+
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -4291,6 +4291,41 @@ int pci_reset_function(struct pci_dev *d
+ EXPORT_SYMBOL_GPL(pci_reset_function);
+
+ /**
++ * pci_reset_function_locked - quiesce and reset a PCI device function
++ * @dev: PCI device to reset
++ *
++ * Some devices allow an individual function to be reset without affecting
++ * other functions in the same device. The PCI device must be responsive
++ * to PCI config space in order to use this function.
++ *
++ * This function does not just reset the PCI portion of a device, but
++ * clears all the state associated with the device. This function differs
++ * from __pci_reset_function() in that it saves and restores device state
++ * over the reset. It also differs from pci_reset_function() in that it
++ * requires the PCI device lock to be held.
++ *
++ * Returns 0 if the device function was successfully reset or negative if the
++ * device doesn't support resetting a single function.
++ */
++int pci_reset_function_locked(struct pci_dev *dev)
++{
++ int rc;
++
++ rc = pci_probe_reset_function(dev);
++ if (rc)
++ return rc;
++
++ pci_dev_save_and_disable(dev);
++
++ rc = __pci_reset_function_locked(dev);
++
++ pci_dev_restore(dev);
++
++ return rc;
++}
++EXPORT_SYMBOL_GPL(pci_reset_function_locked);
++
++/**
+ * pci_try_reset_function - quiesce and reset a PCI device function
+ * @dev: PCI device to reset
+ *
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1049,6 +1049,7 @@ void pcie_flr(struct pci_dev *dev);
+ int __pci_reset_function(struct pci_dev *dev);
+ int __pci_reset_function_locked(struct pci_dev *dev);
+ int pci_reset_function(struct pci_dev *dev);
++int pci_reset_function_locked(struct pci_dev *dev);
+ int pci_try_reset_function(struct pci_dev *dev);
+ int pci_probe_reset_slot(struct pci_slot *slot);
+ int pci_reset_slot(struct pci_slot *slot);
--- /dev/null
+From b014e96d1abbd67404bbe2018937b46466299e9e Mon Sep 17 00:00:00 2001
+From: Christoph Hellwig <hch@lst.de>
+Date: Thu, 1 Jun 2017 13:10:37 +0200
+Subject: PCI: Protect pci_error_handlers->reset_notify() usage with device_lock()
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit b014e96d1abbd67404bbe2018937b46466299e9e upstream.
+
+Every method in struct device_driver or structures derived from it like
+struct pci_driver MUST provide exclusion vs the driver's ->remove() method,
+usually by using device_lock().
+
+Protect use of pci_error_handlers->reset_notify() by holding the device
+lock while calling it.
+
+Note:
+
+ - pci_dev_lock() calls device_lock() in addition to blocking user-space
+ config accesses.
+
+ - pci_err_handlers->reset_notify() is used inside
+ pci_dev_save_and_disable() and pci_dev_restore(). We could hold the
+ device lock directly in pci_reset_notify(), but we expand the region
+ since we have several calls following each other.
+
+Without this, ->reset_notify() may race with ->remove() calls, which can be
+easily triggered in NVMe.
+
+[bhelgaas: changelog, add pci_reset_notify() comment]
+[bhelgaas: fold in fix from Dan Carpenter <dan.carpenter@oracle.com>:
+http://lkml.kernel.org/r/20170701135323.x5vaj4e2wcs2mcro@mwanda]
+Link: http://lkml.kernel.org/r/20170601111039.8913-2-hch@lst.de
+Reported-by: Rakesh Pandit <rakesh@tuxera.com>
+Tested-by: Rakesh Pandit <rakesh@tuxera.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pci.c | 26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -4141,6 +4141,12 @@ static void pci_reset_notify(struct pci_
+ {
+ const struct pci_error_handlers *err_handler =
+ dev->driver ? dev->driver->err_handler : NULL;
++
++ /*
++ * dev->driver->err_handler->reset_notify() is protected against
++ * races with ->remove() by the device lock, which must be held by
++ * the caller.
++ */
+ if (err_handler && err_handler->reset_notify)
+ err_handler->reset_notify(dev, prepare);
+ }
+@@ -4276,11 +4282,13 @@ int pci_reset_function(struct pci_dev *d
+ if (rc)
+ return rc;
+
++ pci_dev_lock(dev);
+ pci_dev_save_and_disable(dev);
+
+- rc = pci_dev_reset(dev, 0);
++ rc = __pci_dev_reset(dev, 0);
+
+ pci_dev_restore(dev);
++ pci_dev_unlock(dev);
+
+ return rc;
+ }
+@@ -4300,16 +4308,14 @@ int pci_try_reset_function(struct pci_de
+ if (rc)
+ return rc;
+
+- pci_dev_save_and_disable(dev);
++ if (!pci_dev_trylock(dev))
++ return -EAGAIN;
+
+- if (pci_dev_trylock(dev)) {
+- rc = __pci_dev_reset(dev, 0);
+- pci_dev_unlock(dev);
+- } else
+- rc = -EAGAIN;
++ pci_dev_save_and_disable(dev);
++ rc = __pci_dev_reset(dev, 0);
++ pci_dev_unlock(dev);
+
+ pci_dev_restore(dev);
+-
+ return rc;
+ }
+ EXPORT_SYMBOL_GPL(pci_try_reset_function);
+@@ -4459,7 +4465,9 @@ static void pci_bus_save_and_disable(str
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
++ pci_dev_lock(dev);
+ pci_dev_save_and_disable(dev);
++ pci_dev_unlock(dev);
+ if (dev->subordinate)
+ pci_bus_save_and_disable(dev->subordinate);
+ }
+@@ -4474,7 +4482,9 @@ static void pci_bus_restore(struct pci_b
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
++ pci_dev_lock(dev);
+ pci_dev_restore(dev);
++ pci_dev_unlock(dev);
+ if (dev->subordinate)
+ pci_bus_restore(dev->subordinate);
+ }
--- /dev/null
+From 52354b9d1f46aae7386db7bb8ec8484b5488087f Mon Sep 17 00:00:00 2001
+From: Christoph Hellwig <hch@lst.de>
+Date: Thu, 1 Jun 2017 13:10:39 +0200
+Subject: PCI: Remove __pci_dev_reset() and pci_dev_reset()
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 52354b9d1f46aae7386db7bb8ec8484b5488087f upstream.
+
+Implement the reset probing / reset chain directly in
+__pci_probe_reset_function() and __pci_reset_function_locked()
+respectively.
+
+Link: http://lkml.kernel.org/r/20170601111039.8913-4-hch@lst.de
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pci.c | 108 ++++++++++++++++++++++++++----------------------------
+ 1 file changed, 52 insertions(+), 56 deletions(-)
+
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -4069,40 +4069,6 @@ static int pci_dev_reset_slot_function(s
+ return pci_reset_hotplug_slot(dev->slot->hotplug, probe);
+ }
+
+-static int __pci_dev_reset(struct pci_dev *dev, int probe)
+-{
+- int rc;
+-
+- might_sleep();
+-
+- rc = pci_dev_specific_reset(dev, probe);
+- if (rc != -ENOTTY)
+- goto done;
+-
+- if (pcie_has_flr(dev)) {
+- if (!probe)
+- pcie_flr(dev);
+- rc = 0;
+- goto done;
+- }
+-
+- rc = pci_af_flr(dev, probe);
+- if (rc != -ENOTTY)
+- goto done;
+-
+- rc = pci_pm_reset(dev, probe);
+- if (rc != -ENOTTY)
+- goto done;
+-
+- rc = pci_dev_reset_slot_function(dev, probe);
+- if (rc != -ENOTTY)
+- goto done;
+-
+- rc = pci_parent_bus_reset(dev, probe);
+-done:
+- return rc;
+-}
+-
+ static void pci_dev_lock(struct pci_dev *dev)
+ {
+ pci_cfg_access_lock(dev);
+@@ -4179,21 +4145,6 @@ static void pci_dev_restore(struct pci_d
+ pci_reset_notify(dev, false);
+ }
+
+-static int pci_dev_reset(struct pci_dev *dev, int probe)
+-{
+- int rc;
+-
+- if (!probe)
+- pci_dev_lock(dev);
+-
+- rc = __pci_dev_reset(dev, probe);
+-
+- if (!probe)
+- pci_dev_unlock(dev);
+-
+- return rc;
+-}
+-
+ /**
+ * __pci_reset_function - reset a PCI device function
+ * @dev: PCI device to reset
+@@ -4213,7 +4164,13 @@ static int pci_dev_reset(struct pci_dev
+ */
+ int __pci_reset_function(struct pci_dev *dev)
+ {
+- return pci_dev_reset(dev, 0);
++ int ret;
++
++ pci_dev_lock(dev);
++ ret = __pci_reset_function_locked(dev);
++ pci_dev_unlock(dev);
++
++ return ret;
+ }
+ EXPORT_SYMBOL_GPL(__pci_reset_function);
+
+@@ -4238,7 +4195,27 @@ EXPORT_SYMBOL_GPL(__pci_reset_function);
+ */
+ int __pci_reset_function_locked(struct pci_dev *dev)
+ {
+- return __pci_dev_reset(dev, 0);
++ int rc;
++
++ might_sleep();
++
++ rc = pci_dev_specific_reset(dev, 0);
++ if (rc != -ENOTTY)
++ return rc;
++ if (pcie_has_flr(dev)) {
++ pcie_flr(dev);
++ return 0;
++ }
++ rc = pci_af_flr(dev, 0);
++ if (rc != -ENOTTY)
++ return rc;
++ rc = pci_pm_reset(dev, 0);
++ if (rc != -ENOTTY)
++ return rc;
++ rc = pci_dev_reset_slot_function(dev, 0);
++ if (rc != -ENOTTY)
++ return rc;
++ return pci_parent_bus_reset(dev, 0);
+ }
+ EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
+
+@@ -4255,7 +4232,26 @@ EXPORT_SYMBOL_GPL(__pci_reset_function_l
+ */
+ int pci_probe_reset_function(struct pci_dev *dev)
+ {
+- return pci_dev_reset(dev, 1);
++ int rc;
++
++ might_sleep();
++
++ rc = pci_dev_specific_reset(dev, 1);
++ if (rc != -ENOTTY)
++ return rc;
++ if (pcie_has_flr(dev))
++ return 0;
++ rc = pci_af_flr(dev, 1);
++ if (rc != -ENOTTY)
++ return rc;
++ rc = pci_pm_reset(dev, 1);
++ if (rc != -ENOTTY)
++ return rc;
++ rc = pci_dev_reset_slot_function(dev, 1);
++ if (rc != -ENOTTY)
++ return rc;
++
++ return pci_parent_bus_reset(dev, 1);
+ }
+
+ /**
+@@ -4278,14 +4274,14 @@ int pci_reset_function(struct pci_dev *d
+ {
+ int rc;
+
+- rc = pci_dev_reset(dev, 1);
++ rc = pci_probe_reset_function(dev);
+ if (rc)
+ return rc;
+
+ pci_dev_lock(dev);
+ pci_dev_save_and_disable(dev);
+
+- rc = __pci_dev_reset(dev, 0);
++ rc = __pci_reset_function_locked(dev);
+
+ pci_dev_restore(dev);
+ pci_dev_unlock(dev);
+@@ -4304,7 +4300,7 @@ int pci_try_reset_function(struct pci_de
+ {
+ int rc;
+
+- rc = pci_dev_reset(dev, 1);
++ rc = pci_probe_reset_function(dev);
+ if (rc)
+ return rc;
+
+@@ -4312,7 +4308,7 @@ int pci_try_reset_function(struct pci_de
+ return -EAGAIN;
+
+ pci_dev_save_and_disable(dev);
+- rc = __pci_dev_reset(dev, 0);
++ rc = __pci_reset_function_locked(dev);
+ pci_dev_unlock(dev);
+
+ pci_dev_restore(dev);
usb-core-unlink-urbs-from-the-tail-of-the-endpoint-s-urb_list.patch
usb-quirks-add-no-lpm-quirk-for-moshi-usb-to-ethernet-adapter.patch
usb-xhci-add-quirk-for-certain-failing-hp-keyboard-on-reset-after-resume.patch
+pci-protect-pci_error_handlers-reset_notify-usage-with-device_lock.patch
+pci-remove-__pci_dev_reset-and-pci_dev_reset.patch
+pci-add-pci_reset_function_locked.patch
+xhci-reset-renesas-upd72020x-usb-controller-for-32-bit-dma-issue.patch
--- /dev/null
+From 8466489ef5ba48272ba4fa4ea9f8f403306de4c7 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier@arm.com>
+Date: Tue, 1 Aug 2017 20:11:08 -0500
+Subject: xhci: Reset Renesas uPD72020x USB controller for 32-bit DMA issue
+
+From: Marc Zyngier <marc.zyngier@arm.com>
+
+commit 8466489ef5ba48272ba4fa4ea9f8f403306de4c7 upstream.
+
+The Renesas uPD72020x XHCI controller seems to suffer from a really
+annoying bug, where it may retain some of its DMA programming across a XHCI
+reset, and despite the driver correctly programming new DMA addresses.
+This is visible if the device has been using 64-bit DMA addresses, and is
+then switched to using 32-bit DMA addresses. The top 32 bits of the
+address (now zero) are ignored are replaced by the 32 bits from the
+*previous* programming. Sticking with 64-bit DMA always works, but doesn't
+seem very appropriate.
+
+A PCI reset of the device restores the normal functionality, which is done
+at probe time. Unfortunately, this has to be done before any quirk has
+been discovered, hence the intrusive nature of the fix.
+
+Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/pci-quirks.c | 20 ++++++++++++++++++++
+ drivers/usb/host/pci-quirks.h | 1 +
+ drivers/usb/host/xhci-pci.c | 7 +++++++
+ 3 files changed, 28 insertions(+)
+
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -1157,3 +1157,23 @@ static void quirk_usb_early_handoff(stru
+ }
+ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff);
++
++bool usb_xhci_needs_pci_reset(struct pci_dev *pdev)
++{
++ /*
++ * Our dear uPD72020{1,2} friend only partially resets when
++ * asked to via the XHCI interface, and may end up doing DMA
++ * at the wrong addresses, as it keeps the top 32bit of some
++ * addresses from its previous programming under obscure
++ * circumstances.
++ * Give it a good wack at probe time. Unfortunately, this
++ * needs to happen before we've had a chance to discover any
++ * quirk, or the system will be in a rather bad state.
++ */
++ if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
++ (pdev->device == 0x0014 || pdev->device == 0x0015))
++ return true;
++
++ return false;
++}
++EXPORT_SYMBOL_GPL(usb_xhci_needs_pci_reset);
+--- a/drivers/usb/host/pci-quirks.h
++++ b/drivers/usb/host/pci-quirks.h
+@@ -15,6 +15,7 @@ void usb_asmedia_modifyflowcontrol(struc
+ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
+ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
+ void sb800_prefetch(struct device *dev, int on);
++bool usb_xhci_needs_pci_reset(struct pci_dev *pdev);
+ #else
+ struct pci_dev;
+ static inline void usb_amd_quirk_pll_disable(void) {}
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -285,6 +285,13 @@ static int xhci_pci_probe(struct pci_dev
+
+ driver = (struct hc_driver *)id->driver_data;
+
++ /* For some HW implementation, a XHCI reset is just not enough... */
++ if (usb_xhci_needs_pci_reset(dev)) {
++ dev_info(&dev->dev, "Resetting\n");
++ if (pci_reset_function_locked(dev))
++ dev_warn(&dev->dev, "Reset failed");
++ }
++
+ /* Prevent runtime suspending between USB-2 and USB-3 initialization */
+ pm_runtime_get_noresume(&dev->dev);
+