]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge tag 'pci-v3.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Apr 2014 22:14:04 +0000 (15:14 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Apr 2014 22:14:04 +0000 (15:14 -0700)
Pull PCI changes from Bjorn Helgaas:
 "Enumeration
   - Increment max correctly in pci_scan_bridge() (Andreas Noever)
   - Clarify the "scan anyway" comment in pci_scan_bridge() (Andreas Noever)
   - Assign CardBus bus number only during the second pass (Andreas Noever)
   - Use request_resource_conflict() instead of insert_ for bus numbers (Andreas Noever)
   - Make sure bus number resources stay within their parents bounds (Andreas Noever)
   - Remove pci_fixup_parent_subordinate_busnr() (Andreas Noever)
   - Check for child busses which use more bus numbers than allocated (Andreas Noever)
   - Don't scan random busses in pci_scan_bridge() (Andreas Noever)
   - x86: Drop pcibios_scan_root() check for bus already scanned (Bjorn Helgaas)
   - x86: Use pcibios_scan_root() instead of pci_scan_bus_with_sysdata() (Bjorn Helgaas)
   - x86: Use pcibios_scan_root() instead of pci_scan_bus_on_node() (Bjorn Helgaas)
   - x86: Merge pci_scan_bus_on_node() into pcibios_scan_root() (Bjorn Helgaas)
   - x86: Drop return value of pcibios_scan_root() (Bjorn Helgaas)

  NUMA
   - x86: Add x86_pci_root_bus_node() to look up NUMA node from PCI bus (Bjorn Helgaas)
   - x86: Use x86_pci_root_bus_node() instead of get_mp_bus_to_node() (Bjorn Helgaas)
   - x86: Remove mp_bus_to_node[], set_mp_bus_to_node(), get_mp_bus_to_node() (Bjorn Helgaas)
   - x86: Use NUMA_NO_NODE, not -1, for unknown node (Bjorn Helgaas)
   - x86: Remove acpi_get_pxm() usage (Bjorn Helgaas)
   - ia64: Use NUMA_NO_NODE, not MAX_NUMNODES, for unknown node (Bjorn Helgaas)
   - ia64: Remove acpi_get_pxm() usage (Bjorn Helgaas)
   - ACPI: Fix acpi_get_node() prototype (Bjorn Helgaas)

  Resource management
   - i2o: Fix and refactor PCI space allocation (Bjorn Helgaas)
   - Add resource_contains() (Bjorn Helgaas)
   - Add %pR support for IORESOURCE_UNSET (Bjorn Helgaas)
   - Mark resources as IORESOURCE_UNSET if we can't assign them (Bjorn Helgaas)
   - Don't clear IORESOURCE_UNSET when updating BAR (Bjorn Helgaas)
   - Check IORESOURCE_UNSET before updating BAR (Bjorn Helgaas)
   - Don't try to claim IORESOURCE_UNSET resources (Bjorn Helgaas)
   - Mark 64-bit resource as IORESOURCE_UNSET if we only support 32-bit (Bjorn Helgaas)
   - Don't enable decoding if BAR hasn't been assigned an address (Bjorn Helgaas)
   - Add "weak" generic pcibios_enable_device() implementation (Bjorn Helgaas)
   - alpha, microblaze, sh, sparc, tile: Use default pcibios_enable_device() (Bjorn Helgaas)
   - s390: Use generic pci_enable_resources() (Bjorn Helgaas)
   - Don't check resource_size() in pci_bus_alloc_resource() (Bjorn Helgaas)
   - Set type in __request_region() (Bjorn Helgaas)
   - Check all IORESOURCE_TYPE_BITS in pci_bus_alloc_from_region() (Bjorn Helgaas)
   - Change pci_bus_alloc_resource() type_mask to unsigned long (Bjorn Helgaas)
   - Log IDE resource quirk in dmesg (Bjorn Helgaas)
   - Revert "[PATCH] Insert GART region into resource map" (Bjorn Helgaas)

  PCI device hotplug
   - Make check_link_active() non-static (Rajat Jain)
   - Use link change notifications for hot-plug and removal (Rajat Jain)
   - Enable link state change notifications (Rajat Jain)
   - Don't disable the link permanently during removal (Rajat Jain)
   - Don't check adapter or latch status while disabling (Rajat Jain)
   - Disable link notification across slot reset (Rajat Jain)
   - Ensure very fast hotplug events are also processed (Rajat Jain)
   - Add hotplug_lock to serialize hotplug events (Rajat Jain)
   - Remove a non-existent card, regardless of "surprise" capability (Rajat Jain)
   - Don't turn slot off when hot-added device already exists (Yijing Wang)

  MSI
   - Keep pci_enable_msi() documentation (Alexander Gordeev)
   - ahci: Fix broken single MSI fallback (Alexander Gordeev)
   - ahci, vfio: Use pci_enable_msi_range() (Alexander Gordeev)
   - Check kmalloc() return value, fix leak of name (Greg Kroah-Hartman)
   - Fix leak of msi_attrs (Greg Kroah-Hartman)
   - Fix pci_msix_vec_count() htmldocs failure (Masanari Iida)

  Virtualization
   - Device-specific ACS support (Alex Williamson)

  Freescale i.MX6
   - Wait for retraining (Marek Vasut)

  Marvell MVEBU
   - Use Device ID and revision from underlying endpoint (Andrew Lunn)
   - Fix incorrect size for PCI aperture resources (Jason Gunthorpe)
   - Call request_resource() on the apertures (Jason Gunthorpe)
   - Fix potential issue in range parsing (Jean-Jacques Hiblot)

  Renesas R-Car
   - Check platform_get_irq() return code (Ben Dooks)
   - Add error interrupt handling (Ben Dooks)
   - Fix bridge logic configuration accesses (Ben Dooks)
   - Register each instance independently (Magnus Damm)
   - Break out window size handling (Magnus Damm)
   - Make the Kconfig dependencies more generic (Magnus Damm)

  Synopsys DesignWare
   - Fix RC BAR to be single 64-bit non-prefetchable memory (Mohit Kumar)

  Miscellaneous
   - Remove unused SR-IOV VF Migration support (Bjorn Helgaas)
   - Enable INTx if BIOS left them disabled (Bjorn Helgaas)
   - Fix hex vs decimal typo in cpqhpc_probe() (Dan Carpenter)
   - Clean up par-arch object file list (Liviu Dudau)
   - Set IORESOURCE_ROM_SHADOW only for the default VGA device (Sander Eikelenboom)
   - ACPI, ARM, drm, powerpc, pcmcia, PCI: Use list_for_each_entry() for bus traversal (Yijing Wang)
   - Fix pci_bus_b() build failure (Paul Gortmaker)"

* tag 'pci-v3.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (108 commits)
  Revert "[PATCH] Insert GART region into resource map"
  PCI: Log IDE resource quirk in dmesg
  PCI: Change pci_bus_alloc_resource() type_mask to unsigned long
  PCI: Check all IORESOURCE_TYPE_BITS in pci_bus_alloc_from_region()
  resources: Set type in __request_region()
  PCI: Don't check resource_size() in pci_bus_alloc_resource()
  s390/PCI: Use generic pci_enable_resources()
  tile PCI RC: Use default pcibios_enable_device()
  sparc/PCI: Use default pcibios_enable_device() (Leon only)
  sh/PCI: Use default pcibios_enable_device()
  microblaze/PCI: Use default pcibios_enable_device()
  alpha/PCI: Use default pcibios_enable_device()
  PCI: Add "weak" generic pcibios_enable_device() implementation
  PCI: Don't enable decoding if BAR hasn't been assigned an address
  PCI: Enable INTx in pci_reenable_device() only when MSI/MSI-X not enabled
  PCI: Mark 64-bit resource as IORESOURCE_UNSET if we only support 32-bit
  PCI: Don't try to claim IORESOURCE_UNSET resources
  PCI: Check IORESOURCE_UNSET before updating BAR
  PCI: Don't clear IORESOURCE_UNSET when updating BAR
  PCI: Mark resources as IORESOURCE_UNSET if we can't assign them
  ...

Conflicts:
arch/x86/include/asm/topology.h
drivers/ata/ahci.c

68 files changed:
Documentation/PCI/pci-iov-howto.txt
arch/alpha/kernel/pci.c
arch/arm/kernel/bios32.c
arch/frv/mb93090-mb00/pci-frv.c
arch/ia64/hp/common/sba_iommu.c
arch/ia64/include/asm/pci.h
arch/ia64/kernel/acpi.c
arch/ia64/pci/fixup.c
arch/ia64/pci/pci.c
arch/microblaze/pci/pci-common.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/s390/pci/pci.c
arch/sh/drivers/pci/pci.c
arch/sparc/kernel/leon_pci.c
arch/tile/kernel/pci_gx.c
arch/x86/include/asm/pci.h
arch/x86/include/asm/topology.h
arch/x86/pci/acpi.c
arch/x86/pci/amd_bus.c
arch/x86/pci/bus_numa.c
arch/x86/pci/common.c
arch/x86/pci/fixup.c
arch/x86/pci/irq.c
arch/x86/pci/legacy.c
arch/x86/pci/numaq_32.c
arch/x86/pci/visws.c
drivers/acpi/numa.c
drivers/ata/ahci.c
drivers/bus/mvebu-mbus.c
drivers/gpu/drm/drm_fops.c
drivers/iommu/amd_iommu_types.h
drivers/message/i2o/iop.c
drivers/misc/mei/hw-me.h
drivers/misc/mic/card/mic_device.h
drivers/misc/mic/host/mic_device.h
drivers/pci/Makefile
drivers/pci/bus.c
drivers/pci/host-bridge.c
drivers/pci/host/Kconfig
drivers/pci/host/pci-imx6.c
drivers/pci/host/pci-mvebu.c
drivers/pci/host/pci-rcar-gen2.c
drivers/pci/host/pcie-designware.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_acpi.c
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/iov.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/rom.c
drivers/pci/search.c
drivers/pci/setup-res.c
drivers/pcmcia/yenta_socket.c
drivers/vfio/pci/vfio_pci_intrs.c
include/acpi/acpi_numa.h
include/linux/acpi.h
include/linux/ioport.h
include/linux/pci.h
kernel/resource.c
lib/vsprintf.c

index 86551cc72e034fc48e63c54c6e662954ca857372..2d91ae25198295dc8559d2ef8d00cae1b5314989 100644 (file)
@@ -68,10 +68,6 @@ To disable SR-IOV capability:
        echo  0 > \
         /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
 
-To notify SR-IOV core of Virtual Function Migration:
-(a) In the driver:
-       irqreturn_t pci_sriov_migration(struct pci_dev *dev);
-
 3.2 Usage example
 
 Following piece of code illustrates the usage of the SR-IOV API.
index edb4e0097b75eff056ea89d37146ec2fe77eadc7..076c35cd6cde7c2d782a46fe3942b8962369230e 100644 (file)
@@ -254,12 +254,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
        }
 }
 
-int
-pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-       return pci_enable_resources(dev, mask);
-}
-
 /*
  *  If we set up a device for bus mastering, we need to check the latency
  *  timer as certain firmware forgets to set it properly, as seen
index 317da88ae65b14f2bdd9145a3b552316f134c18a..d0d46786892cac86f5f8575f063d3637032292fd 100644 (file)
@@ -19,7 +19,7 @@
 static int debug_pci;
 
 /*
- * We can't use pci_find_device() here since we are
+ * We can't use pci_get_device() here since we are
  * called from interrupt context.
  */
 static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, int warn)
@@ -57,13 +57,10 @@ static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, in
 
 void pcibios_report_status(u_int status_mask, int warn)
 {
-       struct list_head *l;
-
-       list_for_each(l, &pci_root_buses) {
-               struct pci_bus *bus = pci_bus_b(l);
+       struct pci_bus *bus;
 
+       list_for_each_entry(bus, &pci_root_buses, node)
                pcibios_bus_report_status(bus, status_mask, warn);
-       }
 }
 
 /*
index c281217654487cb059e1e790c951c3a7dabdef22..67b1d16857593ddc083bf45cc8fd9e19d5430994 100644 (file)
@@ -88,7 +88,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
 
        /* Depth-First Search on bus tree */
        for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
-               bus = pci_bus_b(ln);
+               bus = list_entry(ln, struct pci_bus, node);
                if ((dev = bus->self)) {
                        for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
                                r = &dev->resource[idx];
index 30c43d39dede068c9f54448bc8e1f90917fe0c84..1a871b78e5709232f1f5f3e9aa8021cb4d02dd59 100644 (file)
@@ -1140,11 +1140,13 @@ sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
 
 #ifdef CONFIG_NUMA
        {
+               int node = ioc->node;
                struct page *page;
-               page = alloc_pages_exact_node(ioc->node == MAX_NUMNODES ?
-                                       numa_node_id() : ioc->node, flags,
-                                       get_order(size));
 
+               if (node == NUMA_NO_NODE)
+                       node = numa_node_id();
+
+               page = alloc_pages_exact_node(node, flags, get_order(size));
                if (unlikely(!page))
                        return NULL;
 
@@ -1914,7 +1916,7 @@ ioc_show(struct seq_file *s, void *v)
        seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n",
                ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF));
 #ifdef CONFIG_NUMA
-       if (ioc->node != MAX_NUMNODES)
+       if (ioc->node != NUMA_NO_NODE)
                seq_printf(s, "NUMA node       : %d\n", ioc->node);
 #endif
        seq_printf(s, "IOVA size       : %ld MB\n", ((ioc->pdir_size >> 3) * iovp_size)/(1024*1024));
@@ -2015,31 +2017,19 @@ sba_connect_bus(struct pci_bus *bus)
        printk(KERN_WARNING "No IOC for PCI Bus %04x:%02x in ACPI\n", pci_domain_nr(bus), bus->number);
 }
 
-#ifdef CONFIG_NUMA
 static void __init
 sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
 {
+#ifdef CONFIG_NUMA
        unsigned int node;
-       int pxm;
-
-       ioc->node = MAX_NUMNODES;
-
-       pxm = acpi_get_pxm(handle);
-
-       if (pxm < 0)
-               return;
-
-       node = pxm_to_node(pxm);
 
-       if (node >= MAX_NUMNODES || !node_online(node))
-               return;
+       node = acpi_get_node(handle);
+       if (node != NUMA_NO_NODE && !node_online(node))
+               node = NUMA_NO_NODE;
 
        ioc->node = node;
-       return;
-}
-#else
-#define sba_map_ioc_to_node(ioc, handle)
 #endif
+}
 
 static int
 acpi_sba_ioc_add(struct acpi_device *device,
index 71fbaaa495ccc18af5f33cdaef92c0ab228dad8e..7d41cc0898224ec2211a6e0304e71ac4bb269a5d 100644 (file)
@@ -98,7 +98,7 @@ struct pci_controller {
        struct acpi_device *companion;
        void *iommu;
        int segment;
-       int node;               /* nearest node with memory or -1 for global allocation */
+       int node;               /* nearest node with memory or NUMA_NO_NODE for global allocation */
 
        void *platform_data;
 };
index 467497ade45f82745129c384a638a9ea6b75378a..0d407b300762d5fd5e7224bdfc8dc910485603b2 100644 (file)
@@ -799,14 +799,9 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
  *  ACPI based hotplug CPU support
  */
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
-static
-int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
+static int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 {
 #ifdef CONFIG_ACPI_NUMA
-       int pxm_id;
-       int nid;
-
-       pxm_id = acpi_get_pxm(handle);
        /*
         * We don't have cpu-only-node hotadd. But if the system equips
         * SRAT table, pxm is already found and node is ready.
@@ -814,11 +809,10 @@ int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
         * This code here is for the system which doesn't have full SRAT
         * table for possible cpus.
         */
-       nid = acpi_map_pxm_to_node(pxm_id);
        node_cpuid[cpu].phys_id = physid;
-       node_cpuid[cpu].nid = nid;
+       node_cpuid[cpu].nid = acpi_get_node(handle);
 #endif
-       return (0);
+       return 0;
 }
 
 int additional_cpus __initdata = -1;
@@ -925,7 +919,7 @@ static acpi_status acpi_map_iosapic(acpi_handle handle, u32 depth,
        union acpi_object *obj;
        struct acpi_madt_io_sapic *iosapic;
        unsigned int gsi_base;
-       int pxm, node;
+       int node;
 
        /* Only care about objects w/ a method that returns the MADT */
        if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
@@ -952,17 +946,9 @@ static acpi_status acpi_map_iosapic(acpi_handle handle, u32 depth,
 
        kfree(buffer.pointer);
 
-       /*
-        * OK, it's an IOSAPIC MADT entry, look for a _PXM value to tell
-        * us which node to associate this with.
-        */
-       pxm = acpi_get_pxm(handle);
-       if (pxm < 0)
-               return AE_OK;
-
-       node = pxm_to_node(pxm);
-
-       if (node >= MAX_NUMNODES || !node_online(node) ||
+       /* OK, it's an IOSAPIC MADT entry; associate it with a node */
+       node = acpi_get_node(handle);
+       if (node == NUMA_NO_NODE || !node_online(node) ||
            cpumask_empty(cpumask_of_node(node)))
                return AE_OK;
 
index 5dc969dd4ac06fec04f308894bcfe27dfc324e68..eee069a0b539747da4d4d4b4d3065de1c5373be8 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/vgaarb.h>
 
 #include <asm/machvec.h>
 
  * IORESOURCE_ROM_SHADOW is used to associate the boot video
  * card with this copy. On laptops this copy has to be used since
  * the main ROM may be compressed or combined with another image.
- * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
- * is marked here since the boot video device will be the only enabled
- * video device at this point.
+ * See pci_map_rom() for use of this flag. Before marking the device
+ * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
+ * by either arch cde or vga-arbitration, if so only apply the fixup to this
+ * already determined primary video card.
  */
 
 static void pci_fixup_video(struct pci_dev *pdev)
@@ -35,9 +37,6 @@ static void pci_fixup_video(struct pci_dev *pdev)
                return;
        /* Maybe, this machine supports legacy memory map. */
 
-       if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
-               return;
-
        /* Is VGA routed to us? */
        bus = pdev->bus;
        while (bus) {
@@ -60,10 +59,14 @@ static void pci_fixup_video(struct pci_dev *pdev)
                }
                bus = bus->parent;
        }
-       pci_read_config_word(pdev, PCI_COMMAND, &config);
-       if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
-               pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-               dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
+       if (!vga_default_device() || pdev == vga_default_device()) {
+               pci_read_config_word(pdev, PCI_COMMAND, &config);
+               if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+                       pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+                       dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
+                       vga_set_default_device(pdev);
+               }
        }
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
+                               PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video);
index 9e4938d8ca4d297e331131a79d8458d97a27d256..291a582777cf3dd0320f4757ea1f9c1fc39dd17c 100644 (file)
@@ -126,7 +126,6 @@ static struct pci_controller *alloc_pci_controller(int seg)
                return NULL;
 
        controller->segment = seg;
-       controller->node = -1;
        return controller;
 }
 
