Merge branch 'pci/misc'
authorBjorn Helgaas <bhelgaas@google.com>
Thu, 2 Sep 2021 19:56:44 +0000 (14:56 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Thu, 2 Sep 2021 19:56:44 +0000 (14:56 -0500)
- Add pci_numachip_init() declaration (Krzysztof Wilczyński)

- Allocate pci_dev_str_match_path() string atomically (Dan Carpenter)

- Drop error message when Precision Time Measurement supported but not
  enabled (Jakub Kicinski)

- Correct the pci_iomap.h header guard #endif comment (Jonathan Cameron)

- Add schedule point in proc_bus_pci_read() (Krzysztof Wilczyński)

- Make saved capability state private to core (Bjorn Helgaas)

- Sync __pci_register_driver() stub for CONFIG_PCI=n (Andy Shevchenko)

- Convert sta2x11 from PCI-DMA-API to generic DMA-API (Christophe JAILLET)

* pci/misc:
  x86/PCI: sta2x11: switch from 'pci_' to 'dma_' API
  PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n
  PCI: Make saved capability state private to core
  PCI: Add schedule point in proc_bus_pci_read()
  PCI: Correct the pci_iomap.h header guard #endif comment
  PCI/PTM: Remove error message at boot
  PCI: Fix pci_dev_str_match_path() alloc while atomic bug
  x86/PCI: Add pci_numachip_init() declaration

# Conflicts:
# include/linux/pci.h

1  2 
drivers/pci/pci.c
drivers/pci/pci.h
include/linux/pci.h

diff --combined drivers/pci/pci.c
index c3f6ff3bd2af5bae1afd01019b1561b171cd970d,9a6513ffdef150d873d2495fe093a8cd1fc2ec19..292dadd49d7bde217b8a13da10129587c55d61a8
@@@ -31,7 -31,6 +31,7 @@@
  #include <linux/vmalloc.h>
  #include <asm/dma.h>
  #include <linux/aer.h>
 +#include <linux/bitfield.h>
  #include "pci.h"
  
  DEFINE_MUTEX(pci_slot_mutex);
@@@ -73,11 -72,6 +73,11 @@@ static void pci_dev_d3_sleep(struct pci
                msleep(delay);
  }
  
 +bool pci_reset_supported(struct pci_dev *dev)
 +{
 +      return dev->reset_methods[0] != 0;
 +}
 +
  #ifdef CONFIG_PCI_DOMAINS
  int pci_domains_supported = 1;
  #endif
@@@ -212,36 -206,32 +212,36 @@@ int pci_status_get_and_clear_errors(str
  EXPORT_SYMBOL_GPL(pci_status_get_and_clear_errors);
  
  #ifdef CONFIG_HAS_IOMEM
 -void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
 +static void __iomem *__pci_ioremap_resource(struct pci_dev *pdev, int bar,
 +                                          bool write_combine)
  {
        struct resource *res = &pdev->resource[bar];
 +      resource_size_t start = res->start;
 +      resource_size_t size = resource_size(res);
  
        /*
         * Make sure the BAR is actually a memory resource, not an IO resource
         */
        if (res->flags & IORESOURCE_UNSET || !(res->flags & IORESOURCE_MEM)) {
 -              pci_warn(pdev, "can't ioremap BAR %d: %pR\n", bar, res);
 +              pci_err(pdev, "can't ioremap BAR %d: %pR\n", bar, res);
                return NULL;
        }
 -      return ioremap(res->start, resource_size(res));
 +
 +      if (write_combine)
 +              return ioremap_wc(start, size);
 +
 +      return ioremap(start, size);
 +}
 +
 +void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
 +{
 +      return __pci_ioremap_resource(pdev, bar, false);
  }
  EXPORT_SYMBOL_GPL(pci_ioremap_bar);
  
  void __iomem *pci_ioremap_wc_bar(struct pci_dev *pdev, int bar)
  {
 -      /*
 -       * Make sure the BAR is actually a memory resource, not an IO resource
 -       */
 -      if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
 -              WARN_ON(1);
 -              return NULL;
 -      }
 -      return ioremap_wc(pci_resource_start(pdev, bar),
 -                        pci_resource_len(pdev, bar));
 +      return __pci_ioremap_resource(pdev, bar, true);
  }
  EXPORT_SYMBOL_GPL(pci_ioremap_wc_bar);
  #endif
@@@ -275,7 -265,7 +275,7 @@@ static int pci_dev_str_match_path(struc
  
        *endptr = strchrnul(path, ';');
  
-       wpath = kmemdup_nul(path, *endptr - path, GFP_KERNEL);
+       wpath = kmemdup_nul(path, *endptr - path, GFP_ATOMIC);
        if (!wpath)
                return -ENOMEM;
  
@@@ -925,8 -915,8 +925,8 @@@ static void pci_std_enable_acs(struct p
        /* Upstream Forwarding */
        ctrl |= (cap & PCI_ACS_UF);
  
 -      /* Enable Translation Blocking for external devices */
 -      if (dev->external_facing || dev->untrusted)
 +      /* Enable Translation Blocking for external devices and noats */
 +      if (pci_ats_disabled() || dev->external_facing || dev->untrusted)
                ctrl |= (cap & PCI_ACS_TB);
  
        pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
@@@ -4631,12 -4621,32 +4631,12 @@@ int pci_wait_for_pending_transaction(st
  }
  EXPORT_SYMBOL(pci_wait_for_pending_transaction);
  
 -/**
 - * pcie_has_flr - check if a device supports function level resets
 - * @dev: device to check
 - *
 - * Returns true if the device advertises support for PCIe function level
 - * resets.
 - */
 -bool pcie_has_flr(struct pci_dev *dev)
 -{
 -      u32 cap;
 -
 -      if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET)
 -              return false;
 -
 -      pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
 -      return cap & PCI_EXP_DEVCAP_FLR;
 -}
 -EXPORT_SYMBOL_GPL(pcie_has_flr);
 -
  /**
   * pcie_flr - initiate a PCIe function level reset
   * @dev: device to reset
   *
 - * Initiate a function level reset on @dev.  The caller should ensure the
 - * device supports FLR before calling this function, e.g. by using the
 - * pcie_has_flr() helper.
 + * Initiate a function level reset unconditionally on @dev without
 + * checking any flags and DEVCAP
   */
  int pcie_flr(struct pci_dev *dev)
  {
  }
  EXPORT_SYMBOL_GPL(pcie_flr);
  
 -static int pci_af_flr(struct pci_dev *dev, int probe)
 +/**
 + * pcie_reset_flr - initiate a PCIe function level reset
 + * @dev: device to reset
 + * @probe: if true, return 0 if device can be reset this way
 + *
 + * Initiate a function level reset on @dev.
 + */
 +int pcie_reset_flr(struct pci_dev *dev, bool probe)
 +{
 +      if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET)
 +              return -ENOTTY;
 +
 +      if (!(dev->devcap & PCI_EXP_DEVCAP_FLR))
 +              return -ENOTTY;
 +
 +      if (probe)
 +              return 0;
 +
 +      return pcie_flr(dev);
 +}
 +EXPORT_SYMBOL_GPL(pcie_reset_flr);
 +
 +static int pci_af_flr(struct pci_dev *dev, bool probe)
  {
        int pos;
        u8 cap;
  /**
   * pci_pm_reset - Put device into PCI_D3 and back into PCI_D0.
   * @dev: Device to reset.
 - * @probe: If set, only check if the device can be reset this way.
 + * @probe: if true, return 0 if the device can be reset this way.
   *
   * If @dev supports native PCI PM and its PCI_PM_CTRL_NO_SOFT_RESET flag is
   * unset, it will be reinitialized internally when going from PCI_D3hot to
   * by default (i.e. unless the @dev's d3hot_delay field has a different value).
   * Moreover, only devices in D0 can be reset by this function.
   */
 -static int pci_pm_reset(struct pci_dev *dev, int probe)
 +static int pci_pm_reset(struct pci_dev *dev, bool probe)
  {
        u16 csr;
  
@@@ -5000,7 -4988,7 +5000,7 @@@ int pci_bridge_secondary_bus_reset(stru
  }
  EXPORT_SYMBOL_GPL(pci_bridge_secondary_bus_reset);
  
 -static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
 +static int pci_parent_bus_reset(struct pci_dev *dev, bool probe)
  {
        struct pci_dev *pdev;
  
        return pci_bridge_secondary_bus_reset(dev->bus->self);
  }
  
 -static int pci_reset_hotplug_slot(struct hotplug_slot *hotplug, int probe)
 +static int pci_reset_hotplug_slot(struct hotplug_slot *hotplug, bool probe)
  {
        int rc = -ENOTTY;
  
        return rc;
  }
  
 -static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe)
 +static int pci_dev_reset_slot_function(struct pci_dev *dev, bool probe)
  {
        if (dev->multifunction || dev->subordinate || !dev->slot ||
            dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)
        return pci_reset_hotplug_slot(dev->slot->hotplug, probe);
  }
  
 -static int pci_reset_bus_function(struct pci_dev *dev, int probe)
 +static int pci_reset_bus_function(struct pci_dev *dev, bool probe)
  {
        int rc;
  
@@@ -5126,139 -5114,6 +5126,139 @@@ static void pci_dev_restore(struct pci_
                err_handler->reset_done(dev);
  }
  
 +/* dev->reset_methods[] is a 0-terminated list of indices into this array */
 +static const struct pci_reset_fn_method pci_reset_fn_methods[] = {
 +      { },
 +      { pci_dev_specific_reset, .name = "device_specific" },
 +      { pci_dev_acpi_reset, .name = "acpi" },
 +      { pcie_reset_flr, .name = "flr" },
 +      { pci_af_flr, .name = "af_flr" },
 +      { pci_pm_reset, .name = "pm" },
 +      { pci_reset_bus_function, .name = "bus" },
 +};
 +
 +static ssize_t reset_method_show(struct device *dev,
 +                               struct device_attribute *attr, char *buf)
 +{
 +      struct pci_dev *pdev = to_pci_dev(dev);
 +      ssize_t len = 0;
 +      int i, m;
 +
 +      for (i = 0; i < PCI_NUM_RESET_METHODS; i++) {
 +              m = pdev->reset_methods[i];
 +              if (!m)
 +                      break;
 +
 +              len += sysfs_emit_at(buf, len, "%s%s", len ? " " : "",
 +                                   pci_reset_fn_methods[m].name);
 +      }
 +
 +      if (len)
 +              len += sysfs_emit_at(buf, len, "\n");
 +
 +      return len;
 +}
 +
 +static int reset_method_lookup(const char *name)
 +{
 +      int m;
 +
 +      for (m = 1; m < PCI_NUM_RESET_METHODS; m++) {
 +              if (sysfs_streq(name, pci_reset_fn_methods[m].name))
 +                      return m;
 +      }
 +
 +      return 0;       /* not found */
 +}
 +
 +static ssize_t reset_method_store(struct device *dev,
 +                                struct device_attribute *attr,
 +                                const char *buf, size_t count)
 +{
 +      struct pci_dev *pdev = to_pci_dev(dev);
 +      char *options, *name;
 +      int m, n;
 +      u8 reset_methods[PCI_NUM_RESET_METHODS] = { 0 };
 +
 +      if (sysfs_streq(buf, "")) {
 +              pdev->reset_methods[0] = 0;
 +              pci_warn(pdev, "All device reset methods disabled by user");
 +              return count;
 +      }
 +
 +      if (sysfs_streq(buf, "default")) {
 +              pci_init_reset_methods(pdev);
 +              return count;
 +      }
 +
 +      options = kstrndup(buf, count, GFP_KERNEL);
 +      if (!options)
 +              return -ENOMEM;
 +
 +      n = 0;
 +      while ((name = strsep(&options, " ")) != NULL) {
 +              if (sysfs_streq(name, ""))
 +                      continue;
 +
 +              name = strim(name);
 +
 +              m = reset_method_lookup(name);
 +              if (!m) {
 +                      pci_err(pdev, "Invalid reset method '%s'", name);
 +                      goto error;
 +              }
 +
 +              if (pci_reset_fn_methods[m].reset_fn(pdev, PCI_RESET_PROBE)) {
 +                      pci_err(pdev, "Unsupported reset method '%s'", name);
 +                      goto error;
 +              }
 +
 +              if (n == PCI_NUM_RESET_METHODS - 1) {
 +                      pci_err(pdev, "Too many reset methods\n");
 +                      goto error;
 +              }
 +
 +              reset_methods[n++] = m;
 +      }
 +
 +      reset_methods[n] = 0;
 +
 +      /* Warn if dev-specific supported but not highest priority */
 +      if (pci_reset_fn_methods[1].reset_fn(pdev, PCI_RESET_PROBE) == 0 &&
 +          reset_methods[0] != 1)
 +              pci_warn(pdev, "Device-specific reset disabled/de-prioritized by user");
 +      memcpy(pdev->reset_methods, reset_methods, sizeof(pdev->reset_methods));
 +      kfree(options);
 +      return count;
 +
 +error:
 +      /* Leave previous methods unchanged */
 +      kfree(options);
 +      return -EINVAL;
 +}
 +static DEVICE_ATTR_RW(reset_method);
 +
 +static struct attribute *pci_dev_reset_method_attrs[] = {
 +      &dev_attr_reset_method.attr,
 +      NULL,
 +};
 +
 +static umode_t pci_dev_reset_method_attr_is_visible(struct kobject *kobj,
 +                                                  struct attribute *a, int n)
 +{
 +      struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
 +
 +      if (!pci_reset_supported(pdev))
 +              return 0;
 +
 +      return a->mode;
 +}
 +
 +const struct attribute_group pci_dev_reset_method_attr_group = {
 +      .attrs = pci_dev_reset_method_attrs,
 +      .is_visible = pci_dev_reset_method_attr_is_visible,
 +};
 +
  /**
   * __pci_reset_function_locked - reset a PCI device function while holding
   * the @dev mutex lock.
   */
  int __pci_reset_function_locked(struct pci_dev *dev)
  {
 -      int rc;
 +      int i, m, rc = -ENOTTY;
  
        might_sleep();
  
        /*
 -       * A reset method returns -ENOTTY if it doesn't support this device
 -       * and we should try the next method.
 +       * A reset method returns -ENOTTY if it doesn't support this device and
 +       * we should try the next method.
         *
 -       * If it returns 0 (success), we're finished.  If it returns any
 -       * other error, we're also finished: this indicates that further
 -       * reset mechanisms might be broken on the device.
 +       * If it returns 0 (success), we're finished.  If it returns any other
 +       * error, we're also finished: this indicates that further reset
 +       * mechanisms might be broken on the device.
         */
 -      rc = pci_dev_specific_reset(dev, 0);
 -      if (rc != -ENOTTY)
 -              return rc;
 -      if (pcie_has_flr(dev)) {
 -              rc = pcie_flr(dev);
 +      for (i = 0; i < PCI_NUM_RESET_METHODS; i++) {
 +              m = dev->reset_methods[i];
 +              if (!m)
 +                      return -ENOTTY;
 +
 +              rc = pci_reset_fn_methods[m].reset_fn(dev, PCI_RESET_DO_RESET);
 +              if (!rc)
 +                      return 0;
                if (rc != -ENOTTY)
                        return rc;
        }
 -      rc = pci_af_flr(dev, 0);
 -      if (rc != -ENOTTY)
 -              return rc;
 -      rc = pci_pm_reset(dev, 0);
 -      if (rc != -ENOTTY)
 -              return rc;
 -      return pci_reset_bus_function(dev, 0);
 +
 +      return -ENOTTY;
  }
  EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
  
  /**
 - * pci_probe_reset_function - check whether the device can be safely reset
 - * @dev: PCI device to reset
 + * pci_init_reset_methods - check whether device can be safely reset
 + * and store supported reset mechanisms.
 + * @dev: PCI device to check for reset mechanisms
   *
   * 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.
 + * other functions in the same device.  The PCI device must be in D0-D3hot
 + * state.
   *
 - * Returns 0 if the device function can be reset or negative if the
 - * device doesn't support resetting a single function.
 + * Stores reset mechanisms supported by device in reset_methods byte array
 + * which is a member of struct pci_dev.
   */
 -int pci_probe_reset_function(struct pci_dev *dev)
 +void pci_init_reset_methods(struct pci_dev *dev)
  {
 -      int rc;
 +      int m, i, rc;
 +
 +      BUILD_BUG_ON(ARRAY_SIZE(pci_reset_fn_methods) != PCI_NUM_RESET_METHODS);
  
        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;
 +      i = 0;
 +      for (m = 1; m < PCI_NUM_RESET_METHODS; m++) {
 +              rc = pci_reset_fn_methods[m].reset_fn(dev, PCI_RESET_PROBE);
 +              if (!rc)
 +                      dev->reset_methods[i++] = m;
 +              else if (rc != -ENOTTY)
 +                      break;
 +      }
  
 -      return pci_reset_bus_function(dev, 1);
 +      dev->reset_methods[i] = 0;
  }
  
  /**
@@@ -5361,7 -5218,7 +5361,7 @@@ int pci_reset_function(struct pci_dev *
  {
        int rc;
  
 -      if (!dev->reset_fn)
 +      if (!pci_reset_supported(dev))
                return -ENOTTY;
  
        pci_dev_lock(dev);
@@@ -5397,7 -5254,7 +5397,7 @@@ int pci_reset_function_locked(struct pc
  {
        int rc;
  
 -      if (!dev->reset_fn)
 +      if (!pci_reset_supported(dev))
                return -ENOTTY;
  
        pci_dev_save_and_disable(dev);
@@@ -5420,7 -5277,7 +5420,7 @@@ int pci_try_reset_function(struct pci_d
  {
        int rc;
  
 -      if (!dev->reset_fn)
 +      if (!pci_reset_supported(dev))
                return -ENOTTY;
  
        if (!pci_dev_trylock(dev))
@@@ -5648,7 -5505,7 +5648,7 @@@ static void pci_slot_restore_locked(str
        }
  }
  
 -static int pci_slot_reset(struct pci_slot *slot, int probe)
 +static int pci_slot_reset(struct pci_slot *slot, bool probe)
  {
        int rc;
  
   */
  int pci_probe_reset_slot(struct pci_slot *slot)
  {
 -      return pci_slot_reset(slot, 1);
 +      return pci_slot_reset(slot, PCI_RESET_PROBE);
  }
  EXPORT_SYMBOL_GPL(pci_probe_reset_slot);
  
@@@ -5699,14 -5556,14 +5699,14 @@@ static int __pci_reset_slot(struct pci_
  {
        int rc;
  
 -      rc = pci_slot_reset(slot, 1);
 +      rc = pci_slot_reset(slot, PCI_RESET_PROBE);
        if (rc)
                return rc;
  
        if (pci_slot_trylock(slot)) {
                pci_slot_save_and_disable_locked(slot);
                might_sleep();
 -              rc = pci_reset_hotplug_slot(slot->hotplug, 0);
 +              rc = pci_reset_hotplug_slot(slot->hotplug, PCI_RESET_DO_RESET);
                pci_slot_restore_locked(slot);
                pci_slot_unlock(slot);
        } else
        return rc;
  }
  
 -static int pci_bus_reset(struct pci_bus *bus, int probe)
 +static int pci_bus_reset(struct pci_bus *bus, bool probe)
  {
        int ret;
  
@@@ -5761,14 -5618,14 +5761,14 @@@ int pci_bus_error_reset(struct pci_dev 
                        goto bus_reset;
  
        list_for_each_entry(slot, &bus->slots, list)
 -              if (pci_slot_reset(slot, 0))
 +              if (pci_slot_reset(slot, PCI_RESET_DO_RESET))
                        goto bus_reset;
  
        mutex_unlock(&pci_slot_mutex);
        return 0;
  bus_reset:
        mutex_unlock(&pci_slot_mutex);
 -      return pci_bus_reset(bridge->subordinate, 0);
 +      return pci_bus_reset(bridge->subordinate, PCI_RESET_DO_RESET);
  }
  
  /**
   */
  int pci_probe_reset_bus(struct pci_bus *bus)
  {
 -      return pci_bus_reset(bus, 1);
 +      return pci_bus_reset(bus, PCI_RESET_PROBE);
  }
  EXPORT_SYMBOL_GPL(pci_probe_reset_bus);
  
@@@ -5793,7 -5650,7 +5793,7 @@@ static int __pci_reset_bus(struct pci_b
  {
        int rc;
  
 -      rc = pci_bus_reset(bus, 1);
 +      rc = pci_bus_reset(bus, PCI_RESET_PROBE);
        if (rc)
                return rc;
  
diff --combined drivers/pci/pci.h
index 05b7e7e04246741e00a4580591c1f1a6afce1991,288126062a382ef622f9c9aaa666e9c515bc5fb7..78557d2c66126777c6f240ed633324d22ad5d5f3
@@@ -33,11 -33,31 +33,32 @@@ enum pci_mmap_api 
  int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,
                  enum pci_mmap_api mmap_api);
  
 -int pci_probe_reset_function(struct pci_dev *dev);
 +bool pci_reset_supported(struct pci_dev *dev);
 +void pci_init_reset_methods(struct pci_dev *dev);
  int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
  int pci_bus_error_reset(struct pci_dev *dev);
  
+ struct pci_cap_saved_data {
+       u16             cap_nr;
+       bool            cap_extended;
+       unsigned int    size;
+       u32             data[];
+ };
+ struct pci_cap_saved_state {
+       struct hlist_node               next;
+       struct pci_cap_saved_data       cap;
+ };
+ void pci_allocate_cap_save_buffers(struct pci_dev *dev);
+ void pci_free_cap_save_buffers(struct pci_dev *dev);
+ int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size);
+ int pci_add_ext_cap_save_buffer(struct pci_dev *dev,
+                               u16 cap, unsigned int size);
+ struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap);
+ struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
+                                                  u16 cap);
  #define PCI_PM_D2_DELAY         200   /* usec; see PCIe r4.0, sec 5.9.1 */
  #define PCI_PM_D3HOT_WAIT       10    /* msec */
  #define PCI_PM_D3COLD_WAIT      100   /* msec */
@@@ -101,8 -121,6 +122,6 @@@ void pci_pm_init(struct pci_dev *dev)
  void pci_ea_init(struct pci_dev *dev);
  void pci_msi_init(struct pci_dev *dev);
  void pci_msix_init(struct pci_dev *dev);
- void pci_allocate_cap_save_buffers(struct pci_dev *dev);
- void pci_free_cap_save_buffers(struct pci_dev *dev);
  bool pci_bridge_d3_possible(struct pci_dev *dev);
  void pci_bridge_d3_update(struct pci_dev *dev);
  void pci_bridge_wait_for_secondary_bus(struct pci_dev *dev);
@@@ -608,18 -626,13 +627,18 @@@ static inline int pci_enable_ptm(struc
  struct pci_dev_reset_methods {
        u16 vendor;
        u16 device;
 -      int (*reset)(struct pci_dev *dev, int probe);
 +      int (*reset)(struct pci_dev *dev, bool probe);
 +};
 +
 +struct pci_reset_fn_method {
 +      int (*reset_fn)(struct pci_dev *pdev, bool probe);
 +      char *name;
  };
  
  #ifdef CONFIG_PCI_QUIRKS
 -int pci_dev_specific_reset(struct pci_dev *dev, int probe);
 +int pci_dev_specific_reset(struct pci_dev *dev, bool probe);
  #else
 -static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
 +static inline int pci_dev_specific_reset(struct pci_dev *dev, bool probe)
  {
        return -ENOTTY;
  }
@@@ -707,15 -720,7 +726,15 @@@ static inline int pci_aer_raw_clear_sta
  #ifdef CONFIG_ACPI
  int pci_acpi_program_hp_params(struct pci_dev *dev);
  extern const struct attribute_group pci_dev_acpi_attr_group;
 +void pci_set_acpi_fwnode(struct pci_dev *dev);
 +int pci_dev_acpi_reset(struct pci_dev *dev, bool probe);
  #else
 +static inline int pci_dev_acpi_reset(struct pci_dev *dev, bool probe)
 +{
 +      return -ENOTTY;
 +}
 +
 +static inline void pci_set_acpi_fwnode(struct pci_dev *dev) {}
  static inline int pci_acpi_program_hp_params(struct pci_dev *dev)
  {
        return -ENODEV;
  extern const struct attribute_group aspm_ctrl_attr_group;
  #endif
  
 +extern const struct attribute_group pci_dev_reset_method_attr_group;
 +
  #endif /* DRIVERS_PCI_H */
diff --combined include/linux/pci.h
index bd310ea53f3b79caa3f48fd86a3899a352f5ca53,a662f6c1f120cc04236f3f17c9bdf20c431b16b3..0e29a36accb6c4f0e326f985ea2bbcc137ba3264
                               PCI_STATUS_SIG_TARGET_ABORT | \
                               PCI_STATUS_PARITY)
  
 +/* Number of reset methods used in pci_reset_fn_methods array in pci.c */
 +#define PCI_NUM_RESET_METHODS 7
 +
 +#define PCI_RESET_PROBE               true
 +#define PCI_RESET_DO_RESET    false
 +
  /*
   * The PCI interface treats multi-function devices as independent
   * devices.  The slot/function address of each device is encoded
@@@ -294,26 -288,9 +294,14 @@@ enum pci_bus_speed 
  enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev);
  enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev);
  
- struct pci_cap_saved_data {
-       u16             cap_nr;
-       bool            cap_extended;
-       unsigned int    size;
-       u32             data[];
- };
- struct pci_cap_saved_state {
-       struct hlist_node               next;
-       struct pci_cap_saved_data       cap;
- };
 +struct pci_vpd {
 +      struct mutex    lock;
 +      unsigned int    len;
 +      u8              cap;
 +};
 +
  struct irq_affinity;
  struct pcie_link_state;
 -struct pci_vpd;
  struct pci_sriov;
  struct pci_p2pdma;
  struct rcec_ea;
@@@ -344,7 -321,6 +332,7 @@@ struct pci_dev 
        struct rcec_ea  *rcec_ea;       /* RCEC cached endpoint association */
        struct pci_dev  *rcec;          /* Associated RCEC device */
  #endif
 +      u32             devcap;         /* PCIe Device Capabilities */
        u8              pcie_cap;       /* PCIe capability offset */
        u8              msi_cap;        /* MSI capability offset */
        u8              msix_cap;       /* MSI-X capability offset */
                                           supported from root to here */
        u16             l1ss;           /* L1SS Capability pointer */
  #endif
 +      unsigned int    pasid_no_tlp:1;         /* PASID works without TLP Prefix */
        unsigned int    eetlp_prefix_path:1;    /* End-to-End TLP Prefix */
  
        pci_channel_state_t error_state;        /* Current connectivity state */
        unsigned int    state_saved:1;
        unsigned int    is_physfn:1;
        unsigned int    is_virtfn:1;
 -      unsigned int    reset_fn:1;
        unsigned int    is_hotplug_bridge:1;
        unsigned int    shpc_managed:1;         /* SHPC owned by shpchp */
        unsigned int    is_thunderbolt:1;       /* Thunderbolt controller */
  #ifdef CONFIG_PCI_MSI
        const struct attribute_group **msi_irq_groups;
  #endif
 -      struct pci_vpd *vpd;
 +      struct pci_vpd  vpd;
  #ifdef CONFIG_PCIE_DPC
        u16             dpc_cap;
        unsigned int    dpc_rp_extensions:1;
        char            *driver_override; /* Driver name to force a match */
  
        unsigned long   priv_flags;     /* Private flags for the PCI driver */
 +
 +      /* These methods index pci_reset_fn_methods[] */
 +      u8 reset_methods[PCI_NUM_RESET_METHODS]; /* In priority order */
  };
  
  static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
@@@ -1243,7 -1216,7 +1231,7 @@@ u32 pcie_bandwidth_available(struct pci
                             enum pci_bus_speed *speed,
                             enum pcie_link_width *width);
  void pcie_print_link_status(struct pci_dev *dev);
 -bool pcie_has_flr(struct pci_dev *dev);
 +int pcie_reset_flr(struct pci_dev *dev, bool probe);
  int pcie_flr(struct pci_dev *dev);
  int __pci_reset_function_locked(struct pci_dev *dev);
  int pci_reset_function(struct pci_dev *dev);
@@@ -1293,12 -1266,6 +1281,6 @@@ int pci_load_saved_state(struct pci_de
                         struct pci_saved_state *state);
  int pci_load_and_free_saved_state(struct pci_dev *dev,
                                  struct pci_saved_state **state);
- struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap);
- struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
-                                                  u16 cap);
- int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size);
- int pci_add_ext_cap_save_buffer(struct pci_dev *dev,
-                               u16 cap, unsigned int size);
  int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state);
  int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
  pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
