Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 11 Dec 2009 20:18:16 +0000 (12:18 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 11 Dec 2009 20:18:16 +0000 (12:18 -0800)
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (109 commits)
  PCI: fix coding style issue in pci_save_state()
  PCI: add pci_request_acs
  PCI: fix BUG_ON triggered by logical PCIe root port removal
  PCI: remove ifdefed pci_cleanup_aer_correct_error_status
  PCI: unconditionally clear AER uncorr status register during cleanup
  x86/PCI: claim SR-IOV BARs in pcibios_allocate_resource
  PCI: portdrv: remove redundant definitions
  PCI: portdrv: remove unnecessary struct pcie_port_data
  PCI: portdrv: minor cleanup for pcie_port_device_register
  PCI: portdrv: add missing irq cleanup
  PCI: portdrv: enable device before irq initialization
  PCI: portdrv: cleanup service irqs initialization
  PCI: portdrv: check capabilities first
  PCI: portdrv: move PME capability check
  PCI: portdrv: remove redundant pcie type calculation
  PCI: portdrv: cleanup pcie_device registration
  PCI: portdrv: remove redundant pcie_port_device_probe
  PCI: Always set prefetchable base/limit upper32 registers
  PCI: read-modify-write the pcie device control register when initiating pcie flr
  PCI: show dma_mask bits in /sys
  ...

Fixed up conflicts in:
arch/x86/kernel/amd_iommu_init.c
drivers/pci/dmar.c
drivers/pci/hotplug/acpiphp_glue.c

83 files changed:
arch/ia64/include/asm/xen/hypervisor.h
arch/ia64/pci/pci.c
arch/sparc/include/asm/pci_64.h
arch/sparc/kernel/pci.c
arch/x86/include/asm/pci_x86.h
arch/x86/include/asm/xen/hypervisor.h
arch/x86/kernel/amd_iommu_init.c
arch/x86/pci/Makefile
arch/x86/pci/acpi.c
arch/x86/pci/amd_bus.c
arch/x86/pci/bus_numa.c [new file with mode: 0644]
arch/x86/pci/bus_numa.h [new file with mode: 0644]
arch/x86/pci/common.c
arch/x86/pci/early.c
arch/x86/pci/i386.c
arch/x86/pci/intel_bus.c [new file with mode: 0644]
arch/x86/pci/mmconfig-shared.c
arch/x86/pci/mmconfig_32.c
arch/x86/pci/mmconfig_64.c
arch/x86/xen/enlighten.c
drivers/acpi/Makefile
drivers/acpi/hest.c [new file with mode: 0644]
drivers/block/xen-blkfront.c
drivers/char/hvc_xen.c
drivers/input/xen-kbdfront.c
drivers/net/xen-netfront.c
drivers/pci/Kconfig
drivers/pci/Makefile
drivers/pci/dmar.c
drivers/pci/hotplug/Makefile
drivers/pci/hotplug/acpi_pcihp.c
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/ibmphp_hpc.c
drivers/pci/hotplug/pci_hotplug_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/pcihp_slot.c
drivers/pci/intel-iommu.c
drivers/pci/intr_remapping.c
drivers/pci/ioapic.c [new file with mode: 0644]
drivers/pci/iov.c
drivers/pci/pci-acpi.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/aer_inject.c
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aer/ecrc.c
drivers/pci/pcie/aspm.c
drivers/pci/pcie/portdrv.h
drivers/pci/pcie/portdrv_bus.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/search.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/pcmcia/cardbus.c
drivers/pnp/quirks.c
drivers/pnp/resource.c
drivers/pnp/support.c
drivers/pnp/system.c
drivers/video/xen-fbfront.c
drivers/xen/balloon.c
drivers/xen/cpu_hotplug.c
drivers/xen/evtchn.c
drivers/xen/grant-table.c
drivers/xen/sys-hypervisor.c
drivers/xen/xenbus/xenbus_probe.c
drivers/xen/xenfs/super.c
include/acpi/acpi_hest.h [new file with mode: 0644]
include/linux/pci.h
include/linux/pci_regs.h
include/linux/pcieport_if.h
include/xen/xen.h [new file with mode: 0644]
kernel/resource.c
lib/vsprintf.c

index 88afb54501e48feba6c24d6f25c7f5967b308c89..67455c2ed2b12d85acbaf1087da08d4e57739f76 100644 (file)
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>     /* to compile feature.c */
 #include <xen/features.h>              /* to comiple xen-netfront.c */
+#include <xen/xen.h>
 #include <asm/xen/hypercall.h>
 
-/* xen_domain_type is set before executing any C code by early_xen_setup */
-enum xen_domain_type {
-       XEN_NATIVE,     /* running on bare hardware */
-       XEN_PV_DOMAIN,  /* running in a PV domain */
-       XEN_HVM_DOMAIN, /* running in a Xen hvm domain*/
-};
-
-#ifdef CONFIG_XEN
-extern enum xen_domain_type xen_domain_type;
-#else
-#define xen_domain_type                XEN_NATIVE
-#endif
-
-#define xen_domain()           (xen_domain_type != XEN_NATIVE)
-#define xen_pv_domain()                (xen_domain() &&                        \
-                                xen_domain_type == XEN_PV_DOMAIN)
-#define xen_hvm_domain()       (xen_domain() &&                        \
-                                xen_domain_type == XEN_HVM_DOMAIN)
-
-#ifdef CONFIG_XEN_DOM0
-#define xen_initial_domain()   (xen_pv_domain() &&                     \
-                                (xen_start_info->flags & SIF_INITDOMAIN))
-#else
-#define xen_initial_domain()   (0)
-#endif
-
-
 #ifdef CONFIG_XEN
 extern struct shared_info *HYPERVISOR_shared_info;
 extern struct start_info *xen_start_info;
index c0fca2c1c858372493675695f9a5341200c139ae..df639db779f95192a71d93d5895113080b1bf41a 100644 (file)
@@ -131,6 +131,7 @@ alloc_pci_controller (int seg)
 }
 
 struct pci_root_info {
+       struct acpi_device *bridge;
        struct pci_controller *controller;
        char *name;
 };
@@ -297,9 +298,20 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
        window->offset = offset;
 
        if (insert_resource(root, &window->resource)) {
-               printk(KERN_ERR "alloc 0x%llx-0x%llx from %s for %s failed\n",
-                       window->resource.start, window->resource.end,
-                       root->name, info->name);
+               dev_err(&info->bridge->dev,
+                       "can't allocate host bridge window %pR\n",
+                       &window->resource);
+       } else {
+               if (offset)
+                       dev_info(&info->bridge->dev, "host bridge window %pR "
+                                "(PCI address [%#llx-%#llx])\n",
+                                &window->resource,
+                                window->resource.start - offset,
+                                window->resource.end - offset);
+               else
+                       dev_info(&info->bridge->dev,
+                                "host bridge window %pR\n",
+                                &window->resource);
        }
 
        return AE_OK;
@@ -319,8 +331,9 @@ pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl)
                    (res->end - res->start < 16))
                        continue;
                if (j >= PCI_BUS_NUM_RESOURCES) {
-                       printk("Ignoring range [%#llx-%#llx] (%lx)\n",
-                                       res->start, res->end, res->flags);
+                       dev_warn(&bus->dev,
+                                "ignoring host bridge window %pR (no space)\n",
+                                res);
                        continue;
                }
                bus->resource[j++] = res;
@@ -364,6 +377,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus)
                        goto out3;
 
                sprintf(name, "PCI Bus %04x:%02x", domain, bus);
+               info.bridge = device;
                info.controller = controller;
                info.name = name;
                acpi_walk_resources(device->handle, METHOD_NAME__CRS,
@@ -720,9 +734,6 @@ int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
        return ret;
 }
 
-/* It's defined in drivers/pci/pci.c */
-extern u8 pci_cache_line_size;
-
 /**
  * set_pci_cacheline_size - determine cacheline size for PCI devices
  *
@@ -731,7 +742,7 @@ extern u8 pci_cache_line_size;
  *
  * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info().
  */
-static void __init set_pci_cacheline_size(void)
+static void __init set_pci_dfl_cacheline_size(void)
 {
        unsigned long levels, unique_caches;
        long status;
@@ -751,7 +762,7 @@ static void __init set_pci_cacheline_size(void)
                        "(status=%ld)\n", __func__, status);
                return;
        }
-       pci_cache_line_size = (1 << cci.pcci_line_size) / 4;
+       pci_dfl_cache_line_size = (1 << cci.pcci_line_size) / 4;
 }
 
 u64 ia64_dma_get_required_mask(struct device *dev)
@@ -782,7 +793,7 @@ EXPORT_SYMBOL_GPL(dma_get_required_mask);
 
 static int __init pcibios_init(void)
 {
-       set_pci_cacheline_size();
+       set_pci_dfl_cacheline_size();
        return 0;
 }
 
index b63e51c3c3ee2fdb959b13f5e0fd9511bc344d09..b0576df6ec832ab6996436a6a554dbb2dcd62257 100644 (file)
@@ -16,8 +16,6 @@
 
 #define PCI_IRQ_NONE           0xffffffff
 
-#define PCI_CACHE_LINE_BYTES   64
-
 static inline void pcibios_set_master(struct pci_dev *dev)
 {
        /* No special bus mastering setup handling */
index c68648662802a122932ccece24ad31c250ddb77c..b85374f7cf945f3d4760dbd6fe739455ea52b33b 100644 (file)
@@ -1081,3 +1081,10 @@ void pci_resource_to_user(const struct pci_dev *pdev, int bar,
        *start = rp->start - offset;
        *end = rp->end - offset;
 }
+
+static int __init pcibios_init(void)
+{
+       pci_dfl_cache_line_size = 64 >> 2;
+       return 0;
+}
+subsys_initcall(pcibios_init);
index b399988eee3a3105e60be5fe760089d6cf57d3f0..b4bf9a942ed0810418613f75b156e328fc0fd5d9 100644 (file)
@@ -118,11 +118,27 @@ extern int __init pcibios_init(void);
 
 /* pci-mmconfig.c */
 
+/* "PCI MMCONFIG %04x [bus %02x-%02x]" */
+#define PCI_MMCFG_RESOURCE_NAME_LEN (22 + 4 + 2 + 2)
+
+struct pci_mmcfg_region {
+       struct list_head list;
+       struct resource res;
+       u64 address;
+       char __iomem *virt;
+       u16 segment;
+       u8 start_bus;
+       u8 end_bus;
+       char name[PCI_MMCFG_RESOURCE_NAME_LEN];
+};
+
 extern int __init pci_mmcfg_arch_init(void);
 extern void __init pci_mmcfg_arch_free(void);
+extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
+
+extern struct list_head pci_mmcfg_list;
 
-extern struct acpi_mcfg_allocation *pci_mmcfg_config;
-extern int pci_mmcfg_config_num;
+#define PCI_MMCFG_BUS_OFFSET(bus)      ((bus) << 20)
 
 /*
  * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
index d5b7e90c0edfd3ca1bf7d05e3f4c4e642f8e6fb7..396ff4cc8ed480b7bc306f63091b88f6dda00442 100644 (file)
 extern struct shared_info *HYPERVISOR_shared_info;
 extern struct start_info *xen_start_info;
 
-enum xen_domain_type {
-       XEN_NATIVE,             /* running on bare hardware    */
-       XEN_PV_DOMAIN,          /* running in a PV domain      */
-       XEN_HVM_DOMAIN,         /* running in a Xen hvm domain */
-};
-
-#ifdef CONFIG_XEN
-extern enum xen_domain_type xen_domain_type;
-#else
-#define xen_domain_type                XEN_NATIVE
-#endif
-
-#define xen_domain()           (xen_domain_type != XEN_NATIVE)
-#define xen_pv_domain()                (xen_domain() &&                        \
-                                xen_domain_type == XEN_PV_DOMAIN)
-#define xen_hvm_domain()       (xen_domain() &&                        \
-                                xen_domain_type == XEN_HVM_DOMAIN)
-
-#ifdef CONFIG_XEN_DOM0
-#include <xen/interface/xen.h>
-
-#define xen_initial_domain()   (xen_pv_domain() && \
-                                xen_start_info->flags & SIF_INITDOMAIN)
-#else  /* !CONFIG_XEN_DOM0 */
-#define xen_initial_domain()   (0)
-#endif /* CONFIG_XEN_DOM0 */
-
 #endif /* _ASM_X86_XEN_HYPERVISOR_H */
index 7ffc39965233ce570a7b734f12636ce05e403d1e..9c4a6f7475525469760ca7cc43ad98d7e842c8f2 100644 (file)
@@ -1336,6 +1336,9 @@ void __init amd_iommu_detect(void)
                iommu_detected = 1;
                amd_iommu_detected = 1;
                x86_init.iommu.iommu_init = amd_iommu_init;
+
+               /* Make sure ACS will be enabled */
+               pci_request_acs();
        }
 }
 
index d49202e740eaf5a224897e4991c9eec951657918..564b008a51c7abdee986f03c1ccfe3a09894a93a 100644 (file)
@@ -15,3 +15,8 @@ obj-$(CONFIG_X86_NUMAQ)               += numaq_32.o
 
 obj-y                          += common.o early.o
 obj-y                          += amd_bus.o
+obj-$(CONFIG_X86_64)           += bus_numa.o intel_bus.o
+
+ifeq ($(CONFIG_PCI_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
index 1014eb4bfc37ac15cec9e3b24b3f980a1a52e7d9..959e548a7039e81a85cdd0e7eb114a86f91a05c5 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/pci_x86.h>
 
 struct pci_root_info {
+       struct acpi_device *bridge;
        char *name;
        unsigned int res_num;
        struct resource *res;
@@ -58,6 +59,30 @@ bus_has_transparent_bridge(struct pci_bus *bus)
        return false;
 }
 
+static void
+align_resource(struct acpi_device *bridge, struct resource *res)
+{
+       int align = (res->flags & IORESOURCE_MEM) ? 16 : 4;
+
+       /*
+        * Host bridge windows are not BARs, but the decoders on the PCI side
+        * that claim this address space have starting alignment and length
+        * constraints, so fix any obvious BIOS goofs.
+        */
+       if (!IS_ALIGNED(res->start, align)) {
+               dev_printk(KERN_DEBUG, &bridge->dev,
+                          "host bridge window %pR invalid; "
+                          "aligning start to %d-byte boundary\n", res, align);
+               res->start &= ~(align - 1);
+       }
+       if (!IS_ALIGNED(res->end + 1, align)) {
+               dev_printk(KERN_DEBUG, &bridge->dev,
+                          "host bridge window %pR invalid; "
+                          "aligning end to %d-byte boundary\n", res, align);
+               res->end = ALIGN(res->end, align) - 1;
+       }
+}
+
 static acpi_status
 setup_resource(struct acpi_resource *acpi_res, void *data)
 {
@@ -91,11 +116,12 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
        start = addr.minimum + addr.translation_offset;
        end = start + addr.address_length - 1;
        if (info->res_num >= max_root_bus_resources) {
-               printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx "
-                       "from %s for %s due to _CRS returning more than "
-                       "%d resource descriptors\n", (unsigned long) start,
-                       (unsigned long) end, root->name, info->name,
-                       max_root_bus_resources);
+               if (pci_probe & PCI_USE__CRS)
+                       printk(KERN_WARNING "PCI: Failed to allocate "
+                              "0x%lx-0x%lx from %s for %s due to _CRS "
+                              "returning more than %d resource descriptors\n",
+                              (unsigned long) start, (unsigned long) end,
+                              root->name, info->name, max_root_bus_resources);
                return AE_OK;
        }
 
@@ -105,14 +131,28 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
        res->start = start;
        res->end = end;
        res->child = NULL;
+       align_resource(info->bridge, res);
+
+       if (!(pci_probe & PCI_USE__CRS)) {
+               dev_printk(KERN_DEBUG, &info->bridge->dev,
+                          "host bridge window %pR (ignored)\n", res);
+               return AE_OK;
+       }
 
        if (insert_resource(root, res)) {
-               printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
-                       "from %s for %s\n", (unsigned long) res->start,
-                       (unsigned long) res->end, root->name, info->name);
+               dev_err(&info->bridge->dev,
+                       "can't allocate host bridge window %pR\n", res);
        } else {
                info->bus->resource[info->res_num] = res;
                info->res_num++;
+               if (addr.translation_offset)
+                       dev_info(&info->bridge->dev, "host bridge window %pR "
+                                "(PCI address [%#llx-%#llx])\n",
+                                res, res->start - addr.translation_offset,
+                                res->end - addr.translation_offset);
+               else
+                       dev_info(&info->bridge->dev,
+                                "host bridge window %pR\n", res);
        }
        return AE_OK;
 }
@@ -124,6 +164,12 @@ get_current_resources(struct acpi_device *device, int busnum,
        struct pci_root_info info;
        size_t size;
 
+       if (!(pci_probe & PCI_USE__CRS))
+               dev_info(&device->dev,
+                        "ignoring host bridge windows from ACPI; "
+                        "boot with \"pci=use_crs\" to use them\n");
+
+       info.bridge = device;
        info.bus = bus;
        info.res_num = 0;
        acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
@@ -163,8 +209,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
 #endif
 
        if (domain && !pci_domains_supported) {
-               printk(KERN_WARNING "PCI: Multiple domains not supported "
-                      "(dom %d, bus %d)\n", domain, busnum);
+               printk(KERN_WARNING "pci_bus %04x:%02x: "
+                      "ignored (multiple domains not supported)\n",
+                      domain, busnum);
                return NULL;
        }
 
@@ -188,7 +235,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
         */
        sd = kzalloc(sizeof(*sd), GFP_KERNEL);
        if (!sd) {
-               printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
+               printk(KERN_WARNING "pci_bus %04x:%02x: "
+                      "ignored (out of memory)\n", domain, busnum);
                return NULL;
        }
 
@@ -209,9 +257,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
        } else {
                bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd);
                if (bus) {
-                       if (pci_probe & PCI_USE__CRS)
-                               get_current_resources(device, busnum, domain,
-                                                       bus);
+                       get_current_resources(device, busnum, domain, bus);
                        bus->subordinate = pci_scan_child_bus(bus);
                }
        }
index 572ee9782f2afdf75ca1af76ae172ce01ec9a3a8..95ecbd495955094ac22c7502fe992ea2af7ad444 100644 (file)
@@ -6,10 +6,10 @@
 
 #ifdef CONFIG_X86_64
 #include <asm/pci-direct.h>
-#include <asm/mpspec.h>
-#include <linux/cpumask.h>
 #endif
 
+#include "bus_numa.h"
+
 /*
  * This discovers the pcibus <-> node mapping on AMD K8.
  * also get peer root bus resource for io,mmio
 
 #ifdef CONFIG_X86_64
 
-/*
- * sub bus (transparent) will use entres from 3 to store extra from root,
- * so need to make sure have enought slot there, increase PCI_BUS_NUM_RESOURCES?
- */
-#define RES_NUM 16
-struct pci_root_info {
-       char name[12];
-       unsigned int res_num;
-       struct resource res[RES_NUM];
-       int bus_min;
-       int bus_max;
-       int node;
-       int link;
-};
-
-/* 4 at this time, it may become to 32 */
-#define PCI_ROOT_NR 4
-static int pci_root_num;
-static struct pci_root_info pci_root_info[PCI_ROOT_NR];
-
-void x86_pci_root_bus_res_quirks(struct pci_bus *b)
-{
-       int i;
-       int j;
-       struct pci_root_info *info;
-
-       /* don't go for it if _CRS is used already */
-       if (b->resource[0] != &ioport_resource ||
-           b->resource[1] != &iomem_resource)
-               return;
-
-       /* if only one root bus, don't need to anything */
-       if (pci_root_num < 2)
-               return;
-
-       for (i = 0; i < pci_root_num; i++) {
-               if (pci_root_info[i].bus_min == b->number)
-                       break;
-       }
-
-       if (i == pci_root_num)
-               return;
-
-       printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n",
-                       b->number);
-
-       info = &pci_root_info[i];
-       for (j = 0; j < info->res_num; j++) {
-               struct resource *res;
-               struct resource *root;
-
-               res = &info->res[j];
-               b->resource[j] = res;
-               if (res->flags & IORESOURCE_IO)
-                       root = &ioport_resource;
-               else
-                       root = &iomem_resource;
-               insert_resource(root, res);
-       }
-}
-
 #define RANGE_NUM 16
 
 struct res_range {
@@ -130,52 +69,6 @@ static void __init update_range(struct res_range *range, size_t start,
        }
 }
 
-static void __init update_res(struct pci_root_info *info, size_t start,
-                             size_t end, unsigned long flags, int merge)
-{
-       int i;
-       struct resource *res;
-
-       if (!merge)
-               goto addit;
-
-       /* try to merge it with old one */
-       for (i = 0; i < info->res_num; i++) {
-               size_t final_start, final_end;
-               size_t common_start, common_end;
-
-               res = &info->res[i];
-               if (res->flags != flags)
-                       continue;
-
-               common_start = max((size_t)res->start, start);
-               common_end = min((size_t)res->end, end);
-               if (common_start > common_end + 1)
-                       continue;
-
-               final_start = min((size_t)res->start, start);
-               final_end = max((size_t)res->end, end);
-
-               res->start = final_start;
-               res->end = final_end;
-               return;
-       }
-
-addit:
-
-       /* need to add that */
-       if (info->res_num >= RES_NUM)
-               return;
-
-       res = &info->res[info->res_num];
-       res->name = info->name;
-       res->flags = flags;
-       res->start = start;
-       res->end = end;
-       res->child = NULL;
-       info->res_num++;
-}
-
 struct pci_hostbridge_probe {
        u32 bus;
        u32 slot;
@@ -230,7 +123,6 @@ static int __init early_fill_mp_bus_info(void)
        int j;
        unsigned bus;
        unsigned slot;
-       int found;
        int node;
        int link;
        int def_node;
@@ -247,7 +139,7 @@ static int __init early_fill_mp_bus_info(void)
        if (!early_pci_allowed())
                return -1;
 
-       found = 0;
+       found_all_numa_early = 0;
        for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
                u32 id;
                u16 device;
@@ -261,12 +153,12 @@ static int __init early_fill_mp_bus_info(void)
                device = (id>>16) & 0xffff;
                if (pci_probes[i].vendor == vendor &&
                    pci_probes[i].device == device) {
-                       found = 1;
+                       found_all_numa_early = 1;
                        break;
                }
        }
 
-       if (!found)
+       if (!found_all_numa_early)
                return 0;
 
        pci_root_num = 0;
@@ -488,7 +380,7 @@ static int __init early_fill_mp_bus_info(void)
                info = &pci_root_info[i];
                res_num = info->res_num;
                busnum = info->bus_min;
-               printk(KERN_DEBUG "bus: [%02x,%02x] on node %x link %x\n",
+               printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n",
                       info->bus_min, info->bus_max, info->node, info->link);
                for (j = 0; j < res_num; j++) {
                        res = &info->res[j];
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
new file mode 100644 (file)
index 0000000..145df00
--- /dev/null
@@ -0,0 +1,101 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include "bus_numa.h"
+
+int pci_root_num;
+struct pci_root_info pci_root_info[PCI_ROOT_NR];
+int found_all_numa_early;
+
+void x86_pci_root_bus_res_quirks(struct pci_bus *b)
+{
+       int i;
+       int j;
+       struct pci_root_info *info;
+
+       /* don't go for it if _CRS is used already */
+       if (b->resource[0] != &ioport_resource ||
+           b->resource[1] != &iomem_resource)
+               return;
+
+       if (!pci_root_num)
+               return;
+
+       /* for amd, if only one root bus, don't need to do anything */
+       if (pci_root_num < 2 && found_all_numa_early)
+               return;
+
+       for (i = 0; i < pci_root_num; i++) {
+               if (pci_root_info[i].bus_min == b->number)
+                       break;
+       }
+
+       if (i == pci_root_num)
+               return;
+
+       printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n",
+                       b->number);
+
+       info = &pci_root_info[i];
+       for (j = 0; j < info->res_num; j++) {
+               struct resource *res;
+               struct resource *root;
+
+               res = &info->res[j];
+               b->resource[j] = res;
+               if (res->flags & IORESOURCE_IO)
+                       root = &ioport_resource;
+               else
+                       root = &iomem_resource;
+               insert_resource(root, res);
+       }
+}
+
+void __init update_res(struct pci_root_info *info, size_t start,
+                             size_t end, unsigned long flags, int merge)
+{
+       int i;
+       struct resource *res;
+
+       if (start > end)
+               return;
+
+       if (!merge)
+               goto addit;
+
+       /* try to merge it with old one */
+       for (i = 0; i < info->res_num; i++) {
+               size_t final_start, final_end;
+               size_t common_start, common_end;
+
+               res = &info->res[i];
+               if (res->flags != flags)
+                       continue;
+
+               common_start = max((size_t)res->start, start);
+               common_end = min((size_t)res->end, end);
+               if (common_start > common_end + 1)
+                       continue;
+
+               final_start = min((size_t)res->start, start);
+               final_end = max((size_t)res->end, end);
+
+               res->start = final_start;
+               res->end = final_end;
+               return;
+       }
+
+addit:
+
+       /* need to add that */
+       if (info->res_num >= RES_NUM)
+               return;
+
+       res = &info->res[info->res_num];
+       res->name = info->name;
+       res->flags = flags;
+       res->start = start;
+       res->end = end;
+       res->child = NULL;
+       info->res_num++;
+}
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
new file mode 100644 (file)
index 0000000..adbc23f
--- /dev/null
@@ -0,0 +1,27 @@
+#ifdef CONFIG_X86_64
+
+/*
+ * sub bus (transparent) will use entres from 3 to store extra from
+ * root, so need to make sure we have enough slot there, Should we
+ * increase PCI_BUS_NUM_RESOURCES?
+ */
+#define RES_NUM 16
+struct pci_root_info {
+       char name[12];
+       unsigned int res_num;
+       struct resource res[RES_NUM];
+       int bus_min;
+       int bus_max;
+       int node;
+       int link;
+};
+
+/* 4 at this time, it may become to 32 */
+#define PCI_ROOT_NR 4
+extern int pci_root_num;
+extern struct pci_root_info pci_root_info[PCI_ROOT_NR];
+extern int found_all_numa_early;
+
+extern void update_res(struct pci_root_info *info, size_t start,
+                             size_t end, unsigned long flags, int merge);
+#endif
index 1331fcf261433b72c9d0a4620326a3898f1761fa..d2552c68e94d9670a7086c2eca1258a453c1a516 100644 (file)
@@ -410,8 +410,6 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
        return bus;
 }
 