@@ -430,19 +429,14 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
        struct pci_root_info *info = NULL;
        int busnum = root->secondary.start;
        struct pci_bus *pbus;
-       int pxm, ret;
+       int ret;
 
        controller = alloc_pci_controller(domain);
        if (!controller)
                return NULL;
 
        controller->companion = device;
-
-       pxm = acpi_get_pxm(device->handle);
-#ifdef CONFIG_NUMA
-       if (pxm >= 0)
-               controller->node = pxm_to_node(pxm);
-#endif
+       controller->node = acpi_get_node(device->handle);
 
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info) {
index 66804adcacf02f3430c31f5d1ba275e5d04da382..70996cc66aa228c688d298ade87fd31c5cedaaac 100644 (file)
@@ -1294,11 +1294,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-       return pci_enable_resources(dev, mask);
-}
-
 static void pcibios_setup_phb_resources(struct pci_controller *hose,
                                        struct list_head *resources)
 {
index a9e311f7a9dd58026e1fbd108ae1239415aa6153..2a4779091a5809a42b64d187224dc46da59fa07c 100644 (file)
@@ -208,7 +208,6 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
                          unsigned long in_devfn)
 {
        struct pci_controller* hose;
-       struct list_head *ln;
        struct pci_bus *bus = NULL;
        struct device_node *hose_node;
 
@@ -230,8 +229,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
         * used on pre-domains setup. We return the first match
         */
 
-       for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
-               bus = pci_bus_b(ln);
+       list_for_each_entry(bus, &pci_root_buses, node) {
                if (in_bus >= bus->number && in_bus <= bus->busn_res.end)
                        break;
                bus = NULL;
index efe61374f6eae3eda2447a351787958a2f562cf8..203cbf0dc101a7b4bb93aec27f8a89cf4f015ecb 100644 (file)
@@ -37,15 +37,15 @@ find_bus_among_children(struct pci_bus *bus,
                         struct device_node *dn)
 {
        struct pci_bus *child = NULL;
-       struct list_head *tmp;
+       struct pci_bus *tmp;
        struct device_node *busdn;
 
        busdn = pci_bus_to_OF_node(bus);
        if (busdn == dn)
                return bus;
 
-       list_for_each(tmp, &bus->children) {
-               child = find_bus_among_children(pci_bus_b(tmp), dn);
+       list_for_each_entry(tmp, &bus->children, node) {
+               child = find_bus_among_children(tmp, dn);
                if (child)
                        break;
        };
index 66670ff262a0b5b722aa2f20418f1dae3c2e389f..1df1d29ac81d3710caafad1f7ce0094f530d721d 100644 (file)
@@ -686,27 +686,13 @@ int pcibios_add_device(struct pci_dev *pdev)
 int pcibios_enable_device(struct pci_dev *pdev, int mask)
 {
        struct zpci_dev *zdev = get_zdev(pdev);
-       struct resource *res;
-       u16 cmd;
-       int i;
 
        zdev->pdev = pdev;
        zpci_debug_init_device(zdev);
        zpci_fmb_enable_device(zdev);
        zpci_map_resources(zdev);
 
-       pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-       for (i = 0; i < PCI_BAR_COUNT; i++) {
-               res = &pdev->resource[i];
-
-               if (res->flags & IORESOURCE_IO)
-                       return -EINVAL;
-
-               if (res->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-       pci_write_config_word(pdev, PCI_COMMAND, cmd);
-       return 0;
+       return pci_enable_resources(pdev, mask);
 }
 
 void pcibios_disable_device(struct pci_dev *pdev)
index 60ed3e1c4b753dd92ba4c58cc59def3079ef2050..1bc09ee7948f00a678d9564331dcdd2ae9cb7c78 100644 (file)
@@ -186,11 +186,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
        return start;
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-       return pci_enable_resources(dev, mask);
-}
-
 static void __init
 pcibios_bus_report_status_early(struct pci_channel *hose,
                                int top_bus, int current_bus,
index 88aaaa57bb6439270e6674ec8ad0d536fb538556..e16c4157e1ae1a504c754838caf499404894a6ce 100644 (file)
@@ -99,11 +99,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
        return res->start;
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-       return pci_enable_resources(dev, mask);
-}
-
 /* in/out routines taken from pcic.c
  *
  * This probably belongs here rather than ioport.c because
index a97a6452b812cdb9681d49fb4130ab3403ff3d2d..077b7bc437e5f6a54e5ad28e42e89e524001dbf0 100644 (file)
@@ -1064,18 +1064,6 @@ char *__init pcibios_setup(char *str)
        return str;
 }
 
-/*
- * Enable memory address decoding, as appropriate, for the
- * device described by the 'dev' struct.
- *
- * This is called from the generic PCI layer, and can be called
- * for bridges or endpoints.
- */
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-       return pci_enable_resources(dev, mask);
-}
-
 /*
  * Called for each device after PCI setup is done.
  * We initialize the PCI device capabilities conservatively, assuming that
index 1ac6114c9ea591e73c50d53d47d45592755d8c96..96ae4f4040bb359f8f3588f82f6595e41edbc501 100644 (file)
@@ -26,11 +26,6 @@ extern int pci_routeirq;
 extern int noioapicquirk;
 extern int noioapicreroute;
 
-/* scan a bus after allocating a pci_sysdata for it */
-extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
-                                           int node);
-extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
-
 #ifdef CONFIG_PCI
 
 #ifdef CONFIG_PCI_DOMAINS
@@ -70,7 +65,7 @@ extern unsigned long pci_mem_start;
 
 extern int pcibios_enabled;
 void pcibios_config_init(void);
-struct pci_bus *pcibios_scan_root(int bus);
+void pcibios_scan_root(int bus);
 
 void pcibios_set_master(struct pci_dev *dev);
 void pcibios_penalize_isa_irq(int irq, int active);
index b28097e4c8c3e1e941df963f49cd2db32d89589a..0e8f04f2c26fda3935093b7040dac783e621d71b 100644 (file)
@@ -132,19 +132,7 @@ static inline void arch_fix_phys_package_id(int num, u32 slot)
 }
 
 struct pci_bus;
+int x86_pci_root_bus_node(int bus);
 void x86_pci_root_bus_resources(int bus, struct list_head *resources);
 
-#ifdef CONFIG_NUMA
-extern int get_mp_bus_to_node(int busnum);
-extern void set_mp_bus_to_node(int busnum, int node);
-#else
-static inline int get_mp_bus_to_node(int busnum)
-{
-       return 0;
-}
-static inline void set_mp_bus_to_node(int busnum, int node)
-{
-}
-#endif
-
 #endif /* _ASM_X86_TOPOLOGY_H */
index 4f25ec0775526f45133d9087bc13fd4f76dfb24e..01edac6c5e1867c489b8e99dab52761dcd5b849a 100644 (file)
@@ -218,9 +218,8 @@ static void teardown_mcfg_map(struct pci_root_info *info)
 }
 #endif
 
-static acpi_status
-resource_to_addr(struct acpi_resource *resource,
-                       struct acpi_resource_address64 *addr)
+static acpi_status resource_to_addr(struct acpi_resource *resource,
+                                   struct acpi_resource_address64 *addr)
 {
        acpi_status status;
        struct acpi_resource_memory24 *memory24;
@@ -265,8 +264,7 @@ resource_to_addr(struct acpi_resource *resource,
        return AE_ERROR;
 }
 
-static acpi_status
-count_resource(struct acpi_resource *acpi_res, void *data)
+static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
 {
        struct pci_root_info *info = data;
        struct acpi_resource_address64 addr;
@@ -278,8 +276,7 @@ count_resource(struct acpi_resource *acpi_res, void *data)
        return AE_OK;
 }
 
-static acpi_status
-setup_resource(struct acpi_resource *acpi_res, void *data)
+static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
 {
        struct pci_root_info *info = data;
        struct resource *res;
@@ -435,9 +432,9 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)
        __release_pci_root_info(info);
 }
 
-static void
-probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
-                   int busnum, int domain)
+static void probe_pci_root_info(struct pci_root_info *info,
+                               struct acpi_device *device,
+                               int busnum, int domain)
 {
        size_t size;
 
@@ -473,16 +470,13 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
        struct acpi_device *device = root->device;
-       struct pci_root_info *info = NULL;
+       struct pci_root_info *info;
        int domain = root->segment;
        int busnum = root->secondary.start;
        LIST_HEAD(resources);
-       struct pci_bus *bus = NULL;
+       struct pci_bus *bus;
        struct pci_sysdata *sd;
        int node;
-#ifdef CONFIG_ACPI_NUMA
-       int pxm;
-#endif
 
        if (pci_ignore_seg)
                domain = 0;
@@ -494,19 +488,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
                return NULL;
        }
 
-       node = -1;
-#ifdef CONFIG_ACPI_NUMA
-       pxm = acpi_get_pxm(device->handle);
-       if (pxm >= 0)
-               node = pxm_to_node(pxm);
-       if (node != -1)
-               set_mp_bus_to_node(busnum, node);
-       else
-#endif
-               node = get_mp_bus_to_node(busnum);
+       node = acpi_get_node(device->handle);
+       if (node == NUMA_NO_NODE)
+               node = x86_pci_root_bus_node(busnum);
 
-       if (node != -1 && !node_online(node))
-               node = -1;
+       if (node != NUMA_NO_NODE && !node_online(node))
+               node = NUMA_NO_NODE;
 
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info) {
@@ -519,15 +506,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
        sd->domain = domain;
        sd->node = node;
        sd->companion = device;
-       /*
-        * Maybe the desired pci bus has been already scanned. In such case
-        * it is unnecessary to scan the pci bus with the given domain,busnum.
-        */
+
        bus = pci_find_bus(domain, busnum);
        if (bus) {
                /*
-                * If the desired bus exits, the content of bus->sysdata will
-                * be replaced by sd.
+                * If the desired bus has been scanned already, replace
+                * its bus->sysdata.
                 */
                memcpy(bus->sysdata, sd, sizeof(*sd));
                kfree(info);
@@ -572,15 +556,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
                        pcie_bus_configure_settings(child);
        }
 
-       if (bus && node != -1) {
-#ifdef CONFIG_ACPI_NUMA
-               if (pxm >= 0)
-                       dev_printk(KERN_DEBUG, &bus->dev,
-                                  "on NUMA node %d (pxm %d)\n", node, pxm);
-#else
+       if (bus && node != NUMA_NO_NODE)
                dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
-#endif
-       }
 
        return bus;
 }
index a48be98e9ded5a48be34fd8139d37a97a3748cc4..a313a7fb6b862e26b893ad8f5058e8767bf146c1 100644 (file)
@@ -44,15 +44,6 @@ static struct pci_root_info __init *find_pci_root_info(int node, int link)
        return NULL;
 }
 
-static void __init set_mp_bus_range_to_node(int min_bus, int max_bus, int node)
-{
-#ifdef CONFIG_NUMA
-       int j;
-
-       for (j = min_bus; j <= max_bus; j++)
-               set_mp_bus_to_node(j, node);
-#endif
-}
 /**
  * early_fill_mp_bus_to_node()
  * called before pcibios_scan_root and pci_scan_bus
@@ -117,7 +108,6 @@ static int __init early_fill_mp_bus_info(void)
                min_bus = (reg >> 16) & 0xff;
                max_bus = (reg >> 24) & 0xff;
                node = (reg >> 4) & 0x07;
-               set_mp_bus_range_to_node(min_bus, max_bus, node);
                link = (reg >> 8) & 0x03;
 
                info = alloc_pci_root_info(min_bus, max_bus, node, link);
index c2735feb2508148ec16efab887ec1aab2dcc0aec..f3a2cfc14125bbb387d7eae474304a59cf8b2ef1 100644 (file)
@@ -10,9 +10,6 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
 {
        struct pci_root_info *info;
 
-       if (list_empty(&pci_root_infos))
-               return NULL;
-
        list_for_each_entry(info, &pci_root_infos, list)
                if (info->busn.start == bus)
                        return info;
@@ -20,6 +17,16 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
        return NULL;
 }
 
+int x86_pci_root_bus_node(int bus)
+{
+       struct pci_root_info *info = x86_find_pci_root_info(bus);
+
+       if (!info)
+               return NUMA_NO_NODE;
+
+       return info->node;
+}
+
 void x86_pci_root_bus_resources(int bus, struct list_head *resources)
 {
        struct pci_root_info *info = x86_find_pci_root_info(bus);
index 981c2dbd72cc45e6d77a98dab694d87b0523696a..d491deddebae580d0afa6fb64e62fd9b44b3d665 100644 (file)
@@ -456,19 +456,25 @@ void __init dmi_check_pciprobe(void)
        dmi_check_system(pciprobe_dmi_table);
 }
 
-struct pci_bus *pcibios_scan_root(int busnum)
+void pcibios_scan_root(int busnum)
 {
-       struct pci_bus *bus = NULL;
+       struct pci_bus *bus;
+       struct pci_sysdata *sd;
+       LIST_HEAD(resources);
 
-       while ((bus = pci_find_next_bus(bus)) != NULL) {
-               if (bus->number == busnum) {
-                       /* Already scanned */
-                       return bus;
-               }
+       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+       if (!sd) {
+               printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busnum);
+               return;
+       }
+       sd->node = x86_pci_root_bus_node(busnum);
+       x86_pci_root_bus_resources(busnum, &resources);
+       printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
+       bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
+       if (!bus) {
+               pci_free_resource_list(&resources);
+               kfree(sd);
        }
-
-       return pci_scan_bus_on_node(busnum, &pci_root_ops,
-                                       get_mp_bus_to_node(busnum));
 }
 
 void __init pcibios_set_cache_line_size(void)
@@ -677,105 +683,3 @@ int pci_ext_cfg_avail(void)
        else
                return 0;
 }
-
-struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
-{
-       LIST_HEAD(resources);
-       struct pci_bus *bus = NULL;
-       struct pci_sysdata *sd;
-
-       /*
-        * Allocate per-root-bus (not per bus) arch-specific data.
-        * TODO: leak; this memory is never freed.
-        * It's arguable whether it's worth the trouble to care.
-        */
-       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
-       if (!sd) {
-               printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno);
-               return NULL;
-       }
-       sd->node = node;
-       x86_pci_root_bus_resources(busno, &resources);
-       printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busno);
-       bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources);
-       if (!bus) {
-               pci_free_resource_list(&resources);
-               kfree(sd);
-       }
-
-       return bus;
-}
-
-struct pci_bus *pci_scan_bus_with_sysdata(int busno)
-{
-       return pci_scan_bus_on_node(busno, &pci_root_ops, -1);
-}
-
-/*
- * NUMA info for PCI busses
- *
- * Early arch code is responsible for filling in reasonable values here.
- * A node id of "-1" means "use current node".  In other words, if a bus
- * has a -1 node id, it's not tightly coupled to any particular chunk
- * of memory (as is the case on some Nehalem systems).
- */
-#ifdef CONFIG_NUMA
-
-#define BUS_NR 256
-
-#ifdef CONFIG_X86_64
-
-static int mp_bus_to_node[BUS_NR] = {
-       [0 ... BUS_NR - 1] = -1
-};
-
-void set_mp_bus_to_node(int busnum, int node)
-{
-       if (busnum >= 0 &&  busnum < BUS_NR)
-               mp_bus_to_node[busnum] = node;
-}
-
-int get_mp_bus_to_node(int busnum)
-{
-       int node = -1;
-
-       if (busnum < 0 || busnum > (BUS_NR - 1))
-               return node;
-
-       node = mp_bus_to_node[busnum];
-
-       /*
-        * let numa_node_id to decide it later in dma_alloc_pages
-        * if there is no ram on that node
-        */
-       if (node != -1 && !node_online(node))
-               node = -1;
-
-       return node;
-}
-
-#else /* CONFIG_X86_32 */
-
-static int mp_bus_to_node[BUS_NR] = {
-       [0 ... BUS_NR - 1] = -1
-};
-
-void set_mp_bus_to_node(int busnum, int node)
-{
-       if (busnum >= 0 &&  busnum < BUS_NR)
-       mp_bus_to_node[busnum] = (unsigned char) node;
-}
-
-int get_mp_bus_to_node(int busnum)
-{
-       int node;
-
-       if (busnum < 0 || busnum > (BUS_NR - 1))
-               return 0;
-       node = mp_bus_to_node[busnum];
-       return node;
-}
-
-#endif /* CONFIG_X86_32 */
-
-#endif /* CONFIG_NUMA */
index bca9e85daaa55d04d3e174657264920280be4636..94ae9ae9574fe1678eab5f65c219293a871c8c8a 100644 (file)
@@ -25,9 +25,9 @@ static void pci_fixup_i450nx(struct pci_dev *d)
                dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno,
                        suba, subb);
                if (busno)