@@@ -1755,8 -1722,9 +1737,9 @@@ static inline void pci_disable_device(s
  static inline int pcim_enable_device(struct pci_dev *pdev) { return -EIO; }
  static inline int pci_assign_resource(struct pci_dev *dev, int i)
  { return -EBUSY; }
- static inline int __pci_register_driver(struct pci_driver *drv,
-                                       struct module *owner)
+ static inline int __must_check __pci_register_driver(struct pci_driver *drv,
+                                                    struct module *owner,
+                                                    const char *mod_name)
  { return 0; }
  static inline int pci_register_driver(struct pci_driver *drv)
  { return 0; }
@@@ -1896,7 -1864,9 +1879,7 @@@ int pci_iobar_pfn(struct pci_dev *pdev
  #define pci_resource_end(dev, bar)    ((dev)->resource[(bar)].end)
  #define pci_resource_flags(dev, bar)  ((dev)->resource[(bar)].flags)
  #define pci_resource_len(dev,bar) \
 -      ((pci_resource_start((dev), (bar)) == 0 &&      \
 -        pci_resource_end((dev), (bar)) ==             \
 -        pci_resource_start((dev), (bar))) ? 0 :       \
 +      ((pci_resource_end((dev), (bar)) == 0) ? 0 :    \
                                                        \
         (pci_resource_end((dev), (bar)) -              \
          pci_resource_start((dev), (bar)) + 1))
@@@ -2263,6 -2233,20 +2246,6 @@@ int pci_enable_atomic_ops_to_root(struc
  #define PCI_VPD_LRDT_RO_DATA          PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RO_DATA)
  #define PCI_VPD_LRDT_RW_DATA          PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RW_DATA)
  
 -/* Small Resource Data Type Tag Item Names */
 -#define PCI_VPD_STIN_END              0x0f    /* End */
 -
 -#define PCI_VPD_SRDT_END              (PCI_VPD_STIN_END << 3)
 -
 -#define PCI_VPD_SRDT_TIN_MASK         0x78
 -#define PCI_VPD_SRDT_LEN_MASK         0x07
 -#define PCI_VPD_LRDT_TIN_MASK         0x7f
 -
 -#define PCI_VPD_LRDT_TAG_SIZE         3
 -#define PCI_VPD_SRDT_TAG_SIZE         1
 -
 -#define PCI_VPD_INFO_FLD_HDR_SIZE     3
 -
  #define PCI_VPD_RO_KEYWORD_PARTNO     "PN"
  #define PCI_VPD_RO_KEYWORD_SERIALNO   "SN"
  #define PCI_VPD_RO_KEYWORD_MFR_ID     "MN"
  #define PCI_VPD_RO_KEYWORD_CHKSUM     "RV"
  
  /**
 - * pci_vpd_lrdt_size - Extracts the Large Resource Data Type length
 - * @lrdt: Pointer to the beginning of the Large Resource Data Type tag
 - *
 - * Returns the extracted Large Resource Data Type length.
 - */
 -static inline u16 pci_vpd_lrdt_size(const u8 *lrdt)
 -{
 -      return (u16)lrdt[1] + ((u16)lrdt[2] << 8);
 -}
 -
 -/**
 - * pci_vpd_lrdt_tag - Extracts the Large Resource Data Type Tag Item
 - * @lrdt: Pointer to the beginning of the Large Resource Data Type tag
 - *
 - * Returns the extracted Large Resource Data Type Tag item.
 - */
 -static inline u16 pci_vpd_lrdt_tag(const u8 *lrdt)
 -{
 -      return (u16)(lrdt[0] & PCI_VPD_LRDT_TIN_MASK);
 -}
 -
 -/**
 - * pci_vpd_srdt_size - Extracts the Small Resource Data Type length
 - * @srdt: Pointer to the beginning of the Small Resource Data Type tag
 - *
 - * Returns the extracted Small Resource Data Type length.
 - */
 -static inline u8 pci_vpd_srdt_size(const u8 *srdt)
 -{
 -      return (*srdt) & PCI_VPD_SRDT_LEN_MASK;
 -}
 -
 -/**
 - * pci_vpd_srdt_tag - Extracts the Small Resource Data Type Tag Item
 - * @srdt: Pointer to the beginning of the Small Resource Data Type tag
 + * pci_vpd_alloc - Allocate buffer and read VPD into it
 + * @dev: PCI device
 + * @size: pointer to field where VPD length is returned
   *
 - * Returns the extracted Small Resource Data Type Tag Item.
 + * Returns pointer to allocated buffer or an ERR_PTR in case of failure
   */
 -static inline u8 pci_vpd_srdt_tag(const u8 *srdt)
 -{
 -      return ((*srdt) & PCI_VPD_SRDT_TIN_MASK) >> 3;
 -}
 +void *pci_vpd_alloc(struct pci_dev *dev, unsigned int *size);
  
  /**
 - * pci_vpd_info_field_size - Extracts the information field length
 - * @info_field: Pointer to the beginning of an information field header
 + * pci_vpd_find_id_string - Locate id string in VPD
 + * @buf: Pointer to buffered VPD data
 + * @len: The length of the buffer area in which to search
 + * @size: Pointer to field where length of id string is returned
   *
 - * Returns the extracted information field length.
 + * Returns the index of the id string or -ENOENT if not found.
   */
 -static inline u8 pci_vpd_info_field_size(const u8 *info_field)
 -{
 -      return info_field[2];
 -}
 +int pci_vpd_find_id_string(const u8 *buf, unsigned int len, unsigned int *size);
  
  /**
 - * pci_vpd_find_tag - Locates the Resource Data Type tag provided
 - * @buf: Pointer to buffered vpd data
 - * @len: The length of the vpd buffer
 - * @rdt: The Resource Data Type to search for
 + * pci_vpd_find_ro_info_keyword - Locate info field keyword in VPD RO section
 + * @buf: Pointer to buffered VPD data
 + * @len: The length of the buffer area in which to search
 + * @kw: The keyword to search for
 + * @size: Pointer to field where length of found keyword data is returned
   *
 - * Returns the index where the Resource Data Type was found or
 - * -ENOENT otherwise.
 + * Returns the index of the information field keyword data or -ENOENT if
 + * not found.
   */
 -int pci_vpd_find_tag(const u8 *buf, unsigned int len, u8 rdt);
 +int pci_vpd_find_ro_info_keyword(const void *buf, unsigned int len,
 +                               const char *kw, unsigned int *size);
  
  /**
 - * pci_vpd_find_info_keyword - Locates an information field keyword in the VPD
 - * @buf: Pointer to buffered vpd data
 - * @off: The offset into the buffer at which to begin the search
 - * @len: The length of the buffer area, relative to off, in which to search
 - * @kw: The keyword to search for
 + * pci_vpd_check_csum - Check VPD checksum
 + * @buf: Pointer to buffered VPD data
 + * @len: VPD size
   *
 - * Returns the index where the information field keyword was found or
 - * -ENOENT otherwise.
 + * Returns 1 if VPD has no checksum, otherwise 0 or an errno
   */
 -int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
 -                            unsigned int len, const char *kw);
 +int pci_vpd_check_csum(const void *buf, unsigned int len);
  
  /* PCI <-> OF binding helpers */
  #ifdef CONFIG_OF