-extern u8 pci_cache_line_size;
-
 int __init pcibios_init(void)
 {
        struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -422,15 +420,19 @@ int __init pcibios_init(void)
        }
 
        /*
-        * Assume PCI cacheline size of 32 bytes for all x86s except K7/K8
-        * and P4. It's also good for 386/486s (which actually have 16)
+        * Set PCI cacheline size to that of the CPU if the CPU has reported it.
+        * (For older CPUs that don't support cpuid, we se it to 32 bytes
+        * It's also good for 386/486s (which actually have 16)
         * as quite a few PCI devices do not support smaller values.
         */
-       pci_cache_line_size = 32 >> 2;
-       if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD)
-               pci_cache_line_size = 64 >> 2;  /* K7 & K8 */
-       else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL)
-               pci_cache_line_size = 128 >> 2; /* P4 */
+       if (c->x86_clflush_size > 0) {
+               pci_dfl_cache_line_size = c->x86_clflush_size >> 2;
+               printk(KERN_DEBUG "PCI: pci_cache_line_size set to %d bytes\n",
+                       pci_dfl_cache_line_size << 2);
+       } else {
+               pci_dfl_cache_line_size = 32 >> 2;
+               printk(KERN_DEBUG "PCI: Unknown cacheline size. Setting to 32 bytes\n");
+       }
 
        pcibios_resource_survey();
 
index aaf26ae58cd5cadb73ae168cd7f46edf9cc2b4f3..d1067d539bee2da24fb260ac64b2162ecf63d17b 100644 (file)
@@ -12,8 +12,6 @@ u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset)
        u32 v;
        outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
        v = inl(0xcfc);
-       if (v != 0xffffffff)
-               pr_debug("%x reading 4 from %x: %x\n", slot, offset, v);
        return v;
 }
 
@@ -22,7 +20,6 @@ u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset)
        u8 v;
        outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
        v = inb(0xcfc + (offset&3));
-       pr_debug("%x reading 1 from %x: %x\n", slot, offset, v);
        return v;
 }
 
@@ -31,28 +28,24 @@ u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset)
        u16 v;
        outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
        v = inw(0xcfc + (offset&2));
-       pr_debug("%x reading 2 from %x: %x\n", slot, offset, v);
        return v;
 }
 
 void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
                                    u32 val)
 {
-       pr_debug("%x writing to %x: %x\n", slot, offset, val);
        outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
        outl(val, 0xcfc);
 }
 
 void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val)
 {
-       pr_debug("%x writing to %x: %x\n", slot, offset, val);
        outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
        outb(val, 0xcfc + (offset&3));
 }
 
 void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val)
 {
-       pr_debug("%x writing to %x: %x\n", slot, offset, val);
        outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
        outw(val, 0xcfc + (offset&2));
 }
index b22d13b0c71d0f538cd25f2643490d0bf2fa86a3..5dc9e8c63fcdedb26a096d48efcf2392cd8f8209 100644 (file)
@@ -129,7 +129,9 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
                                        continue;
                                if (!r->start ||
                                    pci_claim_resource(dev, idx) < 0) {
-                                       dev_info(&dev->dev, "BAR %d: can't allocate resource\n", idx);
+                                       dev_info(&dev->dev,
+                                                "can't reserve window %pR\n",
+                                                r);
                                        /*
                                         * Something is wrong with the region.
                                         * Invalidate the resource to prevent
@@ -144,16 +146,29 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
        }
 }
 
+struct pci_check_idx_range {
+       int start;
+       int end;
+};
+
 static void __init pcibios_allocate_resources(int pass)
 {
        struct pci_dev *dev = NULL;
-       int idx, disabled;
+       int idx, disabled, i;
        u16 command;
        struct resource *r;
 
+       struct pci_check_idx_range idx_range[] = {
+               { PCI_STD_RESOURCES, PCI_STD_RESOURCE_END },
+#ifdef CONFIG_PCI_IOV
+               { PCI_IOV_RESOURCES, PCI_IOV_RESOURCE_END },
+#endif
+       };
+
        for_each_pci_dev(dev) {
                pci_read_config_word(dev, PCI_COMMAND, &command);
-               for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+               for (i = 0; i < ARRAY_SIZE(idx_range); i++)
+               for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) {
                        r = &dev->resource[idx];
                        if (r->parent)          /* Already allocated */
                                continue;
@@ -164,12 +179,12 @@ static void __init pcibios_allocate_resources(int pass)
                        else
                                disabled = !(command & PCI_COMMAND_MEMORY);
                        if (pass == disabled) {
-                               dev_dbg(&dev->dev, "resource %#08llx-%#08llx (f=%lx, d=%d, p=%d)\n",
-                                       (unsigned long long) r->start,
-                                       (unsigned long long) r->end,
-                                       r->flags, disabled, pass);
+                               dev_dbg(&dev->dev,
+                                       "BAR %d: reserving %pr (d=%d, p=%d)\n",
+                                       idx, r, disabled, pass);
                                if (pci_claim_resource(dev, idx) < 0) {
-                                       dev_info(&dev->dev, "BAR %d: can't allocate resource\n", idx);
+                                       dev_info(&dev->dev,
+                                                "can't reserve %pR\n", r);
                                        /* We'll assign a new address later */
                                        r->end -= r->start;
                                        r->start = 0;
@@ -182,7 +197,7 @@ static void __init pcibios_allocate_resources(int pass)
                                /* Turn the ROM off, leave the resource region,
                                 * but keep it unregistered. */
                                u32 reg;
-                               dev_dbg(&dev->dev, "disabling ROM\n");
+                               dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
                                r->flags &= ~IORESOURCE_ROM_ENABLE;
                                pci_read_config_dword(dev,
                                                dev->rom_base_reg, &reg);
@@ -282,6 +297,15 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                return -EINVAL;
 
        prot = pgprot_val(vma->vm_page_prot);
+
+       /*
+        * Return error if pat is not enabled and write_combine is requested.
+        * Caller can followup with UC MINUS request and add a WC mtrr if there
+        * is a free mtrr slot.
+        */
+       if (!pat_enabled && write_combine)
+               return -EINVAL;
+
        if (pat_enabled && write_combine)
                prot |= _PAGE_CACHE_WC;
        else if (pat_enabled || boot_cpu_data.x86 > 3)
diff --git a/arch/x86/pci/intel_bus.c b/arch/x86/pci/intel_bus.c
new file mode 100644 (file)
index 0000000..b7a55dc
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * to read io range from IOH pci conf, need to do it after mmconfig is there
+ */
+
+#include <linux/delay.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/pci_x86.h>
+
+#include "bus_numa.h"
+
+static inline void print_ioh_resources(struct pci_root_info *info)
+{
+       int res_num;
+       int busnum;
+       int i;
+
+       printk(KERN_DEBUG "IOH bus: [%02x, %02x]\n",
+                       info->bus_min, info->bus_max);
+       res_num = info->res_num;
+       busnum = info->bus_min;
+       for (i = 0; i < res_num; i++) {
+               struct resource *res;
+
+               res = &info->res[i];
+               printk(KERN_DEBUG "IOH bus: %02x index %x %s: [%llx, %llx]\n",
+                       busnum, i,
+                       (res->flags & IORESOURCE_IO) ? "io port" :
+                                                       "mmio",
+                       res->start, res->end);
+       }
+}
+
+#define IOH_LIO                        0x108
+#define IOH_LMMIOL             0x10c
+#define IOH_LMMIOH             0x110
+#define IOH_LMMIOH_BASEU       0x114
+#define IOH_LMMIOH_LIMITU      0x118
+#define IOH_LCFGBUS            0x11c
+
+static void __devinit pci_root_bus_res(struct pci_dev *dev)
+{
+       u16 word;
+       u32 dword;
+       struct pci_root_info *info;
+       u16 io_base, io_end;
+       u32 mmiol_base, mmiol_end;
+       u64 mmioh_base, mmioh_end;
+       int bus_base, bus_end;
+
+       if (pci_root_num >= PCI_ROOT_NR) {
+               printk(KERN_DEBUG "intel_bus.c: PCI_ROOT_NR is too small\n");
+               return;
+       }
+
+       info = &pci_root_info[pci_root_num];
+       pci_root_num++;
+
+       pci_read_config_word(dev, IOH_LCFGBUS, &word);
+       bus_base = (word & 0xff);
+       bus_end = (word & 0xff00) >> 8;
+       sprintf(info->name, "PCI Bus #%02x", bus_base);
+       info->bus_min = bus_base;
+       info->bus_max = bus_end;
+
+       pci_read_config_word(dev, IOH_LIO, &word);
+       io_base = (word & 0xf0) << (12 - 4);
+       io_end = (word & 0xf000) | 0xfff;
+       update_res(info, io_base, io_end, IORESOURCE_IO, 0);
+
+       pci_read_config_dword(dev, IOH_LMMIOL, &dword);
+       mmiol_base = (dword & 0xff00) << (24 - 8);
+       mmiol_end = (dword & 0xff000000) | 0xffffff;
+       update_res(info, mmiol_base, mmiol_end, IORESOURCE_MEM, 0);
+
+       pci_read_config_dword(dev, IOH_LMMIOH, &dword);
+       mmioh_base = ((u64)(dword & 0xfc00)) << (26 - 10);
+       mmioh_end = ((u64)(dword & 0xfc000000) | 0x3ffffff);
+       pci_read_config_dword(dev, IOH_LMMIOH_BASEU, &dword);
+       mmioh_base |= ((u64)(dword & 0x7ffff)) << 32;
+       pci_read_config_dword(dev, IOH_LMMIOH_LIMITU, &dword);
+       mmioh_end |= ((u64)(dword & 0x7ffff)) << 32;
+       update_res(info, mmioh_base, mmioh_end, IORESOURCE_MEM, 0);
+
+       print_ioh_resources(info);
+}
+
+/* intel IOH */
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, pci_root_bus_res);
index 602c172d3bd5a5c44685893071b32b2d8827c023..b19d1e54201ee95a80d8123e9ba26716811c52fe 100644 (file)
 #include <linux/acpi.h>
 #include <linux/sfi_acpi.h>
 #include <linux/bitmap.h>
-#include <linux/sort.h>
+#include <linux/dmi.h>
 #include <asm/e820.h>
 #include <asm/pci_x86.h>
 #include <asm/acpi.h>
 
 #define PREFIX "PCI: "
 
-/* aperture is up to 256MB but BIOS may reserve less */
-#define MMCONFIG_APER_MIN      (2 * 1024*1024)
-#define MMCONFIG_APER_MAX      (256 * 1024*1024)
-
 /* Indicate if the mmcfg resources have been placed into the resource table. */
 static int __initdata pci_mmcfg_resources_inserted;
 
-static __init int extend_mmcfg(int num)
+LIST_HEAD(pci_mmcfg_list);
+
+static __init void pci_mmconfig_remove(struct pci_mmcfg_region *cfg)
 {
-       struct acpi_mcfg_allocation *new;
-       int new_num = pci_mmcfg_config_num + num;
+       if (cfg->res.parent)
+               release_resource(&cfg->res);
+       list_del(&cfg->list);
+       kfree(cfg);
+}
 
-       new = kzalloc(sizeof(pci_mmcfg_config[0]) * new_num, GFP_KERNEL);
-       if (!new)
-               return -1;
+static __init void free_all_mmcfg(void)
+{
+       struct pci_mmcfg_region *cfg, *tmp;
 
-       if (pci_mmcfg_config) {
-               memcpy(new, pci_mmcfg_config,
-                        sizeof(pci_mmcfg_config[0]) * new_num);
-               kfree(pci_mmcfg_config);
+       pci_mmcfg_arch_free();
+       list_for_each_entry_safe(cfg, tmp, &pci_mmcfg_list, list)
+               pci_mmconfig_remove(cfg);
+}
+
+static __init void list_add_sorted(struct pci_mmcfg_region *new)
+{
+       struct pci_mmcfg_region *cfg;
+
+       /* keep list sorted by segment and starting bus number */
+       list_for_each_entry(cfg, &pci_mmcfg_list, list) {
+               if (cfg->segment > new->segment ||
+                   (cfg->segment == new->segment &&
+                    cfg->start_bus >= new->start_bus)) {
+                       list_add_tail(&new->list, &cfg->list);
+                       return;
+               }
        }
-       pci_mmcfg_config = new;
+       list_add_tail(&new->list, &pci_mmcfg_list);
+}
 
-       return 0;
+static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
+                                                       int end, u64 addr)
+{
+       struct pci_mmcfg_region *new;
+       int num_buses;
+       struct resource *res;
+
+       if (addr == 0)
+               return NULL;
+
+       new = kzalloc(sizeof(*new), GFP_KERNEL);
+       if (!new)
+               return NULL;
+
+       new->address = addr;
+       new->segment = segment;
+       new->start_bus = start;
+       new->end_bus = end;
+
+       list_add_sorted(new);
+
+       num_buses = end - start + 1;
+       res = &new->res;
+       res->start = addr + PCI_MMCFG_BUS_OFFSET(start);
+       res->end = addr + PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
+       res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+       snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN,
+                "PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end);
+       res->name = new->name;
+
+       printk(KERN_INFO PREFIX "MMCONFIG for domain %04x [bus %02x-%02x] at "
+              "%pR (base %#lx)\n", segment, start, end, &new->res,
+              (unsigned long) addr);
+
+       return new;
 }
 
-static __init void fill_one_mmcfg(u64 addr, int segment, int start, int end)
+struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
 {
-       int i = pci_mmcfg_config_num;
+       struct pci_mmcfg_region *cfg;
 
-       pci_mmcfg_config_num++;
-       pci_mmcfg_config[i].address = addr;
-       pci_mmcfg_config[i].pci_segment = segment;
-       pci_mmcfg_config[i].start_bus_number = start;
-       pci_mmcfg_config[i].end_bus_number = end;
+       list_for_each_entry(cfg, &pci_mmcfg_list, list)
+               if (cfg->segment == segment &&
+                   cfg->start_bus <= bus && bus <= cfg->end_bus)
+                       return cfg;
+
+       return NULL;
 }
 
 static const char __init *pci_mmcfg_e7520(void)
@@ -68,11 +118,9 @@ static const char __init *pci_mmcfg_e7520(void)
        if (win == 0x0000 || win == 0xf000)
                return NULL;
 
-       if (extend_mmcfg(1) == -1)
+       if (pci_mmconfig_add(0, 0, 255, win << 16) == NULL)
                return NULL;
 
-       fill_one_mmcfg(win << 16, 0, 0, 255);
-
        return "Intel Corporation E7520 Memory Controller Hub";
 }
 
@@ -114,11 +162,9 @@ static const char __init *pci_mmcfg_intel_945(void)
        if ((pciexbar & mask) >= 0xf0000000U)
                return NULL;
 
-       if (extend_mmcfg(1) == -1)
+       if (pci_mmconfig_add(0, 0, (len >> 20) - 1, pciexbar & mask) == NULL)
                return NULL;
 
-       fill_one_mmcfg(pciexbar & mask, 0, 0, (len >> 20) - 1);
-
        return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
 }
 
@@ -127,7 +173,7 @@ static const char __init *pci_mmcfg_amd_fam10h(void)
        u32 low, high, address;
        u64 base, msr;
        int i;
-       unsigned segnbits = 0, busnbits;
+       unsigned segnbits = 0, busnbits, end_bus;
 
        if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
                return NULL;
@@ -161,11 +207,13 @@ static const char __init *pci_mmcfg_amd_fam10h(void)
                busnbits = 8;
        }
 
-       if (extend_mmcfg(1 << segnbits) == -1)
-               return NULL;
-
+       end_bus = (1 << busnbits) - 1;
        for (i = 0; i < (1 << segnbits); i++)
-               fill_one_mmcfg(base + (1<<28) * i, i, 0, (1 << busnbits) - 1);
+               if (pci_mmconfig_add(i, 0, end_bus,
+                                    base + (1<<28) * i) == NULL) {
+                       free_all_mmcfg();
+                       return NULL;
+               }
 
        return "AMD Family 10h NB";
 }
@@ -190,7 +238,7 @@ static const char __init *pci_mmcfg_nvidia_mcp55(void)
        /*
         * do check if amd fam10h already took over
         */
-       if (!acpi_disabled || pci_mmcfg_config_num || mcp55_checked)
+       if (!acpi_disabled || !list_empty(&pci_mmcfg_list) || mcp55_checked)
                return NULL;
 
        mcp55_checked = true;
@@ -213,16 +261,14 @@ static const char __init *pci_mmcfg_nvidia_mcp55(void)
                if (!(extcfg & extcfg_enable_mask))
                        continue;
 
-               if (extend_mmcfg(1) == -1)
-                       continue;
-
                size_index = (extcfg & extcfg_size_mask) >> extcfg_size_shift;
                base = extcfg & extcfg_base_mask[size_index];
                /* base could > 4G */
                base <<= extcfg_base_lshift;
                start = (extcfg & extcfg_start_mask) >> extcfg_start_shift;
                end = start + extcfg_sizebus[size_index] - 1;
-               fill_one_mmcfg(base, 0, start, end);
+               if (pci_mmconfig_add(0, start, end, base) == NULL)
+                       continue;
                mcp55_mmconf_found++;
        }
 
@@ -253,45 +299,27 @@ static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
          0x0369, pci_mmcfg_nvidia_mcp55 },
 };
 
-static int __init cmp_mmcfg(const void *x1, const void *x2)
-{
-       const typeof(pci_mmcfg_config[0]) *m1 = x1;
-       const typeof(pci_mmcfg_config[0]) *m2 = x2;
-       int start1, start2;
-
-       start1 = m1->start_bus_number;
-       start2 = m2->start_bus_number;
-
-       return start1 - start2;
-}
-
 static void __init pci_mmcfg_check_end_bus_number(void)
 {
-       int i;
-       typeof(pci_mmcfg_config[0]) *cfg, *cfgx;
-
-       /* sort them at first */
-       sort(pci_mmcfg_config, pci_mmcfg_config_num,
-                sizeof(pci_mmcfg_config[0]), cmp_mmcfg, NULL);
+       struct pci_mmcfg_region *cfg, *cfgx;
 
        /* last one*/
-       if (pci_mmcfg_config_num > 0) {
-               i = pci_mmcfg_config_num - 1;
-               cfg = &pci_mmcfg_config[i];
-               if (cfg->end_bus_number < cfg->start_bus_number)
-                       cfg->end_bus_number = 255;
-       }
+       cfg = list_entry(pci_mmcfg_list.prev, typeof(*cfg), list);
+       if (cfg)
+               if (cfg->end_bus < cfg->start_bus)
+                       cfg->end_bus = 255;
 
-       /* don't overlap please */
-       for (i = 0; i < pci_mmcfg_config_num - 1; i++) {
-               cfg = &pci_mmcfg_config[i];
-               cfgx = &pci_mmcfg_config[i+1];
+       if (list_is_singular(&pci_mmcfg_list))
+               return;
 
-               if (cfg->end_bus_number < cfg->start_bus_number)
-                       cfg->end_bus_number = 255;
+       /* don't overlap please */
+       list_for_each_entry(cfg, &pci_mmcfg_list, list) {
+               if (cfg->end_bus < cfg->start_bus)
+                       cfg->end_bus = 255;
 
-               if (cfg->end_bus_number >= cfgx->start_bus_number)
-                       cfg->end_bus_number = cfgx->start_bus_number - 1;
+               cfgx = list_entry(cfg->list.next, typeof(*cfg), list);
+               if (cfg != cfgx && cfg->end_bus >= cfgx->start_bus)
+                       cfg->end_bus = cfgx->start_bus - 1;
        }
 }
 
@@ -306,8 +334,7 @@ static int __init pci_mmcfg_check_hostbridge(void)
        if (!raw_pci_ops)
                return 0;
 
-       pci_mmcfg_config_num = 0;
-       pci_mmcfg_config = NULL;
+       free_all_mmcfg();
 
        for (i = 0; i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
                bus =  pci_mmcfg_probes[i].bus;
@@ -322,45 +349,22 @@ static int __init pci_mmcfg_check_hostbridge(void)
                        name = pci_mmcfg_probes[i].probe();
 
                if (name)
-                       printk(KERN_INFO "PCI: Found %s with MMCONFIG support.\n",
+                       printk(KERN_INFO PREFIX "%s with MMCONFIG support\n",
                               name);
        }
 
        /* some end_bus_number is crazy, fix it */
        pci_mmcfg_check_end_bus_number();
 
-       return pci_mmcfg_config_num != 0;
+       return !list_empty(&pci_mmcfg_list);
 }
 
 static void __init pci_mmcfg_insert_resources(void)
 {
-#define PCI_MMCFG_RESOURCE_NAME_LEN 24
-       int i;
-       struct resource *res;
-       char *names;
-       unsigned num_buses;
-
-       res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
-                       pci_mmcfg_config_num, GFP_KERNEL);
-       if (!res) {
-               printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
-               return;
-       }
+       struct pci_mmcfg_region *cfg;
 
-       names = (void *)&res[pci_mmcfg_config_num];
-       for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
-               struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
-               num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
-               res->name = names;
-               snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN,
-                        "PCI MMCONFIG %u [%02x-%02x]", cfg->pci_segment,
-                        cfg->start_bus_number, cfg->end_bus_number);
-               res->start = cfg->address + (cfg->start_bus_number << 20);
-               res->end = res->start + (num_buses << 20) - 1;
-               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-               insert_resource(&iomem_resource, res);
-               names += PCI_MMCFG_RESOURCE_NAME_LEN;
-       }
+       list_for_each_entry(cfg, &pci_mmcfg_list, list)
+               insert_resource(&iomem_resource, &cfg->res);
 
        /* Mark that the resources have been inserted. */
        pci_mmcfg_resources_inserted = 1;
@@ -437,11 +441,12 @@ static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used)
 typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type);
 
 static int __init is_mmconf_reserved(check_reserved_t is_reserved,
-               u64 addr, u64 size, int i,
-               typeof(pci_mmcfg_config[0]) *cfg, int with_e820)
+                                   struct pci_mmcfg_region *cfg, int with_e820)
 {
+       u64 addr = cfg->res.start;
+       u64 size = resource_size(&cfg->res);
        u64 old_size = size;
-       int valid = 0;
+       int valid = 0, num_buses;
 
        while (!is_reserved(addr, addr + size, E820_RESERVED)) {
                size >>= 1;
@@ -450,19 +455,25 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved,
        }
 
        if (size >= (16UL<<20) || size == old_size) {
-               printk(KERN_NOTICE
-                      "PCI: MCFG area at %Lx reserved in %s\n",
-                       addr, with_e820?"E820":"ACPI motherboard resources");
+               printk(KERN_INFO PREFIX "MMCONFIG at %pR reserved in %s\n",
+                      &cfg->res,
+                      with_e820 ? "E820" : "ACPI motherboard resources");
                valid = 1;
 
                if (old_size != size) {
-                       /* update end_bus_number */
-                       cfg->end_bus_number = cfg->start_bus_number + ((size>>20) - 1);
-                       printk(KERN_NOTICE "PCI: updated MCFG configuration %d: base %lx "
-                              "segment %hu buses %u - %u\n",
-                              i, (unsigned long)cfg->address, cfg->pci_segment,
-                              (unsigned int)cfg->start_bus_number,
-                              (unsigned int)cfg->end_bus_number);
+                       /* update end_bus */
+                       cfg->end_bus = cfg->start_bus + ((size>>20) - 1);
+                       num_buses = cfg->end_bus - cfg->start_bus + 1;
+                       cfg->res.end = cfg->res.start +
+                           PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
+                       snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN,
+                                "PCI MMCONFIG %04x [bus %02x-%02x]",
+                                cfg->segment, cfg->start_bus, cfg->end_bus);
+                       printk(KERN_INFO PREFIX
+                              "MMCONFIG for %04x [bus%02x-%02x] "
+                              "at %pR (base %#lx) (size reduced!)\n",
+                              cfg->segment, cfg->start_bus, cfg->end_bus,
+                              &cfg->res, (unsigned long) cfg->address);
                }
        }
 
@@ -471,45 +482,26 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved,
 
 static void __init pci_mmcfg_reject_broken(int early)
 {
-       typeof(pci_mmcfg_config[0]) *cfg;
-       int i;
+       struct pci_mmcfg_region *cfg;
 
-       if ((pci_mmcfg_config_num == 0) ||
-           (pci_mmcfg_config == NULL) ||
-           (pci_mmcfg_config[0].address == 0))
-               return;
-
-       for (i = 0; i < pci_mmcfg_config_num; i++) {
+       list_for_each_entry(cfg, &pci_mmcfg_list, list) {
                int valid = 0;
-               u64 addr, size;
-
-               cfg = &pci_mmcfg_config[i];
-               addr = cfg->start_bus_number;
-               addr <<= 20;
-               addr += cfg->address;
-               size = cfg->end_bus_number + 1 - cfg->start_bus_number;
-               size <<= 20;
-               printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx "
-                      "segment %hu buses %u - %u\n",
-                      i, (unsigned long)cfg->address, cfg->pci_segment,
-                      (unsigned int)cfg->start_bus_number,
-                      (unsigned int)cfg->end_bus_number);
 
                if (!early && !acpi_disabled)
-                       valid = is_mmconf_reserved(is_acpi_reserved, addr, size, i, cfg, 0);
+                       valid = is_mmconf_reserved(is_acpi_reserved, cfg, 0);
 
                if (valid)
                        continue;
 
                if (!early)
-                       printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
-                              " reserved in ACPI motherboard resources\n",
-                              cfg->address);
+                       printk(KERN_ERR FW_BUG PREFIX
+                              "MMCONFIG at %pR not reserved in "
+                              "ACPI motherboard resources\n", &cfg->res);
 
                /* Don't try to do this check unless configuration
                   type 1 is available. how about type 2 ?*/
                if (raw_pci_ops)
-                       valid = is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1);
+                       valid = is_mmconf_reserved(e820_all_mapped, cfg, 1);
 
                if (!valid)
                        goto reject;
@@ -518,34 +510,41 @@ static void __init pci_mmcfg_reject_broken(int early)
        return;
 
 reject:
-       printk(KERN_INFO "PCI: Not using MMCONFIG.\n");
-       pci_mmcfg_arch_free();
-       kfree(pci_mmcfg_config);
-       pci_mmcfg_config = NULL;
-       pci_mmcfg_config_num = 0;
+       printk(KERN_INFO PREFIX "not using MMCONFIG\n");
+       free_all_mmcfg();
 }
 
 static int __initdata known_bridge;
 
