]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge branch 'pci/resource' into next
authorBjorn Helgaas <bhelgaas@google.com>
Mon, 1 Aug 2016 17:23:44 +0000 (12:23 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 1 Aug 2016 17:23:44 +0000 (12:23 -0500)
* pci/resource:
  unicore32/PCI: Remove pci=firmware command line parameter handling
  ARM/PCI: Remove arch-specific pcibios_enable_device()
  ARM64/PCI: Remove arch-specific pcibios_enable_device()
  MIPS/PCI: Claim bus resources on PCI_PROBE_ONLY set-ups
  ARM/PCI: Claim bus resources on PCI_PROBE_ONLY set-ups
  PCI: generic: Claim bus resources on PCI_PROBE_ONLY set-ups
  PCI: Add generic pci_bus_claim_resources()
  alx: Use pci_(request|release)_mem_regions
  ethernet/intel: Use pci_(request|release)_mem_regions
  GenWQE: Use pci_(request|release)_mem_regions
  lpfc: Use pci_(request|release)_mem_regions
  NVMe: Use pci_(request|release)_mem_regions
  PCI: Add helpers to request/release memory and I/O regions
  PCI: Extending pci=resource_alignment to specify device/vendor IDs
  sparc/PCI: Implement pci_resource_to_user() with pcibios_resource_to_bus()
  powerpc/pci: Implement pci_resource_to_user() with pcibios_resource_to_bus()
  microblaze/PCI: Implement pci_resource_to_user() with pcibios_resource_to_bus()
  PCI: Unify pci_resource_to_user() declarations
  microblaze/PCI: Remove useless __pci_mmap_set_pgprot()
  powerpc/pci: Remove __pci_mmap_set_pgprot()
  PCI: Ignore write combining when mapping I/O port space

1  2 
Documentation/kernel-parameters.txt
arch/arm64/kernel/pci.c
drivers/pci/host/pci-host-common.c
drivers/pci/pci.c
include/linux/pci.h

index 12a99c7aba0f99b37e2006368535fd4f4da73f22,0618cdd5707e11583cececf1562986fa0666b054..2102248005b5be5568aff5719c529c2374bb6f3f
@@@ -2998,6 -2998,8 +2998,8 @@@ bytes respectively. Such letter suffixe
                resource_alignment=
                                Format:
                                [<order of align>@][<domain>:]<bus>:<slot>.<func>[; ...]
+                               [<order of align>@]pci:<vendor>:<device>\
+                                               [:<subvendor>:<subdevice>][; ...]
                                Specifies alignment and device to reassign
                                aligned memory resources.
                                If <order of align> is not specified,
                hpmemsize=nn[KMG]       The fixed amount of bus space which is
                                reserved for hotplug bridge's memory window.
                                Default size is 2 megabytes.
 +              hpbussize=nn    The minimum amount of additional bus numbers
 +                              reserved for buses below a hotplug bridge.
 +                              Default is 1.
                realloc=        Enable/disable reallocating PCI bridge resources
                                if allocations done by BIOS are too small to
                                accommodate resources required by all child
                compat  Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
                        ports driver.
  
 +      pcie_port_pm=   [PCIE] PCIe port power management handling:
 +              off     Disable power management of all PCIe ports
 +              force   Forcibly enable power management of all PCIe ports
 +
        pcie_pme=       [PCIE,PM] Native PCIe PME signaling options:
                nomsi   Do not use MSI for native PCIe PME signaling (this makes
                        all PCIe root ports use INTx for all services).
diff --combined arch/arm64/kernel/pci.c
index 94cd43c201309f504db3b6755f6f19850a87378e,39cfa032ffa70c9ef48020d7fa3fd959d3a1ca64..acf38722457b1d24a4aad62f167cef415b1538c3
@@@ -17,9 -17,6 +17,9 @@@
  #include <linux/mm.h>
  #include <linux/of_pci.h>
  #include <linux/of_platform.h>
 +#include <linux/pci.h>
 +#include <linux/pci-acpi.h>
 +#include <linux/pci-ecam.h>
  #include <linux/slab.h>
  
  /*
@@@ -39,30 -36,12 +39,17 @@@ resource_size_t pcibios_align_resource(
        return res->start;
  }
  
- /**
-  * pcibios_enable_device - Enable I/O and memory.
-  * @dev: PCI device to be enabled
-  * @mask: bitmask of BARs to enable
-  */
- int pcibios_enable_device(struct pci_dev *dev, int mask)
- {
-       if (pci_has_flag(PCI_PROBE_ONLY))
-               return 0;
-       return pci_enable_resources(dev, mask);
- }
  /*
 - * Try to assign the IRQ number from DT when adding a new device
 + * Try to assign the IRQ number when probing a new device
   */
 -int pcibios_add_device(struct pci_dev *dev)
 +int pcibios_alloc_irq(struct pci_dev *dev)
  {
 -      dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
 +      if (acpi_disabled)
 +              dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
 +#ifdef CONFIG_ACPI
 +      else
 +              return acpi_pci_irq_enable(dev);
 +#endif
  
        return 0;
  }
  int raw_pci_read(unsigned int domain, unsigned int bus,
                  unsigned int devfn, int reg, int len, u32 *val)
  {
 -      return -ENXIO;
 +      struct pci_bus *b = pci_find_bus(domain, bus);
 +
 +      if (!b)
 +              return PCIBIOS_DEVICE_NOT_FOUND;
 +      return b->ops->read(b, devfn, reg, len, val);
  }
  
  int raw_pci_write(unsigned int domain, unsigned int bus,
                unsigned int devfn, int reg, int len, u32 val)
  {
 -      return -ENXIO;
 +      struct pci_bus *b = pci_find_bus(domain, bus);
 +
 +      if (!b)
 +              return PCIBIOS_DEVICE_NOT_FOUND;
 +      return b->ops->write(b, devfn, reg, len, val);
  }
  
  #ifdef CONFIG_NUMA
@@@ -101,124 -72,10 +88,124 @@@ EXPORT_SYMBOL(pcibus_to_node)
  #endif
  
  #ifdef CONFIG_ACPI
 -/* Root bridge scanning */
 +
 +struct acpi_pci_generic_root_info {
 +      struct acpi_pci_root_info       common;
 +      struct pci_config_window        *cfg;   /* config space mapping */
 +};
 +
 +int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
 +{
 +      struct pci_config_window *cfg = bus->sysdata;
 +      struct acpi_device *adev = to_acpi_device(cfg->parent);
 +      struct acpi_pci_root *root = acpi_driver_data(adev);
 +
 +      return root->segment;
 +}
 +
 +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
 +{
 +      if (!acpi_disabled) {
 +              struct pci_config_window *cfg = bridge->bus->sysdata;
 +              struct acpi_device *adev = to_acpi_device(cfg->parent);
 +              ACPI_COMPANION_SET(&bridge->dev, adev);
 +      }
 +
 +      return 0;
 +}
 +
 +/*
 + * Lookup the bus range for the domain in MCFG, and set up config space
 + * mapping.
 + */
 +static struct pci_config_window *
 +pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
 +{
 +      struct resource *bus_res = &root->secondary;
 +      u16 seg = root->segment;
 +      struct pci_config_window *cfg;
 +      struct resource cfgres;
 +      unsigned int bsz;
 +
 +      /* Use address from _CBA if present, otherwise lookup MCFG */
 +      if (!root->mcfg_addr)
 +              root->mcfg_addr = pci_mcfg_lookup(seg, bus_res);
 +
 +      if (!root->mcfg_addr) {
 +              dev_err(&root->device->dev, "%04x:%pR ECAM region not found\n",
 +                      seg, bus_res);
 +              return NULL;
 +      }
 +
 +      bsz = 1 << pci_generic_ecam_ops.bus_shift;
 +      cfgres.start = root->mcfg_addr + bus_res->start * bsz;
 +      cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
 +      cfgres.flags = IORESOURCE_MEM;
 +      cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
 +                            &pci_generic_ecam_ops);
 +      if (IS_ERR(cfg)) {
 +              dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n",
 +                      seg, bus_res, PTR_ERR(cfg));
 +              return NULL;
 +      }
 +
 +      return cfg;
 +}
 +
 +/* release_info: free resources allocated by init_info */
 +static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
 +{
 +      struct acpi_pci_generic_root_info *ri;
 +
 +      ri = container_of(ci, struct acpi_pci_generic_root_info, common);
 +      pci_ecam_free(ri->cfg);
 +      kfree(ri);
 +}
 +
 +static struct acpi_pci_root_ops acpi_pci_root_ops = {
 +      .release_info = pci_acpi_generic_release_info,
 +};
 +
 +/* Interface called from ACPI code to setup PCI host controller */
  struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
  {
 -      /* TODO: Should be revisited when implementing PCI on ACPI */
 -      return NULL;
 +      int node = acpi_get_node(root->device->handle);
 +      struct acpi_pci_generic_root_info *ri;
 +      struct pci_bus *bus, *child;
 +
 +      ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node);
 +      if (!ri)
 +              return NULL;
 +
 +      ri->cfg = pci_acpi_setup_ecam_mapping(root);
 +      if (!ri->cfg) {
 +              kfree(ri);
 +              return NULL;
 +      }
 +
 +      acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops;
 +      bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common,
 +                                 ri->cfg);
 +      if (!bus)
 +              return NULL;
 +
 +      pci_bus_size_bridges(bus);
 +      pci_bus_assign_resources(bus);
 +
 +      list_for_each_entry(child, &bus->children, node)
 +              pcie_bus_configure_settings(child);
 +
 +      return bus;
 +}
 +
 +void pcibios_add_bus(struct pci_bus *bus)
 +{
 +      acpi_pci_add_bus(bus);
  }
 +
 +void pcibios_remove_bus(struct pci_bus *bus)
 +{
 +      acpi_pci_remove_bus(bus);
 +}
 +
  #endif
