From c3163004c5cee68acc4a87936da01b82d447f0fd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Apr 2013 11:17:47 -0600 Subject: [PATCH] --- yaml --- r: 362887 b: refs/heads/master c: 139f925126cc31b925484b2bc2cd0b0357c2bbd6 h: refs/heads/master i: 362885: 965a718672f39245a879a38f61bd0bf7007b48e3 362883: 0b63ef0d8d42e2bafee1f6295e7234e66957f02b 362879: 14cfcf797d382741e336a6173710822bab59039d v: v3 --- [refs] | 2 +- trunk/arch/ia64/pci/pci.c | 11 - trunk/arch/mips/pci/pci.c | 8 +- trunk/arch/x86/pci/common.c | 11 - trunk/drivers/acpi/pci_root.c | 48 ++- trunk/drivers/acpi/pci_slot.c | 170 ++++++++-- trunk/drivers/acpi/scan.c | 1 + trunk/drivers/ata/ahci.c | 10 +- trunk/drivers/eisa/eisa-bus.c | 82 +++-- trunk/drivers/eisa/pci_eisa.c | 5 +- trunk/drivers/iommu/amd_iommu.c | 14 +- trunk/drivers/iommu/amd_iommu_init.c | 40 +-- trunk/drivers/iommu/amd_iommu_types.h | 11 +- trunk/drivers/pci/bus.c | 11 +- trunk/drivers/pci/hotplug/Kconfig | 7 +- trunk/drivers/pci/hotplug/acpiphp.h | 13 +- trunk/drivers/pci/hotplug/acpiphp_core.c | 30 +- trunk/drivers/pci/hotplug/acpiphp_glue.c | 415 +++++++++++++++-------- trunk/drivers/pci/hotplug/pciehp_acpi.c | 2 +- trunk/drivers/pci/pci-acpi.c | 30 -- trunk/drivers/pci/pci-sysfs.c | 2 +- trunk/drivers/pci/pcie/Kconfig | 2 +- trunk/drivers/pci/pcie/aer/aer_inject.c | 6 +- trunk/drivers/pci/pcie/aer/aerdrv_core.c | 4 +- trunk/drivers/pci/pcie/pme.c | 2 + trunk/drivers/pci/pcie/portdrv_acpi.c | 1 + trunk/drivers/pci/probe.c | 15 +- trunk/drivers/pci/quirks.c | 148 ++++---- trunk/drivers/pci/remove.c | 4 +- trunk/drivers/scsi/mvsas/mv_init.c | 6 +- trunk/drivers/scsi/mvumi.c | 4 +- trunk/drivers/scsi/mvumi.h | 1 + trunk/include/linux/acpi.h | 9 + trunk/include/linux/pci-acpi.h | 29 -- trunk/include/linux/pci.h | 19 +- trunk/include/linux/pci_ids.h | 1 - 36 files changed, 722 insertions(+), 452 deletions(-) diff --git a/[refs] b/[refs] index 2b6d24b75b2e..8d754b43cb53 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a3b6bbd5774c13dab89d72f79976ba762913b2f2 +refs/heads/master: 139f925126cc31b925484b2bc2cd0b0357c2bbd6 diff --git a/trunk/arch/ia64/pci/pci.c b/trunk/arch/ia64/pci/pci.c index de1474ff0bc5..60532ab27346 100644 --- a/trunk/arch/ia64/pci/pci.c +++ b/trunk/arch/ia64/pci/pci.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -459,16 +458,6 @@ void pcibios_fixup_bus(struct pci_bus *b) platform_pci_fixup_bus(b); } -void pcibios_add_bus(struct pci_bus *bus) -{ - acpi_pci_add_bus(bus); -} - -void pcibios_remove_bus(struct pci_bus *bus) -{ - acpi_pci_remove_bus(bus); -} - void pcibios_set_master (struct pci_dev *dev) { /* No special bus mastering setup handling */ diff --git a/trunk/arch/mips/pci/pci.c b/trunk/arch/mips/pci/pci.c index 594e60d6a43b..0872f12f268d 100644 --- a/trunk/arch/mips/pci/pci.c +++ b/trunk/arch/mips/pci/pci.c @@ -115,6 +115,7 @@ static void pcibios_scanbus(struct pci_controller *hose) pci_bus_assign_resources(bus); pci_enable_bridges(bus); } + bus->dev.of_node = hose->of_node; } } @@ -168,13 +169,6 @@ void pci_load_of_ranges(struct pci_controller *hose, struct device_node *node) } } } - -struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) -{ - struct pci_controller *hose = bus->sysdata; - - return of_node_get(hose->of_node); -} #endif static DEFINE_MUTEX(pci_scan_mutex); diff --git a/trunk/arch/x86/pci/common.c b/trunk/arch/x86/pci/common.c index 305c68b8d538..901177d75ff5 100644 --- a/trunk/arch/x86/pci/common.c +++ b/trunk/arch/x86/pci/common.c @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -171,16 +170,6 @@ void pcibios_fixup_bus(struct pci_bus *b) pcibios_fixup_device_resources(dev); } -void pcibios_add_bus(struct pci_bus *bus) -{ - acpi_pci_add_bus(bus); -} - -void pcibios_remove_bus(struct pci_bus *bus) -{ - acpi_pci_remove_bus(bus); -} - /* * Only use DMI information to set this if nothing was passed * on the kernel command line (which was parsed earlier). diff --git a/trunk/drivers/acpi/pci_root.c b/trunk/drivers/acpi/pci_root.c index b80e06e0b2d9..0ac546d5e53f 100644 --- a/trunk/drivers/acpi/pci_root.c +++ b/trunk/drivers/acpi/pci_root.c @@ -65,12 +65,44 @@ static struct acpi_scan_handler pci_root_handler = { .detach = acpi_pci_root_remove, }; -/* Lock to protect both acpi_pci_roots lists */ +/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ static DEFINE_MUTEX(acpi_pci_root_lock); static LIST_HEAD(acpi_pci_roots); +static LIST_HEAD(acpi_pci_drivers); static DEFINE_MUTEX(osc_lock); +int acpi_pci_register_driver(struct acpi_pci_driver *driver) +{ + int n = 0; + struct acpi_pci_root *root; + + mutex_lock(&acpi_pci_root_lock); + list_add_tail(&driver->node, &acpi_pci_drivers); + if (driver->add) + list_for_each_entry(root, &acpi_pci_roots, node) { + driver->add(root); + n++; + } + mutex_unlock(&acpi_pci_root_lock); + + return n; +} +EXPORT_SYMBOL(acpi_pci_register_driver); + +void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) +{ + struct acpi_pci_root *root; + + mutex_lock(&acpi_pci_root_lock); + list_del(&driver->node); + if (driver->remove) + list_for_each_entry(root, &acpi_pci_roots, node) + driver->remove(root); + mutex_unlock(&acpi_pci_root_lock); +} +EXPORT_SYMBOL(acpi_pci_unregister_driver); + /** * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge * @handle - the ACPI CA node in question. @@ -381,6 +413,7 @@ static int acpi_pci_root_add(struct acpi_device *device, acpi_status status; int result; struct acpi_pci_root *root; + struct acpi_pci_driver *driver; u32 flags, base_flags; bool is_osc_granted = false; @@ -540,6 +573,12 @@ static int acpi_pci_root_add(struct acpi_device *device, pci_assign_unassigned_bus_resources(root->bus); } + mutex_lock(&acpi_pci_root_lock); + list_for_each_entry(driver, &acpi_pci_drivers, node) + if (driver->add) + driver->add(root); + mutex_unlock(&acpi_pci_root_lock); + /* need to after hot-added ioapic is registered */ if (system_state != SYSTEM_BOOTING) pci_enable_bridges(root->bus); @@ -560,9 +599,16 @@ static int acpi_pci_root_add(struct acpi_device *device, static void acpi_pci_root_remove(struct acpi_device *device) { struct acpi_pci_root *root = acpi_driver_data(device); + struct acpi_pci_driver *driver; pci_stop_root_bus(root->bus); + mutex_lock(&acpi_pci_root_lock); + list_for_each_entry_reverse(driver, &acpi_pci_drivers, node) + if (driver->remove) + driver->remove(root); + mutex_unlock(&acpi_pci_root_lock); + device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); diff --git a/trunk/drivers/acpi/pci_slot.c b/trunk/drivers/acpi/pci_slot.c index 033d1179bdb5..cd1434eb1de8 100644 --- a/trunk/drivers/acpi/pci_slot.c +++ b/trunk/drivers/acpi/pci_slot.c @@ -9,9 +9,6 @@ * Copyright (C) 2007-2008 Hewlett-Packard Development Company, L.P. * Alex Chiang * - * Copyright (C) 2013 Huawei Tech. Co., Ltd. - * Jiang Liu - * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. @@ -31,9 +28,10 @@ #include #include #include -#include #include #include +#include +#include #include static bool debug; @@ -63,12 +61,20 @@ ACPI_MODULE_NAME("pci_slot"); #define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ struct acpi_pci_slot { + acpi_handle root_handle; /* handle of the root bridge */ struct pci_slot *pci_slot; /* corresponding pci_slot */ struct list_head list; /* node in the list of slots */ }; +static int acpi_pci_slot_add(struct acpi_pci_root *root); +static void acpi_pci_slot_remove(struct acpi_pci_root *root); + static LIST_HEAD(slot_list); static DEFINE_MUTEX(slot_list_lock); +static struct acpi_pci_driver acpi_pci_slot_driver = { + .add = acpi_pci_slot_add, + .remove = acpi_pci_slot_remove, +}; static int check_slot(acpi_handle handle, unsigned long long *sun) @@ -107,8 +113,21 @@ check_slot(acpi_handle handle, unsigned long long *sun) return device; } +struct callback_args { + acpi_walk_callback user_function; /* only for walk_p2p_bridge */ + struct pci_bus *pci_bus; + acpi_handle root_handle; +}; + /* - * Check whether handle has an associated slot and create PCI slot if it has. + * register_slot + * + * Called once for each SxFy object in the namespace. Don't worry about + * calling pci_create_slot multiple times for the same pci_bus:device, + * since each subsequent call simply bumps the refcount on the pci_slot. + * + * The number of calls to pci_destroy_slot from unregister_slot is + * symmetrical. */ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) @@ -118,22 +137,13 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) char name[SLOT_NAME_SIZE]; struct acpi_pci_slot *slot; struct pci_slot *pci_slot; - struct pci_bus *pci_bus = context; + struct callback_args *parent_context = context; + struct pci_bus *pci_bus = parent_context->pci_bus; device = check_slot(handle, &sun); if (device < 0) return AE_OK; - /* - * There may be multiple PCI functions associated with the same slot. - * Check whether PCI slot has already been created for this PCI device. - */ - list_for_each_entry(slot, &slot_list, list) { - pci_slot = slot->pci_slot; - if (pci_slot->bus == pci_bus && pci_slot->number == device) - return AE_OK; - } - slot = kmalloc(sizeof(*slot), GFP_KERNEL); if (!slot) { err("%s: cannot allocate memory\n", __func__); @@ -148,8 +158,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } + slot->root_handle = parent_context->root_handle; slot->pci_slot = pci_slot; + INIT_LIST_HEAD(&slot->list); + mutex_lock(&slot_list_lock); list_add(&slot->list, &slot_list); + mutex_unlock(&slot_list_lock); get_device(&pci_bus->dev); @@ -159,24 +173,131 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle) +/* + * walk_p2p_bridge - discover and walk p2p bridges + * @handle: points to an acpi_pci_root + * @context: p2p_bridge_context pointer + * + * Note that when we call ourselves recursively, we pass a different + * value of pci_bus in the child_context. + */ +static acpi_status +walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) { - mutex_lock(&slot_list_lock); - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, - register_slot, NULL, bus, NULL); - mutex_unlock(&slot_list_lock); + int device, function; + unsigned long long adr; + acpi_status status; + acpi_handle dummy_handle; + acpi_walk_callback user_function; + + struct pci_dev *dev; + struct pci_bus *pci_bus; + struct callback_args child_context; + struct callback_args *parent_context = context; + + pci_bus = parent_context->pci_bus; + user_function = parent_context->user_function; + + status = acpi_get_handle(handle, "_ADR", &dummy_handle); + if (ACPI_FAILURE(status)) + return AE_OK; + + status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); + if (ACPI_FAILURE(status)) + return AE_OK; + + device = (adr >> 16) & 0xffff; + function = adr & 0xffff; + + dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function)); + if (!dev || !dev->subordinate) + goto out; + + child_context.pci_bus = dev->subordinate; + child_context.user_function = user_function; + child_context.root_handle = parent_context->root_handle; + + dbg("p2p bridge walk, pci_bus = %x\n", dev->subordinate->number); + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + user_function, NULL, &child_context, NULL); + if (ACPI_FAILURE(status)) + goto out; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + walk_p2p_bridge, NULL, &child_context, NULL); +out: + pci_dev_put(dev); + return AE_OK; +} + +/* + * walk_root_bridge - generic root bridge walker + * @root: poiner of an acpi_pci_root + * @user_function: user callback for slot objects + * + * Call user_function for all objects underneath this root bridge. + * Walk p2p bridges underneath us and call user_function on those too. + */ +static int +walk_root_bridge(struct acpi_pci_root *root, acpi_walk_callback user_function) +{ + acpi_status status; + acpi_handle handle = root->device->handle; + struct pci_bus *pci_bus = root->bus; + struct callback_args context; + + context.pci_bus = pci_bus; + context.user_function = user_function; + context.root_handle = handle; + + dbg("root bridge walk, pci_bus = %x\n", pci_bus->number); + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + user_function, NULL, &context, NULL); + if (ACPI_FAILURE(status)) + return status; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + walk_p2p_bridge, NULL, &context, NULL); + if (ACPI_FAILURE(status)) + err("%s: walk_p2p_bridge failure - %d\n", __func__, status); + + return status; } -void acpi_pci_slot_remove(struct pci_bus *bus) +/* + * acpi_pci_slot_add + * @handle: points to an acpi_pci_root + */ +static int +acpi_pci_slot_add(struct acpi_pci_root *root) +{ + acpi_status status; + + status = walk_root_bridge(root, register_slot); + if (ACPI_FAILURE(status)) + err("%s: register_slot failure - %d\n", __func__, status); + + return status; +} + +/* + * acpi_pci_slot_remove + * @handle: points to an acpi_pci_root + */ +static void +acpi_pci_slot_remove(struct acpi_pci_root *root) { struct acpi_pci_slot *slot, *tmp; + struct pci_bus *pbus; + acpi_handle handle = root->device->handle; mutex_lock(&slot_list_lock); list_for_each_entry_safe(slot, tmp, &slot_list, list) { - if (slot->pci_slot->bus == bus) { + if (slot->root_handle == handle) { list_del(&slot->list); + pbus = slot->pci_slot->bus; pci_destroy_slot(slot->pci_slot); - put_device(&bus->dev); + put_device(&pbus->dev); kfree(slot); } } @@ -211,4 +332,5 @@ static struct dmi_system_id acpi_pci_slot_dmi_table[] __initdata = { void __init acpi_pci_slot_init(void) { dmi_check_system(acpi_pci_slot_dmi_table); + acpi_pci_register_driver(&acpi_pci_slot_driver); } diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index f54d1985e594..5e7e991717d7 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -1790,6 +1790,7 @@ int __init acpi_scan_init(void) acpi_platform_init(); acpi_csrt_init(); acpi_container_init(); + acpi_pci_slot_init(); mutex_lock(&acpi_scan_lock); /* diff --git a/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c index 616952facd6e..a99112cfd8b1 100644 --- a/trunk/drivers/ata/ahci.c +++ b/trunk/drivers/ata/ahci.c @@ -413,17 +413,17 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* Marvell */ { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), + { PCI_DEVICE(0x1b4b, 0x9123), .class = PCI_CLASS_STORAGE_SATA_AHCI, .class_mask = 0xffffff, .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), + { PCI_DEVICE(0x1b4b, 0x9125), .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), + { PCI_DEVICE(0x1b4b, 0x917a), .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), + { PCI_DEVICE(0x1b4b, 0x9192), .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), + { PCI_DEVICE(0x1b4b, 0x91a3), .driver_data = board_ahci_yes_fbs }, /* Promise */ diff --git a/trunk/drivers/eisa/eisa-bus.c b/trunk/drivers/eisa/eisa-bus.c index 272a3ec35957..806c77bfd434 100644 --- a/trunk/drivers/eisa/eisa-bus.c +++ b/trunk/drivers/eisa/eisa-bus.c @@ -275,18 +275,19 @@ static int __init eisa_request_resources(struct eisa_root_device *root, } if (slot) { + edev->res[i].name = NULL; edev->res[i].start = SLOT_ADDRESS(root, slot) + (i * 0x400); edev->res[i].end = edev->res[i].start + 0xff; edev->res[i].flags = IORESOURCE_IO; } else { + edev->res[i].name = NULL; edev->res[i].start = SLOT_ADDRESS(root, slot) + EISA_VENDOR_ID_OFFSET; edev->res[i].end = edev->res[i].start + 3; - edev->res[i].flags = IORESOURCE_IO | IORESOURCE_BUSY; + edev->res[i].flags = IORESOURCE_BUSY; } - dev_printk(KERN_DEBUG, &edev->dev, "%pR\n", &edev->res[i]); if (request_resource(root->res, &edev->res[i])) goto failed; } @@ -313,40 +314,41 @@ static int __init eisa_probe(struct eisa_root_device *root) { int i, c; struct eisa_device *edev; - char *enabled_str; - dev_info(root->dev, "Probing EISA bus %d\n", root->bus_nr); + printk(KERN_INFO "EISA: Probing bus %d at %s\n", + root->bus_nr, dev_name(root->dev)); /* First try to get hold of slot 0. If there is no device * here, simply fail, unless root->force_probe is set. */ edev = kzalloc(sizeof(*edev), GFP_KERNEL); if (!edev) { - dev_err(root->dev, "EISA: Couldn't allocate mainboard slot\n"); + printk(KERN_ERR "EISA: Couldn't allocate mainboard slot\n"); return -ENOMEM; } - if (eisa_init_device(root, edev, 0)) { + if (eisa_request_resources(root, edev, 0)) { + printk(KERN_WARNING \ + "EISA: Cannot allocate resource for mainboard\n"); kfree(edev); if (!root->force_probe) - return -ENODEV; + return -EBUSY; goto force_probe; } - if (eisa_request_resources(root, edev, 0)) { - dev_warn(root->dev, - "EISA: Cannot allocate resource for mainboard\n"); + if (eisa_init_device(root, edev, 0)) { + eisa_release_resources(edev); kfree(edev); if (!root->force_probe) - return -EBUSY; + return -ENODEV; goto force_probe; } - dev_info(&edev->dev, "EISA: Mainboard %s detected\n", edev->id.sig); + printk(KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig); if (eisa_register_device(edev)) { - dev_err(&edev->dev, "EISA: Failed to register %s\n", - edev->id.sig); + printk(KERN_ERR "EISA: Failed to register %s\n", + edev->id.sig); eisa_release_resources(edev); kfree(edev); } @@ -356,47 +358,55 @@ static int __init eisa_probe(struct eisa_root_device *root) for (c = 0, i = 1; i <= root->slots; i++) { edev = kzalloc(sizeof(*edev), GFP_KERNEL); if (!edev) { - dev_err(root->dev, "EISA: Out of memory for slot %d\n", - i); + printk(KERN_ERR "EISA: Out of memory for slot %d\n", i); continue; } - if (eisa_init_device(root, edev, i)) { + if (eisa_request_resources(root, edev, i)) { + printk(KERN_WARNING \ + "Cannot allocate resource for EISA slot %d\n", + i); kfree(edev); continue; } - if (eisa_request_resources(root, edev, i)) { - dev_warn(root->dev, - "Cannot allocate resource for EISA slot %d\n", - i); + if (eisa_init_device(root, edev, i)) { + eisa_release_resources(edev); kfree(edev); continue; } - - if (edev->state == (EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED)) - enabled_str = " (forced enabled)"; - else if (edev->state == EISA_CONFIG_FORCED) - enabled_str = " (forced disabled)"; - else if (edev->state == 0) - enabled_str = " (disabled)"; - else - enabled_str = ""; - - dev_info(&edev->dev, "EISA: slot %d: %s detected%s\n", i, - edev->id.sig, enabled_str); + + printk(KERN_INFO "EISA: slot %d : %s detected", + i, edev->id.sig); + + switch (edev->state) { + case EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED: + printk(" (forced enabled)"); + break; + + case EISA_CONFIG_FORCED: + printk(" (forced disabled)"); + break; + + case 0: + printk(" (disabled)"); + break; + } + + printk (".\n"); c++; if (eisa_register_device(edev)) { - dev_err(&edev->dev, "EISA: Failed to register %s\n", - edev->id.sig); + printk(KERN_ERR "EISA: Failed to register %s\n", + edev->id.sig); eisa_release_resources(edev); kfree(edev); } } - dev_info(root->dev, "EISA: Detected %d card%s\n", c, c == 1 ? "" : "s"); + printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s"); + return 0; } diff --git a/trunk/drivers/eisa/pci_eisa.c b/trunk/drivers/eisa/pci_eisa.c index 0d42ea791060..cdae207028a7 100644 --- a/trunk/drivers/eisa/pci_eisa.c +++ b/trunk/drivers/eisa/pci_eisa.c @@ -25,7 +25,8 @@ static int __init pci_eisa_init(struct pci_dev *pdev, int rc; if ((rc = pci_enable_device (pdev))) { - dev_err(&pdev->dev, "Could not enable device\n"); + printk (KERN_ERR "pci_eisa : Could not enable device %s\n", + pci_name(pdev)); return rc; } @@ -37,7 +38,7 @@ static int __init pci_eisa_init(struct pci_dev *pdev, dev_set_drvdata(pci_eisa_root.dev, &pci_eisa_root); if (eisa_root_register (&pci_eisa_root)) { - dev_err(&pdev->dev, "Could not register EISA root\n"); + printk (KERN_ERR "pci_eisa : Could not register EISA root\n"); return -1; } diff --git a/trunk/drivers/iommu/amd_iommu.c b/trunk/drivers/iommu/amd_iommu.c index e046d7acca84..98f555dafb55 100644 --- a/trunk/drivers/iommu/amd_iommu.c +++ b/trunk/drivers/iommu/amd_iommu.c @@ -173,7 +173,7 @@ static inline u16 get_device_id(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - return PCI_DEVID(pdev->bus->number, pdev->devfn); + return calc_devid(pdev->bus->number, pdev->devfn); } static struct iommu_dev_data *get_dev_data(struct device *dev) @@ -649,26 +649,26 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt) case EVENT_TYPE_ILL_DEV: printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x " "address=0x%016llx flags=0x%04x]\n", - PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), address, flags); dump_dte_entry(devid); break; case EVENT_TYPE_IO_FAULT: printk("IO_PAGE_FAULT device=%02x:%02x.%x " "domain=0x%04x address=0x%016llx flags=0x%04x]\n", - PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), domid, address, flags); break; case EVENT_TYPE_DEV_TAB_ERR: printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x " "address=0x%016llx flags=0x%04x]\n", - PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), address, flags); break; case EVENT_TYPE_PAGE_TAB_ERR: printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x " "domain=0x%04x address=0x%016llx flags=0x%04x]\n", - PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), domid, address, flags); break; case EVENT_TYPE_ILL_CMD: @@ -682,13 +682,13 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt) case EVENT_TYPE_IOTLB_INV_TO: printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x " "address=0x%016llx]\n", - PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), address); break; case EVENT_TYPE_INV_DEV_REQ: printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x " "address=0x%016llx flags=0x%04x]\n", - PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), address, flags); break; default: diff --git a/trunk/drivers/iommu/amd_iommu_init.c b/trunk/drivers/iommu/amd_iommu_init.c index 551768af3fe7..b6ecddb63cd0 100644 --- a/trunk/drivers/iommu/amd_iommu_init.c +++ b/trunk/drivers/iommu/amd_iommu_init.c @@ -406,7 +406,7 @@ static int __init find_last_devid_on_pci(int bus, int dev, int fn, int cap_ptr) u32 cap; cap = read_pci_config(bus, dev, fn, cap_ptr+MMIO_RANGE_OFFSET); - update_last_devid(PCI_DEVID(MMIO_GET_BUS(cap), MMIO_GET_LD(cap))); + update_last_devid(calc_devid(MMIO_GET_BUS(cap), MMIO_GET_LD(cap))); return 0; } @@ -423,7 +423,7 @@ static int __init find_last_devid_from_ivhd(struct ivhd_header *h) p += sizeof(*h); end += h->length; - find_last_devid_on_pci(PCI_BUS_NUM(h->devid), + find_last_devid_on_pci(PCI_BUS(h->devid), PCI_SLOT(h->devid), PCI_FUNC(h->devid), h->cap_ptr); @@ -784,10 +784,10 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_ALL\t\t\t first devid: %02x:%02x.%x" " last device %02x:%02x.%x flags: %02x\n", - PCI_BUS_NUM(iommu->first_device), + PCI_BUS(iommu->first_device), PCI_SLOT(iommu->first_device), PCI_FUNC(iommu->first_device), - PCI_BUS_NUM(iommu->last_device), + PCI_BUS(iommu->last_device), PCI_SLOT(iommu->last_device), PCI_FUNC(iommu->last_device), e->flags); @@ -801,7 +801,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_SELECT\t\t\t devid: %02x:%02x.%x " "flags: %02x\n", - PCI_BUS_NUM(e->devid), + PCI_BUS(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags); @@ -813,7 +813,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_SELECT_RANGE_START\t " "devid: %02x:%02x.%x flags: %02x\n", - PCI_BUS_NUM(e->devid), + PCI_BUS(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags); @@ -827,11 +827,11 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_ALIAS\t\t\t devid: %02x:%02x.%x " "flags: %02x devid_to: %02x:%02x.%x\n", - PCI_BUS_NUM(e->devid), + PCI_BUS(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags, - PCI_BUS_NUM(e->ext >> 8), + PCI_BUS(e->ext >> 8), PCI_SLOT(e->ext >> 8), PCI_FUNC(e->ext >> 8)); @@ -846,11 +846,11 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_ALIAS_RANGE\t\t " "devid: %02x:%02x.%x flags: %02x " "devid_to: %02x:%02x.%x\n", - PCI_BUS_NUM(e->devid), + PCI_BUS(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags, - PCI_BUS_NUM(e->ext >> 8), + PCI_BUS(e->ext >> 8), PCI_SLOT(e->ext >> 8), PCI_FUNC(e->ext >> 8)); @@ -864,7 +864,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_EXT_SELECT\t\t devid: %02x:%02x.%x " "flags: %02x ext: %08x\n", - PCI_BUS_NUM(e->devid), + PCI_BUS(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags, e->ext); @@ -877,7 +877,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_EXT_SELECT_RANGE\t devid: " "%02x:%02x.%x flags: %02x ext: %08x\n", - PCI_BUS_NUM(e->devid), + PCI_BUS(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags, e->ext); @@ -890,7 +890,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, case IVHD_DEV_RANGE_END: DUMP_printk(" DEV_RANGE_END\t\t devid: %02x:%02x.%x\n", - PCI_BUS_NUM(e->devid), + PCI_BUS(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid)); @@ -924,7 +924,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_SPECIAL(%s[%d])\t\tdevid: %02x:%02x.%x\n", var, (int)handle, - PCI_BUS_NUM(devid), + PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid)); @@ -1086,7 +1086,7 @@ static int __init init_iommu_all(struct acpi_table_header *table) DUMP_printk("device: %02x:%02x.%01x cap: %04x " "seg: %d flags: %01x info %04x\n", - PCI_BUS_NUM(h->devid), PCI_SLOT(h->devid), + PCI_BUS(h->devid), PCI_SLOT(h->devid), PCI_FUNC(h->devid), h->cap_ptr, h->pci_seg, h->flags, h->info); DUMP_printk(" mmio-addr: %016llx\n", @@ -1116,7 +1116,7 @@ static int iommu_init_pci(struct amd_iommu *iommu) int cap_ptr = iommu->cap_ptr; u32 range, misc, low, high; - iommu->dev = pci_get_bus_and_slot(PCI_BUS_NUM(iommu->devid), + iommu->dev = pci_get_bus_and_slot(PCI_BUS(iommu->devid), iommu->devid & 0xff); if (!iommu->dev) return -ENODEV; @@ -1128,9 +1128,9 @@ static int iommu_init_pci(struct amd_iommu *iommu) pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET, &misc); - iommu->first_device = PCI_DEVID(MMIO_GET_BUS(range), + iommu->first_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_FD(range)); - iommu->last_device = PCI_DEVID(MMIO_GET_BUS(range), + iommu->last_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_LD(range)); if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB))) @@ -1388,8 +1388,8 @@ static int __init init_unity_map_range(struct ivmd_header *m) DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x" " range_start: %016llx range_end: %016llx flags: %x\n", s, - PCI_BUS_NUM(e->devid_start), PCI_SLOT(e->devid_start), - PCI_FUNC(e->devid_start), PCI_BUS_NUM(e->devid_end), + PCI_BUS(e->devid_start), PCI_SLOT(e->devid_start), + PCI_FUNC(e->devid_start), PCI_BUS(e->devid_end), PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end), e->address_start, e->address_end, m->flags); diff --git a/trunk/drivers/iommu/amd_iommu_types.h b/trunk/drivers/iommu/amd_iommu_types.h index ec36cf63e0ca..e38ab438bb34 100644 --- a/trunk/drivers/iommu/amd_iommu_types.h +++ b/trunk/drivers/iommu/amd_iommu_types.h @@ -24,7 +24,6 @@ #include #include #include -#include /* * Maximum number of IOMMUs supported @@ -316,6 +315,9 @@ #define MAX_DOMAIN_ID 65536 +/* FIXME: move this macro to */ +#define PCI_BUS(x) (((x) >> 8) & 0xff) + /* Protection domain flags */ #define PD_DMA_OPS_MASK (1UL << 0) /* domain used for dma_ops */ #define PD_DEFAULT_MASK (1UL << 1) /* domain is a default dma_ops @@ -701,6 +703,13 @@ extern int amd_iommu_max_glx_val; */ extern void iommu_flush_all_caches(struct amd_iommu *iommu); +/* takes bus and device/function and returns the device id + * FIXME: should that be in generic PCI code? */ +static inline u16 calc_devid(u8 bus, u8 devfn) +{ + return (((u16)bus) << 8) | devfn; +} + static inline int get_ioapic_devid(int id) { struct devid_map *entry; diff --git a/trunk/drivers/pci/bus.c b/trunk/drivers/pci/bus.c index bdc1e8bf7e60..8647dc6f52d0 100644 --- a/trunk/drivers/pci/bus.c +++ b/trunk/drivers/pci/bus.c @@ -206,9 +206,16 @@ void pci_bus_add_devices(const struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) { BUG_ON(!dev->is_added); + child = dev->subordinate; - if (child) - pci_bus_add_devices(child); + + if (!child) + continue; + pci_bus_add_devices(child); + + if (child->is_added) + continue; + child->is_added = 1; } } diff --git a/trunk/drivers/pci/hotplug/Kconfig b/trunk/drivers/pci/hotplug/Kconfig index 9fcb87f353d4..13e9e63a7266 100644 --- a/trunk/drivers/pci/hotplug/Kconfig +++ b/trunk/drivers/pci/hotplug/Kconfig @@ -52,12 +52,15 @@ config HOTPLUG_PCI_IBM When in doubt, say N. config HOTPLUG_PCI_ACPI - bool "ACPI PCI Hotplug driver" - depends on HOTPLUG_PCI=y && ((!ACPI_DOCK && ACPI) || (ACPI_DOCK)) + tristate "ACPI PCI Hotplug driver" + depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK) help Say Y here if you have a system that supports PCI Hotplug using ACPI. + To compile this driver as a module, choose M here: the + module will be called acpiphp. + When in doubt, say N. config HOTPLUG_PCI_ACPI_IBM diff --git a/trunk/drivers/pci/hotplug/acpiphp.h b/trunk/drivers/pci/hotplug/acpiphp.h index 6a319f42b30c..b70ac00a117e 100644 --- a/trunk/drivers/pci/hotplug/acpiphp.h +++ b/trunk/drivers/pci/hotplug/acpiphp.h @@ -73,9 +73,8 @@ static inline const char *slot_name(struct slot *slot) */ struct acpiphp_bridge { struct list_head list; - struct list_head slots; - struct kref ref; acpi_handle handle; + struct acpiphp_slot *slots; /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ struct acpiphp_func *func; @@ -98,7 +97,7 @@ struct acpiphp_bridge { * PCI slot information for each *physical* PCI slot */ struct acpiphp_slot { - struct list_head node; + struct acpiphp_slot *next; struct acpiphp_bridge *bridge; /* parent */ struct list_head funcs; /* one slot may have different objects (i.e. for each function) */ @@ -120,6 +119,7 @@ struct acpiphp_slot { */ struct acpiphp_func { struct acpiphp_slot *slot; /* parent */ + struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */ struct list_head sibling; struct notifier_block nb; @@ -146,6 +146,10 @@ struct acpiphp_attention_info #define ACPI_PCI_HOST_HID "PNP0A03" /* ACPI _STA method value (ignore bit 4; battery present) */ +#define ACPI_STA_PRESENT (0x00000001) +#define ACPI_STA_ENABLED (0x00000002) +#define ACPI_STA_SHOW_IN_UI (0x00000004) +#define ACPI_STA_FUNCTIONING (0x00000008) #define ACPI_STA_ALL (0x0000000f) /* bridge flags */ @@ -176,6 +180,8 @@ extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); /* acpiphp_glue.c */ +extern int acpiphp_glue_init (void); +extern void acpiphp_glue_exit (void); typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); extern int acpiphp_enable_slot (struct acpiphp_slot *slot); @@ -188,6 +194,5 @@ extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); /* variables */ extern bool acpiphp_debug; -extern bool acpiphp_disabled; #endif /* _ACPIPHP_H */ diff --git a/trunk/drivers/pci/hotplug/acpiphp_core.c b/trunk/drivers/pci/hotplug/acpiphp_core.c index ca8127950fcd..c2fd3095701f 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_core.c +++ b/trunk/drivers/pci/hotplug/acpiphp_core.c @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -49,7 +48,6 @@ #define SLOT_NAME_SIZE 21 /* {_SUN} */ bool acpiphp_debug; -bool acpiphp_disabled; /* local variables */ static struct acpiphp_attention_info *attention_info; @@ -62,9 +60,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); -MODULE_PARM_DESC(disable, "disable acpiphp driver"); module_param_named(debug, acpiphp_debug, bool, 0644); -module_param_named(disable, acpiphp_disabled, bool, 0444); /* export the attention callback registration methods */ EXPORT_SYMBOL_GPL(acpiphp_register_attention); @@ -355,9 +351,27 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) } -void __init acpiphp_init(void) +static int __init acpiphp_init(void) { - info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n", - acpiphp_disabled ? ", disabled by user; please report a bug" - : ""); + info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + + if (acpi_pci_disabled) + return 0; + + /* read all the ACPI info from the system */ + /* initialize internal data structure etc. */ + return acpiphp_glue_init(); +} + + +static void __exit acpiphp_exit(void) +{ + if (acpi_pci_disabled) + return; + + /* deallocate internal data structures etc. */ + acpiphp_glue_exit(); } + +module_init(acpiphp_init); +module_exit(acpiphp_exit); diff --git a/trunk/drivers/pci/hotplug/acpiphp_glue.c b/trunk/drivers/pci/hotplug/acpiphp_glue.c index 96fed19c6d90..270fdbadc19c 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_glue.c +++ b/trunk/drivers/pci/hotplug/acpiphp_glue.c @@ -54,7 +54,6 @@ #include "acpiphp.h" static LIST_HEAD(bridge_list); -static DEFINE_MUTEX(bridge_mutex); #define MY_NAME "acpiphp_glue" @@ -62,7 +61,6 @@ static void handle_hotplug_event_bridge (acpi_handle, u32, void *); static void acpiphp_sanitize_bus(struct pci_bus *bus); static void acpiphp_set_hpp_values(struct pci_bus *bus); static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); -static void free_bridge(struct kref *kref); /* callback routine to check for the existence of a pci dock device */ static acpi_status @@ -78,39 +76,6 @@ is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) } } -static inline void get_bridge(struct acpiphp_bridge *bridge) -{ - kref_get(&bridge->ref); -} - -static inline void put_bridge(struct acpiphp_bridge *bridge) -{ - kref_put(&bridge->ref, free_bridge); -} - -static void free_bridge(struct kref *kref) -{ - struct acpiphp_bridge *bridge; - struct acpiphp_slot *slot, *next; - struct acpiphp_func *func, *tmp; - - bridge = container_of(kref, struct acpiphp_bridge, ref); - - list_for_each_entry_safe(slot, next, &bridge->slots, node) { - list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { - kfree(func); - } - kfree(slot); - } - - /* Release reference acquired by acpiphp_bridge_handle_to_function() */ - if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) - put_bridge(bridge->func->slot->bridge); - put_device(&bridge->pci_bus->dev); - pci_dev_put(bridge->pci_dev); - kfree(bridge); -} - /* * the _DCK method can do funny things... and sometimes not * hah-hah funny. @@ -189,10 +154,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) acpi_handle tmp; acpi_status status = AE_OK; unsigned long long adr, sun; - int device, function, retval, found = 0; + int device, function, retval; struct pci_bus *pbus = bridge->pci_bus; struct pci_dev *pdev; - u32 val; if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) return AE_OK; @@ -206,7 +170,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) device = (adr >> 16) & 0xffff; function = adr & 0xffff; - pdev = bridge->pci_dev; + pdev = pbus->self; if (pdev && device_is_managed_by_native_pciehp(pdev)) return AE_OK; @@ -214,6 +178,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) if (!newfunc) return AE_NO_MEMORY; + INIT_LIST_HEAD(&newfunc->sibling); newfunc->handle = handle; newfunc->function = function; @@ -242,15 +207,14 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) } /* search for objects that share the same slot */ - list_for_each_entry(slot, &bridge->slots, node) + for (slot = bridge->slots; slot; slot = slot->next) if (slot->device == device) { if (slot->sun != sun) warn("sibling found, but _SUN doesn't match!\n"); - found = 1; break; } - if (!found) { + if (!slot) { slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); if (!slot) { kfree(newfunc); @@ -263,9 +227,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) INIT_LIST_HEAD(&slot->funcs); mutex_init(&slot->crit_sect); - mutex_lock(&bridge_mutex); - list_add_tail(&slot->node, &bridge->slots); - mutex_unlock(&bridge_mutex); + slot->next = bridge->slots; + bridge->slots = slot; + bridge->nr_slots++; dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", @@ -283,13 +247,13 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) } newfunc->slot = slot; - mutex_lock(&bridge_mutex); list_add_tail(&newfunc->sibling, &slot->funcs); - mutex_unlock(&bridge_mutex); - if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function), - &val, 60*1000)) + pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); + if (pdev) { slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); + pci_dev_put(pdev); + } if (is_dock_device(handle)) { /* we don't want to call this device's _EJ0 @@ -326,9 +290,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) err_exit: bridge->nr_slots--; - mutex_lock(&bridge_mutex); - list_del(&slot->node); - mutex_unlock(&bridge_mutex); + bridge->slots = slot->next; kfree(slot); kfree(newfunc); @@ -353,17 +315,13 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) acpi_status status; /* must be added to the list prior to calling register_slot */ - mutex_lock(&bridge_mutex); list_add(&bridge->list, &bridge_list); - mutex_unlock(&bridge_mutex); /* register all slot objects under this bridge */ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, register_slot, NULL, bridge, NULL); if (ACPI_FAILURE(status)) { - mutex_lock(&bridge_mutex); list_del(&bridge->list); - mutex_unlock(&bridge_mutex); return; } @@ -393,46 +351,178 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle { struct acpiphp_bridge *bridge; struct acpiphp_slot *slot; - struct acpiphp_func *func = NULL; + struct acpiphp_func *func; - mutex_lock(&bridge_mutex); list_for_each_entry(bridge, &bridge_list, list) { - list_for_each_entry(slot, &bridge->slots, node) { + for (slot = bridge->slots; slot; slot = slot->next) { list_for_each_entry(func, &slot->funcs, sibling) { - if (func->handle == handle) { - get_bridge(func->slot->bridge); - mutex_unlock(&bridge_mutex); + if (func->handle == handle) return func; - } } } } - mutex_unlock(&bridge_mutex); return NULL; } +static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) +{ + acpi_handle dummy_handle; + struct acpiphp_func *func; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_EJ0", &dummy_handle))) { + bridge->flags |= BRIDGE_HAS_EJ0; + + dbg("found ejectable p2p bridge\n"); + + /* make link between PCI bridge and PCI function */ + func = acpiphp_bridge_handle_to_function(bridge->handle); + if (!func) + return; + bridge->func = func; + func->bridge = bridge; + } +} + + +/* allocate and initialize host bridge data structure */ +static void add_host_bridge(struct acpi_pci_root *root) +{ + struct acpiphp_bridge *bridge; + acpi_handle handle = root->device->handle; + + bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + if (bridge == NULL) + return; + + bridge->handle = handle; + + bridge->pci_bus = root->bus; + + init_bridge_misc(bridge); +} + + +/* allocate and initialize PCI-to-PCI bridge data structure */ +static void add_p2p_bridge(acpi_handle *handle) +{ + struct acpiphp_bridge *bridge; + + bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + if (bridge == NULL) { + err("out of memory\n"); + return; + } + + bridge->handle = handle; + config_p2p_bridge_flags(bridge); + + bridge->pci_dev = acpi_get_pci_dev(handle); + bridge->pci_bus = bridge->pci_dev->subordinate; + if (!bridge->pci_bus) { + err("This is not a PCI-to-PCI bridge!\n"); + goto err; + } + + /* + * Grab a ref to the subordinate PCI bus in case the bus is + * removed via PCI core logical hotplug. The ref pins the bus + * (which we access during module unload). + */ + get_device(&bridge->pci_bus->dev); + + init_bridge_misc(bridge); + return; + err: + pci_dev_put(bridge->pci_dev); + kfree(bridge); + return; +} + + +/* callback routine to find P2P bridges */ +static acpi_status +find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + acpi_status status; + struct pci_dev *dev; + + dev = acpi_get_pci_dev(handle); + if (!dev || !dev->subordinate) + goto out; + + /* check if this bridge has ejectable slots */ + if ((detect_ejectable_slots(handle) > 0)) { + dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); + add_p2p_bridge(handle); + } + + /* search P2P bridges under this p2p bridge */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + find_p2p_bridge, NULL, NULL, NULL); + if (ACPI_FAILURE(status)) + warn("find_p2p_bridge failed (error code = 0x%x)\n", status); + + out: + pci_dev_put(dev); + return AE_OK; +} + + +/* find hot-pluggable slots, and then find P2P bridge */ +static int add_bridge(struct acpi_pci_root *root) +{ + acpi_status status; + unsigned long long tmp; + acpi_handle dummy_handle; + acpi_handle handle = root->device->handle; + + /* if the bridge doesn't have _STA, we assume it is always there */ + status = acpi_get_handle(handle, "_STA", &dummy_handle); + if (ACPI_SUCCESS(status)) { + status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); + if (ACPI_FAILURE(status)) { + dbg("%s: _STA evaluation failure\n", __func__); + return 0; + } + if ((tmp & ACPI_STA_FUNCTIONING) == 0) + /* don't register this object */ + return 0; + } + + /* check if this bridge has ejectable slots */ + if (detect_ejectable_slots(handle) > 0) { + dbg("found PCI host-bus bridge with hot-pluggable slots\n"); + add_host_bridge(root); + } + + /* search P2P bridges under this host bridge */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + find_p2p_bridge, NULL, NULL, NULL); + + if (ACPI_FAILURE(status)) + warn("find_p2p_bridge failed (error code = 0x%x)\n", status); + + return 0; +} + static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) { struct acpiphp_bridge *bridge; - mutex_lock(&bridge_mutex); list_for_each_entry(bridge, &bridge_list, list) - if (bridge->handle == handle) { - get_bridge(bridge); - mutex_unlock(&bridge_mutex); + if (bridge->handle == handle) return bridge; - } - mutex_unlock(&bridge_mutex); return NULL; } static void cleanup_bridge(struct acpiphp_bridge *bridge) { - struct acpiphp_slot *slot; - struct acpiphp_func *func; + struct acpiphp_slot *slot, *next; + struct acpiphp_func *func, *tmp; acpi_status status; acpi_handle handle = bridge->handle; @@ -453,8 +543,10 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) err("failed to install interrupt notify handler\n"); } - list_for_each_entry(slot, &bridge->slots, node) { - list_for_each_entry(func, &slot->funcs, sibling) { + slot = bridge->slots; + while (slot) { + 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); @@ -466,13 +558,63 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) if (ACPI_FAILURE(status)) err("failed to remove notify handler\n"); } + list_del(&func->sibling); + kfree(func); } acpiphp_unregister_hotplug_slot(slot); + list_del(&slot->funcs); + kfree(slot); + slot = next; } - mutex_lock(&bridge_mutex); + /* + * Only P2P bridges have a pci_dev + */ + if (bridge->pci_dev) + put_device(&bridge->pci_bus->dev); + + pci_dev_put(bridge->pci_dev); list_del(&bridge->list); - mutex_unlock(&bridge_mutex); + kfree(bridge); +} + +static acpi_status +cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + struct acpiphp_bridge *bridge; + + /* cleanup p2p bridges under this P2P bridge + in a depth-first manner */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + cleanup_p2p_bridge, NULL, NULL, NULL); + + bridge = acpiphp_handle_to_bridge(handle); + if (bridge) + cleanup_bridge(bridge); + + return AE_OK; +} + +static void remove_bridge(struct acpi_pci_root *root) +{ + struct acpiphp_bridge *bridge; + acpi_handle handle = root->device->handle; + + /* cleanup p2p bridges under this host bridge + in a depth-first manner */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, + (u32)1, cleanup_p2p_bridge, NULL, NULL, NULL); + + /* + * On root bridges with hotplug slots directly underneath (ie, + * no p2p bridge between), we call cleanup_bridge(). + * + * The else clause cleans up root bridges that either had no + * hotplug slots at all, or had a p2p bridge underneath. + */ + bridge = acpiphp_handle_to_bridge(handle); + if (bridge) + cleanup_bridge(bridge); } static int power_on_slot(struct acpiphp_slot *slot) @@ -656,7 +798,6 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) } } } - /** * enable_device - enable, configure a slot * @slot: slot to be enabled @@ -669,7 +810,9 @@ static int __ref enable_device(struct acpiphp_slot *slot) struct pci_dev *dev; struct pci_bus *bus = slot->bridge->pci_bus; struct acpiphp_func *func; + int retval = 0; int num, max, pass; + acpi_status status; if (slot->flags & SLOT_ENABLED) goto err_exit; @@ -724,11 +867,23 @@ static int __ref enable_device(struct acpiphp_slot *slot) slot->flags &= (~SLOT_ENABLED); continue; } + + if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && + dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) { + pci_dev_put(dev); + continue; + } + + status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); + if (ACPI_FAILURE(status)) + warn("find_p2p_bridge failed (error code = 0x%x)\n", + status); + pci_dev_put(dev); } err_exit: - return 0; + return retval; } /* return first device in slot, acquiring a reference on it */ @@ -757,6 +912,23 @@ static int disable_device(struct acpiphp_slot *slot) { struct acpiphp_func *func; struct pci_dev *pdev; + struct pci_bus *bus = slot->bridge->pci_bus; + + /* The slot will be enabled when func 0 is added, so check + func 0 before disable the slot. */ + pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0)); + if (!pdev) + goto err_exit; + pci_dev_put(pdev); + + list_for_each_entry(func, &slot->funcs, sibling) { + if (func->bridge) { + /* cleanup p2p bridges under this P2P bridge */ + cleanup_p2p_bridge(func->bridge->handle, + (u32)1, NULL, NULL); + func->bridge = NULL; + } + } /* * enable_device() enumerates all functions in this device via @@ -775,6 +947,7 @@ static int disable_device(struct acpiphp_slot *slot) slot->flags &= (~SLOT_ENABLED); +err_exit: return 0; } @@ -864,7 +1037,7 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) enabled = disabled = 0; - list_for_each_entry(slot, &bridge->slots, node) { + for (slot = bridge->slots; slot; slot = slot->next) { unsigned int status = get_slot_status(slot); if (slot->flags & SLOT_ENABLED) { if (status == ACPI_STA_ALL) @@ -909,11 +1082,11 @@ static void acpiphp_set_hpp_values(struct pci_bus *bus) */ static void acpiphp_sanitize_bus(struct pci_bus *bus) { - struct pci_dev *dev, *tmp; + struct pci_dev *dev; int i; unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; - list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { + list_for_each_entry(dev, &bus->devices, bus_list) { for (i=0; iresource[i]; if ((res->flags & type_mask) && !res->start && @@ -945,7 +1118,6 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) dbg("%s: re-enumerating slots under %s\n", __func__, objname); acpiphp_check_bridge(bridge); - put_bridge(bridge); } return AE_OK ; } @@ -1023,7 +1195,6 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ - put_bridge(bridge); } /** @@ -1037,8 +1208,6 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context) { - struct acpiphp_bridge *bridge = context; - /* * Currently the code adds all hotplug events to the kacpid_wq * queue when it should add hotplug events to the kacpi_hotplug_wq. @@ -1047,7 +1216,6 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, * For now just re-add this work to the kacpi_hotplug_wq so we * don't deadlock on hotplug actions. */ - get_bridge(bridge); alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge); } @@ -1102,7 +1270,6 @@ static void _handle_hotplug_event_func(struct work_struct *work) acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_func */ - put_bridge(func->slot->bridge); } /** @@ -1116,8 +1283,6 @@ static void _handle_hotplug_event_func(struct work_struct *work) static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) { - struct acpiphp_func *func = context; - /* * Currently the code adds all hotplug events to the kacpid_wq * queue when it should add hotplug events to the kacpi_hotplug_wq. @@ -1126,69 +1291,33 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, * For now just re-add this work to the kacpi_hotplug_wq so we * don't deadlock on hotplug actions. */ - get_bridge(func->slot->bridge); alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func); } -/* - * Create hotplug slots for the PCI bus. - * It should always return 0 to avoid skipping following notifiers. +static struct acpi_pci_driver acpi_pci_hp_driver = { + .add = add_bridge, + .remove = remove_bridge, +}; + +/** + * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures */ -void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) +int __init acpiphp_glue_init(void) { - acpi_handle dummy_handle; - struct acpiphp_bridge *bridge; - - if (acpiphp_disabled) - return; - - if (detect_ejectable_slots(handle) <= 0) - return; - - bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); - if (bridge == NULL) { - err("out of memory\n"); - return; - } - - INIT_LIST_HEAD(&bridge->slots); - kref_init(&bridge->ref); - bridge->handle = handle; - bridge->pci_dev = pci_dev_get(bus->self); - bridge->pci_bus = bus; + acpi_pci_register_driver(&acpi_pci_hp_driver); - /* - * Grab a ref to the subordinate PCI bus in case the bus is - * removed via PCI core logical hotplug. The ref pins the bus - * (which we access during module unload). - */ - get_device(&bus->dev); - - if (!pci_is_root_bus(bridge->pci_bus) && - ACPI_SUCCESS(acpi_get_handle(bridge->handle, - "_EJ0", &dummy_handle))) { - dbg("found ejectable p2p bridge\n"); - bridge->flags |= BRIDGE_HAS_EJ0; - bridge->func = acpiphp_bridge_handle_to_function(handle); - } - - init_bridge_misc(bridge); + return 0; } -/* Destroy hotplug slots associated with the PCI bus */ -void acpiphp_remove_slots(struct pci_bus *bus) -{ - struct acpiphp_bridge *bridge, *tmp; - - if (acpiphp_disabled) - return; - list_for_each_entry_safe(bridge, tmp, &bridge_list, list) - if (bridge->pci_bus == bus) { - cleanup_bridge(bridge); - put_bridge(bridge); - break; - } +/** + * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures + * + * This function frees all data allocated in acpiphp_glue_init(). + */ +void acpiphp_glue_exit(void) +{ + acpi_pci_unregister_driver(&acpi_pci_hp_driver); } /** @@ -1267,7 +1396,7 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) sta = get_slot_status(slot); - return (sta & ACPI_STA_DEVICE_UI) ? 0 : 1; + return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1; } diff --git a/trunk/drivers/pci/hotplug/pciehp_acpi.c b/trunk/drivers/pci/hotplug/pciehp_acpi.c index ead7c534095e..24d709b7388c 100644 --- a/trunk/drivers/pci/hotplug/pciehp_acpi.c +++ b/trunk/drivers/pci/hotplug/pciehp_acpi.c @@ -90,7 +90,7 @@ static int __init dummy_probe(struct pcie_device *dev) slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; - slot->number = (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19; + slot->number = slot_cap >> 19; list_for_each_entry(tmp, &dummy_slots, list) { if (tmp->number == slot->number) dup_slot_id++; diff --git a/trunk/drivers/pci/pci-acpi.c b/trunk/drivers/pci/pci-acpi.c index d927933dcf44..dee5dddaa292 100644 --- a/trunk/drivers/pci/pci-acpi.c +++ b/trunk/drivers/pci/pci-acpi.c @@ -287,32 +287,6 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = { .run_wake = acpi_pci_run_wake, }; -void acpi_pci_add_bus(struct pci_bus *bus) -{ - acpi_handle handle = NULL; - - if (bus->bridge) - handle = ACPI_HANDLE(bus->bridge); - if (acpi_pci_disabled || handle == NULL) - return; - - acpi_pci_slot_enumerate(bus, handle); - acpiphp_enumerate_slots(bus, handle); -} - -void acpi_pci_remove_bus(struct pci_bus *bus) -{ - /* - * bus->bridge->acpi_node.handle has already been reset to NULL - * when acpi_pci_remove_bus() is called, so don't check ACPI handle. - */ - if (acpi_pci_disabled) - return; - - acpiphp_remove_slots(bus); - acpi_pci_slot_remove(bus); -} - /* ACPI bus type */ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) { @@ -387,11 +361,7 @@ static int __init acpi_pci_init(void) ret = register_acpi_bus_type(&acpi_pci_bus); if (ret) return 0; - pci_set_platform_pm(&acpi_pci_platform_pm); - acpi_pci_slot_init(); - acpiphp_init(); - return 0; } arch_initcall(acpi_pci_init); diff --git a/trunk/drivers/pci/pci-sysfs.c b/trunk/drivers/pci/pci-sysfs.c index 5b4a9d9cd200..9c6e9bb674ec 100644 --- a/trunk/drivers/pci/pci-sysfs.c +++ b/trunk/drivers/pci/pci-sysfs.c @@ -897,7 +897,7 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma, if (pci_resource_len(pdev, resno) == 0) return 0; - nr = vma_pages(vma); + nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; start = vma->vm_pgoff; size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; pci_start = (mmap_api == PCI_MMAP_PROCFS) ? diff --git a/trunk/drivers/pci/pcie/Kconfig b/trunk/drivers/pci/pcie/Kconfig index 569f82fc9e22..fde4a32a0295 100644 --- a/trunk/drivers/pci/pcie/Kconfig +++ b/trunk/drivers/pci/pcie/Kconfig @@ -82,4 +82,4 @@ endchoice config PCIE_PME def_bool y - depends on PCIEPORTBUS && PM_RUNTIME + depends on PCIEPORTBUS && PM_RUNTIME && ACPI diff --git a/trunk/drivers/pci/pcie/aer/aer_inject.c b/trunk/drivers/pci/pcie/aer/aer_inject.c index 8d4a5e3dbe8e..4e24cb8a94ae 100644 --- a/trunk/drivers/pci/pcie/aer/aer_inject.c +++ b/trunk/drivers/pci/pcie/aer/aer_inject.c @@ -334,13 +334,13 @@ static int aer_inject(struct aer_error_inj *einj) return -ENODEV; rpdev = pcie_find_root_port(dev); if (!rpdev) { - ret = -ENODEV; + ret = -ENOTTY; goto out_put; } pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); if (!pos_cap_err) { - ret = -EPERM; + ret = -ENOTTY; goto out_put; } pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever); @@ -350,7 +350,7 @@ static int aer_inject(struct aer_error_inj *einj) rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR); if (!rp_pos_cap_err) { - ret = -EPERM; + ret = -ENOTTY; goto out_put; } diff --git a/trunk/drivers/pci/pcie/aer/aerdrv_core.c b/trunk/drivers/pci/pcie/aer/aerdrv_core.c index 8ec8b4f48560..564d97f94b6c 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv_core.c +++ b/trunk/drivers/pci/pcie/aer/aerdrv_core.c @@ -89,6 +89,8 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev) return -ENOSPC; } +#define PCI_BUS(x) (((x) >> 8) & 0xff) + /** * is_error_source - check whether the device is source of reported error * @dev: pointer to pci_dev to be checked @@ -104,7 +106,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) * When bus id is equal to 0, it might be a bad id * reported by root port. */ - if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) { + if (!nosourceid && (PCI_BUS(e_info->id) != 0)) { /* Device ID match? */ if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) return true; diff --git a/trunk/drivers/pci/pcie/pme.c b/trunk/drivers/pci/pcie/pme.c index 795db1f9d50c..9ca0dc9ffd84 100644 --- a/trunk/drivers/pci/pcie/pme.c +++ b/trunk/drivers/pci/pcie/pme.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include "../pci.h" diff --git a/trunk/drivers/pci/pcie/portdrv_acpi.c b/trunk/drivers/pci/pcie/portdrv_acpi.c index a86b56e5f2f2..b4d2894ee3fc 100644 --- a/trunk/drivers/pci/pcie/portdrv_acpi.c +++ b/trunk/drivers/pci/pcie/portdrv_acpi.c @@ -17,6 +17,7 @@ #include "aer/aerdrv.h" #include "../pci.h" +#include "portdrv.h" /** * pcie_port_acpi_setup - Request the BIOS to release control of PCIe services. diff --git a/trunk/drivers/pci/probe.c b/trunk/drivers/pci/probe.c index 43ece5d41d36..b494066ef32f 100644 --- a/trunk/drivers/pci/probe.c +++ b/trunk/drivers/pci/probe.c @@ -673,8 +673,6 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, ret = device_register(&child->dev); WARN_ON(ret < 0); - pcibios_add_bus(child); - /* Create legacy_io and legacy_mem files for this bus */ pci_create_legacy_files(child); @@ -1629,7 +1627,8 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) if (!bus->is_added) { dev_dbg(&bus->dev, "fixups for bus\n"); pcibios_fixup_bus(bus); - bus->is_added = 1; + if (pci_is_root_bus(bus)) + bus->is_added = 1; } for (pass=0; pass < 2; pass++) @@ -1662,14 +1661,6 @@ int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) return 0; } -void __weak pcibios_add_bus(struct pci_bus *bus) -{ -} - -void __weak pcibios_remove_bus(struct pci_bus *bus) -{ -} - struct pci_bus *pci_create_root_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata, struct list_head *resources) { @@ -1724,8 +1715,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, if (error) goto class_dev_reg_err; - pcibios_add_bus(b); - /* Create legacy_io and legacy_mem files for this bus */ pci_create_legacy_files(b); diff --git a/trunk/drivers/pci/quirks.c b/trunk/drivers/pci/quirks.c index 7d68aeebf56b..0369fb6fc1da 100644 --- a/trunk/drivers/pci/quirks.c +++ b/trunk/drivers/pci/quirks.c @@ -324,30 +324,29 @@ static void quirk_cs5536_vsa(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa); -static void quirk_io_region(struct pci_dev *dev, int port, - unsigned size, int nr, const char *name) +static void quirk_io_region(struct pci_dev *dev, unsigned region, + unsigned size, int nr, const char *name) { - u16 region; - struct pci_bus_region bus_region; - struct resource *res = dev->resource + nr; - - pci_read_config_word(dev, port, ®ion); - region &= ~(size - 1); - - if (!region) - return; + region &= ~(size-1); + if (region) { + struct pci_bus_region bus_region; + struct resource *res = dev->resource + nr; - res->name = pci_name(dev); - res->flags = IORESOURCE_IO; + res->name = pci_name(dev); + res->start = region; + res->end = region + size - 1; + res->flags = IORESOURCE_IO; - /* Convert from PCI bus to resource space */ - bus_region.start = region; - bus_region.end = region + size - 1; - pcibios_bus_to_resource(dev, res, &bus_region); + /* Convert from PCI bus to resource space. */ + bus_region.start = res->start; + bus_region.end = res->end; + pcibios_bus_to_resource(dev, res, &bus_region); - if (!pci_claim_resource(dev, nr)) - dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name); -} + if (pci_claim_resource(dev, nr) == 0) + dev_info(&dev->dev, "quirk: %pR claimed by %s\n", + res, name); + } +} /* * ATI Northbridge setups MCE the processor if you even @@ -375,8 +374,12 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_ */ static void quirk_ali7101_acpi(struct pci_dev *dev) { - quirk_io_region(dev, 0xE0, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI"); - quirk_io_region(dev, 0xE2, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB"); + u16 region; + + pci_read_config_word(dev, 0xE0, ®ion); + quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI"); + pci_read_config_word(dev, 0xE2, ®ion); + quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB"); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi); @@ -439,10 +442,12 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int */ static void quirk_piix4_acpi(struct pci_dev *dev) { - u32 res_a; + u32 region, res_a; - quirk_io_region(dev, 0x40, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI"); - quirk_io_region(dev, 0x90, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB"); + pci_read_config_dword(dev, 0x40, ®ion); + quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI"); + pci_read_config_dword(dev, 0x90, ®ion); + quirk_io_region(dev, region, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB"); /* Device resource A has enables for some of the other ones */ pci_read_config_dword(dev, 0x5c, &res_a); @@ -486,6 +491,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, qui */ static void quirk_ich4_lpc_acpi(struct pci_dev *dev) { + u32 region; u8 enable; /* @@ -497,14 +503,22 @@ static void quirk_ich4_lpc_acpi(struct pci_dev *dev) */ pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); - if (enable & ICH4_ACPI_EN) - quirk_io_region(dev, ICH_PMBASE, 128, PCI_BRIDGE_RESOURCES, - "ICH4 ACPI/GPIO/TCO"); + if (enable & ICH4_ACPI_EN) { + pci_read_config_dword(dev, ICH_PMBASE, ®ion); + region &= PCI_BASE_ADDRESS_IO_MASK; + if (region >= PCIBIOS_MIN_IO) + quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, + "ICH4 ACPI/GPIO/TCO"); + } pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable); - if (enable & ICH4_GPIO_EN) - quirk_io_region(dev, ICH4_GPIOBASE, 64, PCI_BRIDGE_RESOURCES+1, - "ICH4 GPIO"); + if (enable & ICH4_GPIO_EN) { + pci_read_config_dword(dev, ICH4_GPIOBASE, ®ion); + region &= PCI_BASE_ADDRESS_IO_MASK; + if (region >= PCIBIOS_MIN_IO) + quirk_io_region(dev, region, 64, + PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO"); + } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi); @@ -519,17 +533,26 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, qui static void ich6_lpc_acpi_gpio(struct pci_dev *dev) { + u32 region; u8 enable; pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); - if (enable & ICH6_ACPI_EN) - quirk_io_region(dev, ICH_PMBASE, 128, PCI_BRIDGE_RESOURCES, - "ICH6 ACPI/GPIO/TCO"); + if (enable & ICH6_ACPI_EN) { + pci_read_config_dword(dev, ICH_PMBASE, ®ion); + region &= PCI_BASE_ADDRESS_IO_MASK; + if (region >= PCIBIOS_MIN_IO) + quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, + "ICH6 ACPI/GPIO/TCO"); + } pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable); - if (enable & ICH6_GPIO_EN) - quirk_io_region(dev, ICH6_GPIOBASE, 64, PCI_BRIDGE_RESOURCES+1, - "ICH6 GPIO"); + if (enable & ICH6_GPIO_EN) { + pci_read_config_dword(dev, ICH6_GPIOBASE, ®ion); + region &= PCI_BASE_ADDRESS_IO_MASK; + if (region >= PCIBIOS_MIN_IO) + quirk_io_region(dev, region, 64, + PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO"); + } } static void ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize) @@ -627,9 +650,13 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_1, qui */ static void quirk_vt82c586_acpi(struct pci_dev *dev) { - if (dev->revision & 0x10) - quirk_io_region(dev, 0x48, 256, PCI_BRIDGE_RESOURCES, - "vt82c586 ACPI"); + u32 region; + + if (dev->revision & 0x10) { + pci_read_config_dword(dev, 0x48, ®ion); + region &= PCI_BASE_ADDRESS_IO_MASK; + quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI"); + } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi); @@ -641,12 +668,18 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt */ static void quirk_vt82c686_acpi(struct pci_dev *dev) { + u16 hm; + u32 smb; + quirk_vt82c586_acpi(dev); - quirk_io_region(dev, 0x70, 128, PCI_BRIDGE_RESOURCES+1, - "vt82c686 HW-mon"); + pci_read_config_word(dev, 0x70, &hm); + hm &= PCI_BASE_ADDRESS_IO_MASK; + quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c686 HW-mon"); - quirk_io_region(dev, 0x90, 16, PCI_BRIDGE_RESOURCES+2, "vt82c686 SMB"); + pci_read_config_dword(dev, 0x90, &smb); + smb &= PCI_BASE_ADDRESS_IO_MASK; + quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB"); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi); @@ -657,8 +690,15 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt */ static void quirk_vt8235_acpi(struct pci_dev *dev) { - quirk_io_region(dev, 0x88, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM"); - quirk_io_region(dev, 0xd0, 16, PCI_BRIDGE_RESOURCES+1, "vt8235 SMB"); + u16 pm, smb; + + pci_read_config_word(dev, 0x88, &pm); + pm &= PCI_BASE_ADDRESS_IO_MASK; + quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM"); + + pci_read_config_word(dev, 0xd0, &smb); + smb &= PCI_BASE_ADDRESS_IO_MASK; + quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1, "vt8235 SMB"); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi); @@ -2554,14 +2594,6 @@ static void quirk_msi_intx_disable_ati_bug(struct pci_dev *dev) dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG; pci_dev_put(p); } -static void quirk_msi_intx_disable_qca_bug(struct pci_dev *dev) -{ - /* AR816X/AR817X/E210X MSI is fixed at HW level from revision 0x18 */ - if (dev->revision < 0x18) { - dev_info(&dev->dev, "set MSI_INTX_DISABLE_BUG flag\n"); - dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG; - } -} DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, quirk_msi_intx_disable_bug); @@ -2611,16 +2643,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1073, quirk_msi_intx_disable_bug); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1083, quirk_msi_intx_disable_bug); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1090, - quirk_msi_intx_disable_qca_bug); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1091, - quirk_msi_intx_disable_qca_bug); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x10a0, - quirk_msi_intx_disable_qca_bug); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x10a1, - quirk_msi_intx_disable_qca_bug); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0xe091, - quirk_msi_intx_disable_qca_bug); #endif /* CONFIG_PCI_MSI */ /* Allow manual resource allocation for PCI hotplug bridges diff --git a/trunk/drivers/pci/remove.c b/trunk/drivers/pci/remove.c index 8fc54b7327bc..cc875e6ed159 100644 --- a/trunk/drivers/pci/remove.c +++ b/trunk/drivers/pci/remove.c @@ -50,8 +50,10 @@ void pci_remove_bus(struct pci_bus *bus) list_del(&bus->node); pci_bus_release_busn_res(bus); up_write(&pci_bus_sem); + if (!bus->is_added) + return; + pci_remove_legacy_files(bus); - pcibios_remove_bus(bus); device_unregister(&bus->dev); } EXPORT_SYMBOL(pci_remove_bus); diff --git a/trunk/drivers/scsi/mvsas/mv_init.c b/trunk/drivers/scsi/mvsas/mv_init.c index 74550922ad55..ce90d0546cdd 100644 --- a/trunk/drivers/scsi/mvsas/mv_init.c +++ b/trunk/drivers/scsi/mvsas/mv_init.c @@ -703,7 +703,7 @@ static struct pci_device_id mvs_pci_table[] = { { PCI_VDEVICE(TTI, 0x2744), chip_9480 }, { PCI_VDEVICE(TTI, 0x2760), chip_9480 }, { - .vendor = PCI_VENDOR_ID_MARVELL_EXT, + .vendor = 0x1b4b, .device = 0x9480, .subvendor = PCI_ANY_ID, .subdevice = 0x9480, @@ -712,7 +712,7 @@ static struct pci_device_id mvs_pci_table[] = { .driver_data = chip_9480, }, { - .vendor = PCI_VENDOR_ID_MARVELL_EXT, + .vendor = 0x1b4b, .device = 0x9445, .subvendor = PCI_ANY_ID, .subdevice = 0x9480, @@ -721,7 +721,7 @@ static struct pci_device_id mvs_pci_table[] = { .driver_data = chip_9445, }, { - .vendor = PCI_VENDOR_ID_MARVELL_EXT, + .vendor = 0x1b4b, .device = 0x9485, .subvendor = PCI_ANY_ID, .subdevice = 0x9480, diff --git a/trunk/drivers/scsi/mvumi.c b/trunk/drivers/scsi/mvumi.c index c3601b57a80c..4594ccaaf49b 100644 --- a/trunk/drivers/scsi/mvumi.c +++ b/trunk/drivers/scsi/mvumi.c @@ -49,8 +49,8 @@ MODULE_AUTHOR("jyli@marvell.com"); MODULE_DESCRIPTION("Marvell UMI Driver"); static DEFINE_PCI_DEVICE_TABLE(mvumi_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9143) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9580) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9143) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9580) }, { 0 } }; diff --git a/trunk/drivers/scsi/mvumi.h b/trunk/drivers/scsi/mvumi.h index 41f168702ac7..e360135fd1bd 100644 --- a/trunk/drivers/scsi/mvumi.h +++ b/trunk/drivers/scsi/mvumi.h @@ -32,6 +32,7 @@ #define VER_BUILD 1500 #define MV_DRIVER_NAME "mvumi" +#define PCI_VENDOR_ID_MARVELL_2 0x1b4b #define PCI_DEVICE_ID_MARVELL_MV9143 0x9143 #define PCI_DEVICE_ID_MARVELL_MV9580 0x9580 diff --git a/trunk/include/linux/acpi.h b/trunk/include/linux/acpi.h index 03053aca5b32..bcbdd7484e58 100644 --- a/trunk/include/linux/acpi.h +++ b/trunk/include/linux/acpi.h @@ -152,6 +152,15 @@ void acpi_penalize_isa_irq(int irq, int active); void acpi_pci_irq_disable (struct pci_dev *dev); +struct acpi_pci_driver { + struct list_head node; + int (*add)(struct acpi_pci_root *root); + void (*remove)(struct acpi_pci_root *root); +}; + +int acpi_pci_register_driver(struct acpi_pci_driver *driver); +void acpi_pci_unregister_driver(struct acpi_pci_driver *driver); + extern int ec_read(u8 addr, u8 *val); extern int ec_write(u8 addr, u8 val); extern int ec_transaction(u8 command, diff --git a/trunk/include/linux/pci-acpi.h b/trunk/include/linux/pci-acpi.h index 81b31613eb25..9a22b5efb384 100644 --- a/trunk/include/linux/pci-acpi.h +++ b/trunk/include/linux/pci-acpi.h @@ -41,37 +41,8 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus) return DEVICE_ACPI_HANDLE(dev); } - -void acpi_pci_add_bus(struct pci_bus *bus); -void acpi_pci_remove_bus(struct pci_bus *bus); - -#ifdef CONFIG_ACPI_PCI_SLOT -void acpi_pci_slot_init(void); -void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle); -void acpi_pci_slot_remove(struct pci_bus *bus); -#else -static inline void acpi_pci_slot_init(void) { } -static inline void acpi_pci_slot_enumerate(struct pci_bus *bus, - acpi_handle handle) { } -static inline void acpi_pci_slot_remove(struct pci_bus *bus) { } #endif -#ifdef CONFIG_HOTPLUG_PCI_ACPI -void acpiphp_init(void); -void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle); -void acpiphp_remove_slots(struct pci_bus *bus); -#else -static inline void acpiphp_init(void) { } -static inline void acpiphp_enumerate_slots(struct pci_bus *bus, - acpi_handle handle) { } -static inline void acpiphp_remove_slots(struct pci_bus *bus) { } -#endif - -#else /* CONFIG_ACPI */ -static inline void acpi_pci_add_bus(struct pci_bus *bus) { } -static inline void acpi_pci_remove_bus(struct pci_bus *bus) { } -#endif /* CONFIG_ACPI */ - #ifdef CONFIG_ACPI_APEI extern bool aer_acpi_firmware_first(void); #else diff --git a/trunk/include/linux/pci.h b/trunk/include/linux/pci.h index 4a6ee631a0c5..2461033a7987 100644 --- a/trunk/include/linux/pci.h +++ b/trunk/include/linux/pci.h @@ -35,21 +35,6 @@ /* Include the ID list */ #include -/* - * The PCI interface treats multi-function devices as independent - * devices. The slot/function address of each device is encoded - * in a single byte as follows: - * - * 7:3 = slot - * 2:0 = function - * PCI_DEVFN(), PCI_SLOT(), and PCI_FUNC() are defined uapi/linux/pci.h - * In the interest of not exposing interfaces to user-space unnecessarily, - * the following kernel only defines are being added here. - */ -#define PCI_DEVID(bus, devfn) ((((u16)bus) << 8) | devfn) -/* return bus from PCI devid = ((u16)bus_number) << 8) | devfn */ -#define PCI_BUS_NUM(x) (((x) >> 8) & 0xff) - /* pci_slot represents a physical slot */ struct pci_slot { struct pci_bus *bus; /* The bus this slot is on */ @@ -693,8 +678,6 @@ extern struct list_head pci_root_buses; /* list of all known PCI buses */ extern int no_pci_devices(void); void pcibios_resource_survey_bus(struct pci_bus *bus); -void pcibios_add_bus(struct pci_bus *bus); -void pcibios_remove_bus(struct pci_bus *bus); void pcibios_fixup_bus(struct pci_bus *); int __must_check pcibios_enable_device(struct pci_dev *, int mask); /* Architecture specific versions may override this (weak) */ @@ -1840,7 +1823,7 @@ extern void pci_set_bus_of_node(struct pci_bus *bus); extern void pci_release_bus_of_node(struct pci_bus *bus); /* Arch may override this (weak) */ -extern struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus); +extern struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus); static inline struct device_node * pci_device_to_OF_node(const struct pci_dev *pdev) diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index a80f9e6ce9e5..f11c1c2609d5 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -1604,7 +1604,6 @@ #define PCI_SUBDEVICE_ID_KEYSPAN_SX2 0x5334 #define PCI_VENDOR_ID_MARVELL 0x11ab -#define PCI_VENDOR_ID_MARVELL_EXT 0x1b4b #define PCI_DEVICE_ID_MARVELL_GT64111 0x4146 #define PCI_DEVICE_ID_MARVELL_GT64260 0x6430 #define PCI_DEVICE_ID_MARVELL_MV64360 0x6460