-static int acpi_mcfg_64bit_base_addr __initdata = FALSE;
+static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
+                                       struct acpi_mcfg_allocation *cfg)
+{
+       int year;
 
-/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
-struct acpi_mcfg_allocation *pci_mmcfg_config;
-int pci_mmcfg_config_num;
+       if (cfg->address < 0xFFFFFFFF)
+               return 0;
 
-static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg)
-{
        if (!strcmp(mcfg->header.oem_id, "SGI"))
-               acpi_mcfg_64bit_base_addr = TRUE;
+               return 0;
 
-       return 0;
+       if (mcfg->header.revision >= 1) {
+               if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) &&
+                   year >= 2010)
+                       return 0;
+       }
+
+       printk(KERN_ERR PREFIX "MCFG region for %04x [bus %02x-%02x] at %#llx "
+              "is above 4GB, ignored\n", cfg->pci_segment,
+              cfg->start_bus_number, cfg->end_bus_number, cfg->address);
+       return -EINVAL;
 }
 
 static int __init pci_parse_mcfg(struct acpi_table_header *header)
 {
        struct acpi_table_mcfg *mcfg;
+       struct acpi_mcfg_allocation *cfg_table, *cfg;
        unsigned long i;
-       int config_size;
+       int entries;
 
        if (!header)
                return -EINVAL;
@@ -553,38 +552,33 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
        mcfg = (struct acpi_table_mcfg *)header;
 
        /* how many config structures do we have */
-       pci_mmcfg_config_num = 0;
+       free_all_mmcfg();
+       entries = 0;
        i = header->length - sizeof(struct acpi_table_mcfg);
        while (i >= sizeof(struct acpi_mcfg_allocation)) {
-               ++pci_mmcfg_config_num;
+               entries++;
                i -= sizeof(struct acpi_mcfg_allocation);
        };
-       if (pci_mmcfg_config_num == 0) {
+       if (entries == 0) {
                printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
                return -ENODEV;
        }
 
-       config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);
-       pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL);
-       if (!pci_mmcfg_config) {
-               printk(KERN_WARNING PREFIX
-                      "No memory for MCFG config tables\n");
-               return -ENOMEM;
-       }
-
-       memcpy(pci_mmcfg_config, &mcfg[1], config_size);
-
-       acpi_mcfg_oem_check(mcfg);
-
-       for (i = 0; i < pci_mmcfg_config_num; ++i) {
-               if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) &&
-                   !acpi_mcfg_64bit_base_addr) {
-                       printk(KERN_ERR PREFIX
-                              "MMCONFIG not in low 4GB of memory\n");
-                       kfree(pci_mmcfg_config);
-                       pci_mmcfg_config_num = 0;
+       cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1];
+       for (i = 0; i < entries; i++) {
+               cfg = &cfg_table[i];
+               if (acpi_mcfg_check_entry(mcfg, cfg)) {
+                       free_all_mmcfg();
                        return -ENODEV;
                }
+
+               if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number,
+                                  cfg->end_bus_number, cfg->address) == NULL) {
+                       printk(KERN_WARNING PREFIX
+                              "no memory for MCFG entries\n");
+                       free_all_mmcfg();
+                       return -ENOMEM;
+               }
        }
 
        return 0;
@@ -614,9 +608,7 @@ static void __init __pci_mmcfg_init(int early)
 
        pci_mmcfg_reject_broken(early);
 
-       if ((pci_mmcfg_config_num == 0) ||
-           (pci_mmcfg_config == NULL) ||
-           (pci_mmcfg_config[0].address == 0))
+       if (list_empty(&pci_mmcfg_list))
                return;
 
        if (pci_mmcfg_arch_init())
@@ -648,9 +640,7 @@ static int __init pci_mmcfg_late_insert_resources(void)
         */
        if ((pci_mmcfg_resources_inserted == 1) ||
            (pci_probe & PCI_PROBE_MMCONF) == 0 ||
-           (pci_mmcfg_config_num == 0) ||
-           (pci_mmcfg_config == NULL) ||
-           (pci_mmcfg_config[0].address == 0))
+           list_empty(&pci_mmcfg_list))
                return 1;
 
        /*
index f10a7e94a84c51d9b87a041a19b3c7b89b283d8b..90d5fd476ed4fe3a093b514f095ca3d237023f54 100644 (file)
@@ -27,18 +27,10 @@ static int mmcfg_last_accessed_cpu;
  */
 static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
 {
-       struct acpi_mcfg_allocation *cfg;
-       int cfg_num;
-
-       for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
-               cfg = &pci_mmcfg_config[cfg_num];
-               if (cfg->pci_segment == seg &&
-                   (cfg->start_bus_number <= bus) &&
-                   (cfg->end_bus_number >= bus))
-                       return cfg->address;
-       }
+       struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus);
 
-       /* Fall back to type 0 */
+       if (cfg)
+               return cfg->address;
        return 0;
 }
 
@@ -47,7 +39,7 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
  */
 static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
 {
-       u32 dev_base = base | (bus << 20) | (devfn << 12);
+       u32 dev_base = base | PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12);
        int cpu = smp_processor_id();
        if (dev_base != mmcfg_last_accessed_device ||
            cpu != mmcfg_last_accessed_cpu) {
index 94349f8b2f964b969f7cc576ad92a50cfac75049..e783841bd1d7c42ea8ca4607d884ffe1e65ba97f 100644 (file)
 #include <asm/e820.h>
 #include <asm/pci_x86.h>
 
-/* Static virtual mapping of the MMCONFIG aperture */
-struct mmcfg_virt {
-       struct acpi_mcfg_allocation *cfg;
-       char __iomem *virt;
-};
-static struct mmcfg_virt *pci_mmcfg_virt;
-
-static char __iomem *get_virt(unsigned int seg, unsigned bus)
-{
-       struct acpi_mcfg_allocation *cfg;
-       int cfg_num;
-
-       for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
-               cfg = pci_mmcfg_virt[cfg_num].cfg;
-               if (cfg->pci_segment == seg &&
-                   (cfg->start_bus_number <= bus) &&
-                   (cfg->end_bus_number >= bus))
-                       return pci_mmcfg_virt[cfg_num].virt;
-       }
-
-       /* Fall back to type 0 */
-       return NULL;
-}
+#define PREFIX "PCI: "
 
 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
 {
-       char __iomem *addr;
+       struct pci_mmcfg_region *cfg = pci_mmconfig_lookup(seg, bus);
 
-       addr = get_virt(seg, bus);
-       if (!addr)
-               return NULL;
-       return addr + ((bus << 20) | (devfn << 12));
+       if (cfg && cfg->virt)
+               return cfg->virt + (PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12));
+       return NULL;
 }
 
 static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
@@ -109,42 +86,30 @@ static struct pci_raw_ops pci_mmcfg = {
        .write =        pci_mmcfg_write,
 };
 
-static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
+static void __iomem * __init mcfg_ioremap(struct pci_mmcfg_region *cfg)
 {
        void __iomem *addr;
        u64 start, size;
+       int num_buses;
 
-       start = cfg->start_bus_number;
-       start <<= 20;
-       start += cfg->address;
-       size = cfg->end_bus_number + 1 - cfg->start_bus_number;
-       size <<= 20;
+       start = cfg->address + PCI_MMCFG_BUS_OFFSET(cfg->start_bus);
+       num_buses = cfg->end_bus - cfg->start_bus + 1;
+       size = PCI_MMCFG_BUS_OFFSET(num_buses);
        addr = ioremap_nocache(start, size);
-       if (addr) {
-               printk(KERN_INFO "PCI: Using MMCONFIG at %Lx - %Lx\n",
-                      start, start + size - 1);
-               addr -= cfg->start_bus_number << 20;
-       }
+       if (addr)
+               addr -= PCI_MMCFG_BUS_OFFSET(cfg->start_bus);
        return addr;
 }
 
 int __init pci_mmcfg_arch_init(void)
 {
-       int i;
-       pci_mmcfg_virt = kzalloc(sizeof(*pci_mmcfg_virt) *
-                                pci_mmcfg_config_num, GFP_KERNEL);
-       if (pci_mmcfg_virt == NULL) {
-               printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n");
-               return 0;
-       }
+       struct pci_mmcfg_region *cfg;
 
-       for (i = 0; i < pci_mmcfg_config_num; ++i) {
-               pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
-               pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]);
-               if (!pci_mmcfg_virt[i].virt) {
-                       printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
-                                       "segment %d\n",
-                               pci_mmcfg_config[i].pci_segment);
+       list_for_each_entry(cfg, &pci_mmcfg_list, list) {
+               cfg->virt = mcfg_ioremap(cfg);
+               if (!cfg->virt) {
+                       printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n",
+                              &cfg->res);
                        pci_mmcfg_arch_free();
                        return 0;
                }
@@ -155,19 +120,12 @@ int __init pci_mmcfg_arch_init(void)
 
 void __init pci_mmcfg_arch_free(void)
 {
-       int i;
-
-       if (pci_mmcfg_virt == NULL)
-               return;
+       struct pci_mmcfg_region *cfg;
 
-       for (i = 0; i < pci_mmcfg_config_num; ++i) {
-               if (pci_mmcfg_virt[i].virt) {
-                       iounmap(pci_mmcfg_virt[i].virt + (pci_mmcfg_virt[i].cfg->start_bus_number << 20));
-                       pci_mmcfg_virt[i].virt = NULL;
-                       pci_mmcfg_virt[i].cfg = NULL;
+       list_for_each_entry(cfg, &pci_mmcfg_list, list) {
+               if (cfg->virt) {
+                       iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
+                       cfg->virt = NULL;
                }
        }
-
-       kfree(pci_mmcfg_virt);
-       pci_mmcfg_virt = NULL;
 }
index b8e45f164e2acc360bcc5c380a864a635761f134..2b26dd5930c6e82e87f0e20505ab5954e6213a83 100644 (file)
@@ -27,7 +27,9 @@
 #include <linux/page-flags.h>
 #include <linux/highmem.h>
 #include <linux/console.h>
+#include <linux/pci.h>
 
+#include <xen/xen.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>
 #include <xen/interface/physdev.h>
@@ -1175,7 +1177,11 @@ asmlinkage void __init xen_start_kernel(void)
                add_preferred_console("xenboot", 0, NULL);
                add_preferred_console("tty", 0, NULL);
                add_preferred_console("hvc", 0, NULL);
+       } else {
+               /* Make sure ACS will be enabled */
+               pci_request_acs();
        }
+               
 
        xen_raw_console_write("about to get started...\n");
 
index 7702118509a0a6e848bee454a983f0ec42e9522b..c7b10b4298e991320cd45af4fcc5168118d4e4b3 100644 (file)
@@ -19,6 +19,7 @@ obj-y                         += acpi.o \
 
 # All the builtin files are in the "acpi." module_param namespace.
 acpi-y                         += osl.o utils.o reboot.o
+acpi-y                         += hest.o
 
 # sleep related files
 acpi-y                         += wakeup.o
diff --git a/drivers/acpi/hest.c b/drivers/acpi/hest.c
new file mode 100644 (file)
index 0000000..4bb18c9
--- /dev/null
@@ -0,0 +1,135 @@
+#include <linux/acpi.h>
+#include <linux/pci.h>
+
+#define PREFIX "ACPI: "
+
+static inline unsigned long parse_acpi_hest_ia_machine_check(struct acpi_hest_ia_machine_check *p)
+{
+       return sizeof(*p) +
+               (sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks);
+}
+
+static inline unsigned long parse_acpi_hest_ia_corrected(struct acpi_hest_ia_corrected *p)
+{
+       return sizeof(*p) +
+               (sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks);
+}
+
+static inline unsigned long parse_acpi_hest_ia_nmi(struct acpi_hest_ia_nmi *p)
+{
+       return sizeof(*p);
+}
+
+static inline unsigned long parse_acpi_hest_generic(struct acpi_hest_generic *p)
+{
+       return sizeof(*p);
+}
+
+static inline unsigned int hest_match_pci(struct acpi_hest_aer_common *p, struct pci_dev *pci)
+{
+       return  (0           == pci_domain_nr(pci->bus) &&
+                p->bus      == pci->bus->number &&
+                p->device   == PCI_SLOT(pci->devfn) &&
+                p->function == PCI_FUNC(pci->devfn));
+}
+
+static unsigned long parse_acpi_hest_aer(void *hdr, int type, struct pci_dev *pci, int *firmware_first)
+{
+       struct acpi_hest_aer_common *p = hdr + sizeof(struct acpi_hest_header);
+       unsigned long rc=0;
+       u8 pcie_type = 0;
+       u8 bridge = 0;
+       switch (type) {
+       case ACPI_HEST_TYPE_AER_ROOT_PORT:
+               rc = sizeof(struct acpi_hest_aer_root);
+               pcie_type = PCI_EXP_TYPE_ROOT_PORT;
+               break;
+       case ACPI_HEST_TYPE_AER_ENDPOINT:
+               rc = sizeof(struct acpi_hest_aer);
+               pcie_type = PCI_EXP_TYPE_ENDPOINT;
+               break;
+       case ACPI_HEST_TYPE_AER_BRIDGE:
+               rc = sizeof(struct acpi_hest_aer_bridge);
+               if ((pci->class >> 16) == PCI_BASE_CLASS_BRIDGE)
+                       bridge = 1;
+               break;
+       }
+
+       if (p->flags & ACPI_HEST_GLOBAL) {
+               if ((pci->is_pcie && (pci->pcie_type == pcie_type)) || bridge)
+                       *firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
+       }
+       else
+               if (hest_match_pci(p, pci))
+                       *firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
+       return rc;
+}
+
+static int acpi_hest_firmware_first(struct acpi_table_header *stdheader, struct pci_dev *pci)
+{
+       struct acpi_table_hest *hest = (struct acpi_table_hest *)stdheader;
+       void *p = (void *)hest + sizeof(*hest); /* defined by the ACPI 4.0 spec */
+       struct acpi_hest_header *hdr = p;
+
+       int i;
+       int firmware_first = 0;
+       static unsigned char printed_unused = 0;
+       static unsigned char printed_reserved = 0;
+
+       for (i=0, hdr=p; p < (((void *)hest) + hest->header.length) && i < hest->error_source_count; i++) {
+               switch (hdr->type) {
+               case ACPI_HEST_TYPE_IA32_CHECK:
+                       p += parse_acpi_hest_ia_machine_check(p);
+                       break;
+               case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
+                       p += parse_acpi_hest_ia_corrected(p);
+                       break;
+               case ACPI_HEST_TYPE_IA32_NMI:
+                       p += parse_acpi_hest_ia_nmi(p);
+                       break;
+               /* These three should never appear */
+               case ACPI_HEST_TYPE_NOT_USED3:
+               case ACPI_HEST_TYPE_NOT_USED4:
+               case ACPI_HEST_TYPE_NOT_USED5:
+                       if (!printed_unused) {
+                               printk(KERN_DEBUG PREFIX
+                                      "HEST Error Source list contains an obsolete type (%d).\n", hdr->type);
+                               printed_unused = 1;
+                       }
+                       break;
+               case ACPI_HEST_TYPE_AER_ROOT_PORT:
+               case ACPI_HEST_TYPE_AER_ENDPOINT:
+               case ACPI_HEST_TYPE_AER_BRIDGE:
+                       p += parse_acpi_hest_aer(p, hdr->type, pci, &firmware_first);
+                       break;
+               case ACPI_HEST_TYPE_GENERIC_ERROR:
+                       p += parse_acpi_hest_generic(p);
+                       break;
+               /* These should never appear either */
+               case ACPI_HEST_TYPE_RESERVED:
+               default:
+                       if (!printed_reserved) {
+                               printk(KERN_DEBUG PREFIX
+                                      "HEST Error Source list contains a reserved type (%d).\n", hdr->type);
+                               printed_reserved = 1;
+                       }
+                       break;
+               }
+       }
+       return firmware_first;
+}
+
+int acpi_hest_firmware_first_pci(struct pci_dev *pci)
+{
+       acpi_status status = AE_NOT_FOUND;
+       struct acpi_table_header *hest = NULL;
+       status = acpi_get_table(ACPI_SIG_HEST, 1, &hest);
+
+       if (ACPI_SUCCESS(status)) {
+               if (acpi_hest_firmware_first(hest, pci)) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_hest_firmware_first_pci);
index b8578bb3f4c9c4393c83be80ddaa36eccc073264..05a31e55d27817bed3f8157c91389c31f0adb1f8 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/module.h>
 #include <linux/scatterlist.h>
 
+#include <xen/xen.h>
 #include <xen/xenbus.h>
 #include <xen/grant_table.h>
 #include <xen/events.h>
index a6ee32b599a880c13f3595fa43aaa9717b7fb1f0..b1a71638c772b8ed5be135408c612130d7b2ec8b 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/types.h>
 
 #include <asm/xen/hypervisor.h>
+
+#include <xen/xen.h>
 #include <xen/page.h>
 #include <xen/events.h>
 #include <xen/interface/io/console.h>
index b115726dc088b169003a725ba29de8a4171e58a9..c721c0a23eb831d20672e16120b3278e8901f428 100644 (file)
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/input.h>
+
 #include <asm/xen/hypervisor.h>
+
+#include <xen/xen.h>
 #include <xen/events.h>
 #include <xen/page.h>
 #include <xen/interface/io/fbif.h>
index baa051d5bfbe0bcd84bd9f28530ac73f6d4863d8..a869b45d3d37b2f38a986c4dfb0146d10be4416d 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/mm.h>
 #include <net/ip.h>
 
+#include <xen/xen.h>
 #include <xen/xenbus.h>
 #include <xen/events.h>
 #include <xen/page.h>
index fdc864f9cf233d5134803593640f49c3ed0b1ccf..b1ecefa2a23dac481b77c06e1090a4ef40daa171 100644 (file)
@@ -27,10 +27,10 @@ config PCI_LEGACY
        default y
        help
          Say Y here if you want to include support for the deprecated
-         pci_find_slot() and pci_find_device() APIs.  Most drivers have
-         been converted over to using the proper hotplug APIs, so this
-         option serves to include/exclude only a few drivers that are
-         still using this API.
+         pci_find_device() API.  Most drivers have been converted over
+         to using the proper hotplug APIs, so this option serves to
+         include/exclude only a few drivers that are still using this
+         API.
 
 config PCI_DEBUG
        bool "PCI Debugging"
@@ -69,3 +69,10 @@ config PCI_IOV
          physical resources.
 
          If unsure, say N.
+
+config PCI_IOAPIC
+       bool
+       depends on PCI
+       depends on ACPI
+       depends on HOTPLUG
+       default y
index 4a7f11d8f43215af8c10f87f8d08642eac28a339..4df48d58eaa6372109bbcd2ca4c7cd04aaa25a6e 100644 (file)
@@ -14,6 +14,8 @@ CFLAGS_legacy.o += -Wno-deprecated-declarations
 # Build PCI Express stuff if needed
 obj-$(CONFIG_PCIEPORTBUS) += pcie/
 
+obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
+
 obj-$(CONFIG_HOTPLUG) += hotplug.o
 
 # Build the PCI Hotplug drivers if we were asked to
index 416f6ac65b761080a2e81a8ace5c5d442a8ea2d1..6cdc931f7c1773e6fb59b2c8bbac85df950a9f86 100644 (file)
@@ -320,7 +320,7 @@ found:
        for (bus = dev->bus; bus; bus = bus->parent) {
                struct pci_dev *bridge = bus->self;
 
-               if (!bridge || !bridge->is_pcie ||
+               if (!bridge || !pci_is_pcie(bridge) ||
                    bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
                        return 0;
 
@@ -645,8 +645,11 @@ void __init detect_intel_iommu(void)
                               "x2apic and Intr-remapping.\n");
 #endif
 #ifdef CONFIG_DMAR
-               if (ret && !no_iommu && !iommu_detected && !dmar_disabled)
+               if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
                        iommu_detected = 1;
+                       /* Make sure ACS will be enabled */
+                       pci_request_acs();
+               }
 #endif
 #ifdef CONFIG_X86
                if (ret)
index 3625b094bf7eeb2a80bde2a3e59fcbf631b5758a..6cd9f3c9887d2ac9841b542d92475a91f1d845b6 100644 (file)
@@ -6,18 +6,22 @@ obj-$(CONFIG_HOTPLUG_PCI)             += pci_hotplug.o
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)       += cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)          += ibmphp.o
 
-# pciehp should be linked before acpiphp in order to allow the native driver
-# to attempt to bind first. We can then fall back to generic support.
+# native drivers should be linked before acpiphp in order to allow the
+# native driver to attempt to bind first. We can then fall back to
+# generic support.
 
 obj-$(CONFIG_HOTPLUG_PCI_PCIE)         += pciehp.o
-obj-$(CONFIG_HOTPLUG_PCI_ACPI)         += acpiphp.o
-obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM)     += acpiphp_ibm.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550)  += cpcihp_zt5550.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o
 obj-$(CONFIG_HOTPLUG_PCI_SHPC)         += shpchp.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA)          += rpaphp.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)    += rpadlpar_io.o
 obj-$(CONFIG_HOTPLUG_PCI_SGI)          += sgi_hotplug.o
+obj-$(CONFIG_HOTPLUG_PCI_ACPI)         += acpiphp.o
+
+# acpiphp_ibm extends acpiphp, so should be linked afterwards.
+
+obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM)     += acpiphp_ibm.o
 
 # Link this last so it doesn't claim devices that have a real hotplug driver
 obj-$(CONFIG_HOTPLUG_PCI_FAKE)         += fakephp.o
index 0f32571b94df406d09c9cbf024d2c11dd41bc89e..3c76fc67cf0e62f8598877881ce40efb0c7a12ae 100644 (file)
@@ -362,6 +362,8 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
                status = acpi_pci_osc_control_set(handle, flags);
                if (ACPI_SUCCESS(status))
                        goto got_one;
+               if (status == AE_SUPPORT)
+                       goto no_control;
                kfree(string.pointer);
                string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL };
        }
@@ -394,10 +396,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
                if (ACPI_FAILURE(status))
                        break;
        }
-
+no_control:
        dbg("Cannot get control of hotplug hardware for pci %s\n",
            pci_name(pdev));
-
        kfree(string.pointer);
        return -ENODEV;
 got_one:
index 7d938df792065f86b26eca672dde731dfcf344d2..bab52047baa84101d2448a06b617381b21918444 100644 (file)
@@ -146,12 +146,6 @@ struct acpiphp_attention_info
        struct module *owner;
 };
 
-struct acpiphp_ioapic {
-       struct pci_dev *dev;
-       u32 gsi_base;
-       struct list_head list;
-};
-
 /* PCI bus bridge HID */
 #define ACPI_PCI_HOST_HID              "PNP0A03"
 
index df1b0ea089d12218c1b7d55342211688aef32c70..8e952fdab7642a83aaedfefeba108826127e8807 100644 (file)
@@ -52,8 +52,6 @@
 #include "acpiphp.h"
 
 static LIST_HEAD(bridge_list);
-static LIST_HEAD(ioapic_list);
-static DEFINE_SPINLOCK(ioapic_list_lock);
 
 #define MY_NAME "acpiphp_glue"
 
