pci-v4.13-changes

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJZYAFUAAoJEFmIoMA60/r8cFQP/A4fpdjhd42WRNQXGTpZieop
 i40lBQtGdBn/UY97U6BoutcS1ygDi9OiSzg+IR6I90iMgidqyUHFhe4hGWgVHD2g
 Tg0KLzd+lKKfQ6Gqt1P6t4dLGLvyEj5NUbCeFE4XYODAUkkiBaOndax6DK1GvU54
 Vjuj63rHtMKFR/tG/4iFTigObqyI8QE6O9JVxwuvIyEX6RXKbJe+wkulv5taSnWt
 Ne94950i10MrELtNreVdi8UbCbXiqjg0r5sKI/WTJ7Bc7WsC7X5PhWlhcNrbHyBT
 Ivhoypkui3Ky8gvwWqL0KBG+cRp8prBXAdabrD9wRbz0TKnfGI6pQzseCGRnkE6T
 mhlSJpsSNIHaejoCjk93yPn5oRiTNtPMdVhMpEQL9V/crVRGRRmbd7v2TYvpMHVR
 JaPZ8bv+C2aBTY8uL3/v/rgrjsMKOYFeaxeNklpErxrknsbgb6BgubmeZXDvTBVv
 YUIbAkvveonUKisv+kbD8L7tp1+jdbRUT0AikS0NVgAJQhfArOmBcDpTL9YC51vE
 feFhkVx4A32vvOm7Zcg9A7IMXNjeSfccKGw3dJOAvzgDODuJiaCG6S0o7B5Yngze
 axMi87ixGT4QM98z/I4MC8E9rDrJdIitlpvb6ZBgiLzoO3kmvsIZZKt8UxWqf5r8
 w3U2HoyKH13Qbkn1xkum
 =mkyb
 -----END PGP SIGNATURE-----

Merge tag 'pci-v4.13-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci

Pull PCI updates from Bjorn Helgaas:

  - add sysfs max_link_speed/width, current_link_speed/width (Wong Vee
    Khee)

  - make host bridge IRQ mapping much more generic (Matthew Minter,
    Lorenzo Pieralisi)

  - convert most drivers to pci_scan_root_bus_bridge() (Lorenzo
    Pieralisi)

  - mutex sriov_configure() (Jakub Kicinski)

  - mutex pci_error_handlers callbacks (Christoph Hellwig)

  - split ->reset_notify() into ->reset_prepare()/reset_done()
    (Christoph Hellwig)

  - support multiple PCIe portdrv interrupts for MSI as well as MSI-X
    (Gabriele Paoloni)

  - allocate MSI/MSI-X vector for Downstream Port Containment (Gabriele
    Paoloni)

  - fix MSI IRQ affinity pre/post/min_vecs issue (Michael Hernandez)

  - test INTx masking during enumeration, not at run-time (Piotr Gregor)

  - avoid using device_may_wakeup() for runtime PM (Rafael J. Wysocki)

  - restore the status of PCI devices across hibernation (Chen Yu)

  - keep parent resources that start at 0x0 (Ard Biesheuvel)

  - enable ECRC only if device supports it (Bjorn Helgaas)

  - restore PRI and PASID state after Function-Level Reset (CQ Tang)

  - skip DPC event if device is not present (Keith Busch)

  - check domain when matching SMBIOS info (Sujith Pandel)

  - mark Intel XXV710 NIC INTx masking as broken (Alex Williamson)

  - avoid AMD SB7xx EHCI USB wakeup defect (Kai-Heng Feng)

  - work around long-standing Macbook Pro poweroff issue (Bjorn Helgaas)

  - add Switchtec "running" status flag (Logan Gunthorpe)

  - fix dra7xx incorrect RW1C IRQ register usage (Arvind Yadav)

  - modify xilinx-nwl IRQ chip for legacy interrupts (Bharat Kumar
    Gogada)

  - move VMD SRCU cleanup after bus, child device removal (Jon Derrick)

  - add Faraday clock handling (Linus Walleij)

  - configure Rockchip MPS and reorganize (Shawn Lin)

  - limit Qualcomm TLP size to 2K (hardware issue) (Srinivas Kandagatla)

  - support Tegra MSI 64-bit addressing (Thierry Reding)

  - use Rockchip normal (not privileged) register bank (Shawn Lin)

  - add HiSilicon Kirin SoC PCIe controller driver (Xiaowei Song)

  - add Sigma Designs Tango SMP8759 PCIe controller driver (Marc
    Gonzalez)

  - add MediaTek PCIe host controller support (Ryder Lee)

  - add Qualcomm IPQ4019 support (John Crispin)

  - add HyperV vPCI protocol v1.2 support (Jork Loeser)

  - add i.MX6 regulator support (Quentin Schulz)