-                       pci_scan_bus_with_sysdata(busno);       /* Bus A */
+                       pcibios_scan_root(busno);       /* Bus A */
                if (suba < subb)
-                       pci_scan_bus_with_sysdata(suba+1);      /* Bus B */
+                       pcibios_scan_root(suba+1);      /* Bus B */
        }
        pcibios_last_bus = -1;
 }
@@ -42,7 +42,7 @@ static void pci_fixup_i450gx(struct pci_dev *d)
        u8 busno;
        pci_read_config_byte(d, 0x4a, &busno);
        dev_info(&d->dev, "i440KX/GX host bridge; secondary bus %02x\n", busno);
-       pci_scan_bus_with_sysdata(busno);
+       pcibios_scan_root(busno);
        pcibios_last_bus = -1;
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);
@@ -313,9 +313,10 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,       PCI_DEVICE_ID_INTEL_MCH_PC1,    pcie_r
  * IORESOURCE_ROM_SHADOW is used to associate the boot video
  * card with this copy. On laptops this copy has to be used since
  * the main ROM may be compressed or combined with another image.
- * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
- * is marked here since the boot video device will be the only enabled
- * video device at this point.
+ * See pci_map_rom() for use of this flag. Before marking the device
+ * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
+ * by either arch cde or vga-arbitration, if so only apply the fixup to this
+ * already determined primary video card.
  */
 
 static void pci_fixup_video(struct pci_dev *pdev)
@@ -346,12 +347,13 @@ static void pci_fixup_video(struct pci_dev *pdev)
                }
                bus = bus->parent;
        }
-       pci_read_config_word(pdev, PCI_COMMAND, &config);
-       if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
-               pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-               dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
-               if (!vga_default_device())
+       if (!vga_default_device() || pdev == vga_default_device()) {
+               pci_read_config_word(pdev, PCI_COMMAND, &config);
+               if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+                       pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+                       dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
                        vga_set_default_device(pdev);
+               }
        }
 }
 DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
index 372e9b8989b322e891cacc192744419a80940d8a..84112f55dd7a95d83232d9416b7e9196a55dee30 100644 (file)
@@ -136,13 +136,9 @@ static void __init pirq_peer_trick(void)
                busmap[e->bus] = 1;
        }
        for (i = 1; i < 256; i++) {
-               int node;
                if (!busmap[i] || pci_find_bus(0, i))
                        continue;
-               node = get_mp_bus_to_node(i);
-               if (pci_scan_bus_on_node(i, &pci_root_ops, node))
-                       printk(KERN_INFO "PCI: Discovered primary peer "
-                              "bus %02x [IRQ]\n", i);
+               pcibios_scan_root(i);
        }
        pcibios_last_bus = -1;
 }
index 4db96fb1c23260394bb7c4f44775ee1c1f0c6f2d..5b662c0faf8c2e1848d15d4dced105db9988c7c8 100644 (file)
@@ -37,19 +37,17 @@ int __init pci_legacy_init(void)
 void pcibios_scan_specific_bus(int busn)
 {
        int devfn;
-       long node;
        u32 l;
 
        if (pci_find_bus(0, busn))
                return;
 
-       node = get_mp_bus_to_node(busn);
        for (devfn = 0; devfn < 256; devfn += 8) {
                if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) &&
                    l != 0x0000 && l != 0xffff) {
                        DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l);
                        printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn);
-                       pci_scan_bus_on_node(busn, &pci_root_ops, node);
+                       pcibios_scan_root(busn);
                        return;
                }
        }
index 72c229f9ebcf68aca50cd7bbb5f668c009df8c5e..080eb0374fff199ce4f933a1d4a770974e9863ca 100644 (file)
@@ -135,11 +135,11 @@ static void pci_fixup_i450nx(struct pci_dev *d)
                        pxb, busno, suba, subb);
                if (busno) {
                        /* Bus A */
-                       pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
+                       pcibios_scan_root(QUADLOCAL2BUS(quad, busno));
                }
                if (suba < subb) {
                        /* Bus B */
-                       pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1));
+                       pcibios_scan_root(QUADLOCAL2BUS(quad, suba+1));
                }
        }
        pcibios_last_bus = -1;
@@ -159,7 +159,7 @@ int __init pci_numaq_init(void)
                                continue;
                        printk("Scanning PCI bus %d for quad %d\n", 
                                QUADLOCAL2BUS(quad,0), quad);
-                       pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0));
+                       pcibios_scan_root(QUADLOCAL2BUS(quad, 0));
                }
        return 0;
 }
index 3e6d2a6db86681d3a1731f7a7956711bdcd36e50..cd9d4d1681d28e6ec75550da99bd716d4608715e 100644 (file)
@@ -78,8 +78,8 @@ int __init pci_visws_init(void)
                "bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0);
 
        raw_pci_ops = &pci_direct_conf1;
-       pci_scan_bus_with_sysdata(pci_bus0);
-       pci_scan_bus_with_sysdata(pci_bus1);
+       pcibios_scan_root(pci_bus0);
+       pcibios_scan_root(pci_bus1);
        pci_fixup_irqs(pci_common_swizzle, visws_map_irq);
        pcibios_resource_survey();
        /* Request bus scan */
index 9e6816ef280ab7a5def6586cfabd3f60b7cd0ccb..24b5476449a110ad8c16ef6a246169be06e41b65 100644 (file)
@@ -60,7 +60,7 @@ int node_to_pxm(int node)
        return node_to_pxm_map[node];
 }
 
-void __acpi_map_pxm_to_node(int pxm, int node)
+static void __acpi_map_pxm_to_node(int pxm, int node)
 {
        if (pxm_to_node_map[pxm] == NUMA_NO_NODE || node < pxm_to_node_map[pxm])
                pxm_to_node_map[pxm] = node;
@@ -193,7 +193,7 @@ static int __init acpi_parse_slit(struct acpi_table_header *table)
        return 0;
 }
 
-void __init __attribute__ ((weak))
+void __init __weak
 acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
 {
        printk(KERN_WARNING PREFIX
@@ -314,7 +314,7 @@ int __init acpi_numa_init(void)
        return 0;
 }
 
-int acpi_get_pxm(acpi_handle h)
+static int acpi_get_pxm(acpi_handle h)
 {
        unsigned long long pxm;
        acpi_status status;
@@ -331,14 +331,14 @@ int acpi_get_pxm(acpi_handle h)
        return -1;
 }
 
-int acpi_get_node(acpi_handle *handle)
+int acpi_get_node(acpi_handle handle)
 {
-       int pxm, node = NUMA_NO_NODE;
+       int pxm;
 
        pxm = acpi_get_pxm(handle);
-       if (pxm >= 0 && pxm < MAX_PXM_DOMAINS)
-               node = acpi_map_pxm_to_node(pxm);
+       if (pxm < 0 || pxm >= MAX_PXM_DOMAINS)
+               return NUMA_NO_NODE;
 
-       return node;
+       return acpi_map_pxm_to_node(pxm);
 }
 EXPORT_SYMBOL(acpi_get_node);
index a52a5b662f35ecceb992fd41943ef5f636834838..5a0bf8ed649b8cf9266530ef309aec89a54f99ef 100644 (file)
@@ -1166,13 +1166,13 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
 static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
                         struct ahci_host_priv *hpriv)
 {
-       int rc, nvec;
+       int nvec;
 
        if (hpriv->flags & AHCI_HFLAG_NO_MSI)
                goto intx;
 
-       rc = pci_msi_vec_count(pdev);
-       if (rc < 0)
+       nvec = pci_msi_vec_count(pdev);
+       if (nvec < 0)
                goto intx;
 
        /*
@@ -1180,21 +1180,19 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
         * Message mode could be enforced. In this case assume that advantage
         * of multipe MSIs is negated and use single MSI mode instead.
         */
-       if (rc < n_ports)
+       if (nvec < n_ports)
                goto single_msi;
 
-       nvec = rc;
-       rc = pci_enable_msi_block(pdev, nvec);
-       if (rc < 0)
-               goto intx;
-       else if (rc > 0)
+       nvec = pci_enable_msi_range(pdev, nvec, nvec);
+       if (nvec == -ENOSPC)
                goto single_msi;
+       else if (nvec < 0)
+               goto intx;
 
        return nvec;
 
 single_msi:
-       rc = pci_enable_msi(pdev);
-       if (rc)
+       if (pci_enable_msi(pdev))
                goto intx;
        return 1;
 
index 725c46162bbd1cb0ad05624502ad16030e5991ca..2ac754e18bcf1af6a285c5de9f6df867f4e83298 100644 (file)
@@ -870,14 +870,14 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
        ret = of_property_read_u32_array(np, "pcie-mem-aperture", reg, ARRAY_SIZE(reg));
        if (!ret) {
                mem->start = reg[0];
-               mem->end = mem->start + reg[1];
+               mem->end = mem->start + reg[1] - 1;
                mem->flags = IORESOURCE_MEM;
        }
 
        ret = of_property_read_u32_array(np, "pcie-io-aperture", reg, ARRAY_SIZE(reg));
        if (!ret) {
                io->start = reg[0];
-               io->end = io->start + reg[1];
+               io->end = io->start + reg[1] - 1;
                io->flags = IORESOURCE_IO;
        }
 }
index 7f2af9aca03895b97c75af76968093a61930b501..309023f12d7ff7ab5413baf14af4f580c2a5ccbc 100644 (file)
@@ -319,7 +319,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
                        pci_dev_put(pci_dev);
                }
                if (!dev->hose) {
-                       struct pci_bus *b = pci_bus_b(pci_root_buses.next);
+                       struct pci_bus *b = list_entry(pci_root_buses.next,
+                               struct pci_bus, node);
                        if (b)
                                dev->hose = b->sysdata;
                }
index e400fbe411dead310bada51fb74d1475eab55bd0..cff039df056ee614ea578a2cf678c1a8b72c39e4 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
+#include <linux/irqreturn.h>
 
 /*
  * Maximum number of IOMMUs supported
index a8c08f332da04c596cf1ae3aa33c2a09f1a4f892..92752fb5b2d3d8b41364261a99eb44938e33be32 100644 (file)
@@ -652,6 +652,44 @@ static int i2o_iop_activate(struct i2o_controller *c)
        return i2o_hrt_get(c);
 };
 
+static void i2o_res_alloc(struct i2o_controller *c, unsigned long flags)
+{
+       i2o_status_block *sb = c->status_block.virt;
+       struct resource *res = &c->mem_resource;
+       resource_size_t size, align;
+       int err;
+
+       res->name = c->pdev->bus->name;
+       res->flags = flags;
+       res->start = 0;
+       res->end = 0;
+       osm_info("%s: requires private memory resources.\n", c->name);
+
+       if (flags & IORESOURCE_MEM) {
+               size = sb->desired_mem_size;
+               align = 1 << 20;        /* unspecified, use 1Mb and play safe */
+       } else {
+               size = sb->desired_io_size;
+               align = 1 << 12;        /* unspecified, use 4Kb and play safe */
+       }
+
+       err = pci_bus_alloc_resource(c->pdev->bus, res, size, align, 0, 0,
+                                    NULL, NULL);
+       if (err < 0)
+               return;
+
+       if (flags & IORESOURCE_MEM) {
+               c->mem_alloc = 1;
+               sb->current_mem_size = resource_size(res);
+               sb->current_mem_base = res->start;
+       } else if (flags & IORESOURCE_IO) {
+               c->io_alloc = 1;
+               sb->current_io_size = resource_size(res);
+               sb->current_io_base = res->start;
+       }
+       osm_info("%s: allocated PCI space %pR\n", c->name, res);
+}
+
 /**
  *     i2o_iop_systab_set - Set the I2O System Table of the specified IOP
  *     @c: I2O controller to which the system table should be send
@@ -665,52 +703,13 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
        struct i2o_message *msg;
        i2o_status_block *sb = c->status_block.virt;
        struct device *dev = &c->pdev->dev;
-       struct resource *root;
        int rc;
 
-       if (sb->current_mem_size < sb->desired_mem_size) {
-               struct resource *res = &c->mem_resource;
-               res->name = c->pdev->bus->name;
-               res->flags = IORESOURCE_MEM;
-               res->start = 0;
-               res->end = 0;
-               osm_info("%s: requires private memory resources.\n", c->name);
-               root = pci_find_parent_resource(c->pdev, res);
-               if (root == NULL)
-                       osm_warn("%s: Can't find parent resource!\n", c->name);
-               if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20,     /* Unspecified, so use 1Mb and play safe */
-                                             NULL, NULL) >= 0) {
-                       c->mem_alloc = 1;
-                       sb->current_mem_size = resource_size(res);
-                       sb->current_mem_base = res->start;
-                       osm_info("%s: allocated %llu bytes of PCI memory at "
-                               "0x%016llX.\n", c->name,
-                               (unsigned long long)resource_size(res),
-                               (unsigned long long)res->start);
-               }
-       }
+       if (sb->current_mem_size < sb->desired_mem_size)
+               i2o_res_alloc(c, IORESOURCE_MEM);
 
-       if (sb->current_io_size < sb->desired_io_size) {
-               struct resource *res = &c->io_resource;
-               res->name = c->pdev->bus->name;
-               res->flags = IORESOURCE_IO;
-               res->start = 0;
-               res->end = 0;
-               osm_info("%s: requires private memory resources.\n", c->name);
-               root = pci_find_parent_resource(c->pdev, res);
-               if (root == NULL)
-                       osm_warn("%s: Can't find parent resource!\n", c->name);
-               if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20,        /* Unspecified, so use 1Mb and play safe */
-                                             NULL, NULL) >= 0) {
-                       c->io_alloc = 1;
-                       sb->current_io_size = resource_size(res);
-                       sb->current_mem_base = res->start;
-                       osm_info("%s: allocated %llu bytes of PCI I/O at "
-                               "0x%016llX.\n", c->name,
-                               (unsigned long long)resource_size(res),
-                               (unsigned long long)res->start);
-               }
-       }
+       if (sb->current_io_size < sb->desired_io_size)
+               i2o_res_alloc(c, IORESOURCE_IO);
 
        msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
        if (IS_ERR(msg))
index 80bd829fbd9ac4f39332a5053cecbce31ff485da..893d5119fa9bb6eec02d6b82f4452611f4637f7b 100644 (file)
@@ -20,6 +20,7 @@
 #define _MEI_INTERFACE_H_
 
 #include <linux/mei.h>
+#include <linux/irqreturn.h>
 #include "mei_dev.h"
 #include "client.h"
 
index 347b9b3b791620767c23ca6a93ccd5121784da53..306f502be95e2b2d7449c0f042eec14d8bbe6959 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <linux/workqueue.h>
 #include <linux/io.h>
+#include <linux/irqreturn.h>
 
 /**
  * struct mic_intr_info - Contains h/w specific interrupt sources info
index 1a6edce2ecde56fc65dbeaaa6a4ead627478a73e..0398c696d25758fa9fe36d1a15fd97cad75b27da 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/cdev.h>
 #include <linux/idr.h>
 #include <linux/notifier.h>
+#include <linux/irqreturn.h>
 
 #include "mic_intr.h"
 
index 17d2b07ee67c2db583a650b2ffbada55324faa53..e2501ac6fe84808ad4816ce8bf2cd14d27001b11 100644 (file)
@@ -33,21 +33,15 @@ obj-$(CONFIG_PCI_IOV) += iov.o
 #
 # Some architectures use the generic PCI setup functions
 #
-obj-$(CONFIG_X86) += setup-bus.o
-obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
-obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
-obj-$(CONFIG_UNICORE32) += setup-bus.o setup-irq.o
-obj-$(CONFIG_PARISC) += setup-bus.o
-obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
-obj-$(CONFIG_PPC) += setup-bus.o
-obj-$(CONFIG_FRV) += setup-bus.o
-obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
+obj-$(CONFIG_ALPHA) += setup-irq.o
+obj-$(CONFIG_ARM) += setup-irq.o
+obj-$(CONFIG_UNICORE32) += setup-irq.o
+obj-$(CONFIG_SUPERH) += setup-irq.o
+obj-$(CONFIG_MIPS) += setup-irq.o
 obj-$(CONFIG_X86_VISWS) += setup-irq.o
-obj-$(CONFIG_MN10300) += setup-bus.o
-obj-$(CONFIG_MICROBLAZE) += setup-bus.o
-obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
-obj-$(CONFIG_SPARC_LEON) += setup-bus.o setup-irq.o
-obj-$(CONFIG_M68K) += setup-bus.o setup-irq.o
+obj-$(CONFIG_TILE) += setup-irq.o
+obj-$(CONFIG_SPARC_LEON) += setup-irq.o
+obj-$(CONFIG_M68K) += setup-irq.o
 
 #
 # ACPI Related PCI FW Functions
index 38901665c77086a20a6bd1cd087f24971c0d172b..fb8aed307c2821d70404dbac467fc94d914ed7e0 100644 (file)
@@ -132,7 +132,7 @@ static void pci_clip_resource_to_region(struct pci_bus *bus,
 
 static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
                resource_size_t size, resource_size_t align,
-               resource_size_t min, unsigned int type_mask,
+               resource_size_t min, unsigned long type_mask,
                resource_size_t (*alignf)(void *,
                                          const struct resource *,
                                          resource_size_t,
@@ -144,7 +144,7 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
        struct resource *r, avail;
        resource_size_t max;
 
-       type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
+       type_mask |= IORESOURCE_TYPE_BITS;
 
        pci_bus_for_each_resource(bus, r, i) {
                if (!r)
@@ -200,7 +200,7 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
  */
 int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
                resource_size_t size, resource_size_t align,