@@ -311,17 +309,13 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
 /* find acpiphp_func from acpiphp_bridge */
 static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle)
 {
-       struct list_head *node, *l;
        struct acpiphp_bridge *bridge;
        struct acpiphp_slot *slot;
        struct acpiphp_func *func;
 
-       list_for_each(node, &bridge_list) {
-               bridge = list_entry(node, struct acpiphp_bridge, list);
+       list_for_each_entry(bridge, &bridge_list, list) {
                for (slot = bridge->slots; slot; slot = slot->next) {
-                       list_for_each(l, &slot->funcs) {
-                               func = list_entry(l, struct acpiphp_func,
-                                                       sibling);
+                       list_for_each_entry(func, &slot->funcs, sibling) {
                                if (func->handle == handle)
                                        return func;
                        }
@@ -495,21 +489,19 @@ static int add_bridge(acpi_handle handle)
 
 static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
 {
-       struct list_head *head;
-       list_for_each(head, &bridge_list) {
-               struct acpiphp_bridge *bridge = list_entry(head,
-                                               struct acpiphp_bridge, list);
+       struct acpiphp_bridge *bridge;
+
+       list_for_each_entry(bridge, &bridge_list, list)
                if (bridge->handle == handle)
                        return bridge;
-       }
 
        return NULL;
 }
 
 static void cleanup_bridge(struct acpiphp_bridge *bridge)
 {
-       struct list_head *list, *tmp;
-       struct acpiphp_slot *slot;
+       struct acpiphp_slot *slot, *next;
+       struct acpiphp_func *func, *tmp;
        acpi_status status;
        acpi_handle handle = bridge->handle;
 
@@ -530,10 +522,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
 
        slot = bridge->slots;
        while (slot) {
-               struct acpiphp_slot *next = slot->next;
-               list_for_each_safe (list, tmp, &slot->funcs) {
-                       struct acpiphp_func *func;
-                       func = list_entry(list, struct acpiphp_func, sibling);
+               next = slot->next;
+               list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) {
                        if (is_dock_device(func->handle)) {
                                unregister_hotplug_dock_device(func->handle);
                                unregister_dock_notifier(&func->nb);
@@ -545,7 +535,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
                                if (ACPI_FAILURE(status))
                                        err("failed to remove notify handler\n");
                        }
-                       list_del(list);
+                       list_del(&func->sibling);
                        kfree(func);
                }
                acpiphp_unregister_hotplug_slot(slot);
@@ -606,204 +596,17 @@ static void remove_bridge(acpi_handle handle)
                                           handle_hotplug_event_bridge);
 }
 
-static struct pci_dev * get_apic_pci_info(acpi_handle handle)
-{
-       struct pci_dev *dev;
-
-       dev = acpi_get_pci_dev(handle);
-       if (!dev)
-               return NULL;
-
-       if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) &&
-           (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC))
-       {
-               pci_dev_put(dev);
-               return NULL;
-       }
-
-       return dev;
-}
-
-static int get_gsi_base(acpi_handle handle, u32 *gsi_base)
-{
-       acpi_status status;
-       int result = -1;
-       unsigned long long gsb;
-       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
-       union acpi_object *obj;
-       void *table;
-
-       status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
-       if (ACPI_SUCCESS(status)) {
-               *gsi_base = (u32)gsb;
-               return 0;
-       }
-
-       status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer);
-       if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer)
-               return -1;
-
-       obj = buffer.pointer;
-       if (obj->type != ACPI_TYPE_BUFFER)
-               goto out;
-
-       table = obj->buffer.pointer;
-       switch (((struct acpi_subtable_header *)table)->type) {
-       case ACPI_MADT_TYPE_IO_SAPIC:
-               *gsi_base = ((struct acpi_madt_io_sapic *)table)->global_irq_base;
-               result = 0;
-               break;
-       case ACPI_MADT_TYPE_IO_APIC:
-               *gsi_base = ((struct acpi_madt_io_apic *)table)->global_irq_base;
-               result = 0;
-               break;
-       default:
-               break;
-       }
- out:
-       kfree(buffer.pointer);
-       return result;
-}
-
-static acpi_status
-ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       acpi_status status;
-       unsigned long long sta;
-       acpi_handle tmp;
-       struct pci_dev *pdev;
-       u32 gsi_base;
-       u64 phys_addr;
-       struct acpiphp_ioapic *ioapic;
-
-       /* Evaluate _STA if present */
-       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-       if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
-               return AE_CTRL_DEPTH;
-
-       /* Scan only PCI bus scope */
-       status = acpi_get_handle(handle, "_HID", &tmp);
-       if (ACPI_SUCCESS(status))
-               return AE_CTRL_DEPTH;
-
-       if (get_gsi_base(handle, &gsi_base))
-               return AE_OK;
-
-       ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL);
-       if (!ioapic)
-               return AE_NO_MEMORY;
-
-       pdev = get_apic_pci_info(handle);
-       if (!pdev)
-               goto exit_kfree;
-
-       if (pci_enable_device(pdev))
-               goto exit_pci_dev_put;
-
-       pci_set_master(pdev);
-
-       if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)"))
-               goto exit_pci_disable_device;
-
-       phys_addr = pci_resource_start(pdev, 0);
-       if (acpi_register_ioapic(handle, phys_addr, gsi_base))
-               goto exit_pci_release_region;
-
-       ioapic->gsi_base = gsi_base;
-       ioapic->dev = pdev;
-       spin_lock(&ioapic_list_lock);
-       list_add_tail(&ioapic->list, &ioapic_list);
-       spin_unlock(&ioapic_list_lock);
-
-       return AE_OK;
-
- exit_pci_release_region:
-       pci_release_region(pdev, 0);
- exit_pci_disable_device:
-       pci_disable_device(pdev);
- exit_pci_dev_put:
-       pci_dev_put(pdev);
- exit_kfree:
-       kfree(ioapic);
-
-       return AE_OK;
-}
-
-static acpi_status
-ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       acpi_status status;
-       unsigned long long sta;
-       acpi_handle tmp;
-       u32 gsi_base;
-       struct acpiphp_ioapic *pos, *n, *ioapic = NULL;
-
-       /* Evaluate _STA if present */
-       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-       if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
-               return AE_CTRL_DEPTH;
-
-       /* Scan only PCI bus scope */
-       status = acpi_get_handle(handle, "_HID", &tmp);
-       if (ACPI_SUCCESS(status))
-               return AE_CTRL_DEPTH;
-
-       if (get_gsi_base(handle, &gsi_base))
-               return AE_OK;
-
-       acpi_unregister_ioapic(handle, gsi_base);
-
-       spin_lock(&ioapic_list_lock);
-       list_for_each_entry_safe(pos, n, &ioapic_list, list) {
-               if (pos->gsi_base != gsi_base)
-                       continue;
-               ioapic = pos;
-               list_del(&ioapic->list);
-               break;
-       }
-       spin_unlock(&ioapic_list_lock);
-
-       if (!ioapic)
-               return AE_OK;
-
-       pci_release_region(ioapic->dev, 0);
-       pci_disable_device(ioapic->dev);
-       pci_dev_put(ioapic->dev);
-       kfree(ioapic);
-
-       return AE_OK;
-}
-
-static int acpiphp_configure_ioapics(acpi_handle handle)
-{
-       ioapic_add(handle, 0, NULL, NULL);
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-                           ACPI_UINT32_MAX, ioapic_add, NULL, NULL, NULL);
-       return 0;
-}
-
-static int acpiphp_unconfigure_ioapics(acpi_handle handle)
-{
-       ioapic_remove(handle, 0, NULL, NULL);
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-                           ACPI_UINT32_MAX, ioapic_remove, NULL, NULL, NULL);
-       return 0;
-}
-
 static int power_on_slot(struct acpiphp_slot *slot)
 {
        acpi_status status;
        struct acpiphp_func *func;
-       struct list_head *l;
        int retval = 0;
 
        /* if already enabled, just skip */
        if (slot->flags & SLOT_POWEREDON)
                goto err_exit;
 
-       list_for_each (l, &slot->funcs) {
-               func = list_entry(l, struct acpiphp_func, sibling);
-
+       list_for_each_entry(func, &slot->funcs, sibling) {
                if (func->flags & FUNC_HAS_PS0) {
                        dbg("%s: executing _PS0\n", __func__);
                        status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
@@ -829,7 +632,6 @@ static int power_off_slot(struct acpiphp_slot *slot)
 {
        acpi_status status;
        struct acpiphp_func *func;
-       struct list_head *l;
 
        int retval = 0;
 
@@ -837,9 +639,7 @@ static int power_off_slot(struct acpiphp_slot *slot)
        if ((slot->flags & SLOT_POWEREDON) == 0)
                goto err_exit;
 
-       list_for_each (l, &slot->funcs) {
-               func = list_entry(l, struct acpiphp_func, sibling);
-
+       list_for_each_entry(func, &slot->funcs, sibling) {
                if (func->flags & FUNC_HAS_PS3) {
                        status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
                        if (ACPI_FAILURE(status)) {
@@ -966,7 +766,6 @@ static int __ref enable_device(struct acpiphp_slot *slot)
 {
        struct pci_dev *dev;
        struct pci_bus *bus = slot->bridge->pci_bus;
-       struct list_head *l;
        struct acpiphp_func *func;
        int retval = 0;
        int num, max, pass;
@@ -1006,21 +805,16 @@ static int __ref enable_device(struct acpiphp_slot *slot)
                }
        }
 
-       list_for_each (l, &slot->funcs) {
-               func = list_entry(l, struct acpiphp_func, sibling);
+       list_for_each_entry(func, &slot->funcs, sibling)
                acpiphp_bus_add(func);
-       }
 
        pci_bus_assign_resources(bus);
        acpiphp_sanitize_bus(bus);
        acpiphp_set_hpp_values(bus);
-       list_for_each_entry(func, &slot->funcs, sibling)
-               acpiphp_configure_ioapics(func->handle);
        pci_enable_bridges(bus);
        pci_bus_add_devices(bus);
 
-       list_for_each (l, &slot->funcs) {
-               func = list_entry(l, struct acpiphp_func, sibling);
+       list_for_each_entry(func, &slot->funcs, sibling) {
                dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
                                                  func->function));
                if (!dev)
@@ -1091,7 +885,6 @@ static int disable_device(struct acpiphp_slot *slot)
        }
 
        list_for_each_entry(func, &slot->funcs, sibling) {
-               acpiphp_unconfigure_ioapics(func->handle);
                acpiphp_bus_trim(func->handle);
        }
 
@@ -1119,12 +912,9 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
        acpi_status status;
        unsigned long long sta = 0;
        u32 dvid;
-       struct list_head *l;
        struct acpiphp_func *func;
 
-       list_for_each (l, &slot->funcs) {
-               func = list_entry(l, struct acpiphp_func, sibling);
-
+       list_for_each_entry(func, &slot->funcs, sibling) {
                if (func->flags & FUNC_HAS_STA) {
                        status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta);
                        if (ACPI_SUCCESS(status) && sta)
@@ -1152,13 +942,10 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot)
 {
        acpi_status status;
        struct acpiphp_func *func;
-       struct list_head *l;
        struct acpi_object_list arg_list;
        union acpi_object arg;
 
-       list_for_each (l, &slot->funcs) {
-               func = list_entry(l, struct acpiphp_func, sibling);
-
+       list_for_each_entry(func, &slot->funcs, sibling) {
                /* We don't want to call _EJ0 on non-existing functions. */
                if ((func->flags & FUNC_HAS_EJ0)) {
                        /* _EJ0 method take one argument */
@@ -1275,7 +1062,6 @@ static int acpiphp_configure_bridge (acpi_handle handle)
        acpiphp_sanitize_bus(bus);
        acpiphp_set_hpp_values(bus);
        pci_enable_bridges(bus);
-       acpiphp_configure_ioapics(handle);
        return 0;
 }
 
@@ -1542,7 +1328,7 @@ int __init acpiphp_get_num_slots(void)
        struct acpiphp_bridge *bridge;
        int num_slots = 0;
 
-       list_for_each_entry (bridge, &bridge_list, list) {
+       list_for_each_entry(bridge, &bridge_list, list) {
                dbg("Bus %04x:%02x has %d slot%s\n",
                                pci_domain_nr(bridge->pci_bus),
                                bridge->pci_bus->number, bridge->nr_slots,
index 83f337c891a9ca2ad78c82c3352c11da181c4cea..c7084f0eca5aaf29678933e7a16cb286ff6b0a3a 100644 (file)
@@ -890,7 +890,7 @@ static int poll_hpc(void *data)
                        msleep(POLL_INTERVAL_SEC * 1000);
 
                        if (kthread_should_stop())
-                               break;
+                               goto out_sleep;
                        
                        down (&semOperations);
                        
@@ -904,6 +904,7 @@ static int poll_hpc(void *data)
                /* give up the hardware semaphore */
                up (&semOperations);
                /* sleep for a short time just for good measure */
+out_sleep:
                msleep(100);
        }
        up (&sem_exit);
index 0325d989bb46f138d7ff1923e8e28bb03efa4d55..38183a534b653c6965ffa875c5b699b02f1d58ab 100644 (file)
@@ -68,26 +68,26 @@ static DEFINE_MUTEX(pci_hp_mutex);
 static char *pci_bus_speed_strings[] = {
        "33 MHz PCI",           /* 0x00 */
        "66 MHz PCI",           /* 0x01 */
-       "66 MHz PCIX",          /* 0x02 */
-       "100 MHz PCIX",         /* 0x03 */
-       "133 MHz PCIX",         /* 0x04 */
+       "66 MHz PCI-X",         /* 0x02 */
+       "100 MHz PCI-X",        /* 0x03 */
+       "133 MHz PCI-X",        /* 0x04 */
        NULL,                   /* 0x05 */
        NULL,                   /* 0x06 */
        NULL,                   /* 0x07 */
        NULL,                   /* 0x08 */
-       "66 MHz PCIX 266",      /* 0x09 */
-       "100 MHz PCIX 266",     /* 0x0a */
-       "133 MHz PCIX 266",     /* 0x0b */
+       "66 MHz PCI-X 266",     /* 0x09 */
+       "100 MHz PCI-X 266",    /* 0x0a */
+       "133 MHz PCI-X 266",    /* 0x0b */
        NULL,                   /* 0x0c */
        NULL,                   /* 0x0d */
        NULL,                   /* 0x0e */
        NULL,                   /* 0x0f */
        NULL,                   /* 0x10 */
-       "66 MHz PCIX 533",      /* 0x11 */
-       "100 MHz PCIX 533",     /* 0x12 */
-       "133 MHz PCIX 533",     /* 0x13 */
-       "2.5 GT/s PCI-E",       /* 0x14 */
-       "5.0 GT/s PCI-E",       /* 0x15 */
+       "66 MHz PCI-X 533",     /* 0x11 */
+       "100 MHz PCI-X 533",    /* 0x12 */
+       "133 MHz PCI-X 533",    /* 0x13 */
+       "2.5 GT/s PCIe",        /* 0x14 */
+       "5.0 GT/s PCIe",        /* 0x15 */
 };
 
 #ifdef CONFIG_HOTPLUG_PCI_CPCI
index 3070f77eb56ad3c4e53bf4369fcad7e40993ed3b..4ed76b47b6dcbd6358e083b11d5f8e823daa9cdb 100644 (file)
@@ -91,7 +91,6 @@ struct controller {
        struct slot *slot;
        wait_queue_head_t queue;        /* sleep & wake process */
        u32 slot_cap;
-       u8 cap_base;
        struct timer_list poll_timer;
        unsigned int cmd_busy:1;
        unsigned int no_cmd_complete:1;
index 37c8d3d0323e60602d6a6b4296e5e6668139c696..b09b083011d69ad43e743490bad963266f6af36b 100644 (file)
@@ -87,7 +87,8 @@ static int __init dummy_probe(struct pcie_device *dev)
        /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
        if (pciehp_get_hp_hw_control_from_firmware(pdev))
                return -ENODEV;
-       if (!(pos = pci_find_capability(pdev, PCI_CAP_ID_EXP)))
+       pos = pci_pcie_cap(pdev);
+       if (!pos)
                return -ENODEV;
        pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap);
        slot = kzalloc(sizeof(*slot), GFP_KERNEL);
index bc234719b1df7208f8f12003fe3f99b8997cb0ee..5674b2075bdc305699388f4e1528f6f951d4fe7b 100644 (file)
@@ -72,18 +72,6 @@ static int get_adapter_status        (struct hotplug_slot *slot, u8 *value);
 static int get_max_bus_speed   (struct hotplug_slot *slot, enum pci_bus_speed *value);
 static int get_cur_bus_speed   (struct hotplug_slot *slot, enum pci_bus_speed *value);
 
-static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
-       .set_attention_status = set_attention_status,
-       .enable_slot =          enable_slot,
-       .disable_slot =         disable_slot,
-       .get_power_status =     get_power_status,
-       .get_attention_status = get_attention_status,
-       .get_latch_status =     get_latch_status,
-       .get_adapter_status =   get_adapter_status,
-       .get_max_bus_speed =    get_max_bus_speed,
-       .get_cur_bus_speed =    get_cur_bus_speed,
-};
-
 /**
  * release_slot - free up the memory used by a slot
  * @hotplug_slot: slot to free
@@ -95,6 +83,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                 __func__, hotplug_slot_name(hotplug_slot));
 
+       kfree(hotplug_slot->ops);
        kfree(hotplug_slot->info);
        kfree(hotplug_slot);
 }
@@ -104,6 +93,7 @@ static int init_slot(struct controller *ctrl)
        struct slot *slot = ctrl->slot;
        struct hotplug_slot *hotplug = NULL;
        struct hotplug_slot_info *info = NULL;
+       struct hotplug_slot_ops *ops = NULL;
        char name[SLOT_NAME_SIZE];
        int retval = -ENOMEM;
 
@@ -115,11 +105,28 @@ static int init_slot(struct controller *ctrl)
        if (!info)
                goto out;
 
+       /* Setup hotplug slot ops */
+       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;
+       ops->get_adapter_status = get_adapter_status;
+       ops->get_max_bus_speed = get_max_bus_speed;
+       ops->get_cur_bus_speed = get_cur_bus_speed;
+       if (MRL_SENS(ctrl))
+               ops->get_latch_status = get_latch_status;
+       if (ATTN_LED(ctrl)) {
+               ops->get_attention_status = get_attention_status;
+               ops->set_attention_status = set_attention_status;
+       }
+
        /* register this slot with the hotplug pci core */
        hotplug->info = info;
        hotplug->private = slot;
        hotplug->release = &release_slot;
-       hotplug->ops = &pciehp_hotplug_slot_ops;
+       hotplug->ops = ops;
        slot->hotplug_slot = hotplug;
        snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl));
 
@@ -128,17 +135,12 @@ static int init_slot(struct controller *ctrl)
                 ctrl->pcie->port->subordinate->number, PSN(ctrl));
        retval = pci_hp_register(hotplug,
                                 ctrl->pcie->port->subordinate, 0, name);
-       if (retval) {
+       if (retval)
                ctrl_err(ctrl,
                         "pci_hp_register failed with error %d\n", retval);
-               goto out;
-       }
-       get_power_status(hotplug, &info->power_status);
-       get_attention_status(hotplug, &info->attention_status);
-       get_latch_status(hotplug, &info->latch_status);
-       get_adapter_status(hotplug, &info->adapter_status);
 out:
        if (retval) {
+               kfree(ops);
                kfree(info);
                kfree(hotplug);
        }
@@ -160,12 +162,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                  __func__, slot_name(slot));
 
-       hotplug_slot->info->attention_status = status;
-
-       if (ATTN_LED(slot->ctrl))
-               pciehp_set_attention_status(slot, status);
-
-       return 0;
+       return pciehp_set_attention_status(slot, status);
 }
 
 
@@ -193,92 +190,62 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
        struct slot *slot = hotplug_slot->private;
-       int retval;
 
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                  __func__, slot_name(slot));
 
-       retval = pciehp_get_power_status(slot, value);
-       if (retval < 0)
-               *value = hotplug_slot->info->power_status;
-
-       return 0;
+       return pciehp_get_power_status(slot, value);
 }
 
 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
        struct slot *slot = hotplug_slot->private;
-       int retval;
 
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                  __func__, slot_name(slot));
 
-       retval = pciehp_get_attention_status(slot, value);
-       if (retval < 0)
-               *value = hotplug_slot->info->attention_status;
-
-       return 0;
+       return pciehp_get_attention_status(slot, value);
 }
 
 static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
        struct slot *slot = hotplug_slot->private;
-       int retval;
 
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                 __func__, slot_name(slot));
 
-       retval = pciehp_get_latch_status(slot, value);
-       if (retval < 0)
-               *value = hotplug_slot->info->latch_status;
-
-       return 0;
+       return pciehp_get_latch_status(slot, value);
 }
 
 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
        struct slot *slot = hotplug_slot->private;
-       int retval;
 
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                 __func__, slot_name(slot));
 
-       retval = pciehp_get_adapter_status(slot, value);
-       if (retval < 0)
-               *value = hotplug_slot->info->adapter_status;
-
-       return 0;
+       return pciehp_get_adapter_status(slot, value);
 }
 
 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
                                enum pci_bus_speed *value)
 {
        struct slot *slot = hotplug_slot->private;
-       int retval;
 
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                 __func__, slot_name(slot));
 
-       retval = pciehp_get_max_link_speed(slot, value);
-       if (retval < 0)
-               *value = PCI_SPEED_UNKNOWN;
-
-       return 0;
+       return pciehp_get_max_link_speed(slot, value);
 }
 
 static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 {
        struct slot *slot = hotplug_slot->private;
-       int retval;
 
        ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
                 __func__, slot_name(slot));
 
-       retval = pciehp_get_cur_link_speed(slot, value);
-       if (retval < 0)
-               *value = PCI_SPEED_UNKNOWN;
-
-       return 0;
+       return pciehp_get_cur_link_speed(slot, value);
 }
 
 static int pciehp_probe(struct pcie_device *dev)
@@ -286,14 +253,13 @@ static int pciehp_probe(struct pcie_device *dev)
        int rc;
        struct controller *ctrl;
        struct slot *slot;
-       u8 value;
-       struct pci_dev *pdev = dev->port;
+       u8 occupied, poweron;
 
        if (pciehp_force)
                dev_info(&dev->device,
                         "Bypassing BIOS check for pciehp use on %s\n",
-                        pci_name(pdev));
-       else if (pciehp_get_hp_hw_control_from_firmware(pdev))
+                        pci_name(dev->port));
+       else if (pciehp_get_hp_hw_control_from_firmware(dev->port))
                goto err_out_none;
 
        ctrl = pcie_init(dev);
@@ -318,23 +284,18 @@ static int pciehp_probe(struct pcie_device *dev)
        rc = pcie_init_notification(ctrl);
        if (rc) {
                ctrl_err(ctrl, "Notification initialization failed\n");
-               goto err_out_release_ctlr;
+               goto err_out_free_ctrl_slot;
        }
 
        /* Check if slot is occupied */
        slot = ctrl->slot;
-       pciehp_get_adapter_status(slot, &value);
-       if (value) {
-               if (pciehp_force)
-                       pciehp_enable_slot(slot);
-       } else {
-               /* Power off slot if not occupied */
-               if (POWER_CTRL(ctrl)) {
-                       rc = pciehp_power_off_slot(slot);
-                       if (rc)
-                               goto err_out_free_ctrl_slot;
-               }
-       }
+       pciehp_get_adapter_status(slot, &occupied);
+       pciehp_get_power_status(slot, &poweron);
+       if (occupied && pciehp_force)
+               pciehp_enable_slot(slot);
+       /* If empty slot's power status is on, turn power off */
+       if (!occupied && poweron && POWER_CTRL(ctrl))
+               pciehp_power_off_slot(slot);
 
        return 0;
 
index 84487d126e4d7098c4010425b3dcfebe6a6122cf..d6ac1b261dd9d8b9a94185c93006b9739ea04305 100644 (file)
@@ -142,23 +142,9 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)
 
        /* power fault */
        ctrl_dbg(ctrl, "Power fault interrupt received\n");
-
-       if (!pciehp_query_power_fault(p_slot)) {
-               /*
-                * power fault Cleared
-                */
-               ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
-                         slot_name(p_slot));
-               event_type = INT_POWER_FAULT_CLEAR;
-       } else {
-               /*
-                *   power fault
-                */
-               ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
-               event_type = INT_POWER_FAULT;
-               ctrl_info(ctrl, "Power fault bit %x set\n", 0);
-       }
-
+       ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
+       event_type = INT_POWER_FAULT;
+       ctrl_info(ctrl, "Power fault bit %x set\n", 0);
        queue_interrupt_event(p_slot, event_type);
 
        return 1;
@@ -224,13 +210,12 @@ static int board_added(struct slot *p_slot)
        retval = pciehp_check_link_status(ctrl);
        if (retval) {
                ctrl_err(ctrl, "Failed to check link status\n");
-               set_slot_off(ctrl, p_slot);
-               return retval;
+               goto err_exit;
        }
 
        /* Check for a power fault */
-       if (pciehp_query_power_fault(p_slot)) {
-               ctrl_dbg(ctrl, "Power fault detected\n");
+       if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
+               ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
                retval = -EIO;
                goto err_exit;
        }
@@ -363,25 +348,6 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
        mutex_unlock(&p_slot->lock);
 }
 
-static int update_slot_info(struct slot *slot)
-{
-       struct hotplug_slot_info *info;
-       int result;
-
-       info = kmalloc(sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       pciehp_get_power_status(slot, &info->power_status);
-       pciehp_get_attention_status(slot, &info->attention_status);
-       pciehp_get_latch_status(slot, &info->latch_status);
-       pciehp_get_adapter_status(slot, &info->adapter_status);
-
-       result = pci_hp_change_slot_info(slot->hotplug_slot, info);
-       kfree (info);
-       return result;
-}
-
 /*
  * Note: This function must be called with slot->lock held
  */
@@ -442,7 +408,6 @@ static void handle_button_press_event(struct slot *p_slot)
                 * to hot-add or hot-remove is undergoing
                 */
                ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot));
-               update_slot_info(p_slot);
                break;
        default:
                ctrl_warn(ctrl, "Not a valid state\n");
@@ -500,11 +465,9 @@ static void interrupt_event_handler(struct work_struct *work)
                if (!HP_SUPR_RM(ctrl))
                        break;
                ctrl_dbg(ctrl, "Surprise Removal\n");
-               update_slot_info(p_slot);
                handle_surprise_event(p_slot);
                break;
        default:
-               update_slot_info(p_slot);
                break;
        }
        mutex_unlock(&p_slot->lock);
@@ -547,9 +510,6 @@ int pciehp_enable_slot(struct slot *p_slot)
        if (rc) {
                pciehp_get_latch_status(p_slot, &getstatus);
        }
-
-       update_slot_info(p_slot);
-
        return rc;
 }
 
@@ -590,10 +550,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                }
        }
 
-       ret = remove_board(p_slot);
-       update_slot_info(p_slot);
-
-       return ret;
+       return remove_board(p_slot);
 }
 
 int pciehp_sysfs_enable_slot(struct slot *p_slot)
index 9ef4605c1ef6471fa6beddd55ccdb4465a2d7952..10040d58c8efaa6ec17b71bb52f419f40d2ccb90 100644 (file)
@@ -45,25 +45,25 @@ static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
 static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value)
 {
        struct pci_dev *dev = ctrl->pcie->port;
-       return pci_read_config_word(dev, ctrl->cap_base + reg, value);
+       return pci_read_config_word(dev, pci_pcie_cap(dev) + reg, value);
 }
 
 static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value)
 {
        struct pci_dev *dev = ctrl->pcie->port;
-       return pci_read_config_dword(dev, ctrl->cap_base + reg, value);
+       return pci_read_config_dword(dev, pci_pcie_cap(dev) + reg, value);
 }
 
 static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value)
 {
        struct pci_dev *dev = ctrl->pcie->port;
-       return pci_write_config_word(dev, ctrl->cap_base + reg, value);
+       return pci_write_config_word(dev, pci_pcie_cap(dev) + reg, value);
 }
 
 static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
 {
        struct pci_dev *dev = ctrl->pcie->port;
-       return pci_write_config_dword(dev, ctrl->cap_base + reg, value);
+       return pci_write_config_dword(dev, pci_pcie_cap(dev) + reg, value);
 }
 
 /* Power Control Command */
@@ -318,8 +318,8 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status)
                return retval;
        }
 
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n",
-                __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl);
+       ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__,
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl);
 
        atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6;
 
@@ -356,8 +356,8 @@ int pciehp_get_power_status(struct slot *slot, u8 *status)
                ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
                return retval;
        }
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n",
-                __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl);
+       ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__,
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl);
 
        pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10;
 
@@ -427,27 +427,24 @@ int pciehp_set_attention_status(struct slot *slot, u8 value)
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
        u16 cmd_mask;
-       int rc;
 
        cmd_mask = PCI_EXP_SLTCTL_AIC;
        switch (value) {
-               case 0 :        /* turn off */
-                       slot_cmd = 0x00C0;
-                       break;
-               case 1:         /* turn on */
-                       slot_cmd = 0x0040;
-                       break;
-               case 2:         /* turn blink */
-                       slot_cmd = 0x0080;
-                       break;
-               default:
-                       return -1;
+       case 0 :        /* turn off */
+               slot_cmd = 0x00C0;
+               break;
+       case 1:         /* turn on */
+               slot_cmd = 0x0040;
+               break;
+       case 2:         /* turn blink */
+               slot_cmd = 0x0080;
+               break;
+       default:
+               return -EINVAL;
        }
-       rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
-                __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
-
-       return rc;
+       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
+       return pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
 }
 
 void pciehp_green_led_on(struct slot *slot)
@@ -459,8 +456,8 @@ void pciehp_green_led_on(struct slot *slot)
        slot_cmd = 0x0100;
        cmd_mask = PCI_EXP_SLTCTL_PIC;
        pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
-                __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
+       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
 }
 
 void pciehp_green_led_off(struct slot *slot)
@@ -472,8 +469,8 @@ void pciehp_green_led_off(struct slot *slot)
        slot_cmd = 0x0300;
        cmd_mask = PCI_EXP_SLTCTL_PIC;
        pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
-                __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
+       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
 }
 
 void pciehp_green_led_blink(struct slot *slot)
@@ -485,8 +482,8 @@ void pciehp_green_led_blink(struct slot *slot)
        slot_cmd = 0x0200;
        cmd_mask = PCI_EXP_SLTCTL_PIC;
        pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
-                __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
+       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
 }
 
 int pciehp_power_on_slot(struct slot * slot)
@@ -514,97 +511,38 @@ int pciehp_power_on_slot(struct slot * slot)
                        return retval;
                }
        }
+       ctrl->power_fault_detected = 0;
 
        slot_cmd = POWER_ON;
        cmd_mask = PCI_EXP_SLTCTL_PCC;
