diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 15:50:23 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 15:50:23 -0700 |
commit | 6a84258e5f5bb8b9bd72e06a5837fa6fdacaf5c5 (patch) | |
tree | 3c4911a489c85e908b0ef3ed83d78264788f858c | |
parent | efefc6eb38d43b8e5daef482f575d767b002004e (diff) | |
parent | f3e6f164c2389853432454c89b316a8ab7485e2f (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6: (37 commits)
PCI: merge almost all of pci_32.h and pci_64.h together
PCI: X86: Introduce and enable PCI domain support
PCI: Add 'nodomains' boot option, and pci_domains_supported global
PCI: modify PCI bridge control ISA flag for clarity
PCI: use _CRS for PCI resource allocation
PCI: avoid P2P prefetch window for expansion ROMs
PCI: skip ISA ioresource alignment on some systems
PCI: remove transparent bridge sizing
pci: write file size to inode on proc bus file write
pci: use size stored in proc_dir_entry for proc bus files
pci: implement "pci=noaer"
PCI: fix IDE legacy mode resources
MSI: Use correct data offset for 32-bit MSI in read_msi_msg()
PCI: Fix incorrect argument order to list_add_tail() in PCI dynamic ID code
PCI: i386: Compaq EVO N800c needs PCI bus renumbering
PCI: Remove no longer correct documentation regarding MSI vector assignment
PCI: re-enable onboard sound on "MSI K8T Neo2-FIR"
PCI: quirk_vt82c586_acpi: Omit reading PCI revision ID
PCI: quirk amd_8131_mmrbc: Omit reading pci revision ID
cpqphp: Use PCI_CLASS_REVISION instead of PCI_REVISION_ID for read
...
38 files changed, 654 insertions, 544 deletions
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index cc7a8c39fb6..b939ebb6287 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -68,6 +68,9 @@ size and dma_handle must all be the same as those passed into the consistent allocate. cpu_addr must be the virtual address returned by the consistent allocate. +Note that unlike their sibling allocation calls, these routines +may only be called with IRQs enabled. + Part Ib - Using small dma-coherent buffers ------------------------------------------ diff --git a/Documentation/MSI-HOWTO.txt b/Documentation/MSI-HOWTO.txt index 0d8240774fc..a51f693c154 100644 --- a/Documentation/MSI-HOWTO.txt +++ b/Documentation/MSI-HOWTO.txt @@ -241,68 +241,7 @@ address space of the MSI-X table/MSI-X PBA. Otherwise, the PCI subsystem will fail enabling MSI-X on its hardware device when it calls the function pci_enable_msix(). -5.3.2 Handling MSI-X allocation - -Determining the number of MSI-X vectors allocated to a function is -dependent on the number of MSI capable devices and MSI-X capable -devices populated in the system. The policy of allocating MSI-X -vectors to a function is defined as the following: - -#of MSI-X vectors allocated to a function = (x - y)/z where - -x = The number of available PCI vector resources by the time - the device driver calls pci_enable_msix(). The PCI vector - resources is the sum of the number of unassigned vectors - (new) and the number of released vectors when any MSI/MSI-X - device driver switches its hardware device back to a legacy - mode or is hot-removed. The number of unassigned vectors - may exclude some vectors reserved, as defined in parameter - NR_HP_RESERVED_VECTORS, for the case where the system is - capable of supporting hot-add/hot-remove operations. Users - may change the value defined in NR_HR_RESERVED_VECTORS to - meet their specific needs. - -y = The number of MSI capable devices populated in the system. - This policy ensures that each MSI capable device has its - vector reserved to avoid the case where some MSI-X capable - drivers may attempt to claim all available vector resources. - -z = The number of MSI-X capable devices populated in the system. - This policy ensures that maximum (x - y) is distributed - evenly among MSI-X capable devices. - -Note that the PCI subsystem scans y and z during a bus enumeration. -When the PCI subsystem completes configuring MSI/MSI-X capability -structure of a device as requested by its device driver, y/z is -decremented accordingly. - -5.3.3 Handling MSI-X shortages - -For the case where fewer MSI-X vectors are allocated to a function -than requested, the function pci_enable_msix() will return the -maximum number of MSI-X vectors available to the caller. A device -driver may re-send its request with fewer or equal vectors indicated -in the return. For example, if a device driver requests 5 vectors, but -the number of available vectors is 3 vectors, a value of 3 will be -returned as a result of pci_enable_msix() call. A function could be -designed for its driver to use only 3 MSI-X table entries as -different combinations as ABC--, A-B-C, A--CB, etc. Note that this -patch does not support multiple entries with the same vector. Such -attempt by a device driver to use 5 MSI-X table entries with 3 vectors -as ABBCC, AABCC, BCCBA, etc will result as a failure by the function -pci_enable_msix(). Below are the reasons why supporting multiple -entries with the same vector is an undesirable solution. - - - The PCI subsystem cannot determine the entry that - generated the message to mask/unmask MSI while handling - software driver ISR. Attempting to walk through all MSI-X - table entries (2048 max) to mask/unmask any match vector - is an undesirable solution. - - - Walking through all MSI-X table entries (2048 max) to handle - SMP affinity of any match vector is an undesirable solution. - -5.3.4 API pci_enable_msix +5.3.2 API pci_enable_msix int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec) @@ -339,7 +278,7 @@ a failure. This failure may be a result of duplicate entries specified in second argument, or a result of no available vector, or a result of failing to initialize MSI-X table entries. -5.3.5 API pci_disable_msix +5.3.3 API pci_disable_msix void pci_disable_msix(struct pci_dev *dev) @@ -349,7 +288,7 @@ always call free_irq() on all MSI-X vectors it has done request_irq() on before calling this API. Failure to do so results in a BUG_ON() and a device will be left with MSI-X enabled and leaks its vectors. -5.3.6 MSI-X mode vs. legacy mode diagram +5.3.4 MSI-X mode vs. legacy mode diagram The below diagram shows the events which switch the interrupt mode on the MSI-X capable device function between MSI-X mode and @@ -407,7 +346,7 @@ between MSI mod MSI-X mode during a run-time. MSI/MSI-X support requires support from both system hardware and individual hardware device functions. -5.5.1 System hardware support +5.5.1 Required x86 hardware support Since the target of MSI address is the local APIC CPU, enabling MSI/MSI-X support in the Linux kernel is dependent on whether existing diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 912c57c2334..9cbc82e37ed 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -68,6 +68,7 @@ parameter is applicable: PARIDE The ParIDE (parallel port IDE) subsystem is enabled. PARISC The PA-RISC architecture is enabled. PCI PCI bus support is enabled. + PCIE PCI Express support is enabled. PCMCIA The PCMCIA subsystem is enabled. PNP Plug & Play support is enabled. PPC PowerPC architecture is enabled. @@ -1277,6 +1278,11 @@ and is between 256 and 4096 characters. It is defined in the file Mechanism 1. conf2 [X86-32] Force use of PCI Configuration Mechanism 2. + noaer [PCIE] If the PCIEAER kernel config parameter is + enabled, this kernel boot option can be used to + disable the use of PCIE advanced error reporting. + nodomains [PCI] Disable support for multiple PCI + root domains (aka PCI segments, in ACPI-speak). nommconf [X86-32,X86_64] Disable use of MMCONFIG for PCI Configuration nomsi [MSI] If the PCI_MSI kernel config parameter is @@ -1321,6 +1327,8 @@ and is between 256 and 4096 characters. It is defined in the file IRQ routing is enabled. noacpi [X86-32] Do not use ACPI for IRQ routing or for PCI scanning. + use_crs [X86-32] Use _CRS for PCI resource + allocation. routeirq Do IRQ routing for all PCI devices. This is normally done in pci_enable_device(), so this option is a temporary workaround diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 6bbbc2755e4..f1486f8a3e6 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -1137,6 +1137,11 @@ config PCI_MMCONFIG depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) default y +config PCI_DOMAINS + bool + depends on PCI + default y + source "drivers/pci/pcie/Kconfig" source "drivers/pci/Kconfig" diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c index 048f09b6255..0aae2f3847a 100644 --- a/arch/x86/kernel/pci-dma_32.c +++ b/arch/x86/kernel/pci-dma_32.c @@ -63,7 +63,8 @@ void dma_free_coherent(struct device *dev, size_t size, { struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; int order = get_order(size); - + + WARN_ON(irqs_disabled()); /* for portability */ if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index 29711445c81..9576a2eb375 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c @@ -167,6 +167,7 @@ EXPORT_SYMBOL(dma_alloc_coherent); void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t bus) { + WARN_ON(irqs_disabled()); /* for portability */ if (dma_ops->unmap_single) dma_ops->unmap_single(dev, bus, size, 0); free_pages((unsigned long)vaddr, get_order(size)); diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c index 03e1cce58f4..139eb03490f 100644 --- a/arch/x86/kernel/reboot_fixups_32.c +++ b/arch/x86/kernel/reboot_fixups_32.c @@ -11,6 +11,7 @@ #include <asm/delay.h> #include <linux/pci.h> +#include <linux/interrupt.h> #include <asm/reboot_fixups.h> #include <asm/msr.h> @@ -56,6 +57,11 @@ void mach_reboot_fixups(void) struct pci_dev *dev; int i; + /* we can be called from sysrq-B code. In such a case it is + * prohibited to dig PCI */ + if (in_interrupt()) + return; + for (i=0; i < ARRAY_SIZE(fixups_table); i++) { cur = &(fixups_table[i]); dev = pci_get_device(cur->vendor, cur->device, NULL); diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index bc8a44bddaa..27a391da9a9 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -2,15 +2,199 @@ #include <linux/acpi.h> #include <linux/init.h> #include <linux/irq.h> +#include <linux/dmi.h> #include <asm/numa.h> #include "pci.h" +static int __devinit can_skip_ioresource_align(struct dmi_system_id *d) +{ + pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; + printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident); + return 0; +} + +static struct dmi_system_id acpi_pciprobe_dmi_table[] = { +/* + * Systems where PCI IO resource ISA alignment can be skipped + * when the ISA enable bit in the bridge control is not set + */ + { + .callback = can_skip_ioresource_align, + .ident = "IBM System x3800", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "IBM"), + DMI_MATCH(DMI_PRODUCT_NAME, "x3800"), + }, + }, + { + .callback = can_skip_ioresource_align, + .ident = "IBM System x3850", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "IBM"), + DMI_MATCH(DMI_PRODUCT_NAME, "x3850"), + }, + }, + { + .callback = can_skip_ioresource_align, + .ident = "IBM System x3950", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "IBM"), + DMI_MATCH(DMI_PRODUCT_NAME, "x3950"), + }, + }, + {} +}; + +struct pci_root_info { + char *name; + unsigned int res_num; + struct resource *res; + struct pci_bus *bus; + int busnum; +}; + +static acpi_status +resource_to_addr(struct acpi_resource *resource, + struct acpi_resource_address64 *addr) +{ + acpi_status status; + + status = acpi_resource_to_address64(resource, addr); + if (ACPI_SUCCESS(status) && + (addr->resource_type == ACPI_MEMORY_RANGE || + addr->resource_type == ACPI_IO_RANGE) && + addr->address_length > 0 && + addr->producer_consumer == ACPI_PRODUCER) { + return AE_OK; + } + return AE_ERROR; +} + +static acpi_status +count_resource(struct acpi_resource *acpi_res, void *data) +{ + struct pci_root_info *info = data; + struct acpi_resource_address64 addr; + acpi_status status; + + status = resource_to_addr(acpi_res, &addr); + if (ACPI_SUCCESS(status)) + info->res_num++; + return AE_OK; +} + +static acpi_status +setup_resource(struct acpi_resource *acpi_res, void *data) +{ + struct pci_root_info *info = data; + struct resource *res; + struct acpi_resource_address64 addr; + acpi_status status; + unsigned long flags; + struct resource *root; + + status = resource_to_addr(acpi_res, &addr); + if (!ACPI_SUCCESS(status)) + return AE_OK; + + if (addr.resource_type == ACPI_MEMORY_RANGE) { + root = &iomem_resource; + flags = IORESOURCE_MEM; + if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY) + flags |= IORESOURCE_PREFETCH; + } else if (addr.resource_type == ACPI_IO_RANGE) { + root = &ioport_resource; + flags = IORESOURCE_IO; + } else + return AE_OK; + + res = &info->res[info->res_num]; + res->name = info->name; + res->flags = flags; + res->start = addr.minimum + addr.translation_offset; + res->end = res->start + addr.address_length - 1; + res->child = NULL; + + 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); + } else { + info->bus->resource[info->res_num] = res; + info->res_num++; + } + return AE_OK; +} + +static void +adjust_transparent_bridge_resources(struct pci_bus *bus) +{ + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + int i; + u16 class = dev->class >> 8; + + if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) { + for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++) + dev->subordinate->resource[i] = + dev->bus->resource[i - 3]; + } + } +} + +static void +get_current_resources(struct acpi_device *device, int busnum, + struct pci_bus *bus) +{ + struct pci_root_info info; + size_t size; + + info.bus = bus; + info.res_num = 0; + acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, + &info); + if (!info.res_num) + return; + + size = sizeof(*info.res) * info.res_num; + info.res = kmalloc(size, GFP_KERNEL); + if (!info.res) + goto res_alloc_fail; + + info.name = kmalloc(12, GFP_KERNEL); + if (!info.name) + goto name_alloc_fail; + sprintf(info.name, "PCI Bus #%02x", busnum); + + info.res_num = 0; + acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, + &info); + if (info.res_num) + adjust_transparent_bridge_resources(bus); + + return; + +name_alloc_fail: + kfree(info.res); +res_alloc_fail: + return; +} + struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) { struct pci_bus *bus; struct pci_sysdata *sd; int pxm; + dmi_check_system(acpi_pciprobe_dmi_table); + + if (domain && !pci_domains_supported) { + printk(KERN_WARNING "PCI: Multiple domains not supported " + "(dom %d, bus %d)\n", domain, busnum); + return NULL; + } + /* Allocate per-root-bus (not per bus) arch-specific data. * TODO: leak; this memory is never freed. * It's arguable whether it's worth the trouble to care. @@ -21,12 +205,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do return NULL; } - if (domain != 0) { - printk(KERN_WARNING "PCI: Multiple domains not supported\n"); - kfree(sd); - return NULL; - } - + sd->domain = domain; sd->node = -1; pxm = acpi_get_pxm(device->handle); @@ -47,6 +226,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do } } #endif + + if (bus && (pci_probe & PCI_USE__CRS)) + get_current_resources(device, busnum, bus); return bus; } diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 07d5223442b..2d71bbc411d 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -29,12 +29,14 @@ struct pci_raw_ops *raw_pci_ops; static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { - return raw_pci_ops->read(0, bus->number, devfn, where, size, value); + return raw_pci_ops->read(pci_domain_nr(bus), bus->number, + devfn, where, size, value); } static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { - return raw_pci_ops->write(0, bus->number, devfn, where, size, value); + return raw_pci_ops->write(pci_domain_nr(bus), bus->number, + devfn, where, size, value); } struct pci_ops pci_root_ops = { @@ -287,6 +289,16 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), }, }, +#ifdef __i386__ + { + .callback = assign_all_busses, + .ident = "Compaq EVO N800c", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), + DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"), + }, + }, +#endif {} }; @@ -426,6 +438,9 @@ char * __devinit pcibios_setup(char *str) } else if (!strcmp(str, "assign-busses")) { pci_probe |= PCI_ASSIGN_ALL_BUSSES; return NULL; + } else if (!strcmp(str, "use_crs")) { + pci_probe |= PCI_USE__CRS; + return NULL; } else if (!strcmp(str, "routeirq")) { pci_routeirq = 1; return NULL; diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index c82cbf4c722..6cff66dd0c9 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -353,6 +353,53 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev) } DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); + +static struct dmi_system_id __devinitdata msi_k8t_dmi_table[] = { + { + .ident = "MSI-K8T-Neo2Fir", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MSI"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-6702E"), + }, + }, + {} +}; + +/* + * The AMD-Athlon64 board MSI "K8T Neo2-FIR" disables the onboard sound + * card if a PCI-soundcard is added. + * + * The BIOS only gives options "DISABLED" and "AUTO". This code sets + * the corresponding register-value to enable the soundcard. + * + * The soundcard is only enabled, if the mainborad is identified + * via DMI-tables and the soundcard is detected to be off. + */ +static void __devinit pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev) +{ + unsigned char val; + if (!dmi_check_system(msi_k8t_dmi_table)) + return; /* only applies to MSI K8T Neo2-FIR */ + + pci_read_config_byte(dev, 0x50, &val); + if (val & 0x40) { + pci_write_config_byte(dev, 0x50, val & (~0x40)); + + /* verify the change for status output */ + pci_read_config_byte(dev, 0x50, &val); + if (val & 0x40) + printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, " + "can't enable onboard soundcard!\n"); + else + printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, " + "enabled onboard soundcard.\n"); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, + pci_fixup_msi_k8t_onboard_sound); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, + pci_fixup_msi_k8t_onboard_sound); + /* * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. * diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index bcd2f94b732..42ba0e2da1a 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -33,6 +33,15 @@ #include "pci.h" +static int +skip_isa_ioresource_align(struct pci_dev *dev) { + + if ((pci_probe & PCI_CAN_SKIP_ISA_ALIGN) && + !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA)) + return 1; + return 0; +} + /* * We need to avoid collisions with `mirrored' VGA ports * and other strange ISA hardware, so we always want the @@ -50,9 +59,13 @@ void pcibios_align_resource(void *data, struct resource *res, resource_size_t size, resource_size_t align) { + struct pci_dev *dev = data; + if (res->flags & IORESOURCE_IO) { resource_size_t start = res->start; + if (skip_isa_ioresource_align(dev)) + return; if (start & 0x300) { start = (start + 0x3ff) & ~0x3ff; res->start = start; diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index d98c6b096f8..c52150fdf82 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -492,6 +492,26 @@ static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq return 1; } +/* + * PicoPower PT86C523 + */ +static int pirq_pico_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +{ + outb(0x10 + ((pirq - 1) >> 1), 0x24); + return ((pirq - 1) & 1) ? (inb(0x26) >> 4) : (inb(0x26) & 0xf); +} + +static int pirq_pico_set(struct pci_dev *router, struct pci_dev *dev, int pirq, + int irq) +{ + unsigned int x; + outb(0x10 + ((pirq - 1) >> 1), 0x24); + x = inb(0x26); + x = ((pirq - 1) & 1) ? ((x & 0x0f) | (irq << 4)) : ((x & 0xf0) | (irq)); + outb(x, 0x26); + return 1; +} + #ifdef CONFIG_PCI_BIOS static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) @@ -721,6 +741,24 @@ static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, return 1; } +static __init int pico_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +{ + switch (device) { + case PCI_DEVICE_ID_PICOPOWER_PT86C523: + r->name = "PicoPower PT86C523"; + r->get = pirq_pico_get; + r->set = pirq_pico_set; + return 1; + + case PCI_DEVICE_ID_PICOPOWER_PT86C523BBP: + r->name = "PicoPower PT86C523 rev. BB+"; + r->get = pirq_pico_get; + r->set = pirq_pico_set; + return 1; + } + return 0; +} + static __initdata struct irq_router_handler pirq_routers[] = { { PCI_VENDOR_ID_INTEL, intel_router_probe }, { PCI_VENDOR_ID_AL, ali_router_probe }, @@ -732,6 +770,7 @@ static __initdata struct irq_router_handler pirq_routers[] = { { PCI_VENDOR_ID_VLSI, vlsi_router_probe }, { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe }, { PCI_VENDOR_ID_AMD, amd_router_probe }, + { PCI_VENDOR_ID_PICOPOWER, pico_router_probe }, /* Someone with docs needs to add the ATI Radeon IGP */ { 0, NULL } }; diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h index 8c66f275756..ac56d3916c5 100644 --- a/arch/x86/pci/pci.h +++ b/arch/x86/pci/pci.h @@ -26,6 +26,8 @@ #define PCI_ASSIGN_ROMS 0x1000 #define PCI_BIOS_IRQ_SCAN 0x2000 #define PCI_ASSIGN_ALL_BUSSES 0x4000 +#define PCI_CAN_SKIP_ISA_ALIGN 0x8000 +#define PCI_USE__CRS 0x10000 extern unsigned int pci_probe; extern unsigned long pirq_table_addr; diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index eb80f5aca54..cf013cb85ea 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -738,6 +738,11 @@ config PCI_MMCONFIG bool "Support mmconfig PCI config space access" depends on PCI && ACPI +config PCI_DOMAINS + bool + depends on PCI + default y + source "drivers/pci/pcie/Kconfig" source "drivers/pci/Kconfig" diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 2305cc450a4..a96b739b2d3 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -549,7 +549,7 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) * slot. */ bus->number = tbus; pci_bus_read_config_dword(bus, PCI_DEVFN(tdevice, 0), - PCI_REVISION_ID, &work); + PCI_CLASS_REVISION, &work); if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { pci_bus_read_config_dword(bus, diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 37d72f123a8..3ef0a4875a6 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -37,6 +37,7 @@ #include <linux/smp_lock.h> #include <linux/pci.h> #include <linux/pci_hotplug.h> +#include <linux/kthread.h> #include "cpqphp.h" static u32 configure_new_device(struct controller* ctrl, struct pci_func *func, @@ -45,34 +46,20 @@ static int configure_new_function(struct controller* ctrl, struct pci_func *func u8 behind_bridge, struct resource_lists *resources); static void interrupt_event_handler(struct controller *ctrl); -static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ -static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ -static int event_finished; -static unsigned long pushbutton_pending; /* = 0 */ -/* things needed for the long_delay function */ -static struct semaphore delay_sem; -static wait_queue_head_t delay_wait; +static struct task_struct *cpqhp_event_thread; +static unsigned long pushbutton_pending; /* = 0 */ /* delay is in jiffies to wait for */ static void long_delay(int delay) { - DECLARE_WAITQUEUE(wait, current); - - /* only allow 1 customer into the delay queue at once - * yes this makes some people wait even longer, but who really cares? - * this is for _huge_ delays to make the hardware happy as the - * signals bounce around + /* + * |