-               resource_size_t min, unsigned int type_mask,
+               resource_size_t min, unsigned long type_mask,
                resource_size_t (*alignf)(void *,
                                          const struct resource *,
                                          resource_size_t,
index 06ace6248c61d9cb02e8618c52e691b251c02580..47aaf22d814e195f7d397237a59267334ccf5ca2 100644 (file)
@@ -32,11 +32,6 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
        bridge->release_data = release_data;
 }
 
-static bool resource_contains(struct resource *res1, struct resource *res2)
-{
-       return res1->start <= res2->start && res1->end >= res2->end;
-}
-
 void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
                             struct resource *res)
 {
@@ -45,9 +40,6 @@ void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
        resource_size_t offset = 0;
 
        list_for_each_entry(window, &bridge->windows, list) {
-               if (resource_type(res) != resource_type(window->res))
-                       continue;
-
                if (resource_contains(window->res, res)) {
                        offset = window->offset;
                        break;
index 47d46c6d84680ba81094de38911a821fb347066e..a6f67ec8882f1f4eab68aad1f64244f55df15738 100644 (file)
@@ -27,7 +27,7 @@ config PCI_TEGRA
 
 config PCI_RCAR_GEN2
        bool "Renesas R-Car Gen2 Internal PCI controller"
-       depends on ARM && (ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST)
+       depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
        help
          Say Y here if you want internal PCI support on R-Car Gen2 SoC.
          There are 3 internal PCI controllers available with a single
index e8663a8c3406a0cb73b5c4a2e1f7380e7fc9f898..ee082509b0baa730b90a6c0111673214889604dd 100644 (file)
@@ -424,20 +424,40 @@ static void imx6_pcie_reset_phy(struct pcie_port *pp)
 
 static int imx6_pcie_link_up(struct pcie_port *pp)
 {
-       u32 rc, ltssm, rx_valid;
+       u32 rc, debug_r0, rx_valid;
+       int count = 5;
 
        /*
-        * Test if the PHY reports that the link is up and also that
-        * the link training finished.  It might happen that the PHY
-        * reports the link is already up, but the link training bit
-        * is still set, so make sure to check the training is done
-        * as well here.
+        * Test if the PHY reports that the link is up and also that the LTSSM
+        * training finished. There are three possible states of the link when
+        * this code is called:
+        * 1) The link is DOWN (unlikely)
+        *     The link didn't come up yet for some reason. This usually means
+        *     we have a real problem somewhere. Reset the PHY and exit. This
+        *     state calls for inspection of the DEBUG registers.
+        * 2) The link is UP, but still in LTSSM training
+        *     Wait for the training to finish, which should take a very short
+        *     time. If the training does not finish, we have a problem and we
+        *     need to inspect the DEBUG registers. If the training does finish,
+        *     the link is up and operating correctly.
+        * 3) The link is UP and no longer in LTSSM training
+        *     The link is up and operating correctly.
         */
-       rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
-       if ((rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) &&
-           !(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
-               return 1;
-
+       while (1) {
+               rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
+               if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP))
+                       break;
+               if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
+                       return 1;
+               if (!count--)
+                       break;
+               dev_dbg(pp->dev, "Link is up, but still in training\n");
+               /*
+                * Wait a little bit, then re-check if the link finished
+                * the training.
+                */
+               usleep_range(1000, 2000);
+       }
        /*
         * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
         * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
@@ -446,15 +466,16 @@ static int imx6_pcie_link_up(struct pcie_port *pp)
         * to gen2 is stuck
         */
        pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
-       ltssm = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0) & 0x3F;
+       debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0);
 
        if (rx_valid & 0x01)
                return 0;
 
-       if (ltssm != 0x0d)
+       if ((debug_r0 & 0x3f) != 0x0d)
                return 0;
 
        dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
+       dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc);
 
        imx6_pcie_reset_phy(pp);
 
index 0e79665afd445ebb8e6198a274960978c58c619e..d3d1cfd51e095f058404d96f063df76d227bd652 100644 (file)
@@ -101,7 +101,9 @@ struct mvebu_pcie {
        struct mvebu_pcie_port *ports;
        struct msi_chip *msi;
        struct resource io;
+       char io_name[30];
        struct resource realio;
+       char mem_name[30];
        struct resource mem;
        struct resource busn;
        int nports;
@@ -672,10 +674,30 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
 {
        struct mvebu_pcie *pcie = sys_to_pcie(sys);
        int i;
+       int domain = 0;
 
-       if (resource_size(&pcie->realio) != 0)
+#ifdef CONFIG_PCI_DOMAINS
+       domain = sys->domain;
+#endif
+
+       snprintf(pcie->mem_name, sizeof(pcie->mem_name), "PCI MEM %04x",
+                domain);
+       pcie->mem.name = pcie->mem_name;
+
+       snprintf(pcie->io_name, sizeof(pcie->io_name), "PCI I/O %04x", domain);
+       pcie->realio.name = pcie->io_name;
+
+       if (request_resource(&iomem_resource, &pcie->mem))
+               return 0;
+
+       if (resource_size(&pcie->realio) != 0) {
+               if (request_resource(&ioport_resource, &pcie->realio)) {
+                       release_resource(&pcie->mem);
+                       return 0;
+               }
                pci_add_resource_offset(&sys->resources, &pcie->realio,
                                        sys->io_offset);
+       }
        pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
        pci_add_resource(&sys->resources, &pcie->busn);
 
@@ -797,7 +819,7 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
 
        for (i = 0; i < nranges; i++) {
                u32 flags = of_read_number(range, 1);
-               u32 slot = of_read_number(range, 2);
+               u32 slot = of_read_number(range + 1, 1);
                u64 cpuaddr = of_read_number(range + na, pna);
                unsigned long rtype;
 
index ceec147baec3560abf5cc07198ab3cc6b1d32d43..fd3e3ab56509125db9e6d25b1b2288eaccda60fd 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/sizes.h>
 #include <linux/slab.h>
 
 /* AHB-PCI Bridge PCI communication registers */
 
 #define RCAR_PCI_INT_ENABLE_REG                (RCAR_AHBPCI_PCICOM_OFFSET + 0x20)
 #define RCAR_PCI_INT_STATUS_REG                (RCAR_AHBPCI_PCICOM_OFFSET + 0x24)
+#define RCAR_PCI_INT_SIGTABORT         (1 << 0)
+#define RCAR_PCI_INT_SIGRETABORT       (1 << 1)
+#define RCAR_PCI_INT_REMABORT          (1 << 2)
+#define RCAR_PCI_INT_PERR              (1 << 3)
+#define RCAR_PCI_INT_SIGSERR           (1 << 4)
+#define RCAR_PCI_INT_RESERR            (1 << 5)
+#define RCAR_PCI_INT_WIN1ERR           (1 << 12)
+#define RCAR_PCI_INT_WIN2ERR           (1 << 13)
 #define RCAR_PCI_INT_A                 (1 << 16)
 #define RCAR_PCI_INT_B                 (1 << 17)
 #define RCAR_PCI_INT_PME               (1 << 19)
+#define RCAR_PCI_INT_ALLERRORS (RCAR_PCI_INT_SIGTABORT         | \
+                               RCAR_PCI_INT_SIGRETABORT        | \
+                               RCAR_PCI_INT_SIGRETABORT        | \
+                               RCAR_PCI_INT_REMABORT           | \
+                               RCAR_PCI_INT_PERR               | \
+                               RCAR_PCI_INT_SIGSERR            | \
+                               RCAR_PCI_INT_RESERR             | \
+                               RCAR_PCI_INT_WIN1ERR            | \
+                               RCAR_PCI_INT_WIN2ERR)
 
 #define RCAR_AHB_BUS_CTR_REG           (RCAR_AHBPCI_PCICOM_OFFSET + 0x30)
 #define RCAR_AHB_BUS_MMODE_HTRANS      (1 << 0)
@@ -74,9 +92,6 @@
 
 #define RCAR_PCI_UNIT_REV_REG          (RCAR_AHBPCI_PCICOM_OFFSET + 0x48)
 
-/* Number of internal PCI controllers */
-#define RCAR_PCI_NR_CONTROLLERS                3
-
 struct rcar_pci_priv {
        struct device *dev;
        void __iomem *reg;
@@ -84,6 +99,7 @@ struct rcar_pci_priv {
        struct resource mem_res;
        struct resource *cfg_res;
        int irq;
+       unsigned long window_size;
 };
 
 /* PCI configuration space operations */
@@ -102,6 +118,10 @@ static void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn,
        if (slot > 2)
                return NULL;
 
+       /* bridge logic only has registers to 0x40 */
+       if (slot == 0x0 && where >= 0x40)
+               return NULL;
+
        val = slot ? RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG :
                     RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG;
 
@@ -156,7 +176,7 @@ static int rcar_pci_write_config(struct pci_bus *bus, unsigned int devfn,
 }
 
 /* PCI interrupt mapping */
-static int __init rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        struct pci_sys_data *sys = dev->bus->sysdata;
        struct rcar_pci_priv *priv = sys->private_data;
@@ -164,8 +184,48 @@ static int __init rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return priv->irq;
 }
 
+#ifdef CONFIG_PCI_DEBUG
+/* if debug enabled, then attach an error handler irq to the bridge */
+
+static irqreturn_t rcar_pci_err_irq(int irq, void *pw)
+{
+       struct rcar_pci_priv *priv = pw;
+       u32 status = ioread32(priv->reg + RCAR_PCI_INT_STATUS_REG);
+
+       if (status & RCAR_PCI_INT_ALLERRORS) {
+               dev_err(priv->dev, "error irq: status %08x\n", status);
+
+               /* clear the error(s) */
+               iowrite32(status & RCAR_PCI_INT_ALLERRORS,
+                         priv->reg + RCAR_PCI_INT_STATUS_REG);
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_NONE;
+}
+
+static void rcar_pci_setup_errirq(struct rcar_pci_priv *priv)
+{
+       int ret;
+       u32 val;
+
+       ret = devm_request_irq(priv->dev, priv->irq, rcar_pci_err_irq,
+                              IRQF_SHARED, "error irq", priv);
+       if (ret) {
+               dev_err(priv->dev, "cannot claim IRQ for error handling\n");
+               return;
+       }
+
+       val = ioread32(priv->reg + RCAR_PCI_INT_ENABLE_REG);
+       val |= RCAR_PCI_INT_ALLERRORS;
+       iowrite32(val, priv->reg + RCAR_PCI_INT_ENABLE_REG);
+}
+#else
+static inline void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) { }
+#endif
+
 /* PCI host controller setup */
-static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
+static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
 {
        struct rcar_pci_priv *priv = sys->private_data;
        void __iomem *reg = priv->reg;
@@ -183,10 +243,31 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
        iowrite32(val, reg + RCAR_USBCTR_REG);
        udelay(4);
 
-       /* De-assert reset and set PCIAHB window1 size to 1GB */
+       /* De-assert reset and reset PCIAHB window1 size */
        val &= ~(RCAR_USBCTR_PCIAHB_WIN1_MASK | RCAR_USBCTR_PCICLK_MASK |
                 RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST);
-       iowrite32(val | RCAR_USBCTR_PCIAHB_WIN1_1G, reg + RCAR_USBCTR_REG);
+
+       /* Setup PCIAHB window1 size */
+       switch (priv->window_size) {
+       case SZ_2G:
+               val |= RCAR_USBCTR_PCIAHB_WIN1_2G;
+               break;
+       case SZ_1G:
+               val |= RCAR_USBCTR_PCIAHB_WIN1_1G;
+               break;
+       case SZ_512M:
+               val |= RCAR_USBCTR_PCIAHB_WIN1_512M;
+               break;
+       default:
+               pr_warn("unknown window size %ld - defaulting to 256M\n",
+                       priv->window_size);
+               priv->window_size = SZ_256M;
+               /* fall-through */
+       case SZ_256M:
+               val |= RCAR_USBCTR_PCIAHB_WIN1_256M;
+               break;
+       }
+       iowrite32(val, reg + RCAR_USBCTR_REG);
 
        /* Configure AHB master and slave modes */
        iowrite32(RCAR_AHB_BUS_MODE, reg + RCAR_AHB_BUS_CTR_REG);
@@ -197,7 +278,7 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
               RCAR_PCI_ARBITER_PCIBP_MODE;
        iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG);
 
-       /* PCI-AHB mapping: 0x40000000-0x80000000 */
+       /* PCI-AHB mapping: 0x40000000 base */
        iowrite32(0x40000000 | RCAR_PCIAHB_PREFETCH16,
                  reg + RCAR_PCIAHB_WIN1_CTR_REG);
 
@@ -224,10 +305,15 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
        iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME,
                  reg + RCAR_PCI_INT_ENABLE_REG);
 
+       if (priv->irq > 0)
+               rcar_pci_setup_errirq(priv);
+
        /* Add PCI resources */
        pci_add_resource(&sys->resources, &priv->io_res);
        pci_add_resource(&sys->resources, &priv->mem_res);
 
+       /* Setup bus number based on platform device id */
+       sys->busnr = to_platform_device(priv->dev)->id;
        return 1;
 }
 
@@ -236,48 +322,13 @@ static struct pci_ops rcar_pci_ops = {
        .write  = rcar_pci_write_config,
 };
 
-static struct hw_pci rcar_hw_pci __initdata = {
-       .map_irq        = rcar_pci_map_irq,
-       .ops            = &rcar_pci_ops,
-       .setup          = rcar_pci_setup,
-};
-
-static int rcar_pci_count __initdata;
-
-static int __init rcar_pci_add_controller(struct rcar_pci_priv *priv)
-{
-       void **private_data;
-       int count;
-
-       if (rcar_hw_pci.nr_controllers < rcar_pci_count)
-               goto add_priv;
-
-       /* (Re)allocate private data pointer array if needed */
-       count = rcar_pci_count + RCAR_PCI_NR_CONTROLLERS;
-       private_data = kzalloc(count * sizeof(void *), GFP_KERNEL);
-       if (!private_data)
-               return -ENOMEM;
-
-       rcar_pci_count = count;
-       if (rcar_hw_pci.private_data) {
-               memcpy(private_data, rcar_hw_pci.private_data,
-                      rcar_hw_pci.nr_controllers * sizeof(void *));
-               kfree(rcar_hw_pci.private_data);
-       }
-
-       rcar_hw_pci.private_data = private_data;
-
-add_priv:
-       /* Add private data pointer to the array */
-       rcar_hw_pci.private_data[rcar_hw_pci.nr_controllers++] = priv;
-       return 0;
-}
-
-static int __init rcar_pci_probe(struct platform_device *pdev)
+static int rcar_pci_probe(struct platform_device *pdev)
 {
        struct resource *cfg_res, *mem_res;
        struct rcar_pci_priv *priv;
        void __iomem *reg;
+       struct hw_pci hw;
+       void *hw_private[1];
 
        cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        reg = devm_ioremap_resource(&pdev->dev, cfg_res);
@@ -308,31 +359,34 @@ static int __init rcar_pci_probe(struct platform_device *pdev)
        priv->reg = reg;
        priv->dev = &pdev->dev;
 
-       return rcar_pci_add_controller(priv);
+       if (priv->irq < 0) {
+               dev_err(&pdev->dev, "no valid irq found\n");
+               return priv->irq;
+       }
+
+       priv->window_size = SZ_1G;
+
+       hw_private[0] = priv;
+       memset(&hw, 0, sizeof(hw));
+       hw.nr_controllers = ARRAY_SIZE(hw_private);
+       hw.private_data = hw_private;
+       hw.map_irq = rcar_pci_map_irq;
+       hw.ops = &rcar_pci_ops;
+       hw.setup = rcar_pci_setup;
+       pci_common_init_dev(&pdev->dev, &hw);
+       return 0;
 }
 
 static struct platform_driver rcar_pci_driver = {
        .driver = {
                .name = "pci-rcar-gen2",
+               .owner = THIS_MODULE,
+               .suppress_bind_attrs = true,
        },
+       .probe = rcar_pci_probe,
 };
 
-static int __init rcar_pci_init(void)
-{
-       int retval;
-
-       retval = platform_driver_probe(&rcar_pci_driver, rcar_pci_probe);
-       if (!retval)
-               pci_common_init(&rcar_hw_pci);
-
-       /* Private data pointer array is not needed any more */
-       kfree(rcar_hw_pci.private_data);
-       rcar_hw_pci.private_data = NULL;
-
-       return retval;
-}
-
-subsys_initcall(rcar_pci_init);
+module_platform_driver(rcar_pci_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Renesas R-Car Gen2 internal PCI");
index 2e48ecf09e2c5a120d4b07879904a0384137982d..509a29d84509364b366ef1e130ed5ea37b40a091 100644 (file)
@@ -798,7 +798,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 
        /* setup RC BARs */
        dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_0);
-       dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_1);
+       dw_pcie_writel_rc(pp, 0x00000000, PCI_BASE_ADDRESS_1);
 
        /* setup interrupt pins */
        dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE, &val);