-       if (!pciehp_poll_mode) {
-               /* Enable power fault detection turned off at power off time */
-               slot_cmd |= PCI_EXP_SLTCTL_PFDE;
-               cmd_mask |= PCI_EXP_SLTCTL_PFDE;
-       }
-
        retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
        if (retval) {
                ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd);
                return retval;
        }
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
-                __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
+       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
 
-       ctrl->power_fault_detected = 0;
        return retval;
 }
 
-static inline int pcie_mask_bad_dllp(struct controller *ctrl)
-{
-       struct pci_dev *dev = ctrl->pcie->port;
-       int pos;
-       u32 reg;
-
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
-       if (!pos)
-               return 0;
-       pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
-       if (reg & PCI_ERR_COR_BAD_DLLP)
-               return 0;
-       reg |= PCI_ERR_COR_BAD_DLLP;
-       pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
-       return 1;
-}
-
-static inline void pcie_unmask_bad_dllp(struct controller *ctrl)
-{
-       struct pci_dev *dev = ctrl->pcie->port;
-       u32 reg;
-       int pos;
-
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
-       if (!pos)
-               return;
-       pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
-       if (!(reg & PCI_ERR_COR_BAD_DLLP))
-               return;
-       reg &= ~PCI_ERR_COR_BAD_DLLP;
-       pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
-}
-
 int pciehp_power_off_slot(struct slot * slot)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
        u16 cmd_mask;
-       int retval = 0;
-       int changed;
-
-       /*
-        * Set Bad DLLP Mask bit in Correctable Error Mask
-        * Register. This is the workaround against Bad DLLP error
-        * that sometimes happens during turning power off the slot
-        * which conforms to PCI Express 1.0a spec.
-        */
-       changed = pcie_mask_bad_dllp(ctrl);
+       int retval;
 
        slot_cmd = POWER_OFF;
        cmd_mask = PCI_EXP_SLTCTL_PCC;
-       if (!pciehp_poll_mode) {
-               /* Disable power fault detection */
-               slot_cmd &= ~PCI_EXP_SLTCTL_PFDE;
-               cmd_mask |= PCI_EXP_SLTCTL_PFDE;
-       }
-
        retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
        if (retval) {
                ctrl_err(ctrl, "Write command failed!\n");
-               retval = -1;
-               goto out;
+               return retval;
        }
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
-                __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
- out:
-       if (changed)
-               pcie_unmask_bad_dllp(ctrl);
-
-       return retval;
+       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
+       return 0;
 }
 
 static irqreturn_t pcie_isr(int irq, void *dev_id)
@@ -840,11 +778,19 @@ int pcie_enable_notification(struct controller *ctrl)
 {
        u16 cmd, mask;
 
+       /*
+        * TBD: Power fault detected software notification support.
+        *
+        * Power fault detected software notification is not enabled
+        * now, because it caused power fault detected interrupt storm
+        * on some machines. On those machines, power fault detected
+        * bit in the slot status register was set again immediately
+        * when it is cleared in the interrupt service routine, and
+        * next power fault detected interrupt was notified again.
+        */
        cmd = PCI_EXP_SLTCTL_PDCE;
        if (ATTN_BUTTN(ctrl))
                cmd |= PCI_EXP_SLTCTL_ABPE;
-       if (POWER_CTRL(ctrl))
-               cmd |= PCI_EXP_SLTCTL_PFDE;
        if (MRL_SENS(ctrl))
                cmd |= PCI_EXP_SLTCTL_MRLSCE;
        if (!pciehp_poll_mode)
@@ -866,7 +812,8 @@ static void pcie_disable_notification(struct controller *ctrl)
        u16 mask;
        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);
        if (pcie_write_cmd(ctrl, 0, mask))
                ctrl_warn(ctrl, "Cannot disable software notification\n");
 }
@@ -934,7 +881,8 @@ static inline void dbg_ctrl(struct controller *ctrl)
                  pdev->subsystem_device);
        ctrl_info(ctrl, "  Subsystem Vendor ID  : 0x%04x\n",
                  pdev->subsystem_vendor);
-       ctrl_info(ctrl, "  PCIe Cap offset      : 0x%02x\n", ctrl->cap_base);
+       ctrl_info(ctrl, "  PCIe Cap offset      : 0x%02x\n",
+                 pci_pcie_cap(pdev));
        for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
                if (!pci_resource_len(pdev, i))
                        continue;
@@ -978,8 +926,7 @@ struct controller *pcie_init(struct pcie_device *dev)
                goto abort;
        }
        ctrl->pcie = dev;
-       ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-       if (!ctrl->cap_base) {
+       if (!pci_pcie_cap(pdev)) {
                ctrl_err(ctrl, "Cannot find PCI Express capability\n");
                goto abort_ctrl;
        }
index cc8ec3aa41a7f494f7338b0c30a4c2efcefe7a81..80b461c985579da3905744c36aabfd215c9cac06 100644 (file)
@@ -43,7 +43,7 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
                 * Perhaps we *should* use default settings for PCIe, but
                 * pciehp didn't, so we won't either.
                 */
-               if (dev->is_pcie)
+               if (pci_is_pcie(dev))
                        return;
                dev_info(&dev->dev, "using default PCI settings\n");
                hpp = &pci_default_type0;
@@ -102,7 +102,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
                return;
 
        /* Find PCI Express capability */
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(dev);
        if (!pos)
                return;
 
index 9261327b49f308941c07af292a31bc379b7cb6b9..8d6159426311bda6a5bcab491b282e5427d6eff2 100644 (file)
@@ -1611,7 +1611,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
                        return ret;
                parent = parent->bus->self;
        }
-       if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */
+       if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */
                return domain_context_mapping_one(domain,
                                        pci_domain_nr(tmp->subordinate),
                                        tmp->subordinate->number, 0,
@@ -1651,7 +1651,7 @@ static int domain_context_mapped(struct pci_dev *pdev)
                        return ret;
                parent = parent->bus->self;
        }
-       if (tmp->is_pcie)
+       if (pci_is_pcie(tmp))
                return device_context_mapped(iommu, tmp->subordinate->number,
                                             0);
        else
@@ -1821,7 +1821,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 
        dev_tmp = pci_find_upstream_pcie_bridge(pdev);
        if (dev_tmp) {
-               if (dev_tmp->is_pcie) {
+               if (pci_is_pcie(dev_tmp)) {
                        bus = dev_tmp->subordinate->number;
                        devfn = 0;
                } else {
@@ -2182,7 +2182,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
         * the 1:1 domain, just in _case_ one of their siblings turns out
         * not to be able to map all of memory.
         */
-       if (!pdev->is_pcie) {
+       if (!pci_is_pcie(pdev)) {
                if (!pci_is_root_bus(pdev->bus))
                        return 0;
                if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
@@ -3319,7 +3319,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
                                         parent->devfn);
                        parent = parent->bus->self;
                }
-               if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */
+               if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */
                        iommu_detach_dev(iommu,
                                tmp->subordinate->number, 0);
                else /* this is a legacy PCI bridge */
index 3b3658669bee0c0002d1e108f9b99a3afa84a9bf..1487bf2be863115a9f858b9ed0886945d012dae1 100644 (file)
@@ -520,7 +520,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
                return -1;
 
        /* PCIe device or Root Complex integrated PCI device */
-       if (dev->is_pcie || !dev->bus->parent) {
+       if (pci_is_pcie(dev) || !dev->bus->parent) {
                set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
                             (dev->bus->number << 8) | dev->devfn);
                return 0;
@@ -528,7 +528,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
 
        bridge = pci_find_upstream_pcie_bridge(dev);
        if (bridge) {
-               if (bridge->is_pcie) /* this is a PCIE-to-PCI/PCIX bridge */
+               if (pci_is_pcie(bridge))/* this is a PCIE-to-PCI/PCIX bridge */
                        set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
                                (bridge->bus->number << 8) | dev->bus->number);
                else /* this is a legacy PCI bridge */
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
new file mode 100644 (file)
index 0000000..3e0d7b5
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * IOAPIC/IOxAPIC/IOSAPIC driver
+ *
+ * Copyright (C) 2009 Fujitsu Limited.
+ * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * This driver manages PCI I/O APICs added by hotplug after boot.  We try to
+ * claim all I/O APIC PCI devices, but those present at boot were registered
+ * when we parsed the ACPI MADT, so we'll fail when we try to re-register
+ * them.
+ */
+
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_bus.h>
+
+struct ioapic {
+       acpi_handle     handle;
+       u32             gsi_base;
+};
+
+static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+       acpi_handle handle;
+       acpi_status status;
+       unsigned long long gsb;
+       struct ioapic *ioapic;
+       u64 addr;
+       int ret;
+       char *type;
+
+       handle = DEVICE_ACPI_HANDLE(&dev->dev);
+       if (!handle)
+               return -EINVAL;
+
+       status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
+       if (ACPI_FAILURE(status))
+               return -EINVAL;
+
+       /*
+        * The previous code in acpiphp evaluated _MAT if _GSB failed, but
+        * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
+        */
+
+       ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
+       if (!ioapic)
+               return -ENOMEM;
+
+       ioapic->handle = handle;
+       ioapic->gsi_base = (u32) gsb;
+
+       if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
+               type = "IOAPIC";
+       else
+               type = "IOxAPIC";
+
+       ret = pci_enable_device(dev);
+       if (ret < 0)
+               goto exit_free;
+
+       pci_set_master(dev);
+
+       if (pci_request_region(dev, 0, type))
+               goto exit_disable;
+
+       addr = pci_resource_start(dev, 0);
+       if (acpi_register_ioapic(ioapic->handle, addr, ioapic->gsi_base))
+               goto exit_release;
+
+       pci_set_drvdata(dev, ioapic);
+       dev_info(&dev->dev, "%s at %#llx, GSI %u\n", type, addr,
+                ioapic->gsi_base);
+       return 0;
+
+exit_release:
+       pci_release_region(dev, 0);
+exit_disable:
+       pci_disable_device(dev);
+exit_free:
+       kfree(ioapic);
+       return -ENODEV;
+}
+
+static void ioapic_remove(struct pci_dev *dev)
+{
+       struct ioapic *ioapic = pci_get_drvdata(dev);
+
+       acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
+       pci_release_region(dev, 0);
+       pci_disable_device(dev);
+       kfree(ioapic);
+}
+
+
+static struct pci_device_id ioapic_devices[] = {
+       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_CLASS_SYSTEM_PIC_IOAPIC << 8, 0xffff00, },
+       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_CLASS_SYSTEM_PIC_IOXAPIC << 8, 0xffff00, },
+       { }
+};
+
+static struct pci_driver ioapic_driver = {
+       .name           = "ioapic",
+       .id_table       = ioapic_devices,
+       .probe          = ioapic_probe,
+       .remove         = __devexit_p(ioapic_remove),
+};
+
+static int __init ioapic_init(void)
+{
+       return pci_register_driver(&ioapic_driver);
+}
+
+static void __exit ioapic_exit(void)
+{
+       pci_unregister_driver(&ioapic_driver);
+}
+
+module_init(ioapic_init);
+module_exit(ioapic_exit);
index e03fe98f06193c1c6a1fa22cbf6db92a0dbd2c6a..b2a448e19fe66e0dc6c90693b6fbd8a7c85a6e4b 100644 (file)
@@ -555,7 +555,7 @@ int pci_iov_init(struct pci_dev *dev)
 {
        int pos;
 
-       if (!dev->is_pcie)
+       if (!pci_is_pcie(dev))
                return -ENODEV;
 
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
index 33317df47699d0a69f18b6970583fb23b246f7f9..cc617ddd33d03ce8c16717249ad7413fdd0a0e3e 100644 (file)
@@ -116,7 +116,7 @@ static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable)
                int ret;
 
                ret = acpi_pm_device_sleep_wake(&bridge->dev, enable);
-               if (!ret || bridge->is_pcie)
+               if (!ret || pci_is_pcie(bridge))
                        return;
                bus = bus->parent;
        }
@@ -131,7 +131,7 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable)
        if (acpi_pci_can_wakeup(dev))
                return acpi_pm_device_sleep_wake(&dev->dev, enable);
 
-       if (!dev->is_pcie)
+       if (!pci_is_pcie(dev))
                acpi_pci_propagate_wakeup_enable(dev->bus, enable);
 
        return 0;
index 0f6382f090ee575f04add353066be31abbb05336..c5df94e866787bb63bf344197edd14a08d7a1398 100644 (file)
@@ -74,7 +74,11 @@ static ssize_t local_cpus_show(struct device *dev,
        const struct cpumask *mask;
        int len;
 
+#ifdef CONFIG_NUMA
+       mask = cpumask_of_node(dev_to_node(dev));
+#else
        mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
+#endif
        len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
        buf[len++] = '\n';
        buf[len] = '\0';
@@ -88,7 +92,11 @@ static ssize_t local_cpulist_show(struct device *dev,
        const struct cpumask *mask;
        int len;
 
+#ifdef CONFIG_NUMA
+       mask = cpumask_of_node(dev_to_node(dev));
+#else
        mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
+#endif
        len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask);
        buf[len++] = '\n';
        buf[len] = '\0';
@@ -175,6 +183,21 @@ numa_node_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 #endif
 
+static ssize_t
+dma_mask_bits_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return sprintf (buf, "%d\n", fls64(pdev->dma_mask));
+}
+
+static ssize_t
+consistent_dma_mask_bits_show(struct device *dev, struct device_attribute *attr,
+                                char *buf)
+{
+       return sprintf (buf, "%d\n", fls64(dev->coherent_dma_mask));
+}
+
 static ssize_t
 msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -306,6 +329,8 @@ struct device_attribute pci_dev_attrs[] = {
 #ifdef CONFIG_NUMA
        __ATTR_RO(numa_node),
 #endif
+       __ATTR_RO(dma_mask_bits),
+       __ATTR_RO(consistent_dma_mask_bits),
        __ATTR(enable, 0600, is_enabled_show, is_enabled_store),
        __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
                broken_parity_status_show,broken_parity_status_store),
index 4e4c295a049f7bfba524f24efe8379530e3dc906..0bc27e0590196484b7733c1e0dbb049e4571cda5 100644 (file)
@@ -47,6 +47,15 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
 unsigned long pci_hotplug_io_size  = DEFAULT_HOTPLUG_IO_SIZE;
 unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
 
+/*
+ * The default CLS is used if arch didn't set CLS explicitly and not
+ * all pci devices agree on the same value.  Arch can override either
+ * the dfl or actual value as it sees fit.  Don't forget this is
+ * measured in 32-bit words, not bytes.
+ */
+u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2;
+u8 pci_cache_line_size;
+
 /**
  * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
  * @bus: pointer to PCI bus structure to search
@@ -373,8 +382,12 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
                        continue;       /* Wrong type */
                if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH))
                        return r;       /* Exact match */
-               if ((res->flags & IORESOURCE_PREFETCH) && !(r->flags & IORESOURCE_PREFETCH))
-                       best = r;       /* Approximating prefetchable by non-prefetchable */
+               /* 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;
        }
        return best;
 }
@@ -728,8 +741,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        u16 *cap;
        u16 flags;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-       if (pos <= 0)
+       pos = pci_pcie_cap(dev);
+       if (!pos)
                return 0;
 
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
@@ -837,7 +850,7 @@ pci_save_state(struct pci_dev *dev)
        int i;
        /* XXX: 100% dword access ok here? */
        for (i = 0; i < 16; i++)
-               pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
+               pci_read_config_dword(dev, i * 4, &dev->saved_config_space[i]);
        dev->state_saved = true;
        if ((i = pci_save_pcie_state(dev)) != 0)
                return i;
@@ -1202,7 +1215,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
 
        pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
 
-       dev_printk(KERN_INFO, &dev->dev, "PME# %s\n",
+       dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n",
                        enable ? "enabled" : "disabled");
 }
 
