From 859e3211b5514d242dc5b78537ffbc73ed8a352b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 25 Jan 2013 11:26:36 -0700 Subject: [PATCH] --- yaml --- r: 358406 b: refs/heads/master c: a2766602ac6885f9514abd97821984cd152cdad3 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/frv/mb93090-mb00/pci-frv.h | 1 + trunk/arch/frv/mb93090-mb00/pci-vdk.c | 4 +- trunk/arch/ia64/pci/pci.c | 8 - trunk/arch/mn10300/unit-asb2305/pci-asb2305.h | 1 + trunk/arch/mn10300/unit-asb2305/pci.c | 4 +- trunk/arch/x86/include/asm/pci.h | 3 - trunk/arch/x86/include/asm/pci_x86.h | 1 + trunk/arch/x86/pci/acpi.c | 9 - trunk/arch/x86/pci/common.c | 1 + trunk/arch/x86/pci/legacy.c | 2 +- trunk/arch/x86/pci/numaq_32.c | 2 +- trunk/drivers/acpi/acpi_memhotplug.c | 4 +- trunk/drivers/acpi/container.c | 2 +- trunk/drivers/acpi/dock.c | 4 +- trunk/drivers/acpi/pci_root.c | 18 ++ trunk/drivers/acpi/processor_driver.c | 4 +- trunk/drivers/acpi/scan.c | 168 +++++++----------- trunk/drivers/pci/hotplug/acpiphp_glue.c | 8 +- trunk/drivers/pci/hotplug/cpci_hotplug_pci.c | 29 +-- trunk/drivers/pci/hotplug/cpqphp_ctrl.c | 57 +++--- trunk/drivers/pci/hotplug/pciehp_pci.c | 44 +++-- trunk/drivers/pci/hotplug/sgi_hotplug.c | 69 +++---- trunk/drivers/pci/hotplug/shpchp_pci.c | 36 ++-- trunk/drivers/pci/pci-acpi.c | 19 ++ trunk/drivers/pci/pci.c | 30 ++-- trunk/drivers/pci/pci.h | 2 +- trunk/drivers/pci/probe.c | 66 +++---- trunk/include/acpi/acpi_bus.h | 10 +- trunk/include/linux/pci.h | 2 - 30 files changed, 308 insertions(+), 302 deletions(-) diff --git a/[refs] b/[refs] index 495c6ab96f3b..2a17ffaefe9b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 14b5cb37cc6172a54ce920c61784f44422ae306d +refs/heads/master: a2766602ac6885f9514abd97821984cd152cdad3 diff --git a/trunk/arch/frv/mb93090-mb00/pci-frv.h b/trunk/arch/frv/mb93090-mb00/pci-frv.h index 76c4e73d643d..089eeba4f3bc 100644 --- a/trunk/arch/frv/mb93090-mb00/pci-frv.h +++ b/trunk/arch/frv/mb93090-mb00/pci-frv.h @@ -31,6 +31,7 @@ void pcibios_resource_survey(void); /* pci-vdk.c */ extern int __nongpreldata pcibios_last_bus; +extern struct pci_bus *__nongpreldata pci_root_bus; extern struct pci_ops *__nongpreldata pci_root_ops; /* pci-irq.c */ diff --git a/trunk/arch/frv/mb93090-mb00/pci-vdk.c b/trunk/arch/frv/mb93090-mb00/pci-vdk.c index 1152a1e3cabb..71e9bcf58105 100644 --- a/trunk/arch/frv/mb93090-mb00/pci-vdk.c +++ b/trunk/arch/frv/mb93090-mb00/pci-vdk.c @@ -26,6 +26,7 @@ unsigned int __nongpreldata pci_probe = 1; int __nongpreldata pcibios_last_bus = -1; +struct pci_bus *__nongpreldata pci_root_bus; struct pci_ops *__nongpreldata pci_root_ops; /* @@ -415,7 +416,8 @@ int __init pcibios_init(void) printk("PCI: Probing PCI hardware\n"); pci_add_resource(&resources, &pci_ioport_resource); pci_add_resource(&resources, &pci_iomem_resource); - pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources); + pci_root_bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, + &resources); pcibios_irq_init(); pcibios_fixup_peer_bridges(); diff --git a/trunk/arch/ia64/pci/pci.c b/trunk/arch/ia64/pci/pci.c index 00e59c7ad3c0..5faa66c5c2a8 100644 --- a/trunk/arch/ia64/pci/pci.c +++ b/trunk/arch/ia64/pci/pci.c @@ -396,14 +396,6 @@ pci_acpi_scan_root(struct acpi_pci_root *root) return NULL; } -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) -{ - struct pci_controller *controller = bridge->bus->sysdata; - - ACPI_HANDLE_SET(&bridge->dev, controller->acpi_handle); - return 0; -} - static int __devinit is_valid_resource(struct pci_dev *dev, int idx) { unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; diff --git a/trunk/arch/mn10300/unit-asb2305/pci-asb2305.h b/trunk/arch/mn10300/unit-asb2305/pci-asb2305.h index 7fa66a0e4624..1194fe486b01 100644 --- a/trunk/arch/mn10300/unit-asb2305/pci-asb2305.h +++ b/trunk/arch/mn10300/unit-asb2305/pci-asb2305.h @@ -36,6 +36,7 @@ extern void pcibios_resource_survey(void); /* pci.c */ extern int pcibios_last_bus; +extern struct pci_bus *pci_root_bus; extern struct pci_ops *pci_root_ops; extern struct irq_routing_table *pcibios_get_irq_routing_table(void); diff --git a/trunk/arch/mn10300/unit-asb2305/pci.c b/trunk/arch/mn10300/unit-asb2305/pci.c index 426bf51605f3..e2059486d3f8 100644 --- a/trunk/arch/mn10300/unit-asb2305/pci.c +++ b/trunk/arch/mn10300/unit-asb2305/pci.c @@ -24,6 +24,7 @@ unsigned int pci_probe = 1; int pcibios_last_bus = -1; +struct pci_bus *pci_root_bus; struct pci_ops *pci_root_ops; /* @@ -376,7 +377,8 @@ static int __init pcibios_init(void) pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset); pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset); - pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources); + pci_root_bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, + &resources); pcibios_irq_init(); pcibios_fixup_irqs(); diff --git a/trunk/arch/x86/include/asm/pci.h b/trunk/arch/x86/include/asm/pci.h index 9f437e97e9e8..dba7805176bf 100644 --- a/trunk/arch/x86/include/asm/pci.h +++ b/trunk/arch/x86/include/asm/pci.h @@ -14,9 +14,6 @@ struct pci_sysdata { int domain; /* PCI domain */ int node; /* NUMA node */ -#ifdef CONFIG_ACPI - void *acpi; /* ACPI-specific data */ -#endif #ifdef CONFIG_X86_64 void *iommu; /* IOMMU private data */ #endif diff --git a/trunk/arch/x86/include/asm/pci_x86.h b/trunk/arch/x86/include/asm/pci_x86.h index 0126f104f0a5..73e8eeff22ee 100644 --- a/trunk/arch/x86/include/asm/pci_x86.h +++ b/trunk/arch/x86/include/asm/pci_x86.h @@ -54,6 +54,7 @@ void pcibios_set_cache_line_size(void); /* pci-pc.c */ extern int pcibios_last_bus; +extern struct pci_bus *pci_root_bus; extern struct pci_ops pci_root_ops; void pcibios_scan_specific_bus(int busn); diff --git a/trunk/arch/x86/pci/acpi.c b/trunk/arch/x86/pci/acpi.c index 3d49094ed3e8..0c01261fe5a8 100644 --- a/trunk/arch/x86/pci/acpi.c +++ b/trunk/arch/x86/pci/acpi.c @@ -522,7 +522,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) sd = &info->sd; sd->domain = domain; sd->node = node; - sd->acpi = device->handle; /* * Maybe the desired pci bus has been already scanned. In such case * it is unnecessary to scan the pci bus with the given domain,busnum. @@ -594,14 +593,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) return bus; } -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) -{ - struct pci_sysdata *sd = bridge->bus->sysdata; - - ACPI_HANDLE_SET(&bridge->dev, sd->acpi); - return 0; -} - int __init pci_acpi_init(void) { struct pci_dev *dev = NULL; diff --git a/trunk/arch/x86/pci/common.c b/trunk/arch/x86/pci/common.c index 505731b139f4..412e1286d1fc 100644 --- a/trunk/arch/x86/pci/common.c +++ b/trunk/arch/x86/pci/common.c @@ -34,6 +34,7 @@ int noioapicreroute = 1; #endif int pcibios_last_bus = -1; unsigned long pirq_table_addr; +struct pci_bus *pci_root_bus; const struct pci_raw_ops *__read_mostly raw_pci_ops; const struct pci_raw_ops *__read_mostly raw_pci_ext_ops; diff --git a/trunk/arch/x86/pci/legacy.c b/trunk/arch/x86/pci/legacy.c index a9e83083fb85..a1df191129d3 100644 --- a/trunk/arch/x86/pci/legacy.c +++ b/trunk/arch/x86/pci/legacy.c @@ -30,7 +30,7 @@ int __init pci_legacy_init(void) } printk("PCI: Probing PCI hardware\n"); - pcibios_scan_root(0); + pci_root_bus = pcibios_scan_root(0); return 0; } diff --git a/trunk/arch/x86/pci/numaq_32.c b/trunk/arch/x86/pci/numaq_32.c index 00edfe652b72..83e125b95ca6 100644 --- a/trunk/arch/x86/pci/numaq_32.c +++ b/trunk/arch/x86/pci/numaq_32.c @@ -152,7 +152,7 @@ int __init pci_numaq_init(void) raw_pci_ops = &pci_direct_conf1_mq; - pcibios_scan_root(0); + pci_root_bus = pcibios_scan_root(0); if (num_online_nodes() > 1) for_each_online_node(quad) { if (quad == 0) diff --git a/trunk/drivers/acpi/acpi_memhotplug.c b/trunk/drivers/acpi/acpi_memhotplug.c index 327ab4459558..15ea22fc1f5e 100644 --- a/trunk/drivers/acpi/acpi_memhotplug.c +++ b/trunk/drivers/acpi/acpi_memhotplug.c @@ -167,7 +167,7 @@ acpi_memory_get_device(acpi_handle handle, * Now add the notified device. This creates the acpi_device * and invokes .add function */ - result = acpi_bus_add(handle); + result = acpi_bus_scan(handle); if (result) { acpi_handle_warn(handle, "Cannot add acpi bus\n"); return -EINVAL; @@ -361,7 +361,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) break; } - ej_event->handle = handle; + ej_event->device = device; ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event); diff --git a/trunk/drivers/acpi/container.c b/trunk/drivers/acpi/container.c index f8fb2281f34a..cc79d3e53a39 100644 --- a/trunk/drivers/acpi/container.c +++ b/trunk/drivers/acpi/container.c @@ -166,7 +166,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (!ACPI_FAILURE(status) || device) break; - result = acpi_bus_add(handle); + result = acpi_bus_scan(handle); if (result) { acpi_handle_warn(handle, "Failed to add container\n"); break; diff --git a/trunk/drivers/acpi/dock.c b/trunk/drivers/acpi/dock.c index 9e31b2bd93d3..420d24fc9388 100644 --- a/trunk/drivers/acpi/dock.c +++ b/trunk/drivers/acpi/dock.c @@ -317,7 +317,7 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) * no device created for this object, * so we should create one. */ - ret = acpi_bus_add(handle); + ret = acpi_bus_scan(handle); if (ret) pr_debug("error adding bus, %x\n", -ret); @@ -339,7 +339,7 @@ static void dock_remove_acpi_device(acpi_handle handle) int ret; if (!acpi_bus_get_device(handle, &device)) { - ret = acpi_bus_trim(device, 1); + ret = acpi_bus_trim(device); if (ret) pr_debug("error removing bus, %x\n", -ret); } diff --git a/trunk/drivers/acpi/pci_root.c b/trunk/drivers/acpi/pci_root.c index bf5108ad4d63..471b2dcb1c67 100644 --- a/trunk/drivers/acpi/pci_root.c +++ b/trunk/drivers/acpi/pci_root.c @@ -107,6 +107,24 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) } EXPORT_SYMBOL(acpi_pci_unregister_driver); +acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) +{ + struct acpi_pci_root *root; + acpi_handle handle = NULL; + + mutex_lock(&acpi_pci_root_lock); + list_for_each_entry(root, &acpi_pci_roots, node) + if ((root->segment == (u16) seg) && + (root->secondary.start == (u16) bus)) { + handle = root->device->handle; + break; + } + mutex_unlock(&acpi_pci_root_lock); + return handle; +} + +EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); + /** * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge * @handle - the ACPI CA node in question. diff --git a/trunk/drivers/acpi/processor_driver.c b/trunk/drivers/acpi/processor_driver.c index 0777663f443e..9c5929a17d3a 100644 --- a/trunk/drivers/acpi/processor_driver.c +++ b/trunk/drivers/acpi/processor_driver.c @@ -699,7 +699,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, if (!acpi_bus_get_device(handle, &device)) break; - result = acpi_bus_add(handle); + result = acpi_bus_scan(handle); if (result) { acpi_handle_err(handle, "Unable to add the device\n"); break; @@ -733,7 +733,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, break; } - ej_event->handle = handle; + ej_event->device = device; ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event); diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index e380345b643a..7c43bdc36abc 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -116,24 +116,18 @@ static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); void acpi_bus_hot_remove_device(void *context) { struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context; - struct acpi_device *device; - acpi_handle handle = ej_event->handle; + struct acpi_device *device = ej_event->device; + acpi_handle handle = device->handle; acpi_handle temp; struct acpi_object_list arg_list; union acpi_object arg; acpi_status status = AE_OK; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ - if (acpi_bus_get_device(handle, &device)) - goto err_out; - - if (!device) - goto err_out; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Hot-removing device %s...\n", dev_name(&device->dev))); - if (acpi_bus_trim(device, 1)) { + if (acpi_bus_trim(device)) { printk(KERN_ERR PREFIX "Removing device failed\n"); goto err_out; @@ -215,7 +209,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, goto err; } - ej_event->handle = acpi_device->handle; + ej_event->device = acpi_device; if (acpi_device->flags.eject_pending) { /* event originated from ACPI eject notification */ ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; @@ -223,7 +217,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, } else { /* event originated from user */ ej_event->event = ACPI_OST_EC_OSPM_EJECT; - (void) acpi_evaluate_hotplug_ost(ej_event->handle, + (void) acpi_evaluate_hotplug_ost(acpi_device->handle, ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); } @@ -701,7 +695,7 @@ static int acpi_device_register(struct acpi_device *device) return result; } -static void acpi_device_unregister(struct acpi_device *device, int type) +static void acpi_device_unregister(struct acpi_device *device) { mutex_lock(&acpi_device_lock); if (device->parent) @@ -1374,22 +1368,6 @@ static int acpi_device_set_context(struct acpi_device *device) return -ENODEV; } -static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) -{ - if (!dev) - return -EINVAL; - - dev->removal_type = ACPI_BUS_REMOVAL_EJECT; - device_release_driver(&dev->dev); - - if (!rmdevice) - return 0; - - acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT); - - return 0; -} - static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, bool match_driver) @@ -1593,13 +1571,25 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { /* This is a known good platform device. */ acpi_create_platform_device(device); - } else if (device_attach(&device->dev)) { + } else if (device_attach(&device->dev) < 0) { status = AE_CTRL_DEPTH; } return status; } -static int acpi_bus_scan(acpi_handle handle) +/** + * acpi_bus_scan - Add ACPI device node objects in a given namespace scope. + * @handle: Root of the namespace scope to scan. + * + * Scan a given ACPI tree (probably recently hot-plugged) and create and add + * found devices. + * + * If no devices were found, -ENODEV is returned, but it does not mean that + * there has been a real error. There just have been no suitable ACPI objects + * in the table trunk from which the kernel could create a device and add an + * appropriate driver. + */ +int acpi_bus_scan(acpi_handle handle) { void *device = NULL; @@ -1616,84 +1606,48 @@ static int acpi_bus_scan(acpi_handle handle) return 0; } +EXPORT_SYMBOL(acpi_bus_scan); -/** - * acpi_bus_add - Add ACPI device node objects in a given namespace scope. - * @handle: Root of the namespace scope to scan. - * - * Scan a given ACPI tree (probably recently hot-plugged) and create and add - * found devices. - * - * If no devices were found, -ENODEV is returned, but it does not mean that - * there has been a real error. There just have been no suitable ACPI objects - * in the table trunk from which the kernel could create a device and add an - * appropriate driver. - */ -int acpi_bus_add(acpi_handle handle) +static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) { - int err; - - err = acpi_bus_scan(handle); - if (err) - return err; + struct acpi_device *device = NULL; - acpi_update_all_gpes(); - return 0; + if (!acpi_bus_get_device(handle, &device)) { + device->removal_type = ACPI_BUS_REMOVAL_EJECT; + device_release_driver(&device->dev); + } + return AE_OK; } -EXPORT_SYMBOL(acpi_bus_add); -int acpi_bus_trim(struct acpi_device *start, int rmdevice) +static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) { - acpi_status status; - struct acpi_device *parent, *child; - acpi_handle phandle, chandle; - acpi_object_type type; - u32 level = 1; - int err = 0; - - parent = start; - phandle = start->handle; - child = chandle = NULL; - - while ((level > 0) && parent && (!err)) { - status = acpi_get_next_object(ACPI_TYPE_ANY, phandle, - chandle, &chandle); + struct acpi_device *device = NULL; - /* - * If this scope is exhausted then move our way back up. - */ - if (ACPI_FAILURE(status)) { - level--; - chandle = phandle; - acpi_get_parent(phandle, &phandle); - child = parent; - parent = parent->parent; - - if (level == 0) - err = acpi_bus_remove(child, rmdevice); - else - err = acpi_bus_remove(child, 1); + if (!acpi_bus_get_device(handle, &device)) + acpi_device_unregister(device); - continue; - } + return AE_OK; +} - status = acpi_get_type(chandle, &type); - if (ACPI_FAILURE(status)) { - continue; - } - /* - * If there is a device corresponding to chandle then - * parse it (depth-first). - */ - if (acpi_bus_get_device(chandle, &child) == 0) { - level++; - phandle = chandle; - chandle = NULL; - parent = child; - } - continue; - } - return err; +int acpi_bus_trim(struct acpi_device *start) +{ + /* + * Execute acpi_bus_device_detach() as a post-order callback to detach + * all ACPI drivers from the device nodes being removed. + */ + acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, + acpi_bus_device_detach, NULL, NULL); + acpi_bus_device_detach(start->handle, 0, NULL, NULL); + /* + * Execute acpi_bus_remove() as a post-order callback to remove device + * nodes in the given namespace scope. + */ + acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, + acpi_bus_remove, NULL, NULL); + acpi_bus_remove(start->handle, 0, NULL, NULL); + return 0; } EXPORT_SYMBOL_GPL(acpi_bus_trim); @@ -1742,13 +1696,15 @@ int __init acpi_scan_init(void) return result; result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); - if (!result) - result = acpi_bus_scan_fixed(); - if (result) - acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); - else - acpi_update_all_gpes(); + return result; - return result; + result = acpi_bus_scan_fixed(); + if (result) { + acpi_device_unregister(acpi_root); + return result; + } + + acpi_update_all_gpes(); + return 0; } diff --git a/trunk/drivers/pci/hotplug/acpiphp_glue.c b/trunk/drivers/pci/hotplug/acpiphp_glue.c index 91b5ad875c53..9e2b1f6dbe41 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_glue.c +++ b/trunk/drivers/pci/hotplug/acpiphp_glue.c @@ -742,11 +742,11 @@ static int acpiphp_bus_add(struct acpiphp_func *func) /* this shouldn't be in here, so remove * the bus then re-add it... */ - ret_val = acpi_bus_trim(device, 1); + ret_val = acpi_bus_trim(device); dbg("acpi_bus_trim return %x\n", ret_val); } - ret_val = acpi_bus_add(func->handle); + ret_val = acpi_bus_scan(func->handle); if (!ret_val) ret_val = acpi_bus_get_device(func->handle, &device); @@ -772,7 +772,7 @@ static int acpiphp_bus_trim(acpi_handle handle) return retval; } - retval = acpi_bus_trim(device, 1); + retval = acpi_bus_trim(device); if (retval) err("cannot remove from acpi list\n"); @@ -1129,7 +1129,7 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type) return; } - if (acpi_bus_add(handle)) { + if (acpi_bus_scan(handle)) { err("cannot add bridge to acpi list\n"); return; } diff --git a/trunk/drivers/pci/hotplug/cpci_hotplug_pci.c b/trunk/drivers/pci/hotplug/cpci_hotplug_pci.c index d8add34177f2..dcc75c785443 100644 --- a/trunk/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/trunk/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -252,8 +252,8 @@ int cpci_led_off(struct slot* slot) int __ref cpci_configure_slot(struct slot *slot) { - struct pci_dev *dev; struct pci_bus *parent; + int fn; dbg("%s - enter", __func__); @@ -282,13 +282,18 @@ int __ref cpci_configure_slot(struct slot *slot) } parent = slot->dev->bus; - list_for_each_entry(dev, &parent->devices, bus_list) - if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) + for (fn = 0; fn < 8; fn++) { + struct pci_dev *dev; + + dev = pci_get_slot(parent, + PCI_DEVFN(PCI_SLOT(slot->devfn), fn)); + if (!dev) continue; if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) pci_hp_add_bridge(dev); - + pci_dev_put(dev); + } pci_assign_unassigned_bridge_resources(parent->self); @@ -300,7 +305,8 @@ int __ref cpci_configure_slot(struct slot *slot) int cpci_unconfigure_slot(struct slot* slot) { - struct pci_dev *dev, *temp; + int i; + struct pci_dev *dev; dbg("%s - enter", __func__); if (!slot->dev) { @@ -308,12 +314,13 @@ int cpci_unconfigure_slot(struct slot* slot) return -ENODEV; } - list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) { - if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) - continue; - pci_dev_get(dev); - pci_stop_and_remove_bus_device(dev); - pci_dev_put(dev); + for (i = 0; i < 8; i++) { + dev = pci_get_slot(slot->bus, + PCI_DEVFN(PCI_SLOT(slot->devfn), i)); + if (dev) { + pci_stop_and_remove_bus_device(dev); + pci_dev_put(dev); + } } pci_dev_put(slot->dev); slot->dev = NULL; diff --git a/trunk/drivers/pci/hotplug/cpqphp_ctrl.c b/trunk/drivers/pci/hotplug/cpqphp_ctrl.c index d282019cda5f..36112fe212d3 100644 --- a/trunk/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/trunk/drivers/pci/hotplug/cpqphp_ctrl.c @@ -1900,7 +1900,8 @@ static void interrupt_event_handler(struct controller *ctrl) dbg("power fault\n"); } else { /* refresh notification */ - update_slot_info(ctrl, p_slot); + if (p_slot) + update_slot_info(ctrl, p_slot); } ctrl->event_queue[loop].event_type = 0; @@ -2519,28 +2520,44 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func /* If we have IO resources copy them and fill in the bridge's * IO range registers */ - memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); - io_node->next = NULL; + if (io_node) { + memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); + io_node->next = NULL; - /* set IO base and Limit registers */ - temp_byte = io_node->base >> 8; - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte); + /* set IO base and Limit registers */ + temp_byte = io_node->base >> 8; + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte); - temp_byte = (io_node->base + io_node->length - 1) >> 8; - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + temp_byte = (io_node->base + io_node->length - 1) >> 8; + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + } else { + kfree(hold_IO_node); + hold_IO_node = NULL; + } - /* Copy the memory resources and fill in the bridge's memory - * range registers. - */ - memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource)); - mem_node->next = NULL; + /* If we have memory resources copy them and fill in the + * bridge's memory range registers. Otherwise, fill in the + * range registers with values that disable them. */ + if (mem_node) { + memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource)); + mem_node->next = NULL; - /* set Mem base and Limit registers */ - temp_word = mem_node->base >> 16; - rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + /* set Mem base and Limit registers */ + temp_word = mem_node->base >> 16; + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word); - temp_word = (mem_node->base + mem_node->length - 1) >> 16; - rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + temp_word = (mem_node->base + mem_node->length - 1) >> 16; + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + } else { + temp_word = 0xFFFF; + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + + temp_word = 0x0000; + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + + kfree(hold_mem_node); + hold_mem_node = NULL; + } memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource)); p_mem_node->next = NULL; @@ -2610,7 +2627,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func /* Return unused bus resources * First use the temporary node to store information for * the board */ - if (bus_node && temp_resources.bus_head) { + if (hold_bus_node && bus_node && temp_resources.bus_head) { hold_bus_node->length = bus_node->base - hold_bus_node->base; hold_bus_node->next = func->bus_head; @@ -2734,7 +2751,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func } /* If we have prefetchable memory space available and there * is some left at the end, return the unused portion */ - if (temp_resources.p_mem_head) { + if (hold_p_mem_node && temp_resources.p_mem_head) { p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), &hold_p_mem_node, 0x100000); diff --git a/trunk/drivers/pci/hotplug/pciehp_pci.c b/trunk/drivers/pci/hotplug/pciehp_pci.c index aac7a40e4a4a..09cecaf450c5 100644 --- a/trunk/drivers/pci/hotplug/pciehp_pci.c +++ b/trunk/drivers/pci/hotplug/pciehp_pci.c @@ -39,7 +39,7 @@ int pciehp_configure_device(struct slot *p_slot) struct pci_dev *dev; struct pci_dev *bridge = p_slot->ctrl->pcie->port; struct pci_bus *parent = bridge->subordinate; - int num; + int num, fn; struct controller *ctrl = p_slot->ctrl; dev = pci_get_slot(parent, PCI_DEVFN(0, 0)); @@ -57,18 +57,28 @@ int pciehp_configure_device(struct slot *p_slot) return -ENODEV; } - list_for_each_entry(dev, &parent->devices, bus_list) + for (fn = 0; fn < 8; fn++) { + dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); + if (!dev) + continue; if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) pci_hp_add_bridge(dev); + pci_dev_put(dev); + } pci_assign_unassigned_bridge_resources(bridge); - list_for_each_entry(dev, &parent->devices, bus_list) { - if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) + for (fn = 0; fn < 8; fn++) { + dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); + if (!dev) continue; - + if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { + pci_dev_put(dev); + continue; + } pci_configure_slot(dev); + pci_dev_put(dev); } pci_bus_add_devices(parent); @@ -79,9 +89,9 @@ int pciehp_configure_device(struct slot *p_slot) int pciehp_unconfigure_device(struct slot *p_slot) { int ret, rc = 0; + int j; u8 bctl = 0; u8 presence = 0; - struct pci_dev *dev, *temp; struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate; u16 command; struct controller *ctrl = p_slot->ctrl; @@ -92,31 +102,33 @@ int pciehp_unconfigure_device(struct slot *p_slot) if (ret) presence = 0; - list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { - pci_dev_get(dev); - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { - pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl); + for (j = 0; j < 8; j++) { + struct pci_dev *temp = pci_get_slot(parent, PCI_DEVFN(0, j)); + if (!temp) + continue; + if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { + pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); if (bctl & PCI_BRIDGE_CTL_VGA) { ctrl_err(ctrl, "Cannot remove display device %s\n", - pci_name(dev)); - pci_dev_put(dev); + pci_name(temp)); + pci_dev_put(temp); rc = -EINVAL; break; } } - pci_stop_and_remove_bus_device(dev); + pci_stop_and_remove_bus_device(temp); /* * Ensure that no new Requests will be generated from * the device. */ if (presence) { - pci_read_config_word(dev, PCI_COMMAND, &command); + pci_read_config_word(temp, PCI_COMMAND, &command); command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR); command |= PCI_COMMAND_INTX_DISABLE; - pci_write_config_word(dev, PCI_COMMAND, command); + pci_write_config_word(temp, PCI_COMMAND, command); } - pci_dev_put(dev); + pci_dev_put(temp); } return rc; diff --git a/trunk/drivers/pci/hotplug/sgi_hotplug.c b/trunk/drivers/pci/hotplug/sgi_hotplug.c index 24dace645871..ae606b3e991e 100644 --- a/trunk/drivers/pci/hotplug/sgi_hotplug.c +++ b/trunk/drivers/pci/hotplug/sgi_hotplug.c @@ -334,7 +334,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) struct slot *slot = bss_hotplug_slot->private; struct pci_bus *new_bus = NULL; struct pci_dev *dev; - int num_funcs; + int func, num_funcs; int new_ppb = 0; int rc; char *ssdt = NULL; @@ -381,26 +381,29 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) * to the Linux PCI interface and tell the drivers * about them. */ - list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) { - if (PCI_SLOT(dev->devfn) != slot->device_num + 1) - continue; - - /* Need to do slot fixup on PPB before fixup of children - * (PPB's pcidev_info needs to be in pcidev_info list - * before child's SN_PCIDEV_INFO() call to setup - * pdi_host_pcidev_info). - */ - pcibios_fixup_device_resources(dev); - if (SN_ACPI_BASE_SUPPORT()) - sn_acpi_slot_fixup(dev); - else - sn_io_slot_fixup(dev); - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - pci_hp_add_bridge(dev); - if (dev->subordinate) { - new_bus = dev->subordinate; - new_ppb = 1; + for (func = 0; func < num_funcs; func++) { + dev = pci_get_slot(slot->pci_bus, + PCI_DEVFN(slot->device_num + 1, + PCI_FUNC(func))); + if (dev) { + /* Need to do slot fixup on PPB before fixup of children + * (PPB's pcidev_info needs to be in pcidev_info list + * before child's SN_PCIDEV_INFO() call to setup + * pdi_host_pcidev_info). + */ + pcibios_fixup_device_resources(dev); + if (SN_ACPI_BASE_SUPPORT()) + sn_acpi_slot_fixup(dev); + else + sn_io_slot_fixup(dev); + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + pci_hp_add_bridge(dev); + if (dev->subordinate) { + new_bus = dev->subordinate; + new_ppb = 1; + } } + pci_dev_put(dev); } } @@ -444,9 +447,9 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) if (ACPI_SUCCESS(ret) && (adr>>16) == (slot->device_num + 1)) { - ret = acpi_bus_add(chandle); + ret = acpi_bus_scan(chandle); if (ACPI_FAILURE(ret)) { - printk(KERN_ERR "%s: acpi_bus_add " + printk(KERN_ERR "%s: acpi_bus_scan " "failed (0x%x) for slot %d " "func %d\n", __func__, ret, (int)(adr>>16), @@ -478,7 +481,8 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) static int disable_slot(struct hotplug_slot *bss_hotplug_slot) { struct slot *slot = bss_hotplug_slot->private; - struct pci_dev *dev, *temp; + struct pci_dev *dev; + int func; int rc; acpi_owner_id ssdt_id = 0; @@ -531,21 +535,22 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) ret = acpi_bus_get_device(chandle, &device); if (ACPI_SUCCESS(ret)) - acpi_bus_trim(device, 1); + acpi_bus_trim(device); } } } /* Free the SN resources assigned to the Linux device.*/ - list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) { - if (PCI_SLOT(dev->devfn) != slot->device_num + 1) - continue; - - pci_dev_get(dev); - sn_bus_free_data(dev); - pci_stop_and_remove_bus_device(dev); - pci_dev_put(dev); + for (func = 0; func < 8; func++) { + dev = pci_get_slot(slot->pci_bus, + PCI_DEVFN(slot->device_num + 1, + PCI_FUNC(func))); + if (dev) { + sn_bus_free_data(dev); + pci_stop_and_remove_bus_device(dev); + pci_dev_put(dev); + } } /* Remove the SSDT for the slot from the ACPI namespace */ diff --git a/trunk/drivers/pci/hotplug/shpchp_pci.c b/trunk/drivers/pci/hotplug/shpchp_pci.c index b0e83132542e..c627ed9957d1 100644 --- a/trunk/drivers/pci/hotplug/shpchp_pci.c +++ b/trunk/drivers/pci/hotplug/shpchp_pci.c @@ -40,7 +40,7 @@ int __ref shpchp_configure_device(struct slot *p_slot) struct controller *ctrl = p_slot->ctrl; struct pci_dev *bridge = ctrl->pci_dev; struct pci_bus *parent = bridge->subordinate; - int num; + int num, fn; dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); if (dev) { @@ -57,20 +57,24 @@ int __ref shpchp_configure_device(struct slot *p_slot) return -ENODEV; } - list_for_each_entry(dev, &parent->devices, bus_list) { - if (PCI_SLOT(dev->devfn) != p_slot->device) + for (fn = 0; fn < 8; fn++) { + dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); + if (!dev) continue; if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) pci_hp_add_bridge(dev); + pci_dev_put(dev); } pci_assign_unassigned_bridge_resources(bridge); - list_for_each_entry(dev, &parent->devices, bus_list) { - if (PCI_SLOT(dev->devfn) != p_slot->device) + for (fn = 0; fn < 8; fn++) { + dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); + if (!dev) continue; pci_configure_slot(dev); + pci_dev_put(dev); } pci_bus_add_devices(parent); @@ -81,32 +85,32 @@ int __ref shpchp_configure_device(struct slot *p_slot) int shpchp_unconfigure_device(struct slot *p_slot) { int rc = 0; + int j; u8 bctl = 0; struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; - struct pci_dev *dev, *temp; struct controller *ctrl = p_slot->ctrl; ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); - list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { - if (PCI_SLOT(dev->devfn) != p_slot->device) + for (j = 0; j < 8 ; j++) { + struct pci_dev *temp = pci_get_slot(parent, + (p_slot->device << 3) | j); + if (!temp) continue; - - pci_dev_get(dev); - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl); + if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); if (bctl & PCI_BRIDGE_CTL_VGA) { ctrl_err(ctrl, "Cannot remove display device %s\n", - pci_name(dev)); - pci_dev_put(dev); + pci_name(temp)); + pci_dev_put(temp); rc = -EINVAL; break; } } - pci_stop_and_remove_bus_device(dev); - pci_dev_put(dev); + pci_stop_and_remove_bus_device(temp); + pci_dev_put(temp); } return rc; } diff --git a/trunk/drivers/pci/pci-acpi.c b/trunk/drivers/pci/pci-acpi.c index 1c2587c40299..42736e213f25 100644 --- a/trunk/drivers/pci/pci-acpi.c +++ b/trunk/drivers/pci/pci-acpi.c @@ -302,6 +302,24 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) return 0; } +static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle) +{ + int num; + unsigned int seg, bus; + + /* + * The string should be the same as root bridge's name + * Please look at 'pci_scan_bus_parented' + */ + num = sscanf(dev_name(dev), "pci%04x:%02x", &seg, &bus); + if (num != 2) + return -ENODEV; + *handle = acpi_get_pci_rootbridge_handle(seg, bus); + if (!*handle) + return -ENODEV; + return 0; +} + static void pci_acpi_setup(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -360,6 +378,7 @@ static void pci_acpi_cleanup(struct device *dev) static struct acpi_bus_type acpi_pci_bus = { .bus = &pci_bus_type, .find_device = acpi_pci_find_device, + .find_bridge = acpi_pci_find_root_bridge, .setup = pci_acpi_setup, .cleanup = pci_acpi_cleanup, }; diff --git a/trunk/drivers/pci/pci.c b/trunk/drivers/pci/pci.c index 177a50ff6454..0c4f641b7be1 100644 --- a/trunk/drivers/pci/pci.c +++ b/trunk/drivers/pci/pci.c @@ -1151,7 +1151,8 @@ int pci_reenable_device(struct pci_dev *dev) return 0; } -static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) +static int __pci_enable_device_flags(struct pci_dev *dev, + resource_size_t flags) { int err; int i, bars = 0; @@ -1195,7 +1196,7 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) */ int pci_enable_device_io(struct pci_dev *dev) { - return pci_enable_device_flags(dev, IORESOURCE_IO); + return __pci_enable_device_flags(dev, IORESOURCE_IO); } /** @@ -1208,7 +1209,7 @@ int pci_enable_device_io(struct pci_dev *dev) */ int pci_enable_device_mem(struct pci_dev *dev) { - return pci_enable_device_flags(dev, IORESOURCE_MEM); + return __pci_enable_device_flags(dev, IORESOURCE_MEM); } /** @@ -1224,7 +1225,7 @@ int pci_enable_device_mem(struct pci_dev *dev) */ int pci_enable_device(struct pci_dev *dev) { - return pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO); + return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO); } /* @@ -2042,13 +2043,10 @@ void pci_free_cap_save_buffers(struct pci_dev *dev) } /** - * pci_configure_ari - enable or disable ARI forwarding + * pci_enable_ari - enable ARI forwarding if hardware support it * @dev: the PCI device - * - * If @dev and its upstream bridge both support ARI, enable ARI in the - * bridge. Otherwise, disable ARI in the bridge. */ -void pci_configure_ari(struct pci_dev *dev) +void pci_enable_ari(struct pci_dev *dev) { u32 cap; struct pci_dev *bridge; @@ -2056,6 +2054,9 @@ void pci_configure_ari(struct pci_dev *dev) if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn) return; + if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) + return; + bridge = dev->bus->self; if (!bridge) return; @@ -2064,15 +2065,8 @@ void pci_configure_ari(struct pci_dev *dev) if (!(cap & PCI_EXP_DEVCAP2_ARI)) return; - if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) { - pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, - PCI_EXP_DEVCTL2_ARI); - bridge->ari_enabled = 1; - } else { - pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2, - PCI_EXP_DEVCTL2_ARI); - bridge->ari_enabled = 0; - } + pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI); + bridge->ari_enabled = 1; } /** diff --git a/trunk/drivers/pci/pci.h b/trunk/drivers/pci/pci.h index 81b6a8752517..adfd172c5b9b 100644 --- a/trunk/drivers/pci/pci.h +++ b/trunk/drivers/pci/pci.h @@ -204,7 +204,7 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, extern int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type); extern int pci_bus_add_child(struct pci_bus *bus); -extern void pci_configure_ari(struct pci_dev *dev); +extern void pci_enable_ari(struct pci_dev *dev); /** * pci_ari_enabled - query ARI forwarding status * @bus: the PCI bus diff --git a/trunk/drivers/pci/probe.c b/trunk/drivers/pci/probe.c index b4a6ede8f17a..2dcd22d9c816 100644 --- a/trunk/drivers/pci/probe.c +++ b/trunk/drivers/pci/probe.c @@ -1285,7 +1285,7 @@ static void pci_init_capabilities(struct pci_dev *dev) pci_vpd_pci22_init(dev); /* Alternative Routing-ID Forwarding */ - pci_configure_ari(dev); + pci_enable_ari(dev); /* Single Root I/O Virtualization */ pci_iov_init(dev); @@ -1348,31 +1348,31 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) } EXPORT_SYMBOL(pci_scan_single_device); -static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn) +static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn) { - int pos; - u16 cap = 0; - unsigned next_fn; - - if (pci_ari_enabled(bus)) { - if (!dev) - return 0; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); - if (!pos) - return 0; + u16 cap; + unsigned pos, next_fn; - pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap); - next_fn = PCI_ARI_CAP_NFN(cap); - if (next_fn <= fn) - return 0; /* protect against malformed list */ + if (!dev) + return 0; - return next_fn; - } + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); + if (!pos) + return 0; + pci_read_config_word(dev, pos + 4, &cap); + next_fn = cap >> 8; + if (next_fn <= fn) + return 0; + return next_fn; +} - /* dev may be NULL for non-contiguous multifunction devices */ - if (!dev || dev->multifunction) - return (fn + 1) % 8; +static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn) +{ + return (fn + 1) % 8; +} +static unsigned no_next_fn(struct pci_dev *dev, unsigned fn) +{ return 0; } @@ -1405,6 +1405,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) { unsigned fn, nr = 0; struct pci_dev *dev; + unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn; if (only_one_child(bus) && (devfn > 0)) return 0; /* Already scanned the entire slot */ @@ -1415,7 +1416,12 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) if (!dev->is_added) nr++; - for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) { + if (pci_ari_enabled(bus)) + next_fn = next_ari_fn; + else if (dev->multifunction) + next_fn = next_trad_fn; + + for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) { dev = pci_scan_single_device(bus, devfn + fn); if (dev) { if (!dev->is_added) @@ -1626,18 +1632,6 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) return max; } -/** - * pcibios_root_bridge_prepare - Platform-specific host bridge setup. - * @bridge: Host bridge to set up. - * - * Default empty implementation. Replace with an architecture-specific setup - * routine, if necessary. - */ -int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) -{ - return 0; -} - struct pci_bus *pci_create_root_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata, struct list_head *resources) { @@ -1671,10 +1665,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, bridge->dev.parent = parent; bridge->dev.release = pci_release_bus_bridge_dev; dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus); - error = pcibios_root_bridge_prepare(bridge); - if (error) - goto bridge_dev_reg_err; - error = device_register(&bridge->dev); if (error) goto bridge_dev_reg_err; diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index 796ccc3247df..2c722deb2490 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -91,8 +91,6 @@ struct acpi_device; typedef int (*acpi_op_add) (struct acpi_device * device); typedef int (*acpi_op_remove) (struct acpi_device * device, int type); typedef int (*acpi_op_start) (struct acpi_device * device); -typedef int (*acpi_op_bind) (struct acpi_device * device); -typedef int (*acpi_op_unbind) (struct acpi_device * device); typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event); struct acpi_device_ops { @@ -273,7 +271,6 @@ struct acpi_device { struct acpi_device_wakeup wakeup; struct acpi_device_perf performance; struct acpi_device_dir dir; - struct acpi_device_ops ops; struct acpi_driver *driver; void *driver_data; struct device dev; @@ -309,7 +306,7 @@ struct acpi_bus_event { }; struct acpi_eject_event { - acpi_handle handle; + struct acpi_device *device; u32 event; }; @@ -349,9 +346,9 @@ static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 ty #endif int acpi_bus_register_driver(struct acpi_driver *driver); void acpi_bus_unregister_driver(struct acpi_driver *driver); -int acpi_bus_add(acpi_handle handle); +int acpi_bus_scan(acpi_handle handle); void acpi_bus_hot_remove_device(void *context); -int acpi_bus_trim(struct acpi_device *start, int rmdevice); +int acpi_bus_trim(struct acpi_device *start); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); int acpi_match_device_ids(struct acpi_device *device, const struct acpi_device_id *ids); @@ -402,6 +399,7 @@ struct acpi_pci_root { /* helper */ acpi_handle acpi_get_child(acpi_handle, u64); int acpi_is_root_bridge(acpi_handle); +acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev)) diff --git a/trunk/include/linux/pci.h b/trunk/include/linux/pci.h index 6860f4dec997..907b455ab603 100644 --- a/trunk/include/linux/pci.h +++ b/trunk/include/linux/pci.h @@ -378,8 +378,6 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge, void (*release_fn)(struct pci_host_bridge *), void *release_data); -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge); - /* * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond * to P2P or CardBus bridge windows) go in a table. Additional ones (for