index 828acf422c17eca4fe02cab5feca62e41e50908e..bccc27ee10308f4d1ec388db248d1af1ab08aaba 100644 (file)
@@ -424,7 +424,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
  */
 static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
 {
-       struct list_head *tmp;
+       struct pci_bus *tmp;
        unsigned char max, n;
 
        /*
@@ -437,8 +437,8 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
         */
        max = bus->busn_res.start;
 
-       list_for_each(tmp, &bus->children) {
-               n = pci_bus_max_busnr(pci_bus_b(tmp));
+       list_for_each_entry(tmp, &bus->children, node) {
+               n = pci_bus_max_busnr(tmp);
                if (n > max)
                        max = n;
        }
index 31273e155e6cd360946f068fe7268d13c7e41c27..037e2612c5bd036df0afb7a56c710439839cf31c 100644 (file)
@@ -920,12 +920,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                                bus->max_bus_speed = PCI_SPEED_100MHz_PCIX;
                                break;
                        }
-                       if (bus_cap & 20) {
+                       if (bus_cap & 0x20) {
                                dbg("bus max supports 66MHz PCI-X\n");
                                bus->max_bus_speed = PCI_SPEED_66MHz_PCIX;
                                break;
                        }
-                       if (bus_cap & 10) {
+                       if (bus_cap & 0x10) {
                                dbg("bus max supports 66MHz PCI\n");
                                bus->max_bus_speed = PCI_SPEED_66MHz;
                                break;
index 88b37cad4b35eed91fa48b8fbcecc569744f7a45..8a66866b8cf1ad799de42c2a15075f7549f0ca3a 100644 (file)
@@ -76,6 +76,7 @@ struct slot {
        struct hotplug_slot *hotplug_slot;
        struct delayed_work work;       /* work for button event */
        struct mutex lock;
+       struct mutex hotplug_lock;
        struct workqueue_struct *wq;
 };
 
@@ -109,6 +110,8 @@ struct controller {
 #define INT_BUTTON_PRESS               7
 #define INT_BUTTON_RELEASE             8
 #define INT_BUTTON_CANCEL              9
+#define INT_LINK_UP                    10
+#define INT_LINK_DOWN                  11
 
 #define STATIC_STATE                   0
 #define BLINKINGON_STATE               1
@@ -132,6 +135,7 @@ u8 pciehp_handle_attention_button(struct slot *p_slot);
 u8 pciehp_handle_switch_change(struct slot *p_slot);
 u8 pciehp_handle_presence_change(struct slot *p_slot);
 u8 pciehp_handle_power_fault(struct slot *p_slot);
+void pciehp_handle_linkstate_change(struct slot *p_slot);
 int pciehp_configure_device(struct slot *p_slot);
 int pciehp_unconfigure_device(struct slot *p_slot);
 void pciehp_queue_pushbutton_work(struct work_struct *work);
@@ -153,6 +157,7 @@ void pciehp_green_led_on(struct slot *slot);
 void pciehp_green_led_off(struct slot *slot);
 void pciehp_green_led_blink(struct slot *slot);
 int pciehp_check_link_status(struct controller *ctrl);
+bool pciehp_check_link_active(struct controller *ctrl);
 void pciehp_release_ctrl(struct controller *ctrl);
 int pciehp_reset_slot(struct slot *slot, int probe);
 
index eddddd447d0df61074d7a133524f37879ab73741..20fea57d2149c7ecf43e31c6ee16d820415ba85d 100644 (file)
@@ -112,6 +112,7 @@ static struct pcie_port_service_driver __initdata dummy_driver = {
 static int __init select_detection_mode(void)
 {
        struct dummy_slot *slot, *tmp;
+
        if (pcie_port_service_register(&dummy_driver))
                return PCIEHP_DETECT_ACPI;
        pcie_port_service_unregister(&dummy_driver);
index 53b58debc28804e02460e09344be754db435056a..0e0a2fff20a39be57f7c9abc8bb422831c771416 100644 (file)
@@ -108,6 +108,7 @@ static int init_slot(struct controller *ctrl)
        ops = kzalloc(sizeof(*ops), GFP_KERNEL);
        if (!ops)
                goto out;
+
        ops->enable_slot = enable_slot;
        ops->disable_slot = disable_slot;
        ops->get_power_status = get_power_status;
@@ -283,8 +284,11 @@ static int pciehp_probe(struct pcie_device *dev)
        slot = ctrl->slot;
        pciehp_get_adapter_status(slot, &occupied);
        pciehp_get_power_status(slot, &poweron);
-       if (occupied && pciehp_force)
+       if (occupied && pciehp_force) {
+               mutex_lock(&slot->hotplug_lock);
                pciehp_enable_slot(slot);
+               mutex_unlock(&slot->hotplug_lock);
+       }
        /* If empty slot's power status is on, turn power off */
        if (!occupied && poweron && POWER_CTRL(ctrl))
                pciehp_power_off_slot(slot);
@@ -328,10 +332,12 @@ static int pciehp_resume (struct pcie_device *dev)
 
        /* Check if slot is occupied */
        pciehp_get_adapter_status(slot, &status);
+       mutex_lock(&slot->hotplug_lock);
        if (status)
                pciehp_enable_slot(slot);
        else
                pciehp_disable_slot(slot);
+       mutex_unlock(&slot->hotplug_lock);
        return 0;
 }
 #endif /* PM */
index 50628487597deb2fe9de2b7499bc7dc253c7c388..c75e6a678dcc22f19707fc8d77200e1ee307afe6 100644 (file)
@@ -150,6 +150,27 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)
        return 1;
 }
 
+void pciehp_handle_linkstate_change(struct slot *p_slot)
+{
+       u32 event_type;
+       struct controller *ctrl = p_slot->ctrl;
+
+       /* Link Status Change */
+       ctrl_dbg(ctrl, "Data Link Layer State change\n");
+
+       if (pciehp_check_link_active(ctrl)) {
+               ctrl_info(ctrl, "slot(%s): Link Up event\n",
+                         slot_name(p_slot));
+               event_type = INT_LINK_UP;
+       } else {
+               ctrl_info(ctrl, "slot(%s): Link Down event\n",
+                         slot_name(p_slot));
+               event_type = INT_LINK_DOWN;
+       }
+
+       queue_interrupt_event(p_slot, event_type);
+}
+
 /* The following routines constitute the bulk of the
    hotplug controller logic
  */
@@ -212,7 +233,8 @@ static int board_added(struct slot *p_slot)
        if (retval) {
                ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
                         pci_domain_nr(parent), parent->number);
-               goto err_exit;
+               if (retval != -EEXIST)
+                       goto err_exit;
        }
 
        pciehp_green_led_on(p_slot);
@@ -255,6 +277,9 @@ static int remove_board(struct slot *p_slot)
 struct power_work_info {
        struct slot *p_slot;
        struct work_struct work;
+       unsigned int req;
+#define DISABLE_REQ 0
+#define ENABLE_REQ  1
 };
 
 /**
@@ -269,30 +294,38 @@ static void pciehp_power_thread(struct work_struct *work)
        struct power_work_info *info =
                container_of(work, struct power_work_info, work);
        struct slot *p_slot = info->p_slot;
+       int ret;
 
-       mutex_lock(&p_slot->lock);
-       switch (p_slot->state) {
-       case POWEROFF_STATE:
-               mutex_unlock(&p_slot->lock);
+       switch (info->req) {
+       case DISABLE_REQ:
                ctrl_dbg(p_slot->ctrl,
                         "Disabling domain:bus:device=%04x:%02x:00\n",
                         pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
                         p_slot->ctrl->pcie->port->subordinate->number);
+               mutex_lock(&p_slot->hotplug_lock);
                pciehp_disable_slot(p_slot);
+               mutex_unlock(&p_slot->hotplug_lock);
                mutex_lock(&p_slot->lock);
                p_slot->state = STATIC_STATE;
-               break;
-       case POWERON_STATE:
                mutex_unlock(&p_slot->lock);
-               if (pciehp_enable_slot(p_slot))
+               break;
+       case ENABLE_REQ:
+               ctrl_dbg(p_slot->ctrl,
+                        "Enabling domain:bus:device=%04x:%02x:00\n",
+                        pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
+                        p_slot->ctrl->pcie->port->subordinate->number);
+               mutex_lock(&p_slot->hotplug_lock);
+               ret = pciehp_enable_slot(p_slot);
+               mutex_unlock(&p_slot->hotplug_lock);
+               if (ret)
                        pciehp_green_led_off(p_slot);
                mutex_lock(&p_slot->lock);
                p_slot->state = STATIC_STATE;
+               mutex_unlock(&p_slot->lock);
                break;
        default:
                break;
        }
-       mutex_unlock(&p_slot->lock);
 
        kfree(info);
 }
@@ -315,9 +348,11 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
        switch (p_slot->state) {
        case BLINKINGOFF_STATE:
                p_slot->state = POWEROFF_STATE;
+               info->req = DISABLE_REQ;
                break;
        case BLINKINGON_STATE:
                p_slot->state = POWERON_STATE;
+               info->req = ENABLE_REQ;
                break;
        default:
                kfree(info);
@@ -364,11 +399,10 @@ static void handle_button_press_event(struct slot *p_slot)
                 */
                ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));
                cancel_delayed_work(&p_slot->work);
-               if (p_slot->state == BLINKINGOFF_STATE) {
+               if (p_slot->state == BLINKINGOFF_STATE)
                        pciehp_green_led_on(p_slot);
-               } else {
+               else
                        pciehp_green_led_off(p_slot);
-               }
                pciehp_set_attention_status(p_slot, 0);
                ctrl_info(ctrl, "PCI slot #%s - action canceled "
                          "due to button press\n", slot_name(p_slot));
@@ -407,14 +441,81 @@ static void handle_surprise_event(struct slot *p_slot)
        INIT_WORK(&info->work, pciehp_power_thread);
 
        pciehp_get_adapter_status(p_slot, &getstatus);
-       if (!getstatus)
+       if (!getstatus) {
                p_slot->state = POWEROFF_STATE;
-       else
+               info->req = DISABLE_REQ;
+       } else {
                p_slot->state = POWERON_STATE;
+               info->req = ENABLE_REQ;
+       }
 
        queue_work(p_slot->wq, &info->work);
 }
 
+/*
+ * Note: This function must be called with slot->lock held
+ */
+static void handle_link_event(struct slot *p_slot, u32 event)
+{
+       struct controller *ctrl = p_slot->ctrl;
+       struct power_work_info *info;
+
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
+                        __func__);
+               return;
+       }
+       info->p_slot = p_slot;
+       info->req = event == INT_LINK_UP ? ENABLE_REQ : DISABLE_REQ;
+       INIT_WORK(&info->work, pciehp_power_thread);
+
+       switch (p_slot->state) {
+       case BLINKINGON_STATE:
+       case BLINKINGOFF_STATE:
+               cancel_delayed_work(&p_slot->work);
+               /* Fall through */
+       case STATIC_STATE:
+               p_slot->state = event == INT_LINK_UP ?
+                   POWERON_STATE : POWEROFF_STATE;
+               queue_work(p_slot->wq, &info->work);
+               break;
+       case POWERON_STATE:
+               if (event == INT_LINK_UP) {
+                       ctrl_info(ctrl,
+                                 "Link Up event ignored on slot(%s): already powering on\n",
+                                 slot_name(p_slot));
+                       kfree(info);
+               } else {
+                       ctrl_info(ctrl,
+                                 "Link Down event queued on slot(%s): currently getting powered on\n",
+                                 slot_name(p_slot));
+                       p_slot->state = POWEROFF_STATE;
+                       queue_work(p_slot->wq, &info->work);
+               }
+               break;
+       case POWEROFF_STATE:
+               if (event == INT_LINK_UP) {
+                       ctrl_info(ctrl,
+                                 "Link Up event queued on slot(%s): currently getting powered off\n",
+                                 slot_name(p_slot));
+                       p_slot->state = POWERON_STATE;
+                       queue_work(p_slot->wq, &info->work);
+               } else {
+                       ctrl_info(ctrl,
+                                 "Link Down event ignored on slot(%s): already powering off\n",
+                                 slot_name(p_slot));
+                       kfree(info);
+               }
+               break;
+       default:
+               ctrl_err(ctrl, "Not a valid state on slot(%s)\n",
+                        slot_name(p_slot));
+               kfree(info);
+               break;
+       }
+}
+
 static void interrupt_event_handler(struct work_struct *work)
 {
        struct event_info *info = container_of(work, struct event_info, work);
@@ -433,12 +534,23 @@ static void interrupt_event_handler(struct work_struct *work)
                pciehp_green_led_off(p_slot);
                break;
        case INT_PRESENCE_ON:
-       case INT_PRESENCE_OFF:
                if (!HP_SUPR_RM(ctrl))
                        break;
+               ctrl_dbg(ctrl, "Surprise Insertion\n");
+               handle_surprise_event(p_slot);
+               break;
+       case INT_PRESENCE_OFF:
+               /*
+                * Regardless of surprise capability, we need to
+                * definitely remove a card that has been pulled out!
+                */
                ctrl_dbg(ctrl, "Surprise Removal\n");
                handle_surprise_event(p_slot);
                break;
+       case INT_LINK_UP:
+       case INT_LINK_DOWN:
+               handle_link_event(p_slot, info->event_type);
+               break;
        default:
                break;
        }
@@ -447,6 +559,9 @@ static void interrupt_event_handler(struct work_struct *work)
        kfree(info);
 }
 
+/*
+ * Note: This function must be called with slot->hotplug_lock held
+ */
 int pciehp_enable_slot(struct slot *p_slot)
 {
        u8 getstatus = 0;
@@ -479,13 +594,15 @@ int pciehp_enable_slot(struct slot *p_slot)
        pciehp_get_latch_status(p_slot, &getstatus);
 
        rc = board_added(p_slot);
-       if (rc) {
+       if (rc)
                pciehp_get_latch_status(p_slot, &getstatus);
-       }
+
        return rc;
 }
 
-
+/*
+ * Note: This function must be called with slot->hotplug_lock held
+ */
 int pciehp_disable_slot(struct slot *p_slot)
 {
        u8 getstatus = 0;
@@ -494,24 +611,6 @@ int pciehp_disable_slot(struct slot *p_slot)
        if (!p_slot->ctrl)
                return 1;
 
-       if (!HP_SUPR_RM(p_slot->ctrl)) {
-               pciehp_get_adapter_status(p_slot, &getstatus);
-               if (!getstatus) {
-                       ctrl_info(ctrl, "No adapter on slot(%s)\n",
-                                 slot_name(p_slot));
-                       return -ENODEV;
-               }
-       }
-
-       if (MRL_SENS(p_slot->ctrl)) {
-               pciehp_get_latch_status(p_slot, &getstatus);
-               if (getstatus) {
-                       ctrl_info(ctrl, "Latch open on slot(%s)\n",
-                                 slot_name(p_slot));
-                       return -ENODEV;
-               }
-       }
-
        if (POWER_CTRL(p_slot->ctrl)) {
                pciehp_get_power_status(p_slot, &getstatus);
                if (!getstatus) {
@@ -536,7 +635,9 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
        case STATIC_STATE:
                p_slot->state = POWERON_STATE;
                mutex_unlock(&p_slot->lock);
+               mutex_lock(&p_slot->hotplug_lock);
                retval = pciehp_enable_slot(p_slot);
+               mutex_unlock(&p_slot->hotplug_lock);
                mutex_lock(&p_slot->lock);
                p_slot->state = STATIC_STATE;
                break;
index 14acfccb767072bb58b00417413afb55747ac0e5..d7d058fa19a428e5503c919979e5a6e1e5e5e0b2 100644 (file)
@@ -206,7 +206,7 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
        mutex_unlock(&ctrl->ctrl_lock);
 }
 
-static bool check_link_active(struct controller *ctrl)
+bool pciehp_check_link_active(struct controller *ctrl)
 {
        struct pci_dev *pdev = ctrl_dev(ctrl);
        u16 lnk_status;
@@ -225,12 +225,12 @@ static void __pcie_wait_link_active(struct controller *ctrl, bool active)
 {
        int timeout = 1000;
 
-       if (check_link_active(ctrl) == active)
+       if (pciehp_check_link_active(ctrl) == active)
                return;
        while (timeout > 0) {
                msleep(10);
                timeout -= 10;
-               if (check_link_active(ctrl) == active)
+               if (pciehp_check_link_active(ctrl) == active)
                        return;
        }
        ctrl_dbg(ctrl, "Data Link Layer Link Active not %s in 1000 msec\n",
@@ -242,11 +242,6 @@ static void pcie_wait_link_active(struct controller *ctrl)
        __pcie_wait_link_active(ctrl, true);
 }
 
-static void pcie_wait_link_not_active(struct controller *ctrl)
-{
-       __pcie_wait_link_active(ctrl, false);
-}
-
 static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)
 {
        u32 l;
@@ -332,11 +327,6 @@ static int pciehp_link_enable(struct controller *ctrl)
        return __pciehp_link_set(ctrl, true);
 }
 
-static int pciehp_link_disable(struct controller *ctrl)
-{
-       return __pciehp_link_set(ctrl, false);
-}
-
 void pciehp_get_attention_status(struct slot *slot, u8 *status)
 {
        struct controller *ctrl = slot->ctrl;
@@ -508,14 +498,6 @@ void pciehp_power_off_slot(struct slot * slot)
 {
        struct controller *ctrl = slot->ctrl;
 
-       /* Disable the link at first */
-       pciehp_link_disable(ctrl);
-       /* wait the link is down */
-       if (ctrl->link_active_reporting)
-               pcie_wait_link_not_active(ctrl);
-       else
-               msleep(1000);
-
        pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC);
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
                 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
@@ -540,7 +522,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
 
                detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
                             PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
-                            PCI_EXP_SLTSTA_CC);
+                            PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);
                detected &= ~intr_loc;
                intr_loc |= detected;
                if (!intr_loc)
@@ -579,6 +561,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
                ctrl->power_fault_detected = 1;
                pciehp_handle_power_fault(slot);
        }
+
+       if (intr_loc & PCI_EXP_SLTSTA_DLLSC)
+               pciehp_handle_linkstate_change(slot);
+
        return IRQ_HANDLED;
 }
 