@@ -1413,7 +1426,8 @@ void pci_pm_init(struct pci_dev *dev)
 
        pmc &= PCI_PM_CAP_PME_MASK;
        if (pmc) {
-               dev_info(&dev->dev, "PME# supported from%s%s%s%s%s\n",
+               dev_printk(KERN_DEBUG, &dev->dev,
+                        "PME# supported from%s%s%s%s%s\n",
                         (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
                         (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
                         (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
@@ -1510,7 +1524,7 @@ void pci_enable_ari(struct pci_dev *dev)
        u16 ctrl;
        struct pci_dev *bridge;
 
-       if (!dev->is_pcie || dev->devfn)
+       if (!pci_is_pcie(dev) || dev->devfn)
                return;
 
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
@@ -1518,10 +1532,10 @@ void pci_enable_ari(struct pci_dev *dev)
                return;
 
        bridge = dev->bus->self;
-       if (!bridge || !bridge->is_pcie)
+       if (!bridge || !pci_is_pcie(bridge))
                return;
 
-       pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(bridge);
        if (!pos)
                return;
 
@@ -1536,6 +1550,54 @@ void pci_enable_ari(struct pci_dev *dev)
        bridge->ari_enabled = 1;
 }
 
+static int pci_acs_enable;
+
+/**
+ * pci_request_acs - ask for ACS to be enabled if supported
+ */
+void pci_request_acs(void)
+{
+       pci_acs_enable = 1;
+}
+
+/**
+ * pci_enable_acs - enable ACS if hardware support it
+ * @dev: the PCI device
+ */
+void pci_enable_acs(struct pci_dev *dev)
+{
+       int pos;
+       u16 cap;
+       u16 ctrl;
+
+       if (!pci_acs_enable)
+               return;
+
+       if (!pci_is_pcie(dev))
+               return;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
+       if (!pos)
+               return;
+
+       pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
+       pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
+
+       /* Source Validation */
+       ctrl |= (cap & PCI_ACS_SV);
+
+       /* P2P Request Redirect */
+       ctrl |= (cap & PCI_ACS_RR);
+
+       /* P2P Completion Redirect */
+       ctrl |= (cap & PCI_ACS_CR);
+
+       /* Upstream Forwarding */
+       ctrl |= (cap & PCI_ACS_UF);
+
+       pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+}
+
 /**
  * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
  * @dev: the PCI device
@@ -1669,9 +1731,7 @@ static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_n
        return 0;
 
 err_out:
-       dev_warn(&pdev->dev, "BAR %d: can't reserve %s region %pR\n",
-                bar,
-                pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem",
+       dev_warn(&pdev->dev, "BAR %d: can't reserve %pR\n", bar,
                 &pdev->resource[bar]);
        return -EBUSY;
 }
@@ -1866,31 +1926,6 @@ void pci_clear_master(struct pci_dev *dev)
        __pci_set_master(dev, false);
 }
 
-#ifdef PCI_DISABLE_MWI
-int pci_set_mwi(struct pci_dev *dev)
-{
-       return 0;
-}
-
-int pci_try_set_mwi(struct pci_dev *dev)
-{
-       return 0;
-}
-
-void pci_clear_mwi(struct pci_dev *dev)
-{
-}
-
-#else
-
-#ifndef PCI_CACHE_LINE_BYTES
-#define PCI_CACHE_LINE_BYTES L1_CACHE_BYTES
-#endif
-
-/* This can be overridden by arch code. */
-/* Don't forget this is measured in 32-bit words, not bytes */
-u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4;
-
 /**
  * pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed
  * @dev: the PCI device for which MWI is to be enabled
@@ -1901,13 +1936,12 @@ u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4;
  *
  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
  */
-static int
-pci_set_cacheline_size(struct pci_dev *dev)
+int pci_set_cacheline_size(struct pci_dev *dev)
 {
        u8 cacheline_size;
 
        if (!pci_cache_line_size)
-               return -EINVAL;         /* The system doesn't support MWI. */
+               return -EINVAL;
 
        /* Validate current setting: the PCI_CACHE_LINE_SIZE must be
           equal to or multiple of the right value. */
@@ -1928,6 +1962,24 @@ pci_set_cacheline_size(struct pci_dev *dev)
 
        return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(pci_set_cacheline_size);
+
+#ifdef PCI_DISABLE_MWI
+int pci_set_mwi(struct pci_dev *dev)
+{
+       return 0;
+}
+
+int pci_try_set_mwi(struct pci_dev *dev)
+{
+       return 0;
+}
+
+void pci_clear_mwi(struct pci_dev *dev)
+{
+}
+
+#else
 
 /**
  * pci_set_mwi - enables memory-write-invalidate PCI transaction
@@ -2062,6 +2114,7 @@ pci_set_dma_mask(struct pci_dev *dev, u64 mask)
                return -EIO;
 
        dev->dma_mask = mask;
+       dev_dbg(&dev->dev, "using %dbit DMA mask\n", fls64(mask));
 
        return 0;
 }
@@ -2073,6 +2126,7 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
                return -EIO;
 
        dev->dev.coherent_dma_mask = mask;
+       dev_dbg(&dev->dev, "using %dbit consistent DMA mask\n", fls64(mask));
 
        return 0;
 }
@@ -2099,9 +2153,9 @@ static int pcie_flr(struct pci_dev *dev, int probe)
        int i;
        int pos;
        u32 cap;
-       u16 status;
+       u16 status, control;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(dev);
        if (!pos)
                return -ENOTTY;
 
@@ -2126,8 +2180,10 @@ static int pcie_flr(struct pci_dev *dev, int probe)
                        "proceeding with reset anyway\n");
 
 clear:
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
-                               PCI_EXP_DEVCTL_BCR_FLR);
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &control);
+       control |= PCI_EXP_DEVCTL_BCR_FLR;
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, control);
+
        msleep(100);
 
        return 0;
@@ -2450,7 +2506,7 @@ int pcie_get_readrq(struct pci_dev *dev)
        int ret, cap;
        u16 ctl;
 
-       cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       cap = pci_pcie_cap(dev);
        if (!cap)
                return -EINVAL;
 
@@ -2480,7 +2536,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
 
        v = (ffs(rq) - 8) << 12;
 
-       cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       cap = pci_pcie_cap(dev);
        if (!cap)
                goto out;
 
@@ -2540,7 +2596,7 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
                        return reg;
        }
 
-       dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno);
+       dev_err(&dev->dev, "BAR %d: invalid resource\n", resno);
        return 0;
 }
 
@@ -2590,7 +2646,7 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,
 
 #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
 static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
-spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(resource_alignment_lock);
 
 /**
  * pci_specified_resource_alignment - get resource alignment specified by user.
index d92d1954a2fb17ea0415772531ee27563ec02da3..33ed8e0aba1ea25b54c928691e1a03c78b1391f8 100644 (file)
@@ -311,4 +311,6 @@ static inline int pci_resource_alignment(struct pci_dev *dev,
        return resource_alignment(res);
 }
 
+extern void pci_enable_acs(struct pci_dev *dev);
+
 #endif /* DRIVERS_PCI_H */
index 62d15f652bb6530f72605eea0cd3b964fd02a3f8..7fcd5331b14c37fdbbe4662e80afdf393191dcb8 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/pci.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
+#include <linux/stddef.h>
 #include "aerdrv.h"
 
 struct aer_error_inj {
@@ -35,10 +36,12 @@ struct aer_error_inj {
        u32 header_log1;
        u32 header_log2;
        u32 header_log3;
+       u16 domain;
 };
 
 struct aer_error {
        struct list_head list;
+       u16 domain;
        unsigned int bus;
        unsigned int devfn;
        int pos_cap_err;
@@ -66,22 +69,27 @@ static LIST_HEAD(pci_bus_ops_list);
 /* Protect einjected and pci_bus_ops_list */
 static DEFINE_SPINLOCK(inject_lock);
 
-static void aer_error_init(struct aer_error *err, unsigned int bus,
-                          unsigned int devfn, int pos_cap_err)
+static void aer_error_init(struct aer_error *err, u16 domain,
+                          unsigned int bus, unsigned int devfn,
+                          int pos_cap_err)
 {
        INIT_LIST_HEAD(&err->list);
+       err->domain = domain;
        err->bus = bus;
        err->devfn = devfn;
        err->pos_cap_err = pos_cap_err;
 }
 
 /* inject_lock must be held before calling */
-static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn)
+static struct aer_error *__find_aer_error(u16 domain, unsigned int bus,
+                                         unsigned int devfn)
 {
        struct aer_error *err;
 
        list_for_each_entry(err, &einjected, list) {
-               if (bus == err->bus && devfn == err->devfn)
+               if (domain == err->domain &&
+                   bus == err->bus &&
+                   devfn == err->devfn)
                        return err;
        }
        return NULL;
@@ -90,7 +98,10 @@ static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn)
 /* inject_lock must be held before calling */
 static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev)
 {
-       return __find_aer_error(dev->bus->number, dev->devfn);
+       int domain = pci_domain_nr(dev->bus);
+       if (domain < 0)
+               return NULL;
+       return __find_aer_error((u16)domain, dev->bus->number, dev->devfn);
 }
 
 /* inject_lock must be held before calling */
@@ -172,11 +183,15 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
        struct aer_error *err;
        unsigned long flags;
        struct pci_ops *ops;
+       int domain;
 
        spin_lock_irqsave(&inject_lock, flags);
        if (size != sizeof(u32))
                goto out;
-       err = __find_aer_error(bus->number, devfn);
+       domain = pci_domain_nr(bus);
+       if (domain < 0)
+               goto out;
+       err = __find_aer_error((u16)domain, bus->number, devfn);
        if (!err)
                goto out;
 
@@ -200,11 +215,15 @@ int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size,
        unsigned long flags;
        int rw1cs;
        struct pci_ops *ops;
+       int domain;
 
        spin_lock_irqsave(&inject_lock, flags);
        if (size != sizeof(u32))
                goto out;
-       err = __find_aer_error(bus->number, devfn);
+       domain = pci_domain_nr(bus);
+       if (domain < 0)
+               goto out;
+       err = __find_aer_error((u16)domain, bus->number, devfn);
        if (!err)
                goto out;
 
@@ -262,7 +281,7 @@ out:
 static struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
 {
        while (1) {
-               if (!dev->is_pcie)
+               if (!pci_is_pcie(dev))
                        break;
                if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
                        return dev;
@@ -305,25 +324,25 @@ static int aer_inject(struct aer_error_inj *einj)
        u32 sever;
        int ret = 0;
 
-       dev = pci_get_bus_and_slot(einj->bus, devfn);
+       dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
        if (!dev)
-               return -EINVAL;
+               return -ENODEV;
        rpdev = pcie_find_root_port(dev);
        if (!rpdev) {
-               ret = -EINVAL;
+               ret = -ENOTTY;
                goto out_put;
        }
 
        pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
        if (!pos_cap_err) {
-               ret = -EIO;
+               ret = -ENOTTY;
                goto out_put;
        }
        pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever);
 
        rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
        if (!rp_pos_cap_err) {
-               ret = -EIO;
+               ret = -ENOTTY;
                goto out_put;
        }
 
@@ -344,7 +363,8 @@ static int aer_inject(struct aer_error_inj *einj)
        if (!err) {
                err = err_alloc;
                err_alloc = NULL;
-               aer_error_init(err, einj->bus, devfn, pos_cap_err);
+               aer_error_init(err, einj->domain, einj->bus, devfn,
+                              pos_cap_err);
                list_add(&err->list, &einjected);
        }
        err->uncor_status |= einj->uncor_status;
@@ -358,7 +378,8 @@ static int aer_inject(struct aer_error_inj *einj)
        if (!rperr) {
                rperr = rperr_alloc;
                rperr_alloc = NULL;
-               aer_error_init(rperr, rpdev->bus->number, rpdev->devfn,
+               aer_error_init(rperr, pci_domain_nr(rpdev->bus),
+                              rpdev->bus->number, rpdev->devfn,
                               rp_pos_cap_err);
                list_add(&rperr->list, &einjected);
        }
@@ -411,10 +432,11 @@ static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf,
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
-
-       if (usize != sizeof(struct aer_error_inj))
+       if (usize < offsetof(struct aer_error_inj, domain) ||
+           usize > sizeof(einj))
                return -EINVAL;
 
+       memset(&einj, 0, sizeof(einj));
        if (copy_from_user(&einj, ubuf, usize))
                return -EFAULT;
 
@@ -452,7 +474,7 @@ static void __exit aer_inject_exit(void)
        }
 
        spin_lock_irqsave(&inject_lock, flags);
-       list_for_each_entry_safe(err, err_next, &pci_bus_ops_list, list) {
+       list_for_each_entry_safe(err, err_next, &einjected, list) {
                list_del(&err->list);
                kfree(err);
        }
index 40c3cc5d1caf1f1c74eb0a64cb3096aa700c4ca2..97a345927b55644e1798095d385ff6104abb3499 100644 (file)
@@ -53,7 +53,7 @@ static struct pci_error_handlers aer_error_handlers = {
 
 static struct pcie_port_service_driver aerdriver = {
        .name           = "aer",
-       .port_type      = PCIE_RC_PORT,
+       .port_type      = PCI_EXP_TYPE_ROOT_PORT,
        .service        = PCIE_PORT_SERVICE_AER,
 
        .probe          = aer_probe,
@@ -295,7 +295,7 @@ static void aer_error_resume(struct pci_dev *dev)
        u16 reg16;
 
        /* Clean up Root device status */
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(dev);
        pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
        pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
 
index 9f5ccbeb4fa5fcef281eb2ed3d3a079ae885909e..ae672ca803331f6c70ad12422110b5079a2090c2 100644 (file)
@@ -35,11 +35,14 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev)
        u16 reg16 = 0;
        int pos;
 
+       if (dev->aer_firmware_first)
+               return -EIO;
+
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
        if (!pos)
                return -EIO;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(dev);
        if (!pos)
                return -EIO;
 
@@ -60,7 +63,10 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev)
        u16 reg16 = 0;
        int pos;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (dev->aer_firmware_first)
+               return -EIO;
+
+       pos = pci_pcie_cap(dev);
        if (!pos)
                return -EIO;
 
@@ -78,48 +84,27 @@ EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
 {
        int pos;
-       u32 status, mask;
+       u32 status;
 
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
        if (!pos)
                return -EIO;
 
        pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
-       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
-       if (dev->error_state == pci_channel_io_normal)
-               status &= ~mask; /* Clear corresponding nonfatal bits */
-       else
-               status &= mask; /* Clear corresponding fatal bits */
-       pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+       if (status)
+               pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
 
-#if 0
-int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
-{
-       int pos;
-       u32 status;
-
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
-       if (!pos)
-               return -EIO;
-
-       pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
-       pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
-
-       return 0;
-}
-#endif  /*  0  */
-
 static int set_device_error_reporting(struct pci_dev *dev, void *data)
 {
        bool enable = *((bool *)data);
 
-       if (dev->pcie_type == PCIE_RC_PORT ||
-           dev->pcie_type == PCIE_SW_UPSTREAM_PORT ||
-           dev->pcie_type == PCIE_SW_DOWNSTREAM_PORT) {
+       if ((dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
+           (dev->pcie_type == PCI_EXP_TYPE_UPSTREAM) ||
+           (dev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)) {
                if (enable)
                        pci_enable_pcie_error_reporting(dev);
                else
@@ -218,7 +203,7 @@ static int find_device_iter(struct pci_dev *dev, void *data)
         */
        if (atomic_read(&dev->enable_cnt) == 0)
                return 0;
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(dev);
        if (!pos)
                return 0;
        /* Check if AER is enabled */
@@ -431,10 +416,9 @@ static int find_aer_service_iter(struct device *device, void *data)
        result = (struct find_aer_service_data *) data;
 
        if (device->bus == &pcie_port_bus_type) {
-               struct pcie_port_data *port_data;
+               struct pcie_device *pcie = to_pcie_device(device);
 
-               port_data = pci_get_drvdata(to_pcie_device(device)->port);
-               if (port_data->port_type == PCIE_SW_DOWNSTREAM_PORT)
+               if (pcie->port->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
                        result->is_downstream = 1;
 
                driver = device->driver;
@@ -612,7 +596,7 @@ void aer_enable_rootport(struct aer_rpc *rpc)
        u16 reg16;
        u32 reg32;
 
-       pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(pdev);
        /* Clear PCIE Capability's Device Status */
        pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16);
        pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16);
@@ -874,8 +858,22 @@ void aer_delete_rootport(struct aer_rpc *rpc)
  */
 int aer_init(struct pcie_device *dev)
 {
-       if (aer_osc_setup(dev) && !forceload)
-               return -ENXIO;
+       if (dev->port->aer_firmware_first) {
+               dev_printk(KERN_DEBUG, &dev->device,
+                          "PCIe errors handled by platform firmware.\n");
+               goto out;
+       }
+
+       if (aer_osc_setup(dev))
+               goto out;
 
        return 0;
+out:
+       if (forceload) {
+               dev_printk(KERN_DEBUG, &dev->device,
+                          "aerdrv forceload requested.\n");
+               dev->port->aer_firmware_first = 0;
+               return 0;
+       }
+       return -ENXIO;
 }
index a928d8ab6bda2a95f3fce746617778c53163585d..a2747a663bc9bf9dc8dfa34ca1efc1f922701ef5 100644 (file)
@@ -51,7 +51,7 @@ static int enable_ecrc_checking(struct pci_dev *dev)
        int pos;
        u32 reg32;
 
-       if (!dev->is_pcie)
+       if (!pci_is_pcie(dev))
                return -ENODEV;
 
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
@@ -79,7 +79,7 @@ static int disable_ecrc_checking(struct pci_dev *dev)
        int pos;
        u32 reg32;
 
-       if (!dev->is_pcie)
+       if (!pci_is_pcie(dev))
                return -ENODEV;
 
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
index 5b7056cec00c4ebcc74e0de01de421477dc27fad..5a01fc7fbf056371e6a1e90c874060cec486c221 100644 (file)
@@ -122,7 +122,7 @@ static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
        struct pci_bus *linkbus = link->pdev->subordinate;
 
        list_for_each_entry(child, &linkbus->devices, bus_list) {
-               pos = pci_find_capability(child, PCI_CAP_ID_EXP);
+               pos = pci_pcie_cap(child);
                if (!pos)
                        return;
                pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
@@ -156,7 +156,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
 
        /* All functions should have the same cap and state, take the worst */
        list_for_each_entry(child, &linkbus->devices, bus_list) {
-               pos = pci_find_capability(child, PCI_CAP_ID_EXP);
+               pos = pci_pcie_cap(child);
                if (!pos)
                        return;
                pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, &reg32);
@@ -191,23 +191,23 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
         * Configuration, so just check one function
         */
        child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
-       BUG_ON(!child->is_pcie);
+       BUG_ON(!pci_is_pcie(child));
 
        /* Check downstream component if bit Slot Clock Configuration is 1 */
-       cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
+       cpos = pci_pcie_cap(child);
        pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, &reg16);
        if (!(reg16 & PCI_EXP_LNKSTA_SLC))
                same_clock = 0;
 
        /* Check upstream component if bit Slot Clock Configuration is 1 */
-       ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
+       ppos = pci_pcie_cap(parent);
        pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
        if (!(reg16 & PCI_EXP_LNKSTA_SLC))
                same_clock = 0;
 
        /* Configure downstream component, all functions */
        list_for_each_entry(child, &linkbus->devices, bus_list) {
-               cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
+               cpos = pci_pcie_cap(child);
                pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, &reg16);
                child_reg[PCI_FUNC(child->devfn)] = reg16;
                if (same_clock)
@@ -247,7 +247,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
        dev_printk(KERN_ERR, &parent->dev,
                   "ASPM: Could not configure common clock\n");
        list_for_each_entry(child, &linkbus->devices, bus_list) {
-               cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
+               cpos = pci_pcie_cap(child);
                pci_write_config_word(child, cpos + PCI_EXP_LNKCTL,
                                      child_reg[PCI_FUNC(child->devfn)]);
        }
@@ -300,7 +300,7 @@ static void pcie_get_aspm_reg(struct pci_dev *pdev,
        u16 reg16;
        u32 reg32;
 
-       pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(pdev);
        pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
        info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
        info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
@@ -420,7 +420,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
                    child->pcie_type != PCI_EXP_TYPE_LEG_END)
                        continue;
 
-               pos = pci_find_capability(child, PCI_CAP_ID_EXP);
+               pos = pci_pcie_cap(child);
                pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32);
                /* Calculate endpoint L0s acceptable latency */
                encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
@@ -436,7 +436,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
 {
        u16 reg16;
-       int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       int pos = pci_pcie_cap(pdev);
 
        pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
        reg16 &= ~0x3;
@@ -503,7 +503,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
         * very strange. Disable ASPM for the whole slot
         */
        list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
-               pos = pci_find_capability(child, PCI_CAP_ID_EXP);
+               pos = pci_pcie_cap(child);
                if (!pos)
                        return -EINVAL;
                /*
@@ -563,7 +563,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
        struct pcie_link_state *link;
        int blacklist = !!pcie_aspm_sanity_check(pdev);
 
-       if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
+       if (aspm_disabled || !pci_is_pcie(pdev) || pdev->link_state)
                return;
        if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
            pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
@@ -629,7 +629,8 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
        struct pci_dev *parent = pdev->bus->self;
        struct pcie_link_state *link, *root, *parent_link;
 
-       if (aspm_disabled || !pdev->is_pcie || !parent || !parent->link_state)
+       if (aspm_disabled || !pci_is_pcie(pdev) ||
+           !parent || !parent->link_state)
                return;
        if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
            (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
@@ -670,7 +671,7 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev)
 {
        struct pcie_link_state *link = pdev->link_state;
 
-       if (aspm_disabled || !pdev->is_pcie || !link)
+       if (aspm_disabled || !pci_is_pcie(pdev) || !link)
                return;
        if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
            (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
@@ -696,7 +697,7 @@ void pci_disable_link_state(struct pci_dev *pdev, int state)
        struct pci_dev *parent = pdev->bus->self;
        struct pcie_link_state *link;
 
-       if (aspm_disabled || !pdev->is_pcie)
+       if (aspm_disabled || !pci_is_pcie(pdev))
                return;
        if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
            pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
@@ -841,8 +842,9 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
 {
        struct pcie_link_state *link_state = pdev->link_state;
 
-       if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-               pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
+       if (!pci_is_pcie(pdev) ||
+           (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+            pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
                return;
 
        if (link_state->aspm_support)
@@ -857,8 +859,9 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
 {
        struct pcie_link_state *link_state = pdev->link_state;
 
-       if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-               pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
+       if (!pci_is_pcie(pdev) ||
+           (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+            pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
                return;
 
        if (link_state->aspm_support)
index 17ad53868f9f1566b0628061a4359cb15d1ae472..aaeb9d21cba5eab65b02aa1696a177e29def6d63 100644 (file)
 
 #include <linux/compiler.h>
 
-#if !defined(PCI_CAP_ID_PME)
-#define PCI_CAP_ID_PME                 1
-#endif
-
-#if !defined(PCI_CAP_ID_EXP)
-#define PCI_CAP_ID_EXP                 0x10
-#endif
-
-#define PORT_TYPE_MASK                 0xf
-#define PORT_TO_SLOT_MASK              0x100
-#define SLOT_HP_CAPABLE_MASK           0x40
-#define PCIE_CAPABILITIES_REG          0x2
-#define PCIE_SLOT_CAPABILITIES_REG     0x14
-#define PCIE_PORT_DEVICE_MAXSERVICES   4
-#define PCIE_PORT_MSI_VECTOR_MASK      0x1f
+#define PCIE_PORT_DEVICE_MAXSERVICES   4
 /*
- * According to the PCI Express Base Specification 2.0, the indices of the MSI-X
- * table entires used by port services must not exceed 31
+ * According to the PCI Express Base Specification 2.0, the indices of
+ * the MSI-X table entires used by port services must not exceed 31
  */
 #define PCIE_PORT_MAX_MSIX_ENTRIES     32
 
 #define get_descriptor_id(type, service) (((type - 4) << 4) | service)
 
 extern struct bus_type pcie_port_bus_type;
-extern int pcie_port_device_probe(struct pci_dev *dev);
 extern int pcie_port_device_register(struct pci_dev *dev);
 #ifdef CONFIG_PM
 extern int pcie_port_device_suspend(struct device *dev);
index ef3a4eeaebb45077005f4948b458e3b241ba1f38..18bf90f748f6346753e92a8e47dca991966f02b4 100644 (file)
@@ -26,7 +26,6 @@ EXPORT_SYMBOL_GPL(pcie_port_bus_type);
 static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
 {
        struct pcie_device *pciedev;
-       struct pcie_port_data *port_data;
        struct pcie_port_service_driver *driver;
 
        if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type)
@@ -38,10 +37,8 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
        if (driver->service != pciedev->service)
                return 0;
 
-       port_data = pci_get_drvdata(pciedev->port);
-
-       if (driver->port_type != PCIE_ANY_PORT
-            && driver->port_type != port_data->port_type)
+       if ((driver->port_type != PCIE_ANY_PORT) &&
+           (driver->port_type != pciedev->port->pcie_type))
                return 0;
 
        return 1;
index 52f84fca9f7d4ded61c797b58323b23f6cc6bb90..413262eb95b7607be682ac374bbcd7f9e00fc682 100644 (file)
@@ -108,9 +108,9 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
                 * the value in this field indicates which MSI-X Table entry is
                 * used to generate the interrupt message."
                 */
-               pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-               pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg16);
-               entry = (reg16 >> 9) & PCIE_PORT_MSI_VECTOR_MASK;
+               pos = pci_pcie_cap(dev);
+               pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
+               entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
                if (entry >= nr_entries)
                        goto Error;
 
@@ -177,37 +177,40 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
 }
 
 /**
- * assign_interrupt_mode - choose interrupt mode for PCI Express port services
- *                         (INTx, MSI-X, MSI) and set up vectors
+ * init_service_irqs - initialize irqs for PCI Express port services
  * @dev: PCI Express port to handle
- * @vectors: Array of interrupt vectors to populate
+ * @irqs: Array of irqs to populate
  * @mask: Bitmask of port capabilities returned by get_port_device_capability()
  *
  * Return value: Interrupt mode associated with the port
  */
-static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
+static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
 {
-       int irq, interrupt_mode = PCIE_PORT_NO_IRQ;
-       int i;
+       int i, irq;
 
        /* Try to use MSI-X if supported */
-       if (!pcie_port_enable_msix(dev, vectors, mask))
-               return PCIE_PORT_MSIX_MODE;
-
+       if (!pcie_port_enable_msix(dev, irqs, mask))
+               return 0;
        /* We're not going to use MSI-X, so try MSI and fall back to INTx */
-       if (!pci_enable_msi(dev))
-               interrupt_mode = PCIE_PORT_MSI_MODE;
-
-       if (interrupt_mode == PCIE_PORT_NO_IRQ && dev->pin)
-               interrupt_mode = PCIE_PORT_INTx_MODE;
+       irq = -1;
+       if (!pci_enable_msi(dev) || dev->pin)
+               irq = dev->irq;
 
-       irq = interrupt_mode != PCIE_PORT_NO_IRQ ? dev->irq : -1;
        for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
-               vectors[i] = irq;
+               irqs[i] = irq;
+       irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1;
 
-       vectors[PCIE_PORT_SERVICE_VC_SHIFT] = -1;
+       if (irq < 0)
+               return -ENODEV;
+       return 0;
+}
 
-       return interrupt_mode;
+static void cleanup_service_irqs(struct pci_dev *dev)
+{
+       if (dev->msix_enabled)
+               pci_disable_msix(dev);
+       else if (dev->msi_enabled)
+               pci_disable_msi(dev);
 }
 
 /**
@@ -226,13 +229,12 @@ static int get_port_device_capability(struct pci_dev *dev)
        u16 reg16;
        u32 reg32;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-       pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg16);
+       pos = pci_pcie_cap(dev);
+       pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
        /* Hot-Plug Capable */
-       if (reg16 & PORT_TO_SLOT_MASK) {
-               pci_read_config_dword(dev, 
-                       pos + PCIE_SLOT_CAPABILITIES_REG, &reg32);
-               if (reg32 & SLOT_HP_CAPABLE_MASK)
+       if (reg16 & PCI_EXP_FLAGS_SLOT) {
+               pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, &reg32);
+               if (reg32 & PCI_EXP_SLTCAP_HPC)
                        services |= PCIE_PORT_SERVICE_HP;
        }
        /* AER capable */
@@ -241,80 +243,47 @@ static int get_port_device_capability(struct pci_dev *dev)
        /* VC support */
        if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
                services |= PCIE_PORT_SERVICE_VC;
+       /* Root ports are capable of generating PME too */
+       if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
+               services |= PCIE_PORT_SERVICE_PME;
 
        return services;
 }
 
 /**
- * pcie_device_init - initialize PCI Express port service device
- * @dev: Port service device to initialize
- * @parent: PCI Express port to associate the service device with
- * @port_type: Type of the port
- * @service_type: Type of service to associate with the service device
+ * pcie_device_init - allocate and initialize PCI Express port service device
+ * @pdev: PCI Express port to associate the service device with
+ * @service: Type of service to associate with the service device
  * @irq: Interrupt vector to associate with the service device
  */
-static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, 
-       int service_type, int irq)
+static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
 {
-       struct pcie_port_data *port_data = pci_get_drvdata(parent);
+       int retval;
+       struct pcie_device *pcie;
        struct device *device;
-       int port_type = port_data->port_type;
 
-       dev->port = parent;
-       dev->irq = irq;
-       dev->service = service_type;
+       pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
+       if (!pcie)
+               return -ENOMEM;
+       pcie->port = pdev;
+       pcie->irq = irq;
+       pcie->service = service;
 
        /* Initialize generic device interface */
-       device = &dev->device;
-       memset(device, 0, sizeof(struct device));
+       device = &pcie->device;
        device->bus = &pcie_port_bus_type;
-       device->driver = NULL;
-       dev_set_drvdata(device, NULL);
        device->release = release_pcie_device;  /* callback to free pcie dev */
        dev_set_name(device, "%s:pcie%02x",
-                pci_name(parent), get_descriptor_id(port_type, service_type));
-       device->parent = &parent->dev;
-}
-
-/**
- * alloc_pcie_device - allocate PCI Express port service device structure
- * @parent: PCI Express port to associate the service device with
- * @port_type: Type of the port
- * @service_type: Type of service to associate with the service device
- * @irq: Interrupt vector to associate with the service device
- */
-static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
-       int service_type, int irq)
-{
-       struct pcie_device *device;
-
-       device = kzalloc(sizeof(struct pcie_device), GFP_KERNEL);
-       if (!device)
-               return NULL;
-
-       pcie_device_init(parent, device, service_type, irq);
-       return device;
-}
-
-/**
- * pcie_port_device_probe - check if device is a PCI Express port
- * @dev: Device to check
- */
-int pcie_port_device_probe(struct pci_dev *dev)
-{
-       int pos, type;
-       u16 reg;
-
-       if (!(pos = pci_find_capability(dev, PCI_CAP_ID_EXP)))
-               return -ENODEV;
-
-       pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg);
-       type = (reg >> 4) & PORT_TYPE_MASK;
-       if (    type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT ||
-               type == PCIE_SW_DOWNSTREAM_PORT )
-               return 0;
-
-       return -ENODEV;
+                    pci_name(pdev),
+                    get_descriptor_id(pdev->pcie_type, service));
+       device->parent = &pdev->dev;
+
+       retval = device_register(device);
+       if (retval)
+               kfree(pcie);
+       else
+               get_device(device);
+       return retval;
 }
 
 /**
@@ -326,77 +295,49 @@ int pcie_port_device_probe(struct pci_dev *dev)
  */
 int pcie_port_device_register(struct pci_dev *dev)
 {
-       struct pcie_port_data *port_data;
-       int status, capabilities, irq_mode, i, nr_serv;
-       int vectors[PCIE_PORT_DEVICE_MAXSERVICES];
-       u16 reg16;
-
-       port_data = kzalloc(sizeof(*port_data), GFP_KERNEL);
-       if (!port_data)
-               return -ENOMEM;
-       pci_set_drvdata(dev, port_data);
-
-       /* Get port type */
-       pci_read_config_word(dev,
-               pci_find_capability(dev, PCI_CAP_ID_EXP) +
-               PCIE_CAPABILITIES_REG, &reg16);
-       port_data->port_type = (reg16 >> 4) & PORT_TYPE_MASK;
+       int status, capabilities, i, nr_service;
+       int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
 
+       /* Get and check PCI Express port services */
        capabilities = get_port_device_capability(dev);
-       /* Root ports are capable of generating PME too */
-       if (port_data->port_type == PCIE_RC_PORT)
-               capabilities |= PCIE_PORT_SERVICE_PME;
-
-       irq_mode = assign_interrupt_mode(dev, vectors, capabilities);
-       if (irq_mode == PCIE_PORT_NO_IRQ) {
-               /*
-                * Don't use service devices that require interrupts if there is
-                * no way to generate them.
-                */
-               if (!(capabilities & PCIE_PORT_SERVICE_VC)) {
-                       status = -ENODEV;
-                       goto Error;
-               }
-               capabilities = PCIE_PORT_SERVICE_VC;
-       }
-       port_data->port_irq_mode = irq_mode;
+       if (!capabilities)
+               return -ENODEV;
 
+       /* Enable PCI Express port device */
        status = pci_enable_device(dev);
        if (status)
-               goto Error;
+               return status;
        pci_set_master(dev);
+       /*
+        * Initialize service irqs. Don't use service devices that
+        * require interrupts if there is no way to generate them.
+        */
+       status = init_service_irqs(dev, irqs, capabilities);
+       if (status) {
+               capabilities &= PCIE_PORT_SERVICE_VC;
+               if (!capabilities)
+                       goto error_disable;
+       }
 
        /* Allocate child services if any */
-       for (i = 0, nr_serv = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
-               struct pcie_device *child;
+       status = -ENODEV;
+       nr_service = 0;
+       for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
                int service = 1 << i;
-
                if (!(capabilities & service))
                        continue;
-
-               child = alloc_pcie_device(dev, service, vectors[i]);
-               if (!child)
-                       continue;
-
-               status = device_register(&child->device);
-               if (status) {
-                       kfree(child);
-                       continue;
-               }
-
-               get_device(&child->device);
-               nr_serv++;
-       }
-       if (!nr_serv) {
-               pci_disable_device(dev);
-               status = -ENODEV;
-               goto Error;
+               if (!pcie_device_init(dev, service, irqs[i]))
+                       nr_service++;
        }
+       if (!nr_service)
+               goto error_cleanup_irqs;
 
        return 0;
 
- Error:
-       kfree(port_data);
+error_cleanup_irqs:
+       cleanup_service_irqs(dev);
+error_disable:
+       pci_disable_device(dev);
        return status;
 }
 
@@ -464,21 +405,9 @@ static int remove_iter(struct device *dev, void *data)
  */
 void pcie_port_device_remove(struct pci_dev *dev)
 {
-       struct pcie_port_data *port_data = pci_get_drvdata(dev);
-
        device_for_each_child(&dev->dev, NULL, remove_iter);
+       cleanup_service_irqs(dev);
        pci_disable_device(dev);
-
-       switch (port_data->port_irq_mode) {
-       case PCIE_PORT_MSIX_MODE:
-               pci_disable_msix(dev);
-               break;
-       case PCIE_PORT_MSI_MODE:
-               pci_disable_msi(dev);
-               break;
-       }
-
-       kfree(port_data);
 }
 
 /**
index f635e476d6322d5032082e5697c208c18f3174b7..ce52ea34fee5513822ef903a8b27ab8d38dfb359 100644 (file)
@@ -67,14 +67,16 @@ static struct dev_pm_ops pcie_portdrv_pm_ops = {
  * this port device.
  *
  */
-static int __devinit pcie_portdrv_probe (struct pci_dev *dev, 
-                               const struct pci_device_id *id )
+static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
+                                       const struct pci_device_id *id)
 {
-       int                     status;
+       int status;
 
-       status = pcie_port_device_probe(dev);
-       if (status)
-               return status;
+       if (!pci_is_pcie(dev) ||
+           ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
+            (dev->pcie_type != PCI_EXP_TYPE_UPSTREAM) &&
+            (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
+               return -ENODEV;
 
         if (!dev->irq && dev->pin) {
                dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
index 8105e32117f67d8ce60317fb9a4151b305773434..98ffb2de22e90a3a17984bc75480237178d882b8 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/cpumask.h>
 #include <linux/pci-aspm.h>
+#include <acpi/acpi_hest.h>
 #include "pci.h"
 
 #define CARDBUS_LATENCY_TIMER  176     /* secondary latency timer */
@@ -163,12 +164,12 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
 {
        u32 l, sz, mask;
 
-       mask = type ? ~PCI_ROM_ADDRESS_ENABLE : ~0;
+       mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
 
        res->name = pci_name(dev);
 
        pci_read_config_dword(dev, pos, &l);
-       pci_write_config_dword(dev, pos, mask);
+       pci_write_config_dword(dev, pos, l | mask);
        pci_read_config_dword(dev, pos, &sz);
        pci_write_config_dword(dev, pos, l);
 
@@ -223,9 +224,13 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        goto fail;
 
                if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
-                       dev_err(&dev->dev, "can't handle 64-bit BAR\n");
+                       dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
+                               pos);
                        goto fail;
-               } else if ((sizeof(resource_size_t) < 8) && l) {
+               }
+
+               res->flags |= IORESOURCE_MEM_64;
+               if ((sizeof(resource_size_t) < 8) && l) {
                        /* Address above 32-bit boundary; disable the BAR */
                        pci_write_config_dword(dev, pos, 0);
                        pci_write_config_dword(dev, pos + 4, 0);
@@ -234,14 +239,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                } else {
                        res->start = l64;
                        res->end = l64 + sz64;
-                       dev_printk(KERN_DEBUG, &dev->dev,
-                               "reg %x %s: %pR\n", pos,
-                                (res->flags & IORESOURCE_PREFETCH) ?
-                                       "64bit mmio pref" : "64bit mmio",
-                                res);
+                       dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
+                                  pos, res);
                }
-
-               res->flags |= IORESOURCE_MEM_64;
        } else {
                sz = pci_size(l, sz, mask);
 
@@ -251,11 +251,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                res->start = l;
                res->end = l + sz;
 
-               dev_printk(KERN_DEBUG, &dev->dev, "reg %x %s: %pR\n", pos,
-                       (res->flags & IORESOURCE_IO) ? "io port" :
-                        ((res->flags & IORESOURCE_PREFETCH) ?
-                                "32bit mmio pref" : "32bit mmio"),
-                       res);
+               dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
        }
 
  out:
@@ -297,8 +293,11 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
        if (pci_is_root_bus(child))     /* It's a host bus, nothing to read */
                return;
 
+       dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n",
+                child->secondary, child->subordinate,
+                dev->transparent ? " (subtractive decode)": "");
+
        if (dev->transparent) {
-               dev_info(&dev->dev, "transparent bridge\n");
                for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
                        child->resource[i] = child->parent->resource[i - 3];
        }
@@ -323,7 +322,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
                        res->start = base;
                if (!res->end)
                        res->end = limit + 0xfff;
-               dev_printk(KERN_DEBUG, &dev->dev, "bridge io port: %pR\n", res);
+               dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);
        }
 
        res = child->resource[1];
@@ -335,8 +334,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
                res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
                res->start = base;
                res->end = limit + 0xfffff;
-               dev_printk(KERN_DEBUG, &dev->dev, "bridge 32bit mmio: %pR\n",
-                       res);
+               dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);
        }
 
        res = child->resource[2];
@@ -375,9 +373,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
                        res->flags |= IORESOURCE_MEM_64;
                res->start = base;
                res->end = limit + 0xfffff;
-               dev_printk(KERN_DEBUG, &dev->dev, "bridge %sbit mmio pref: %pR\n",
-                       (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
-                       res);
+               dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);
        }
 }
 