index c18b9e3bb8bd370d1193d274ccd2ebaa0619a84b,c95d45dc5699e6c9d6016d5ea162028bea402e7b..542b3992ebf360786b70e066da27062f8b1b808e
  #include <linux/module.h>
  #include <linux/of_address.h>
  #include <linux/of_pci.h>
 +#include <linux/pci-ecam.h>
  #include <linux/platform_device.h>
  
 -#include "../ecam.h"
 -
  static int gen_pci_parse_request_of_pci_ranges(struct device *dev,
                       struct list_head *resources, struct resource **bus_range)
  {
@@@ -154,7 -155,14 +154,14 @@@ int pci_host_common_probe(struct platfo
  
        pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
  
-       if (!pci_has_flag(PCI_PROBE_ONLY)) {
+       /*
+        * We insert PCI resources into the iomem_resource and
+        * ioport_resource trees in either pci_bus_claim_resources()
+        * or pci_bus_assign_resources().
+        */
+       if (pci_has_flag(PCI_PROBE_ONLY)) {
+               pci_bus_claim_resources(bus);
+       } else {
                pci_bus_size_bridges(bus);
                pci_bus_assign_resources(bus);
  
diff --combined drivers/pci/pci.c
index 14d24b4fc5087e4cffe6b5f5087f4a98aef5ee79,78de36f1b0126b4d97b8ee09f3740aa1bd714294..9a6bc77ce3aa9137c9327eba06eb48117403de0f
@@@ -7,10 -7,8 +7,10 @@@
   *    Copyright 1997 -- 2000 Martin Mares <mj@ucw.cz>
   */
  
 +#include <linux/acpi.h>
  #include <linux/kernel.h>
  #include <linux/delay.h>
 +#include <linux/dmi.h>
  #include <linux/init.h>
  #include <linux/of.h>
  #include <linux/of_pci.h>
@@@ -27,9 -25,7 +27,9 @@@
  #include <linux/device.h>
  #include <linux/pm_runtime.h>
  #include <linux/pci_hotplug.h>
 +#include <linux/vmalloc.h>
  #include <asm/setup.h>
 +#include <asm/dma.h>
  #include <linux/aer.h>
  #include "pci.h"
  
@@@ -85,9 -81,6 +85,9 @@@ unsigned long pci_cardbus_mem_size = DE
  unsigned long pci_hotplug_io_size  = DEFAULT_HOTPLUG_IO_SIZE;
  unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
  
 +#define DEFAULT_HOTPLUG_BUS_SIZE      1
 +unsigned long pci_hotplug_bus_size = DEFAULT_HOTPLUG_BUS_SIZE;
 +
  enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT;
  
  /*
@@@ -108,21 -101,6 +108,21 @@@ unsigned int pcibios_max_latency = 255
  /* If set, the PCIe ARI capability will not be used. */
  static bool pcie_ari_disabled;
  
 +/* Disable bridge_d3 for all PCIe ports */
 +static bool pci_bridge_d3_disable;
 +/* Force bridge_d3 for all PCIe ports */
 +static bool pci_bridge_d3_force;
 +
 +static int __init pcie_port_pm_setup(char *str)
 +{
 +      if (!strcmp(str, "off"))
 +              pci_bridge_d3_disable = true;
 +      else if (!strcmp(str, "force"))
 +              pci_bridge_d3_force = true;
 +      return 1;
 +}
 +__setup("pcie_port_pm=", pcie_port_pm_setup);
 +
  /**
   * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
   * @bus: pointer to PCI bus structure to search
@@@ -2177,164 -2155,6 +2177,164 @@@ void pci_config_pm_runtime_put(struct p
                pm_runtime_put_sync(parent);
  }
  
 +/**
 + * pci_bridge_d3_possible - Is it possible to put the bridge into D3
 + * @bridge: Bridge to check
 + *
 + * This function checks if it is possible to move the bridge to D3.
 + * Currently we only allow D3 for recent enough PCIe ports.
 + */
 +static bool pci_bridge_d3_possible(struct pci_dev *bridge)
 +{
 +      unsigned int year;
 +
 +      if (!pci_is_pcie(bridge))
 +              return false;
 +
 +      switch (pci_pcie_type(bridge)) {
 +      case PCI_EXP_TYPE_ROOT_PORT:
 +      case PCI_EXP_TYPE_UPSTREAM:
 +      case PCI_EXP_TYPE_DOWNSTREAM:
 +              if (pci_bridge_d3_disable)
 +                      return false;
 +              if (pci_bridge_d3_force)
 +                      return true;
 +
 +              /*
 +               * It should be safe to put PCIe ports from 2015 or newer
 +               * to D3.
 +               */
 +              if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) &&
 +                  year >= 2015) {
 +                      return true;
 +              }
 +              break;
 +      }
 +
 +      return false;
 +}
 +
 +static int pci_dev_check_d3cold(struct pci_dev *dev, void *data)
 +{
 +      bool *d3cold_ok = data;
 +      bool no_d3cold;
 +
 +      /*
 +       * The device needs to be allowed to go D3cold and if it is wake
 +       * capable to do so from D3cold.
 +       */
 +      no_d3cold = dev->no_d3cold || !dev->d3cold_allowed ||
 +              (device_may_wakeup(&dev->dev) && !pci_pme_capable(dev, PCI_D3cold)) ||
 +              !pci_power_manageable(dev);
 +
 +      *d3cold_ok = !no_d3cold;
 +
 +      return no_d3cold;
 +}
 +
 +/*
 + * pci_bridge_d3_update - Update bridge D3 capabilities
 + * @dev: PCI device which is changed
 + * @remove: Is the device being removed
 + *
 + * Update upstream bridge PM capabilities accordingly depending on if the
 + * device PM configuration was changed or the device is being removed.  The
 + * change is also propagated upstream.
 + */
 +static void pci_bridge_d3_update(struct pci_dev *dev, bool remove)
 +{
 +      struct pci_dev *bridge;
 +      bool d3cold_ok = true;
 +
 +      bridge = pci_upstream_bridge(dev);
 +      if (!bridge || !pci_bridge_d3_possible(bridge))
 +              return;
 +
 +      pci_dev_get(bridge);
 +      /*
 +       * If the device is removed we do not care about its D3cold
 +       * capabilities.
 +       */
 +      if (!remove)
 +              pci_dev_check_d3cold(dev, &d3cold_ok);
 +
 +      if (d3cold_ok) {
 +              /*
 +               * We need to go through all children to find out if all of
 +               * them can still go to D3cold.
 +               */
 +              pci_walk_bus(bridge->subordinate, pci_dev_check_d3cold,
 +                           &d3cold_ok);
 +      }
 +
 +      if (bridge->bridge_d3 != d3cold_ok) {
 +              bridge->bridge_d3 = d3cold_ok;
 +              /* Propagate change to upstream bridges */
 +              pci_bridge_d3_update(bridge, false);
 +      }
 +
 +      pci_dev_put(bridge);
 +}
 +
 +/**
 + * pci_bridge_d3_device_changed - Update bridge D3 capabilities on change
 + * @dev: PCI device that was changed
 + *
 + * If a device is added or its PM configuration, such as is it allowed to
 + * enter D3cold, is changed this function updates upstream bridge PM
 + * capabilities accordingly.
 + */
 +void pci_bridge_d3_device_changed(struct pci_dev *dev)
 +{
 +      pci_bridge_d3_update(dev, false);
 +}
 +
 +/**
 + * pci_bridge_d3_device_removed - Update bridge D3 capabilities on remove
 + * @dev: PCI device being removed
 + *
 + * Function updates upstream bridge PM capabilities based on other devices
 + * still left on the bus.
 + */
 +void pci_bridge_d3_device_removed(struct pci_dev *dev)
 +{
 +      pci_bridge_d3_update(dev, true);
 +}
 +
 +/**
 + * pci_d3cold_enable - Enable D3cold for device
 + * @dev: PCI device to handle
 + *
 + * This function can be used in drivers to enable D3cold from the device
 + * they handle.  It also updates upstream PCI bridge PM capabilities
 + * accordingly.
 + */
 +void pci_d3cold_enable(struct pci_dev *dev)
 +{
 +      if (dev->no_d3cold) {
 +              dev->no_d3cold = false;
 +              pci_bridge_d3_device_changed(dev);
 +      }
 +}
 +EXPORT_SYMBOL_GPL(pci_d3cold_enable);
 +
 +/**
 + * pci_d3cold_disable - Disable D3cold for device
 + * @dev: PCI device to handle
 + *
 + * This function can be used in drivers to disable D3cold from the device
 + * they handle.  It also updates upstream PCI bridge PM capabilities
 + * accordingly.
 + */
 +void pci_d3cold_disable(struct pci_dev *dev)
 +{
 +      if (!dev->no_d3cold) {
 +              dev->no_d3cold = true;
 +              pci_bridge_d3_device_changed(dev);
 +      }
 +}
 +EXPORT_SYMBOL_GPL(pci_d3cold_disable);
 +
  /**
   * pci_pm_init - Initialize PM functions of given PCI device
   * @dev: PCI device to handle.
@@@ -2369,7 -2189,6 +2369,7 @@@ void pci_pm_init(struct pci_dev *dev
        dev->pm_cap = pm;
        dev->d3_delay = PCI_PM_D3_WAIT;
        dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
 +      dev->bridge_d3 = pci_bridge_d3_possible(dev);
        dev->d3cold_allowed = true;
  
        dev->d1_support = false;
@@@ -3346,23 -3165,6 +3346,23 @@@ int __weak pci_remap_iospace(const stru
  #endif
  }
  
 +/**
 + *    pci_unmap_iospace - Unmap the memory mapped I/O space
 + *    @res: resource to be unmapped
 + *
 + *    Unmap the CPU virtual address @res from virtual address space.
 + *    Only architectures that have memory mapped IO functions defined
 + *    (and the PCI_IOBASE value defined) should call this function.
 + */
 +void pci_unmap_iospace(struct resource *res)
 +{
 +#if defined(PCI_IOBASE) && defined(CONFIG_MMU)
 +      unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start;
 +
 +      unmap_kernel_range(vaddr, resource_size(res));
 +#endif
 +}
 +
  static void __pci_set_master(struct pci_dev *dev, bool enable)
  {
        u16 old_cmd, cmd;
@@@ -4953,6 -4755,7 +4953,7 @@@ static DEFINE_SPINLOCK(resource_alignme
  static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
  {
        int seg, bus, slot, func, align_order, count;
+       unsigned short vendor, device, subsystem_vendor, subsystem_device;
        resource_size_t align = 0;
        char *p;
  
                } else {
                        align_order = -1;
                }
-               if (sscanf(p, "%x:%x:%x.%x%n",
-                       &seg, &bus, &slot, &func, &count) != 4) {
-                       seg = 0;
-                       if (sscanf(p, "%x:%x.%x%n",
-                                       &bus, &slot, &func, &count) != 3) {
-                               /* Invalid format */
-                               printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: %s\n",
-                                       p);
+               if (strncmp(p, "pci:", 4) == 0) {
+                       /* PCI vendor/device (subvendor/subdevice) ids are specified */
+                       p += 4;
+                       if (sscanf(p, "%hx:%hx:%hx:%hx%n",
+                               &vendor, &device, &subsystem_vendor, &subsystem_device, &count) != 4) {
+                               if (sscanf(p, "%hx:%hx%n", &vendor, &device, &count) != 2) {
+                                       printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: pci:%s\n",
+                                               p);
+                                       break;
+                               }
+                               subsystem_vendor = subsystem_device = 0;
+                       }
+                       p += count;
+                       if ((!vendor || (vendor == dev->vendor)) &&
+                               (!device || (device == dev->device)) &&
+                               (!subsystem_vendor || (subsystem_vendor == dev->subsystem_vendor)) &&
+                               (!subsystem_device || (subsystem_device == dev->subsystem_device))) {
+                               if (align_order == -1)
+                                       align = PAGE_SIZE;
+                               else
+                                       align = 1 << align_order;
+                               /* Found */
                                break;
                        }
                }
-               p += count;
-               if (seg == pci_domain_nr(dev->bus) &&
-                       bus == dev->bus->number &&
-                       slot == PCI_SLOT(dev->devfn) &&
-                       func == PCI_FUNC(dev->devfn)) {
-                       if (align_order == -1)
-                               align = PAGE_SIZE;
-                       else
-                               align = 1 << align_order;
-                       /* Found */
-                       break;
+               else {
+                       if (sscanf(p, "%x:%x:%x.%x%n",
+                               &seg, &bus, &slot, &func, &count) != 4) {
+                               seg = 0;
+                               if (sscanf(p, "%x:%x.%x%n",
+                                               &bus, &slot, &func, &count) != 3) {
+                                       /* Invalid format */
+                                       printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: %s\n",
+                                               p);
+                                       break;
+                               }
+                       }
+                       p += count;
+                       if (seg == pci_domain_nr(dev->bus) &&
+                               bus == dev->bus->number &&
+                               slot == PCI_SLOT(dev->devfn) &&
+                               func == PCI_FUNC(dev->devfn)) {
+                               if (align_order == -1)
+                                       align = PAGE_SIZE;
+                               else
+                                       align = 1 << align_order;
+                               /* Found */
+                               break;
+                       }
                }
                if (*p != ';' && *p != ',') {
                        /* End of param or invalid format */
@@@ -5095,7 -4925,7 +5123,7 @@@ static ssize_t pci_resource_alignment_s
        return pci_set_resource_alignment_param(buf, count);
  }
  
 -BUS_ATTR(resource_alignment, 0644, pci_resource_alignment_show,
 +static BUS_ATTR(resource_alignment, 0644, pci_resource_alignment_show,
                                        pci_resource_alignment_store);
  
  static int __init pci_resource_alignment_sysfs_init(void)
@@@ -5121,7 -4951,7 +5149,7 @@@ int pci_get_new_domain_nr(void
  }
  
  #ifdef CONFIG_PCI_DOMAINS_GENERIC
 -void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
 +static int of_pci_bus_find_domain_nr(struct device *parent)
  {
        static int use_dt_domains = -1;
        int domain = -1;
                domain = -1;
        }
  
 -      bus->domain_nr = domain;
 +      return domain;
 +}
 +
 +int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
 +{
 +      return acpi_disabled ? of_pci_bus_find_domain_nr(parent) :
 +                             acpi_pci_bus_find_domain_nr(bus);
  }
  #endif
  #endif
@@@ -5225,11 -5049,6 +5253,11 @@@ static int __init pci_setup(char *str
                                pci_hotplug_io_size = memparse(str + 9, &str);
                        } else if (!strncmp(str, "hpmemsize=", 10)) {
                                pci_hotplug_mem_size = memparse(str + 10, &str);
 +                      } else if (!strncmp(str, "hpbussize=", 10)) {
 +                              pci_hotplug_bus_size =
 +                                      simple_strtoul(str + 10, &str, 0);
 +                              if (pci_hotplug_bus_size > 0xff)
 +                                      pci_hotplug_bus_size = DEFAULT_HOTPLUG_BUS_SIZE;
                        } else if (!strncmp(str, "pcie_bus_tune_off", 17)) {
                                pcie_bus_config = PCIE_BUS_TUNE_OFF;
                        } else if (!strncmp(str, "pcie_bus_safe", 13)) {
diff --combined include/linux/pci.h
index 5db39dddd96b8cf2546fe2b4d4e88d2947fe1a72,d6cfecfee864fdea9f1173c53a5f0141b339efb9..13d9c415eb64f801d4246a4d4e42a11b1a73579c
@@@ -101,10 -101,6 +101,10 @@@ enum 
        DEVICE_COUNT_RESOURCE = PCI_NUM_RESOURCES,
  };
  
 +/*
 + * pci_power_t values must match the bits in the Capabilities PME_Support
 + * and Control/Status PowerState fields in the Power Management capability.
 + */
  typedef int __bitwise pci_power_t;
  
  #define PCI_D0                ((pci_power_t __force) 0)
@@@ -120,7 -116,7 +120,7 @@@ extern const char *pci_power_names[]
  
  static inline const char *pci_power_name(pci_power_t state)
  {
 -      return pci_power_names[1 + (int) state];
 +      return pci_power_names[1 + (__force int) state];
  }
  
  #define PCI_PM_D2_DELAY               200
@@@ -298,7 -294,6 +298,7 @@@ struct pci_dev 
        unsigned int    d2_support:1;   /* Low power state D2 is supported */
        unsigned int    no_d1d2:1;      /* D1 and D2 are forbidden */
        unsigned int    no_d3cold:1;    /* D3cold is forbidden */
 +      unsigned int    bridge_d3:1;    /* Allow D3 for bridge */
        unsigned int    d3cold_allowed:1;       /* D3cold is allowed by user */
        unsigned int    mmio_always_on:1;       /* disallow turning off io/mem
                                                   decoding during bar sizing */
@@@ -1088,8 -1083,6 +1088,8 @@@ int pci_back_from_sleep(struct pci_dev 
  bool pci_dev_run_wake(struct pci_dev *dev);
  bool pci_check_pme_status(struct pci_dev *dev);
  void pci_pme_wakeup_bus(struct pci_bus *bus);
 +void pci_d3cold_enable(struct pci_dev *dev);
 +void pci_d3cold_disable(struct pci_dev *dev);
  
  static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
                                  bool enable)
@@@ -1121,6 -1114,7 +1121,7 @@@ int pci_set_vpd_size(struct pci_dev *de
  /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
  resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx);
  void pci_bus_assign_resources(const struct pci_bus *bus);
+ void pci_bus_claim_resources(struct pci_bus *bus);
  void pci_bus_size_bridges(struct pci_bus *bus);
  int pci_claim_resource(struct pci_dev *, int);
  int pci_claim_bridge_resource(struct pci_dev *bridge, int i);
@@@ -1174,7 -1168,6 +1175,7 @@@ int pci_register_io_range(phys_addr_t a
  unsigned long pci_address_to_pio(phys_addr_t addr);
  phys_addr_t pci_pio_to_address(unsigned long pio);
  int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
 +void pci_unmap_iospace(struct resource *res);
  
  static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
  {
@@@ -1397,13 -1390,12 +1398,13 @@@ static inline int pci_domain_nr(struct 
  {
        return bus->domain_nr;
  }
 -void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
 +#ifdef CONFIG_ACPI
 +int acpi_pci_bus_find_domain_nr(struct pci_bus *bus);
  #else
 -static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
 -                                      struct device *parent)
 -{
 -}
 +static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
 +{ return 0; }
 +#endif
 +int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
  #endif
  
  /* some architectures require additional setup to direct VGA traffic */
@@@ -1411,6 -1403,34 +1412,34 @@@ typedef int (*arch_set_vga_state_t)(str
                      unsigned int command_bits, u32 flags);
  void pci_register_set_vga_state(arch_set_vga_state_t func);
  
+ static inline int
+ pci_request_io_regions(struct pci_dev *pdev, const char *name)
+ {
+       return pci_request_selected_regions(pdev,
+                           pci_select_bars(pdev, IORESOURCE_IO), name);
+ }
+ static inline void
+ pci_release_io_regions(struct pci_dev *pdev)
+ {
+       return pci_release_selected_regions(pdev,
+                           pci_select_bars(pdev, IORESOURCE_IO));
+ }
+ static inline int
+ pci_request_mem_regions(struct pci_dev *pdev, const char *name)
+ {
+       return pci_request_selected_regions(pdev,
+                           pci_select_bars(pdev, IORESOURCE_MEM), name);
+ }
+ static inline void
+ pci_release_mem_regions(struct pci_dev *pdev)
+ {
+       return pci_release_selected_regions(pdev,
+                           pci_select_bars(pdev, IORESOURCE_MEM));
+ }
  #else /* CONFIG_PCI is not enabled */
  
  static inline void pci_set_flags(int flags) { }
@@@ -1563,7 -1583,11 +1592,11 @@@ static inline const char *pci_name(cons
  /* Some archs don't want to expose struct resource to userland as-is
   * in sysfs and /proc
   */
- #ifndef HAVE_ARCH_PCI_RESOURCE_TO_USER
+ #ifdef HAVE_ARCH_PCI_RESOURCE_TO_USER
+ void pci_resource_to_user(const struct pci_dev *dev, int bar,
+                         const struct resource *rsrc,
+                         resource_size_t *start, resource_size_t *end);
+ #else
  static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
                const struct resource *rsrc, resource_size_t *start,
                resource_size_t *end)
@@@ -1715,7 -1739,6 +1748,7 @@@ extern u8 pci_cache_line_size
  
  extern unsigned long pci_hotplug_io_size;
  extern unsigned long pci_hotplug_mem_size;
 +extern unsigned long pci_hotplug_bus_size;
  
  /* Architecture-specific versions may override these (weak) */
  void pcibios_disable_device(struct pci_dev *dev);
@@@ -1732,7 -1755,7 +1765,7 @@@ void pcibios_free_irq(struct pci_dev *d
  extern struct dev_pm_ops pcibios_pm_ops;
  #endif
  
 -#ifdef CONFIG_PCI_MMCONFIG
 +#if defined(CONFIG_PCI_MMCONFIG) || defined(CONFIG_ACPI_MCFG)
  void __init pci_mmcfg_early_init(void);
  void __init pci_mmcfg_late_init(void);
  #else