@@ -596,9 +582,17 @@ void pcie_enable_notification(struct controller *ctrl)
         * when it is cleared in the interrupt service routine, and
         * next power fault detected interrupt was notified again.
         */
-       cmd = PCI_EXP_SLTCTL_PDCE;
+
+       /*
+        * Always enable link events: thus link-up and link-down shall
+        * always be treated as hotplug and unplug respectively. Enable
+        * presence detect only if Attention Button is not present.
+        */
+       cmd = PCI_EXP_SLTCTL_DLLSCE;
        if (ATTN_BUTTN(ctrl))
                cmd |= PCI_EXP_SLTCTL_ABPE;
+       else
+               cmd |= PCI_EXP_SLTCTL_PDCE;
        if (MRL_SENS(ctrl))
                cmd |= PCI_EXP_SLTCTL_MRLSCE;
        if (!pciehp_poll_mode)
@@ -606,7 +600,8 @@ void pcie_enable_notification(struct controller *ctrl)
 
        mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
                PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
-               PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE);
+               PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |
+               PCI_EXP_SLTCTL_DLLSCE);
 
        pcie_write_cmd(ctrl, cmd, mask);
 }
@@ -624,33 +619,38 @@ static void pcie_disable_notification(struct controller *ctrl)
 
 /*
  * pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary
- * bus reset of the bridge, but if the slot supports surprise removal we need
- * to disable presence detection around the bus reset and clear any spurious
+ * bus reset of the bridge, but at the same time we want to ensure that it is
+ * not seen as a hot-unplug, followed by the hot-plug of the device. Thus,
+ * disable link state notification and presence detection change notification
+ * momentarily, if we see that they could interfere. Also, clear any spurious
  * events after.
  */
 int pciehp_reset_slot(struct slot *slot, int probe)
 {
        struct controller *ctrl = slot->ctrl;
        struct pci_dev *pdev = ctrl_dev(ctrl);
+       u16 stat_mask = 0, ctrl_mask = 0;
 
        if (probe)
                return 0;
 
-       if (HP_SUPR_RM(ctrl)) {
-               pcie_write_cmd(ctrl, 0, PCI_EXP_SLTCTL_PDCE);
-               if (pciehp_poll_mode)
-                       del_timer_sync(&ctrl->poll_timer);
+       if (!ATTN_BUTTN(ctrl)) {
+               ctrl_mask |= PCI_EXP_SLTCTL_PDCE;
+               stat_mask |= PCI_EXP_SLTSTA_PDC;
        }
+       ctrl_mask |= PCI_EXP_SLTCTL_DLLSCE;
+       stat_mask |= PCI_EXP_SLTSTA_DLLSC;
+
+       pcie_write_cmd(ctrl, 0, ctrl_mask);
+       if (pciehp_poll_mode)
+               del_timer_sync(&ctrl->poll_timer);
 
        pci_reset_bridge_secondary_bus(ctrl->pcie->port);
 
-       if (HP_SUPR_RM(ctrl)) {
-               pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
-                                          PCI_EXP_SLTSTA_PDC);
-               pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE);
-               if (pciehp_poll_mode)
-                       int_poll_timeout(ctrl->poll_timer.data);
-       }
+       pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, stat_mask);
+       pcie_write_cmd(ctrl, ctrl_mask, ctrl_mask);
+       if (pciehp_poll_mode)
+               int_poll_timeout(ctrl->poll_timer.data);
 
        return 0;
 }
@@ -687,6 +687,7 @@ static int pcie_init_slot(struct controller *ctrl)
 
        slot->ctrl = ctrl;
        mutex_init(&slot->lock);
+       mutex_init(&slot->hotplug_lock);
        INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
        ctrl->slot = slot;
        return 0;
index b07d7cc2d697e8c9ce9152eaca90980e90906015..1b533060ce650778bbdc74e2a676d333c9afe7d7 100644 (file)
@@ -50,7 +50,7 @@ int pciehp_configure_device(struct slot *p_slot)
                         "at %04x:%02x:00, cannot hot-add\n", pci_name(dev),
                         pci_domain_nr(parent), parent->number);
                pci_dev_put(dev);
-               ret = -EINVAL;
+               ret = -EEXIST;
                goto out;
        }
 
index 9dce7c5e2a772231b5a33e480d8888452507efbf..de7a74782f929234d808aef1abac26097f1abfe3 100644 (file)
@@ -170,97 +170,6 @@ static void virtfn_remove(struct pci_dev *dev, int id, int reset)
        pci_dev_put(dev);
 }
 
-static int sriov_migration(struct pci_dev *dev)
-{
-       u16 status;
-       struct pci_sriov *iov = dev->sriov;
-
-       if (!iov->num_VFs)
-               return 0;
-
-       if (!(iov->cap & PCI_SRIOV_CAP_VFM))
-               return 0;
-
-       pci_read_config_word(dev, iov->pos + PCI_SRIOV_STATUS, &status);
-       if (!(status & PCI_SRIOV_STATUS_VFM))
-               return 0;
-
-       schedule_work(&iov->mtask);
-
-       return 1;
-}
-
-static void sriov_migration_task(struct work_struct *work)
-{
-       int i;
-       u8 state;
-       u16 status;
-       struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask);
-
-       for (i = iov->initial_VFs; i < iov->num_VFs; i++) {
-               state = readb(iov->mstate + i);
-               if (state == PCI_SRIOV_VFM_MI) {
-                       writeb(PCI_SRIOV_VFM_AV, iov->mstate + i);
-                       state = readb(iov->mstate + i);
-                       if (state == PCI_SRIOV_VFM_AV)
-                               virtfn_add(iov->self, i, 1);
-               } else if (state == PCI_SRIOV_VFM_MO) {
-                       virtfn_remove(iov->self, i, 1);
-                       writeb(PCI_SRIOV_VFM_UA, iov->mstate + i);
-                       state = readb(iov->mstate + i);
-                       if (state == PCI_SRIOV_VFM_AV)
-                               virtfn_add(iov->self, i, 0);
-               }
-       }
-
-       pci_read_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, &status);
-       status &= ~PCI_SRIOV_STATUS_VFM;
-       pci_write_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, status);
-}
-
-static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn)
-{
-       int bir;
-       u32 table;
-       resource_size_t pa;
-       struct pci_sriov *iov = dev->sriov;
-
-       if (nr_virtfn <= iov->initial_VFs)
-               return 0;
-
-       pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table);
-       bir = PCI_SRIOV_VFM_BIR(table);
-       if (bir > PCI_STD_RESOURCE_END)
-               return -EIO;
-
-       table = PCI_SRIOV_VFM_OFFSET(table);
-       if (table + nr_virtfn > pci_resource_len(dev, bir))
-               return -EIO;
-
-       pa = pci_resource_start(dev, bir) + table;
-       iov->mstate = ioremap(pa, nr_virtfn);
-       if (!iov->mstate)
-               return -ENOMEM;
-
-       INIT_WORK(&iov->mtask, sriov_migration_task);
-
-       iov->ctrl |= PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR;
-       pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
-
-       return 0;
-}
-
-static void sriov_disable_migration(struct pci_dev *dev)
-{
-       struct pci_sriov *iov = dev->sriov;
-
-       iov->ctrl &= ~(PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR);
-       pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
-
-       cancel_work_sync(&iov->mtask);
-       iounmap(iov->mstate);
-}
-
 static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 {
        int rc;
@@ -351,12 +260,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
                        goto failed;
        }
 
-       if (iov->cap & PCI_SRIOV_CAP_VFM) {
-               rc = sriov_enable_migration(dev, nr_virtfn);
-               if (rc)
-                       goto failed;
-       }
-
        kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);
        iov->num_VFs = nr_virtfn;
 
@@ -387,9 +290,6 @@ static void sriov_disable(struct pci_dev *dev)
        if (!iov->num_VFs)
                return;
 
-       if (iov->cap & PCI_SRIOV_CAP_VFM)
-               sriov_disable_migration(dev);
-
        for (i = 0; i < iov->num_VFs; i++)
                virtfn_remove(dev, i, 0);
 
@@ -687,25 +587,6 @@ void pci_disable_sriov(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_disable_sriov);
 
-/**
- * pci_sriov_migration - notify SR-IOV core of Virtual Function Migration
- * @dev: the PCI device
- *
- * Returns IRQ_HANDLED if the IRQ is handled, or IRQ_NONE if not.
- *
- * Physical Function driver is responsible to register IRQ handler using
- * VF Migration Interrupt Message Number, and call this function when the
- * interrupt is generated by the hardware.
- */
-irqreturn_t pci_sriov_migration(struct pci_dev *dev)
-{
-       if (!dev->is_physfn)
-               return IRQ_NONE;
-
-       return sriov_migration(dev) ? IRQ_HANDLED : IRQ_NONE;
-}
-EXPORT_SYMBOL_GPL(pci_sriov_migration);
-
 /**
  * pci_num_vf - return number of VFs associated with a PF device_release_driver
  * @dev: the PCI device
index fdbc294821e6468d55ca7d5fd68162b407607e97..7325d43bf030ce65d5f386f6aeeeb3bfa4d5c482 100644 (file)
@@ -108,12 +108,12 @@ static bool pcie_ari_disabled;
  */
 unsigned char pci_bus_max_busnr(struct pci_bus* bus)
 {
-       struct list_head *tmp;
+       struct pci_bus *tmp;
        unsigned char max, n;
 
        max = bus->busn_res.end;
-       list_for_each(tmp, &bus->children) {
-               n = pci_bus_max_busnr(pci_bus_b(tmp));
+       list_for_each_entry(tmp, &bus->children, node) {
+               n = pci_bus_max_busnr(tmp);
                if(n > max)
                        max = n;
        }
@@ -401,33 +401,40 @@ EXPORT_SYMBOL_GPL(pci_find_ht_capability);
  * @res: child resource record for which parent is sought
  *
  *  For given resource region of given device, return the resource
- *  region of parent bus the given region is contained in or where
- *  it should be allocated from.
+ *  region of parent bus the given region is contained in.
  */
 struct resource *
 pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
 {
        const struct pci_bus *bus = dev->bus;
+       struct resource *r;
        int i;
-       struct resource *best = NULL, *r;
 
        pci_bus_for_each_resource(bus, r, i) {
                if (!r)
                        continue;
-               if (res->start && !(res->start >= r->start && res->end <= r->end))
-                       continue;       /* Not contained */
-               if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
-                       continue;       /* Wrong type */
-               if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH))
-                       return r;       /* Exact match */
-               /* We can't insert a non-prefetch resource inside a prefetchable parent .. */
-               if (r->flags & IORESOURCE_PREFETCH)
-                       continue;
-               /* .. but we can put a prefetchable resource inside a non-prefetchable one */
-               if (!best)
-                       best = r;
+               if (res->start && resource_contains(r, res)) {
+
+                       /*
+                        * If the window is prefetchable but the BAR is
+                        * not, the allocator made a mistake.
+                        */
+                       if (r->flags & IORESOURCE_PREFETCH &&
+                           !(res->flags & IORESOURCE_PREFETCH))
+                               return NULL;
+
+                       /*
+                        * If we're below a transparent bridge, there may
+                        * be both a positively-decoded aperture and a
+                        * subtractively-decoded region that contain the BAR.
+                        * We want the positively-decoded one, so this depends
+                        * on pci_bus_for_each_resource() giving us those
+                        * first.
+                        */
+                       return r;
+               }
        }
-       return best;
+       return NULL;
 }
 
 /**
@@ -1178,6 +1185,11 @@ int pci_load_and_free_saved_state(struct pci_dev *dev,
 }
 EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state);
 
+int __weak pcibios_enable_device(struct pci_dev *dev, int bars)
+{
+       return pci_enable_resources(dev, bars);
+}
+
 static int do_pci_enable_device(struct pci_dev *dev, int bars)
 {
        int err;
@@ -1624,29 +1636,27 @@ static void pci_pme_list_scan(struct work_struct *work)
        struct pci_pme_device *pme_dev, *n;
 
        mutex_lock(&pci_pme_list_mutex);
-       if (!list_empty(&pci_pme_list)) {
-               list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
-                       if (pme_dev->dev->pme_poll) {
-                               struct pci_dev *bridge;
-
-                               bridge = pme_dev->dev->bus->self;
-                               /*
-                                * If bridge is in low power state, the
-                                * configuration space of subordinate devices
-                                * may be not accessible
-                                */
-                               if (bridge && bridge->current_state != PCI_D0)
-                                       continue;
-                               pci_pme_wakeup(pme_dev->dev, NULL);
-                       } else {
-                               list_del(&pme_dev->list);
-                               kfree(pme_dev);
-                       }
+       list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
+               if (pme_dev->dev->pme_poll) {
+                       struct pci_dev *bridge;
+
+                       bridge = pme_dev->dev->bus->self;
+                       /*
+                        * If bridge is in low power state, the
+                        * configuration space of subordinate devices
+                        * may be not accessible
+                        */
+                       if (bridge && bridge->current_state != PCI_D0)
+                               continue;
+                       pci_pme_wakeup(pme_dev->dev, NULL);
+               } else {
+                       list_del(&pme_dev->list);
+                       kfree(pme_dev);
                }
-               if (!list_empty(&pci_pme_list))
-                       schedule_delayed_work(&pci_pme_work,
-                                             msecs_to_jiffies(PME_TIMEOUT));
        }
+       if (!list_empty(&pci_pme_list))
+               schedule_delayed_work(&pci_pme_work,
+                                     msecs_to_jiffies(PME_TIMEOUT));
        mutex_unlock(&pci_pme_list_mutex);
 }
 
@@ -2193,21 +2203,18 @@ void pci_request_acs(void)
 }
 
 /**
- * pci_enable_acs - enable ACS if hardware support it
+ * pci_std_enable_acs - enable ACS on devices using standard ACS capabilites
  * @dev: the PCI device
  */
-void pci_enable_acs(struct pci_dev *dev)
+static int pci_std_enable_acs(struct pci_dev *dev)
 {
        int pos;
        u16 cap;
        u16 ctrl;
 
-       if (!pci_acs_enable)
-               return;
-
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
        if (!pos)
-               return;
+               return -ENODEV;
 
        pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
        pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
@@ -2225,6 +2232,23 @@ void pci_enable_acs(struct pci_dev *dev)
        ctrl |= (cap & PCI_ACS_UF);
 
        pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+
+       return 0;
+}
+
+/**
+ * pci_enable_acs - enable ACS if hardware support it
+ * @dev: the PCI device
+ */
+void pci_enable_acs(struct pci_dev *dev)
+{
+       if (!pci_acs_enable)
+               return;
+
+       if (!pci_std_enable_acs(dev))
+               return;
+
+       pci_dev_specific_enable_acs(dev);
 }
 
 static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
@@ -4250,6 +4274,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
                                "Rounding up size of resource #%d to %#llx.\n",
                                i, (unsigned long long)size);
                }
+               r->flags |= IORESOURCE_UNSET;
                r->end = size - 1;
                r->start = 0;
        }
@@ -4263,6 +4288,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
                        r = &dev->resource[i];
                        if (!(r->flags & IORESOURCE_MEM))
                                continue;
+                       r->flags |= IORESOURCE_UNSET;
                        r->end = resource_size(r) - 1;
                        r->start = 0;
                }
index 4df38df224f4d3e61f53a5519ad55d9b2053a567..6bd082299e3190b5676e49d781231f49e5eaa3fc 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef DRIVERS_PCI_H
 #define DRIVERS_PCI_H
 