* tag 'pci-v4.13-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (113 commits)
  PCI: tango: Add Sigma Designs Tango SMP8759 PCIe host bridge support
  PCI: Add DT binding for Sigma Designs Tango PCIe controller
  PCI: rockchip: Use normal register bank for config accessors
  dt-bindings: PCI: Add documentation for MediaTek PCIe
  PCI: Remove __pci_dev_reset() and pci_dev_reset()
  PCI: Split ->reset_notify() method into ->reset_prepare() and ->reset_done()
  PCI: xilinx: Make of_device_ids const
  PCI: xilinx-nwl: Modify IRQ chip for legacy interrupts
  PCI: vmd: Move SRCU cleanup after bus, child device removal
  PCI: vmd: Correct comment: VMD domains start at 0x10000, not 0x1000
  PCI: versatile: Add local struct device pointers
  PCI: tegra: Do not allocate MSI target memory
  PCI: tegra: Support MSI 64-bit addressing
  PCI: rockchip: Use local struct device pointer consistently
  PCI: rockchip: Check for clk_prepare_enable() errors during resume
  MAINTAINERS: Remove Wenrui Li as Rockchip PCIe driver maintainer
  PCI: rockchip: Configure RC's MPS setting
  PCI: rockchip: Reconfigure configuration space header type
  PCI: rockchip: Split out rockchip_pcie_cfg_configuration_accesses()
  PCI: rockchip: Move configuration accesses into rockchip_pcie_cfg_atu()
  ...
This commit is contained in:
Linus Torvalds 2017-07-08 15:51:57 -07:00
commit f263fbb8d6
90 changed files with 3789 additions and 825 deletions

View file