@@ -651,13 +647,14 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
                    (child->number > bus->subordinate) ||
                    (child->number < bus->number) ||
                    (child->subordinate < bus->number)) {
-                       pr_debug("PCI: Bus #%02x (-#%02x) is %s "
-                               "hidden behind%s bridge #%02x (-#%02x)\n",
+                       dev_info(&child->dev, "[bus %02x-%02x] %s "
+                               "hidden behind%s bridge %s [bus %02x-%02x]\n",
                                child->number, child->subordinate,
                                (bus->number > child->subordinate &&
                                 bus->subordinate < child->number) ?
                                        "wholly" : "partially",
                                bus->self->transparent ? " transparent" : "",
+                               dev_name(&bus->dev),
                                bus->number, bus->subordinate);
                }
                bus = bus->parent;
@@ -693,6 +690,7 @@ static void set_pcie_port_type(struct pci_dev *pdev)
        if (!pos)
                return;
        pdev->is_pcie = 1;
+       pdev->pcie_cap = pos;
        pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
        pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4;
 }
@@ -703,7 +701,7 @@ static void set_pcie_hotplug_bridge(struct pci_dev *pdev)
        u16 reg16;
        u32 reg32;
 
-       pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(pdev);
        if (!pos)
                return;
        pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
@@ -714,6 +712,12 @@ static void set_pcie_hotplug_bridge(struct pci_dev *pdev)
                pdev->is_hotplug_bridge = 1;
 }
 
+static void set_pci_aer_firmware_first(struct pci_dev *pdev)
+{
+       if (acpi_hest_firmware_first_pci(pdev))
+               pdev->aer_firmware_first = 1;
+}
+
 #define LEGACY_IO_RESOURCE     (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
 
 /**
@@ -731,6 +735,7 @@ int pci_setup_device(struct pci_dev *dev)
        u32 class;
        u8 hdr_type;
        struct pci_slot *slot;
+       int pos = 0;
 
        if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type))
                return -EIO;
@@ -742,6 +747,7 @@ int pci_setup_device(struct pci_dev *dev)
        dev->multifunction = !!(hdr_type & 0x80);
        dev->error_state = pci_channel_io_normal;
        set_pcie_port_type(dev);
+       set_pci_aer_firmware_first(dev);
 
        list_for_each_entry(slot, &dev->bus->slots, list)
                if (PCI_SLOT(dev->devfn) == slot->number)
@@ -822,6 +828,11 @@ int pci_setup_device(struct pci_dev *dev)
                dev->transparent = ((dev->class & 0xff) == 1);
                pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);
                set_pcie_hotplug_bridge(dev);
+               pos = pci_find_capability(dev, PCI_CAP_ID_SSVID);
+               if (pos) {
+                       pci_read_config_word(dev, pos + PCI_SSVID_VENDOR_ID, &dev->subsystem_vendor);
+                       pci_read_config_word(dev, pos + PCI_SSVID_DEVICE_ID, &dev->subsystem_device);
+               }
                break;
 
        case PCI_HEADER_TYPE_CARDBUS:               /* CardBus bridge header */
@@ -907,7 +918,7 @@ int pci_cfg_space_size(struct pci_dev *dev)
        if (class == PCI_CLASS_BRIDGE_HOST)
                return pci_cfg_space_size_ext(dev);
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       pos = pci_pcie_cap(dev);
        if (!pos) {
                pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
                if (!pos)
@@ -1014,6 +1025,9 @@ static void pci_init_capabilities(struct pci_dev *dev)
 
        /* Single Root I/O Virtualization */
        pci_iov_init(dev);
+
+       /* Enable ACS P2P upstream forwarding */
+       pci_enable_acs(dev);
 }
 
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
@@ -1110,7 +1124,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
        unsigned int devfn, pass, max = bus->secondary;
        struct pci_dev *dev;
 
-       pr_debug("PCI: Scanning bus %04x:%02x\n", pci_domain_nr(bus), bus->number);
+       dev_dbg(&bus->dev, "scanning bus\n");
 
        /* Go find them, Rover! */
        for (devfn = 0; devfn < 0x100; devfn += 8)
@@ -1124,8 +1138,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
         * all PCI-to-PCI bridges on this bus.
         */
        if (!bus->is_added) {
-               pr_debug("PCI: Fixups for bus %04x:%02x\n",
-                        pci_domain_nr(bus), bus->number);
+               dev_dbg(&bus->dev, "fixups for bus\n");
                pcibios_fixup_bus(bus);
                if (pci_is_root_bus(bus))
                        bus->is_added = 1;
@@ -1145,8 +1158,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
         *
         * Return how far we've got finding sub-buses.
         */
-       pr_debug("PCI: Bus scan for %04x:%02x returning with max=%02x\n",
-               pci_domain_nr(bus), bus->number, max);
+       dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max);
        return max;
 }
 
@@ -1154,7 +1166,7 @@ struct pci_bus * pci_create_bus(struct device *parent,
                int bus, struct pci_ops *ops, void *sysdata)
 {
        int error;
-       struct pci_bus *b;
+       struct pci_bus *b, *b2;
        struct device *dev;
 
        b = pci_alloc_bus();
@@ -1170,9 +1182,10 @@ struct pci_bus * pci_create_bus(struct device *parent,
        b->sysdata = sysdata;
        b->ops = ops;
 
-       if (pci_find_bus(pci_domain_nr(b), bus)) {
+       b2 = pci_find_bus(pci_domain_nr(b), bus);
+       if (b2) {
                /* If we already got to this bus through a different bridge, ignore it */
-               pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus);
+               dev_dbg(&b2->dev, "bus already known\n");
                goto err_out;
        }
 
index 245d2cdb47651d4d095edd847417b5251565fc69..7cfa7c38d31869bd482138fa2fc3fcba06d561e7 100644 (file)
@@ -357,7 +357,7 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
                pcibios_bus_to_resource(dev, res, &bus_region);
 
                pci_claim_resource(dev, nr);
-               dev_info(&dev->dev, "quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name);
+               dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name);
        }
 }      
 
@@ -1680,6 +1680,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS,   PCI_DEVICE_ID_SERVERWORKS_
  */
 #define AMD_813X_MISC                  0x40
 #define AMD_813X_NOIOAMODE             (1<<0)
+#define AMD_813X_REV_B1                        0x12
 #define AMD_813X_REV_B2                        0x13
 
 static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
@@ -1688,7 +1689,8 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
 
        if (noioapicquirk)
                return;
-       if (dev->revision == AMD_813X_REV_B2)
+       if ((dev->revision == AMD_813X_REV_B1) ||
+           (dev->revision == AMD_813X_REV_B2))
                return;
 
        pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword);
@@ -1698,8 +1700,10 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
        dev_info(&dev->dev, "disabled boot interrupts on device [%04x:%04x]\n",
                 dev->vendor, dev->device);
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,   PCI_DEVICE_ID_AMD_8131_BRIDGE,    quirk_disable_amd_813x_boot_interrupt);
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD,   PCI_DEVICE_ID_AMD_8132_BRIDGE,   quirk_disable_amd_813x_boot_interrupt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_8131_BRIDGE,  quirk_disable_amd_813x_boot_interrupt);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD,    PCI_DEVICE_ID_AMD_8131_BRIDGE,  quirk_disable_amd_813x_boot_interrupt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_8132_BRIDGE,  quirk_disable_amd_813x_boot_interrupt);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD,    PCI_DEVICE_ID_AMD_8132_BRIDGE,  quirk_disable_amd_813x_boot_interrupt);
 
 #define AMD_8111_PCI_IRQ_ROUTING       0x56
 
@@ -2595,9 +2599,37 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
 static int __init pci_apply_final_quirks(void)
 {
        struct pci_dev *dev = NULL;
+       u8 cls = 0;
+       u8 tmp;
+
+       if (pci_cache_line_size)
+               printk(KERN_DEBUG "PCI: CLS %u bytes\n",
+                      pci_cache_line_size << 2);
 
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
                pci_fixup_device(pci_fixup_final, dev);
+               /*
+                * If arch hasn't set it explicitly yet, use the CLS
+                * value shared by all PCI devices.  If there's a
+                * mismatch, fall back to the default value.
+                */
+               if (!pci_cache_line_size) {
+                       pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp);
+                       if (!cls)
+                               cls = tmp;
+                       if (!tmp || cls == tmp)
+                               continue;
+
+                       printk(KERN_DEBUG "PCI: CLS mismatch (%u != %u), "
+                              "using %u bytes\n", cls << 2, tmp << 2,
+                              pci_dfl_cache_line_size << 2);
+                       pci_cache_line_size = pci_dfl_cache_line_size;
+               }
+       }
+       if (!pci_cache_line_size) {
+               printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n",
+                      cls << 2, pci_dfl_cache_line_size << 2);
+               pci_cache_line_size = cls;
        }
 
        return 0;
index ec415352d9ba5cbf0d5572adfad37618ea88d773..6dae871432588e29f93b86e7a2565856cc36ab99 100644 (file)
@@ -26,14 +26,14 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
 {
        struct pci_dev *tmp = NULL;
 
-       if (pdev->is_pcie)
+       if (pci_is_pcie(pdev))
                return NULL;
        while (1) {
                if (pci_is_root_bus(pdev->bus))
                        break;
                pdev = pdev->bus->self;
                /* a p2p bridge */
-               if (!pdev->is_pcie) {
+               if (!pci_is_pcie(pdev)) {
                        tmp = pdev;
                        continue;
                }
@@ -149,32 +149,33 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
 }
 
 /**
- * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot
- * @bus: number of PCI bus on which desired PCI device resides
- * @devfn: encodes number of PCI slot in which the desired PCI
- * device resides and the logical device number within that slot
- * in case of multi-function devices.
- *
- * Note: the bus/slot search is limited to PCI domain (segment) 0.
+ * pci_get_domain_bus_and_slot - locate PCI device for a given PCI domain (segment), bus, and slot
+ * @domain: PCI domain/segment on which the PCI device resides.
+ * @bus: PCI bus on which desired PCI device resides
+ * @devfn: encodes number of PCI slot in which the desired PCI device
+ * resides and the logical device number within that slot in case of
+ * multi-function devices.
  *
- * Given a PCI bus and slot/function number, the desired PCI device
- * is located in system global list of PCI devices.  If the device
- * is found, a pointer to its data structure is returned.  If no
- * device is found, %NULL is returned. The returned device has its
- * reference count bumped by one.
+ * Given a PCI domain, bus, and slot/function number, the desired PCI
+ * device is located in the list of PCI devices. If the device is
+ * found, its reference count is increased and this function returns a
+ * pointer to its data structure.  The caller must decrement the
+ * reference count by calling pci_dev_put().  If no device is found,
+ * %NULL is returned.
  */
-
-struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
+struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
+                                           unsigned int devfn)
 {
        struct pci_dev *dev = NULL;
 
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               if (pci_domain_nr(dev->bus) == 0 &&
-                  (dev->bus->number == bus && dev->devfn == devfn))
+               if (pci_domain_nr(dev->bus) == domain &&
+                   (dev->bus->number == bus && dev->devfn == devfn))
                        return dev;
        }
        return NULL;
 }
+EXPORT_SYMBOL(pci_get_domain_bus_and_slot);
 
 static int match_pci_dev_by_id(struct device *dev, void *data)
 {
@@ -354,5 +355,4 @@ EXPORT_SYMBOL(pci_find_next_bus);
 EXPORT_SYMBOL(pci_get_device);
 EXPORT_SYMBOL(pci_get_subsys);
 EXPORT_SYMBOL(pci_get_slot);
-EXPORT_SYMBOL(pci_get_bus_and_slot);
 EXPORT_SYMBOL(pci_get_class);
index cb1a027eb552228a08bc53cef27af8e7db34e70e..c48cd377b3f56451731ed72d6953caaea349f8bd 100644 (file)
@@ -71,53 +71,50 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus)
 void pci_setup_cardbus(struct pci_bus *bus)
 {
        struct pci_dev *bridge = bus->self;
+       struct resource *res;
        struct pci_bus_region region;
 
-       dev_info(&bridge->dev, "CardBus bridge, secondary bus %04x:%02x\n",
-                pci_domain_nr(bus), bus->number);
+       dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n",
+                bus->secondary, bus->subordinate);
 
-       pcibios_resource_to_bus(bridge, &region, bus->resource[0]);
-       if (bus->resource[0]->flags & IORESOURCE_IO) {
+       res = bus->resource[0];
+       pcibios_resource_to_bus(bridge, &region, res);
+       if (res->flags & IORESOURCE_IO) {
                /*
                 * The IO resource is allocated a range twice as large as it
                 * would normally need.  This allows us to set both IO regs.
                 */
-               dev_info(&bridge->dev, "  IO window: %#08lx-%#08lx\n",
-                      (unsigned long)region.start,
-                      (unsigned long)region.end);
+               dev_info(&bridge->dev, "  bridge window %pR\n", res);
                pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
                                        region.start);
                pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
                                        region.end);
        }
 
-       pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
-       if (bus->resource[1]->flags & IORESOURCE_IO) {
-               dev_info(&bridge->dev, "  IO window: %#08lx-%#08lx\n",
-                      (unsigned long)region.start,
-                      (unsigned long)region.end);
+       res = bus->resource[1];
+       pcibios_resource_to_bus(bridge, &region, res);
+       if (res->flags & IORESOURCE_IO) {
+               dev_info(&bridge->dev, "  bridge window %pR\n", res);
                pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
                                        region.start);
                pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
                                        region.end);
        }
 
-       pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
-       if (bus->resource[2]->flags & IORESOURCE_MEM) {
-               dev_info(&bridge->dev, "  PREFETCH window: %#08lx-%#08lx\n",
-                      (unsigned long)region.start,
-                      (unsigned long)region.end);
+       res = bus->resource[2];
+       pcibios_resource_to_bus(bridge, &region, res);
+       if (res->flags & IORESOURCE_MEM) {
+               dev_info(&bridge->dev, "  bridge window %pR\n", res);
                pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
                                        region.start);
                pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
                                        region.end);
        }
 
-       pcibios_resource_to_bus(bridge, &region, bus->resource[3]);
-       if (bus->resource[3]->flags & IORESOURCE_MEM) {
-               dev_info(&bridge->dev, "  MEM window: %#08lx-%#08lx\n",
-                      (unsigned long)region.start,
-                      (unsigned long)region.end);
+       res = bus->resource[3];
+       pcibios_resource_to_bus(bridge, &region, res);
+       if (res->flags & IORESOURCE_MEM) {
+               dev_info(&bridge->dev, "  bridge window %pR\n", res);
                pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
                                        region.start);
                pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
@@ -140,34 +137,33 @@ EXPORT_SYMBOL(pci_setup_cardbus);
 static void pci_setup_bridge(struct pci_bus *bus)
 {
        struct pci_dev *bridge = bus->self;
+       struct resource *res;
        struct pci_bus_region region;
        u32 l, bu, lu, io_upper16;
-       int pref_mem64;
 
        if (pci_is_enabled(bridge))
                return;
 
-       dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
-                pci_domain_nr(bus), bus->number);
+       dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
+                bus->secondary, bus->subordinate);
 
        /* Set up the top and bottom of the PCI I/O segment for this bus. */
-       pcibios_resource_to_bus(bridge, &region, bus->resource[0]);
-       if (bus->resource[0]->flags & IORESOURCE_IO) {
+       res = bus->resource[0];
+       pcibios_resource_to_bus(bridge, &region, res);
+       if (res->flags & IORESOURCE_IO) {
                pci_read_config_dword(bridge, PCI_IO_BASE, &l);
                l &= 0xffff0000;
                l |= (region.start >> 8) & 0x00f0;
                l |= region.end & 0xf000;
                /* Set up upper 16 bits of I/O base/limit. */
                io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
-               dev_info(&bridge->dev, "  IO window: %#04lx-%#04lx\n",
-                   (unsigned long)region.start,
-                   (unsigned long)region.end);
+               dev_info(&bridge->dev, "  bridge window %pR\n", res);
        }
        else {
                /* Clear upper 16 bits of I/O base/limit. */
                io_upper16 = 0;
                l = 0x00f0;
-               dev_info(&bridge->dev, "  IO window: disabled\n");
+               dev_info(&bridge->dev, "  bridge window [io  disabled]\n");
        }
        /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
@@ -178,17 +174,16 @@ static void pci_setup_bridge(struct pci_bus *bus)
 
        /* Set up the top and bottom of the PCI Memory segment
           for this bus. */
-       pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
-       if (bus->resource[1]->flags & IORESOURCE_MEM) {
+       res = bus->resource[1];
+       pcibios_resource_to_bus(bridge, &region, res);
+       if (res->flags & IORESOURCE_MEM) {
                l = (region.start >> 16) & 0xfff0;
                l |= region.end & 0xfff00000;
-               dev_info(&bridge->dev, "  MEM window: %#08lx-%#08lx\n",
-                   (unsigned long)region.start,
-                   (unsigned long)region.end);
+               dev_info(&bridge->dev, "  bridge window %pR\n", res);
        }
        else {
                l = 0x0000fff0;
-               dev_info(&bridge->dev, "  MEM window: disabled\n");
+               dev_info(&bridge->dev, "  bridge window [mem disabled]\n");
        }
        pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
 
@@ -198,34 +193,27 @@ static void pci_setup_bridge(struct pci_bus *bus)
        pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
 
        /* Set up PREF base/limit. */
-       pref_mem64 = 0;
        bu = lu = 0;
-       pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
-       if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
-               int width = 8;
+       res = bus->resource[2];
+       pcibios_resource_to_bus(bridge, &region, res);
+       if (res->flags & IORESOURCE_PREFETCH) {
                l = (region.start >> 16) & 0xfff0;
                l |= region.end & 0xfff00000;
-               if (bus->resource[2]->flags & IORESOURCE_MEM_64) {
-                       pref_mem64 = 1;
+               if (res->flags & IORESOURCE_MEM_64) {
                        bu = upper_32_bits(region.start);
                        lu = upper_32_bits(region.end);
-                       width = 16;
                }
-               dev_info(&bridge->dev, "  PREFETCH window: %#0*llx-%#0*llx\n",
-                               width, (unsigned long long)region.start,
-                               width, (unsigned long long)region.end);
+               dev_info(&bridge->dev, "  bridge window %pR\n", res);
        }
        else {
                l = 0x0000fff0;
-               dev_info(&bridge->dev, "  PREFETCH window: disabled\n");
+               dev_info(&bridge->dev, "  bridge window [mem pref disabled]\n");
        }
        pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
 
-       if (pref_mem64) {
-               /* Set the upper 32 bits of PREF base & limit. */
-               pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
-               pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
-       }
+       /* Set the upper 32 bits of PREF base & limit. */
+       pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
+       pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
 
        pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
 }
@@ -345,6 +333,10 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
 #endif
        size = ALIGN(size + size1, 4096);
        if (!size) {
+               if (b_res->start || b_res->end)
+                       dev_info(&bus->self->dev, "disabling bridge window "
+                                "%pR to [bus %02x-%02x] (unused)\n", b_res,
+                                bus->secondary, bus->subordinate);
                b_res->flags = 0;
                return;
        }
@@ -390,8 +382,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                        align = pci_resource_alignment(dev, r);
                        order = __ffs(align) - 20;
                        if (order > 11) {
-                               dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
-                                        "%pR\n", i, (unsigned long long)align, r);
+                               dev_warn(&dev->dev, "disabling BAR %d: %pR "
+                                        "(bad alignment %#llx)\n", i, r,
+                                        (unsigned long long) align);
                                r->flags = 0;
                                continue;
                        }
@@ -425,6 +418,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
        }
        size = ALIGN(size, min_align);
        if (!size) {
+               if (b_res->start || b_res->end)
+                       dev_info(&bus->self->dev, "disabling bridge window "
+                                "%pR to [bus %02x-%02x] (unused)\n", b_res,
+                                bus->secondary, bus->subordinate);
                b_res->flags = 0;
                return 1;
        }
@@ -582,10 +579,7 @@ static void pci_bus_dump_res(struct pci_bus *bus)
                 if (!res || !res->end)
                         continue;
 
-               dev_printk(KERN_DEBUG, &bus->dev, "resource %d %s %pR\n", i,
-                          (res->flags & IORESOURCE_IO) ? "io: " :
-                           ((res->flags & IORESOURCE_PREFETCH)? "pref mem":"mem:"),
-                          res);
+               dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res);
         }
 }
 
index c54526b206b5da957d78170a6e430ce5c3b9f95b..7d678bb15ffb30daed8bebf18d1ef5642a30a13b 100644 (file)
@@ -51,12 +51,6 @@ void pci_update_resource(struct pci_dev *dev, int resno)
 
        pcibios_resource_to_bus(dev, &region, res);
 
-       dev_dbg(&dev->dev, "BAR %d: got res %pR bus [%#llx-%#llx] "
-               "flags %#lx\n", resno, res,
-                (unsigned long long)region.start,
-                (unsigned long long)region.end,
-                (unsigned long)res->flags);
-
        new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
        if (res->flags & IORESOURCE_IO)
                mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
@@ -91,9 +85,9 @@ void pci_update_resource(struct pci_dev *dev, int resno)
                }
        }
        res->flags &= ~IORESOURCE_UNSET;
-       dev_dbg(&dev->dev, "BAR %d: moved to bus [%#llx-%#llx] flags %#lx\n",
-               resno, (unsigned long long)region.start,
-               (unsigned long long)region.end, res->flags);
+       dev_info(&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)
@@ -103,20 +97,17 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
        int err;
 
        root = pci_find_parent_resource(dev, res);
-
-       err = -EINVAL;
-       if (root != NULL)
-               err = request_resource(root, res);
-
-       if (err) {
-               const char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
-               dev_err(&dev->dev, "BAR %d: %s of %s %pR\n",
-                       resource,
-                       root ? "address space collision on" :
-                               "no parent found for",
-                       dtype, res);
+       if (!root) {
+               dev_err(&dev->dev, "no compatible bridge window for %pR\n",
+                       res);
+               return -EINVAL;
        }
 
+       err = request_resource(root, res);
+       if (err)
+               dev_err(&dev->dev,
+                       "address space collision: %pR already in use\n", res);
+
        return err;
 }
 EXPORT_SYMBOL(pci_claim_resource);
@@ -124,7 +115,7 @@ EXPORT_SYMBOL(pci_claim_resource);
 #ifdef CONFIG_PCI_QUIRKS
 void pci_disable_bridge_window(struct pci_dev *dev)
 {
-       dev_dbg(&dev->dev, "Disabling bridge window.\n");
+       dev_info(&dev->dev, "disabling bridge mem windows\n");
 
        /* MMIO Base/Limit */
        pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
@@ -165,6 +156,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
 
        if (!ret) {
                res->flags &= ~IORESOURCE_STARTALIGN;
+               dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
                if (resno < PCI_BRIDGE_RESOURCES)
                        pci_update_resource(dev, resno);
        }
@@ -178,12 +170,12 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
        resource_size_t align;
        struct pci_bus *bus;
        int ret;
+       char *type;
 
        align = pci_resource_alignment(dev, res);
        if (!align) {
-               dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
-                       "alignment) %pR flags %#lx\n",
-                       resno, res, res->flags);
+               dev_info(&dev->dev, "BAR %d: can't assign %pR "
+                        "(bogus alignment)\n", resno, res);
                return -EINVAL;
        }
 
@@ -198,9 +190,20 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
                break;
        }
 
-       if (ret)
-               dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
-                       resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
+       if (ret) {
+               if (res->flags & IORESOURCE_MEM)
+                       if (res->flags & IORESOURCE_PREFETCH)
+                               type = "mem pref";
+                       else
+                               type = "mem";
+               else if (res->flags & IORESOURCE_IO)
+                       type = "io";
+               else
+                       type = "unknown";
+               dev_info(&dev->dev,
+                        "BAR %d: can't assign %s (size %#llx)\n",
+                        resno, type, (unsigned long long) resource_size(res));
+       }
 
        return ret;
 }
