From a17320bc99925198603ec846041f749d43f2e1a9 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 18 Mar 2012 22:46:26 -0700 Subject: [PATCH] --- yaml --- r: 358427 b: refs/heads/master c: 10c463a7a3b96285133c37e230781a1274abbd31 h: refs/heads/master i: 358425: 1741ff257848dd714ff8161d846fb2e994d7d75d 358423: 826a60fd5e59d8d370923b002d757dc03e828e6d v: v3 --- [refs] | 2 +- trunk/arch/ia64/pci/pci.c | 8 - trunk/arch/x86/include/asm/pci.h | 3 - trunk/arch/x86/pci/acpi.c | 9 - trunk/arch/x86/pci/i386.c | 185 ++++------- trunk/drivers/acpi/Makefile | 2 +- trunk/drivers/acpi/acpi_memhotplug.c | 26 +- trunk/drivers/acpi/container.c | 31 +- trunk/drivers/acpi/device_pm.c | 2 +- trunk/drivers/acpi/dock.c | 17 +- trunk/drivers/acpi/glue.c | 50 +-- trunk/drivers/acpi/internal.h | 2 - trunk/drivers/acpi/osl.c | 24 +- trunk/drivers/acpi/pci_bind.c | 122 +++++++ trunk/drivers/acpi/pci_root.c | 217 ++++-------- trunk/drivers/acpi/processor_driver.c | 32 +- trunk/drivers/acpi/scan.c | 329 ++++++++++++------- trunk/drivers/pci/bus.c | 81 ++++- trunk/drivers/pci/hotplug/acpiphp.h | 14 +- trunk/drivers/pci/hotplug/acpiphp_core.c | 23 +- trunk/drivers/pci/hotplug/acpiphp_glue.c | 292 ++++++++++++---- trunk/drivers/pci/hotplug/cpci_hotplug_pci.c | 29 +- trunk/drivers/pci/hotplug/pciehp_pci.c | 44 ++- trunk/drivers/pci/hotplug/sgi_hotplug.c | 73 ++-- trunk/drivers/pci/hotplug/shpchp_pci.c | 36 +- trunk/drivers/pci/iov.c | 10 +- trunk/drivers/pci/pci-acpi.c | 65 +--- trunk/drivers/pci/pci-driver.c | 6 +- trunk/drivers/pci/pci.c | 64 ++-- trunk/drivers/pci/pci.h | 9 +- trunk/drivers/pci/pcie/aspm.c | 8 +- trunk/drivers/pci/probe.c | 104 +++--- trunk/drivers/pci/remove.c | 4 +- trunk/drivers/pci/search.c | 10 +- trunk/drivers/pci/setup-bus.c | 2 +- trunk/include/acpi/acpi_bus.h | 35 +- trunk/include/acpi/acpiosxf.h | 2 + trunk/include/linux/acpi.h | 5 - trunk/include/linux/pci.h | 4 - 39 files changed, 1142 insertions(+), 839 deletions(-) create mode 100644 trunk/drivers/acpi/pci_bind.c diff --git a/[refs] b/[refs] index 802497ccb9f8..f76bcfe00bd1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ecb87e6609d3a559eacf7a61f5b4e088a797d07c +refs/heads/master: 10c463a7a3b96285133c37e230781a1274abbd31 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/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/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/i386.c b/trunk/arch/x86/pci/i386.c index 94919e307f8e..dd8ca6f7223b 100644 --- a/trunk/arch/x86/pci/i386.c +++ b/trunk/arch/x86/pci/i386.c @@ -51,7 +51,6 @@ struct pcibios_fwaddrmap { static LIST_HEAD(pcibios_fwaddrmappings); static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock); -static bool pcibios_fw_addr_done; /* Must be called with 'pcibios_fwaddrmap_lock' lock held. */ static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev) @@ -73,9 +72,6 @@ pcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr) unsigned long flags; struct pcibios_fwaddrmap *map; - if (pcibios_fw_addr_done) - return; - spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags); map = pcibios_fwaddrmap_lookup(dev); if (!map) { @@ -101,9 +97,6 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx) struct pcibios_fwaddrmap *map; resource_size_t fw_addr = 0; - if (pcibios_fw_addr_done) - return 0; - spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags); map = pcibios_fwaddrmap_lookup(dev); if (map) @@ -113,7 +106,7 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx) return fw_addr; } -static void __init pcibios_fw_addr_list_del(void) +static void pcibios_fw_addr_list_del(void) { unsigned long flags; struct pcibios_fwaddrmap *entry, *next; @@ -125,7 +118,6 @@ static void __init pcibios_fw_addr_list_del(void) kfree(entry); } spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags); - pcibios_fw_addr_done = true; } static int @@ -201,46 +193,46 @@ EXPORT_SYMBOL(pcibios_align_resource); * as well. */ -static void pcibios_allocate_bridge_resources(struct pci_dev *dev) +static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) { + struct pci_bus *bus; + struct pci_dev *dev; int idx; struct resource *r; - for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { - r = &dev->resource[idx]; - if (!r->flags) - continue; - if (!r->start || pci_claim_resource(dev, idx) < 0) { - /* - * Something is wrong with the region. - * Invalidate the resource to prevent - * child resource allocations in this - * range. - */ - r->start = r->end = 0; - r->flags = 0; + /* Depth-First Search on bus tree */ + list_for_each_entry(bus, bus_list, node) { + if ((dev = bus->self)) { + for (idx = PCI_BRIDGE_RESOURCES; + idx < PCI_NUM_RESOURCES; idx++) { + r = &dev->resource[idx]; + if (!r->flags) + continue; + if (!r->start || + pci_claim_resource(dev, idx) < 0) { + /* + * Something is wrong with the region. + * Invalidate the resource to prevent + * child resource allocations in this + * range. + */ + r->start = r->end = 0; + r->flags = 0; + } + } } + pcibios_allocate_bus_resources(&bus->children); } } -static void pcibios_allocate_bus_resources(struct pci_bus *bus) -{ - struct pci_bus *child; - - /* Depth-First Search on bus tree */ - if (bus->self) - pcibios_allocate_bridge_resources(bus->self); - list_for_each_entry(child, &bus->children, node) - pcibios_allocate_bus_resources(child); -} - struct pci_check_idx_range { int start; int end; }; -static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass) +static void __init pcibios_allocate_resources(int pass) { + struct pci_dev *dev = NULL; int idx, disabled, i; u16 command; struct resource *r; @@ -252,13 +244,14 @@ static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass) #endif }; - pci_read_config_word(dev, PCI_COMMAND, &command); - for (i = 0; i < ARRAY_SIZE(idx_range); i++) + for_each_pci_dev(dev) { + pci_read_config_word(dev, PCI_COMMAND, &command); + for (i = 0; i < ARRAY_SIZE(idx_range); i++) for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) { r = &dev->resource[idx]; - if (r->parent) /* Already allocated */ + if (r->parent) /* Already allocated */ continue; - if (!r->start) /* Address not assigned at all */ + if (!r->start) /* Address not assigned at all */ continue; if (r->flags & IORESOURCE_IO) disabled = !(command & PCI_COMMAND_IO); @@ -277,74 +270,44 @@ static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass) } } } - if (!pass) { - r = &dev->resource[PCI_ROM_RESOURCE]; - if (r->flags & IORESOURCE_ROM_ENABLE) { - /* Turn the ROM off, leave the resource region, - * but keep it unregistered. */ - u32 reg; - dev_dbg(&dev->dev, "disabling ROM %pR\n", r); - r->flags &= ~IORESOURCE_ROM_ENABLE; - pci_read_config_dword(dev, dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, + if (!pass) { + r = &dev->resource[PCI_ROM_RESOURCE]; + if (r->flags & IORESOURCE_ROM_ENABLE) { + /* Turn the ROM off, leave the resource region, + * but keep it unregistered. */ + u32 reg; + dev_dbg(&dev->dev, "disabling ROM %pR\n", r); + r->flags &= ~IORESOURCE_ROM_ENABLE; + pci_read_config_dword(dev, + dev->rom_base_reg, ®); + pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); + } } } } -static void pcibios_allocate_resources(struct pci_bus *bus, int pass) -{ - struct pci_dev *dev; - struct pci_bus *child; - - list_for_each_entry(dev, &bus->devices, bus_list) { - pcibios_allocate_dev_resources(dev, pass); - - child = dev->subordinate; - if (child) - pcibios_allocate_resources(child, pass); - } -} - -static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev) +static int __init pcibios_assign_resources(void) { + struct pci_dev *dev = NULL; struct resource *r; - /* - * Try to use BIOS settings for ROMs, otherwise let - * pci_assign_unassigned_resources() allocate the new - * addresses. - */ - r = &dev->resource[PCI_ROM_RESOURCE]; - if (!r->flags || !r->start) - return; - - if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) { - r->end -= r->start; - r->start = 0; - } -} -static void pcibios_allocate_rom_resources(struct pci_bus *bus) -{ - struct pci_dev *dev; - struct pci_bus *child; - - list_for_each_entry(dev, &bus->devices, bus_list) { - pcibios_allocate_dev_rom_resource(dev); - - child = dev->subordinate; - if (child) - pcibios_allocate_rom_resources(child); + if (!(pci_probe & PCI_ASSIGN_ROMS)) { + /* + * Try to use BIOS settings for ROMs, otherwise let + * pci_assign_unassigned_resources() allocate the new + * addresses. + */ + for_each_pci_dev(dev) { + r = &dev->resource[PCI_ROM_RESOURCE]; + if (!r->flags || !r->start) + continue; + if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) { + r->end -= r->start; + r->start = 0; + } + } } -} - -static int __init pcibios_assign_resources(void) -{ - struct pci_bus *bus; - - if (!(pci_probe & PCI_ASSIGN_ROMS)) - list_for_each_entry(bus, &pci_root_buses, node) - pcibios_allocate_rom_resources(bus); pci_assign_unassigned_resources(); pcibios_fw_addr_list_del(); @@ -352,32 +315,12 @@ static int __init pcibios_assign_resources(void) return 0; } -void pcibios_resource_survey_bus(struct pci_bus *bus) -{ - dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n"); - - pcibios_allocate_bus_resources(bus); - - pcibios_allocate_resources(bus, 0); - pcibios_allocate_resources(bus, 1); - - if (!(pci_probe & PCI_ASSIGN_ROMS)) - pcibios_allocate_rom_resources(bus); -} - void __init pcibios_resource_survey(void) { - struct pci_bus *bus; - DBG("PCI: Allocating resources\n"); - - list_for_each_entry(bus, &pci_root_buses, node) - pcibios_allocate_bus_resources(bus); - - list_for_each_entry(bus, &pci_root_buses, node) - pcibios_allocate_resources(bus, 0); - list_for_each_entry(bus, &pci_root_buses, node) - pcibios_allocate_resources(bus, 1); + pcibios_allocate_bus_resources(&pci_root_buses); + pcibios_allocate_resources(0); + pcibios_allocate_resources(1); e820_reserve_resources_late(); /* diff --git a/trunk/drivers/acpi/Makefile b/trunk/drivers/acpi/Makefile index 4ee2e753306a..2a4502becd13 100644 --- a/trunk/drivers/acpi/Makefile +++ b/trunk/drivers/acpi/Makefile @@ -37,7 +37,7 @@ acpi-y += resource.o acpi-y += processor_core.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o -acpi-y += pci_root.o pci_link.o pci_irq.o +acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o acpi-y += acpi_platform.o acpi-y += power.o acpi-y += event.o diff --git a/trunk/drivers/acpi/acpi_memhotplug.c b/trunk/drivers/acpi/acpi_memhotplug.c index 15ea22fc1f5e..eb30e5ab4cab 100644 --- a/trunk/drivers/acpi/acpi_memhotplug.c +++ b/trunk/drivers/acpi/acpi_memhotplug.c @@ -157,26 +157,38 @@ static int acpi_memory_get_device(acpi_handle handle, struct acpi_memory_device **mem_device) { + acpi_status status; + acpi_handle phandle; struct acpi_device *device = NULL; + struct acpi_device *pdevice = NULL; int result; + if (!acpi_bus_get_device(handle, &device) && device) goto end; + status = acpi_get_parent(handle, &phandle); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Cannot find acpi parent")); + return -EINVAL; + } + + /* Get the parent device */ + result = acpi_bus_get_device(phandle, &pdevice); + if (result) { + acpi_handle_warn(phandle, "Cannot get acpi bus device\n"); + return -EINVAL; + } + /* * Now add the notified device. This creates the acpi_device * and invokes .add function */ - result = acpi_bus_scan(handle); + result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); if (result) { acpi_handle_warn(handle, "Cannot add acpi bus\n"); return -EINVAL; } - result = acpi_bus_get_device(handle, &device); - if (result) { - acpi_handle_warn(handle, "Missing device object\n"); - return -EINVAL; - } end: *mem_device = acpi_driver_data(device); @@ -361,7 +373,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) break; } - ej_event->device = device; + ej_event->handle = handle; 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 cc79d3e53a39..811910b50b75 100644 --- a/trunk/drivers/acpi/container.c +++ b/trunk/drivers/acpi/container.c @@ -135,6 +135,30 @@ static int acpi_container_remove(struct acpi_device *device, int type) return status; } +static int container_device_add(struct acpi_device **device, acpi_handle handle) +{ + acpi_handle phandle; + struct acpi_device *pdev; + int result; + + + if (acpi_get_parent(handle, &phandle)) { + return -ENODEV; + } + + if (acpi_bus_get_device(phandle, &pdev)) { + return -ENODEV; + } + + if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) { + return -ENODEV; + } + + result = acpi_bus_start(*device); + + return result; +} + static void container_notify_cb(acpi_handle handle, u32 type, void *context) { struct acpi_device *device = NULL; @@ -166,16 +190,11 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (!ACPI_FAILURE(status) || device) break; - result = acpi_bus_scan(handle); + result = container_device_add(&device, handle); if (result) { acpi_handle_warn(handle, "Failed to add container\n"); break; } - result = acpi_bus_get_device(handle, &device); - if (result) { - acpi_handle_warn(handle, "Missing device object\n"); - break; - } kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); ost_code = ACPI_OST_SC_SUCCESS; diff --git a/trunk/drivers/acpi/device_pm.c b/trunk/drivers/acpi/device_pm.c index e4f6ac95595c..f09dc987cf17 100644 --- a/trunk/drivers/acpi/device_pm.c +++ b/trunk/drivers/acpi/device_pm.c @@ -353,7 +353,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) * acpi_dev_pm_get_node - Get ACPI device node for the given physical device. * @dev: Device to get the ACPI node for. */ -struct acpi_device *acpi_dev_pm_get_node(struct device *dev) +static struct acpi_device *acpi_dev_pm_get_node(struct device *dev) { acpi_handle handle = DEVICE_ACPI_HANDLE(dev); struct acpi_device *adev; diff --git a/trunk/drivers/acpi/dock.c b/trunk/drivers/acpi/dock.c index 420d24fc9388..f32bd47b35e0 100644 --- a/trunk/drivers/acpi/dock.c +++ b/trunk/drivers/acpi/dock.c @@ -310,6 +310,8 @@ static int dock_present(struct dock_station *ds) static struct acpi_device * dock_create_acpi_device(acpi_handle handle) { struct acpi_device *device; + struct acpi_device *parent_device; + acpi_handle parent; int ret; if (acpi_bus_get_device(handle, &device)) { @@ -317,11 +319,16 @@ 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_scan(handle); - if (ret) - pr_debug("error adding bus, %x\n", -ret); + acpi_get_parent(handle, &parent); + if (acpi_bus_get_device(parent, &parent_device)) + parent_device = NULL; - acpi_bus_get_device(handle, &device); + ret = acpi_bus_add(&device, parent_device, handle, + ACPI_BUS_TYPE_DEVICE); + if (ret) { + pr_debug("error adding bus, %x\n", -ret); + return NULL; + } } return device; } @@ -339,7 +346,7 @@ static void dock_remove_acpi_device(acpi_handle handle) int ret; if (!acpi_bus_get_device(handle, &device)) { - ret = acpi_bus_trim(device); + ret = acpi_bus_trim(device, 1); if (ret) pr_debug("error removing bus, %x\n", -ret); } diff --git a/trunk/drivers/acpi/glue.c b/trunk/drivers/acpi/glue.c index ac00b882e75d..01551840d236 100644 --- a/trunk/drivers/acpi/glue.c +++ b/trunk/drivers/acpi/glue.c @@ -63,9 +63,6 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) { struct acpi_bus_type *tmp, *ret = NULL; - if (!type) - return NULL; - down_read(&bus_type_sem); list_for_each_entry(tmp, &bus_type_list, list) { if (tmp->bus == type) { @@ -267,39 +264,28 @@ static int acpi_platform_notify(struct device *dev) { struct acpi_bus_type *type; acpi_handle handle; - int ret; + int ret = -EINVAL; ret = acpi_bind_one(dev, NULL); - if (ret && (!dev->bus || !dev->parent)) { + if (!ret) + goto out; + + if (!dev->bus || !dev->parent) { /* bridge devices genernally haven't bus or parent */ ret = acpi_find_bridge_device(dev, &handle); - if (!ret) { - ret = acpi_bind_one(dev, handle); - if (ret) - goto out; - } + goto end; } - type = acpi_get_bus_type(dev->bus); - if (ret) { - if (!type || !type->find_device) { - DBG("No ACPI bus support for %s\n", dev_name(dev)); - ret = -EINVAL; - goto out; - } - - ret = type->find_device(dev, &handle); - if (ret) { - DBG("Unable to get handle for %s\n", dev_name(dev)); - goto out; - } - ret = acpi_bind_one(dev, handle); - if (ret) - goto out; + if (!type) { + DBG("No ACPI bus support for %s\n", dev_name(dev)); + ret = -EINVAL; + goto end; } - - if (type && type->setup) - type->setup(dev); + if ((ret = type->find_device(dev, &handle)) != 0) + DBG("Can't get handler for %s\n", dev_name(dev)); + end: + if (!ret) + acpi_bind_one(dev, handle); out: #if ACPI_GLUE_DEBUG @@ -318,12 +304,6 @@ static int acpi_platform_notify(struct device *dev) static int acpi_platform_notify_remove(struct device *dev) { - struct acpi_bus_type *type; - - type = acpi_get_bus_type(dev->bus); - if (type && type->cleanup) - type->cleanup(dev); - acpi_unbind_one(dev); return 0; } diff --git a/trunk/drivers/acpi/internal.h b/trunk/drivers/acpi/internal.h index 0f24148a2b2a..3c407cdc1ec1 100644 --- a/trunk/drivers/acpi/internal.h +++ b/trunk/drivers/acpi/internal.h @@ -67,8 +67,6 @@ struct acpi_ec { extern struct acpi_ec *first_ec; -int acpi_pci_root_init(void); -void acpi_pci_root_hp_init(void); int acpi_ec_init(void); int acpi_ec_ecdt_probe(void); int acpi_boot_ec_enable(void); diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index 59ec5f52e849..3ff267861541 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -84,7 +84,8 @@ static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; static struct workqueue_struct *kacpi_notify_wq; -static struct workqueue_struct *kacpi_hotplug_wq; +struct workqueue_struct *kacpi_hotplug_wq; +EXPORT_SYMBOL(kacpi_hotplug_wq); /* * This list of permanent mappings is for memory that may be accessed from @@ -1777,24 +1778,3 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, { __acpi_os_prepare_sleep = func; } - -void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context, - void (*func)(struct work_struct *work)) -{ - struct acpi_hp_work *hp_work; - int ret; - - hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL); - if (!hp_work) - return; - - hp_work->handle = handle; - hp_work->type = type; - hp_work->context = context; - - INIT_WORK(&hp_work->work, func); - ret = queue_work(kacpi_hotplug_wq, &hp_work->work); - if (!ret) - kfree(hp_work); -} -EXPORT_SYMBOL_GPL(alloc_acpi_hp_work); diff --git a/trunk/drivers/acpi/pci_bind.c b/trunk/drivers/acpi/pci_bind.c new file mode 100644 index 000000000000..a1dee29beed3 --- /dev/null +++ b/trunk/drivers/acpi/pci_bind.c @@ -0,0 +1,122 @@ +/* + * pci_bind.c - ACPI PCI Device Binding ($Revision: 2 $) + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_PCI_COMPONENT +ACPI_MODULE_NAME("pci_bind"); + +static int acpi_pci_unbind(struct acpi_device *device) +{ + struct pci_dev *dev; + + dev = acpi_get_pci_dev(device->handle); + if (!dev) + goto out; + + device_set_run_wake(&dev->dev, false); + pci_acpi_remove_pm_notifier(device); + acpi_power_resource_unregister_device(&dev->dev, device->handle); + + if (!dev->subordinate) + goto out; + + acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number); + + device->ops.bind = NULL; + device->ops.unbind = NULL; + +out: + pci_dev_put(dev); + return 0; +} + +static int acpi_pci_bind(struct acpi_device *device) +{ + acpi_status status; + acpi_handle handle; + unsigned char bus; + struct pci_dev *dev; + + dev = acpi_get_pci_dev(device->handle); + if (!dev) + return 0; + + pci_acpi_add_pm_notifier(device, dev); + acpi_power_resource_register_device(&dev->dev, device->handle); + if (device->wakeup.flags.run_wake) + device_set_run_wake(&dev->dev, true); + + /* + * Install the 'bind' function to facilitate callbacks for + * children of the P2P bridge. + */ + if (dev->subordinate) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Device %04x:%02x:%02x.%d is a PCI bridge\n", + pci_domain_nr(dev->bus), dev->bus->number, + PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn))); + device->ops.bind = acpi_pci_bind; + device->ops.unbind = acpi_pci_unbind; + } + + /* + * Evaluate and parse _PRT, if exists. This code allows parsing of + * _PRT objects within the scope of non-bridge devices. Note that + * _PRTs within the scope of a PCI bridge assume the bridge's + * subordinate bus number. + * + * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? + */ + status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); + if (ACPI_FAILURE(status)) + goto out; + + if (dev->subordinate) + bus = dev->subordinate->number; + else + bus = dev->bus->number; + + acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus); + +out: + pci_dev_put(dev); + return 0; +} + +int acpi_pci_bind_root(struct acpi_device *device) +{ + device->ops.bind = acpi_pci_bind; + device->ops.unbind = acpi_pci_unbind; + + return 0; +} diff --git a/trunk/drivers/acpi/pci_root.c b/trunk/drivers/acpi/pci_root.c index 417487a201fb..7928d4dc7056 100644 --- a/trunk/drivers/acpi/pci_root.c +++ b/trunk/drivers/acpi/pci_root.c @@ -47,6 +47,7 @@ ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" static int acpi_pci_root_add(struct acpi_device *device); static int acpi_pci_root_remove(struct acpi_device *device, int type); +static int acpi_pci_root_start(struct acpi_device *device); #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ | OSC_ACTIVE_STATE_PWR_SUPPORT \ @@ -66,6 +67,7 @@ static struct acpi_driver acpi_pci_root_driver = { .ops = { .add = acpi_pci_root_add, .remove = acpi_pci_root_remove, + .start = acpi_pci_root_start, }, }; @@ -107,6 +109,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. @@ -168,6 +188,21 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, return AE_OK; } +static void acpi_pci_bridge_scan(struct acpi_device *device) +{ + int status; + struct acpi_device *child = NULL; + + if (device->flags.bus_address) + if (device->parent && device->parent->ops.bind) { + status = device->parent->ops.bind(device); + if (!status) { + list_for_each_entry(child, &device->children, node) + acpi_pci_bridge_scan(child); + } + } +} + static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; static acpi_status acpi_pci_run_osc(acpi_handle handle, @@ -417,7 +452,7 @@ static int acpi_pci_root_add(struct acpi_device *device) int result; struct acpi_pci_root *root; acpi_handle handle; - struct acpi_pci_driver *driver; + struct acpi_device *child; u32 flags, base_flags; bool is_osc_granted = false; @@ -568,6 +603,21 @@ static int acpi_pci_root_add(struct acpi_device *device) goto out_del_root; } + /* + * Attach ACPI-PCI Context + * ----------------------- + * Thus binding the ACPI and PCI devices. + */ + result = acpi_pci_bind_root(device); + if (result) + goto out_del_root; + + /* + * Scan and bind all _ADR-Based Devices + */ + list_for_each_entry(child, &device->children, node) + acpi_pci_bridge_scan(child); + /* ASPM setting */ if (is_osc_granted) { if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) @@ -582,10 +632,26 @@ static int acpi_pci_root_add(struct acpi_device *device) if (device->wakeup.flags.run_wake) device_set_run_wake(root->bus->bridge, true); - if (system_state != SYSTEM_BOOTING) { - pcibios_resource_survey_bus(root->bus); + return 0; + +out_del_root: + mutex_lock(&acpi_pci_root_lock); + list_del(&root->node); + mutex_unlock(&acpi_pci_root_lock); + + acpi_pci_irq_del_prt(root->segment, root->secondary.start); +end: + kfree(root); + return result; +} + +static int acpi_pci_root_start(struct acpi_device *device) +{ + struct acpi_pci_root *root = acpi_driver_data(device); + struct acpi_pci_driver *driver; + + if (system_state != SYSTEM_BOOTING) pci_assign_unassigned_bus_resources(root->bus); - } mutex_lock(&acpi_pci_root_lock); list_for_each_entry(driver, &acpi_pci_drivers, node) @@ -598,17 +664,8 @@ static int acpi_pci_root_add(struct acpi_device *device) pci_enable_bridges(root->bus); pci_bus_add_devices(root->bus); - return 0; - -out_del_root: - mutex_lock(&acpi_pci_root_lock); - list_del(&root->node); - mutex_unlock(&acpi_pci_root_lock); - acpi_pci_irq_del_prt(root->segment, root->secondary.start); -end: - kfree(root); - return result; + return 0; } static int acpi_pci_root_remove(struct acpi_device *device, int type) @@ -642,7 +699,7 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) return 0; } -int __init acpi_pci_root_init(void) +static int __init acpi_pci_root_init(void) { acpi_hest_init(); @@ -655,133 +712,5 @@ int __init acpi_pci_root_init(void) return 0; } -/* Support root bridge hotplug */ - -static void handle_root_bridge_insertion(acpi_handle handle) -{ - struct acpi_device *device; - - if (!acpi_bus_get_device(handle, &device)) { - printk(KERN_DEBUG "acpi device exists...\n"); - return; - } - - if (acpi_bus_scan(handle)) - printk(KERN_ERR "cannot add bridge to acpi list\n"); -} - -static void handle_root_bridge_removal(struct acpi_device *device) -{ - struct acpi_eject_event *ej_event; - - ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); - if (!ej_event) { - /* Inform firmware the hot-remove operation has error */ - (void) acpi_evaluate_hotplug_ost(device->handle, - ACPI_NOTIFY_EJECT_REQUEST, - ACPI_OST_SC_NON_SPECIFIC_FAILURE, - NULL); - return; - } - - ej_event->device = device; - ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; - - acpi_bus_hot_remove_device(ej_event); -} - -static void _handle_hotplug_event_root(struct work_struct *work) -{ - struct acpi_pci_root *root; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER }; - struct acpi_hp_work *hp_work; - acpi_handle handle; - u32 type; - - hp_work = container_of(work, struct acpi_hp_work, work); - handle = hp_work->handle; - type = hp_work->type; - root = acpi_pci_find_root(handle); - - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - - switch (type) { - case ACPI_NOTIFY_BUS_CHECK: - /* bus enumerate */ - printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__, - (char *)buffer.pointer); - if (!root) - handle_root_bridge_insertion(handle); - - break; - - case ACPI_NOTIFY_DEVICE_CHECK: - /* device check */ - printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__, - (char *)buffer.pointer); - if (!root) - handle_root_bridge_insertion(handle); - break; - - case ACPI_NOTIFY_EJECT_REQUEST: - /* request device eject */ - printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__, - (char *)buffer.pointer); - if (root) - handle_root_bridge_removal(root->device); - break; - default: - printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n", - type, (char *)buffer.pointer); - break; - } - - kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ - kfree(buffer.pointer); -} - -static void handle_hotplug_event_root(acpi_handle handle, u32 type, - void *context) -{ - alloc_acpi_hp_work(handle, type, context, - _handle_hotplug_event_root); -} - -static acpi_status __init -find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - char objname[64]; - struct acpi_buffer buffer = { .length = sizeof(objname), - .pointer = objname }; - int *count = (int *)context; - - if (!acpi_is_root_bridge(handle)) - return AE_OK; - - (*count)++; - - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - - status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_root, NULL); - if (ACPI_FAILURE(status)) - printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n", - objname, (unsigned int)status); - else - printk(KERN_DEBUG "acpi root: %s notify handler is installed\n", - objname); - - return AE_OK; -} - -void __init acpi_pci_root_hp_init(void) -{ - int num = 0; - - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); - - printk(KERN_DEBUG "Found %d acpi root devices\n", num); -} +subsys_initcall(acpi_pci_root_init); diff --git a/trunk/drivers/acpi/processor_driver.c b/trunk/drivers/acpi/processor_driver.c index 9c5929a17d3a..e83311bf1ebd 100644 --- a/trunk/drivers/acpi/processor_driver.c +++ b/trunk/drivers/acpi/processor_driver.c @@ -677,6 +677,28 @@ static int is_processor_present(acpi_handle handle) return 0; } +static +int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) +{ + acpi_handle phandle; + struct acpi_device *pdev; + + + if (acpi_get_parent(handle, &phandle)) { + return -ENODEV; + } + + if (acpi_bus_get_device(phandle, &pdev)) { + return -ENODEV; + } + + if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { + return -ENODEV; + } + + return 0; +} + static void acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) { @@ -699,16 +721,12 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, if (!acpi_bus_get_device(handle, &device)) break; - result = acpi_bus_scan(handle); + result = acpi_processor_device_add(handle, &device); if (result) { acpi_handle_err(handle, "Unable to add the device\n"); break; } - result = acpi_bus_get_device(handle, &device); - if (result) { - acpi_handle_err(handle, "Missing device object\n"); - break; - } + ost_code = ACPI_OST_SC_SUCCESS; break; @@ -733,7 +751,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, break; } - ej_event->device = device; + ej_event->handle = handle; 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 bc2f33790e83..53502d1bbf26 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -116,18 +116,24 @@ 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 = ej_event->device; - acpi_handle handle = device->handle; + struct acpi_device *device; + acpi_handle handle = ej_event->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)) { + if (acpi_bus_trim(device, 1)) { printk(KERN_ERR PREFIX "Removing device failed\n"); goto err_out; @@ -209,7 +215,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, goto err; } - ej_event->device = acpi_device; + ej_event->handle = acpi_device->handle; if (acpi_device->flags.eject_pending) { /* event originated from ACPI eject notification */ ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; @@ -217,7 +223,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(acpi_device->handle, + (void) acpi_evaluate_hotplug_ost(ej_event->handle, ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); } @@ -488,8 +494,7 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return acpi_dev->flags.match_driver - && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); + return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -565,6 +570,7 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device) } static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); +static int acpi_start_single_object(struct acpi_device *); static int acpi_device_probe(struct device * dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -573,6 +579,9 @@ static int acpi_device_probe(struct device * dev) ret = acpi_bus_driver_init(acpi_dev, acpi_drv); if (!ret) { + if (acpi_dev->bus_ops.acpi_op_start) + acpi_start_single_object(acpi_dev); + if (acpi_drv->ops.notify) { ret = acpi_device_install_notify_handler(acpi_dev); if (ret) { @@ -695,7 +704,7 @@ static int acpi_device_register(struct acpi_device *device) return result; } -static void acpi_device_unregister(struct acpi_device *device) +static void acpi_device_unregister(struct acpi_device *device, int type) { mutex_lock(&acpi_device_lock); if (device->parent) @@ -751,6 +760,24 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) return 0; } +static int acpi_start_single_object(struct acpi_device *device) +{ + int result = 0; + struct acpi_driver *driver; + + + if (!(driver = device->driver)) + return 0; + + if (driver->ops.start) { + result = driver->ops.start(device); + if (result && driver->ops.remove) + driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); + } + + return result; +} + /** * acpi_bus_register_driver - register a driver with the ACPI bus * @driver: driver being registered @@ -1368,9 +1395,33 @@ 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; + + /* + * unbind _ADR-Based Devices when hot removal + */ + if (dev->flags.bus_address) { + if ((dev->parent) && (dev->parent->ops.unbind)) + dev->parent->ops.unbind(dev); + } + 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) + unsigned long long sta, + struct acpi_bus_ops *ops) { int result; struct acpi_device *device; @@ -1386,6 +1437,7 @@ static int acpi_add_single_object(struct acpi_device **child, device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); + device->bus_ops = *ops; /* workround for not call .start */ STRUCT_TO_INT(device->status) = sta; acpi_device_get_busid(device); @@ -1436,9 +1488,16 @@ static int acpi_add_single_object(struct acpi_device **child, if ((result = acpi_device_set_context(device))) goto end; - device->flags.match_driver = match_driver; result = acpi_device_register(device); + /* + * Bind _ADR-Based Devices when hot add + */ + if (device->flags.bus_address) { + if (device->parent && device->parent->ops.bind) + device->parent->ops.bind(device); + } + end: if (!result) { acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); @@ -1460,12 +1519,16 @@ static int acpi_add_single_object(struct acpi_device **child, static void acpi_bus_add_power_resource(acpi_handle handle) { + struct acpi_bus_ops ops = { + .acpi_op_add = 1, + .acpi_op_start = 1, + }; struct acpi_device *device = NULL; acpi_bus_get_device(handle, &device); if (!device) acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, - ACPI_STA_DEFAULT, true); + ACPI_STA_DEFAULT, &ops); } static int acpi_bus_type_and_status(acpi_handle handle, int *type, @@ -1507,19 +1570,16 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, return 0; } -static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, - void *not_used, void **return_value) +static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, + void *context, void **return_value) { - struct acpi_device *device = NULL; + struct acpi_bus_ops *ops = context; int type; unsigned long long sta; + struct acpi_device *device; acpi_status status; int result; - acpi_bus_get_device(handle, &device); - if (device) - goto out; - result = acpi_bus_type_and_status(handle, &type, &sta); if (result) return AE_OK; @@ -1536,118 +1596,150 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, return AE_CTRL_DEPTH; } - acpi_add_single_object(&device, handle, type, sta, - type == ACPI_BUS_TYPE_POWER); + /* + * We may already have an acpi_device from a previous enumeration. If + * so, we needn't add it again, but we may still have to start it. + */ + device = NULL; + acpi_bus_get_device(handle, &device); + if (ops->acpi_op_add && !device) { + acpi_add_single_object(&device, handle, type, sta, ops); + /* Is the device a known good platform device? */ + if (device + && !acpi_match_device_ids(device, acpi_platform_device_ids)) + acpi_create_platform_device(device); + } + if (!device) return AE_CTRL_DEPTH; - device->flags.match_driver = true; + if (ops->acpi_op_start && !(ops->acpi_op_add)) { + status = acpi_start_single_object(device); + if (ACPI_FAILURE(status)) + return AE_CTRL_DEPTH; + } - out: if (!*return_value) *return_value = device; - return AE_OK; } -static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, - void *not_used, void **ret_not_used) +static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, + struct acpi_device **child) { - acpi_status status = AE_OK; - struct acpi_device *device; - unsigned long long sta_not_used; - int type_not_used; + acpi_status status; + void *device = NULL; - /* - * Ignore errors ignored by acpi_bus_check_add() to avoid terminating - * namespace walks prematurely. - */ - if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) - return AE_OK; + status = acpi_bus_check_add(handle, 0, ops, &device); + if (ACPI_SUCCESS(status)) + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_check_add, NULL, ops, &device); - if (acpi_bus_get_device(handle, &device)) - return AE_CTRL_DEPTH; + if (child) + *child = device; - 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) < 0) { - status = AE_CTRL_DEPTH; - } - return status; + if (device) + return 0; + else + return -ENODEV; } -/** - * acpi_bus_scan - Add ACPI device node objects in a given namespace scope. - * @handle: Root of the namespace scope to scan. +/* + * acpi_bus_add and acpi_bus_start * - * Scan a given ACPI tree (probably recently hot-plugged) and create and add - * found devices. + * scan a given ACPI tree and (probably recently hot-plugged) + * create and add or starts 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. + * If no devices were found -ENODEV is returned which does not + * mean that this is 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/start an appropriate driver. */ -int acpi_bus_scan(acpi_handle handle) + +int +acpi_bus_add(struct acpi_device **child, + struct acpi_device *parent, acpi_handle handle, int type) { - void *device = NULL; + struct acpi_bus_ops ops; - if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) - acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, NULL, &device); + memset(&ops, 0, sizeof(ops)); + ops.acpi_op_add = 1; + + return acpi_bus_scan(handle, &ops, child); +} +EXPORT_SYMBOL(acpi_bus_add); + +int acpi_bus_start(struct acpi_device *device) +{ + struct acpi_bus_ops ops; + int result; if (!device) - return -ENODEV; + return -EINVAL; - if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL))) - acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_device_attach, NULL, NULL, NULL); + memset(&ops, 0, sizeof(ops)); + ops.acpi_op_start = 1; - return 0; -} -EXPORT_SYMBOL(acpi_bus_scan); + result = acpi_bus_scan(device->handle, &ops, NULL); -static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, - void *not_used, void **ret_not_used) -{ - struct acpi_device *device = NULL; + acpi_update_all_gpes(); - if (!acpi_bus_get_device(handle, &device)) { - device->removal_type = ACPI_BUS_REMOVAL_EJECT; - device_release_driver(&device->dev); - } - return AE_OK; + return result; } +EXPORT_SYMBOL(acpi_bus_start); -static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, - void *not_used, void **ret_not_used) +int acpi_bus_trim(struct acpi_device *start, int rmdevice) { - struct acpi_device *device = NULL; + acpi_status status; + struct acpi_device *parent, *child; + acpi_handle phandle, chandle; + acpi_object_type type; + u32 level = 1; + int err = 0; - if (!acpi_bus_get_device(handle, &device)) - acpi_device_unregister(device); + parent = start; + phandle = start->handle; + child = chandle = NULL; - return AE_OK; -} + while ((level > 0) && parent && (!err)) { + status = acpi_get_next_object(ACPI_TYPE_ANY, phandle, + chandle, &chandle); -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; + /* + * 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); + + continue; + } + + 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; } EXPORT_SYMBOL_GPL(acpi_bus_trim); @@ -1655,6 +1747,11 @@ static int acpi_bus_scan_fixed(void) { int result = 0; struct acpi_device *device = NULL; + struct acpi_bus_ops ops; + + memset(&ops, 0, sizeof(ops)); + ops.acpi_op_add = 1; + ops.acpi_op_start = 1; /* * Enumerate all fixed-feature devices. @@ -1662,14 +1759,16 @@ static int acpi_bus_scan_fixed(void) if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_POWER_BUTTON, - ACPI_STA_DEFAULT, true); + ACPI_STA_DEFAULT, + &ops); device_init_wakeup(&device->dev, true); } if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, - ACPI_STA_DEFAULT, true); + ACPI_STA_DEFAULT, + &ops); } return result; @@ -1678,6 +1777,11 @@ static int acpi_bus_scan_fixed(void) int __init acpi_scan_init(void) { int result; + struct acpi_bus_ops ops; + + memset(&ops, 0, sizeof(ops)); + ops.acpi_op_add = 1; + ops.acpi_op_start = 1; result = bus_register(&acpi_bus_type); if (result) { @@ -1686,28 +1790,19 @@ int __init acpi_scan_init(void) } acpi_power_init(); - acpi_pci_root_init(); /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT); - if (result) - return result; - - result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); - if (result) - return result; - - result = acpi_bus_scan_fixed(); - if (result) { - acpi_device_unregister(acpi_root); - return result; - } + result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root); - acpi_update_all_gpes(); + if (!result) + result = acpi_bus_scan_fixed(); - acpi_pci_root_hp_init(); + if (result) + acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); + else + acpi_update_all_gpes(); - return 0; + return result; } diff --git a/trunk/drivers/pci/bus.c b/trunk/drivers/pci/bus.c index 8647dc6f52d0..ad6a8b635692 100644 --- a/trunk/drivers/pci/bus.c +++ b/trunk/drivers/pci/bus.c @@ -158,38 +158,69 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, return ret; } -void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { } - /** - * pci_bus_add_device - start driver for a single device + * pci_bus_add_device - add a single device * @dev: device to add * - * This adds add sysfs entries and start device drivers + * This adds a single pci device to the global + * device list and adds sysfs and procfs entries */ int pci_bus_add_device(struct pci_dev *dev) { int retval; - /* - * Can not put in pci_device_add yet because resources - * are not assigned yet for some devices. - */ - pci_create_sysfs_dev_files(dev); + pci_fixup_device(pci_fixup_final, dev); - dev->match_driver = true; - retval = device_attach(&dev->dev); - WARN_ON(retval < 0); + retval = pcibios_add_device(dev); + if (retval) + return retval; - dev->is_added = 1; + retval = device_add(&dev->dev); + if (retval) + return retval; + dev->is_added = 1; + pci_proc_attach_device(dev); + pci_create_sysfs_dev_files(dev); return 0; } /** - * pci_bus_add_devices - start driver for PCI devices + * pci_bus_add_child - add a child bus + * @bus: bus to add + * + * This adds sysfs entries for a single bus + */ +int pci_bus_add_child(struct pci_bus *bus) +{ + int retval; + + if (bus->bridge) + bus->dev.parent = bus->bridge; + + retval = device_register(&bus->dev); + if (retval) + return retval; + + bus->is_added = 1; + + /* Create legacy_io and legacy_mem files for this bus */ + pci_create_legacy_files(bus); + + return retval; +} + +/** + * pci_bus_add_devices - insert newly discovered PCI devices * @bus: bus to check for new devices * - * Start driver for PCI devices and add some sysfs entries. + * Add newly discovered PCI devices (which are on the bus->devices + * list) to the global PCI device list, add the sysfs and procfs + * entries. Where a bridge is found, add the discovered bus to + * the parents list of child buses, and recurse (breadth-first + * to be compatible with 2.4) + * + * Call hotplug for each new devices. */ void pci_bus_add_devices(const struct pci_bus *bus) { @@ -202,20 +233,36 @@ void pci_bus_add_devices(const struct pci_bus *bus) if (dev->is_added) continue; retval = pci_bus_add_device(dev); + if (retval) + dev_err(&dev->dev, "Error adding device, continuing\n"); } list_for_each_entry(dev, &bus->devices, bus_list) { BUG_ON(!dev->is_added); child = dev->subordinate; - + /* + * If there is an unattached subordinate bus, attach + * it and then scan for unattached PCI devices. + */ if (!child) continue; + if (list_empty(&child->node)) { + down_write(&pci_bus_sem); + list_add_tail(&child->node, &dev->bus->children); + up_write(&pci_bus_sem); + } pci_bus_add_devices(child); + /* + * register the bus with sysfs as the parent is now + * properly registered. + */ if (child->is_added) continue; - child->is_added = 1; + retval = pci_bus_add_child(child); + if (retval) + dev_err(&dev->dev, "Error adding bus, continuing\n"); } } diff --git a/trunk/drivers/pci/hotplug/acpiphp.h b/trunk/drivers/pci/hotplug/acpiphp.h index b70ac00a117e..a1afb5b39ad4 100644 --- a/trunk/drivers/pci/hotplug/acpiphp.h +++ b/trunk/drivers/pci/hotplug/acpiphp.h @@ -79,6 +79,7 @@ struct acpiphp_bridge { /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ struct acpiphp_func *func; + int type; int nr_slots; u32 flags; @@ -145,6 +146,10 @@ struct acpiphp_attention_info /* PCI bus bridge HID */ #define ACPI_PCI_HOST_HID "PNP0A03" +/* PCI BRIDGE type */ +#define BRIDGE_TYPE_HOST 0 +#define BRIDGE_TYPE_P2P 1 + /* ACPI _STA method value (ignore bit 4; battery present) */ #define ACPI_STA_PRESENT (0x00000001) #define ACPI_STA_ENABLED (0x00000002) @@ -153,7 +158,13 @@ struct acpiphp_attention_info #define ACPI_STA_ALL (0x0000000f) /* bridge flags */ -#define BRIDGE_HAS_EJ0 (0x00000001) +#define BRIDGE_HAS_STA (0x00000001) +#define BRIDGE_HAS_EJ0 (0x00000002) +#define BRIDGE_HAS_HPP (0x00000004) +#define BRIDGE_HAS_PS0 (0x00000010) +#define BRIDGE_HAS_PS1 (0x00000020) +#define BRIDGE_HAS_PS2 (0x00000040) +#define BRIDGE_HAS_PS3 (0x00000080) /* slot flags */ @@ -182,6 +193,7 @@ 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); +extern int acpiphp_get_num_slots (void); typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); extern int acpiphp_enable_slot (struct acpiphp_slot *slot); diff --git a/trunk/drivers/pci/hotplug/acpiphp_core.c b/trunk/drivers/pci/hotplug/acpiphp_core.c index c2fd3095701f..96316b74969f 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_core.c +++ b/trunk/drivers/pci/hotplug/acpiphp_core.c @@ -50,6 +50,7 @@ bool acpiphp_debug; /* local variables */ +static int num_slots; static struct acpiphp_attention_info *attention_info; #define DRIVER_VERSION "0.5" @@ -271,6 +272,25 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) return 0; } +static int __init init_acpi(void) +{ + int retval; + + /* initialize internal data structure etc. */ + retval = acpiphp_glue_init(); + + /* read initial number of slots */ + if (!retval) { + num_slots = acpiphp_get_num_slots(); + if (num_slots == 0) { + acpiphp_glue_exit(); + retval = -ENODEV; + } + } + + return retval; +} + /** * release_slot - free up the memory used by a slot * @hotplug_slot: slot to free @@ -359,8 +379,7 @@ static int __init acpiphp_init(void) return 0; /* read all the ACPI info from the system */ - /* initialize internal data structure etc. */ - return acpiphp_glue_init(); + return init_acpi(); } diff --git a/trunk/drivers/pci/hotplug/acpiphp_glue.c b/trunk/drivers/pci/hotplug/acpiphp_glue.c index 4681d2c9b1dd..3d6d4fd1e3c5 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_glue.c +++ b/trunk/drivers/pci/hotplug/acpiphp_glue.c @@ -325,8 +325,8 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) return; } - /* install notify handler for P2P bridges */ - if (!pci_is_root_bus(bridge->pci_bus)) { + /* install notify handler */ + if (bridge->type != BRIDGE_TYPE_HOST) { if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { status = acpi_remove_notify_handler(bridge->func->handle, ACPI_SYSTEM_NOTIFY, @@ -369,12 +369,27 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle 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))) { + "_STA", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_STA; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_EJ0", &dummy_handle))) bridge->flags |= BRIDGE_HAS_EJ0; + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_PS0", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_PS0; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_PS3", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_PS3; + + /* is this ejectable p2p bridge? */ + if (bridge->flags & BRIDGE_HAS_EJ0) { + struct acpiphp_func *func; + dbg("found ejectable p2p bridge\n"); /* make link between PCI bridge and PCI function */ @@ -397,6 +412,7 @@ static void add_host_bridge(struct acpi_pci_root *root) if (bridge == NULL) return; + bridge->type = BRIDGE_TYPE_HOST; bridge->handle = handle; bridge->pci_bus = root->bus; @@ -416,6 +432,7 @@ static void add_p2p_bridge(acpi_handle *handle) return; } + bridge->type = BRIDGE_TYPE_P2P; bridge->handle = handle; config_p2p_bridge_flags(bridge); @@ -526,15 +543,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) acpi_status status; acpi_handle handle = bridge->handle; - if (!pci_is_root_bus(bridge->pci_bus)) { - status = acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, + status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_bridge); - if (ACPI_FAILURE(status)) - err("failed to remove notify handler\n"); - } + if (ACPI_FAILURE(status)) + err("failed to remove notify handler\n"); - if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { + if ((bridge->type != BRIDGE_TYPE_HOST) && + ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) { status = acpi_install_notify_handler(bridge->func->handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_func, @@ -615,6 +630,9 @@ static void remove_bridge(struct acpi_pci_root *root) bridge = acpiphp_handle_to_bridge(handle); if (bridge) cleanup_bridge(bridge); + else + acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_bridge); } static int power_on_slot(struct acpiphp_slot *slot) @@ -716,25 +734,34 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) */ static int acpiphp_bus_add(struct acpiphp_func *func) { - struct acpi_device *device; + acpi_handle phandle; + struct acpi_device *device, *pdevice; int ret_val; + acpi_get_parent(func->handle, &phandle); + if (acpi_bus_get_device(phandle, &pdevice)) { + dbg("no parent device, assuming NULL\n"); + pdevice = NULL; + } if (!acpi_bus_get_device(func->handle, &device)) { dbg("bus exists... trim\n"); /* this shouldn't be in here, so remove * the bus then re-add it... */ - ret_val = acpi_bus_trim(device); + ret_val = acpi_bus_trim(device, 1); dbg("acpi_bus_trim return %x\n", ret_val); } - ret_val = acpi_bus_scan(func->handle); - if (!ret_val) - ret_val = acpi_bus_get_device(func->handle, &device); - - if (ret_val) - dbg("error adding bus, %x\n", -ret_val); + ret_val = acpi_bus_add(&device, pdevice, func->handle, + ACPI_BUS_TYPE_DEVICE); + if (ret_val) { + dbg("error adding bus, %x\n", + -ret_val); + goto acpiphp_bus_add_out; + } + ret_val = acpi_bus_start(device); +acpiphp_bus_add_out: return ret_val; } @@ -754,7 +781,7 @@ static int acpiphp_bus_trim(acpi_handle handle) return retval; } - retval = acpi_bus_trim(device); + retval = acpi_bus_trim(device, 1); if (retval) err("cannot remove from acpi list\n"); @@ -779,29 +806,6 @@ static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) } } -static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) -{ - struct acpiphp_func *func; - - if (!dev->subordinate) - return; - - /* quirk, or pcie could set it already */ - if (dev->is_hotplug_bridge) - return; - - if (PCI_SLOT(dev->devfn) != slot->device) - return; - - list_for_each_entry(func, &slot->funcs, sibling) { - if (PCI_FUNC(dev->devfn) == func->function) { - /* check if this bridge has ejectable slots */ - if ((detect_ejectable_slots(func->handle) > 0)) - dev->is_hotplug_bridge = 1; - break; - } - } -} /** * enable_device - enable, configure a slot * @slot: slot to be enabled @@ -821,9 +825,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) if (slot->flags & SLOT_ENABLED) goto err_exit; - list_for_each_entry(func, &slot->funcs, sibling) - acpiphp_bus_add(func); - num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); if (num == 0) { /* Maybe only part of funcs are added. */ @@ -839,14 +840,15 @@ static int __ref enable_device(struct acpiphp_slot *slot) if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { max = pci_scan_bridge(bus, dev, max, pass); - if (pass && dev->subordinate) { - check_hotplug_bridge(slot, dev); + if (pass && dev->subordinate) pci_bus_size_bridges(dev->subordinate); - } } } } + list_for_each_entry(func, &slot->funcs, sibling) + acpiphp_bus_add(func); + pci_bus_assign_resources(bus); acpiphp_sanitize_bus(bus); acpiphp_set_hpp_values(bus); @@ -1104,10 +1106,72 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) } } +/* Program resources in newly inserted bridge */ +static int acpiphp_configure_bridge (acpi_handle handle) +{ + struct pci_bus *bus; + + if (acpi_is_root_bridge(handle)) { + struct acpi_pci_root *root = acpi_pci_find_root(handle); + bus = root->bus; + } else { + struct pci_dev *pdev = acpi_get_pci_dev(handle); + bus = pdev->subordinate; + pci_dev_put(pdev); + } + + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); + acpiphp_sanitize_bus(bus); + acpiphp_set_hpp_values(bus); + pci_enable_bridges(bus); + return 0; +} + +static void handle_bridge_insertion(acpi_handle handle, u32 type) +{ + struct acpi_device *device, *pdevice; + acpi_handle phandle; + + if ((type != ACPI_NOTIFY_BUS_CHECK) && + (type != ACPI_NOTIFY_DEVICE_CHECK)) { + err("unexpected notification type %d\n", type); + return; + } + + acpi_get_parent(handle, &phandle); + if (acpi_bus_get_device(phandle, &pdevice)) { + dbg("no parent device, assuming NULL\n"); + pdevice = NULL; + } + if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) { + err("cannot add bridge to acpi list\n"); + return; + } + if (!acpiphp_configure_bridge(handle) && + !acpi_bus_start(device)) + add_bridge(handle); + else + err("cannot configure and start bridge\n"); + +} + /* * ACPI event handlers */ +static acpi_status +count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + int *count = (int *)context; + struct acpiphp_bridge *bridge; + + bridge = acpiphp_handle_to_bridge(handle); + if (bridge) + (*count)++; + return AE_OK ; +} + static acpi_status check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) { @@ -1126,20 +1190,66 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK ; } +struct acpiphp_hp_work { + struct work_struct work; + acpi_handle handle; + u32 type; + void *context; +}; + +static void alloc_acpiphp_hp_work(acpi_handle handle, u32 type, + void *context, + void (*func)(struct work_struct *work)) +{ + struct acpiphp_hp_work *hp_work; + int ret; + + hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL); + if (!hp_work) + return; + + hp_work->handle = handle; + hp_work->type = type; + hp_work->context = context; + + INIT_WORK(&hp_work->work, func); + ret = queue_work(kacpi_hotplug_wq, &hp_work->work); + if (!ret) + kfree(hp_work); +} + static void _handle_hotplug_event_bridge(struct work_struct *work) { struct acpiphp_bridge *bridge; char objname[64]; struct acpi_buffer buffer = { .length = sizeof(objname), .pointer = objname }; - struct acpi_hp_work *hp_work; + struct acpi_device *device; + int num_sub_bridges = 0; + struct acpiphp_hp_work *hp_work; acpi_handle handle; u32 type; - hp_work = container_of(work, struct acpi_hp_work, work); + hp_work = container_of(work, struct acpiphp_hp_work, work); handle = hp_work->handle; type = hp_work->type; - bridge = (struct acpiphp_bridge *)hp_work->context; + + if (acpi_bus_get_device(handle, &device)) { + /* This bridge must have just been physically inserted */ + handle_bridge_insertion(handle, type); + goto out; + } + + bridge = acpiphp_handle_to_bridge(handle); + if (type == ACPI_NOTIFY_BUS_CHECK) { + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX, + count_sub_bridges, NULL, &num_sub_bridges, NULL); + } + + if (!bridge && !num_sub_bridges) { + err("cannot get bridge info\n"); + goto out; + } acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); @@ -1147,10 +1257,14 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) case ACPI_NOTIFY_BUS_CHECK: /* bus re-enumerate */ dbg("%s: Bus check notify on %s\n", __func__, objname); - dbg("%s: re-enumerating slots under %s\n", __func__, objname); - acpiphp_check_bridge(bridge); - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); + if (bridge) { + dbg("%s: re-enumerating slots under %s\n", + __func__, objname); + acpiphp_check_bridge(bridge); + } + if (num_sub_bridges) + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, + ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); break; case ACPI_NOTIFY_DEVICE_CHECK: @@ -1167,7 +1281,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ dbg("%s: Device eject notify on %s\n", __func__, objname); - if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { + if ((bridge->type != BRIDGE_TYPE_HOST) && + (bridge->flags & BRIDGE_HAS_EJ0)) { struct acpiphp_slot *slot; slot = bridge->func->slot; if (!acpiphp_disable_slot(slot)) @@ -1195,6 +1310,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) break; } +out: kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ } @@ -1217,7 +1333,8 @@ 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. */ - alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge); + alloc_acpiphp_hp_work(handle, type, context, + _handle_hotplug_event_bridge); } static void _handle_hotplug_event_func(struct work_struct *work) @@ -1226,17 +1343,20 @@ static void _handle_hotplug_event_func(struct work_struct *work) char objname[64]; struct acpi_buffer buffer = { .length = sizeof(objname), .pointer = objname }; - struct acpi_hp_work *hp_work; + struct acpiphp_hp_work *hp_work; acpi_handle handle; u32 type; + void *context; - hp_work = container_of(work, struct acpi_hp_work, work); + hp_work = container_of(work, struct acpiphp_hp_work, work); handle = hp_work->handle; type = hp_work->type; - func = (struct acpiphp_func *)hp_work->context; + context = hp_work->context; acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + func = (struct acpiphp_func *)context; + switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* bus re-enumerate */ @@ -1289,7 +1409,23 @@ 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. */ - alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func); + alloc_acpiphp_hp_work(handle, type, context, + _handle_hotplug_event_func); +} + +static acpi_status +find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + int *count = (int *)context; + + if (!acpi_is_root_bridge(handle)) + return AE_OK; + + (*count)++; + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_bridge, NULL); + + return AE_OK ; } static struct acpi_pci_driver acpi_pci_hp_driver = { @@ -1302,7 +1438,15 @@ static struct acpi_pci_driver acpi_pci_hp_driver = { */ int __init acpiphp_glue_init(void) { - acpi_pci_register_driver(&acpi_pci_hp_driver); + int num = 0; + + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); + + if (num <= 0) + return -1; + else + acpi_pci_register_driver(&acpi_pci_hp_driver); return 0; } @@ -1318,6 +1462,28 @@ void acpiphp_glue_exit(void) acpi_pci_unregister_driver(&acpi_pci_hp_driver); } + +/** + * acpiphp_get_num_slots - count number of slots in a system + */ +int __init acpiphp_get_num_slots(void) +{ + struct acpiphp_bridge *bridge; + int num_slots = 0; + + list_for_each_entry(bridge, &bridge_list, list) { + dbg("Bus %04x:%02x has %d slot%s\n", + pci_domain_nr(bridge->pci_bus), + bridge->pci_bus->number, bridge->nr_slots, + bridge->nr_slots == 1 ? "" : "s"); + num_slots += bridge->nr_slots; + } + + dbg("Total %d slots\n", num_slots); + return num_slots; +} + + /** * acpiphp_enable_slot - power on slot * @slot: ACPI PHP slot 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/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 180e760c1653..f64ca92253da 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); } } @@ -409,6 +412,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) if (SN_ACPI_BASE_SUPPORT() && ssdt) { unsigned long long adr; struct acpi_device *pdevice; + struct acpi_device *device; acpi_handle phandle; acpi_handle chandle = NULL; acpi_handle rethandle; @@ -444,14 +448,17 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) if (ACPI_SUCCESS(ret) && (adr>>16) == (slot->device_num + 1)) { - ret = acpi_bus_scan(chandle); + ret = acpi_bus_add(&device, pdevice, chandle, + ACPI_BUS_TYPE_DEVICE); if (ACPI_FAILURE(ret)) { - printk(KERN_ERR "%s: acpi_bus_scan " + printk(KERN_ERR "%s: acpi_bus_add " "failed (0x%x) for slot %d " "func %d\n", __func__, ret, (int)(adr>>16), (int)(adr&0xffff)); /* try to continue on */ + } else { + acpi_bus_start(device); } } } @@ -478,7 +485,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 +539,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); + acpi_bus_trim(device, 1); } } } /* 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/iov.c b/trunk/drivers/pci/iov.c index 4ea7139db1be..bafd2bbcaf65 100644 --- a/trunk/drivers/pci/iov.c +++ b/trunk/drivers/pci/iov.c @@ -33,6 +33,7 @@ static inline u8 virtfn_devfn(struct pci_dev *dev, int id) static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) { + int rc; struct pci_bus *child; if (bus->number == busnr) @@ -47,7 +48,12 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) return NULL; pci_bus_insert_busn_res(child, busnr, busnr); - bus->is_added = 1; + child->dev.parent = bus->bridge; + rc = pci_bus_add_child(child); + if (rc) { + pci_remove_bus(child); + return NULL; + } return child; } @@ -117,6 +123,8 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset) virtfn->is_virtfn = 1; rc = pci_bus_add_device(virtfn); + if (rc) + goto failed1; sprintf(buf, "virtfn%u", id); rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf); if (rc) diff --git a/trunk/drivers/pci/pci-acpi.c b/trunk/drivers/pci/pci-acpi.c index 1c2587c40299..1af4008182fd 100644 --- a/trunk/drivers/pci/pci-acpi.c +++ b/trunk/drivers/pci/pci-acpi.c @@ -283,6 +283,7 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = { .is_manageable = acpi_pci_power_manageable, .set_state = acpi_pci_set_power_state, .choose_state = acpi_pci_choose_state, + .can_wakeup = acpi_pci_can_wakeup, .sleep_wake = acpi_pci_sleep_wake, .run_wake = acpi_pci_run_wake, }; @@ -302,66 +303,28 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) return 0; } -static void pci_acpi_setup(struct device *dev) +static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle) { - struct pci_dev *pci_dev = to_pci_dev(dev); - acpi_handle handle = ACPI_HANDLE(dev); - struct acpi_device *adev; - acpi_status status; - acpi_handle dummy; + int num; + unsigned int seg, bus; /* - * Evaluate and parse _PRT, if exists. This code allows parsing of - * _PRT objects within the scope of non-bridge devices. Note that - * _PRTs within the scope of a PCI bridge assume the bridge's - * subordinate bus number. - * - * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? + * The string should be the same as root bridge's name + * Please look at 'pci_scan_bus_parented' */ - status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy); - if (ACPI_SUCCESS(status)) { - unsigned char bus; - - bus = pci_dev->subordinate ? - pci_dev->subordinate->number : pci_dev->bus->number; - acpi_pci_irq_add_prt(handle, pci_domain_nr(pci_dev->bus), bus); - } - - acpi_power_resource_register_device(dev, handle); - if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid) - return; - - device_set_wakeup_capable(dev, true); - acpi_pci_sleep_wake(pci_dev, false); - - pci_acpi_add_pm_notifier(adev, pci_dev); - if (adev->wakeup.flags.run_wake) - device_set_run_wake(dev, true); -} - -static void pci_acpi_cleanup(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - acpi_handle handle = ACPI_HANDLE(dev); - struct acpi_device *adev; - - if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) { - device_set_wakeup_capable(dev, false); - device_set_run_wake(dev, false); - pci_acpi_remove_pm_notifier(adev); - } - acpi_power_resource_unregister_device(dev, handle); - - if (pci_dev->subordinate) - acpi_pci_irq_del_prt(pci_domain_nr(pci_dev->bus), - pci_dev->subordinate->number); + 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 struct acpi_bus_type acpi_pci_bus = { .bus = &pci_bus_type, .find_device = acpi_pci_find_device, - .setup = pci_acpi_setup, - .cleanup = pci_acpi_cleanup, + .find_bridge = acpi_pci_find_root_bridge, }; static int __init acpi_pci_init(void) diff --git a/trunk/drivers/pci/pci-driver.c b/trunk/drivers/pci/pci-driver.c index acdcc3c6ecdd..f79cbcd3944b 100644 --- a/trunk/drivers/pci/pci-driver.c +++ b/trunk/drivers/pci/pci-driver.c @@ -1186,13 +1186,9 @@ pci_dev_driver(const struct pci_dev *dev) static int pci_bus_match(struct device *dev, struct device_driver *drv) { struct pci_dev *pci_dev = to_pci_dev(dev); - struct pci_driver *pci_drv; + struct pci_driver *pci_drv = to_pci_driver(drv); const struct pci_device_id *found_id; - if (!pci_dev->match_driver) - return 0; - - pci_drv = to_pci_driver(drv); found_id = pci_match_device(pci_drv, pci_dev); if (found_id) return 1; diff --git a/trunk/drivers/pci/pci.c b/trunk/drivers/pci/pci.c index 177a50ff6454..11c36654c95d 100644 --- a/trunk/drivers/pci/pci.c +++ b/trunk/drivers/pci/pci.c @@ -450,7 +450,7 @@ static struct pci_platform_pm_ops *pci_platform_pm; int pci_set_platform_pm(struct pci_platform_pm_ops *ops) { if (!ops->is_manageable || !ops->set_state || !ops->choose_state - || !ops->sleep_wake) + || !ops->sleep_wake || !ops->can_wakeup) return -EINVAL; pci_platform_pm = ops; return 0; @@ -473,6 +473,11 @@ static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev) pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR; } +static inline bool platform_pci_can_wakeup(struct pci_dev *dev) +{ + return pci_platform_pm ? pci_platform_pm->can_wakeup(dev) : false; +} + static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) { return pci_platform_pm ? @@ -1979,6 +1984,25 @@ void pci_pm_init(struct pci_dev *dev) } } +/** + * platform_pci_wakeup_init - init platform wakeup if present + * @dev: PCI device + * + * Some devices don't have PCI PM caps but can still generate wakeup + * events through platform methods (like ACPI events). If @dev supports + * platform wakeup events, set the device flag to indicate as much. This + * may be redundant if the device also supports PCI PM caps, but double + * initialization should be safe in that case. + */ +void platform_pci_wakeup_init(struct pci_dev *dev) +{ + if (!platform_pci_can_wakeup(dev)) + return; + + device_set_wakeup_capable(&dev->dev, true); + platform_pci_sleep_wake(dev, false); +} + static void pci_add_saved_cap(struct pci_dev *pci_dev, struct pci_cap_saved_state *new_cap) { @@ -2042,13 +2066,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 +2077,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 +2088,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; } /** @@ -3748,18 +3765,6 @@ resource_size_t pci_specified_resource_alignment(struct pci_dev *dev) return align; } -/** - * pci_is_reassigndev - check if specified PCI is target device to reassign - * @dev: the PCI device to check - * - * RETURNS: non-zero for PCI device is a target device to reassign, - * or zero is not. - */ -int pci_is_reassigndev(struct pci_dev *dev) -{ - return (pci_specified_resource_alignment(dev) != 0); -} - /* * This function disables memory decoding and releases memory resources * of the device specified by kernel's boot parameter 'pci=resource_alignment='. @@ -3774,7 +3779,9 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev) resource_size_t align, size; u16 command; - if (!pci_is_reassigndev(dev)) + /* check if specified PCI is target device to reassign */ + align = pci_specified_resource_alignment(dev); + if (!align) return; if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL && @@ -3790,7 +3797,6 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev) command &= ~PCI_COMMAND_MEMORY; pci_write_config_word(dev, PCI_COMMAND, command); - align = pci_specified_resource_alignment(dev); for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) { r = &dev->resource[i]; if (!(r->flags & IORESOURCE_MEM)) diff --git a/trunk/drivers/pci/pci.h b/trunk/drivers/pci/pci.h index 7346ee68f47d..e8518292826f 100644 --- a/trunk/drivers/pci/pci.h +++ b/trunk/drivers/pci/pci.h @@ -43,6 +43,9 @@ int pci_probe_reset_function(struct pci_dev *dev); * platform; to be used during system-wide transitions from a * sleeping state to the working state and vice versa * + * @can_wakeup: returns 'true' if given device is capable of waking up the + * system from a sleeping state + * * @sleep_wake: enables/disables the system wake up capability of given device * * @run_wake: enables/disables the platform to generate run-time wake-up events @@ -56,6 +59,7 @@ struct pci_platform_pm_ops { bool (*is_manageable)(struct pci_dev *dev); int (*set_state)(struct pci_dev *dev, pci_power_t state); pci_power_t (*choose_state)(struct pci_dev *dev); + bool (*can_wakeup)(struct pci_dev *dev); int (*sleep_wake)(struct pci_dev *dev, bool enable); int (*run_wake)(struct pci_dev *dev, bool enable); }; @@ -70,6 +74,7 @@ extern void pci_wakeup_bus(struct pci_bus *bus); extern void pci_config_pm_runtime_get(struct pci_dev *dev); extern void pci_config_pm_runtime_put(struct pci_dev *dev); extern void pci_pm_init(struct pci_dev *dev); +extern void platform_pci_wakeup_init(struct pci_dev *dev); extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); void pci_free_cap_save_buffers(struct pci_dev *dev); @@ -203,8 +208,8 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, struct resource *res, unsigned int reg); extern int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type); -extern void pci_configure_ari(struct pci_dev *dev); - +extern int pci_bus_add_child(struct pci_bus *bus); +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/pcie/aspm.c b/trunk/drivers/pci/pcie/aspm.c index e8a19772cf52..b52630b8eada 100644 --- a/trunk/drivers/pci/pcie/aspm.c +++ b/trunk/drivers/pci/pcie/aspm.c @@ -556,9 +556,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) struct pcie_link_state *link; int blacklist = !!pcie_aspm_sanity_check(pdev); - if (!aspm_support_enabled) - return; - if (!pci_is_pcie(pdev) || pdev->link_state) return; if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && @@ -637,7 +634,10 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) struct pci_dev *parent = pdev->bus->self; struct pcie_link_state *link, *root, *parent_link; - if (!parent || !parent->link_state) + if (!pci_is_pcie(pdev) || !parent || !parent->link_state) + return; + if ((pci_pcie_type(parent) != PCI_EXP_TYPE_ROOT_PORT) && + (pci_pcie_type(parent) != PCI_EXP_TYPE_DOWNSTREAM)) return; down_read(&pci_bus_sem); diff --git a/trunk/drivers/pci/probe.c b/trunk/drivers/pci/probe.c index b494066ef32f..6186f03d84f3 100644 --- a/trunk/drivers/pci/probe.c +++ b/trunk/drivers/pci/probe.c @@ -623,7 +623,6 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, { struct pci_bus *child; int i; - int ret; /* * Allocate a new bus, and inherit stuff from the parent.. @@ -638,7 +637,8 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, child->bus_flags = parent->bus_flags; /* initialize some portions of the bus device, but don't register it - * now as the parent is not properly set up yet. + * now as the parent is not properly set up yet. This device will get + * registered later in pci_bus_add_devices() */ child->dev.class = &pcibus_class; dev_set_name(&child->dev, "%04x:%02x", pci_domain_nr(child), busnr); @@ -651,14 +651,11 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, child->primary = parent->busn_res.start; child->busn_res.end = 0xff; - if (!bridge) { - child->dev.parent = parent->bridge; - goto add_dev; - } + if (!bridge) + return child; child->self = bridge; child->bridge = get_device(&bridge->dev); - child->dev.parent = child->bridge; pci_set_bus_of_node(child); pci_set_bus_speed(child); @@ -669,13 +666,6 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, } bridge->subordinate = child; -add_dev: - ret = device_register(&child->dev); - WARN_ON(ret < 0); - - /* Create legacy_io and legacy_mem files for this bus */ - pci_create_legacy_files(child); - return child; } @@ -1290,12 +1280,13 @@ static void pci_init_capabilities(struct pci_dev *dev) /* Power Management */ pci_pm_init(dev); + platform_pci_wakeup_init(dev); /* Vital Product Data */ 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); @@ -1306,12 +1297,10 @@ static void pci_init_capabilities(struct pci_dev *dev) void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) { - int ret; - device_initialize(&dev->dev); dev->dev.release = pci_release_dev; + pci_dev_get(dev); - set_dev_node(&dev->dev, pcibus_to_node(bus)); dev->dev.dma_mask = &dev->dma_mask; dev->dev.dma_parms = &dev->dma_parms; dev->dev.coherent_dma_mask = 0xffffffffull; @@ -1338,17 +1327,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) down_write(&pci_bus_sem); list_add_tail(&dev->bus_list, &bus->devices); up_write(&pci_bus_sem); - - pci_fixup_device(pci_fixup_final, dev); - ret = pcibios_add_device(dev); - WARN_ON(ret < 0); - - /* Notifier could use PCI capabilities */ - dev->match_driver = false; - ret = device_add(&dev->dev); - WARN_ON(ret < 0); - - pci_proc_attach_device(dev); } struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) @@ -1371,31 +1349,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; + u16 cap; + unsigned pos, 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; - - 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; } @@ -1428,6 +1406,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 */ @@ -1438,7 +1417,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) @@ -1649,18 +1633,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) { @@ -1673,13 +1645,13 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, char bus_addr[64]; char *fmt; + b = pci_alloc_bus(); if (!b) return NULL; b->sysdata = sysdata; b->ops = ops; - b->number = b->busn_res.start = bus; b2 = pci_find_bus(pci_domain_nr(b), bus); if (b2) { /* If we already got to this bus through a different bridge, ignore it */ @@ -1694,10 +1666,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; @@ -1718,6 +1686,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, /* Create legacy_io and legacy_mem files for this bus */ pci_create_legacy_files(b); + b->number = b->busn_res.start = bus; + if (parent) dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev)); else diff --git a/trunk/drivers/pci/remove.c b/trunk/drivers/pci/remove.c index fc38c4883e1d..7c0fd9252e6f 100644 --- a/trunk/drivers/pci/remove.c +++ b/trunk/drivers/pci/remove.c @@ -22,7 +22,7 @@ static void pci_stop_dev(struct pci_dev *dev) if (dev->is_added) { pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); - device_del(&dev->dev); + device_unregister(&dev->dev); dev->is_added = 0; } @@ -37,7 +37,7 @@ static void pci_destroy_dev(struct pci_dev *dev) up_write(&pci_bus_sem); pci_free_resources(dev); - put_device(&dev->dev); + pci_dev_put(dev); } void pci_remove_bus(struct pci_bus *bus) diff --git a/trunk/drivers/pci/search.c b/trunk/drivers/pci/search.c index d0627fa9f368..bf969ba58e59 100644 --- a/trunk/drivers/pci/search.c +++ b/trunk/drivers/pci/search.c @@ -319,13 +319,13 @@ int pci_dev_present(const struct pci_device_id *ids) WARN_ON(in_interrupt()); while (ids->vendor || ids->subvendor || ids->class_mask) { found = pci_get_dev_by_id(ids, NULL); - if (found) { - pci_dev_put(found); - return 1; - } + if (found) + goto exit; ids++; } - +exit: + if (found) + return 1; return 0; } EXPORT_SYMBOL(pci_dev_present); diff --git a/trunk/drivers/pci/setup-bus.c b/trunk/drivers/pci/setup-bus.c index 7e8739e25b9e..6d3591d57ea0 100644 --- a/trunk/drivers/pci/setup-bus.c +++ b/trunk/drivers/pci/setup-bus.c @@ -283,7 +283,7 @@ static void assign_requested_resources_sorted(struct list_head *head, idx = res - &dev_res->dev->resource[0]; if (resource_size(res) && pci_assign_resource(dev_res->dev, idx)) { - if (fail_head) { + if (fail_head && !pci_is_root_bus(dev_res->dev->bus)) { /* * if the failed res is for ROM BAR, and it will * be enabled later, don't add it to the list diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index 5ce8d5e86734..7ced5dc20dd3 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -91,12 +91,21 @@ 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_bus_ops { + u32 acpi_op_add:1; + u32 acpi_op_start:1; +}; + struct acpi_device_ops { acpi_op_add add; acpi_op_remove remove; acpi_op_start start; + acpi_op_bind bind; + acpi_op_unbind unbind; acpi_op_notify notify; }; @@ -139,8 +148,7 @@ struct acpi_device_flags { u32 power_manageable:1; u32 performance_manageable:1; u32 eject_pending:1; - u32 match_driver:1; - u32 reserved:23; + u32 reserved:24; }; /* File System */ @@ -271,9 +279,11 @@ 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; + struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ u8 physical_node_count; struct list_head physical_node_list; @@ -306,19 +316,10 @@ struct acpi_bus_event { }; struct acpi_eject_event { - struct acpi_device *device; + acpi_handle handle; u32 event; }; -struct acpi_hp_work { - struct work_struct work; - acpi_handle handle; - u32 type; - void *context; -}; -void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context, - void (*func)(struct work_struct *work)); - extern struct kobject *acpi_kobj; extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); void acpi_bus_private_data_handler(acpi_handle, void *); @@ -355,9 +356,11 @@ 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_scan(acpi_handle handle); +int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, + acpi_handle handle, int type); void acpi_bus_hot_remove_device(void *context); -int acpi_bus_trim(struct acpi_device *start); +int acpi_bus_trim(struct acpi_device *start, int rmdevice); +int acpi_bus_start(struct acpi_device *device); 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); @@ -387,8 +390,6 @@ struct acpi_bus_type { int (*find_device) (struct device *, acpi_handle *); /* For bridges, such as PCI root bridge, IDE controller */ int (*find_bridge) (struct device *, acpi_handle *); - void (*setup)(struct device *); - void (*cleanup)(struct device *); }; int register_acpi_bus_type(struct acpi_bus_type *); int unregister_acpi_bus_type(struct acpi_bus_type *); @@ -396,6 +397,7 @@ int unregister_acpi_bus_type(struct acpi_bus_type *); struct acpi_pci_root { struct list_head node; struct acpi_device * device; + struct acpi_pci_id id; struct pci_bus *bus; u16 segment; struct resource secondary; /* downstream bus range */ @@ -408,6 +410,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/acpi/acpiosxf.h b/trunk/include/acpi/acpiosxf.h index 66f1fd70e8c2..43152742b46f 100644 --- a/trunk/include/acpi/acpiosxf.h +++ b/trunk/include/acpi/acpiosxf.h @@ -193,6 +193,8 @@ void acpi_os_fixed_event_count(u32 fixed_event_number); /* * Threads and Scheduling */ +extern struct workqueue_struct *kacpi_hotplug_wq; + acpi_thread_id acpi_os_get_thread_id(void); acpi_status diff --git a/trunk/include/linux/acpi.h b/trunk/include/linux/acpi.h index 8c1d6f2a2193..3994d7790b23 100644 --- a/trunk/include/linux/acpi.h +++ b/trunk/include/linux/acpi.h @@ -526,14 +526,9 @@ static inline int acpi_subsys_resume_early(struct device *dev) { return 0; } #endif #if defined(CONFIG_ACPI) && defined(CONFIG_PM) -struct acpi_device *acpi_dev_pm_get_node(struct device *dev); int acpi_dev_pm_attach(struct device *dev, bool power_on); void acpi_dev_pm_detach(struct device *dev, bool power_off); #else -static inline struct acpi_device *acpi_dev_pm_get_node(struct device *dev) -{ - return NULL; -} static inline int acpi_dev_pm_attach(struct device *dev, bool power_on) { return -ENODEV; diff --git a/trunk/include/linux/pci.h b/trunk/include/linux/pci.h index 056d3d66b976..15472d691ee6 100644 --- a/trunk/include/linux/pci.h +++ b/trunk/include/linux/pci.h @@ -286,7 +286,6 @@ struct pci_dev { unsigned int irq; struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */ - bool match_driver; /* Skip attaching driver */ /* These fields are used by common fixups */ unsigned int transparent:1; /* Transparent PCI bridge */ unsigned int multifunction:1;/* Part of multi-function device */ @@ -379,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 @@ -677,7 +674,6 @@ extern struct list_head pci_root_buses; /* list of all known PCI buses */ /* Some device drivers need know if pci is initiated */ extern int no_pci_devices(void); -void pcibios_resource_survey_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) */