@ -28,6 +28,7 @@
#include <linux/pm_runtime.h>
#include <linux/pci_hotplug.h>
#include <linux/vmalloc.h>
#include <linux/pci-ats.h>
#include <asm/setup.h>
#include <asm/dma.h>
#include <linux/aer.h>
@ -455,7 +456,7 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev,
pci_bus_for_each_resource(bus, r, i) {
if (!r)
continue;
if (res->start && resource_contains(r, res)) {
if (resource_contains(r, res)) {
/*
* If the window is prefetchable but the BAR is
@ -1166,6 +1167,8 @@ void pci_restore_state(struct pci_dev *dev)
/* PCI Express register must be restored first */
pci_restore_pcie_state(dev);
pci_restore_pasid_state(dev);
pci_restore_pri_state(dev);
pci_restore_ats_state(dev);
pci_restore_vc_state(dev);
@ -1966,12 +1969,13 @@ EXPORT_SYMBOL(pci_wake_from_d3);
/**
* pci_target_state - find an appropriate low power state for a given PCI dev
* @dev: PCI device
* @wakeup: Whether or not wakeup functionality will be enabled for the device.
*
* Use underlying platform code to find a supported low power state for @dev.
* If the platform can't manage @dev, return the deepest state from which it
* can generate wake events, based on any available PME info.
*/
static pci_power_t pci_target_state(struct pci_dev *dev)
static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
{
pci_power_t target_state = PCI_D3hot;
@ -2008,7 +2012,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev)
if (dev->current_state == PCI_D3cold)
target_state = PCI_D3cold;
if (device_may_wakeup(&dev->dev)) {
if (wakeup) {
/*
* Find the deepest state from which the device can generate
* wake-up events, make it the target state and enable device
@ -2034,13 +2038,14 @@ static pci_power_t pci_target_state(struct pci_dev *dev)
*/
int pci_prepare_to_sleep(struct pci_dev *dev)
{
pci_power_t target_state = pci_target_state(dev);
bool wakeup = device_may_wakeup(&dev->dev);
pci_power_t target_state = pci_target_state(dev, wakeup);
int error;
if (target_state == PCI_POWER_ERROR)
return -EIO;
pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));
pci_enable_wake(dev, target_state, wakeup);
error = pci_set_power_state(dev, target_state);
@ -2073,9 +2078,10 @@ EXPORT_SYMBOL(pci_back_from_sleep);
*/
int pci_finish_runtime_suspend(struct pci_dev *dev)
{
pci_power_t target_state = pci_target_state(dev);
pci_power_t target_state;
int error;
target_state = pci_target_state(dev, device_can_wakeup(&dev->dev));
if (target_state == PCI_POWER_ERROR)
return -EIO;
@ -2111,8 +2117,8 @@ bool pci_dev_run_wake(struct pci_dev *dev)
if (!dev->pme_support)
return false;
/* PME-capable in principle, but not from the intended sleep state */
if (!pci_pme_capable(dev, pci_target_state(dev)))
/* PME-capable in principle, but not from the target power state */
if (!pci_pme_capable(dev, pci_target_state(dev, false)))
return false;
while (bus->parent) {
@ -2147,9 +2153,10 @@ EXPORT_SYMBOL_GPL(pci_dev_run_wake);
bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
{
struct device *dev = &pci_dev->dev;
bool wakeup = device_may_wakeup(dev);
if (!pm_runtime_suspended(dev)
|| pci_target_state(pci_dev) != pci_dev->current_state
|| pci_target_state(pci_dev, wakeup) != pci_dev->current_state
|| platform_pci_need_resume(pci_dev)
|| (pci_dev->dev_flags & PCI_DEV_FLAGS_NEEDS_RESUME))
return false;
@ -2167,7 +2174,7 @@ bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
spin_lock_irq(&dev->power.lock);
if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold &&
!device_may_wakeup(dev))
!wakeup)
__pci_pme_active(pci_dev, false);
spin_unlock_irq(&dev->power.lock);
@ -3715,46 +3722,6 @@ void pci_intx(struct pci_dev *pdev, int enable)
}
EXPORT_SYMBOL_GPL(pci_intx);
/**
* pci_intx_mask_supported - probe for INTx masking support
* @dev: the PCI device to operate on
*
* Check if the device dev support INTx masking via the config space
* command word.
*/
bool pci_intx_mask_supported(struct pci_dev *dev)
{
bool mask_supported = false;
u16 orig, new;
if (dev->broken_intx_masking)
return false;
pci_cfg_access_lock(dev);
pci_read_config_word(dev, PCI_COMMAND, &orig);
pci_write_config_word(dev, PCI_COMMAND,
orig ^ PCI_COMMAND_INTX_DISABLE);
pci_read_config_word(dev, PCI_COMMAND, &new);
/*
* There's no way to protect against hardware bugs or detect them
* reliably, but as long as we know what the value should be, let's
* go ahead and check it.
*/
if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
dev_err(&dev->dev, "Command register changed from 0x%x to 0x%x: driver or hardware bug?\n",
orig, new);
} else if ((new ^ orig) & PCI_COMMAND_INTX_DISABLE) {
mask_supported = true;
pci_write_config_word(dev, PCI_COMMAND, orig);
}
pci_cfg_access_unlock(dev);
return mask_supported;
}
EXPORT_SYMBOL_GPL(pci_intx_mask_supported);
static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
{
struct pci_bus *bus = dev->bus;
@ -3805,7 +3772,7 @@ done:
* @dev: the PCI device to operate on
*
* Check if the device dev has its INTx line asserted, mask it and
* return true in that case. False is returned if not interrupt was
* return true in that case. False is returned if no interrupt was
* pending.
*/
bool pci_check_and_mask_intx(struct pci_dev *dev)
@ -4075,40 +4042,6 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe)
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);
@ -4134,26 +4067,18 @@ static void pci_dev_unlock(struct pci_dev *dev)
pci_cfg_access_unlock(dev);
}
/**
* pci_reset_notify - notify device driver of reset
* @dev: device to be notified of reset
* @prepare: 'true' if device is about to be reset; 'false' if reset attempt
* completed
*
* Must be called prior to device access being disabled and after device
* access is restored.
*/
static void pci_reset_notify(struct pci_dev *dev, bool prepare)
static void pci_dev_save_and_disable(struct pci_dev *dev)
{
const struct pci_error_handlers *err_handler =
dev->driver ? dev->driver->err_handler : NULL;
if (err_handler && err_handler->reset_notify)
err_handler->reset_notify(dev, prepare);
}
static void pci_dev_save_and_disable(struct pci_dev *dev)
{
pci_reset_notify(dev, true);
/*
* dev->driver->err_handler->reset_prepare() is protected against
* races with ->remove() by the device lock, which must be held by
* the caller.
*/
if (err_handler && err_handler->reset_prepare)
err_handler->reset_prepare(dev);
/*
* Wake-up device prior to save. PM registers default to D0 after
@ -4175,23 +4100,18 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)
static void pci_dev_restore(struct pci_dev *dev)
{
const struct pci_error_handlers *err_handler =
dev->driver ? dev->driver->err_handler : NULL;
pci_restore_state(dev);
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;
/*
* dev->driver->err_handler->reset_done() is protected against
* races with ->remove() by the device lock, which must be held by
* the caller.
*/
if (err_handler && err_handler->reset_done)
err_handler->reset_done(dev);
}
/**
@ -4213,7 +4133,13 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
*/
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 +4164,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 +4201,26 @@ EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
*/
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,15 +4243,17 @@ int pci_reset_function(struct pci_dev *dev)
{
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);
return rc;
}
@ -4302,20 +4269,18 @@ int pci_try_reset_function(struct pci_dev *dev)
{
int rc;
rc = pci_dev_reset(dev, 1);
rc = pci_probe_reset_function(dev);
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_reset_function_locked(dev);
pci_dev_unlock(dev);
pci_dev_restore(dev);
return rc;
}
EXPORT_SYMBOL_GPL(pci_try_reset_function);
@ -4465,7 +4430,9 @@ static void pci_bus_save_and_disable(struct pci_bus *bus)
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);
}
@ -4480,7 +4447,9 @@ static void pci_bus_restore(struct pci_bus *bus)
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);
}