From: Stephen Rothwell Date: Wed, 20 Feb 2013 01:55:18 +0000 (+1100) Subject: Merge remote-tracking branch 'pm/linux-next' X-Git-Tag: next-20130220~75 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=083ee11b034aab59d0ce5aebfc6d22e401d5b81a;p=karo-tx-linux.git Merge remote-tracking branch 'pm/linux-next' Conflicts: drivers/acpi/internal.h drivers/acpi/scan.c drivers/pci/hotplug/acpiphp_glue.c drivers/pci/pci-acpi.c --- 083ee11b034aab59d0ce5aebfc6d22e401d5b81a diff --cc drivers/acpi/internal.h index e09ce0373d41,79092328cf06..61312bd169a2 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@@ -67,13 -94,6 +94,12 @@@ struct acpi_ec extern struct acpi_ec *first_ec; +#ifdef CONFIG_ACPI_PCI_SLOT +void acpi_pci_slot_init(void); +#else +static inline void acpi_pci_slot_init(void) { } +#endif - 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 --cc drivers/acpi/pci_root.c index 8b5a73b76202,b3cc69c5caf1..0ac546d5e53f --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@@ -599,8 -624,10 +596,8 @@@ end return result; } - static int acpi_pci_root_remove(struct acpi_device *device, int type) + static void acpi_pci_root_remove(struct acpi_device *device) { - acpi_status status; - acpi_handle handle; struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; @@@ -628,142 -658,8 +624,138 @@@ void __init acpi_pci_root_init(void { acpi_hest_init(); - if (acpi_pci_disabled) - return 0; - - pci_acpi_crs_quirks(); - if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) - return -ENODEV; - - return 0; + if (!acpi_pci_disabled) { + pci_acpi_crs_quirks(); + acpi_scan_add_handler(&pci_root_handler); + } } +/* 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); +} diff --cc drivers/acpi/scan.c index d9ee41eacf51,daee7497efd3..8aba2a93eb15 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@@ -1685,10 -1778,13 +1778,14 @@@ int __init acpi_scan_init(void printk(KERN_ERR PREFIX "Could not register bus type\n"); } - acpi_power_init(); acpi_pci_root_init(); + acpi_pci_slot_init(); + acpi_pci_link_init(); + acpi_platform_init(); + acpi_csrt_init(); + acpi_container_init(); + mutex_lock(&acpi_scan_lock); /* * Enumerate devices in the ACPI namespace. */ @@@ -1708,7 -1804,7 +1805,9 @@@ acpi_update_all_gpes(); + acpi_pci_root_hp_init(); + - return 0; + out: + mutex_unlock(&acpi_scan_lock); + return result; } diff --cc drivers/pci/hotplug/acpiphp_glue.c index 4681d2c9b1dd,a951c22921d1..f9264331a7eb --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@@ -1136,11 -1214,29 +1132,13 @@@ static void _handle_hotplug_event_bridg acpi_handle handle; u32 type; - hp_work = container_of(work, struct acpiphp_hp_work, work); + hp_work = container_of(work, struct acpi_hp_work, work); handle = hp_work->handle; type = hp_work->type; + bridge = (struct acpiphp_bridge *)hp_work->context; + acpi_scan_lock_acquire(); + - 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); switch (type) { @@@ -1195,6 -1296,8 +1193,7 @@@ break; } -out: + acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ } @@@ -1237,6 -1342,10 +1236,8 @@@ static void _handle_hotplug_event_func( acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - func = (struct acpiphp_func *)context; - + acpi_scan_lock_acquire(); + switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* bus re-enumerate */ diff --cc drivers/pci/pci-acpi.c index c685ff5e12d2,e407c61559ca..39c937f9b426 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@@ -307,8 -325,26 +307,7 @@@ static void pci_acpi_setup(struct devic 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; - - /* - * 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(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; @@@ -330,7 -367,10 +329,6 @@@ static void pci_acpi_cleanup(struct dev 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); } static struct acpi_bus_type acpi_pci_bus = {