-#include <linux/workqueue.h>
-
 #define PCI_CFG_SPACE_SIZE     256
 #define PCI_CFG_SPACE_EXP_SIZE 4096
 
@@ -240,8 +238,6 @@ struct pci_sriov {
        struct pci_dev *dev;    /* lowest numbered PF */
        struct pci_dev *self;   /* this PF */
        struct mutex lock;      /* lock for VF bus */
-       struct work_struct mtask; /* VF Migration task */
-       u8 __iomem *mstate;     /* VF Migration State Array */
 };
 
 #ifdef CONFIG_PCI_ATS
index 6e34498ec9f0269387c296e498174ccb29cbe3fb..ef09f5f2fe6c0bc7f0ba84ae06eaa9d46adea4e6 100644 (file)
@@ -252,6 +252,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        /* Address above 32-bit boundary; disable the BAR */
                        pci_write_config_dword(dev, pos, 0);
                        pci_write_config_dword(dev, pos + 4, 0);
+                       res->flags |= IORESOURCE_UNSET;
                        region.start = 0;
                        region.end = sz64;
                        bar_disabled = true;
@@ -731,22 +732,6 @@ struct pci_bus *__ref pci_add_new_bus(struct pci_bus *parent, struct pci_dev *de
        return child;
 }
 
-static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
-{
-       struct pci_bus *parent = child->parent;
-
-       /* Attempts to fix that up are really dangerous unless
-          we're going to re-assign all bus numbers. */
-       if (!pcibios_assign_all_busses())
-               return;
-
-       while (parent->parent && parent->busn_res.end < max) {
-               parent->busn_res.end = max;
-               pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
-               parent = parent->parent;
-       }
-}
-
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
@@ -782,7 +767,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
        /* Check if setup is sensible at all */
        if (!pass &&
            (primary != bus->number || secondary <= bus->number ||
-            secondary > subordinate)) {
+            secondary > subordinate || subordinate > bus->busn_res.end)) {
                dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n",
                         secondary, subordinate);
                broken = 1;
@@ -805,11 +790,10 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
                        goto out;
 
                /*
-                * If we already got to this bus through a different bridge,
-                * don't re-add it. This can happen with the i450NX chipset.
-                *
-                * However, we continue to descend down the hierarchy and
-                * scan remaining child buses.
+                * The bus might already exist for two reasons: Either we are
+                * rescanning the bus or the bus is reachable through more than
+                * one bridge. The second case can happen with the i450NX
+                * chipset.
                 */
                child = pci_find_bus(pci_domain_nr(bus), secondary);
                if (!child) {
@@ -822,17 +806,19 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
                }
 
                cmax = pci_scan_child_bus(child);
-               if (cmax > max)
-                       max = cmax;
-               if (child->busn_res.end > max)
-                       max = child->busn_res.end;
+               if (cmax > subordinate)
+                       dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n",
+                                subordinate, cmax);
+               /* subordinate should equal child->busn_res.end */
+               if (subordinate > max)
+                       max = subordinate;
        } else {
                /*
                 * We need to assign a number to this bus which we always
                 * do in the second pass.
                 */
                if (!pass) {
-                       if (pcibios_assign_all_busses() || broken)
+                       if (pcibios_assign_all_busses() || broken || is_cardbus)
                                /* Temporarily disable forwarding of the
                                   configuration cycles on all bridges in
                                   this bus segment to avoid possible
@@ -844,19 +830,25 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
                        goto out;
                }
 
+               if (max >= bus->busn_res.end) {
+                       dev_warn(&dev->dev, "can't allocate child bus %02x from %pR\n",
+                                max, &bus->busn_res);
+                       goto out;
+               }
+
                /* Clear errors */
                pci_write_config_word(dev, PCI_STATUS, 0xffff);
 
-               /* Prevent assigning a bus number that already exists.
-                * This can happen when a bridge is hot-plugged, so in
-                * this case we only re-scan this bus. */
+               /* The bus will already exist if we are rescanning */
                child = pci_find_bus(pci_domain_nr(bus), max+1);
                if (!child) {
-                       child = pci_add_new_bus(bus, dev, ++max);
+                       child = pci_add_new_bus(bus, dev, max+1);
                        if (!child)
                                goto out;
-                       pci_bus_insert_busn_res(child, max, 0xff);
+                       pci_bus_insert_busn_res(child, max+1,
+                                               bus->busn_res.end);
                }
+               max++;
                buses = (buses & 0xff000000)
                      | ((unsigned int)(child->primary)     <<  0)
                      | ((unsigned int)(child->busn_res.start)   <<  8)
@@ -878,20 +870,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 
                if (!is_cardbus) {
                        child->bridge_ctl = bctl;
-                       /*
-                        * Adjust subordinate busnr in parent buses.
-                        * We do this before scanning for children because
-                        * some devices may not be detected if the bios
-                        * was lazy.
-                        */
-                       pci_fixup_parent_subordinate_busnr(child, max);
-                       /* Now we can scan all subordinate buses... */
                        max = pci_scan_child_bus(child);
-                       /*
-                        * now fix it up again since we have found
-                        * the real value of max.
-                        */
-                       pci_fixup_parent_subordinate_busnr(child, max);
                } else {
                        /*
                         * For CardBus bridges, we leave 4 bus numbers
@@ -922,11 +901,15 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
                                }
                        }
                        max += i;
-                       pci_fixup_parent_subordinate_busnr(child, max);
                }
                /*
                 * Set the subordinate bus number to its real value.
                 */
+               if (max > bus->busn_res.end) {
+                       dev_warn(&dev->dev, "max busn %02x is outside %pR\n",
+                                max, &bus->busn_res);
+                       max = bus->busn_res.end;
+               }
                pci_bus_update_busn_res_end(child, max);
                pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
        }
@@ -1125,10 +1108,10 @@ int pci_setup_device(struct pci_dev *dev)
                pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);
 
                /*
-                *      Do the ugly legacy mode stuff here rather than broken chip
-                *      quirk code. Legacy mode ATA controllers have fixed
-                *      addresses. These are not always echoed in BAR0-3, and
-                *      BAR0-3 in a few cases contain junk!
+                * Do the ugly legacy mode stuff here rather than broken chip
+                * quirk code. Legacy mode ATA controllers have fixed
+                * addresses. These are not always echoed in BAR0-3, and
+                * BAR0-3 in a few cases contain junk!
                 */
                if (class == PCI_CLASS_STORAGE_IDE) {
                        u8 progif;
@@ -1139,11 +1122,15 @@ int pci_setup_device(struct pci_dev *dev)
                                res = &dev->resource[0];
                                res->flags = LEGACY_IO_RESOURCE;
                                pcibios_bus_to_resource(dev->bus, res, &region);
+                               dev_info(&dev->dev, "legacy IDE quirk: reg 0x10: %pR\n",
+                                        res);
                                region.start = 0x3F6;
                                region.end = 0x3F6;
                                res = &dev->resource[1];
                                res->flags = LEGACY_IO_RESOURCE;
                                pcibios_bus_to_resource(dev->bus, res, &region);
+                               dev_info(&dev->dev, "legacy IDE quirk: reg 0x14: %pR\n",
+                                        res);
                        }
                        if ((progif & 4) == 0) {
                                region.start = 0x170;
@@ -1151,11 +1138,15 @@ int pci_setup_device(struct pci_dev *dev)
                                res = &dev->resource[2];
                                res->flags = LEGACY_IO_RESOURCE;
                                pcibios_bus_to_resource(dev->bus, res, &region);
+                               dev_info(&dev->dev, "legacy IDE quirk: reg 0x18: %pR\n",
+                                        res);
                                region.start = 0x376;
                                region.end = 0x376;
                                res = &dev->resource[3];
                                res->flags = LEGACY_IO_RESOURCE;
                                pcibios_bus_to_resource(dev->bus, res, &region);
+                               dev_info(&dev->dev, "legacy IDE quirk: reg 0x1c: %pR\n",
+                                        res);
                        }
                }
                break;
@@ -1835,7 +1826,7 @@ int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
                res->flags |= IORESOURCE_PCI_FIXED;
        }
 
-       conflict = insert_resource_conflict(parent_res, res);
+       conflict = request_resource_conflict(parent_res, res);
 
        if (conflict)
                dev_printk(KERN_DEBUG, &b->dev,
index 5cb726c193de824db34ece33610cc6b3bec86eaa..e7292065a1b13f3281eaebde605db8c2eb556145 100644 (file)
@@ -296,6 +296,7 @@ static void quirk_s3_64M(struct pci_dev *dev)
        struct resource *r = &dev->resource[0];
 
        if ((r->start & 0x3ffffff) || r->end != r->start + 0x3ffffff) {
+               r->flags |= IORESOURCE_UNSET;
                r->start = 0;
                r->end = 0x3ffffff;
        }
@@ -937,6 +938,8 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD,   PCI_DEVICE_ID_AMD_FE_GATE_700C
 static void quirk_dunord(struct pci_dev *dev)
 {
        struct resource *r = &dev->resource [1];
+
+       r->flags |= IORESOURCE_UNSET;
        r->start = 0;
        r->end = 0xffffff;
 }
@@ -1740,6 +1743,7 @@ static void quirk_tc86c001_ide(struct pci_dev *dev)
        struct resource *r = &dev->resource[0];
 
        if (r->start & 0x8) {
+               r->flags |= IORESOURCE_UNSET;
                r->start = 0;
                r->end = 0xf;
        }
@@ -1769,6 +1773,7 @@ static void quirk_plx_pci9050(struct pci_dev *dev)
                        dev_info(&dev->dev,
                                 "Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",
                                 bar);
+                       r->flags |= IORESOURCE_UNSET;
                        r->start = 0;
                        r->end = 0xff;
                }
@@ -3423,6 +3428,61 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
 #endif
 }
 
+/*
+ * Many Intel PCH root ports do provide ACS-like features to disable peer
+ * transactions and validate bus numbers in requests, but do not provide an
+ * actual PCIe ACS capability.  This is the list of device IDs known to fall
+ * into that category as provided by Intel in Red Hat bugzilla 1037684.
+ */
+static const u16 pci_quirk_intel_pch_acs_ids[] = {
+       /* Ibexpeak PCH */
+       0x3b42, 0x3b43, 0x3b44, 0x3b45, 0x3b46, 0x3b47, 0x3b48, 0x3b49,
+       0x3b4a, 0x3b4b, 0x3b4c, 0x3b4d, 0x3b4e, 0x3b4f, 0x3b50, 0x3b51,
+       /* Cougarpoint PCH */
+       0x1c10, 0x1c11, 0x1c12, 0x1c13, 0x1c14, 0x1c15, 0x1c16, 0x1c17,
+       0x1c18, 0x1c19, 0x1c1a, 0x1c1b, 0x1c1c, 0x1c1d, 0x1c1e, 0x1c1f,
+       /* Pantherpoint PCH */
+       0x1e10, 0x1e11, 0x1e12, 0x1e13, 0x1e14, 0x1e15, 0x1e16, 0x1e17,
+       0x1e18, 0x1e19, 0x1e1a, 0x1e1b, 0x1e1c, 0x1e1d, 0x1e1e, 0x1e1f,
+       /* Lynxpoint-H PCH */
+       0x8c10, 0x8c11, 0x8c12, 0x8c13, 0x8c14, 0x8c15, 0x8c16, 0x8c17,
+       0x8c18, 0x8c19, 0x8c1a, 0x8c1b, 0x8c1c, 0x8c1d, 0x8c1e, 0x8c1f,
+       /* Lynxpoint-LP PCH */
+       0x9c10, 0x9c11, 0x9c12, 0x9c13, 0x9c14, 0x9c15, 0x9c16, 0x9c17,
+       0x9c18, 0x9c19, 0x9c1a, 0x9c1b,
+       /* Wildcat PCH */
+       0x9c90, 0x9c91, 0x9c92, 0x9c93, 0x9c94, 0x9c95, 0x9c96, 0x9c97,
+       0x9c98, 0x9c99, 0x9c9a, 0x9c9b,
+};
+
+static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev)
+{
+       int i;
+
+       /* Filter out a few obvious non-matches first */
+       if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
+               return false;
+
+       for (i = 0; i < ARRAY_SIZE(pci_quirk_intel_pch_acs_ids); i++)
+               if (pci_quirk_intel_pch_acs_ids[i] == dev->device)
+                       return true;
+
+       return false;
+}
+
+#define INTEL_PCH_ACS_FLAGS (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_SV)
+
+static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
+{
+       u16 flags = dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK ?
+                   INTEL_PCH_ACS_FLAGS : 0;
+
+       if (!pci_quirk_intel_pch_acs_match(dev))
+               return -ENOTTY;
+
+       return acs_flags & ~flags ? 0 : 1;
+}
+
 static const struct pci_dev_acs_enabled {
        u16 vendor;
        u16 device;
@@ -3434,6 +3494,7 @@ static const struct pci_dev_acs_enabled {
        { PCI_VENDOR_ID_ATI, 0x439d, pci_quirk_amd_sb_acs },
        { PCI_VENDOR_ID_ATI, 0x4384, pci_quirk_amd_sb_acs },
        { PCI_VENDOR_ID_ATI, 0x4399, pci_quirk_amd_sb_acs },
+       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
        { 0 }
 };
 
@@ -3461,3 +3522,132 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
 
        return -ENOTTY;
 }