@@ -225,9 +228,8 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
 
                r_align = pci_resource_alignment(dev, r);
                if (!r_align) {
-                       dev_warn(&dev->dev, "BAR %d: bogus alignment "
-                               "%pR flags %#lx\n",
-                               i, r, r->flags);
+                       dev_warn(&dev->dev, "BAR %d: %pR has bogus alignment\n",
+                                i, r);
                        continue;
                }
                for (list = head; ; list = list->next) {
@@ -274,8 +276,8 @@ int pci_enable_resources(struct pci_dev *dev, int mask)
                        continue;
 
                if (!r->parent) {
-                       dev_err(&dev->dev, "device not available because of "
-                               "BAR %d %pR collisions\n", i, r);
+                       dev_err(&dev->dev, "device not available "
+                               "(can't reserve %pR)\n", r);
                        return -EINVAL;
                }
 
index 4cd70d0568109d061d6b716140adc52494cfd062..a73b040ddbfb81102fffe2a6da4768155f7689e3 100644 (file)
@@ -184,26 +184,33 @@ fail:
     
 =====================================================================*/
 
-/*
- * Since there is only one interrupt available to CardBus
- * devices, all devices downstream of this device must
- * be using this IRQ.
- */
-static void cardbus_assign_irqs(struct pci_bus *bus, int irq)
+static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
 {
        struct pci_dev *dev;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                u8 irq_pin;
 
+               /*
+                * Since there is only one interrupt available to
+                * CardBus devices, all devices downstream of this
+                * device must be using this IRQ.
+                */
                pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
                if (irq_pin) {
                        dev->irq = irq;
                        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
                }
 
+               /*
+                * Some controllers transfer very slowly with 0 CLS.
+                * Configure it.  This may fail as CLS configuration
+                * is mandatory only for MWI.
+                */
+               pci_set_cacheline_size(dev);
+
                if (dev->subordinate)
-                       cardbus_assign_irqs(dev->subordinate, irq);
+                       cardbus_config_irq_and_cls(dev->subordinate, irq);
        }
 }
 
@@ -228,7 +235,7 @@ int __ref cb_alloc(struct pcmcia_socket * s)
         */
        pci_bus_size_bridges(bus);
        pci_bus_assign_resources(bus);
-       cardbus_assign_irqs(bus, s->pci_irq);
+       cardbus_config_irq_and_cls(bus, s->pci_irq);
 
        /* socket specific tune function */
        if (s->tune_bridge)
index 8473fe5ed7ffe79d190cffcc42b3b2b383e4cf58..dfbd5a6cc58becc8cca321e4c6c34a043aebe81f 100644 (file)
@@ -285,15 +285,10 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
                                 * the PCI region, and that might prevent a PCI
                                 * driver from requesting its resources.
                                 */
-                               dev_warn(&dev->dev, "%s resource "
-                                       "(0x%llx-0x%llx) overlaps %s BAR %d "
-                                       "(0x%llx-0x%llx), disabling\n",
-                                       pnp_resource_type_name(res),
-                                       (unsigned long long) pnp_start,
-                                       (unsigned long long) pnp_end,
-                                       pci_name(pdev), i,
-                                       (unsigned long long) pci_start,
-                                       (unsigned long long) pci_end);
+                               dev_warn(&dev->dev,
+                                        "disabling %pR because it overlaps "
+                                        "%s BAR %d %pR\n", res,
+                                        pci_name(pdev), i, &pdev->resource[i]);
                                res->flags |= IORESOURCE_DISABLED;
                        }
                }
index ba97654278862ea5824c9645bcaa740dfcfe3061..64d0596bafb5949aacc8e1ae9c6bffdd578f91fe 100644 (file)
@@ -517,7 +517,7 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
        res->start = irq;
        res->end = irq;
 
-       pnp_dbg(&dev->dev, "  add irq %d flags %#x\n", irq, flags);
+       pnp_dbg(&dev->dev, "  add %pr\n", res);
        return pnp_res;
 }
 
@@ -538,7 +538,7 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
        res->start = dma;
        res->end = dma;
 
-       pnp_dbg(&dev->dev, "  add dma %d flags %#x\n", dma, flags);
+       pnp_dbg(&dev->dev, "  add %pr\n", res);
        return pnp_res;
 }
 
@@ -562,8 +562,7 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
        res->start = start;
        res->end = end;
 
-       pnp_dbg(&dev->dev, "  add io  %#llx-%#llx flags %#x\n",
-               (unsigned long long) start, (unsigned long long) end, flags);
+       pnp_dbg(&dev->dev, "  add %pr\n", res);
        return pnp_res;
 }
 
@@ -587,8 +586,7 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
        res->start = start;
        res->end = end;
 
-       pnp_dbg(&dev->dev, "  add mem %#llx-%#llx flags %#x\n",
-               (unsigned long long) start, (unsigned long long) end, flags);
+       pnp_dbg(&dev->dev, "  add %pr\n", res);
        return pnp_res;
 }
 
index 63087d5ce609a189ca0b564ffa546e15e7b0c176..9585c1c1cc3669783653deb6841d14fe0c10b292 100644 (file)
@@ -75,47 +75,14 @@ char *pnp_resource_type_name(struct resource *res)
 
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
 {
-       char buf[128];
-       int len;
        struct pnp_resource *pnp_res;
-       struct resource *res;
 
-       if (list_empty(&dev->resources)) {
+       if (list_empty(&dev->resources))
                pnp_dbg(&dev->dev, "%s: no current resources\n", desc);
-               return;
-       }
-
-       pnp_dbg(&dev->dev, "%s: current resources:\n", desc);
-       list_for_each_entry(pnp_res, &dev->resources, list) {
-               res = &pnp_res->res;
-               len = 0;
-
-               len += scnprintf(buf + len, sizeof(buf) - len, "  %-3s ",
-                                pnp_resource_type_name(res));
-
-               if (res->flags & IORESOURCE_DISABLED) {
-                       pnp_dbg(&dev->dev, "%sdisabled\n", buf);
-                       continue;
-               }
-
-               switch (pnp_resource_type(res)) {
-               case IORESOURCE_IO:
-               case IORESOURCE_MEM:
-                       len += scnprintf(buf + len, sizeof(buf) - len,
-                                        "%#llx-%#llx flags %#lx",
-                                        (unsigned long long) res->start,
-                                        (unsigned long long) res->end,
-                                        res->flags);
-                       break;
-               case IORESOURCE_IRQ:
-               case IORESOURCE_DMA:
-                       len += scnprintf(buf + len, sizeof(buf) - len,
-                                        "%lld flags %#lx",
-                                        (unsigned long long) res->start,
-                                        res->flags);
-                       break;
-               }
-               pnp_dbg(&dev->dev, "%s\n", buf);
+       else {
+               pnp_dbg(&dev->dev, "%s: current resources:\n", desc);
+               list_for_each_entry(pnp_res, &dev->resources, list)
+                       pnp_dbg(&dev->dev, "%pr\n", &pnp_res->res);
        }
 }
 
index 59b90922da8c324529c4d198c23b54211168f23f..49c1720df59a8550cdca31735e6ef519f6b88266 100644 (file)
@@ -22,11 +22,11 @@ static const struct pnp_device_id pnp_dev_table[] = {
        {"", 0}
 };
 
-static void reserve_range(struct pnp_dev *dev, resource_size_t start,
-                         resource_size_t end, int port)
+static void reserve_range(struct pnp_dev *dev, struct resource *r, int port)
 {
        char *regionid;
        const char *pnpid = dev_name(&dev->dev);
+       resource_size_t start = r->start, end = r->end;
        struct resource *res;
 
        regionid = kmalloc(16, GFP_KERNEL);
@@ -48,10 +48,8 @@ static void reserve_range(struct pnp_dev *dev, resource_size_t start,
         * example do reserve stuff they know about too, so we may well
         * have double reservations.
         */
-       dev_info(&dev->dev, "%s range 0x%llx-0x%llx %s reserved\n",
-               port ? "ioport" : "iomem",
-               (unsigned long long) start, (unsigned long long) end,
-               res ? "has been" : "could not be");
+       dev_info(&dev->dev, "%pR %s reserved\n", r,
+                res ? "has been" : "could not be");
 }
 
 static void reserve_resources_of_dev(struct pnp_dev *dev)
@@ -77,14 +75,14 @@ static void reserve_resources_of_dev(struct pnp_dev *dev)
                if (res->end < res->start)
                        continue;       /* invalid */
 
-               reserve_range(dev, res->start, res->end, 1);
+               reserve_range(dev, res, 1);
        }
 
        for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
                if (res->flags & IORESOURCE_DISABLED)
                        continue;
 
-               reserve_range(dev, res->start, res->end, 0);
+               reserve_range(dev, res, 0);
        }
 }
 
index 91a68e9eb66d7ff7ad8fd866d1266bd2ebf6dd10..603598f4dbb1a5ddc969478d42a41912d1bfe1fe 100644 (file)
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
+
 #include <asm/xen/hypervisor.h>
+
+#include <xen/xen.h>
 #include <xen/events.h>
 #include <xen/page.h>
 #include <xen/interface/io/fbif.h>
index 4204336135849de16ffd5a9d9d010d5ed5231433..f6738d8b02bcdd55d7b3ebdde6782f3394726831 100644 (file)
@@ -52,6 +52,8 @@
 
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
+
+#include <xen/xen.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/memory.h>
 #include <xen/xenbus.h>
index 0f765a92018913ff93791a3c97c6d7d094c586df..14e2d995e95800ca88a064ac5ba09caec2b48973 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/notifier.h>
 
+#include <xen/xen.h>
 #include <xen/xenbus.h>
 
 #include <asm/xen/hypervisor.h>
index 79bedba44feef5651177f10c2e3469e98a089e9a..f70a4f4698c5994348a14dd216bb91ad72ec5b6a 100644 (file)
@@ -48,6 +48,8 @@
 #include <linux/gfp.h>
 #include <linux/mutex.h>
 #include <linux/cpu.h>
+
+#include <xen/xen.h>
 #include <xen/events.h>
 #include <xen/evtchn.h>
 #include <asm/xen/hypervisor.h>
index 7d8f531fb8e8a60a342f2fce3f2168fe5127db39..4c6c0bd636a8073ab743dbcc2a643d3ea7fd73a0 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/vmalloc.h>
 #include <linux/uaccess.h>
 
+#include <xen/xen.h>
 #include <xen/interface/xen.h>
 #include <xen/page.h>
 #include <xen/grant_table.h>
index 88a60e03ccf079f40c1bab8f4da18d03720d5955..ae5cb05a1a1cb01cd4777d84b66ea3ba84e98c8a 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 
+#include <xen/xen.h>
 #include <xen/xenbus.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>
index 649fcdf114b7aab926cfbe4c3c348441d0c58ee0..2f7aaa99dc47e5d26701308e761612a2cdcbec8e 100644 (file)
@@ -49,6 +49,8 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/xen/hypervisor.h>
+
+#include <xen/xen.h>
 #include <xen/xenbus.h>
 #include <xen/events.h>
 #include <xen/page.h>
index 6559e0c752ce1494baa127921834e388832cbd75..8924d93136f152a7dd6b84d267db3162a4ff739b 100644 (file)
@@ -13,6 +13,8 @@
 #include <linux/fs.h>
 #include <linux/magic.h>
 
+#include <xen/xen.h>
+
 #include "xenfs.h"
 
 #include <asm/xen/hypervisor.h>
diff --git a/include/acpi/acpi_hest.h b/include/acpi/acpi_hest.h
new file mode 100644 (file)
index 0000000..63194d0
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __ACPI_HEST_H
+#define __ACPI_HEST_H
+
+#include <linux/pci.h>
+
+#ifdef CONFIG_ACPI
+extern int acpi_hest_firmware_first_pci(struct pci_dev *pci);
+#else
+static inline int acpi_hest_firmware_first_pci(struct pci_dev *pci) { return 0; }
+#endif
+
+#endif
index f5c7cd343e56ae85dafe8a660a280054a53bd433..04771b9c33160552cf050e2270af7ce360fd066d 100644 (file)
@@ -218,6 +218,7 @@ struct pci_dev {
        unsigned int    class;          /* 3 bytes: (base,sub,prog-if) */
        u8              revision;       /* PCI revision, low byte of class word */
        u8              hdr_type;       /* PCI header type (`multi' flag masked out) */
+       u8              pcie_cap;       /* PCI-E capability offset */
        u8              pcie_type;      /* PCI-E device/port type */
        u8              rom_base_reg;   /* which config register controls the ROM */
        u8              pin;            /* which interrupt pin this device uses */
@@ -280,6 +281,7 @@ struct pci_dev {
        unsigned int    is_virtfn:1;
        unsigned int    reset_fn:1;
        unsigned int    is_hotplug_bridge:1;
+       unsigned int    aer_firmware_first:1;
        pci_dev_flags_t dev_flags;
        atomic_t        enable_cnt;     /* pci_enable_device has been called */
 
@@ -635,7 +637,13 @@ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
                                unsigned int ss_vendor, unsigned int ss_device,
                                struct pci_dev *from);
 struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
-struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn);
+struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
+                                           unsigned int devfn);
+static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
+                                                  unsigned int devfn)
+{
+       return pci_get_domain_bus_and_slot(0, bus, devfn);
+}
 struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from);
 int pci_dev_present(const struct pci_device_id *ids);
 
@@ -701,6 +709,7 @@ void pci_disable_device(struct pci_dev *dev);
 void pci_set_master(struct pci_dev *dev);
 void pci_clear_master(struct pci_dev *dev);
 int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
+int pci_set_cacheline_size(struct pci_dev *dev);
 #define HAVE_PCI_SET_MWI
 int __must_check pci_set_mwi(struct pci_dev *dev);
 int pci_try_set_mwi(struct pci_dev *dev);
@@ -1246,6 +1255,8 @@ extern int pci_pci_problems;
 
 extern unsigned long pci_cardbus_io_size;
 extern unsigned long pci_cardbus_mem_size;
+extern u8 pci_dfl_cache_line_size;
+extern u8 pci_cache_line_size;
 
 extern unsigned long pci_hotplug_io_size;
 extern unsigned long pci_hotplug_mem_size;
@@ -1290,5 +1301,34 @@ extern void pci_hp_create_module_link(struct pci_slot *pci_slot);
 extern void pci_hp_remove_module_link(struct pci_slot *pci_slot);
 #endif
 
+/**
+ * pci_pcie_cap - get the saved PCIe capability offset
+ * @dev: PCI device
+ *
+ * PCIe capability offset is calculated at PCI device initialization
+ * time and saved in the data structure. This function returns saved
+ * PCIe capability offset. Using this instead of pci_find_capability()
+ * reduces unnecessary search in the PCI configuration space. If you
+ * need to calculate PCIe capability offset from raw device for some
+ * reasons, please use pci_find_capability() instead.
+ */
+static inline int pci_pcie_cap(struct pci_dev *dev)
+{
+       return dev->pcie_cap;
+}
+
+/**
+ * pci_is_pcie - check if the PCI device is PCI Express capable
+ * @dev: PCI device
+ *
+ * Retrun true if the PCI device is PCI Express capable, false otherwise.
+ */
+static inline bool pci_is_pcie(struct pci_dev *dev)
+{
+       return !!pci_pcie_cap(dev);
+}
+
+void pci_request_acs(void);
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
index dd0bed4f1cf00ffd00f5b2eace8103a25d606432..9f2ad0aa3c3961ae1ba55c981b815815e6cd35b7 100644 (file)
 #define  PCI_X_STATUS_266MHZ   0x40000000      /* 266 MHz capable */
 #define  PCI_X_STATUS_533MHZ   0x80000000      /* 533 MHz capable */
 
+/* PCI Bridge Subsystem ID registers */
+
+#define PCI_SSVID_VENDOR_ID     4      /* PCI-Bridge subsystem vendor id register */
+#define PCI_SSVID_DEVICE_ID     6      /* PCI-Bridge subsystem device id register */
+
 /* PCI Express capability registers */
 
 #define PCI_EXP_FLAGS          2       /* Capabilities register */
 #define PCI_EXT_CAP_ID_VC      2
 #define PCI_EXT_CAP_ID_DSN     3
 #define PCI_EXT_CAP_ID_PWR     4
+#define PCI_EXT_CAP_ID_ACS     13
 #define PCI_EXT_CAP_ID_ARI     14
 #define PCI_EXT_CAP_ID_ATS     15
 #define PCI_EXT_CAP_ID_SRIOV   16
 #define  PCI_SRIOV_VFM_MO      0x2     /* Active.MigrateOut */
 #define  PCI_SRIOV_VFM_AV      0x3     /* Active.Available */
 
+/* Access Control Service */
+#define PCI_ACS_CAP            0x04    /* ACS Capability Register */
+#define  PCI_ACS_SV            0x01    /* Source Validation */
+#define  PCI_ACS_TB            0x02    /* Translation Blocking */
+#define  PCI_ACS_RR            0x04    /* P2P Request Redirect */
+#define  PCI_ACS_CR            0x08    /* P2P Completion Redirect */
+#define  PCI_ACS_UF            0x10    /* Upstream Forwarding */
+#define  PCI_ACS_EC            0x20    /* P2P Egress Control */
+#define  PCI_ACS_DT            0x40    /* Direct Translated P2P */
+#define PCI_ACS_CTRL           0x06    /* ACS Control Register */
+#define PCI_ACS_EGRESS_CTL_V   0x08    /* ACS Egress Control Vector */
+
 #endif /* LINUX_PCI_REGS_H */
index b4c79545330be8b5ef8e061161b8a2d61ce868b2..6775532b92a9a04befeff78664023b1181cd2132 100644 (file)
 #define _PCIEPORT_IF_H_
 
 /* Port Type */
-#define PCIE_RC_PORT                   4       /* Root port of RC */
-#define PCIE_SW_UPSTREAM_PORT          5       /* Upstream port of Switch */
-#define PCIE_SW_DOWNSTREAM_PORT                6       /* Downstream port of Switch */
-#define PCIE_ANY_PORT                  7
+#define PCIE_ANY_PORT                  (~0)
 
 /* Service Type */
 #define PCIE_PORT_SERVICE_PME_SHIFT    0       /* Power Management Event */
 #define PCIE_PORT_SERVICE_VC_SHIFT     3       /* Virtual Channel */
 #define PCIE_PORT_SERVICE_VC           (1 << PCIE_PORT_SERVICE_VC_SHIFT)
 
-/* Root/Upstream/Downstream Port's Interrupt Mode */
-#define PCIE_PORT_NO_IRQ               (-1)
-#define PCIE_PORT_INTx_MODE            0
-#define PCIE_PORT_MSI_MODE             1
-#define PCIE_PORT_MSIX_MODE            2
-
-struct pcie_port_data {
-       int port_type;          /* Type of the port */
-       int port_irq_mode;      /* [0:INTx | 1:MSI | 2:MSI-X] */
-};
-
 struct pcie_device {
        int             irq;        /* Service IRQ/MSI/MSI-X Vector */
        struct pci_dev *port;       /* Root/Upstream/Downstream Port */
diff --git a/include/xen/xen.h b/include/xen/xen.h
new file mode 100644 (file)
index 0000000..a164024
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _XEN_XEN_H
+#define _XEN_XEN_H
+
+enum xen_domain_type {
+       XEN_NATIVE,             /* running on bare hardware    */
+       XEN_PV_DOMAIN,          /* running in a PV domain      */
+       XEN_HVM_DOMAIN,         /* running in a Xen hvm domain */
+};
+
+#ifdef CONFIG_XEN
+extern enum xen_domain_type xen_domain_type;
+#else
+#define xen_domain_type                XEN_NATIVE
+#endif
+
+#define xen_domain()           (xen_domain_type != XEN_NATIVE)
+#define xen_pv_domain()                (xen_domain() &&                        \
+                                xen_domain_type == XEN_PV_DOMAIN)
+#define xen_hvm_domain()       (xen_domain() &&                        \
+                                xen_domain_type == XEN_HVM_DOMAIN)
+
+#ifdef CONFIG_XEN_DOM0
+#include <xen/interface/xen.h>
+#include <asm/xen/hypervisor.h>
+
+#define xen_initial_domain()   (xen_pv_domain() && \
+                                xen_start_info->flags & SIF_INITDOMAIN)
+#else  /* !CONFIG_XEN_DOM0 */
+#define xen_initial_domain()   (0)
+#endif /* CONFIG_XEN_DOM0 */
+
+#endif /* _XEN_XEN_H */
index fb11a58b95948a08c57ec46033f538d974a480dd..dc15686b7a7783927e28f5866064bdaba10d39e6 100644 (file)
@@ -308,35 +308,37 @@ static int find_resource(struct resource *root, struct resource *new,
                         void *alignf_data)
 {
        struct resource *this = root->child;
+       resource_size_t start, end;
 
-       new->start = root->start;
+       start = root->start;
        /*
         * Skip past an allocated resource that starts at 0, since the assignment
         * of this->start - 1 to new->end below would cause an underflow.
         */
        if (this && this->start == 0) {
-               new->start = this->end + 1;
+               start = this->end + 1;
                this = this->sibling;
        }
        for(;;) {
                if (this)
-                       new->end = this->start - 1;
+                       end = this->start - 1;
                else
-                       new->end = root->end;
-               if (new->start < min)
-                       new->start = min;
-               if (new->end > max)
-                       new->end = max;
-               new->start = ALIGN(new->start, align);
+                       end = root->end;
+               if (start < min)
+                       start = min;
+               if (end > max)
+                       end = max;
+               start = ALIGN(start, align);
                if (alignf)
                        alignf(alignf_data, new, size, align);
-               if (new->start < new->end && new->end - new->start >= size - 1) {
-                       new->end = new->start + size - 1;
+               if (start < end && end - start >= size - 1) {
+                       new->start = start;
+                       new->end = start + size - 1;
                        return 0;
                }
                if (!this)
                        break;
-               new->start = this->end + 1;
+               start = this->end + 1;
                this = this->sibling;
        }
        return -EBUSY;
index 33bed5e67a2110b2201856b8828b457110147728..6438cd5599eefe583451b9b5bd858b9ab5a0ca38 100644 (file)
@@ -595,37 +595,89 @@ static char *symbol_string(char *buf, char *end, void *ptr,
 }
 
 static char *resource_string(char *buf, char *end, struct resource *res,
-                               struct printf_spec spec)
+                               struct printf_spec spec, const char *fmt)
 {
 #ifndef IO_RSRC_PRINTK_SIZE
-#define IO_RSRC_PRINTK_SIZE    4
+#define IO_RSRC_PRINTK_SIZE    6
 #endif
 
 #ifndef MEM_RSRC_PRINTK_SIZE
-#define MEM_RSRC_PRINTK_SIZE   8
+#define MEM_RSRC_PRINTK_SIZE   10
 #endif
-       struct printf_spec num_spec = {
+       struct printf_spec hex_spec = {
                .base = 16,
                .precision = -1,
                .flags = SPECIAL | SMALL | ZEROPAD,
        };
-       /* room for the actual numbers, the two "0x", -, [, ] and the final zero */
-       char sym[4*sizeof(resource_size_t) + 8];
+       struct printf_spec dec_spec = {
+               .base = 10,
+               .precision = -1,
+               .flags = 0,
+       };
+       struct printf_spec str_spec = {
+               .field_width = -1,
+               .precision = 10,
+               .flags = LEFT,
+       };
+       struct printf_spec flag_spec = {
+               .base = 16,
+               .precision = -1,
+               .flags = SPECIAL | SMALL,
+       };
+
+       /* 32-bit res (sizeof==4): 10 chars in dec, 10 in hex ("0x" + 8)
+        * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */
+#define RSRC_BUF_SIZE          ((2 * sizeof(resource_size_t)) + 4)
+#define FLAG_BUF_SIZE          (2 * sizeof(res->flags))
+#define DECODED_BUF_SIZE       sizeof("[mem - 64bit pref disabled]")
+#define RAW_BUF_SIZE           sizeof("[mem - flags 0x]")
+       char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
+                    2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
+
        char *p = sym, *pend = sym + sizeof(sym);
-       int size = -1;
+       int size = -1, addr = 0;
+       int decode = (fmt[0] == 'R') ? 1 : 0;
 
-       if (res->flags & IORESOURCE_IO)
+       if (res->flags & IORESOURCE_IO) {
                size = IO_RSRC_PRINTK_SIZE;
-       else if (res->flags & IORESOURCE_MEM)
+               addr = 1;
+       } else if (res->flags & IORESOURCE_MEM) {
                size = MEM_RSRC_PRINTK_SIZE;
+               addr = 1;
+       }
 
        *p++ = '[';
-       num_spec.field_width = size;
-       p = number(p, pend, res->start, num_spec);
-       *p++ = '-';
-       p = number(p, pend, res->end, num_spec);
+       if (res->flags & IORESOURCE_IO)
+               p = string(p, pend, "io  ", str_spec);
+       else if (res->flags & IORESOURCE_MEM)
+               p = string(p, pend, "mem ", str_spec);
+       else if (res->flags & IORESOURCE_IRQ)
+               p = string(p, pend, "irq ", str_spec);
+       else if (res->flags & IORESOURCE_DMA)
+               p = string(p, pend, "dma ", str_spec);
+       else {
+               p = string(p, pend, "??? ", str_spec);
+               decode = 0;
+       }
+       hex_spec.field_width = size;
+       p = number(p, pend, res->start, addr ? hex_spec : dec_spec);
+       if (res->start != res->end) {
+               *p++ = '-';
+               p = number(p, pend, res->end, addr ? hex_spec : dec_spec);
+       }
+       if (decode) {
+               if (res->flags & IORESOURCE_MEM_64)
+                       p = string(p, pend, " 64bit", str_spec);
+               if (res->flags & IORESOURCE_PREFETCH)
+                       p = string(p, pend, " pref", str_spec);
+               if (res->flags & IORESOURCE_DISABLED)
+                       p = string(p, pend, " disabled", str_spec);
+       } else {
+               p = string(p, pend, " flags ", str_spec);
+               p = number(p, pend, res->flags, flag_spec);
+       }
        *p++ = ']';
-       *p = 0;
+       *p = '\0';
 
        return string(buf, end, sym, spec);
 }
@@ -801,8 +853,8 @@ static char *ip4_addr_string(char *buf, char *end, const u8 *addr,
  * - 'f' For simple symbolic function names without offset
  * - 'S' For symbolic direct pointers with offset
  * - 's' For symbolic direct pointers without offset
- * - 'R' For a struct resource pointer, it prints the range of
- *       addresses (not the name nor the flags)
+ * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
+ * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
  * - 'M' For a 6-byte MAC address, it prints the address in the
  *       usual colon-separated hex notation
  * - 'm' For a 6-byte MAC address, it prints the hex address without colons
@@ -833,7 +885,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
        case 'S':
                return symbol_string(buf, end, ptr, spec, *fmt);
        case 'R':
-               return resource_string(buf, end, ptr, spec);
+       case 'r':
+               return resource_string(buf, end, ptr, spec, fmt);
        case 'M':                       /* Colon separated: 00:01:02:03:04:05 */
        case 'm':                       /* Contiguous: 000102030405 */
                return mac_address_string(buf, end, ptr, spec, fmt);