+
+/* Config space offset of Root Complex Base Address register */
+#define INTEL_LPC_RCBA_REG 0xf0
+/* 31:14 RCBA address */
+#define INTEL_LPC_RCBA_MASK 0xffffc000
+/* RCBA Enable */
+#define INTEL_LPC_RCBA_ENABLE (1 << 0)
+
+/* Backbone Scratch Pad Register */
+#define INTEL_BSPR_REG 0x1104
+/* Backbone Peer Non-Posted Disable */
+#define INTEL_BSPR_REG_BPNPD (1 << 8)
+/* Backbone Peer Posted Disable */
+#define INTEL_BSPR_REG_BPPD  (1 << 9)
+
+/* Upstream Peer Decode Configuration Register */
+#define INTEL_UPDCR_REG 0x1114
+/* 5:0 Peer Decode Enable bits */
+#define INTEL_UPDCR_REG_MASK 0x3f
+
+static int pci_quirk_enable_intel_lpc_acs(struct pci_dev *dev)
+{
+       u32 rcba, bspr, updcr;
+       void __iomem *rcba_mem;
+
+       /*
+        * Read the RCBA register from the LPC (D31:F0).  PCH root ports
+        * are D28:F* and therefore get probed before LPC, thus we can't
+        * use pci_get_slot/pci_read_config_dword here.
+        */
+       pci_bus_read_config_dword(dev->bus, PCI_DEVFN(31, 0),
+                                 INTEL_LPC_RCBA_REG, &rcba);
+       if (!(rcba & INTEL_LPC_RCBA_ENABLE))
+               return -EINVAL;
+
+       rcba_mem = ioremap_nocache(rcba & INTEL_LPC_RCBA_MASK,
+                                  PAGE_ALIGN(INTEL_UPDCR_REG));
+       if (!rcba_mem)
+               return -ENOMEM;
+
+       /*
+        * The BSPR can disallow peer cycles, but it's set by soft strap and
+        * therefore read-only.  If both posted and non-posted peer cycles are
+        * disallowed, we're ok.  If either are allowed, then we need to use
+        * the UPDCR to disable peer decodes for each port.  This provides the
+        * PCIe ACS equivalent of PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF
+        */
+       bspr = readl(rcba_mem + INTEL_BSPR_REG);
+       bspr &= INTEL_BSPR_REG_BPNPD | INTEL_BSPR_REG_BPPD;
+       if (bspr != (INTEL_BSPR_REG_BPNPD | INTEL_BSPR_REG_BPPD)) {
+               updcr = readl(rcba_mem + INTEL_UPDCR_REG);
+               if (updcr & INTEL_UPDCR_REG_MASK) {
+                       dev_info(&dev->dev, "Disabling UPDCR peer decodes\n");
+                       updcr &= ~INTEL_UPDCR_REG_MASK;
+                       writel(updcr, rcba_mem + INTEL_UPDCR_REG);
+               }
+       }
+
+       iounmap(rcba_mem);
+       return 0;
+}
+
+/* Miscellaneous Port Configuration register */
+#define INTEL_MPC_REG 0xd8
+/* MPC: Invalid Receive Bus Number Check Enable */
+#define INTEL_MPC_REG_IRBNCE (1 << 26)
+
+static void pci_quirk_enable_intel_rp_mpc_acs(struct pci_dev *dev)
+{
+       u32 mpc;
+
+       /*
+        * When enabled, the IRBNCE bit of the MPC register enables the
+        * equivalent of PCI ACS Source Validation (PCI_ACS_SV), which
+        * ensures that requester IDs fall within the bus number range
+        * of the bridge.  Enable if not already.
+        */
+       pci_read_config_dword(dev, INTEL_MPC_REG, &mpc);
+       if (!(mpc & INTEL_MPC_REG_IRBNCE)) {
+               dev_info(&dev->dev, "Enabling MPC IRBNCE\n");
+               mpc |= INTEL_MPC_REG_IRBNCE;
+               pci_write_config_word(dev, INTEL_MPC_REG, mpc);
+       }
+}
+
+static int pci_quirk_enable_intel_pch_acs(struct pci_dev *dev)
+{
+       if (!pci_quirk_intel_pch_acs_match(dev))
+               return -ENOTTY;
+
+       if (pci_quirk_enable_intel_lpc_acs(dev)) {
+               dev_warn(&dev->dev, "Failed to enable Intel PCH ACS quirk\n");
+               return 0;
+       }
+
+       pci_quirk_enable_intel_rp_mpc_acs(dev);
+
+       dev->dev_flags |= PCI_DEV_FLAGS_ACS_ENABLED_QUIRK;
+
+       dev_info(&dev->dev, "Intel PCH root port ACS workaround enabled\n");
+
+       return 0;
+}
+
+static const struct pci_dev_enable_acs {
+       u16 vendor;
+       u16 device;
+       int (*enable_acs)(struct pci_dev *dev);
+} pci_dev_enable_acs[] = {
+       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_pch_acs },
+       { 0 }
+};
+
+void pci_dev_specific_enable_acs(struct pci_dev *dev)
+{
+       const struct pci_dev_enable_acs *i;
+       int ret;
+
+       for (i = pci_dev_enable_acs; i->enable_acs; i++) {
+               if ((i->vendor == dev->vendor ||
+                    i->vendor == (u16)PCI_ANY_ID) &&
+                   (i->device == dev->device ||
+                    i->device == (u16)PCI_ANY_ID)) {
+                       ret = i->enable_acs(dev);
+                       if (ret >= 0)
+                               return;
+               }
+       }
+}
index 5d595724e5f4deee3a3390a65bd85c1914bfaecb..c1839450d4d6cc4d77a5b37e983b7dbecdafe31b 100644 (file)
@@ -197,8 +197,10 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
 void pci_cleanup_rom(struct pci_dev *pdev)
 {
        struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
+
        if (res->flags & IORESOURCE_ROM_COPY) {
                kfree((void*)(unsigned long)res->start);
+               res->flags |= IORESOURCE_UNSET;
                res->flags &= ~IORESOURCE_ROM_COPY;
                res->start = 0;
                res->end = 0;
index 3ff2ac7c14e235c564b3b8d9c4d11609a4696fe5..4a1b972efe7f2fbb76c33467de665a16004fda37 100644 (file)
@@ -54,14 +54,14 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
 
 static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
 {
-       struct pci_buschild;
-       struct list_head *tmp;
+       struct pci_bus *child;
+       struct pci_bus *tmp;
 
        if(bus->number == busnr)
                return bus;
 
-       list_for_each(tmp, &bus->children) {
-               child = pci_do_find_bus(pci_bus_b(tmp), busnr);
+       list_for_each_entry(tmp, &bus->children, node) {
+               child = pci_do_find_bus(tmp, busnr);
                if(child)
                        return child;
        }
@@ -111,7 +111,7 @@ pci_find_next_bus(const struct pci_bus *from)
        down_read(&pci_bus_sem);
        n = from ? from->node.next : pci_root_buses.next;
        if (n != &pci_root_buses)
-               b = pci_bus_b(n);
+               b = list_entry(n, struct pci_bus, node);
        up_read(&pci_bus_sem);
        return b;
 }
index 5c060b152ce6aaffba7f1bd9844cdeaf1c56d605..7eed671d55861c4ef890b33a68cfbaa2d7ef47e0 100644 (file)
@@ -44,6 +44,9 @@ void pci_update_resource(struct pci_dev *dev, int resno)
        if (!res->flags)
                return;
 
+       if (res->flags & IORESOURCE_UNSET)
+               return;
+
        /*
         * Ignore non-moveable resources.  This might be legacy resources for
         * which no functional BAR register exists or another important
@@ -101,11 +104,6 @@ void pci_update_resource(struct pci_dev *dev, int resno)
 
        if (disable)
                pci_write_config_word(dev, PCI_COMMAND, cmd);
-
-       res->flags &= ~IORESOURCE_UNSET;
-       dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
-               resno, res, (unsigned long long)region.start,
-               (unsigned long long)region.end);
 }
 
 int pci_claim_resource(struct pci_dev *dev, int resource)
@@ -113,18 +111,23 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
        struct resource *res = &dev->resource[resource];
        struct resource *root, *conflict;
 
+       if (res->flags & IORESOURCE_UNSET) {
+               dev_info(&dev->dev, "can't claim BAR %d %pR: no address assigned\n",
+                        resource, res);
+               return -EINVAL;
+       }
+
        root = pci_find_parent_resource(dev, res);
        if (!root) {
-               dev_info(&dev->dev, "no compatible bridge window for %pR\n",
-                        res);
+               dev_info(&dev->dev, "can't claim BAR %d %pR: no compatible bridge window\n",
+                        resource, res);
                return -EINVAL;
        }
 
        conflict = request_resource_conflict(root, res);
        if (conflict) {
-               dev_info(&dev->dev,
-                        "address space collision: %pR conflicts with %s %pR\n",
-                        res, conflict->name, conflict);
+               dev_info(&dev->dev, "can't claim BAR %d %pR: address conflict with %s %pR\n",
+                        resource, res, conflict->name, conflict);
                return -EBUSY;
        }
 
@@ -263,6 +266,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
        resource_size_t align, size;
        int ret;
 
+       res->flags |= IORESOURCE_UNSET;
        align = pci_resource_alignment(dev, res);
        if (!align) {
                dev_info(&dev->dev, "BAR %d: can't assign %pR "
@@ -282,6 +286,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
                ret = pci_revert_fw_address(res, dev, resno, size);
 
        if (!ret) {
+               res->flags &= ~IORESOURCE_UNSET;
                res->flags &= ~IORESOURCE_STARTALIGN;
                dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
                if (resno < PCI_BRIDGE_RESOURCES)
@@ -297,6 +302,7 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
        resource_size_t new_size;
        int ret;
 
+       res->flags |= IORESOURCE_UNSET;
        if (!res->parent) {
                dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR "
                         "\n", resno, res);
@@ -307,6 +313,7 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
        new_size = resource_size(res) + addsize;
        ret = _pci_assign_resource(dev, resno, new_size, min_align);
        if (!ret) {
+               res->flags &= ~IORESOURCE_UNSET;
                res->flags &= ~IORESOURCE_STARTALIGN;
                dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
                if (resno < PCI_BRIDGE_RESOURCES)
@@ -336,9 +343,15 @@ int pci_enable_resources(struct pci_dev *dev, int mask)
                                (!(r->flags & IORESOURCE_ROM_ENABLE)))
                        continue;
 
+               if (r->flags & IORESOURCE_UNSET) {
+                       dev_err(&dev->dev, "can't enable device: BAR %d %pR not assigned\n",
+                               i, r);
+                       return -EINVAL;
+               }
+
                if (!r->parent) {
-                       dev_err(&dev->dev, "device not available "
-                               "(can't reserve %pR)\n", r);
+                       dev_err(&dev->dev, "can't enable device: BAR %d %pR not claimed\n",
+                               i, r);
                        return -EINVAL;
                }
 
index 8485761e76af11821f24e64bc3474dd0f5f487d4..946f90ef60203a7e3a06c89041ea3c50e2a9b364 100644 (file)
@@ -1076,7 +1076,7 @@ static void yenta_config_init(struct yenta_socket *socket)
  */
 static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
 {
-       struct list_head *tmp;
+       struct pci_bus *sibling;
        unsigned char upper_limit;
        /*
         * We only check and fix the parent bridge: All systems which need
@@ -1095,18 +1095,18 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
        /* stay within the limits of the bus range of the parent: */
        upper_limit = bridge_to_fix->parent->busn_res.end;
 
-       /* check the bus ranges of all silbling bridges to prevent overlap */
-       list_for_each(tmp, &bridge_to_fix->parent->children) {
-               struct pci_bus *silbling = pci_bus_b(tmp);
+       /* check the bus ranges of all sibling bridges to prevent overlap */
+       list_for_each_entry(sibling, &bridge_to_fix->parent->children,
+                       node) {
                /*
-                * If the silbling has a higher secondary bus number
+                * If the sibling has a higher secondary bus number
                 * and it's secondary is equal or smaller than our
                 * current upper limit, set the new upper limit to
-                * the bus number below the silbling's range:
+                * the bus number below the sibling's range:
                 */
-               if (silbling->busn_res.start > bridge_to_fix->busn_res.end
-                   && silbling->busn_res.start <= upper_limit)
-                       upper_limit = silbling->busn_res.start - 1;
+               if (sibling->busn_res.start > bridge_to_fix->busn_res.end
+                   && sibling->busn_res.start <= upper_limit)
+                       upper_limit = sibling->busn_res.start - 1;
        }
 
        /* Show that the wanted subordinate number is not possible: */
index 210357691dc0a06e65b522e5847321e62c43541c..9dd49c9839ac6de24496d37e0f4020e424415a1d 100644 (file)
@@ -482,15 +482,19 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
                for (i = 0; i < nvec; i++)
                        vdev->msix[i].entry = i;
 
-               ret = pci_enable_msix(pdev, vdev->msix, nvec);
-               if (ret) {
+               ret = pci_enable_msix_range(pdev, vdev->msix, 1, nvec);
+               if (ret < nvec) {
+                       if (ret > 0)
+                               pci_disable_msix(pdev);
                        kfree(vdev->msix);
                        kfree(vdev->ctx);
                        return ret;
                }
        } else {
-               ret = pci_enable_msi_block(pdev, nvec);
-               if (ret) {
+               ret = pci_enable_msi_range(pdev, 1, nvec);
+               if (ret < nvec) {
+                       if (ret > 0)
+                               pci_disable_msi(pdev);
                        kfree(vdev->ctx);
                        return ret;
                }
index 451823cb88372b2130793abbbb4e17869af34faf..94a37cd7fbda47ce85c6ff1a2e82772c4582045b 100644 (file)
@@ -13,7 +13,6 @@
 
 extern int pxm_to_node(int);
 extern int node_to_pxm(int);
-extern void __acpi_map_pxm_to_node(int, int);
 extern int acpi_map_pxm_to_node(int);
 extern unsigned char acpi_srat_revision;
 
index 6a15dddbaa09a1e55eaa09e56b4582fee94f4813..7a8f2cd66c8bb9ff5dc866f1f6f28da10b69ccbe 100644 (file)
@@ -263,14 +263,9 @@ extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);
 extern void acpi_osi_setup(char *str);
 
 #ifdef CONFIG_ACPI_NUMA
-int acpi_get_pxm(acpi_handle handle);
-int acpi_get_node(acpi_handle *handle);
+int acpi_get_node(acpi_handle handle);
 #else
-static inline int acpi_get_pxm(acpi_handle handle)
-{
-       return 0;
-}
-static inline int acpi_get_node(acpi_handle *handle)
+static inline int acpi_get_node(acpi_handle handle)
 {
        return 0;
 }
index 89b7c24a36e9fd7a8af6fea77bf7986507e86c65..5e3a906cc089a721eaacdf390e3e30927fd37434 100644 (file)
@@ -51,7 +51,7 @@ struct resource {
 
 #define IORESOURCE_EXCLUSIVE   0x08000000      /* Userland may not map this resource */
 #define IORESOURCE_DISABLED    0x10000000
-#define IORESOURCE_UNSET       0x20000000
+#define IORESOURCE_UNSET       0x20000000      /* No address assigned yet */
 #define IORESOURCE_AUTO                0x40000000
 #define IORESOURCE_BUSY                0x80000000      /* Driver has marked this resource busy */
 
@@ -169,6 +169,16 @@ static inline unsigned long resource_type(const struct resource *res)
 {
        return res->flags & IORESOURCE_TYPE_BITS;
 }
+/* True iff r1 completely contains r2 */
+static inline bool resource_contains(struct resource *r1, struct resource *r2)
+{
+       if (resource_type(r1) != resource_type(r2))
+               return false;
+       if (r1->flags & IORESOURCE_UNSET || r2->flags & IORESOURCE_UNSET)
+               return false;
+       return r1->start <= r2->start && r1->end >= r2->end;
+}
+
 
 /* Convenience shorthand with allocation */
 #define request_region(start,n,name)           __request_region(&ioport_resource, (start), (n), (name), 0)
index 33aa2caf0f0c9e5bd9e7cf07c8d92b08207be959..aab57b4abe7fce4ef59adc14db6400d3a6af57cc 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/atomic.h>
 #include <linux/device.h>
 #include <linux/io.h>
-#include <linux/irqreturn.h>
 #include <uapi/linux/pci.h>
 
 #include <linux/pci_ids.h>
@@ -170,6 +169,8 @@ enum pci_dev_flags {
        PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
        /* Provide indication device is assigned by a Virtual Machine Manager */
        PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4,
+       /* Flag for quirk use to store if quirk-specific ACS is enabled */
+       PCI_DEV_FLAGS_ACS_ENABLED_QUIRK = (__force pci_dev_flags_t) 8,
 };
 
 enum pci_irq_reroute_variant {
@@ -461,7 +462,6 @@ struct pci_bus {
        unsigned int            is_added:1;
 };
 
-#define pci_bus_b(n)   list_entry(n, struct pci_bus, node)
 #define to_pci_bus(n)  container_of(n, struct pci_bus, dev)
 
 /*
@@ -1066,7 +1066,7 @@ void pci_bus_remove_resources(struct pci_bus *bus);
 int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
                        struct resource *res, resource_size_t size,
                        resource_size_t align, resource_size_t min,
-                       unsigned int type_mask,
+                       unsigned long type_mask,
                        resource_size_t (*alignf)(void *,
                                                  const struct resource *,
                                                  resource_size_t,
@@ -1530,6 +1530,7 @@ enum pci_fixup_pass {
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
 struct pci_dev *pci_get_dma_source(struct pci_dev *dev);
 int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags);
+void pci_dev_specific_enable_acs(struct pci_dev *dev);
 #else
 static inline void pci_fixup_device(enum pci_fixup_pass pass,
                                    struct pci_dev *dev) { }
@@ -1542,6 +1543,7 @@ static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev,
 {
        return -ENOTTY;
 }
+static inline void pci_dev_specific_enable_acs(struct pci_dev *dev) { }
 #endif
 
 void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
@@ -1597,7 +1599,6 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
 #ifdef CONFIG_PCI_IOV
 int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
 void pci_disable_sriov(struct pci_dev *dev);
-irqreturn_t pci_sriov_migration(struct pci_dev *dev);
 int pci_num_vf(struct pci_dev *dev);
 int pci_vfs_assigned(struct pci_dev *dev);
 int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
@@ -1606,8 +1607,6 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev);
 static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
 { return -ENODEV; }
 static inline void pci_disable_sriov(struct pci_dev *dev) { }
-static inline irqreturn_t pci_sriov_migration(struct pci_dev *dev)
-{ return IRQ_NONE; }
 static inline int pci_num_vf(struct pci_dev *dev) { return 0; }
 static inline int pci_vfs_assigned(struct pci_dev *dev)
 { return 0; }
index 3f285dce9347191537b8d13f8db53f869d4744ad..673061c06da182dbe02993d6f332168f8b3b3c96 100644 (file)
@@ -432,11 +432,6 @@ static void resource_clip(struct resource *res, resource_size_t min,
                res->end = max;
 }
 
-static bool resource_contains(struct resource *res1, struct resource *res2)
-{
-       return res1->start <= res2->start && res1->end >= res2->end;
-}
-
 /*
  * Find empty slot in the resource tree with the given range and
  * alignment constraints
@@ -471,10 +466,11 @@ static int __find_resource(struct resource *root, struct resource *old,
                arch_remove_reservations(&tmp);
 
                /* Check for overflow after ALIGN() */
-               avail = *new;
                avail.start = ALIGN(tmp.start, constraint->align);
                avail.end = tmp.end;
+               avail.flags = new->flags & ~IORESOURCE_UNSET;
                if (avail.start >= tmp.start) {
+                       alloc.flags = avail.flags;
                        alloc.start = constraint->alignf(constraint->alignf_data, &avail,
                                        size, constraint->align);
                        alloc.end = alloc.start + size - 1;
@@ -949,8 +945,8 @@ struct resource * __request_region(struct resource *parent,
        res->name = name;
        res->start = start;
        res->end = start + n - 1;
-       res->flags = IORESOURCE_BUSY;
-       res->flags |= flags;
+       res->flags = resource_type(parent);
+       res->flags |= IORESOURCE_BUSY | flags;
 
        write_lock(&resource_lock);
 
index 185b6d300ebcedb86c0214c7007716ac868c17a1..5e2cf6f342f8cac5dad0d91481c0622c36542179 100644 (file)
@@ -719,10 +719,15 @@ char *resource_string(char *buf, char *end, struct resource *res,
                specp = &mem_spec;
                decode = 0;
        }
-       p = number(p, pend, res->start, *specp);
-       if (res->start != res->end) {
-               *p++ = '-';
-               p = number(p, pend, res->end, *specp);
+       if (decode && res->flags & IORESOURCE_UNSET) {
+               p = string(p, pend, "size ", str_spec);
+               p = number(p, pend, resource_size(res), *specp);
+       } else {
+               p = number(p, pend, res->start, *specp);
+               if (res->start != res->end) {
+                       *p++ = '-';
+                       p = number(p, pend, res->end, *specp);
+               }
        }
        if (decode) {
                if (res->flags & IORESOURCE_MEM_64)